-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Qiskit v0.23 updates #112
Qiskit v0.23 updates #112
Changes from all commits
90a72ac
47c5aef
e474865
40173c9
819de2d
9f27b63
6201c54
084f456
fc55a1b
5f71da1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,25 @@ | |
from ._version import __version__ | ||
|
||
|
||
# Auxiliary functions for gates subject to deprecation | ||
def U1Gate(theta): | ||
"""Auxiliary function for the ``U1Gate``.""" | ||
return ex.PhaseGate(theta) | ||
|
||
|
||
def U2Gate(phi, lam): | ||
"""Auxiliary function for the ``U2Gate``. | ||
|
||
Uses the equation ``u2(phi, lam) = u(pi/2, phi, lam)``. | ||
""" | ||
return ex.U(np.pi / 2, phi, lam) | ||
|
||
|
||
def U3Gate(theta, phi, lam): | ||
"""Auxiliary function for the ``U3Gate``.""" | ||
return ex.U(theta, phi, lam) | ||
Comment on lines
+36
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very nice solution! |
||
|
||
|
||
QISKIT_OPERATION_MAP = { | ||
# native PennyLane operations also native to qiskit | ||
"PauliX": ex.XGate, | ||
|
@@ -52,12 +71,16 @@ | |
"CRX": ex.CRXGate, | ||
"CRY": ex.CRYGate, | ||
"CRZ": ex.CRZGate, | ||
"PhaseShift": ex.U1Gate, | ||
"PhaseShift": ex.PhaseGate, | ||
"QubitStateVector": ex.Initialize, | ||
"U2": ex.U2Gate, | ||
"U3": ex.U3Gate, | ||
"Toffoli": ex.CCXGate, | ||
"QubitUnitary": ex.UnitaryGate, | ||
"U": ex.UGate, | ||
# Qiskit gates subject to deprecation (using custom definitions that depend on | ||
# the latest recommended gates) | ||
"U1": U1Gate, | ||
"U2": U2Gate, | ||
"U3": U3Gate, | ||
} | ||
|
||
# Separate dictionary for the inverses as the operations dictionary needs | ||
|
@@ -147,22 +170,28 @@ def __init__(self, wires, provider, backend, shots=1024, **kwargs): | |
# Initialize inner state | ||
self.reset() | ||
|
||
# determine if backend supports backend options and noise models, | ||
# and properly put together backend run arguments | ||
s = inspect.signature(b.run) | ||
self.run_args = {} | ||
self.compile_backend = None | ||
|
||
if "compile_backend" in kwargs: | ||
self.compile_backend = kwargs.pop("compile_backend") | ||
|
||
aer_provider = str(provider) == "AerProvider" | ||
self.noise_model = None | ||
if "noise_model" in kwargs: | ||
if "noise_model" in s.parameters: | ||
self.run_args["noise_model"] = kwargs.pop("noise_model") | ||
else: | ||
if not aer_provider or backend != "qasm_simulator": | ||
raise ValueError("Backend {} does not support noisy simulations".format(backend)) | ||
|
||
if "backend_options" in s.parameters: | ||
self.noise_model = kwargs.pop("noise_model") | ||
|
||
# Get further arguments for run | ||
s = inspect.signature(b.run) | ||
self.run_args = {} | ||
|
||
if aer_provider: | ||
# Consider the remaining kwargs as keyword arguments to run | ||
self.run_args.update(kwargs) | ||
Comment on lines
+189
to
+191
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
elif "backend_options" in s.parameters: | ||
# BasicAer | ||
Comment on lines
+193
to
+194
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not seem to be the case for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that the entirety of |
||
self.run_args["backend_options"] = kwargs | ||
|
||
@property | ||
|
@@ -177,6 +206,7 @@ def reset(self): | |
|
||
self._current_job = None | ||
self._state = None # statevector of a simulator backend | ||
self.noise_model = None | ||
|
||
def apply(self, operations, **kwargs): | ||
rotations = kwargs.get("rotations", []) | ||
|
@@ -276,14 +306,17 @@ def compile(self): | |
memory = str(compile_backend) not in self._state_backends | ||
|
||
return assemble( | ||
experiments=compiled_circuits, | ||
backend=compile_backend, | ||
shots=self.shots, | ||
memory=memory, | ||
experiments=compiled_circuits, backend=compile_backend, shots=self.shots, memory=memory | ||
) | ||
|
||
def run(self, qobj): | ||
"""Run the compiled circuit, and query the result.""" | ||
backend = self.backend | ||
|
||
if self.noise_model: | ||
# Set the noise model before execution | ||
backend.set_options(noise_model=self.noise_model) | ||
|
||
self._current_job = self.backend.run(qobj, **self.run_args) | ||
result = self._current_job.result() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
qiskit>=0.20 | ||
qiskit>=0.23 | ||
pennylane>=0.11.0 | ||
numpy | ||
networkx>=2.2;python_version>'3.5' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,7 +132,7 @@ def test_quantum_circuit_with_gate_requiring_multiple_parameters(self, recorder) | |
theta = Parameter('θ') | ||
|
||
qc = QuantumCircuit(3, 1) | ||
qc.u3(phi, lam, theta, [0]) | ||
qc.u(phi, lam, theta, [0]) | ||
|
||
quantum_circuit = load(qc) | ||
|
||
|
@@ -333,12 +333,11 @@ def test_one_qubit_parametrized_operations_supported_by_pennylane(self, recorder | |
q_reg = QuantumRegister(1) | ||
qc = QuantumCircuit(q_reg) | ||
|
||
qc.u1(angle, single_wire) | ||
qc.p(angle, single_wire) | ||
qc.rx(angle, single_wire) | ||
qc.ry(angle, single_wire) | ||
qc.rz(angle, single_wire) | ||
qc.u2(phi, lam, [0]) | ||
qc.u3(phi, lam, theta, [0]) | ||
qc.u(phi, lam, theta, [0]) | ||
|
||
quantum_circuit = load(qc) | ||
with recorder: | ||
|
@@ -360,16 +359,11 @@ def test_one_qubit_parametrized_operations_supported_by_pennylane(self, recorder | |
assert recorder.queue[3].parameters == [angle] | ||
assert recorder.queue[3].wires == Wires(single_wire) | ||
|
||
assert recorder.queue[4].name == 'U2' | ||
assert len(recorder.queue[4].parameters) == 2 | ||
assert recorder.queue[4].parameters == [0.3, 0.4] | ||
assert recorder.queue[4].name == 'U3' | ||
assert len(recorder.queue[4].parameters) == 3 | ||
assert recorder.queue[4].parameters == [0.3, 0.4, 0.2] | ||
assert recorder.queue[4].wires == Wires([0]) | ||
|
||
assert recorder.queue[5].name == 'U3' | ||
assert len(recorder.queue[5].parameters) == 3 | ||
assert recorder.queue[5].parameters == [0.3, 0.4, 0.2] | ||
assert recorder.queue[5].wires == Wires([0]) | ||
|
||
def test_two_qubit_operations_supported_by_pennylane(self, recorder): | ||
"""Tests loading a circuit with the two-qubit operations supported by PennyLane.""" | ||
|
||
|
@@ -551,36 +545,60 @@ def test_operation_transformed_into_qubit_unitary(self, recorder): | |
assert np.array_equal(recorder.queue[0].parameters[0], ex.CHGate().to_matrix()) | ||
assert recorder.queue[0].wires == Wires([0, 1]) | ||
|
||
def test_quantum_circuit_error_by_passing_wrong_parameters(self, recorder): | ||
"""Tests the load method for a QuantumCircuit raises a QiskitError, | ||
if the wrong type of arguments were passed.""" | ||
def test_qiskit_gates_to_be_deprecated(self, recorder): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a good idea. This way, we will know when the gates have been removed due to this test failing :) |
||
"""Tests the Qiskit gates that will be deprecated in an upcoming Qiskit version. | ||
|
||
This test case can be removed once the gates are finally deprecated. | ||
""" | ||
qc = QuantumCircuit(1, 1) | ||
|
||
theta = Parameter('θ') | ||
angle = 'some_string_instead_of_an_angle' | ||
single_wire = [0] | ||
|
||
qc = QuantumCircuit(3, 1) | ||
qc.rz(theta, [0]) | ||
with pytest.warns(DeprecationWarning) as record: | ||
with recorder: | ||
qc.u1(0.1, single_wire) | ||
qc.u2(0.1, 0.2, single_wire) | ||
qc.u3(0.1, 0.2, 0.3, single_wire) | ||
|
||
# check that warnings were raised | ||
assert len(record) == 3 | ||
# check that the message matches | ||
deprecation_substring = "method is deprecated" | ||
assert deprecation_substring in record[0].message.args[0] | ||
assert deprecation_substring in record[1].message.args[0] | ||
assert deprecation_substring in record[2].message.args[0] | ||
|
||
quantum_circuit = load(qc) | ||
with recorder: | ||
quantum_circuit() | ||
|
||
with pytest.raises(QiskitError): | ||
with recorder: | ||
quantum_circuit(params={theta: angle}) | ||
assert recorder.queue[0].name == 'U1' | ||
assert recorder.queue[0].parameters == [0.1] | ||
assert recorder.queue[0].wires == Wires(single_wire) | ||
|
||
assert recorder.queue[1].name == 'U2' | ||
assert recorder.queue[1].parameters == [0.1, 0.2] | ||
assert recorder.queue[1].wires == Wires(single_wire) | ||
|
||
assert recorder.queue[2].name == 'U3' | ||
assert recorder.queue[2].parameters == [0.1, 0.2, 0.3] | ||
assert recorder.queue[2].wires == Wires(single_wire) | ||
|
||
def test_quantum_circuit_error_by_calling_wrong_parameters(self, recorder): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Weird diff from GitHub, this test was removed. It doesn't make too much sense as parameter validation has been added to Qiskit so a string input would not work. Arrays will soon be deprecated too. |
||
"""Tests that the load method for a QuantumCircuit raises a TypeError, | ||
def test_quantum_circuit_error_by_passing_wrong_parameters(self, recorder): | ||
"""Tests the load method for a QuantumCircuit raises a QiskitError, | ||
if the wrong type of arguments were passed.""" | ||
|
||
theta = Parameter('θ') | ||
angle = 'some_string_instead_of_an_angle' | ||
|
||
qc = QuantumCircuit(3, 1) | ||
qc.rz(angle, [0]) | ||
qc.rz(theta, [0]) | ||
|
||
quantum_circuit = load(qc) | ||
|
||
with pytest.raises(TypeError, match="parameter expected, got <class 'str'>"): | ||
with pytest.raises(QiskitError): | ||
with recorder: | ||
quantum_circuit() | ||
quantum_circuit(params={theta: angle}) | ||
|
||
def test_quantum_circuit_error_passing_parameters_not_required(self, recorder): | ||
"""Tests the load method raises a QiskitError if arguments | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I'll convert this into an issue so that we don't forget
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#113