quantastica / quantum-circuit

Quantum Circuit Simulator implemented in JavaScript
MIT License
248 stars 49 forks source link

Matrix of S Gate #92

Closed glanzz closed 2 months ago

glanzz commented 2 months ago

The matrix representation of the S Gate as given in https://www.quantum-inspire.com/kbase/s-gate/ is

Screenshot 2024-07-10 at 6 34 04 PM

But i see that the definition of matrix of S gate is different in the library.

How to Reproduce ?

Create circuit with gates applied in following order XHSS and XHZ gate since result of applying SS and Z gates are equivalent. the results should be the same. But the results diverge and so do their states:

{
  '0': { re: 0.7071067811865475, im: 0 },
  '1': { re: 0.7071067811865475, im: -8.659560562354932e-17 }
} // States with SS gate
{
  '0': { re: 0.7071067811865475, im: 0 },
  '1': { re: 0.7071067811865475, im: 0 }
} // States with Z gate
import QuantumCircuit from 'quantum-circuit';

var ss = new QuantumCircuit();
ss.addGate("h", 0,0) // Apply this so that imaginary part is accounted
ss.addGate("s", 1,0)
ss.addGate("s", 2,0)

var z = new QuantumCircuit();
z.addGate("h", 0,0) // Apply this so that imaginary part is accounted
z.addGate("z", 1, 0)
for(let circuit of [ss, z]) {
  const shots = 100;
  const results = {};
  for (let i = 0; i < shots; i++) {
      circuit.run([true]);
      const measuredState = circuit.measureAll();
      const bitstring = measuredState.map(bit => bit ? '1' : '0').join('');
      if (!results[bitstring]) {
          results[bitstring] = 0;
      }
      results[bitstring]++;
  }
  console.log(results)
}

Results

{ '0': 50, '1': 50 }
{ '0': 40, '1': 60 }
glanzz commented 2 months ago

Looks like 'mathjs' evaluates to different values when used exp(i*pi/2) and i where the first adds some real part to the apart from the imaginary part.

const math = require('mathjs')
console.log(math.evaluate("i"))
console.log(math.evaluate("exp(i * pi / 2)"))
Complex { re: 0, im: 1 }
Complex { re: 6.123233995736766e-17, im: 1 }
perak commented 2 months ago

@glanzz thank you for reporting, but I claim this is not a bug.

Error on 16th decimal place simply cannot make that big difference in results.

You have too small number of shots. If I run your example multiple times, I get very different counts each time, which is normal behavior:

{ '0': 50, '1': 50 }
{ '0': 49, '1': 51 }

{ '0': 41, '1': 59 }
{ '0': 60, '1': 40 }

{ '0': 49, '1': 51 }
{ '0': 39, '1': 61 }

{ '0': 59, '1': 41 }
{ '0': 49, '1': 51 }

Try with more shots:

{ '0': 5017, '1': 4983 }
{ '0': 5037, '1': 4963 }

{ '0': 4980, '1': 5020 }
{ '0': 4965, '1': 5035 }

{ '0': 5054, '1': 4946 }
{ '0': 5009, '1': 4991 }

By the way, there is: circuit.measureAllMultishot(numShots) method which simplifies code:

import QuantumCircuit from 'quantum-circuit';

var ss = new QuantumCircuit();
ss.addGate("h", 0,0) // Apply this so that imaginary part is accounted
ss.addGate("s", 1,0)
ss.addGate("s", 2,0)

var z = new QuantumCircuit();
z.addGate("h", 0,0) // Apply this so that imaginary part is accounted
z.addGate("z", 1, 0)

const shots = 100;
for(let circuit of [ss, z]) {
  circuit.run([true]);
  results = circuit.measureAllMultishot(shots);
  console.log(results)
}

P.S. if you try the same with Qiskit or other framework (also with real quantum computer), you will get similar results.

perak commented 2 months ago

I mean, this is a bug (in mathjs), but effect on results is insignificant.

perak commented 2 months ago

Ah, now I see what you are suggesting: simple solution to decimal error in this case is to simply change matrix definition from exp(i * pi / 2) to i. Will be done in the next update :+1: Thanks.

(but this will not change results in your example code - results are already correct)

perak commented 2 months ago

Fixed in v.0.9.223:

Thank you @glanzz