diff --git a/docs/changelog.rst b/docs/changelog.rst index cb6b19cc..ba1bd6ff 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,7 +5,7 @@ Unreleased ---------- * Update pytket version requirement to 1.25. -* Update qiskit version requirement to 0.46. +* Update qiskit version requirement to 1.0. * Update qiskit-ibm-provider version requirement to 0.10. * Update qiskit-ibm-runtime version requirement to 0.19. * Add ``IBMQLocalEmulatorBackend`` for running local emulation of diff --git a/docs/intro.txt b/docs/intro.txt index 5b2d1978..b2c3a4f6 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. diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index 87ccf250..3bcb57d1 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 + from qiskit_aer.backends.aerbackend import AerBackend as QiskitAerBackend # type: ignore def _default_q_index(q: Qubit) -> int: @@ -455,7 +455,7 @@ class AerBackend(_AerBaseBackend): :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 84d1da3d..e97b264c 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/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 diff --git a/pytket/extensions/qiskit/qiskit_convert.py b/pytket/extensions/qiskit/qiskit_convert.py index 7d04ba63..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,10 @@ 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 +352,14 @@ 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 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] + 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 +508,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 +558,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() 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 623d324f..3014ccca 100644 --- a/setup.py +++ b/setup.py @@ -45,10 +45,10 @@ include_package_data=True, install_requires=[ "pytket ~= 1.25", - "qiskit ~= 0.46.0", + "qiskit ~= 1.0", "qiskit-algorithms ~= 0.2.1", "qiskit-ibm-runtime ~= 0.19.0", - "qiskit-aer ~= 0.13.0", + "qiskit-aer ~= 0.13.3", "qiskit-ibm-provider ~= 0.10.0", "numpy", ], diff --git a/tests/backend_test.py b/tests/backend_test.py index 4ac610cd..61a031f8 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 @@ -1114,17 +1114,17 @@ def test_postprocess() -> None: @pytest.mark.flaky(reruns=3, reruns_delay=10) @pytest.mark.skipif(skip_remote_tests, reason=REASON) -def test_postprocess_emu(brisbane_emulator_backend: IBMQEmulatorBackend) -> None: - assert brisbane_emulator_backend.supports_contextual_optimisation +def test_postprocess_emu(ibmq_qasm_emulator_backend: IBMQEmulatorBackend) -> None: + assert ibmq_qasm_emulator_backend.supports_contextual_optimisation c = Circuit(2, 2) c.X(0).X(1).measure_all() - c = brisbane_emulator_backend.get_compiled_circuit(c) - h = brisbane_emulator_backend.process_circuit(c, n_shots=10, postprocess=True) + c = ibmq_qasm_emulator_backend.get_compiled_circuit(c) + h = ibmq_qasm_emulator_backend.process_circuit(c, n_shots=10, postprocess=True) ppcirc = Circuit.from_dict(json.loads(cast(str, h[3]))) ppcmds = ppcirc.get_commands() assert len(ppcmds) > 0 assert all(ppcmd.op.type == OpType.ClassicalTransform for ppcmd in ppcmds) - r = brisbane_emulator_backend.get_result(h) + r = ibmq_qasm_emulator_backend.get_result(h) counts = r.get_counts() assert sum(counts.values()) == 10 diff --git a/tests/qiskit_backend_test.py b/tests/qiskit_backend_test.py index 68e563f9..31b51b34 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] @@ -161,7 +161,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