Skip to content

Commit ebbf9d4

Browse files
authored
catch up to Qiskit 0.11 (#47)
* catch up to Qiskit 0.11 (#46) * remove qiskit dependency from classical simulation_executor. test passed, but C-Rk gate is not yet implmented * removed `before_script` ref : https://benlimmer.com/2019/01/14/travis-ci-xvfb/ * added test for numpy executor * removed format string, removed unnecessary print() * fixed qiskit version to 0.11.1
1 parent 02dc221 commit ebbf9d4

File tree

4 files changed

+116
-87
lines changed

4 files changed

+116
-87
lines changed

.travis.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ python:
66
# command to install dependencies
77
install:
88
- pip install -r requirements.txt
9-
before_script: # configure a headless display to test plot generation
10-
- "export DISPLAY=:99.0"
11-
- "sh -e /etc/init.d/xvfb start"
12-
- sleep 3 # give xvfb some time to start
139
# command to run tests
1410
script:
1511
- pytest # or py.test for Python versions 3.5 and below

quantpy/sympy/executor/classical_simulation_executor.py

Lines changed: 48 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@
44

55
from collections import defaultdict
66
import numpy as np
7-
from qiskit import QuantumCircuit, transpiler
8-
from qiskit.qasm import Qasm
9-
from qiskit.providers.builtinsimulators import QasmSimulatorPy
10-
from qiskit.converters import circuits_to_qobj
11-
from qiskit.qobj import qobj_to_dict
7+
import sympy
128

139
from quantpy.sympy.executor._base_quantum_executor import BaseQuantumExecutor
1410
from quantpy.sympy.executor.simulator.numpy_simulator import NumpySimulator
11+
import quantpy.sympy
1512

1613
def _default_random_sequence(num):
1714
import random
@@ -23,95 +20,64 @@ def __init__(self):
2320
super().__init__()
2421
self.simulator = None
2522

26-
2723
def execute(self, circuit, **options):
28-
"""
29-
Execute sympy-circuit with classical simulator
30-
We use numpy simulator as default
31-
@param circuit sympy object to simulate
32-
"""
33-
qasm = self.to_qasm(circuit)
3424
self.simulator = NumpySimulator()
35-
basis_gates_str = (",".join(self.simulator.basis_gates)).lower()
36-
# the following one-line compilation ignores basis_gates, and returnes "u2" for "h".
37-
quantum_circuit = QuantumCircuit.from_qasm_str(qasm)
38-
circuit = transpiler.transpile(quantum_circuit, basis_gates=basis_gates_str, backend=QasmSimulatorPy())
39-
qobj = circuits_to_qobj(circuit, QasmSimulatorPy())
40-
json = qobj_to_dict(qobj)["experiments"][0]
41-
self.simulate(json)
42-
return self.simulator.to_coefficients()
43-
44-
def simulate(self, circuitJson):
45-
"""
46-
Simulate qasm script with json format
47-
@param circuitJson qasm in json format
48-
"""
49-
50-
sim = self.simulator
51-
52-
numQubit = circuitJson["header"]["n_qubits"]
53-
sim.initialize(numQubit)
25+
qubit = circuit.args[-1]
26+
assert isinstance(qubit, sympy.physics.quantum.qubit.Qubit), 'Sorry. Now, U*U*U*Qubit format is only supported'
27+
28+
self.simulator.initialize(qubit.dimension)
29+
30+
# set initial qubit value
31+
for i, qb in enumerate(reversed(qubit.args)):
32+
if isinstance(qb, sympy.numbers.One):
33+
self.simulator.apply('x', i)
34+
35+
# main loop
36+
GATE_TO_STR = {
37+
sympy.physics.quantum.gate.HadamardGate: 'h',
38+
sympy.physics.quantum.gate.XGate: 'x',
39+
sympy.physics.quantum.gate.YGate: 'y',
40+
sympy.physics.quantum.gate.ZGate: 'z',
41+
sympy.physics.quantum.gate.PhaseGate: 's',
42+
sympy.physics.quantum.gate.TGate: 't',
43+
}
44+
for gate in reversed(circuit.args[:-1]):
45+
if isinstance(gate, sympy.physics.quantum.gate.IdentityGate):
46+
continue
5447

55-
if "clbit_labels" in circuitJson["header"].keys():
56-
numBit = len(circuitJson["header"]["clbit_labels"])
57-
clbitsArray = np.zeros(numBit)
48+
if type(gate) in GATE_TO_STR:
49+
# gate without parameters
50+
self.simulator.apply(GATE_TO_STR[type(gate)], int(gate.args[0]))
5851

59-
for operation in circuitJson["instructions"]:
52+
elif isinstance(gate, sympy.physics.quantum.gate.CNotGate):
53+
self.simulator.apply('cx', int(gate.args[0]), int(gate.args[1]))
6054

61-
gateOps = operation["name"]
55+
elif isinstance(gate, sympy.physics.quantum.gate.SwapGate):
56+
self.simulator.apply('cx', int(gate.args[0]), int(gate.args[1]))
57+
self.simulator.apply('cx', int(gate.args[1]), int(gate.args[0]))
58+
self.simulator.apply('cx', int(gate.args[0]), int(gate.args[1]))
6259

63-
if not self.simulator.can_simulate_gate(gateOps):
64-
print(" !!! {} is not supported !!!".format(gateOps))
65-
print(operation)
66-
continue
60+
elif isinstance(gate, sympy.physics.quantum.gate.CGate):
61+
control = tuple(gate.args[0])[0]
62+
target_gate = gate.args[1]
6763

68-
gateTargets = operation["qubits"]
69-
70-
if "conditional" in operation.keys():
71-
condition = operation["conditional"]
72-
condVal = int(condition["val"], 0)
73-
condMask = int(condition["mask"], 0)
74-
flag = True
75-
for ind in range(numBit):
76-
if ((condMask >> ind) % 2 == 1):
77-
flag = flag and (condVal % 2 == clbitsArray[ind])
78-
condVal //= 2
79-
if (not flag):
64+
if isinstance(target_gate, sympy.physics.quantum.gate.IdentityGate):
8065
continue
8166

82-
if "memory" in operation.keys():
83-
measureTargets = operation["memory"]
67+
if type(target_gate) in GATE_TO_STR:
68+
# C-"simple" gate
69+
self.simulator.apply(GATE_TO_STR[type(target_gate)],
70+
int(target_gate.args[0]), control=control)
8471

85-
if "params" in operation.keys():
86-
params = operation["params"]
87-
88-
# unparameterized gates
89-
if (gateOps in ["x", "y", "z", "h", "s", "t", "cx", "cz", "CX"]):
90-
if (len(gateTargets) == 1):
91-
sim.apply(gateOps, target = gateTargets[0])
92-
elif (len(gateTargets) == 2):
93-
sim.apply(gateOps, target = gateTargets[0], control = gateTargets[1])
94-
else:
95-
raise ValueError("Too many target qubits")
96-
97-
# measurement
98-
elif (gateOps in ["measure"]):
99-
trace = sim.trace()
100-
prob = sim.apply("M0", target = gateTargets[0], update=False) / trace
101-
if (np.random.rand() < prob):
102-
sim.update()
103-
clbitsArray[measureTargets[0]] = 0
72+
elif isinstance(target_gate, quantpy.sympy.Rk):
73+
k = gate.args[1].k
74+
self.simulator.apply('u', int(target_gate.args[0]), param=(1, float(k/2), float(k/2)))
10475
else:
105-
sim.apply("M1", target = gateTargets[0])
106-
clbitsArray[measureTargets[0]] = 1
107-
sim.normalize()
108-
109-
# generic unitary operation
110-
elif (gateOps in ["U"]):
111-
sim.apply("U", target = gateTargets[0], param = params)
112-
76+
assert False, '{} it is not a gate operator, nor is a supported operator'.format(repr(gate))
11377
else:
114-
raise ValueError("Op:{} is contained in basis gates, but not supported in simulator".format(operation))
78+
assert False, '{} it is not a gate operator, nor is a supported operator'.format(repr(gate))
79+
80+
return self.simulator.to_coefficients()
11581

11682
def getStateStr(self):
11783
"""
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import time
2+
import pytest
3+
import functools
4+
5+
from sympy import simplify
6+
from sympy.physics.quantum.gate import H, X, Y, Z, IdentityGate, PhaseGate, TGate, CNotGate, SwapGate, CGate
7+
from sympy.physics.quantum.qubit import Qubit, QubitBra
8+
from sympy.physics.quantum.qapply import qapply as sympy_qapply
9+
from quantpy.sympy import Rk
10+
11+
from sympy.physics.quantum.qft import RkGate
12+
from quantpy.sympy.qapply import qapply
13+
from quantpy.sympy.executor.classical_simulation_executor import ClassicalSimulationExecutor
14+
15+
#from sympy.physics.quantum.qapply import qapply
16+
17+
ERR = 1e-9
18+
def normalize(values):
19+
e = None
20+
for c in values:
21+
if abs(c) < ERR:
22+
continue
23+
e = c.conjugate() / abs(c)
24+
else:
25+
return True
26+
return [ e * c for c in coefficient]
27+
28+
29+
def same_state(state_numpy, state_sympy):
30+
# fix global phase
31+
n = normalize([ state_numpy.get('{:02b}'.format(x), 0) for x in range(4)])
32+
s = normalize([ sympy_qapply(QubitBra('{:02b}'.format(x)) * state_sympy).doit() for x in range(4) ])
33+
for i in range(4):
34+
if abs(n - s) > ERR:
35+
return False
36+
return True
37+
38+
39+
@pytest.mark.parametrize("gate", [
40+
IdentityGate(0),
41+
H(0),
42+
X(0),
43+
Y(0),
44+
Z(0),
45+
PhaseGate(0),
46+
TGate(0),
47+
CNotGate(0, 1),
48+
CGate((0,), IdentityGate(1)),
49+
CGate((0,), H(1)),
50+
CGate((0,), X(1)),
51+
CGate((0,), Y(1)),
52+
CGate((0,), Z(1)),
53+
CGate((0,), PhaseGate(1)),
54+
CGate((0,), TGate(1)),
55+
])
56+
def test_numpy_simulator(gate):
57+
for bits in ['00', '01', '10', '11']:
58+
circuit = gate * Qubit(bits)
59+
executor = ClassicalSimulationExecutor()
60+
assert same_state(qapply(circuit, executor=executor), sympy_qapply(circuit)), "failed {} * Qubit({})".format(gate, bits)
61+
62+
def test_rk():
63+
for bits in ['00', '01', '10', '11']:
64+
circuit_quantpy = CGate((0,), Rk(1, 4)) * Qubit(bits)
65+
circuit_sympy = CGate((0,), RkGate(1, 4)) * Qubit(bits)
66+
executor = ClassicalSimulationExecutor()
67+
assert same_state(qapply(circuit_quantpy, executor=executor), sympy_qapply(circuit_sympy)), "failed Rk * Qubit({})".format(bits)

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
numpy
2-
qiskit >= 0.7.0
2+
qiskit == 0.11.1
33
sympy == 1.4

0 commit comments

Comments
 (0)