From 1b46638dcb8c90df2a227925dd8f3ee1f8799d00 Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Mon, 4 Mar 2024 13:37:09 +0000 Subject: [PATCH 1/6] Simple fixes --- pytket/extensions/qiskit/backends/aer.py | 8 ++-- .../qiskit/backends/crosstalk_model.py | 2 +- .../qiskit/backends/ibmq_emulator.py | 2 +- pytket/extensions/qiskit/tket_pass.py | 2 +- setup.py | 8 ++-- tests/backend_test.py | 6 +-- tests/qiskit_backend_test.py | 16 ++++---- tests/qiskit_convert_test.py | 38 +++++++++++-------- 8 files changed, 44 insertions(+), 38 deletions(-) diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index 480d4b45..f7d0467b 100644 --- a/pytket/extensions/qiskit/backends/aer.py +++ b/pytket/extensions/qiskit/backends/aer.py @@ -30,7 +30,7 @@ import numpy as np from qiskit import transpile # type: ignore -from qiskit.providers.aer.noise import NoiseModel # type: ignore +from qiskit_aer.noise import NoiseModel # type: ignore from qiskit.quantum_info.operators import Pauli as qk_Pauli # type: ignore from qiskit.quantum_info.operators.symplectic.sparse_pauli_op import SparsePauliOp # type: ignore from qiskit_aer import Aer # type: ignore @@ -80,8 +80,8 @@ ) if TYPE_CHECKING: - from qiskit.providers.aer import AerJob # type: ignore - from qiskit.providers.aer.backends.aerbackend import AerBackend as QiskitAerBackend # type: ignore + from qiskit_aer import AerJob # type: ignore + from qiskit_aer.backends.aerbackend import AerBackend as QiskitAerBackend # type: ignore def _default_q_index(q: Qubit) -> int: @@ -477,7 +477,7 @@ def __init__( :param noise_model: Noise model to apply during simulation. Defaults to None. :type noise_model: Optional[NoiseModel], optional :param simulation_method: Simulation method, see - https://qiskit.org/documentation/stubs/qiskit.providers.aer.AerSimulator.html + https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.AerSimulator.html for available values. Defaults to "automatic". :type simulation_method: str :param crosstalk_params: Apply crosstalk noise simulation to the circuits before diff --git a/pytket/extensions/qiskit/backends/crosstalk_model.py b/pytket/extensions/qiskit/backends/crosstalk_model.py index 25af7a0e..0964cf74 100644 --- a/pytket/extensions/qiskit/backends/crosstalk_model.py +++ b/pytket/extensions/qiskit/backends/crosstalk_model.py @@ -16,7 +16,7 @@ from typing import List, Tuple, Union, Dict, Optional from dataclasses import dataclass -from qiskit.providers.aer.noise import NoiseModel # type: ignore +from qiskit_aer.noise import NoiseModel # type: ignore from qiskit_aer.noise.errors.standard_errors import amplitude_damping_error, phase_damping_error # type: ignore import numpy as np diff --git a/pytket/extensions/qiskit/backends/ibmq_emulator.py b/pytket/extensions/qiskit/backends/ibmq_emulator.py index 93297427..fbd244be 100644 --- a/pytket/extensions/qiskit/backends/ibmq_emulator.py +++ b/pytket/extensions/qiskit/backends/ibmq_emulator.py @@ -27,7 +27,7 @@ ) from warnings import warn -from qiskit.providers.aer.noise.noise_model import NoiseModel # type: ignore +from qiskit_aer.noise.noise_model import NoiseModel # type: ignore from qiskit_ibm_runtime import ( # type: ignore QiskitRuntimeService, Session, diff --git a/pytket/extensions/qiskit/tket_pass.py b/pytket/extensions/qiskit/tket_pass.py index 37fb6fdf..bdceb7df 100644 --- a/pytket/extensions/qiskit/tket_pass.py +++ b/pytket/extensions/qiskit/tket_pass.py @@ -17,7 +17,7 @@ from qiskit.providers import BackendV1 # type: ignore from qiskit.transpiler.basepasses import TransformationPass, BasePass as qBasePass # type: ignore from qiskit.converters import circuit_to_dag, dag_to_circuit # type: ignore -from qiskit.providers.aer.aerprovider import AerProvider # type: ignore # type: ignore +from qiskit_aer.aerprovider import AerProvider # type: ignore # type: ignore from qiskit_ibm_provider import IBMProvider # type: ignore diff --git a/setup.py b/setup.py index f9e0c700..fd100438 100644 --- a/setup.py +++ b/setup.py @@ -45,11 +45,11 @@ include_package_data=True, install_requires=[ "pytket ~= 1.24", - "qiskit ~= 0.45.0", + "qiskit ~= 1.0.1", "qiskit-algorithms ~= 0.2.1", - "qiskit-ibm-runtime ~= 0.17.0", - "qiskit-aer ~= 0.13.0", - "qiskit-ibm-provider ~= 0.8.0", + "qiskit-ibm-runtime ~= 0.20.0", + "qiskit-aer ~= 0.13.3", + "qiskit-ibm-provider ~= 0.10.0", "numpy", ], classifiers=[ diff --git a/tests/backend_test.py b/tests/backend_test.py index 5dfc5130..3e1b9c2e 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -25,9 +25,9 @@ from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister # type: ignore from qiskit.circuit import Parameter # type: ignore -from qiskit.providers.aer.noise.noise_model import NoiseModel # type: ignore -from qiskit.providers.aer.noise import ReadoutError # type: ignore -from qiskit.providers.aer.noise.errors import depolarizing_error, pauli_error # type: ignore +from qiskit_aer.noise.noise_model import NoiseModel # type: ignore +from qiskit_aer.noise import ReadoutError # type: ignore +from qiskit_aer.noise.errors import depolarizing_error, pauli_error # type: ignore from qiskit_ibm_provider import IBMProvider # type: ignore from qiskit_aer import Aer # type: ignore diff --git a/tests/qiskit_backend_test.py b/tests/qiskit_backend_test.py index 26574934..ee73cb5f 100644 --- a/tests/qiskit_backend_test.py +++ b/tests/qiskit_backend_test.py @@ -18,7 +18,7 @@ import numpy as np import pytest -from qiskit import QuantumCircuit, execute # type: ignore +from qiskit import QuantumCircuit # type: ignore from qiskit.primitives import BackendSampler # type: ignore from qiskit.providers import JobStatus # type: ignore from qiskit_algorithms import Grover, AmplificationProblem, AlgorithmError # type: ignore @@ -66,7 +66,7 @@ def test_samples() -> None: b = AerBackend() for comp in (None, b.default_compilation_pass()): tb = TketBackend(b, comp) - job = execute(qc, tb, shots=100, memory=True) + job = tb.run(qc, shots=100, memory=True) shots = job.result().get_memory() assert all(((r[0] == "1" and r[1] == r[2]) for r in shots)) counts = job.result().get_counts() @@ -78,12 +78,12 @@ def test_state() -> None: b = AerStateBackend() for comp in (None, b.default_compilation_pass()): tb = TketBackend(b, comp) - job = execute(qc, tb) + job = tb.run(qc) state = job.result().get_statevector() qb = Aer.get_backend("aer_simulator_statevector") qc1 = qc.copy() qc1.save_state() - job2 = execute(qc1, qb) + job2 = qb.run(qc1) state2 = job2.result().get_statevector() assert np.allclose(state, state2) @@ -93,12 +93,12 @@ def test_unitary() -> None: b = AerUnitaryBackend() for comp in (None, b.default_compilation_pass()): tb = TketBackend(b, comp) - job = execute(qc, tb) + job = tb.run(qc) u = job.result().get_unitary() qb = Aer.get_backend("aer_simulator_unitary") qc1 = qc.copy() qc1.save_unitary() - job2 = execute(qc1, qb) + job2 = qb.run(qc1) u2 = job2.result().get_unitary() assert np.allclose(u, u2) @@ -107,7 +107,7 @@ def test_cancel() -> None: b = AerBackend() tb = TketBackend(b) qc = circuit_gen() - job = execute(qc, tb, shots=1024) + job = tb.run(qc, shots=1024) job.cancel() assert job.status() in [JobStatus.CANCELLED, JobStatus.DONE] @@ -137,7 +137,7 @@ def test_architectures() -> None: # without architecture b = MockShotBackend(arch=arch) tb = TketBackend(b, b.default_compilation_pass()) - job = execute(qc, tb, shots=100, memory=True) + job = tb.run(qc, shots=100, memory=True) shots = job.result().get_memory() assert all(((r[0] == "1" and r[1] == r[2]) for r in shots)) counts = job.result().get_counts() diff --git a/tests/qiskit_convert_test.py b/tests/qiskit_convert_test.py index 16c941fa..81bf258a 100644 --- a/tests/qiskit_convert_test.py +++ b/tests/qiskit_convert_test.py @@ -22,7 +22,7 @@ QuantumCircuit, QuantumRegister, ClassicalRegister, - execute, + transpile, ) from qiskit.quantum_info import SparsePauliOp, Statevector, Operator # type: ignore from qiskit.transpiler import PassManager # type: ignore @@ -33,7 +33,7 @@ from qiskit_aer import Aer # type: ignore from qiskit.transpiler.passes import BasisTranslator # type: ignore from qiskit.circuit.equivalence_library import StandardEquivalenceLibrary # type: ignore -from qiskit.providers.fake_provider import FakeGuadalupe # type: ignore +from qiskit_ibm_runtime.fake_provider import FakeGuadalupe # type: ignore from qiskit.circuit.parameterexpression import ParameterExpression # type: ignore from pytket.circuit import ( @@ -188,10 +188,12 @@ def test_convert() -> None: backend = Aer.get_backend("aer_simulator_statevector") qc.save_state() - job = execute([qc], backend) + qc = transpile(qc, backend) + job = backend.run([qc]) state0 = job.result().get_statevector(qc) qc1.save_state() - job1 = execute([qc1], backend) + qc1 = transpile(qc1, backend) + job1 = backend.run([qc1]) state1 = job1.result().get_statevector(qc1) assert np.allclose(state0, state1, atol=1e-10) @@ -214,7 +216,7 @@ def test_symbolic() -> None: qc = tk_to_qiskit(tkc2) assert qc.name == tkc.name qc.save_state() - job = execute([qc], backend) + job = backend.run([qc]) state1 = job.result().get_statevector(qc) state0 = np.array( [ @@ -234,11 +236,13 @@ def test_symbolic() -> None: def test_measures() -> None: qc = get_test_circuit(True) backend = Aer.get_backend("aer_simulator") - job = execute([qc], backend, seed_simulator=7) + qc = transpile(qc, backend) + job = backend.run([qc], seed_simulator=7) counts0 = job.result().get_counts(qc) tkc = qiskit_to_tk(qc) qc = tk_to_qiskit(tkc) - job = execute([qc], backend, seed_simulator=7) + qc = transpile(qc, backend) + job = backend.run([qc], seed_simulator=7) counts1 = job.result().get_counts(qc) for result, count in counts1.items(): result_str = result.replace(" ", "") @@ -276,7 +280,7 @@ def test_Unitary1qBox() -> None: # Verify that unitary from simulator is correct back = Aer.get_backend("aer_simulator_unitary") qc.save_unitary() - job = execute(qc, back).result() + job = back.run(qc).result() a = job.get_unitary(qc) u1 = np.asarray(a) assert np.allclose(u1, u) @@ -292,7 +296,7 @@ def test_Unitary2qBox() -> None: # Verify that unitary from simulator is correct back = Aer.get_backend("aer_simulator_unitary") qc.save_unitary() - job = execute(qc, back).result() + job = back.run(qc).result() a = job.get_unitary(qc) u1 = permute_rows_cols_in_unitary(np.asarray(a), (1, 0)) # correct for endianness assert np.allclose(u1, u) @@ -319,7 +323,7 @@ def test_Unitary3qBox() -> None: # Verify that unitary from simulator is correct back = Aer.get_backend("aer_simulator_unitary") qc.save_unitary() - job = execute(qc, back).result() + job = back.run(qc).result() a = job.get_unitary(qc) u1 = permute_rows_cols_in_unitary( np.asarray(a), (2, 1, 0) @@ -351,13 +355,13 @@ def test_tketpass() -> None: tkpass.apply(tkc) qc1 = tk_to_qiskit(tkc) qc1.save_unitary() - res = execute(qc1, back).result() + res = back.run(qc1).result() u1 = res.get_unitary(qc1) qispass = TketPass(tkpass) pm = PassManager(qispass) qc2 = pm.run(qc) qc2.save_unitary() - res = execute(qc2, back).result() + res = back.run(qc2).result() u2 = res.get_unitary(qc2) assert np.allclose(u1, u2) @@ -517,7 +521,8 @@ def test_customgate() -> None: states = [] for qc in (qc1, qc2, correct_qc): qc.save_state() - job = execute([qc], backend) + qc = transpile(qc, backend) + job = backend.run([qc]) states.append(job.result().get_statevector(qc)) assert compare_statevectors(states[0], states[1]) @@ -538,7 +543,7 @@ def test_convert_result() -> None: simulator = Aer.get_backend("aer_simulator_statevector") qc1 = qc.copy() qc1.save_state() - qisk_result = execute(qc1, simulator, shots=10).result() + qisk_result = simulator.run(qc1, shots=10).result() tk_res = next(qiskit_result_to_backendresult(qisk_result)) @@ -552,7 +557,7 @@ def test_convert_result() -> None: qc.measure(qr2[1], cr2[0]) simulator = Aer.get_backend("aer_simulator") - qisk_result = execute(qc, simulator, shots=10).result() + qisk_result = simulator.run(qc, shots=10).result() tk_res = next(qiskit_result_to_backendresult(qisk_result)) one_bits = [Bit("z", 0), Bit("b", 0)] @@ -652,7 +657,8 @@ def assert_equivalence( assert isinstance(circ, QuantumCircuit) circ1 = circ.copy() circ1.save_unitary() - job = execute(circ1, backend) + circ1 = transpile(circ1, backend) + job = backend.run(circ1) unitaries.append(job.result().get_unitary(circ1)) for nn in range(1, len(circuits)): # Default np.allclose is very lax here, so use strict tolerances From d43c3a9da907b676a8438b2857184966d9f0ccd2 Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Mon, 4 Mar 2024 13:37:40 +0000 Subject: [PATCH 2/6] Fix for removed Clbit attributes --- pytket/extensions/qiskit/qiskit_convert.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pytket/extensions/qiskit/qiskit_convert.py b/pytket/extensions/qiskit/qiskit_convert.py index 7d04ba63..3210a7f1 100644 --- a/pytket/extensions/qiskit/qiskit_convert.py +++ b/pytket/extensions/qiskit/qiskit_convert.py @@ -339,7 +339,8 @@ def add_xs( if ((c >> i) & 1) == 0: self.tkc.X(self.qbmap[qargs[i]]) - def add_qiskit_data(self, data: "QuantumCircuitData") -> None: + def add_qiskit_data(self, circuit: QuantumCircuit, data: Optional["QuantumCircuitData"] = None) -> None: + data = data or circuit.data for instr, qargs, cargs in data: condition_kwargs = {} if instr.condition is not None: @@ -350,9 +351,13 @@ def add_qiskit_data(self, data: "QuantumCircuitData") -> None: "condition_value": instr.condition[1], } elif type(instr.condition[0]) == Clbit: - cond_reg = self.cregmap[instr.condition[0].register] + # .find_bit() returns tuple[index, list[tuple[ ClassicalRegister, index]]] + # We assume each bit belongs to exactly one register. + index = circuit.find_bit(instr.condition[0])[0] + register = circuit.find_bit(instr.condition[0])[1][0][0] + cond_reg = self.cregmap[register] condition_kwargs = { - "condition_bits": [cond_reg[instr.condition[0].index]], + "condition_bits": [cond_reg[index]], "condition_value": instr.condition[1], } else: @@ -501,7 +506,7 @@ def add_qiskit_data(self, data: "QuantumCircuitData") -> None: else [] ) builder = CircuitBuilder(qregs, cregs) - builder.add_qiskit_data(instr.definition) + builder.add_qiskit_data(circuit, instr.definition) subc = builder.circuit() subc.name = instr.name self.tkc.add_circbox(CircBox(subc), qubits + bits, **condition_kwargs) # type: ignore @@ -551,7 +556,7 @@ def qiskit_to_tk(qcirc: QuantumCircuit, preserve_param_uuid: bool = False) -> Ci name=circ_name, phase=param_to_tk(qcirc.global_phase), ) - builder.add_qiskit_data(qcirc.data) + builder.add_qiskit_data(qcirc) return builder.circuit() From 4029dda3c7dd21426886a6951750bbd388512edb Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Mon, 4 Mar 2024 13:43:49 +0000 Subject: [PATCH 3/6] Update changelog --- docs/changelog.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 1fd0cafc..f7849079 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,14 @@ Changelog ~~~~~~~~~ +0.49.0 +------ + +* Update qiskit version to 1.0 +* Update qiskit-ibm-runtime to 0.20.0 +* Update qiskit-ibm-provider to 0.10.0 +* Update qiskit-aer to 0.13.3 + 0.48.1rc1 --------- From 75b5ddc26d1c0d70e079ad27329cd9acc2237b30 Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Mon, 4 Mar 2024 13:47:07 +0000 Subject: [PATCH 4/6] Update docs --- docs/intro.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/intro.txt b/docs/intro.txt index 0bdda121..e747ce3d 100644 --- a/docs/intro.txt +++ b/docs/intro.txt @@ -1,7 +1,7 @@ pytket-qiskit ================================== -IBM's `Qiskit `_ is an open-source framework for quantum +IBM's `Qiskit `_ is an open-source framework for quantum computation, ranging from high-level algorithms to low-level circuit representations, simulation and access to the `IBMQ `_ Experience devices. From a593450b0d585dbe6baaee277552e1162ee4ba8f Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Mon, 4 Mar 2024 14:30:40 +0000 Subject: [PATCH 5/6] lint :sparkles: --- pytket/extensions/qiskit/qiskit_convert.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pytket/extensions/qiskit/qiskit_convert.py b/pytket/extensions/qiskit/qiskit_convert.py index 3210a7f1..6aab6fd5 100644 --- a/pytket/extensions/qiskit/qiskit_convert.py +++ b/pytket/extensions/qiskit/qiskit_convert.py @@ -72,7 +72,6 @@ Unitary2qBox, Unitary3qBox, UnitType, - CustomGateDef, Bit, Qubit, QControlBox, @@ -339,7 +338,9 @@ def add_xs( if ((c >> i) & 1) == 0: self.tkc.X(self.qbmap[qargs[i]]) - def add_qiskit_data(self, circuit: QuantumCircuit, data: Optional["QuantumCircuitData"] = None) -> None: + def add_qiskit_data( + self, circuit: QuantumCircuit, data: Optional["QuantumCircuitData"] = None + ) -> None: data = data or circuit.data for instr, qargs, cargs in data: condition_kwargs = {} @@ -351,7 +352,8 @@ def add_qiskit_data(self, circuit: QuantumCircuit, data: Optional["QuantumCircui "condition_value": instr.condition[1], } elif type(instr.condition[0]) == Clbit: - # .find_bit() returns tuple[index, list[tuple[ ClassicalRegister, index]]] + # .find_bit() returns type: + # tuple[index, list[tuple[ClassicalRegister, index]]] # We assume each bit belongs to exactly one register. index = circuit.find_bit(instr.condition[0])[0] register = circuit.find_bit(instr.condition[0])[1][0][0] From 0bbafb42a12ba2a5a55a55559fcd0ed94b3b88ce Mon Sep 17 00:00:00 2001 From: cqc-melf <70640934+cqc-melf@users.noreply.github.com> Date: Mon, 4 Mar 2024 15:45:56 +0000 Subject: [PATCH 6/6] Update ibmq_local_emulator.py --- pytket/extensions/qiskit/backends/ibmq_local_emulator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytket/extensions/qiskit/backends/ibmq_local_emulator.py b/pytket/extensions/qiskit/backends/ibmq_local_emulator.py index 88e0764f..ff326374 100644 --- a/pytket/extensions/qiskit/backends/ibmq_local_emulator.py +++ b/pytket/extensions/qiskit/backends/ibmq_local_emulator.py @@ -22,7 +22,7 @@ Union, ) -from qiskit.providers.aer.noise.noise_model import NoiseModel # type: ignore +from qiskit_aer.noise.noise_model import NoiseModel # type: ignore from qiskit_ibm_provider import IBMProvider # type: ignore