Skip to content
Permalink
Browse files

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
  • Loading branch information...
openql-org committed Jul 31, 2019
1 parent 02dc221 commit ebbf9d4465313bb6b451253ab15ed34ffb4fb2c0
Showing with 116 additions and 87 deletions.
  1. +0 −4 .travis.yml
  2. +48 −82 quantpy/sympy/executor/classical_simulation_executor.py
  3. +67 −0 quantpy/sympy/tests/test_numpy_sim.py
  4. +1 −1 requirements.txt
@@ -6,10 +6,6 @@ python:
# command to install dependencies
install:
- pip install -r requirements.txt
before_script: # configure a headless display to test plot generation
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- sleep 3 # give xvfb some time to start
# command to run tests
script:
- pytest # or py.test for Python versions 3.5 and below
@@ -4,14 +4,11 @@

from collections import defaultdict
import numpy as np
from qiskit import QuantumCircuit, transpiler
from qiskit.qasm import Qasm
from qiskit.providers.builtinsimulators import QasmSimulatorPy
from qiskit.converters import circuits_to_qobj
from qiskit.qobj import qobj_to_dict
import sympy

from quantpy.sympy.executor._base_quantum_executor import BaseQuantumExecutor
from quantpy.sympy.executor.simulator.numpy_simulator import NumpySimulator
import quantpy.sympy

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


def execute(self, circuit, **options):
"""
Execute sympy-circuit with classical simulator
We use numpy simulator as default
@param circuit sympy object to simulate
"""
qasm = self.to_qasm(circuit)
self.simulator = NumpySimulator()
basis_gates_str = (",".join(self.simulator.basis_gates)).lower()
# the following one-line compilation ignores basis_gates, and returnes "u2" for "h".
quantum_circuit = QuantumCircuit.from_qasm_str(qasm)
circuit = transpiler.transpile(quantum_circuit, basis_gates=basis_gates_str, backend=QasmSimulatorPy())
qobj = circuits_to_qobj(circuit, QasmSimulatorPy())
json = qobj_to_dict(qobj)["experiments"][0]
self.simulate(json)
return self.simulator.to_coefficients()

def simulate(self, circuitJson):
"""
Simulate qasm script with json format
@param circuitJson qasm in json format
"""

sim = self.simulator

numQubit = circuitJson["header"]["n_qubits"]
sim.initialize(numQubit)
qubit = circuit.args[-1]
assert isinstance(qubit, sympy.physics.quantum.qubit.Qubit), 'Sorry. Now, U*U*U*Qubit format is only supported'

self.simulator.initialize(qubit.dimension)

# set initial qubit value
for i, qb in enumerate(reversed(qubit.args)):
if isinstance(qb, sympy.numbers.One):
self.simulator.apply('x', i)

# main loop
GATE_TO_STR = {
sympy.physics.quantum.gate.HadamardGate: 'h',
sympy.physics.quantum.gate.XGate: 'x',
sympy.physics.quantum.gate.YGate: 'y',
sympy.physics.quantum.gate.ZGate: 'z',
sympy.physics.quantum.gate.PhaseGate: 's',
sympy.physics.quantum.gate.TGate: 't',
}
for gate in reversed(circuit.args[:-1]):
if isinstance(gate, sympy.physics.quantum.gate.IdentityGate):
continue

if "clbit_labels" in circuitJson["header"].keys():
numBit = len(circuitJson["header"]["clbit_labels"])
clbitsArray = np.zeros(numBit)
if type(gate) in GATE_TO_STR:
# gate without parameters
self.simulator.apply(GATE_TO_STR[type(gate)], int(gate.args[0]))

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

gateOps = operation["name"]
elif isinstance(gate, sympy.physics.quantum.gate.SwapGate):
self.simulator.apply('cx', int(gate.args[0]), int(gate.args[1]))
self.simulator.apply('cx', int(gate.args[1]), int(gate.args[0]))
self.simulator.apply('cx', int(gate.args[0]), int(gate.args[1]))

if not self.simulator.can_simulate_gate(gateOps):
print(" !!! {} is not supported !!!".format(gateOps))
print(operation)
continue
elif isinstance(gate, sympy.physics.quantum.gate.CGate):
control = tuple(gate.args[0])[0]
target_gate = gate.args[1]

gateTargets = operation["qubits"]

if "conditional" in operation.keys():
condition = operation["conditional"]
condVal = int(condition["val"], 0)
condMask = int(condition["mask"], 0)
flag = True
for ind in range(numBit):
if ((condMask >> ind) % 2 == 1):
flag = flag and (condVal % 2 == clbitsArray[ind])
condVal //= 2
if (not flag):
if isinstance(target_gate, sympy.physics.quantum.gate.IdentityGate):
continue

if "memory" in operation.keys():
measureTargets = operation["memory"]
if type(target_gate) in GATE_TO_STR:
# C-"simple" gate
self.simulator.apply(GATE_TO_STR[type(target_gate)],
int(target_gate.args[0]), control=control)

if "params" in operation.keys():
params = operation["params"]

# unparameterized gates
if (gateOps in ["x", "y", "z", "h", "s", "t", "cx", "cz", "CX"]):
if (len(gateTargets) == 1):
sim.apply(gateOps, target = gateTargets[0])
elif (len(gateTargets) == 2):
sim.apply(gateOps, target = gateTargets[0], control = gateTargets[1])
else:
raise ValueError("Too many target qubits")

# measurement
elif (gateOps in ["measure"]):
trace = sim.trace()
prob = sim.apply("M0", target = gateTargets[0], update=False) / trace
if (np.random.rand() < prob):
sim.update()
clbitsArray[measureTargets[0]] = 0
elif isinstance(target_gate, quantpy.sympy.Rk):
k = gate.args[1].k
self.simulator.apply('u', int(target_gate.args[0]), param=(1, float(k/2), float(k/2)))
else:
sim.apply("M1", target = gateTargets[0])
clbitsArray[measureTargets[0]] = 1
sim.normalize()

# generic unitary operation
elif (gateOps in ["U"]):
sim.apply("U", target = gateTargets[0], param = params)

assert False, '{} it is not a gate operator, nor is a supported operator'.format(repr(gate))
else:
raise ValueError("Op:{} is contained in basis gates, but not supported in simulator".format(operation))
assert False, '{} it is not a gate operator, nor is a supported operator'.format(repr(gate))

return self.simulator.to_coefficients()

def getStateStr(self):
"""
@@ -0,0 +1,67 @@
import time
import pytest
import functools

from sympy import simplify
from sympy.physics.quantum.gate import H, X, Y, Z, IdentityGate, PhaseGate, TGate, CNotGate, SwapGate, CGate
from sympy.physics.quantum.qubit import Qubit, QubitBra
from sympy.physics.quantum.qapply import qapply as sympy_qapply
from quantpy.sympy import Rk

from sympy.physics.quantum.qft import RkGate
from quantpy.sympy.qapply import qapply
from quantpy.sympy.executor.classical_simulation_executor import ClassicalSimulationExecutor

#from sympy.physics.quantum.qapply import qapply

ERR = 1e-9
def normalize(values):
e = None
for c in values:
if abs(c) < ERR:
continue
e = c.conjugate() / abs(c)
else:
return True
return [ e * c for c in coefficient]


def same_state(state_numpy, state_sympy):
# fix global phase
n = normalize([ state_numpy.get('{:02b}'.format(x), 0) for x in range(4)])
s = normalize([ sympy_qapply(QubitBra('{:02b}'.format(x)) * state_sympy).doit() for x in range(4) ])
for i in range(4):
if abs(n - s) > ERR:
return False
return True


@pytest.mark.parametrize("gate", [
IdentityGate(0),
H(0),
X(0),
Y(0),
Z(0),
PhaseGate(0),
TGate(0),
CNotGate(0, 1),
CGate((0,), IdentityGate(1)),
CGate((0,), H(1)),
CGate((0,), X(1)),
CGate((0,), Y(1)),
CGate((0,), Z(1)),
CGate((0,), PhaseGate(1)),
CGate((0,), TGate(1)),
])
def test_numpy_simulator(gate):
for bits in ['00', '01', '10', '11']:
circuit = gate * Qubit(bits)
executor = ClassicalSimulationExecutor()
assert same_state(qapply(circuit, executor=executor), sympy_qapply(circuit)), "failed {} * Qubit({})".format(gate, bits)

def test_rk():
for bits in ['00', '01', '10', '11']:
circuit_quantpy = CGate((0,), Rk(1, 4)) * Qubit(bits)
circuit_sympy = CGate((0,), RkGate(1, 4)) * Qubit(bits)
executor = ClassicalSimulationExecutor()
assert same_state(qapply(circuit_quantpy, executor=executor), sympy_qapply(circuit_sympy)), "failed Rk * Qubit({})".format(bits)
@@ -1,3 +1,3 @@
numpy
qiskit >= 0.7.0
qiskit == 0.11.1
sympy == 1.4

0 comments on commit ebbf9d4

Please sign in to comment.
You can’t perform that action at this time.