diff --git a/docs/apidoc/index.rst b/docs/apidoc/index.rst index 60c30286fa8c..4960779841aa 100644 --- a/docs/apidoc/index.rst +++ b/docs/apidoc/index.rst @@ -20,8 +20,9 @@ API Reference dagcircuit extensions passmanager - providers_basicaer providers + providers_basicaer + providers_basic_provider providers_fake_provider providers_models pulse diff --git a/docs/apidoc/providers_basic_provider.rst b/docs/apidoc/providers_basic_provider.rst new file mode 100644 index 000000000000..d8647710a408 --- /dev/null +++ b/docs/apidoc/providers_basic_provider.rst @@ -0,0 +1,6 @@ +.. _qiskit-providers-basicprovider: + +.. automodule:: qiskit.providers.basic_provider + :no-members: + :no-inherited-members: + :no-special-members: diff --git a/examples/python/ghz.py b/examples/python/ghz.py index a92e913c7003..81715be33946 100644 --- a/examples/python/ghz.py +++ b/examples/python/ghz.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -14,9 +14,8 @@ GHZ state example. It also compares running on experiment and simulator. """ -from qiskit import QuantumCircuit -from qiskit import BasicAer, transpile - +from qiskit import QuantumCircuit, transpile +from qiskit.providers.basic_provider import BasicSimulator ############################################################### # Make a quantum circuit for the GHZ state. @@ -34,8 +33,8 @@ for i in range(num_qubits): qc.measure(i, i) -sim_backend = BasicAer.get_backend("qasm_simulator") +sim_backend = BasicSimulator() job = sim_backend.run(transpile(qc, sim_backend), shots=1024) result = job.result() -print("Qasm simulator : ") +print("Basic simulator : ") print(result.get_counts(qc)) diff --git a/examples/python/initialize.py b/examples/python/initialize.py index 30bb3c9c336d..3e47922d3304 100644 --- a/examples/python/initialize.py +++ b/examples/python/initialize.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -15,7 +15,8 @@ """ import math -from qiskit import QuantumCircuit, transpile, BasicAer +from qiskit import QuantumCircuit, transpile +from qiskit.providers.basic_provider import BasicSimulator ############################################################### @@ -58,7 +59,7 @@ print([format(abs(x * x), ".3f") for x in desired_vector]) # Initialize on local simulator -sim_backend = BasicAer.get_backend("qasm_simulator") +sim_backend = BasicSimulator() job = sim_backend.run(transpile(circuit, sim_backend), shots=shots) result = job.result() diff --git a/examples/python/load_qasm.py b/examples/python/load_qasm.py index c4ef7d97422d..af4878c41866 100644 --- a/examples/python/load_qasm.py +++ b/examples/python/load_qasm.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2018. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -13,14 +13,13 @@ """Example on how to load a file into a QuantumCircuit.""" from qiskit import QuantumCircuit -from qiskit import BasicAer +from qiskit.providers.basic_provider import BasicSimulator circ = QuantumCircuit.from_qasm_file("examples/qasm/entangled_registers.qasm") print(circ) # See the backend -sim_backend = BasicAer.get_backend("qasm_simulator") - +sim_backend = BasicSimulator() # Compile and run the Quantum circuit on a local simulator backend job_sim = sim_backend.run(circ) diff --git a/examples/python/qft.py b/examples/python/qft.py index 467b8042b61f..ca22d0d60538 100644 --- a/examples/python/qft.py +++ b/examples/python/qft.py @@ -16,7 +16,8 @@ import math from qiskit import QuantumCircuit -from qiskit import transpile, BasicAer +from qiskit import transpile +from qiskit.providers.basic_provider import BasicSimulator ############################################################### @@ -66,8 +67,8 @@ def qft(circ, n): print(qft4) print(qft5) -print("Qasm simulator") -sim_backend = BasicAer.get_backend("qasm_simulator") +print("Basic simulator") +sim_backend = BasicSimulator() job = sim_backend.run(transpile([qft3, qft4, qft5], sim_backend), shots=1024) result = job.result() print(result.get_counts(qft3)) diff --git a/examples/python/rippleadd.py b/examples/python/rippleadd.py index 6b02774b1c3c..6cb40f424c5b 100644 --- a/examples/python/rippleadd.py +++ b/examples/python/rippleadd.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -16,13 +16,13 @@ """ from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit -from qiskit import BasicAer from qiskit import transpile +from qiskit.providers.basic_provider import BasicSimulator ############################################################### # Set the backend name and coupling map. ############################################################### -backend = BasicAer.get_backend("qasm_simulator") +backend = BasicSimulator() coupling_map = [ [0, 1], [0, 8], diff --git a/examples/python/teleport.py b/examples/python/teleport.py index c7ca3559c4c7..73d7fd61d22c 100644 --- a/examples/python/teleport.py +++ b/examples/python/teleport.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,14 +18,14 @@ """ from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit -from qiskit import BasicAer from qiskit import transpile +from qiskit.providers.basic_provider import BasicSimulator ############################################################### # Set the backend name and coupling map. ############################################################### coupling_map = [[0, 1], [0, 2], [1, 2], [3, 2], [3, 4], [4, 2]] -backend = BasicAer.get_backend("qasm_simulator") +backend = BasicSimulator() ############################################################### # Make a quantum program for quantum teleportation. diff --git a/examples/python/using_qiskit_terra_level_0.py b/examples/python/using_qiskit_terra_level_0.py index ce46396c1d6d..575293f855b1 100644 --- a/examples/python/using_qiskit_terra_level_0.py +++ b/examples/python/using_qiskit_terra_level_0.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2018. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -11,19 +11,16 @@ # that they have been altered from the originals. """ -Example showing how to use Qiskit at level 0 (no optimization). - -This example shows the most basic way to user Terra. It builds some circuits -and runs them on both the BasicAer (local Qiskit provider) or IBM Quantum (remote IBM Quantum provider). - -To control the compile parameters we have provided a transpile function which can be used -as a level 1 user. +Example showing how to use Qiskit-Terra at level 0 (novice). +This example shows the most basic way to use Qiskit. It builds some circuits +and runs them on the BasicProvider (local Qiskit provider). """ # Import the Qiskit modules from qiskit import QuantumCircuit -from qiskit import transpile, BasicAer +from qiskit import transpile +from qiskit.providers.basic_provider import BasicSimulator # making first circuit: bell state qc1 = QuantumCircuit(2, 2) @@ -36,12 +33,8 @@ qc2.h([0, 1]) qc2.measure([0, 1], [0, 1]) -# setting up the backend -print("(BasicAER Backends)") -print(BasicAer.backends()) - # running the job -sim_backend = BasicAer.get_backend("qasm_simulator") +sim_backend = BasicSimulator() job_sim = sim_backend.run(transpile([qc1, qc2], sim_backend)) sim_result = job_sim.result() diff --git a/qiskit/__init__.py b/qiskit/__init__.py index 456205d82d89..f9526e4f2dfb 100644 --- a/qiskit/__init__.py +++ b/qiskit/__init__.py @@ -77,9 +77,6 @@ # Remove this after 0.46.0 release __path__ = pkgutil.extend_path(__path__, __name__) -# Please note these are global instances, not modules. -from qiskit.providers.basicaer import BasicAer - _config = _user_config.get_config() # Moved to after IBMQ and Aer imports due to import issues @@ -189,7 +186,6 @@ def __getattr__(self, attr): __all__ = [ "Aer", "AncillaRegister", - "BasicAer", "ClassicalRegister", "IBMQ", "MissingOptionalLibraryError", @@ -202,3 +198,26 @@ def __getattr__(self, attr): "sequence", "transpile", ] + +# lazily deprecate BasicAer import (global instance) +_DEPRECATED_NAMES = { + "BasicAer": "qiskit.providers.basicaer", +} + + +def __getattr__(name): + if name in _DEPRECATED_NAMES: + import importlib + + module_name = _DEPRECATED_NAMES[name] + warnings.warn( + f"{name} is deprecated since Qiskit 0.46 and will be removed in Qiskit 1.0. " + f"The BasicAer (qiskit.providers.basicaer) module has been superseded by " + f"qiskit.providers.basic_provider, and all its classes have been renamed " + f"to follow a new naming convention. More information and migration guidelines " + f"can be found in the 0.46 API docs for BasicAer.", + DeprecationWarning, + stacklevel=2, + ) + return getattr(importlib.import_module(module_name), name) + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") diff --git a/qiskit/circuit/__init__.py b/qiskit/circuit/__init__.py index 6699f2efbbd5..d5eb77b97050 100644 --- a/qiskit/circuit/__init__.py +++ b/qiskit/circuit/__init__.py @@ -71,8 +71,7 @@ .. plot:: :include-source: - from qiskit import BasicAer, transpile, QuantumRegister, ClassicalRegister, QuantumCircuit - + from qiskit import transpile, QuantumRegister, ClassicalRegister, QuantumCircuit qr = QuantumRegister(1) cr = ClassicalRegister(1) qc = QuantumCircuit(qr, cr) @@ -82,7 +81,8 @@ .. code-block:: - backend = BasicAer.get_backend('qasm_simulator') + from qiskit.providers.basic_provider import BasicSimulator + backend = BasicSimulator() tqc = transpile(qc, backend) counts = backend.run(tqc).result().get_counts() @@ -100,7 +100,7 @@ .. plot:: :include-source: - from qiskit import BasicAer, transpile, QuantumRegister, ClassicalRegister, QuantumCircuit + from qiskit import transpile, QuantumRegister, ClassicalRegister, QuantumCircuit qr = QuantumRegister(1) cr = ClassicalRegister(1) @@ -115,7 +115,8 @@ .. code-block:: - backend = BasicAer.get_backend('qasm_simulator') + from qiskit.providers.basic_provider import BasicSimulator + backend = BasicSimulator() tqc = transpile(qc, backend) counts = backend.run(tqc).result().get_counts() diff --git a/qiskit/opflow/expectations/expectation_factory.py b/qiskit/opflow/expectations/expectation_factory.py index 68bf55143b63..98be4806c5e6 100644 --- a/qiskit/opflow/expectations/expectation_factory.py +++ b/qiskit/opflow/expectations/expectation_factory.py @@ -15,7 +15,7 @@ import logging from typing import Optional, Union -from qiskit import BasicAer +from qiskit.providers.basicaer import BasicAer # pylint: disable=no-name-in-module from qiskit.opflow.expectations.aer_pauli_expectation import AerPauliExpectation from qiskit.opflow.expectations.expectation_base import ExpectationBase from qiskit.opflow.expectations.matrix_expectation import MatrixExpectation diff --git a/qiskit/opflow/state_fns/circuit_state_fn.py b/qiskit/opflow/state_fns/circuit_state_fn.py index 6a4aa3a2b5e3..054929d726c3 100644 --- a/qiskit/opflow/state_fns/circuit_state_fn.py +++ b/qiskit/opflow/state_fns/circuit_state_fn.py @@ -17,7 +17,13 @@ import numpy as np -from qiskit import BasicAer, ClassicalRegister, QuantumCircuit, transpile +from qiskit import ( # pylint: disable=no-name-in-module + BasicAer, + ClassicalRegister, + QuantumCircuit, + transpile, +) + from qiskit.circuit import Instruction, ParameterExpression from qiskit.circuit.exceptions import CircuitError from qiskit.circuit.library import IGate, StatePreparation diff --git a/qiskit/providers/basic_provider/__init__.py b/qiskit/providers/basic_provider/__init__.py new file mode 100644 index 000000000000..853720744bc8 --- /dev/null +++ b/qiskit/providers/basic_provider/__init__.py @@ -0,0 +1,66 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +""" +=============================================================================== +BasicProvider: Python-based Simulators (:mod:`qiskit.providers.basic_provider`) +=============================================================================== + +.. currentmodule:: qiskit.providers.basic_provider + +A module of Python-based quantum simulators. Simulators can be accessed +via the `BasicProvider` provider, e.g.: + +.. code-block:: + + from qiskit.providers.basic_provider import BasicProvider + + backend = BasicProvider().get_backend('basic_simulator') + + +Simulators +========== + +.. autosummary:: + :toctree: ../stubs/ + + BasicSimulator + +Provider +======== + +.. autosummary:: + :toctree: ../stubs/ + + BasicProvider + +Job Class +========= + +.. autosummary:: + :toctree: ../stubs/ + + BasicProviderJob + +Exceptions +========== + +.. autosummary:: + :toctree: ../stubs/ + + BasicProviderError +""" + +from .basic_provider import BasicProvider +from .basic_provider_job import BasicProviderJob +from .basic_simulator import BasicSimulator +from .exceptions import BasicProviderError diff --git a/qiskit/providers/basic_provider/basic_provider.py b/qiskit/providers/basic_provider/basic_provider.py new file mode 100644 index 000000000000..7274376bd6b3 --- /dev/null +++ b/qiskit/providers/basic_provider/basic_provider.py @@ -0,0 +1,122 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + + +"""Provider for basic simulator backends, formerly known as `BasicAer`.""" + +from __future__ import annotations + +from collections.abc import Callable +from collections import OrderedDict +from typing import Type + +import logging + +from qiskit.exceptions import QiskitError +from qiskit.providers.backend import Backend +from qiskit.providers.provider import ProviderV1 +from qiskit.providers.exceptions import QiskitBackendNotFoundError +from qiskit.providers.providerutils import resolve_backend_name, filter_backends + +from .basic_simulator import BasicSimulator + + +logger = logging.getLogger(__name__) + +SIMULATORS = [BasicSimulator] + + +class BasicProvider(ProviderV1): + """Provider for test simulators.""" + + def __init__(self) -> None: + super().__init__() + + # Populate the list of test backends (simulators) + self._backends = self._verify_backends() + + def get_backend(self, name: str | None = None, **kwargs) -> Backend: + backends = self._backends.values() + + # Special handling of the `name` parameter, to support alias resolution + # and deprecated names. + if name: + try: + resolved_name = resolve_backend_name(name, backends, {}, {}) + name = resolved_name + except LookupError as ex: + raise QiskitBackendNotFoundError( + f"The '{name}' backend is not installed in your system." + ) from ex + + return super().get_backend(name=name, **kwargs) + + def backends( + self, name: str | None = None, filters: Callable | None = None, **kwargs + ) -> list[Backend]: + backends = self._backends.values() + + # Special handling of the `name` parameter, to support alias resolution + # and deprecated names. + if name: + try: + resolved_name = resolve_backend_name(name, backends, {}, {}) + new_backends = [] + for backend in backends: + if backend.version == 1 and backend.name() == resolved_name: + new_backends.append(backend) + elif backend.version == 2 and backend.name == resolved_name: + new_backends.append(backend) + backends = new_backends + except LookupError: + return [] + + return filter_backends(backends, filters=filters, **kwargs) + + def _verify_backends(self) -> OrderedDict[str, Backend]: + """ + Return the test backends in `BACKENDS` that are + effectively available (as some of them might depend on the presence + of an optional dependency or on the existence of a binary). + + Returns: + dict[str:Backend]: a dict of test backend instances for + the backends that could be instantiated, keyed by backend name. + """ + ret = OrderedDict() + for backend_cls in SIMULATORS: + backend_instance = self._get_backend_instance(backend_cls) + backend_name = backend_instance.name + ret[backend_name] = backend_instance + return ret + + def _get_backend_instance(self, backend_cls: Type[Backend]) -> Backend: + """ + Return an instance of a backend from its class. + + Args: + backend_cls (class): backend class. + Returns: + Backend: a backend instance. + Raises: + QiskitError: if the backend could not be instantiated. + """ + # Verify that the backend can be instantiated. + try: + backend_instance = backend_cls(provider=self) + except Exception as err: + raise QiskitError(f"Backend {backend_cls} could not be instantiated: {err}") from err + + return backend_instance + + def __str__(self) -> str: + return "BasicProvider" diff --git a/qiskit/providers/basic_provider/basic_provider_job.py b/qiskit/providers/basic_provider/basic_provider_job.py new file mode 100644 index 000000000000..bc7dbf4781ee --- /dev/null +++ b/qiskit/providers/basic_provider/basic_provider_job.py @@ -0,0 +1,65 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + + +"""This module implements the job class used by Basic Aer Provider.""" + +import warnings + +from qiskit.providers import JobStatus +from qiskit.providers.job import JobV1 + + +class BasicProviderJob(JobV1): + """BasicProviderJob class.""" + + _async = False + + def __init__(self, backend, job_id, result): + super().__init__(backend, job_id) + self._result = result + + def submit(self): + """Submit the job to the backend for execution. + + Raises: + JobError: if trying to re-submit the job. + """ + return + + def result(self, timeout=None): + """Get job result . + + Returns: + qiskit.result.Result: Result object + """ + if timeout is not None: + warnings.warn( + "The timeout kwarg doesn't have any meaning with " + "BasicProvider because execution is synchronous and the " + "result already exists when run() returns.", + UserWarning, + ) + + return self._result + + def status(self): + """Gets the status of the job by querying the Python's future + + Returns: + qiskit.providers.JobStatus: The current JobStatus + """ + return JobStatus.DONE + + def backend(self): + """Return the instance of the backend used for this job.""" + return self._backend diff --git a/qiskit/providers/basic_provider/basic_provider_tools.py b/qiskit/providers/basic_provider/basic_provider_tools.py new file mode 100644 index 000000000000..030c629275ed --- /dev/null +++ b/qiskit/providers/basic_provider/basic_provider_tools.py @@ -0,0 +1,182 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Contains functions used by the basic provider simulators. + +""" +from __future__ import annotations + +from string import ascii_uppercase, ascii_lowercase + +import numpy as np + +import qiskit.circuit.library.standard_gates as gates +from qiskit.exceptions import QiskitError + +# Single qubit gates supported by ``single_gate_params``. +SINGLE_QUBIT_GATES = ("U", "u", "h", "p", "u1", "u2", "u3", "rz", "sx", "x") + + +def single_gate_matrix(gate: str, params: list[float] | None = None) -> np.ndarray: + """Get the matrix for a single qubit. + + Args: + gate: the single qubit gate name + params: the operation parameters op['params'] + Returns: + array: A numpy array representing the matrix + Raises: + QiskitError: If a gate outside the supported set is passed in for the + ``Gate`` argument. + """ + if params is None: + params = [] + + if gate == "U": + gc = gates.UGate + elif gate == "u3": + gc = gates.U3Gate + elif gate == "h": + gc = gates.HGate + elif gate == "u": + gc = gates.UGate + elif gate == "p": + gc = gates.PhaseGate + elif gate == "u2": + gc = gates.U2Gate + elif gate == "u1": + gc = gates.U1Gate + elif gate == "rz": + gc = gates.RZGate + elif gate == "id": + gc = gates.IGate + elif gate == "sx": + gc = gates.SXGate + elif gate == "x": + gc = gates.XGate + else: + raise QiskitError("Gate is not a valid basis gate for this simulator: %s" % gate) + + return gc(*params).to_matrix() + + +# Cache CX matrix as no parameters. +_CX_MATRIX = gates.CXGate().to_matrix() + + +def cx_gate_matrix() -> np.ndarray: + """Get the matrix for a controlled-NOT gate.""" + return _CX_MATRIX + + +def einsum_matmul_index(gate_indices: list[int], number_of_qubits: int) -> str: + """Return the index string for Numpy.einsum matrix-matrix multiplication. + + The returned indices are to perform a matrix multiplication A.B where + the matrix A is an M-qubit matrix, matrix B is an N-qubit matrix, and + M <= N, and identity matrices are implied on the subsystems where A has no + support on B. + + Args: + gate_indices (list[int]): the indices of the right matrix subsystems + to contract with the left matrix. + number_of_qubits (int): the total number of qubits for the right matrix. + + Returns: + str: An indices string for the Numpy.einsum function. + """ + + mat_l, mat_r, tens_lin, tens_lout = _einsum_matmul_index_helper(gate_indices, number_of_qubits) + + # Right indices for the N-qubit input and output tensor + tens_r = ascii_uppercase[:number_of_qubits] + + # Combine indices into matrix multiplication string format + # for numpy.einsum function + return f"{mat_l}{mat_r}, {tens_lin}{tens_r}->{tens_lout}{tens_r}" + + +def einsum_vecmul_index(gate_indices: list[int], number_of_qubits: int) -> str: + """Return the index string for Numpy.einsum matrix-vector multiplication. + + The returned indices are to perform a matrix multiplication A.v where + the matrix A is an M-qubit matrix, vector v is an N-qubit vector, and + M <= N, and identity matrices are implied on the subsystems where A has no + support on v. + + Args: + gate_indices (list[int]): the indices of the right matrix subsystems + to contract with the left matrix. + number_of_qubits (int): the total number of qubits for the right matrix. + + Returns: + str: An indices string for the Numpy.einsum function. + """ + + mat_l, mat_r, tens_lin, tens_lout = _einsum_matmul_index_helper(gate_indices, number_of_qubits) + + # Combine indices into matrix multiplication string format + # for numpy.einsum function + return f"{mat_l}{mat_r}, {tens_lin}->{tens_lout}" + + +def _einsum_matmul_index_helper( + gate_indices: list[int], number_of_qubits: int +) -> tuple[str, str, str, str]: + """Return the index string for Numpy.einsum matrix multiplication. + + The returned indices are to perform a matrix multiplication A.v where + the matrix A is an M-qubit matrix, matrix v is an N-qubit vector, and + M <= N, and identity matrices are implied on the subsystems where A has no + support on v. + + Args: + gate_indices (list[int]): the indices of the right matrix subsystems + to contract with the left matrix. + number_of_qubits (int): the total number of qubits for the right matrix. + + Returns: + tuple: (mat_left, mat_right, tens_in, tens_out) of index strings for + that may be combined into a Numpy.einsum function string. + + Raises: + QiskitError: if the total number of qubits plus the number of + contracted indices is greater than 26. + """ + + # Since we use ASCII alphabet for einsum index labels we are limited + # to 26 total free left (lowercase) and 26 right (uppercase) indexes. + # The rank of the contracted tensor reduces this as we need to use that + # many characters for the contracted indices + if len(gate_indices) + number_of_qubits > 26: + raise QiskitError("Total number of free indexes limited to 26") + + # Indices for N-qubit input tensor + tens_in = ascii_lowercase[:number_of_qubits] + + # Indices for the N-qubit output tensor + tens_out = list(tens_in) + + # Left and right indices for the M-qubit multiplying tensor + mat_left = "" + mat_right = "" + + # Update left indices for mat and output + for pos, idx in enumerate(reversed(gate_indices)): + mat_left += ascii_lowercase[-1 - pos] + mat_right += tens_in[-1 - idx] + tens_out[-1 - idx] = ascii_lowercase[-1 - pos] + tens_out = "".join(tens_out) + + # Combine indices into matrix multiplication string format + # for numpy.einsum function + return mat_left, mat_right, tens_in, tens_out diff --git a/qiskit/providers/basic_provider/basic_simulator.py b/qiskit/providers/basic_provider/basic_simulator.py new file mode 100644 index 000000000000..ca1cee0b7d5e --- /dev/null +++ b/qiskit/providers/basic_provider/basic_simulator.py @@ -0,0 +1,743 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Contains a (slow) Python simulator. + +It simulates a quantum circuit (an experiment) that has been compiled +to run on the simulator. It is exponential in the number of qubits. + +The simulator is run using + +.. code-block:: python + + BasicSimulator().run(run_input) + +Where the input is a :class:`.QuantumCircuit` object and the +output is a :class:`.BasicProviderJob` object, +which can later be queried for the Result object. The result will contain a 'memory' data +field, which is a result of measurements for each shot. +""" + +from __future__ import annotations + +import uuid +import time +import logging +import warnings + +from collections import Counter +import numpy as np + +from qiskit.circuit import QuantumCircuit +from qiskit.circuit.library import UnitaryGate +from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping +from qiskit.providers import Provider +from qiskit.providers.backend import BackendV2 +from qiskit.providers.models import BackendConfiguration +from qiskit.providers.options import Options +from qiskit.qobj import QasmQobj, QasmQobjConfig, QasmQobjExperiment +from qiskit.result import Result +from qiskit.transpiler import Target + +from .basic_provider_job import BasicProviderJob +from .basic_provider_tools import single_gate_matrix +from .basic_provider_tools import SINGLE_QUBIT_GATES +from .basic_provider_tools import cx_gate_matrix +from .basic_provider_tools import einsum_vecmul_index +from .exceptions import BasicProviderError + +logger = logging.getLogger(__name__) + + +class BasicSimulator(BackendV2): + """Python implementation of a basic (non-efficient) quantum simulator.""" + + # Formerly calculated as `int(log2(local_hardware_info()["memory"]*(1024**3)/16))`. + # After the removal of `local_hardware_info()`, it's hardcoded to 24 qubits, + # which matches the ~268 MB of required memory. + MAX_QUBITS_MEMORY = 24 + + def __init__( + self, + provider: Provider | None = None, + target: Target | None = None, + **fields, + ) -> None: + """ + Args: + provider: An optional backwards reference to the + :class:`~qiskit.providers.Provider` object that the backend + is from. + target: An optional target to configure the simulator. + fields: kwargs for the values to use to override the default + options. + + Raises: + AttributeError: If a field is specified that's outside the backend's + options. + """ + + super().__init__( + provider=provider, + name="basic_simulator", + description="A python simulator for quantum experiments", + backend_version="0.1", + **fields, + ) + + self._target = target + self._configuration = None + + # Internal simulator variables + self._local_random = None + self._classical_memory = 0 + self._classical_register = 0 + self._statevector = 0 + self._number_of_cmembits = 0 + self._number_of_qubits = 0 + self._shots = 0 + self._memory = False + self._initial_statevector = self.options.get("initial_statevector") + self._chop_threshold = self.options.get("chop_threashold") + self._qobj_config = None + self._sample_measure = False + + @property + def max_circuits(self) -> None: + return None + + @property + def target(self) -> Target: + if not self._target: + self._target = self._build_basic_target() + return self._target + + def _build_basic_target(self) -> Target: + """Helper method that returns a minimal target with a basis gate set but + no coupling map, instruction properties or calibrations. + + Returns: + The configured target. + """ + # Set num_qubits to None to signal the transpiler not to + # resize the circuit to fit a specific (potentially too large) + # number of qubits. The number of qubits in the circuits given to the + # `run` method will determine the size of the simulated statevector. + target = Target( + description="Basic Target", + num_qubits=None, + ) + basis_gates = [ + "h", + "u", + "p", + "u1", + "u2", + "u3", + "rz", + "sx", + "x", + "cx", + "id", + "unitary", + "measure", + "delay", + "reset", + ] + inst_mapping = get_standard_gate_name_mapping() + for name in basis_gates: + if name in inst_mapping: + instruction = inst_mapping[name] + target.add_instruction(instruction, properties=None, name=name) + elif name == "unitary": + # This is a placeholder for a UnitaryGate instance, + # to signal the transpiler not to decompose unitaries + # in the circuit. + target.add_instruction(UnitaryGate, name="unitary") + else: + raise BasicProviderError( + "Gate is not a valid basis gate for this simulator: %s" % name + ) + return target + + def configuration(self) -> BackendConfiguration: + """Return the simulator backend configuration. + + Returns: + The configuration for the backend. + """ + # Note: this is a custom attribute of the BasicSimulator class and + # not part of the BackendV2 interface. It has only been added for + # compatibility with the `assemble` function (currently used in `run`), + # which still relies on legacy BackendV1 attributes. Once the internal + # use of `assemble` is resolved, this attribute will no longer be + # necessary. + + if self._configuration: + return self._configuration + + gates = [ + { + "name": name, + "parameters": self.target.operation_from_name(name).params, + } + for name in self.target.operation_names + ] + + self._configuration = BackendConfiguration( + backend_name=self.name, + backend_version=self.backend_version, + n_qubits=self.num_qubits, + basis_gates=self.target.operation_names, + gates=gates, + local=True, + simulator=True, + conditional=True, + open_pulse=False, + memory=True, + # This max_shots is used by the assembler, setting it to 0 + # to maintain the behavior from the previous implementation. + # Not related to the actual shots set in the backend options + max_shots=0, + coupling_map=None, + description="A python simulator for quantum experiments", + ) + return self._configuration + + @classmethod + def _default_options(cls) -> Options: + return Options( + shots=1024, + memory=False, + initial_statevector=None, + chop_threshold=1e-15, + allow_sample_measuring=True, + seed_simulator=None, + parameter_binds=None, + ) + + def _add_unitary(self, gate: np.ndarray, qubits: list[int]) -> None: + """Apply an N-qubit unitary matrix. + + Args: + gate (matrix_like): an N-qubit unitary matrix + qubits (list): the list of N-qubits. + """ + # Get the number of qubits + num_qubits = len(qubits) + # Compute einsum index string for 1-qubit matrix multiplication + indexes = einsum_vecmul_index(qubits, self._number_of_qubits) + # Convert to complex rank-2N tensor + gate_tensor = np.reshape(np.array(gate, dtype=complex), num_qubits * [2, 2]) + # Apply matrix multiplication + self._statevector = np.einsum( + indexes, gate_tensor, self._statevector, dtype=complex, casting="no" + ) + + def _get_measure_outcome(self, qubit: int) -> tuple[str, int]: + """Simulate the outcome of measurement of a qubit. + + Args: + qubit: the qubit to measure + + Return: + pair (outcome, probability) where outcome is '0' or '1' and + probability is the probability of the returned outcome. + """ + # Axis for numpy.sum to compute probabilities + axis = list(range(self._number_of_qubits)) + axis.remove(self._number_of_qubits - 1 - qubit) + probabilities = np.sum(np.abs(self._statevector) ** 2, axis=tuple(axis)) + # Compute einsum index string for 1-qubit matrix multiplication + random_number = self._local_random.random() + if random_number < probabilities[0]: + return "0", probabilities[0] + # Else outcome was '1' + return "1", probabilities[1] + + def _add_sample_measure( + self, measure_params: list[list[int, int]], num_samples: int + ) -> list[hex]: + """Generate memory samples from current statevector. + + Args: + measure_params: List of (qubit, cmembit) values for + measure instructions to sample. + num_samples: The number of memory samples to generate. + + Returns: + A list of memory values in hex format. + """ + # Get unique qubits that are actually measured and sort in + # ascending order + measured_qubits = sorted({qubit for qubit, cmembit in measure_params}) + num_measured = len(measured_qubits) + # We use the axis kwarg for numpy.sum to compute probabilities + # this sums over all non-measured qubits to return a vector + # of measure probabilities for the measured qubits + axis = list(range(self._number_of_qubits)) + for qubit in reversed(measured_qubits): + # Remove from largest qubit to smallest so list position is correct + # with respect to position from end of the list + axis.remove(self._number_of_qubits - 1 - qubit) + probabilities = np.reshape( + np.sum(np.abs(self._statevector) ** 2, axis=tuple(axis)), 2**num_measured + ) + # Generate samples on measured qubits as ints with qubit + # position in the bit-string for each int given by the qubit + # position in the sorted measured_qubits list + samples = self._local_random.choice(range(2**num_measured), num_samples, p=probabilities) + # Convert the ints to bitstrings + memory = [] + for sample in samples: + classical_memory = self._classical_memory + for qubit, cmembit in measure_params: + pos = measured_qubits.index(qubit) + qubit_outcome = int((sample & (1 << pos)) >> pos) + membit = 1 << cmembit + classical_memory = (classical_memory & (~membit)) | (qubit_outcome << cmembit) + value = bin(classical_memory)[2:] + memory.append(hex(int(value, 2))) + return memory + + def _add_measure(self, qubit: int, cmembit: int, cregbit: int | None = None) -> None: + """Apply a measure instruction to a qubit. + + Args: + qubit: qubit is the qubit measured. + cmembit: is the classical memory bit to store outcome in. + cregbit: is the classical register bit to store outcome in. + """ + # get measure outcome + outcome, probability = self._get_measure_outcome(qubit) + # update classical state + membit = 1 << cmembit + self._classical_memory = (self._classical_memory & (~membit)) | (int(outcome) << cmembit) + + if cregbit is not None: + regbit = 1 << cregbit + self._classical_register = (self._classical_register & (~regbit)) | ( + int(outcome) << cregbit + ) + + # update quantum state + if outcome == "0": + update_diag = [[1 / np.sqrt(probability), 0], [0, 0]] + else: + update_diag = [[0, 0], [0, 1 / np.sqrt(probability)]] + # update classical state + self._add_unitary(update_diag, [qubit]) + + def _add_reset(self, qubit: int) -> None: + """Apply a reset instruction to a qubit. + + Args: + qubit: the qubit being rest + + This is done by doing a simulating a measurement + outcome and projecting onto the outcome state while + renormalizing. + """ + # get measure outcome + outcome, probability = self._get_measure_outcome(qubit) + # update quantum state + if outcome == "0": + update = [[1 / np.sqrt(probability), 0], [0, 0]] + self._add_unitary(update, [qubit]) + else: + update = [[0, 1 / np.sqrt(probability)], [0, 0]] + self._add_unitary(update, [qubit]) + + def _validate_initial_statevector(self) -> None: + """Validate an initial statevector""" + # If the initial statevector isn't set we don't need to validate + if self._initial_statevector is None: + return + # Check statevector is correct length for number of qubits + length = len(self._initial_statevector) + required_dim = 2**self._number_of_qubits + if length != required_dim: + raise BasicProviderError( + f"initial statevector is incorrect length: {length} != {required_dim}" + ) + + def _set_options( + self, qobj_config: QasmQobjConfig | None = None, backend_options: dict | None = None + ) -> None: + """Set the backend options for all experiments in a qobj""" + # Reset default options + self._initial_statevector = self.options.get("initial_statevector") + self._chop_threshold = self.options.get("chop_threshold") + if "backend_options" in backend_options and backend_options["backend_options"]: + backend_options = backend_options["backend_options"] + + # Check for custom initial statevector in backend_options first, + # then config second + if ( + "initial_statevector" in backend_options + and backend_options["initial_statevector"] is not None + ): + self._initial_statevector = np.array( + backend_options["initial_statevector"], dtype=complex + ) + elif hasattr(qobj_config, "initial_statevector"): + self._initial_statevector = np.array(qobj_config.initial_statevector, dtype=complex) + if self._initial_statevector is not None: + # Check the initial statevector is normalized + norm = np.linalg.norm(self._initial_statevector) + if round(norm, 12) != 1: + raise BasicProviderError(f"initial statevector is not normalized: norm {norm} != 1") + # Check for custom chop threshold + # Replace with custom options + if "chop_threshold" in backend_options: + self._chop_threshold = backend_options["chop_threshold"] + elif hasattr(qobj_config, "chop_threshold"): + self._chop_threshold = qobj_config.chop_threshold + + def _initialize_statevector(self) -> None: + """Set the initial statevector for simulation""" + if self._initial_statevector is None: + # Set to default state of all qubits in |0> + self._statevector = np.zeros(2**self._number_of_qubits, dtype=complex) + self._statevector[0] = 1 + else: + self._statevector = self._initial_statevector.copy() + # Reshape to rank-N tensor + self._statevector = np.reshape(self._statevector, self._number_of_qubits * [2]) + + def _validate_measure_sampling(self, experiment: QasmQobjExperiment) -> None: + """Determine if measure sampling is allowed for an experiment + + Args: + experiment: a qobj experiment. + """ + # If shots=1 we should disable measure sampling. + # This is also required for statevector simulator to return the + # correct final statevector without silently dropping final measurements. + if self._shots <= 1: + self._sample_measure = False + return + + # Check for config flag + if hasattr(experiment.config, "allows_measure_sampling"): + self._sample_measure = experiment.config.allows_measure_sampling + # If flag isn't found do a simple test to see if a circuit contains + # no reset instructions, and no gates instructions after + # the first measure. + else: + measure_flag = False + for instruction in experiment.instructions: + # If circuit contains reset operations we cannot sample + if instruction.name == "reset": + self._sample_measure = False + return + # If circuit contains a measure option then we can + # sample only if all following operations are measures + if measure_flag: + # If we find a non-measure instruction + # we cannot do measure sampling + if instruction.name not in ["measure", "barrier", "id", "u0"]: + self._sample_measure = False + return + elif instruction.name == "measure": + measure_flag = True + # If we made it to the end of the circuit without returning + # measure sampling is allowed + self._sample_measure = True + + def run( + self, run_input: QuantumCircuit | list[QuantumCircuit], **backend_options + ) -> BasicProviderJob: + """Run on the backend. + + Args: + run_input: payload of the experiment + backend_options: backend options + + Returns: + BasicProviderJob: derived from BaseJob + + Additional Information: + backend_options: Is a dict of options for the backend. It may contain + * "initial_statevector": vector_like + + The "initial_statevector" option specifies a custom initial + initial statevector for the simulator to be used instead of the all + zero state. This size of this vector must be correct for the number + of qubits in ``run_input`` parameter. + + Example:: + + backend_options = { + "initial_statevector": np.array([1, 0, 0, 1j]) / np.sqrt(2), + } + """ + # TODO: replace assemble with new run flow + from qiskit.compiler import assemble + + out_options = {} + for key in backend_options: + if not hasattr(self.options, key): + warnings.warn( + "Option %s is not used by this backend" % key, UserWarning, stacklevel=2 + ) + else: + out_options[key] = backend_options[key] + qobj = assemble(run_input, self, **out_options) + qobj_options = qobj.config + self._set_options(qobj_config=qobj_options, backend_options=backend_options) + job_id = str(uuid.uuid4()) + job = BasicProviderJob(self, job_id, self._run_job(job_id, qobj)) + return job + + def _run_job(self, job_id: str, qobj: QasmQobj) -> Result: + """Run experiments in qobj + + Args: + job_id: unique id for the job. + qobj: job description + + Returns: + Result object + """ + self._validate(qobj) + result_list = [] + self._shots = qobj.config.shots + self._memory = getattr(qobj.config, "memory", False) + self._qobj_config = qobj.config + start = time.time() + for experiment in qobj.experiments: + result_list.append(self.run_experiment(experiment)) + end = time.time() + result = { + "backend_name": self.name, + "backend_version": self.backend_version, + "qobj_id": qobj.qobj_id, + "job_id": job_id, + "results": result_list, + "status": "COMPLETED", + "success": True, + "time_taken": (end - start), + "header": qobj.header.to_dict(), + } + + return Result.from_dict(result) + + def run_experiment(self, experiment: QasmQobjExperiment) -> dict[str, ...]: + """Run an experiment (circuit) and return a single experiment result. + + Args: + experiment: experiment from qobj experiments list + + Returns: + A result dictionary which looks something like:: + + { + "name": name of this experiment (obtained from qobj.experiment header) + "seed": random seed used for simulation + "shots": number of shots used in the simulation + "data": + { + "counts": {'0x9: 5, ...}, + "memory": ['0x9', '0xF', '0x1D', ..., '0x9'] + }, + "status": status string for the simulation + "success": boolean + "time_taken": simulation time of this single experiment + } + Raises: + BasicProviderError: if an error occurred. + """ + start = time.time() + self._number_of_qubits = experiment.config.n_qubits + self._number_of_cmembits = experiment.config.memory_slots + self._statevector = 0 + self._classical_memory = 0 + self._classical_register = 0 + self._sample_measure = False + global_phase = experiment.header.global_phase + + # Validate the dimension of initial statevector if set + self._validate_initial_statevector() + + # Get the seed looking in circuit, qobj, and then random. + if hasattr(experiment.config, "seed_simulator"): + seed_simulator = experiment.config.seed_simulator + elif hasattr(self._qobj_config, "seed_simulator"): + seed_simulator = self._qobj_config.seed_simulator + else: + # For compatibility on Windows force dyte to be int32 + # and set the maximum value to be (2 ** 31) - 1 + seed_simulator = np.random.randint(2147483647, dtype="int32") + + self._local_random = np.random.default_rng(seed=seed_simulator) + # Check if measure sampling is supported for current circuit + self._validate_measure_sampling(experiment) + + # List of final counts for all shots + memory = [] + # Check if we can sample measurements, if so we only perform 1 shot + # and sample all outcomes from the final state vector + if self._sample_measure: + shots = 1 + # Store (qubit, cmembit) pairs for all measure ops in circuit to + # be sampled + measure_sample_ops = [] + else: + shots = self._shots + for _ in range(shots): + self._initialize_statevector() + # apply global_phase + self._statevector *= np.exp(1j * global_phase) + # Initialize classical memory to all 0 + self._classical_memory = 0 + self._classical_register = 0 + for operation in experiment.instructions: + conditional = getattr(operation, "conditional", None) + if isinstance(conditional, int): + conditional_bit_set = (self._classical_register >> conditional) & 1 + if not conditional_bit_set: + continue + elif conditional is not None: + mask = int(operation.conditional.mask, 16) + if mask > 0: + value = self._classical_memory & mask + while (mask & 0x1) == 0: + mask >>= 1 + value >>= 1 + if value != int(operation.conditional.val, 16): + continue + # Check if single gate + if operation.name == "unitary": + qubits = operation.qubits + gate = operation.params[0] + self._add_unitary(gate, qubits) + elif operation.name in SINGLE_QUBIT_GATES: + params = getattr(operation, "params", None) + qubit = operation.qubits[0] + gate = single_gate_matrix(operation.name, params) + self._add_unitary(gate, [qubit]) + # Check if CX gate + elif operation.name in ("id", "u0"): + pass + elif operation.name in ("CX", "cx"): + qubit0 = operation.qubits[0] + qubit1 = operation.qubits[1] + gate = cx_gate_matrix() + self._add_unitary(gate, [qubit0, qubit1]) + # Check if reset + elif operation.name == "reset": + qubit = operation.qubits[0] + self._add_reset(qubit) + # Check if barrier + elif operation.name == "barrier": + pass + # Check if measure + elif operation.name == "measure": + qubit = operation.qubits[0] + cmembit = operation.memory[0] + cregbit = operation.register[0] if hasattr(operation, "register") else None + + if self._sample_measure: + # If sampling measurements record the qubit and cmembit + # for this measurement for later sampling + measure_sample_ops.append((qubit, cmembit)) + else: + # If not sampling perform measurement as normal + self._add_measure(qubit, cmembit, cregbit) + elif operation.name == "bfunc": + mask = int(operation.mask, 16) + relation = operation.relation + val = int(operation.val, 16) + + cregbit = operation.register + cmembit = operation.memory if hasattr(operation, "memory") else None + + compared = (self._classical_register & mask) - val + + if relation == "==": + outcome = compared == 0 + elif relation == "!=": + outcome = compared != 0 + elif relation == "<": + outcome = compared < 0 + elif relation == "<=": + outcome = compared <= 0 + elif relation == ">": + outcome = compared > 0 + elif relation == ">=": + outcome = compared >= 0 + else: + raise BasicProviderError("Invalid boolean function relation.") + + # Store outcome in register and optionally memory slot + regbit = 1 << cregbit + self._classical_register = (self._classical_register & (~regbit)) | ( + int(outcome) << cregbit + ) + if cmembit is not None: + membit = 1 << cmembit + self._classical_memory = (self._classical_memory & (~membit)) | ( + int(outcome) << cmembit + ) + else: + backend = self.name + err_msg = '{0} encountered unrecognized operation "{1}"' + raise BasicProviderError(err_msg.format(backend, operation.name)) + + # Add final creg data to memory list + if self._number_of_cmembits > 0: + if self._sample_measure: + # If sampling we generate all shot samples from the final statevector + memory = self._add_sample_measure(measure_sample_ops, self._shots) + else: + # Turn classical_memory (int) into bit string and pad zero for unused cmembits + outcome = bin(self._classical_memory)[2:] + memory.append(hex(int(outcome, 2))) + + # Add data + data = {"counts": dict(Counter(memory))} + # Optionally add memory list + if self._memory: + data["memory"] = memory + end = time.time() + return { + "name": experiment.header.name, + "seed_simulator": seed_simulator, + "shots": self._shots, + "data": data, + "status": "DONE", + "success": True, + "time_taken": (end - start), + "header": experiment.header.to_dict(), + } + + def _validate(self, qobj: QasmQobj) -> None: + """Semantic validations of the qobj which cannot be done via schemas.""" + n_qubits = qobj.config.n_qubits + max_qubits = self.MAX_QUBITS_MEMORY + if n_qubits > max_qubits: + raise BasicProviderError( + f"Number of qubits {n_qubits} is greater than maximum ({max_qubits}) " + f'for "{self.name}".' + ) + for experiment in qobj.experiments: + name = experiment.header.name + if experiment.config.memory_slots == 0: + logger.warning( + 'No classical registers in circuit "%s", counts will be empty.', name + ) + elif "measure" not in [op.name for op in experiment.instructions]: + logger.warning( + 'No measurements in circuit "%s", classical register will remain all zeros.', + name, + ) diff --git a/qiskit/providers/basic_provider/exceptions.py b/qiskit/providers/basic_provider/exceptions.py new file mode 100644 index 000000000000..dc5923e77c54 --- /dev/null +++ b/qiskit/providers/basic_provider/exceptions.py @@ -0,0 +1,30 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +""" +Exception for errors raised by the Basic Provider. +""" + +from qiskit.exceptions import QiskitError + + +class BasicProviderError(QiskitError): + """Base class for errors raised by the Basic Provider.""" + + def __init__(self, *message): + """Set the error message.""" + super().__init__(*message) + self.message = " ".join(message) + + def __str__(self): + """Return the message.""" + return repr(self.message) diff --git a/qiskit/providers/basicaer/__init__.py b/qiskit/providers/basicaer/__init__.py index d2ae5638e19f..a4bca9ed3096 100644 --- a/qiskit/providers/basicaer/__init__.py +++ b/qiskit/providers/basicaer/__init__.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2018. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -17,6 +17,97 @@ .. currentmodule:: qiskit.providers.basicaer +.. deprecated:: 0.46.0 + + The :mod:`qiskit.providers.basicaer` module is deprecated as of Qiskit 0.46 and will + be removed in Qiskit 1.0. Its functionality has been replaced by the new + :mod:`qiskit.providers.basic_provider` module and the :mod:`qiskit.quantum_info` + module. + + The migration from using :mod:`qiskit.providers.basicaer` to + :mod:`qiskit.providers.basic_provider` can be performed as follows:: + + Migrate from | Replace with + ------------------------------------------------------------------------------ + :mod:`.basicaer` | :mod:`.basic_provider` + :class:`.BasicAerProvider` | :class:`.BasicProvider` + :class:`.BasicAerJob` | :class:`.BasicProviderJob` + :class:`.QasmSimulatorPy` | :class:`.BasicSimulator` + :class:`.UnitarySimulatorPy` | use :class:`~.quantum_info.Operator` + :class:`.StatevectorSimulatorPy` | use :class:`~.quantum_info.Statevector` + + A notable difference is that the new provider is no longer exposed through a global instance + (like ``BasicAer``), so it will not be valid to do ``from qiskit import BasicProvider``. + Instead, the provider class must be imported from its submodule and instantiated:: + + from qiskit.providers.basic_provider import BasicProvider + provider = BasicProvider() + backend = provider.get_backend("sim_name") + + The following examples show the migration paths of the three simulators in :mod:`.basicaer`. + + 1. Statevector simulator:: + + from qiskit import QuantumCircuit + qc = QuantumCircuit(3) + qc.h(0) + qc.h(1) + qc.cx(1,2) + qc.measure_all() + + # Former path + from qiskit import BasicAer + backend = BasicAer.get_backend("statevector_simulator") + statevector = backend.run(qc).result().get_statevector() + + # New path + qc.remove_final_measurements() # no measurements allowed + from qiskit.quantum_info import Statevector + statevector = Statevector(qc) + + 2. Unitary simulator:: + + from qiskit import QuantumCircuit + qc = QuantumCircuit(3) + qc.h(0) + qc.h(1) + qc.cx(1,2) + qc.measure_all() + + # Former path + from qiskit import BasicAer + backend = BasicAer.get_backend("unitary_simulator") + result = backend.run(qc).result() + + # New path + qc.remove_final_measurements() # no measurements allowed + from qiskit.quantum_info import Operator + result = Operator(qc).data + + 3. Qasm simulator:: + + from qiskit import QuantumCircuit + qc = QuantumCircuit(3) + qc.h(0) + qc.h(1) + qc.cx(1,2) + qc.measure_all() + + # Former path + from qiskit import BasicAer + backend = BasicAer.get_backend("qasm_simulator") + result = backend.run(qc).result() + + # New path + from qiskit.providers.basic_provider import BasicProvider + backend = BasicProvider().get_backend("basic_simulator") + result = backend.run(qc).result() + # or, directly + from qiskit.providers.basic_provider import BasicSimulator + backend = BasicSimulator() + result = backend.run(qc).result() + + A module of Python-based quantum simulators. Simulators are accessed via the `BasicAer` provider, e.g.: diff --git a/qiskit/providers/basicaer/basicaerjob.py b/qiskit/providers/basicaer/basicaerjob.py index 99c2f45bf86d..4e661f6d2f00 100644 --- a/qiskit/providers/basicaer/basicaerjob.py +++ b/qiskit/providers/basicaer/basicaerjob.py @@ -17,6 +17,7 @@ from qiskit.providers import JobStatus from qiskit.providers.job import JobV1 +from qiskit.utils.deprecation import deprecate_func class BasicAerJob(JobV1): @@ -24,6 +25,14 @@ class BasicAerJob(JobV1): _async = False + @deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider, and all its classes have been renamed " + "to follow a new naming convention. " + "Use the new qiskit.providers.basic_provider.BasicProviderJob class instead.", + ) def __init__(self, backend, job_id, result): super().__init__(backend, job_id) self._result = result diff --git a/qiskit/providers/basicaer/basicaerprovider.py b/qiskit/providers/basicaer/basicaerprovider.py index b46a83826a18..9e579809c2f8 100644 --- a/qiskit/providers/basicaer/basicaerprovider.py +++ b/qiskit/providers/basicaer/basicaerprovider.py @@ -20,6 +20,7 @@ from qiskit.providers.provider import ProviderV1 from qiskit.providers.exceptions import QiskitBackendNotFoundError from qiskit.providers.providerutils import resolve_backend_name, filter_backends +from qiskit.utils.deprecation import deprecate_func from .qasm_simulator import QasmSimulatorPy from .statevector_simulator import StatevectorSimulatorPy @@ -34,13 +35,21 @@ class BasicAerProvider(ProviderV1): """Provider for Basic Aer backends.""" + @deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider, and all its classes have been renamed " + "to follow a new naming convention. " + "Use the new qiskit.providers.basic_provider.BasicProvider class instead.", + ) def __init__(self): super().__init__() - # Populate the list of Basic Aer backends. self._backends = self._verify_backends() def get_backend(self, name=None, **kwargs): + backends = self._backends.values() # Special handling of the `name` parameter, to support alias resolution diff --git a/qiskit/providers/basicaer/basicaertools.py b/qiskit/providers/basicaer/basicaertools.py index 768febaecc75..1d21cbce3187 100644 --- a/qiskit/providers/basicaer/basicaertools.py +++ b/qiskit/providers/basicaer/basicaertools.py @@ -21,11 +21,20 @@ import qiskit.circuit.library.standard_gates as gates from qiskit.exceptions import QiskitError +from qiskit.utils.deprecation import deprecate_func # Single qubit gates supported by ``single_gate_params``. SINGLE_QUBIT_GATES = ("U", "u", "h", "p", "u1", "u2", "u3", "rz", "sx", "x") +@deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider, and all its classes have been renamed " + "to follow a new naming convention. " + "Use the function in qiskit.providers.basic_provider.basic_provider_tools instead.", +) def single_gate_matrix(gate: str, params: Optional[List[float]] = None): """Get the matrix for a single qubit. @@ -38,6 +47,7 @@ def single_gate_matrix(gate: str, params: Optional[List[float]] = None): QiskitError: If a gate outside the supported set is passed in for the ``Gate`` argument. """ + if params is None: params = [] @@ -73,11 +83,28 @@ def single_gate_matrix(gate: str, params: Optional[List[float]] = None): _CX_MATRIX = gates.CXGate().to_matrix() +@deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider, and all its classes have been renamed " + "to follow a new naming convention. " + "Use the function in qiskit.providers.basic_provider.basic_provider_tools instead.", +) def cx_gate_matrix(): """Get the matrix for a controlled-NOT gate.""" + return np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]], dtype=complex) +@deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider, and all its classes have been renamed " + "to follow a new naming convention. " + "Use the function in qiskit.providers.basic_provider.basic_provider_tools instead.", +) def einsum_matmul_index(gate_indices, number_of_qubits): """Return the index string for Numpy.einsum matrix-matrix multiplication. @@ -109,6 +136,14 @@ def einsum_matmul_index(gate_indices, number_of_qubits): ) +@deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider, and all its classes have been renamed " + "to follow a new naming convention. " + "Use the function in qiskit.providers.basic_provider.basic_provider_tools instead.", +) def einsum_vecmul_index(gate_indices, number_of_qubits): """Return the index string for Numpy.einsum matrix-vector multiplication. diff --git a/qiskit/providers/basicaer/exceptions.py b/qiskit/providers/basicaer/exceptions.py index a973e4f73fe0..ca15ec227636 100644 --- a/qiskit/providers/basicaer/exceptions.py +++ b/qiskit/providers/basicaer/exceptions.py @@ -15,11 +15,19 @@ """ from qiskit.exceptions import QiskitError +from qiskit.utils.deprecation import deprecate_func class BasicAerError(QiskitError): """Base class for errors raised by Basic Aer.""" + @deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider. " + "Use the new qiskit.providers.basic_provider.BasicProviderError class instead.", + ) def __init__(self, *message): """Set the error message.""" super().__init__(*message) diff --git a/qiskit/providers/basicaer/qasm_simulator.py b/qiskit/providers/basicaer/qasm_simulator.py index 97b3d3eb8f3d..25ed12b04410 100644 --- a/qiskit/providers/basicaer/qasm_simulator.py +++ b/qiskit/providers/basicaer/qasm_simulator.py @@ -41,6 +41,7 @@ from qiskit.providers.backend import BackendV1 from qiskit.providers.options import Options from qiskit.providers.basicaer.basicaerjob import BasicAerJob +from qiskit.utils.deprecation import deprecate_func from .exceptions import BasicAerError from .basicaertools import single_gate_matrix from .basicaertools import SINGLE_QUBIT_GATES @@ -119,6 +120,13 @@ class QasmSimulatorPy(BackendV1): # This should be set to True for the statevector simulator SHOW_FINAL_STATE = False + @deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider. " + "Use the new qiskit.providers.basic_provider.BasicSimulator class instead.", + ) def __init__(self, configuration=None, provider=None, **fields): super().__init__( configuration=( diff --git a/qiskit/providers/basicaer/statevector_simulator.py b/qiskit/providers/basicaer/statevector_simulator.py index 355c5ce99589..f72a62349767 100644 --- a/qiskit/providers/basicaer/statevector_simulator.py +++ b/qiskit/providers/basicaer/statevector_simulator.py @@ -28,6 +28,7 @@ from qiskit.utils.multiprocessing import local_hardware_info from qiskit.providers.basicaer.exceptions import BasicAerError from qiskit.providers.models import QasmBackendConfiguration +from qiskit.utils.deprecation import deprecate_func from .qasm_simulator import QasmSimulatorPy logger = logging.getLogger(__name__) @@ -84,6 +85,14 @@ class StatevectorSimulatorPy(QasmSimulatorPy): # Override base class value to return the final state vector SHOW_FINAL_STATE = True + @deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider. " + "The new module has no replacement for this class. " + "Use the qiskit.quantum_info.Statevector class instead.", + ) def __init__(self, configuration=None, provider=None, **fields): super().__init__( configuration=( diff --git a/qiskit/providers/basicaer/unitary_simulator.py b/qiskit/providers/basicaer/unitary_simulator.py index 53f15465fd56..474e7376dd86 100644 --- a/qiskit/providers/basicaer/unitary_simulator.py +++ b/qiskit/providers/basicaer/unitary_simulator.py @@ -19,8 +19,8 @@ UnitarySimulator().run(run_input) -Where the input is a either Qobj object (deprecated) or QuantumCircuit or a list of circuits and -the output is a BasicAerJob object, which can later be queried for the Result object. The result +Where the input is a either Qobj object (deprecated) or QuantumCircuit or a list of circuits and +the output is a BasicAerJob object, which can later be queried for the Result object. The result will contain a 'unitary' data field, which is a 2**n x 2**n complex numpy array representing the circuit's unitary matrix. """ @@ -39,7 +39,7 @@ from qiskit.providers.options import Options from qiskit.providers.basicaer.basicaerjob import BasicAerJob from qiskit.result import Result -from qiskit.utils.deprecation import deprecate_arg +from qiskit.utils.deprecation import deprecate_arg, deprecate_func from .exceptions import BasicAerError from .basicaertools import single_gate_matrix from .basicaertools import SINGLE_QUBIT_GATES @@ -103,6 +103,14 @@ class UnitarySimulatorPy(BackendV1): DEFAULT_OPTIONS = {"initial_unitary": None, "chop_threshold": 1e-15} + @deprecate_func( + since="0.46.0", + removal_timeline="in Qiskit 1.0.0", + additional_msg="The qiskit.providers.basicaer module has been superseded " + "by qiskit.providers.basic_provider. " + "The new module has no replacement for this class. " + "Use the qiskit.quantum_info.Operator class instead.", + ) def __init__(self, configuration=None, provider=None, **fields): super().__init__( configuration=( diff --git a/qiskit/providers/fake_provider/fake_backend.py b/qiskit/providers/fake_provider/fake_backend.py index 2963639a86a1..1b092d16a5e9 100644 --- a/qiskit/providers/fake_provider/fake_backend.py +++ b/qiskit/providers/fake_provider/fake_backend.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -30,7 +30,7 @@ from qiskit import pulse from qiskit.exceptions import QiskitError from qiskit.utils import optionals as _optionals -from qiskit.providers import basicaer +from qiskit.providers import basic_provider from qiskit.transpiler import Target from qiskit.providers.backend_compat import convert_to_target @@ -129,7 +129,7 @@ def _setup_sim(self): self.set_options(noise_model=noise_model) else: - self.sim = basicaer.QasmSimulatorPy() + self.sim = basic_provider.BasicSimulator() def _get_conf_dict_from_json(self): if not self.conf_filename: @@ -204,7 +204,7 @@ def _default_options(cls): return qiskit_aer.AerSimulator._default_options() else: - return basicaer.QasmSimulatorPy._default_options() + return basic_provider.BasicSimulator._default_options() @property def dtm(self) -> float: @@ -303,12 +303,12 @@ def run(self, run_input, **options): This method runs circuit jobs (an individual or a list of QuantumCircuit ) and pulse jobs (an individual or a list of Schedule or ScheduleBlock) - using BasicAer or Aer simulator and returns a + using a :class:`.BasicSimulator` or Aer simulator and returns a :class:`~qiskit.providers.Job` object. If qiskit-aer is installed, jobs will be run using AerSimulator with noise model of the fake backend. Otherwise, jobs will be run using - BasicAer simulator without noise. + :class:`.BasicSimulator` without noise. Currently noisy simulation of a pulse job is not supported yet in FakeBackendV2. @@ -352,7 +352,7 @@ def run(self, run_input, **options): raise QiskitError("Pulse simulation is currently not supported for V2 fake backends.") # circuit job if not _optionals.HAS_AER: - warnings.warn("Aer not found using BasicAer and no noise", RuntimeWarning) + warnings.warn("Aer not found using BasicProvider and no noise", RuntimeWarning) if self.sim is None: self._setup_sim() self.sim._options = self._options @@ -470,7 +470,7 @@ def _setup_sim(self): # it when run() is called self.set_options(noise_model=noise_model) else: - self.sim = basicaer.QasmSimulatorPy() + self.sim = basic_provider.BasicSimulator() def properties(self): """Return backend properties""" @@ -531,7 +531,7 @@ def _default_options(cls): return QasmSimulator._default_options() else: - return basicaer.QasmSimulatorPy._default_options() + return basic_provider.BasicSimulator._default_options() def run(self, run_input, **kwargs): """Main job in simulator""" @@ -574,7 +574,7 @@ def run(self, run_input, **kwargs): if self.sim is None: self._setup_sim() if not _optionals.HAS_AER: - warnings.warn("Aer not found using BasicAer and no noise", RuntimeWarning) + warnings.warn("Aer not found using BasicSimulator and no noise", RuntimeWarning) self.sim._options = self._options job = self.sim.run(circuits, **kwargs) return job diff --git a/qiskit/providers/fake_provider/fake_backend_v2.py b/qiskit/providers/fake_provider/fake_backend_v2.py index 96cd6dff9d37..b14b87bc35a8 100644 --- a/qiskit/providers/fake_provider/fake_backend_v2.py +++ b/qiskit/providers/fake_provider/fake_backend_v2.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2021. +# (C) Copyright IBM 2021, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -31,7 +31,7 @@ from qiskit.providers.backend import BackendV2, QubitProperties from qiskit.providers.options import Options from qiskit.transpiler import Target, InstructionProperties -from qiskit.providers.basicaer.qasm_simulator import QasmSimulatorPy +from qiskit.providers.basic_provider.basic_simulator import BasicSimulator class FakeBackendV2(BackendV2): @@ -181,7 +181,7 @@ def run(self, run_input, **options): class FakeBackendSimple(BackendV2): - """A fake simple backend that wraps BasicAer to implement run().""" + """A fake simple backend that wraps BasicSimulator to implement run().""" def __init__(self): super().__init__( @@ -198,7 +198,7 @@ def __init__(self): self._target.add_instruction(RZGate(self._lam)) self._target.add_instruction(CXGate()) self._target.add_instruction(Measure()) - self._runner = QasmSimulatorPy() + self._runner = BasicSimulator() @property def target(self): @@ -210,7 +210,7 @@ def max_circuits(self): @classmethod def _default_options(cls): - return QasmSimulatorPy._default_options() + return BasicSimulator._default_options() def run(self, run_input, **options): self._runner._options = self._options diff --git a/qiskit/providers/providerutils.py b/qiskit/providers/providerutils.py index edd83c6dbe24..7c914e9fdd28 100644 --- a/qiskit/providers/providerutils.py +++ b/qiskit/providers/providerutils.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2018. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -84,7 +84,10 @@ def resolve_backend_name(name, backends, deprecated, aliased): LookupError: if name cannot be resolved through regular available names, nor deprecated, nor alias names. """ - available = [backend.name() for backend in backends] + # account for BackendV2 + available = [] + for backend in backends: + available.append(backend.name() if backend.version == 1 else backend.name) resolved_name = deprecated.get(name, aliased.get(name, name)) if isinstance(resolved_name, list): diff --git a/qiskit/quantum_info/analysis/distance.py b/qiskit/quantum_info/analysis/distance.py index d24bb1f580df..065b23011845 100644 --- a/qiskit/quantum_info/analysis/distance.py +++ b/qiskit/quantum_info/analysis/distance.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2019. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -76,8 +76,9 @@ def hellinger_fidelity(dist_p: dict, dist_q: dict) -> float: .. code-block:: - from qiskit import QuantumCircuit, BasicAer + from qiskit import QuantumCircuit from qiskit.quantum_info.analysis import hellinger_fidelity + from qiskit.providers.basic_provider import BasicSimulator qc = QuantumCircuit(5, 5) qc.h(2) @@ -87,7 +88,7 @@ def hellinger_fidelity(dist_p: dict, dist_q: dict) -> float: qc.cx(1, 0) qc.measure(range(5), range(5)) - sim = BasicAer.get_backend('qasm_simulator') + sim = BasicSimulator() res1 = sim.run(qc).result() res2 = sim.run(qc).result() diff --git a/qiskit/test/base.py b/qiskit/test/base.py index 65ef6c3cce20..353921f8888b 100644 --- a/qiskit/test/base.py +++ b/qiskit/test/base.py @@ -185,9 +185,15 @@ def tearDown(self): super().tearDown() # Reset the default providers, as in practice they acts as a singleton # due to importing the instances from the top-level qiskit namespace. + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") from qiskit.providers.basicaer import BasicAer BasicAer._backends = BasicAer._verify_backends() + warnings.filterwarnings("error", category=DeprecationWarning, message=r".*basicaer.*") + + from qiskit.providers.basic_provider import BasicProvider + + BasicProvider()._backends = BasicProvider()._verify_backends() @classmethod def setUpClass(cls): diff --git a/qiskit/test/providers/backend.py b/qiskit/test/providers/backend.py index 6587c9ab167a..b836339a6013 100644 --- a/qiskit/test/providers/backend.py +++ b/qiskit/test/providers/backend.py @@ -12,6 +12,7 @@ """Base TestCase for testing backends.""" +import warnings from unittest import SkipTest from qiskit import transpile @@ -38,7 +39,9 @@ class BackendTestCase(QiskitTestCase): def setUp(self): super().setUp() - self.backend = self._get_backend() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + self.backend = self._get_backend() @classmethod def setUpClass(cls): @@ -69,7 +72,9 @@ def test_status(self): def test_run_circuit(self): """Test running a single circuit.""" - job = self.backend.run(transpile(self.circuit, self.backend)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run(transpile(self.circuit, self.backend)) result = job.result() self.assertEqual(result.success, True) return result diff --git a/qiskit/test/providers/provider.py b/qiskit/test/providers/provider.py index 8170ae35859b..1f1cb0ed417c 100644 --- a/qiskit/test/providers/provider.py +++ b/qiskit/test/providers/provider.py @@ -11,7 +11,7 @@ # that they have been altered from the originals. """Base TestCase for testing Providers.""" - +import warnings from unittest import SkipTest from ..base import QiskitTestCase @@ -36,7 +36,9 @@ class ProviderTestCase(QiskitTestCase): def setUp(self): super().setUp() - self.provider = self._get_provider() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*BasicAer.*") + self.provider = self._get_provider() @classmethod def setUpClass(cls): diff --git a/qiskit/transpiler/passes/layout/full_ancilla_allocation.py b/qiskit/transpiler/passes/layout/full_ancilla_allocation.py index 72d2c6f2c4d0..bdfced0d084b 100644 --- a/qiskit/transpiler/passes/layout/full_ancilla_allocation.py +++ b/qiskit/transpiler/passes/layout/full_ancilla_allocation.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2019. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -81,7 +81,7 @@ def run(self, dag): idle_physical_qubits = [q for q in layout_physical_qubits if q not in physical_bits] - if self.target: + if self.target is not None and self.target.num_qubits is not None: idle_physical_qubits = [ q for q in range(self.target.num_qubits) if q not in physical_bits ] diff --git a/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py b/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py index cafc0a5a7382..045033cd90e5 100644 --- a/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +++ b/qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2018. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -94,7 +94,8 @@ def __init__(self, basis=None, target=None): self.error_map = self._build_error_map() def _build_error_map(self): - if self._target is not None: + # include path for when target exists but target.num_qubits is None (BasicSimulator) + if self._target is not None and self._target.num_qubits is not None: error_map = euler_one_qubit_decomposer.OneQubitGateErrorMap(self._target.num_qubits) for qubit in range(self._target.num_qubits): gate_error = {} @@ -118,7 +119,8 @@ def _resynthesize_run(self, matrix, qubit=None): When multiple synthesis options are available, it prefers the one with the lowest error when the circuit is applied to `qubit`. """ - if self._target: + # include path for when target exists but target.num_qubits is None (BasicSimulator) + if self._target is not None and self._target.num_qubits is not None: if qubit is not None: qubits_tuple = (qubit,) else: diff --git a/qiskit/transpiler/passes/synthesis/high_level_synthesis.py b/qiskit/transpiler/passes/synthesis/high_level_synthesis.py index 22bcf5abb127..c9bc9970b6ae 100644 --- a/qiskit/transpiler/passes/synthesis/high_level_synthesis.py +++ b/qiskit/transpiler/passes/synthesis/high_level_synthesis.py @@ -207,7 +207,8 @@ def __init__( self._top_level_only = self._basis_gates is None and self._target is None - if not self._top_level_only and self._target is None: + # include path for when target exists but target.num_qubits is None (BasicSimulator) + if not self._top_level_only and (self._target is None or self._target.num_qubits is None): basic_insts = {"measure", "reset", "barrier", "snapshot", "delay"} self._device_insts = basic_insts | set(self._basis_gates) @@ -305,12 +306,13 @@ def _recursively_handle_op( controlled_gate_open_ctrl = isinstance(op, ControlledGate) and op._open_ctrl if not controlled_gate_open_ctrl: qargs = tuple(qubits) if qubits is not None else None + # include path for when target exists but target.num_qubits is None (BasicSimulator) inst_supported = ( self._target.instruction_supported( operation_name=op.name, qargs=qargs, ) - if self._target is not None + if self._target is not None and self._target.num_qubits is not None else op.name in self._device_insts ) if inst_supported or (self._equiv_lib is not None and self._equiv_lib.has_entry(op)): diff --git a/qiskit/transpiler/target.py b/qiskit/transpiler/target.py index bc42a9c11e99..ede94542aadf 100644 --- a/qiskit/transpiler/target.py +++ b/qiskit/transpiler/target.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2021 +# (C) Copyright IBM 2021, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -702,6 +702,9 @@ def operation_names_for_qargs(self, qargs): Raises: KeyError: If ``qargs`` is not in target """ + # if num_qubits == 0, we will return globally defined operations + if self.num_qubits == 0 or self.num_qubits is None: + qargs = None if qargs is not None and any(x not in range(0, self.num_qubits) for x in qargs): raise KeyError(f"{qargs} not in target.") res = self._qarg_gate_map.get(qargs, set()) @@ -784,6 +787,9 @@ def check_obj_params(parameters, obj): return False return True + # Handle case where num_qubits is None by always checking globally supported operations + if self.num_qubits is None: + qargs = None # Case a list if passed in by mistake if qargs is not None: qargs = tuple(qargs) @@ -1502,7 +1508,9 @@ def target_to_backend_properties(target: Target): } ) else: - qubit_props: dict[int, Any] = {x: None for x in range(target.num_qubits)} + qubit_props: dict[int, Any] = {} + if target.num_qubits is not None: + qubit_props = {x: None for x in range(target.num_qubits)} for qargs, props in qargs_list.items(): if qargs is None: continue diff --git a/releasenotes/notes/deprecate-basicaer-for-basicprovider-38ed13c282faac9f.yaml b/releasenotes/notes/deprecate-basicaer-for-basicprovider-38ed13c282faac9f.yaml new file mode 100644 index 000000000000..b2f600114f66 --- /dev/null +++ b/releasenotes/notes/deprecate-basicaer-for-basicprovider-38ed13c282faac9f.yaml @@ -0,0 +1,112 @@ +--- +features: + - | + A new :mod:`qiskit.providers.basic_provider` module has been introduced + to replace ``qiskit.providers.basicaer``. This module contains provider + tools that mirror those of the ``BasicAer`` provider and offers a single, + non-efficient, statevector based simulator: :class:`.BasicSimulator`. + This simulator based on the :class:`.BackendV2` interface and is + exclusively intended for testing and simple prototyping, for more + advanced simulation capabilities, please refer to the ``qiskit-aer`` + package. + + - | + The :class:`.Target` interface and transpiler pipeline now support + target definitions with ``num_qubits=None``. This is to support the + creation of :class:`.Target`-based simulators with a flexible number of qubits. + A target with ``num_qubits=None`` will exclusively contain global + instructions (with ``qargs=None``) and when given to the transpiler, + it is expected that the transpiler will not resize the circuit. + This change in the :class:`.Target` requires future transpiler passes + to account for the case where ``target.num_qubits is None``. + +deprecations: + - | + The ``qiskit.providers.basicaer`` module and all of its classes are deprecated + from Qiskit 0.46 onwards. Their use should be replaced with + the :mod:`qiskit.quantum_info` module and the new + :mod:`qiskit.providers.basic_provider` module. + + The migration from using :mod:`qiskit.providers.basicaer` to + :mod:`qiskit.providers.basic_provider` can be performed as follows:: + + Migrate from | Replace with + ------------------------------------------------------------------------------ + :mod:`.basicaer` | :mod:`.basic_provider` + :class:`.BasicAerProvider` | :class:`.BasicProvider` + :class:`.BasicAerJob` | :class:`.BasicProviderJob` + :class:`.QasmSimulatorPy` | :class:`.BasicSimulator` + :class:`.UnitarySimulatorPy` | use :class:`~.quantum_info.Operator` + :class:`.StatevectorSimulatorPy` | use :class:`~.quantum_info.Statevector` + + + A notable difference is that the new provider is no longer exposed through a global instance + (like ``BasicAer``), so it will not be valid to do ``from qiskit import BasicProvider``. + Instead, the provider class must be imported from its submodule and instantiated:: + + from qiskit.providers.basic_provider import BasicProvider + provider = BasicProvider() + backend = provider.get_backend("sim_name") + + The following examples show the migration paths of the three simulators in :mod:`.basicaer`. + + 1. Statevector simulator:: + + from qiskit import QuantumCircuit + qc = QuantumCircuit(3) + qc.h(0) + qc.h(1) + qc.cx(1,2) + qc.measure_all() + + # Former path + from qiskit import BasicAer + backend = BasicAer.get_backend("statevector_simulator") + statevector = backend.run(qc).result().get_statevector() + + # New path + qc.remove_final_measurements() # no measurements allowed + from qiskit.quantum_info import Statevector + statevector = Statevector(qc) + + 2. Unitary simulator:: + + from qiskit import QuantumCircuit + qc = QuantumCircuit(3) + qc.h(0) + qc.h(1) + qc.cx(1,2) + qc.measure_all() + + # Former path + from qiskit import BasicAer + backend = BasicAer.get_backend("unitary_simulator") + result = backend.run(qc).result() + + # New path + qc.remove_final_measurements() # no measurements allowed + from qiskit.quantum_info import Operator + result = Operator(qc).data + + 3. Qasm simulator:: + + from qiskit import QuantumCircuit + qc = QuantumCircuit(3) + qc.h(0) + qc.h(1) + qc.cx(1,2) + qc.measure_all() + + # Former path + from qiskit import BasicAer + backend = BasicAer.get_backend("qasm_simulator") + result = backend.run(qc).result() + + # New path + from qiskit.providers.basic_provider import BasicProvider + backend = BasicProvider().get_backend("basic_simulator") + result = backend.run(qc).result() + # or, directly + from qiskit.providers.basic_provider import BasicSimulator + backend = BasicSimulator() + result = backend.run(qc).result( diff --git a/test/benchmarks/state_tomography.py b/test/benchmarks/state_tomography.py index 03496c9bf35f..102e6ceb33ff 100644 --- a/test/benchmarks/state_tomography.py +++ b/test/benchmarks/state_tomography.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2023 +# (C) Copyright IBM 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -26,7 +26,8 @@ class StateTomographyBench: timeout = 120.0 def setup(self, _): - self.qasm_backend = qiskit.BasicAer.get_backend("qasm_simulator") + provider = qiskit.providers.basic_provider.BasicProvider() + self.qasm_backend = provider.get_backend("basic_simulator") def time_state_tomography_bell(self, n_qubits): meas_qubits = [n_qubits - 2, n_qubits - 1] diff --git a/test/python/algorithms/algorithms_test_case.py b/test/python/algorithms/algorithms_test_case.py index 8fc9effd0bf7..7e1ef68f63d3 100644 --- a/test/python/algorithms/algorithms_test_case.py +++ b/test/python/algorithms/algorithms_test_case.py @@ -12,10 +12,19 @@ """Algorithms Test Case""" +import warnings from qiskit.test import QiskitTestCase class QiskitAlgorithmsTestCase(QiskitTestCase): """Algorithms test Case""" - pass + def setUp(self): + super().setUp() + # ignore basicaer msgs + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + + def tearDown(self): + super().tearDown() + # restore basicaer msgs + warnings.filterwarnings("error", category=DeprecationWarning, message=r".*basicaer.*") diff --git a/test/python/algorithms/evolvers/trotterization/test_trotter_qrte.py b/test/python/algorithms/evolvers/trotterization/test_trotter_qrte.py index 6635d4db5d85..97588e7a204e 100644 --- a/test/python/algorithms/evolvers/trotterization/test_trotter_qrte.py +++ b/test/python/algorithms/evolvers/trotterization/test_trotter_qrte.py @@ -20,7 +20,10 @@ import numpy as np from numpy.testing import assert_raises -from qiskit import BasicAer, QuantumCircuit +from qiskit import ( # pylint: disable=no-name-in-module + BasicAer, + QuantumCircuit, +) from qiskit.algorithms import EvolutionProblem from qiskit.algorithms.evolvers.trotterization import ( TrotterQRTE, diff --git a/test/python/algorithms/optimizers/test_optimizer_nft.py b/test/python/algorithms/optimizers/test_optimizer_nft.py index e904c3bffd91..67a915d389ef 100644 --- a/test/python/algorithms/optimizers/test_optimizer_nft.py +++ b/test/python/algorithms/optimizers/test_optimizer_nft.py @@ -16,7 +16,7 @@ import warnings from test.python.algorithms import QiskitAlgorithmsTestCase -from qiskit import BasicAer +from qiskit import BasicAer # pylint: disable=no-name-in-module from qiskit.circuit.library import RealAmplitudes from qiskit.utils import QuantumInstance, algorithm_globals from qiskit.opflow import PauliSumOp diff --git a/test/python/algorithms/optimizers/test_optimizers_scikitquant.py b/test/python/algorithms/optimizers/test_optimizers_scikitquant.py index f3d3f645d895..0f689af741e1 100644 --- a/test/python/algorithms/optimizers/test_optimizers_scikitquant.py +++ b/test/python/algorithms/optimizers/test_optimizers_scikitquant.py @@ -20,7 +20,7 @@ from ddt import ddt, data, unpack import numpy -from qiskit import BasicAer +from qiskit import BasicAer # pylint: disable=no-name-in-module from qiskit.circuit.library import RealAmplitudes from qiskit.utils import QuantumInstance, algorithm_globals from qiskit.exceptions import MissingOptionalLibraryError diff --git a/test/python/algorithms/test_amplitude_estimators.py b/test/python/algorithms/test_amplitude_estimators.py index ea0a1af099ee..e60a99370617 100644 --- a/test/python/algorithms/test_amplitude_estimators.py +++ b/test/python/algorithms/test_amplitude_estimators.py @@ -16,7 +16,11 @@ from test.python.algorithms import QiskitAlgorithmsTestCase import numpy as np from ddt import ddt, idata, data, unpack -from qiskit import QuantumRegister, QuantumCircuit, BasicAer +from qiskit import ( # pylint: disable=no-name-in-module + BasicAer, + QuantumCircuit, + QuantumRegister, +) from qiskit.circuit.library import QFT, GroverOperator from qiskit.utils import QuantumInstance from qiskit.algorithms import ( diff --git a/test/python/algorithms/test_aux_ops_evaluator.py b/test/python/algorithms/test_aux_ops_evaluator.py index bff0b07c09c9..fb3368c025de 100644 --- a/test/python/algorithms/test_aux_ops_evaluator.py +++ b/test/python/algorithms/test_aux_ops_evaluator.py @@ -23,7 +23,10 @@ from qiskit.providers import Backend from qiskit.quantum_info import Statevector from qiskit.algorithms import eval_observables -from qiskit import BasicAer, QuantumCircuit +from qiskit import ( # pylint: disable=no-name-in-module + BasicAer, + QuantumCircuit, +) from qiskit.circuit.library import EfficientSU2 from qiskit.opflow import ( PauliSumOp, diff --git a/test/python/algorithms/test_grover.py b/test/python/algorithms/test_grover.py index 0ba6cbaccf04..3b2cd072c60a 100644 --- a/test/python/algorithms/test_grover.py +++ b/test/python/algorithms/test_grover.py @@ -21,7 +21,10 @@ import numpy as np from ddt import data, ddt, idata, unpack -from qiskit import BasicAer, QuantumCircuit +from qiskit import ( # pylint: disable=no-name-in-module + BasicAer, + QuantumCircuit, +) from qiskit.algorithms import AmplificationProblem, Grover from qiskit.circuit.library import GroverOperator, PhaseOracle from qiskit.primitives import Sampler diff --git a/test/python/algorithms/test_qaoa.py b/test/python/algorithms/test_qaoa.py index 5edb525022a3..58f4cd0ebf88 100644 --- a/test/python/algorithms/test_qaoa.py +++ b/test/python/algorithms/test_qaoa.py @@ -28,7 +28,11 @@ from qiskit.opflow import I, X, Z, PauliSumOp -from qiskit import BasicAer, QuantumCircuit, QuantumRegister +from qiskit import ( # pylint: disable=no-name-in-module + BasicAer, + QuantumCircuit, + QuantumRegister, +) from qiskit.circuit import Parameter from qiskit.quantum_info import Pauli diff --git a/test/python/algorithms/test_skip_qobj_validation.py b/test/python/algorithms/test_skip_qobj_validation.py index 10ae37e8a2a6..ff77208750b2 100644 --- a/test/python/algorithms/test_skip_qobj_validation.py +++ b/test/python/algorithms/test_skip_qobj_validation.py @@ -15,7 +15,7 @@ import unittest from test.python.algorithms import QiskitAlgorithmsTestCase from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister -from qiskit import BasicAer +from qiskit import BasicAer # pylint: disable=no-name-in-module from qiskit.utils import QuantumInstance from qiskit.exceptions import QiskitError diff --git a/test/python/algorithms/test_vqd.py b/test/python/algorithms/test_vqd.py index f33dac82b6b5..2a8f4a927ff8 100644 --- a/test/python/algorithms/test_vqd.py +++ b/test/python/algorithms/test_vqd.py @@ -20,7 +20,10 @@ import numpy as np from ddt import data, ddt, unpack -from qiskit import BasicAer, QuantumCircuit +from qiskit import ( # pylint: disable=no-name-in-module + BasicAer, + QuantumCircuit, +) from qiskit.algorithms import VQD, AlgorithmError from qiskit.algorithms.optimizers import ( COBYLA, diff --git a/test/python/algorithms/test_vqe.py b/test/python/algorithms/test_vqe.py index 781728400f2b..edf4d403b355 100644 --- a/test/python/algorithms/test_vqe.py +++ b/test/python/algorithms/test_vqe.py @@ -24,7 +24,10 @@ from scipy.optimize import minimize as scipy_minimize from ddt import data, ddt, unpack -from qiskit import BasicAer, QuantumCircuit +from qiskit import ( # pylint: disable=no-name-in-module + BasicAer, + QuantumCircuit, +) from qiskit.algorithms import VQE, AlgorithmError from qiskit.algorithms.optimizers import ( CG, diff --git a/test/python/basicaer/test_basicaer_backends.py b/test/python/basicaer/test_basicaer_backends.py index 549827fa30ab..638d17337f7a 100644 --- a/test/python/basicaer/test_basicaer_backends.py +++ b/test/python/basicaer/test_basicaer_backends.py @@ -12,7 +12,7 @@ """BasicAer Backends Test.""" -from qiskit import BasicAer +from qiskit import BasicAer # pylint: disable=no-name-in-module from qiskit.providers.basicaer import BasicAerProvider from qiskit.providers.exceptions import QiskitBackendNotFoundError from qiskit.test import providers diff --git a/test/python/basicaer/test_basicaer_integration.py b/test/python/basicaer/test_basicaer_integration.py index 9dc00df843d1..2502c71bc10e 100644 --- a/test/python/basicaer/test_basicaer_integration.py +++ b/test/python/basicaer/test_basicaer_integration.py @@ -13,8 +13,9 @@ """BasicAer provider integration tests.""" import unittest +import warnings -from qiskit import BasicAer +from qiskit import BasicAer # pylint: disable=no-name-in-module from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.result import Result from qiskit.providers.basicaer import BasicAerError @@ -32,7 +33,9 @@ def setUp(self): self._qc2 = QuantumCircuit(qr, cr, name="qc2") self._qc1.measure(qr[0], cr[0]) self.backend = BasicAer.get_backend("qasm_simulator") - self._result1 = self.backend.run(self._qc1).result() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + self._result1 = self.backend.run(self._qc1).result() def test_builtin_simulator_result_fields(self): """Test components of a result from a local simulator.""" @@ -51,7 +54,9 @@ def test_basicaer_execute(self): qc.cx(qubit_reg[0], qubit_reg[1]) qc.measure(qubit_reg, clbit_reg) - job = self.backend.run(qc) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run(qc) result = job.result() self.assertIsInstance(result, Result) @@ -65,7 +70,9 @@ def test_basicaer_execute_two(self): qc.measure(qubit_reg, clbit_reg) qc_extra = QuantumCircuit(qubit_reg, clbit_reg, name="extra") qc_extra.measure(qubit_reg, clbit_reg) - job = self.backend.run([qc, qc_extra]) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run([qc, qc_extra]) result = job.result() self.assertIsInstance(result, Result) @@ -74,8 +81,10 @@ def test_basicaer_num_qubits(self): qc = QuantumCircuit(50, 1) qc.x(0) qc.measure(0, 0) - with self.assertRaises(BasicAerError): - self.backend.run(qc) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + with self.assertRaises(BasicAerError): + self.backend.run(qc) if __name__ == "__main__": diff --git a/test/python/basicaer/test_multi_registers_convention.py b/test/python/basicaer/test_multi_registers_convention.py index 45abcd5453cf..693d7b9d9126 100644 --- a/test/python/basicaer/test_multi_registers_convention.py +++ b/test/python/basicaer/test_multi_registers_convention.py @@ -12,7 +12,8 @@ """Test executing multiple-register circuits on BasicAer.""" -from qiskit import BasicAer +import warnings +from qiskit import BasicAer # pylint: disable=no-name-in-module from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister from qiskit.quantum_info import Operator, Statevector, process_fidelity, state_fidelity from qiskit.test import QiskitTestCase @@ -37,23 +38,29 @@ def test_circuit_multi(self): qc = circ.compose(meas) - backend_sim = BasicAer.get_backend("qasm_simulator") + # filter warnings raised by deprecated functionality in BasicAer backends .run() method + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") - result = backend_sim.run(qc).result() - counts = result.get_counts(qc) + backend_sim = BasicAer.get_backend("qasm_simulator") - target = {"01 10": 1024} + result = backend_sim.run(qc).result() + counts = result.get_counts(qc) - backend_sim = BasicAer.get_backend("statevector_simulator") - result = backend_sim.run(circ).result() - state = result.get_statevector(circ) + target = {"01 10": 1024} - backend_sim = BasicAer.get_backend("unitary_simulator") - result = backend_sim.run(circ).result() - unitary = Operator(result.get_unitary(circ)) + backend_sim = BasicAer.get_backend("statevector_simulator") + result = backend_sim.run(circ).result() + state = result.get_statevector(circ) - self.assertEqual(counts, target) - self.assertAlmostEqual(state_fidelity(Statevector.from_label("0110"), state), 1.0, places=7) - self.assertAlmostEqual( - process_fidelity(Operator.from_label("IXXI"), unitary), 1.0, places=7 - ) + backend_sim = BasicAer.get_backend("unitary_simulator") + result = backend_sim.run(circ).result() + unitary = Operator(result.get_unitary(circ)) + + self.assertEqual(counts, target) + self.assertAlmostEqual( + state_fidelity(Statevector.from_label("0110"), state), 1.0, places=7 + ) + self.assertAlmostEqual( + process_fidelity(Operator.from_label("IXXI"), unitary), 1.0, places=7 + ) diff --git a/test/python/basicaer/test_qasm_simulator.py b/test/python/basicaer/test_qasm_simulator.py index cb0f86761123..b36bf30cd71d 100644 --- a/test/python/basicaer/test_qasm_simulator.py +++ b/test/python/basicaer/test_qasm_simulator.py @@ -17,6 +17,7 @@ import io from logging import StreamHandler, getLogger import sys +import warnings import numpy as np @@ -76,9 +77,11 @@ def test_submission_log_time(self): def test_qasm_simulator_single_shot(self): """Test single shot run.""" shots = 1 - result = self.backend.run( - self.transpiled_circuit, shots=shots, seed_simulator=self.seed - ).result() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + result = self.backend.run( + self.transpiled_circuit, shots=shots, seed_simulator=self.seed + ).result() self.assertEqual(result.success, True) def test_measure_sampler_repeated_qubits(self): @@ -93,7 +96,9 @@ def test_measure_sampler_repeated_qubits(self): circuit.measure(qr[1], cr[2]) circuit.measure(qr[0], cr[3]) target = {"0110": shots} - job = self.backend.run(circuit, shots=shots, seed_simulator=self.seed) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run(circuit, shots=shots, seed_simulator=self.seed) result = job.result() counts = result.get_counts(0) self.assertEqual(counts, target) @@ -110,7 +115,11 @@ def test_measure_sampler_single_qubit(self): circuit.x(qr[qubit]) circuit.measure(qr[qubit], cr[0]) target = {"1": shots} - job = self.backend.run(circuit, shots=shots, seed_simulator=self.seed) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", category=DeprecationWarning, message=r".*basicaer.*" + ) + job = self.backend.run(circuit, shots=shots, seed_simulator=self.seed) result = job.result() counts = result.get_counts(0) self.assertEqual(counts, target) @@ -147,16 +156,20 @@ def test_measure_sampler_partial_qubit(self): circuit.barrier(qr) circuit.measure(qr[3], cr[3]) target = {"1011": shots} - job = self.backend.run(circuit, shots=shots, seed_simulator=self.seed) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run(circuit, shots=shots, seed_simulator=self.seed) result = job.result() counts = result.get_counts(0) self.assertEqual(counts, target) def test_qasm_simulator(self): """Test data counts output for single circuit run against reference.""" - result = self.backend.run( - self.transpiled_circuit, shots=1000, seed_simulator=self.seed - ).result() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + result = self.backend.run( + self.transpiled_circuit, shots=1000, seed_simulator=self.seed + ).result() shots = 1024 threshold = 0.04 * shots counts = result.get_counts("test") @@ -216,11 +229,13 @@ def test_if_statement(self): circuit_if_false.measure(qr[0], cr[0]) circuit_if_false.measure(qr[1], cr[1]) circuit_if_false.measure(qr[2], cr[2]) - job = self.backend.run( - [circuit_if_true, circuit_if_false], - shots=shots, - seed_simulator=self.seed, - ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run( + [circuit_if_true, circuit_if_false], + shots=shots, + seed_simulator=self.seed, + ) result = job.result() counts_if_true = result.get_counts(circuit_if_true) @@ -252,7 +267,9 @@ def test_bit_cif_crossaffect(self): circuit.measure(qr[2], cr[2]) circuit.h(qr[0]).c_if(cr[0], True) circuit.measure(qr[0], cr1[0]) - job = self.backend.run(circuit, shots=shots, seed_simulator=self.seed) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run(circuit, shots=shots, seed_simulator=self.seed) result = job.result().get_counts() target = {"0 110": 100} self.assertEqual(result, target) @@ -292,9 +309,11 @@ def test_teleport(self): circuit.z(qr[2]).c_if(cr0, 1) circuit.x(qr[2]).c_if(cr1, 1) circuit.measure(qr[2], cr2[0]) - job = self.backend.run( - transpile(circuit, self.backend), shots=shots, seed_simulator=self.seed - ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run( + transpile(circuit, self.backend), shots=shots, seed_simulator=self.seed + ) results = job.result() data = results.get_counts("teleport") alice = { @@ -348,7 +367,9 @@ def test_memory(self): circ.measure(qr[3], cr1[1]) shots = 50 - job = self.backend.run(circ, shots=shots, memory=True) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run(circ, shots=shots, memory=True) result = job.result() memory = result.get_memory() self.assertEqual(len(memory), shots) @@ -375,7 +396,11 @@ def test_unitary(self): circuit = QuantumCircuit(qr, cr) circuit.unitary(multi_x, qr) circuit.measure(qr, cr) - job = self.backend.run(transpile(circuit), shots=shots) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", category=DeprecationWarning, message=r".*basicaer.*" + ) + job = self.backend.run(transpile(circuit, self.backend), shots=shots) result = job.result() counts = result.get_counts(0) self.assertEqual(counts, target_counts) diff --git a/test/python/basicaer/test_statevector_simulator.py b/test/python/basicaer/test_statevector_simulator.py index 611fd86fd606..b0749bc1f336 100644 --- a/test/python/basicaer/test_statevector_simulator.py +++ b/test/python/basicaer/test_statevector_simulator.py @@ -12,6 +12,7 @@ """Test StateVectorSimulatorPy.""" import unittest +import warnings import numpy as np @@ -76,7 +77,11 @@ def test_unitary(self): # Simulate output on circuit circuit = QuantumCircuit(qr) circuit.unitary(unitary, qr) - job = self.backend.run(transpile(circuit, self.backend)) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", category=DeprecationWarning, message=r".*BasicAer.*" + ) + job = self.backend.run(transpile(circuit, self.backend)) result = job.result() psi_out = result.get_statevector(0) fidelity = state_fidelity(psi_target, psi_out) diff --git a/test/python/basicaer/test_unitary_simulator.py b/test/python/basicaer/test_unitary_simulator.py index 13b504f2503f..69deaeead562 100644 --- a/test/python/basicaer/test_unitary_simulator.py +++ b/test/python/basicaer/test_unitary_simulator.py @@ -13,6 +13,7 @@ """Tests for unitary simulator.""" import unittest +import warnings import numpy as np @@ -35,7 +36,9 @@ class BasicAerUnitarySimulatorPyTest(providers.BackendTestCase): def test_basicaer_unitary_simulator_py(self): """Test unitary simulator.""" circuits = self._test_circuits() - job = self.backend.run(transpile(circuits, self.backend)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run(transpile(circuits, self.backend)) sim_unitaries = [job.result().get_unitary(circ) for circ in circuits] reference_unitaries = self._reference_unitaries() for u_sim, u_ref in zip(sim_unitaries, reference_unitaries): @@ -108,7 +111,11 @@ def test_unitary(self): # Simulate output on circuit circuit = QuantumCircuit(qr) circuit.unitary(unitary, qr) - job = self.backend.run(transpile(circuit, self.backend)) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", category=DeprecationWarning, message=r".*basicaer.*" + ) + job = self.backend.run(transpile(circuit, self.backend)) result = job.result() unitary_out = Operator(result.get_unitary(0)) fidelity = process_fidelity(unitary_target, unitary_out) @@ -124,7 +131,9 @@ def test_global_phase(self): circuit.z(q[0]) circuit.x(q[0]) - job = self.backend.run(transpile(circuit, self.backend)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") + job = self.backend.run(transpile(circuit, self.backend)) result = job.result() unitary_out = result.get_unitary(circuit) diff --git a/test/python/circuit/library/test_functional_pauli_rotations.py b/test/python/circuit/library/test_functional_pauli_rotations.py index 85bc16ec7a8e..638608c95690 100644 --- a/test/python/circuit/library/test_functional_pauli_rotations.py +++ b/test/python/circuit/library/test_functional_pauli_rotations.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2020. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,13 +18,13 @@ from ddt import ddt, data, unpack from qiskit.test.base import QiskitTestCase -from qiskit import BasicAer, transpile from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import ( LinearPauliRotations, PolynomialPauliRotations, PiecewiseLinearPauliRotations, ) +from qiskit.quantum_info import Statevector @ddt @@ -38,10 +38,7 @@ def assertFunctionIsCorrect(self, function_circuit, reference): circuit = QuantumCircuit(num_state_qubits + 1 + num_ancilla_qubits) circuit.h(list(range(num_state_qubits))) circuit.append(function_circuit.to_instruction(), list(range(circuit.num_qubits))) - - backend = BasicAer.get_backend("statevector_simulator") - statevector = backend.run(transpile(circuit, backend)).result().get_statevector() - + statevector = Statevector(circuit) probabilities = defaultdict(float) for i, statevector_amplitude in enumerate(statevector): i = bin(i)[2:].zfill(circuit.num_qubits)[num_ancilla_qubits:] @@ -84,7 +81,7 @@ def test_polynomial_rotations_mutability(self): with self.subTest(msg="missing number of state qubits"): with self.assertRaises(AttributeError): # no state qubits set - print(polynomial_rotations.draw()) + _ = str(polynomial_rotations.draw()) with self.subTest(msg="default setup, just setting number of state qubits"): polynomial_rotations.num_state_qubits = 2 @@ -121,7 +118,7 @@ def test_linear_rotations_mutability(self): with self.subTest(msg="missing number of state qubits"): with self.assertRaises(AttributeError): # no state qubits set - print(linear_rotation.draw()) + _ = str(linear_rotation.draw()) with self.subTest(msg="default setup, just setting number of state qubits"): linear_rotation.num_state_qubits = 2 @@ -171,7 +168,7 @@ def test_piecewise_linear_rotations_mutability(self): with self.subTest(msg="missing number of state qubits"): with self.assertRaises(AttributeError): # no state qubits set - print(pw_linear_rotations.draw()) + _ = str(pw_linear_rotations.draw()) with self.subTest(msg="default setup, just setting number of state qubits"): pw_linear_rotations.num_state_qubits = 2 diff --git a/test/python/circuit/library/test_integer_comparator.py b/test/python/circuit/library/test_integer_comparator.py index a98e3cca3cec..7de451975d5f 100644 --- a/test/python/circuit/library/test_integer_comparator.py +++ b/test/python/circuit/library/test_integer_comparator.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2020. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -17,9 +17,9 @@ from ddt import ddt, data, unpack from qiskit.test.base import QiskitTestCase -from qiskit import BasicAer, transpile from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import IntegerComparator +from qiskit.quantum_info import Statevector @ddt @@ -33,8 +33,7 @@ def assertComparisonIsCorrect(self, comp, num_state_qubits, value, geq): qc.append(comp, list(range(comp.num_qubits))) # add comparator # run simulation - backend = BasicAer.get_backend("statevector_simulator") - statevector = backend.run(transpile(qc, backend)).result().get_statevector() + statevector = Statevector(qc) for i, amplitude in enumerate(statevector): prob = np.abs(amplitude) ** 2 if prob > 1e-6: @@ -71,13 +70,13 @@ def test_mutability(self): with self.subTest(msg="missing num state qubits and value"): with self.assertRaises(AttributeError): - print(comp.draw()) + _ = str(comp.draw()) comp.num_state_qubits = 2 with self.subTest(msg="missing value"): with self.assertRaises(AttributeError): - print(comp.draw()) + _ = str(comp.draw()) comp.value = 0 comp.geq = True diff --git a/test/python/circuit/library/test_linear_amplitude_function.py b/test/python/circuit/library/test_linear_amplitude_function.py index b7c15bab2d9e..24147e12377e 100644 --- a/test/python/circuit/library/test_linear_amplitude_function.py +++ b/test/python/circuit/library/test_linear_amplitude_function.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2020. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,10 +18,10 @@ from ddt import ddt, data, unpack import numpy as np -from qiskit import BasicAer, transpile from qiskit.test.base import QiskitTestCase from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import LinearAmplitudeFunction +from qiskit.quantum_info import Statevector @ddt @@ -36,10 +36,7 @@ def assertFunctionIsCorrect(self, function_circuit, reference): circuit = QuantumCircuit(function_circuit.num_qubits) circuit.h(list(range(num_state_qubits))) circuit.append(function_circuit.to_instruction(), list(range(circuit.num_qubits))) - - backend = BasicAer.get_backend("statevector_simulator") - statevector = backend.run(transpile(circuit, backend)).result().get_statevector() - + statevector = Statevector(circuit) probabilities = defaultdict(float) for i, statevector_amplitude in enumerate(statevector): i = bin(i)[2:].zfill(circuit.num_qubits)[num_ancillas:] diff --git a/test/python/circuit/library/test_phase_estimation.py b/test/python/circuit/library/test_phase_estimation.py index 8a423128ad2a..71b13e6f8c1e 100644 --- a/test/python/circuit/library/test_phase_estimation.py +++ b/test/python/circuit/library/test_phase_estimation.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2020. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -63,7 +63,7 @@ def assertPhaseEstimationIsCorrect( inplace=True, ) circuit.compose(pec, inplace=True) - actual = Statevector.from_instruction(circuit).data + actual = Statevector(circuit) np.testing.assert_almost_equal(reference, actual) def test_phase_estimation(self): diff --git a/test/python/circuit/library/test_piecewise_chebyshev.py b/test/python/circuit/library/test_piecewise_chebyshev.py index 203f8448db53..f0d738ec9e29 100644 --- a/test/python/circuit/library/test_piecewise_chebyshev.py +++ b/test/python/circuit/library/test_piecewise_chebyshev.py @@ -18,9 +18,9 @@ from ddt import ddt, data, unpack from qiskit.test.base import QiskitTestCase -from qiskit import BasicAer, transpile from qiskit.circuit import QuantumCircuit from qiskit.circuit.library.arithmetic.piecewise_chebyshev import PiecewiseChebyshev +from qiskit.quantum_info import Statevector @ddt @@ -35,10 +35,7 @@ def assertFunctionIsCorrect(self, function_circuit, reference): circuit = QuantumCircuit(num_state_qubits + 1 + num_ancilla_qubits) circuit.h(list(range(num_state_qubits))) circuit.append(function_circuit.to_instruction(), list(range(circuit.num_qubits))) - - backend = BasicAer.get_backend("statevector_simulator") - statevector = backend.run(transpile(circuit, backend)).result().get_statevector() - + statevector = Statevector(circuit) probabilities = defaultdict(float) for i, statevector_amplitude in enumerate(statevector): i = bin(i)[2:].zfill(circuit.num_qubits)[num_ancilla_qubits:] @@ -103,7 +100,7 @@ def f_x_1(x): with self.subTest(msg="missing number of state qubits"): with self.assertRaises(AttributeError): # no state qubits set - print(pw_approximation.draw()) + _ = str(pw_approximation.draw()) with self.subTest(msg="default setup, just setting number of state qubits"): pw_approximation.num_state_qubits = 2 diff --git a/test/python/circuit/library/test_weighted_adder.py b/test/python/circuit/library/test_weighted_adder.py index c363222c2e00..4003588bbc0c 100644 --- a/test/python/circuit/library/test_weighted_adder.py +++ b/test/python/circuit/library/test_weighted_adder.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2020. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,9 +18,9 @@ import numpy as np from qiskit.test.base import QiskitTestCase -from qiskit import BasicAer, transpile from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import WeightedAdder +from qiskit.quantum_info import Statevector @ddt @@ -34,8 +34,7 @@ def assertSummationIsCorrect(self, adder): circuit.h(list(range(adder.num_state_qubits))) circuit.append(adder.to_instruction(), list(range(adder.num_qubits))) - backend = BasicAer.get_backend("statevector_simulator") - statevector = backend.run(transpile(circuit, backend)).result().get_statevector() + statevector = Statevector(circuit) probabilities = defaultdict(float) for i, statevector_amplitude in enumerate(statevector): @@ -67,7 +66,7 @@ def test_mutability(self): with self.subTest(msg="missing number of state qubits"): with self.assertRaises(AttributeError): - print(adder.draw()) + _ = str(adder.draw()) with self.subTest(msg="default weights"): adder.num_state_qubits = 3 @@ -81,7 +80,7 @@ def test_mutability(self): with self.subTest(msg="mismatching number of state qubits and weights"): with self.assertRaises(ValueError): adder.weights = [0, 1, 2, 3] - print(adder.draw()) + _ = str(adder.draw()) with self.subTest(msg="change all attributes"): adder.num_state_qubits = 4 diff --git a/test/python/circuit/test_circuit_operations.py b/test/python/circuit/test_circuit_operations.py index f7a3b0df5589..0c3bd21e92fc 100644 --- a/test/python/circuit/test_circuit_operations.py +++ b/test/python/circuit/test_circuit_operations.py @@ -16,7 +16,7 @@ import numpy as np from ddt import data, ddt -from qiskit import BasicAer, ClassicalRegister, QuantumCircuit, QuantumRegister +from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister from qiskit.circuit import Gate, Instruction, Measure, Parameter, Barrier from qiskit.circuit.bit import Bit from qiskit.circuit.classicalregister import Clbit @@ -27,6 +27,7 @@ from qiskit.circuit.quantumcircuit import BitLocations from qiskit.circuit.quantumcircuitdata import CircuitInstruction from qiskit.circuit.quantumregister import AncillaQubit, AncillaRegister, Qubit +from qiskit.providers.basic_provider import BasicSimulator from qiskit.pulse import DriveChannel, Gaussian, Play, Schedule from qiskit.quantum_info import Operator from qiskit.test import QiskitTestCase @@ -186,7 +187,7 @@ def test_compose_circuit(self): qc2.measure(qr[1], cr[1]) qc3 = qc1.compose(qc2) - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() shots = 1024 result = backend.run(qc3, shots=shots, seed_simulator=78).result() counts = result.get_counts() @@ -208,7 +209,7 @@ def test_compose_circuit_and(self): qc2.measure(qr[1], cr[1]) qc3 = qc1 & qc2 - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() shots = 1024 result = backend.run(qc3, shots=shots, seed_simulator=78).result() counts = result.get_counts() @@ -230,7 +231,7 @@ def test_compose_circuit_iand(self): qc2.measure(qr[1], cr[1]) qc1 &= qc2 - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() shots = 1024 result = backend.run(qc1, shots=shots, seed_simulator=78).result() counts = result.get_counts() @@ -280,7 +281,7 @@ def test_tensor_circuit(self): qc1.measure(0, 0) qc3 = qc1.tensor(qc2) - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() shots = 1024 result = backend.run(qc3, shots=shots, seed_simulator=78).result() counts = result.get_counts() @@ -301,7 +302,7 @@ def test_tensor_circuit_xor(self): qc1.measure(0, 0) qc3 = qc1 ^ qc2 - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() shots = 1024 result = backend.run(qc3, shots=shots, seed_simulator=78).result() counts = result.get_counts() @@ -322,7 +323,7 @@ def test_tensor_circuit_ixor(self): qc1.measure(0, 0) qc1 ^= qc2 - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() shots = 1024 result = backend.run(qc1, shots=shots, seed_simulator=78).result() counts = result.get_counts() diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py index 39042ae3d3ac..5f9a29e80242 100644 --- a/test/python/circuit/test_controlled_gate.py +++ b/test/python/circuit/test_controlled_gate.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,7 +19,7 @@ from numpy import pi from ddt import ddt, data, unpack -from qiskit import QuantumRegister, QuantumCircuit, BasicAer, QiskitError, transpile +from qiskit import QuantumRegister, QuantumCircuit, QiskitError from qiskit.test import QiskitTestCase from qiskit.circuit import ControlledGate, Parameter, Gate from qiskit.circuit.singleton import SingletonControlledGate, _SingletonControlledGateOverrides @@ -424,21 +424,13 @@ def test_multi_control_u1(self): c_cu1 = cu1gate.control(1) qc_cu1.append(c_cu1, qr, []) - backend = BasicAer.get_backend("unitary_simulator") - job = backend.run( - transpile( - [qcnu1, qu1, qcu1, qc_cu1], backend, basis_gates=["u1", "u2", "u3", "id", "cx"] - ), - ) - result = job.result() - # Circuit unitaries - mat_cnu1 = result.get_unitary(0) + mat_cnu1 = Operator(qcnu1).data # trace out ancillae - mat_u1 = result.get_unitary(1) - mat_cu1 = result.get_unitary(2) - mat_c_cu1 = result.get_unitary(3) + mat_u1 = Operator(qu1).data + mat_cu1 = Operator(qcu1).data + mat_c_cu1 = Operator(qc_cu1).data # Target Controlled-U1 unitary target_cnu1 = _compute_control_matrix(mat_u1, num_ctrl) @@ -489,7 +481,6 @@ def test_multi_controlled_u1_matrix(self, num_controls): qc.x(q_controls[idx]) simulated = Operator(qc) - base = PhaseGate(lam).to_matrix() expected = _compute_control_matrix(base, num_controls, ctrl_state=ctrl_state) with self.subTest(msg=f"control state = {ctrl_state}"): @@ -518,9 +509,8 @@ def test_multi_control_toffoli_matrix_clean_ancillas(self, num_controls): # apply hadamard on control qubits and toffoli gate qc.mcx(q_controls, q_target[0], q_ancillas, mode="basic") - # execute the circuit and obtain statevector result - backend = BasicAer.get_backend("unitary_simulator") - simulated = backend.run(transpile(qc, backend)).result().get_unitary(qc) + # obtain unitary for circuit + simulated = Operator(qc).data # compare to expectation if num_ancillas > 0: @@ -551,8 +541,7 @@ def test_multi_control_toffoli_matrix_basic_dirty_ancillas(self, num_controls): qc.mcx(q_controls, q_target[0], q_ancillas, mode="basic-dirty-ancilla") - simulator = BasicAer.get_backend("unitary_simulator") - simulated = simulator.run(transpile(qc, simulator)).result().get_unitary(qc) + simulated = Operator(qc).data if num_ancillas > 0: simulated = simulated[: 2 ** (num_controls + 1), : 2 ** (num_controls + 1)] @@ -581,8 +570,7 @@ def test_multi_control_toffoli_matrix_advanced_dirty_ancillas(self, num_controls qc.mcx(q_controls, q_target[0], q_ancillas, mode="advanced") - simulator = BasicAer.get_backend("unitary_simulator") - simulated = simulator.run(transpile(qc, simulator)).result().get_unitary(qc) + simulated = Operator(qc).data if num_ancillas > 0: simulated = simulated[: 2 ** (num_controls + 1), : 2 ** (num_controls + 1)] @@ -603,8 +591,7 @@ def test_multi_control_toffoli_matrix_noancilla_dirty_ancillas(self, num_control qc.mcx(q_controls, q_target[0], None, mode="noancilla") - simulator = BasicAer.get_backend("unitary_simulator") - simulated = simulator.run(transpile(qc, simulator)).result().get_unitary(qc) + simulated = Operator(qc) base = XGate().to_matrix() expected = _compute_control_matrix(base, num_controls) @@ -665,8 +652,7 @@ def test_multi_controlled_rotation_gate_matrices( gates_used = set(qc.count_ops().keys()) self.assertTrue(gates_used.issubset({"x", "u", "p", "cx"})) - backend = BasicAer.get_backend("unitary_simulator") - simulated = backend.run(transpile(qc, backend)).result().get_unitary(qc) + simulated = Operator(qc) if base_gate_name == "x": rot_mat = RXGate(theta).to_matrix() @@ -724,9 +710,8 @@ def test_multi_controlled_y_rotation_matrix_basic_mode(self, num_controls, use_b qc.x(q_controls[idx]) rot_mat = RYGate(theta).to_matrix() + simulated = Operator(qc).data - backend = BasicAer.get_backend("unitary_simulator") - simulated = backend.run(transpile(qc, backend)).result().get_unitary(qc) if num_ancillas > 0: simulated = simulated[: 2 ** (num_controls + 1), : 2 ** (num_controls + 1)] @@ -766,7 +751,6 @@ def test_mcxgraycode_gates_yield_explicit_gates(self, num_ctrl_qubits): @data(3, 4, 5, 8) def test_mcx_gates(self, num_ctrl_qubits): """Test the mcx gates.""" - backend = BasicAer.get_backend("statevector_simulator") reference = np.zeros(2 ** (num_ctrl_qubits + 1)) reference[-1] = 1 @@ -781,7 +765,7 @@ def test_mcx_gates(self, num_ctrl_qubits): if num_ctrl_qubits > 0: circuit.x(list(range(num_ctrl_qubits))) circuit.append(gate, list(range(gate.num_qubits)), []) - statevector = backend.run(transpile(circuit, backend)).result().get_statevector() + statevector = Statevector(circuit).data # account for ancillas if hasattr(gate, "num_ancilla_qubits") and gate.num_ancilla_qubits > 0: @@ -1083,8 +1067,8 @@ def test_relative_phase_toffoli_gates(self, num_ctrl_qubits): circuit.rccx(0, 1, 2) else: # num_ctrl_qubits == 3: circuit.rcccx(0, 1, 2, 3) - simulator = BasicAer.get_backend("unitary_simulator") - simulated_mat = simulator.run(transpile(circuit, simulator)).result().get_unitary() + + simulated_mat = Operator(circuit) # get the matrix representation from the class itself if num_ctrl_qubits == 2: diff --git a/test/python/circuit/test_diagonal_gate.py b/test/python/circuit/test_diagonal_gate.py index eb73a9605b67..bc280f4fabbe 100644 --- a/test/python/circuit/test_diagonal_gate.py +++ b/test/python/circuit/test_diagonal_gate.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -16,13 +16,14 @@ import unittest import numpy as np -from qiskit import QuantumCircuit, QuantumRegister, BasicAer, assemble +from qiskit import QuantumCircuit, QuantumRegister, assemble from qiskit import QiskitError from qiskit.test import QiskitTestCase from qiskit.compiler import transpile from qiskit.extensions.quantum_initializer import DiagonalGate from qiskit.quantum_info.operators.predicates import matrix_equal +from qiskit.quantum_info import Operator class TestDiagonalGate(QiskitTestCase): @@ -51,9 +52,7 @@ def test_diag_gate(self): # Decompose the gate qc = transpile(qc, basis_gates=["u1", "u3", "u2", "cx", "id"], optimization_level=0) # Simulate the decomposed gate - simulator = BasicAer.get_backend("unitary_simulator") - result = simulator.run(qc).result() - unitary = result.get_unitary(qc) + unitary = Operator(qc) unitary_desired = _get_diag_gate_matrix(diag) self.assertTrue(matrix_equal(unitary, unitary_desired, ignore_phase=False)) diff --git a/test/python/circuit/test_extensions_standard.py b/test/python/circuit/test_extensions_standard.py index 9f69d13400d6..62a20132aeb8 100644 --- a/test/python/circuit/test_extensions_standard.py +++ b/test/python/circuit/test_extensions_standard.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory diff --git a/test/python/circuit/test_initializer.py b/test/python/circuit/test_initializer.py index 23666297a3e6..979401d3c9f7 100644 --- a/test/python/circuit/test_initializer.py +++ b/test/python/circuit/test_initializer.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -23,10 +23,10 @@ QuantumCircuit, QuantumRegister, ClassicalRegister, - BasicAer, transpile, assemble, ) +from qiskit.providers.basic_provider import BasicSimulator from qiskit.quantum_info import state_fidelity, Statevector, Operator from qiskit.exceptions import QiskitError from qiskit.test import QiskitTestCase @@ -45,10 +45,7 @@ def test_uniform_superposition(self): qr = QuantumRegister(2, "qr") qc = QuantumCircuit(qr) qc.initialize(desired_vector, [qr[0], qr[1]]) - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, desired_vector) self.assertGreater( fidelity, @@ -62,11 +59,7 @@ def test_deterministic_state(self): qr = QuantumRegister(2, "qr") qc = QuantumCircuit(qr) qc.initialize(desired_vector, [qr[0], qr[1]]) - - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, desired_vector) self.assertGreater( fidelity, @@ -89,11 +82,7 @@ def test_bell_state(self): qr = QuantumRegister(2, "qr") qc = QuantumCircuit(qr) qc.initialize(desired_vector, [qr[0], qr[1]]) - - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, desired_vector) self.assertGreater( fidelity, @@ -107,11 +96,7 @@ def test_ghz_state(self): qr = QuantumRegister(3, "qr") qc = QuantumCircuit(qr) qc.initialize(desired_vector, [qr[0], qr[1], qr[2]]) - - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, desired_vector) self.assertGreater( fidelity, @@ -126,11 +111,7 @@ def test_initialize_register(self): qr2 = QuantumRegister(2, "qr2") qc = QuantumCircuit(qr, qr2) qc.initialize(desired_vector, qr) - - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, np.kron([1, 0, 0, 0], desired_vector)) self.assertGreater( fidelity, @@ -150,11 +131,8 @@ def test_initialize_one_by_one(self): qc_b.initialize(qubit_0_state, [qr[0]]) qc_b.initialize(qubit_1_state, [qr[1]]) - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile([qc_a, qc_b], backend)) - result = job.result() - statevector_a = result.get_statevector(0) - statevector_b = result.get_statevector(1) + statevector_a = Statevector(qc_a) + statevector_b = Statevector(qc_b) fidelity = state_fidelity(statevector_a, statevector_b) self.assertGreater( fidelity, @@ -168,10 +146,7 @@ def test_single_qubit(self): qr = QuantumRegister(1, "qr") qc = QuantumCircuit(qr) qc.initialize(desired_vector, [qr[0]]) - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, desired_vector) self.assertGreater( fidelity, @@ -194,10 +169,7 @@ def test_random_3qubit(self): qr = QuantumRegister(3, "qr") qc = QuantumCircuit(qr) qc.initialize(desired_vector, [qr[0], qr[1], qr[2]]) - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, desired_vector) self.assertGreater( fidelity, @@ -228,10 +200,7 @@ def test_random_4qubit(self): qr = QuantumRegister(4, "qr") qc = QuantumCircuit(qr) qc.initialize(desired_vector, [qr[0], qr[1], qr[2], qr[3]]) - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, desired_vector) self.assertGreater( fidelity, @@ -298,9 +267,8 @@ def test_initialize_middle_circuit(self): qc.measure(qr, cr) # statevector simulator does not support reset shots = 2000 - threshold = 0.005 * shots - - backend = BasicAer.get_backend("qasm_simulator") + threshold = 0.05 * shots + backend = BasicSimulator() job = backend.run(transpile(qc, backend), shots=shots, seed_simulator=42) result = job.result() counts = result.get_counts() @@ -330,10 +298,7 @@ def test_math_amplitudes(self): qr = QuantumRegister(4, "qr") qc = QuantumCircuit(qr) qc.initialize(desired_vector, [qr[0], qr[1], qr[2], qr[3]]) - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc, backend)) - result = job.result() - statevector = result.get_statevector() + statevector = Statevector(qc) fidelity = state_fidelity(statevector, desired_vector) self.assertGreater( fidelity, @@ -353,11 +318,8 @@ def test_combiner(self): qc2 = QuantumCircuit(qr, cr) qc2.initialize(desired_vector_2, [qr[0]]) - backend = BasicAer.get_backend("statevector_simulator") - job = backend.run(transpile(qc1.compose(qc2), backend)) - result = job.result() - quantum_state = result.get_statevector() - fidelity = state_fidelity(quantum_state, desired_vector_2) + statevector = Statevector(qc1.compose(qc2)) + fidelity = state_fidelity(statevector, desired_vector_2) self.assertGreater( fidelity, self._desired_fidelity, diff --git a/test/python/circuit/test_isometry.py b/test/python/circuit/test_isometry.py index ac1b4c548ce0..f5fcf4e3a530 100644 --- a/test/python/circuit/test_isometry.py +++ b/test/python/circuit/test_isometry.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,7 +18,6 @@ from ddt import ddt, data from qiskit.quantum_info.random import random_unitary -from qiskit import BasicAer from qiskit import QuantumCircuit from qiskit import QuantumRegister from qiskit.test import QiskitTestCase @@ -64,9 +63,7 @@ def test_isometry(self, iso): qc = transpile(qc, basis_gates=["u1", "u3", "u2", "cx", "id"]) # Simulate the decomposed gate - simulator = BasicAer.get_backend("unitary_simulator") - result = simulator.run(qc).result() - unitary = result.get_unitary(qc) + unitary = Operator(qc).data iso_from_circuit = unitary[::, 0 : 2**num_q_input] iso_desired = iso @@ -106,9 +103,7 @@ def test_isometry_tolerance(self, iso): qc = transpile(qc, basis_gates=["u1", "u3", "u2", "cx", "id"]) # Simulate the decomposed gate - simulator = BasicAer.get_backend("unitary_simulator") - result = simulator.run(qc).result() - unitary = result.get_unitary(qc) + unitary = Operator(qc).data iso_from_circuit = unitary[::, 0 : 2**num_q_input] self.assertTrue(np.allclose(iso_from_circuit, iso)) diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index 012498bb1a21..8ca195b83d2c 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2019. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -27,7 +27,7 @@ import qiskit import qiskit.circuit.library as circlib from qiskit.circuit.library.standard_gates.rz import RZGate -from qiskit import BasicAer, ClassicalRegister, QuantumCircuit, QuantumRegister +from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister from qiskit.circuit import Gate, Instruction, Parameter, ParameterExpression, ParameterVector from qiskit.circuit.parametertable import ParameterReferences, ParameterTable, ParameterView from qiskit.circuit.exceptions import CircuitError @@ -35,6 +35,7 @@ from qiskit import pulse from qiskit.quantum_info import Operator from qiskit.test import QiskitTestCase +from qiskit.providers.basic_provider import BasicSimulator from qiskit.providers.fake_provider import FakeOurense from qiskit.tools import parallel_map @@ -132,7 +133,7 @@ def test_compile_quantum_circuit(self): qr = QuantumRegister(1) qc = QuantumCircuit(qr) qc.rx(theta, qr) - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qc_aer = transpile(qc, backend) self.assertIn(theta, qc_aer.parameters) @@ -671,7 +672,7 @@ def test_circuit_generation(self): qr = QuantumRegister(1) qc = QuantumCircuit(qr) qc.rx(theta, qr) - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qc_aer = transpile(qc, backend) # generate list of circuits @@ -769,7 +770,7 @@ def test_compile_vector(self): for i, q in enumerate(qc.qubits[:-1]): qc.cx(qc.qubits[i], qc.qubits[i + 1]) qc.barrier() - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qc_aer = transpile(qc, backend) for param in theta: self.assertIn(param, qc_aer.parameters) @@ -800,7 +801,7 @@ def test_instruction_ryrz_vector(self): qc.append(cxs, qargs=qc.qubits[:-1]) qc.barrier() - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qc_aer = transpile(qc, backend) for vec in paramvecs: for param in vec: @@ -893,7 +894,7 @@ def test_binding_parameterized_circuits_built_in_multiproc(self): qobj = assemble( circuit, - backend=BasicAer.get_backend("qasm_simulator"), + backend=BasicSimulator(), parameter_binds=parameter_values, ) @@ -923,7 +924,7 @@ def test_transpiling_multiple_parameterized_circuits(self): circuits = [qc1, qc2] - backend = BasicAer.get_backend("unitary_simulator") + backend = BasicSimulator() job = backend.run(transpile(circuits, backend), shots=512, parameter_binds=[{theta: 1}]) self.assertTrue(len(job.result().results), 2) @@ -1120,7 +1121,7 @@ def test_executing_parameterized_instruction_bound_early(self, target_type): bound_qc = getattr(unbound_qc, assign_fun)({theta: numpy.pi / 2}) shots = 1024 - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() job = backend.run(transpile(bound_qc, backend), shots=shots) self.assertDictAlmostEqual(job.result().get_counts(), {"1": shots}, 0.05 * shots) @@ -1156,7 +1157,7 @@ def test_execute_result_names(self): qc.measure(0, 0) plist = [{theta: i} for i in range(reps)] - simulator = BasicAer.get_backend("qasm_simulator") + simulator = BasicSimulator() result = simulator.run(transpile(qc, simulator), parameter_binds=plist).result() result_names = {res.name for res in result.results} self.assertEqual(reps, len(result_names)) diff --git a/test/python/circuit/test_piecewise_polynomial.py b/test/python/circuit/test_piecewise_polynomial.py index 639ad6f3ac6e..74b5387e56da 100644 --- a/test/python/circuit/test_piecewise_polynomial.py +++ b/test/python/circuit/test_piecewise_polynomial.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2020. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,11 +18,11 @@ from ddt import ddt, data, unpack from qiskit.test.base import QiskitTestCase -from qiskit import BasicAer, transpile from qiskit.circuit import QuantumCircuit from qiskit.circuit.library.arithmetic.piecewise_polynomial_pauli_rotations import ( PiecewisePolynomialPauliRotations, ) +from qiskit.quantum_info import Statevector @ddt @@ -37,8 +37,7 @@ def assertFunctionIsCorrect(self, function_circuit, reference): circuit.h(list(range(num_state_qubits))) circuit.append(function_circuit.to_instruction(), list(range(circuit.num_qubits))) - backend = BasicAer.get_backend("statevector_simulator") - statevector = backend.run(transpile(circuit, backend)).result().get_statevector() + statevector = Statevector(circuit) probabilities = defaultdict(float) for i, statevector_amplitude in enumerate(statevector): @@ -101,7 +100,7 @@ def pw_poly(x): with self.subTest(msg="missing number of state qubits"): with self.assertRaises(AttributeError): # no state qubits set - print(pw_polynomial_rotations.draw()) + _ = str(pw_polynomial_rotations.draw()) with self.subTest(msg="default setup, just setting number of state qubits"): pw_polynomial_rotations.num_state_qubits = 2 diff --git a/test/python/circuit/test_scheduled_circuit.py b/test/python/circuit/test_scheduled_circuit.py index 872a79e3e0f6..8de46cfb4458 100644 --- a/test/python/circuit/test_scheduled_circuit.py +++ b/test/python/circuit/test_scheduled_circuit.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2020. +# (C) Copyright IBM 2020, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -15,8 +15,9 @@ """Test scheduled circuit (quantum circuit with duration).""" from ddt import ddt, data from qiskit import QuantumCircuit, QiskitError -from qiskit import transpile, assemble, BasicAer +from qiskit import transpile, assemble from qiskit.circuit import Parameter +from qiskit.providers.basic_provider import BasicSimulator from qiskit.providers.fake_provider import FakeParis from qiskit.transpiler.exceptions import TranspilerError from qiskit.transpiler.instruction_durations import InstructionDurations @@ -34,7 +35,7 @@ def setUp(self): self.backend_without_dt = FakeParis() delattr(self.backend_without_dt.configuration(), "dt") self.dt = 2.2222222222222221e-10 - self.simulator_backend = BasicAer.get_backend("qasm_simulator") + self.simulator_backend = BasicSimulator() def test_schedule_circuit_when_backend_tells_dt(self): """dt is known to transpiler by backend""" diff --git a/test/python/circuit/test_squ.py b/test/python/circuit/test_squ.py index e80a17e20b68..4b9a886b6030 100644 --- a/test/python/circuit/test_squ.py +++ b/test/python/circuit/test_squ.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,11 +19,12 @@ import numpy as np from ddt import ddt from qiskit.quantum_info.random import random_unitary -from qiskit import BasicAer, QuantumCircuit, QuantumRegister +from qiskit import QuantumCircuit, QuantumRegister from qiskit.test import QiskitTestCase from qiskit.extensions.quantum_initializer.squ import SingleQubitUnitary from qiskit.compiler import transpile from qiskit.quantum_info.operators.predicates import matrix_equal +from qiskit.quantum_info import Operator squs = [ np.eye(2, 2), @@ -50,9 +51,7 @@ def test_squ(self, u, up_to_diagonal): # Decompose the gate qc = transpile(qc, basis_gates=["u1", "u3", "u2", "cx", "id"]) # Simulate the decomposed gate - simulator = BasicAer.get_backend("unitary_simulator") - result = simulator.run(qc).result() - unitary = result.get_unitary(qc) + unitary = Operator(qc).data if up_to_diagonal: with self.assertWarns(DeprecationWarning): squ = SingleQubitUnitary(u, up_to_diagonal=up_to_diagonal) diff --git a/test/python/circuit/test_uc.py b/test/python/circuit/test_uc.py index 9ac5da4471dd..48f493791b23 100644 --- a/test/python/circuit/test_uc.py +++ b/test/python/circuit/test_uc.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -25,7 +25,7 @@ from qiskit.circuit.library.generalized_gates import UCGate -from qiskit import QuantumCircuit, QuantumRegister, BasicAer +from qiskit import QuantumCircuit, QuantumRegister from qiskit.test import QiskitTestCase from qiskit.quantum_info.random import random_unitary from qiskit.compiler import transpile @@ -66,9 +66,7 @@ def test_ucg(self, squs, up_to_diagonal): # Decompose the gate qc = transpile(qc, basis_gates=["u1", "u3", "u2", "cx", "id"]) # Simulate the decomposed gate - simulator = BasicAer.get_backend("unitary_simulator") - result = simulator.run(qc).result() - unitary = result.get_unitary(qc) + unitary = Operator(qc).data if up_to_diagonal: ucg = UCGate(squs, up_to_diagonal=up_to_diagonal) unitary = np.dot(np.diagflat(ucg._get_diagonal()), unitary) @@ -85,9 +83,7 @@ def test_global_phase_ucg(self): uc = UCGate(gates, up_to_diagonal=False) qc.append(uc, q) - simulator = BasicAer.get_backend("unitary_simulator") - result = simulator.run(transpile(qc, simulator)).result() - unitary = result.get_unitary(qc) + unitary = Operator(qc).data unitary_desired = _get_ucg_matrix(gates) self.assertTrue(np.allclose(unitary_desired, unitary)) diff --git a/test/python/circuit/test_ucx_y_z.py b/test/python/circuit/test_ucx_y_z.py index 4450fc9e16d8..c213dd1154e6 100644 --- a/test/python/circuit/test_ucx_y_z.py +++ b/test/python/circuit/test_ucx_y_z.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019. +# (C) Copyright IBM 2019, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -19,10 +19,11 @@ import numpy as np from scipy.linalg import block_diag -from qiskit import BasicAer, QuantumCircuit, QuantumRegister +from qiskit import QuantumCircuit, QuantumRegister from qiskit.test import QiskitTestCase from qiskit.quantum_info.operators.predicates import matrix_equal +from qiskit.quantum_info import Operator from qiskit.compiler import transpile from qiskit.circuit.library import UCRXGate, UCRYGate, UCRZGate @@ -66,9 +67,7 @@ def test_ucy(self, use_method): # Decompose the gate qc = transpile(qc, basis_gates=["u1", "u3", "u2", "cx", "id"]) # Simulate the decomposed gate - simulator = BasicAer.get_backend("unitary_simulator") - result = simulator.run(qc).result() - unitary = result.get_unitary(qc) + unitary = Operator(qc) unitary_desired = _get_ucr_matrix(angles, rot_axis) self.assertTrue(matrix_equal(unitary_desired, unitary, ignore_phase=True)) diff --git a/test/python/classical_function_compiler/test_boolean_expression.py b/test/python/classical_function_compiler/test_boolean_expression.py index 12d5eebc422b..b5445af29dce 100644 --- a/test/python/classical_function_compiler/test_boolean_expression.py +++ b/test/python/classical_function_compiler/test_boolean_expression.py @@ -17,7 +17,8 @@ from ddt import ddt, unpack, data from qiskit.test.base import QiskitTestCase -from qiskit import BasicAer, transpile +from qiskit import transpile +from qiskit.providers.basic_provider import BasicSimulator from qiskit.utils.optionals import HAS_TWEEDLEDUM if HAS_TWEEDLEDUM: @@ -58,7 +59,7 @@ def test_synth(self, expression, expected): expr_circ.add_register(new_creg) expr_circ.measure(expression.num_qubits - 1, new_creg) - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() [result] = ( backend.run( transpile(expr_circ, backend), diff --git a/test/python/compiler/test_compiler.py b/test/python/compiler/test_compiler.py index da697c18ea81..d2d9a59c0000 100644 --- a/test/python/compiler/test_compiler.py +++ b/test/python/compiler/test_compiler.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -15,13 +15,13 @@ import os import unittest -from qiskit import BasicAer from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.transpiler import PassManager from qiskit.circuit.library import U1Gate, U2Gate from qiskit.compiler import transpile, assemble from qiskit.test import QiskitTestCase from qiskit.providers.fake_provider import FakeRueschlikon, FakeTenerife +from qiskit.providers.basic_provider import BasicSimulator from qiskit.qobj import QasmQobj @@ -31,14 +31,14 @@ class TestCompiler(QiskitTestCase): def setUp(self): super().setUp() self.seed_simulator = 42 - self.backend = BasicAer.get_backend("qasm_simulator") + self.backend = BasicSimulator() def test_example_multiple_compile(self): """Test a toy example compiling multiple circuits. Pass if the results are correct. """ - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() coupling_map = [[0, 1], [0, 2], [1, 2], [3, 2], [3, 4], [4, 2]] qr = QuantumRegister(5) @@ -80,7 +80,7 @@ def test_compile_coupling_map(self): If all correct should return data with the same stats. The circuit may be different. """ - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qr = QuantumRegister(3, "qr") cr = ClassicalRegister(3, "cr") @@ -113,7 +113,7 @@ def test_example_swap_bits(self): Uses the mapper. Pass if results are correct. """ - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() coupling_map = [ [0, 1], [0, 8], @@ -202,7 +202,7 @@ def test_parallel_compile(self): def test_no_conflict_backend_passmanager(self): """See: https://github.com/Qiskit/qiskit-terra/issues/5037""" - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qc = QuantumCircuit(2) qc.append(U1Gate(0), [0]) qc.measure_all() @@ -257,7 +257,7 @@ def test_compile_pass_manager(self): qc.append(U2Gate(3.14, 1.57), [qr[0]]) qc.barrier(qr) qc.measure(qr, cr) - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qrtrue = transpile(qc, backend, seed_transpiler=8) rtrue = backend.run(qrtrue, seed_simulator=42).result() qrfalse = PassManager().run(qc) @@ -309,12 +309,7 @@ def test_mapper_overoptimization(self): ) count1 = result1.result().get_counts() result2 = self.backend.run( - transpile( - circ, - backend=self.backend, - coupling_map=None, - seed_transpiler=8, - ), + transpile(circ, backend=self.backend, coupling_map=None, seed_transpiler=8), seed_simulator=self.seed_simulator, shots=shots, ) diff --git a/test/python/compiler/test_transpiler.py b/test/python/compiler/test_transpiler.py index 9a54bdc7da0b..bc6e73c151e9 100644 --- a/test/python/compiler/test_transpiler.py +++ b/test/python/compiler/test_transpiler.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2019. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -27,7 +27,14 @@ import rustworkx as rx from ddt import data, ddt, unpack -from qiskit import BasicAer, ClassicalRegister, QuantumCircuit, QuantumRegister, pulse, qasm3, qpy +from qiskit import ( + ClassicalRegister, + QuantumCircuit, + QuantumRegister, + pulse, + qasm3, + qpy, +) from qiskit.circuit import ( Clbit, ControlFlowOp, @@ -82,6 +89,7 @@ FakeVigo, ) from qiskit.providers.options import Options +from qiskit.providers.basic_provider import BasicSimulator from qiskit.pulse import InstructionScheduleMap from qiskit.quantum_info import Operator, random_unitary from qiskit.test import QiskitTestCase, slow_test @@ -140,7 +148,7 @@ def test_pass_manager_none(self): coupling_map = [[1, 0]] basis_gates = ["u1", "u2", "u3", "cx", "id"] - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() circuit2 = transpile( circuit, backend=backend, @@ -409,7 +417,7 @@ def test_transpile_bell(self): If all correct some should exists. """ - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qubit_reg = QuantumRegister(2, name="q") clbit_reg = ClassicalRegister(2, name="c") @@ -448,7 +456,7 @@ def test_transpile_one(self): Check that the top-level `transpile` function returns a single circuit.""" - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qubit_reg = QuantumRegister(2) clbit_reg = ClassicalRegister(2) @@ -465,7 +473,7 @@ def test_transpile_two(self): Check that the transpiler returns a list of two circuits. """ - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qubit_reg = QuantumRegister(2) clbit_reg = ClassicalRegister(2) @@ -491,7 +499,7 @@ def test_transpile_singleton(self): See https://github.com/Qiskit/qiskit-terra/issues/5260 """ - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() qubit_reg = QuantumRegister(2) clbit_reg = ClassicalRegister(2) @@ -681,7 +689,7 @@ def test_parameterized_circuit_for_simulator(self): theta = Parameter("theta") qc.rz(theta, qr[0]) - transpiled_qc = transpile(qc, backend=BasicAer.get_backend("qasm_simulator")) + transpiled_qc = transpile(qc, backend=BasicSimulator()) expected_qc = QuantumCircuit(qr) expected_qc.append(RZGate(theta), [qr[0]]) @@ -715,7 +723,7 @@ def test_parameter_expression_circuit_for_simulator(self): square = theta * theta qc.rz(square, qr[0]) - transpiled_qc = transpile(qc, backend=BasicAer.get_backend("qasm_simulator")) + transpiled_qc = transpile(qc, backend=BasicSimulator()) expected_qc = QuantumCircuit(qr) expected_qc.append(RZGate(square), [qr[0]]) diff --git a/test/python/opflow/opflow_test_case.py b/test/python/opflow/opflow_test_case.py index 142fb1db76b5..da30d8ce1dd8 100644 --- a/test/python/opflow/opflow_test_case.py +++ b/test/python/opflow/opflow_test_case.py @@ -23,8 +23,10 @@ def setUp(self): super().setUp() # ignore opflow msgs warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*opflow.*") + warnings.filterwarnings("ignore", category=DeprecationWarning, message=r".*basicaer.*") def tearDown(self): super().tearDown() # restore opflow msgs warnings.filterwarnings("error", category=DeprecationWarning, message=r".*opflow.*") + warnings.filterwarnings("error", category=DeprecationWarning, message=r".*basicaer.*") diff --git a/test/python/opflow/test_gradients.py b/test/python/opflow/test_gradients.py index b0fee1233bf5..3103d380bed3 100644 --- a/test/python/opflow/test_gradients.py +++ b/test/python/opflow/test_gradients.py @@ -20,7 +20,7 @@ import numpy as np from ddt import ddt, data, idata, unpack -from qiskit import QuantumCircuit, QuantumRegister, BasicAer +from qiskit import QuantumCircuit, QuantumRegister, BasicAer # pylint: disable=no-name-in-module from qiskit.test import slow_test from qiskit.utils import QuantumInstance from qiskit.exceptions import MissingOptionalLibraryError diff --git a/test/python/opflow/test_matrix_expectation.py b/test/python/opflow/test_matrix_expectation.py index 10448c3a64e1..fe4a7f1f6eef 100644 --- a/test/python/opflow/test_matrix_expectation.py +++ b/test/python/opflow/test_matrix_expectation.py @@ -35,7 +35,7 @@ MatrixExpectation, CircuitSampler, ) -from qiskit import BasicAer +from qiskit import BasicAer # pylint: disable=no-name-in-module class TestMatrixExpectation(QiskitOpflowTestCase): diff --git a/test/python/opflow/test_pauli_expectation.py b/test/python/opflow/test_pauli_expectation.py index 19821aab56da..e8f308b61859 100644 --- a/test/python/opflow/test_pauli_expectation.py +++ b/test/python/opflow/test_pauli_expectation.py @@ -19,7 +19,7 @@ import numpy as np -from qiskit import BasicAer +from qiskit import BasicAer # pylint: disable=no-name-in-module from qiskit.opflow import ( CX, CircuitSampler, diff --git a/test/python/opflow/test_state_construction.py b/test/python/opflow/test_state_construction.py index 97c24e94adda..9deaf08dfd14 100644 --- a/test/python/opflow/test_state_construction.py +++ b/test/python/opflow/test_state_construction.py @@ -16,7 +16,7 @@ from test.python.opflow import QiskitOpflowTestCase import numpy as np -from qiskit import QuantumCircuit, BasicAer +from qiskit import QuantumCircuit, BasicAer # pylint: disable=no-name-in-module from qiskit.circuit import ParameterVector from qiskit.quantum_info import Statevector diff --git a/test/python/primitives/test_backend_sampler.py b/test/python/primitives/test_backend_sampler.py index 84cfe691f7d6..aa7d7b421e2c 100644 --- a/test/python/primitives/test_backend_sampler.py +++ b/test/python/primitives/test_backend_sampler.py @@ -27,7 +27,7 @@ from qiskit.primitives import BackendSampler, SamplerResult from qiskit.providers import JobStatus, JobV1 from qiskit.providers.fake_provider import FakeNairobi, FakeNairobiV2 -from qiskit.providers.basicaer import QasmSimulatorPy +from qiskit.providers.basic_provider import BasicSimulator from qiskit.test import QiskitTestCase from qiskit.transpiler import PassManager from qiskit.utils import optionals @@ -130,7 +130,6 @@ def test_sample_run_multiple_circuits(self, backend): bell = self._circuit[1] sampler = BackendSampler(backend=backend) result = sampler.run([bell, bell, bell]).result() - # print([q.binary_probabilities() for q in result.quasi_dists]) self._compare_probs(result.quasi_dists[0], self._target[1]) self._compare_probs(result.quasi_dists[1], self._target[1]) self._compare_probs(result.quasi_dists[2], self._target[1]) @@ -388,7 +387,7 @@ def test_outcome_bitstring_size(self): # We need a noise-free backend here (shot noise is fine) to ensure that # the only bit string measured is "0001". With device noise, it could happen that # strings with a leading 1 are measured and then the truncation cannot be tested. - sampler = BackendSampler(backend=QasmSimulatorPy()) + sampler = BackendSampler(backend=BasicSimulator()) result = sampler.run(qc).result() probs = result.quasi_dists[0].binary_probabilities() diff --git a/test/python/providers/basic_provider/__init__.py b/test/python/providers/basic_provider/__init__.py new file mode 100644 index 000000000000..0c8b92822219 --- /dev/null +++ b/test/python/providers/basic_provider/__init__.py @@ -0,0 +1,32 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Qiskit BasicProvider integration tests.""" + +from qiskit import transpile + + +class BasicProviderBackendTestMixin: + """Test mixins for BasicProvider backend tests.""" + + def test_configuration(self): + """Test backend.configuration().""" + configuration = self.backend.configuration() + return configuration + + def test_run_circuit(self): + """Test running a single circuit.""" + transpiled_qc = transpile(self.circuit, self.backend) + job = self.backend.run(transpiled_qc) + result = job.result() + self.assertEqual(result.success, True) + return result diff --git a/test/python/providers/basic_provider/test_basic_provider_backends.py b/test/python/providers/basic_provider/test_basic_provider_backends.py new file mode 100644 index 000000000000..38d9d7ca557b --- /dev/null +++ b/test/python/providers/basic_provider/test_basic_provider_backends.py @@ -0,0 +1,44 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""BasicProvider Backends Test.""" + +from qiskit.providers.basic_provider.basic_provider import BasicProvider +from qiskit.providers.exceptions import QiskitBackendNotFoundError +from qiskit.test import QiskitTestCase + + +class TestBasicProviderBackends(QiskitTestCase): + """Qiskit BasicProvider Backends (Object) Tests.""" + + def setUp(self): + super().setUp() + self.provider = BasicProvider() + self.backend_name = "basic_simulator" + + def test_backends(self): + """Test the provider has backends.""" + backends = self.provider.backends() + self.assertTrue(len(backends) > 0) + + def test_get_backend(self): + """Test getting a backend from the provider.""" + backend = self.provider.get_backend(name=self.backend_name) + self.assertEqual(backend.name, self.backend_name) + + def test_aliases_fail(self): + """Test a failing backend lookup.""" + self.assertRaises(QiskitBackendNotFoundError, BasicProvider().get_backend, "bad_name") + + def test_aliases_return_empty_list(self): + """Test backends() return an empty list if name is unknown.""" + self.assertEqual(BasicProvider().backends("bad_name"), []) diff --git a/test/python/providers/basic_provider/test_basic_provider_integration.py b/test/python/providers/basic_provider/test_basic_provider_integration.py new file mode 100644 index 000000000000..db831514e2fd --- /dev/null +++ b/test/python/providers/basic_provider/test_basic_provider_integration.py @@ -0,0 +1,82 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""BasicProvider provider integration tests.""" + +import unittest + +from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit +from qiskit import transpile +from qiskit.result import Result +from qiskit.providers.basic_provider import BasicProviderError, BasicSimulator +from qiskit.test import QiskitTestCase + + +class TestBasicProviderIntegration(QiskitTestCase): + """Qiskit BasicProvider simulator integration tests.""" + + def setUp(self): + super().setUp() + qr = QuantumRegister(1) + cr = ClassicalRegister(1) + self._qc1 = QuantumCircuit(qr, cr, name="qc1") + self._qc2 = QuantumCircuit(qr, cr, name="qc2") + self._qc1.measure(qr[0], cr[0]) + self.backend = BasicSimulator() + self._result1 = self.backend.run(transpile(self._qc1)).result() + + def test_builtin_simulator_result_fields(self): + """Test components of a result from a local simulator.""" + + self.assertEqual("basic_simulator", self._result1.backend_name) + self.assertIsInstance(self._result1.job_id, str) + self.assertEqual(self._result1.status, "COMPLETED") + self.assertEqual(self._result1.results[0].status, "DONE") + + def test_basicprovider_execute(self): + """Test Compiler and run.""" + qubit_reg = QuantumRegister(2, name="q") + clbit_reg = ClassicalRegister(2, name="c") + qc = QuantumCircuit(qubit_reg, clbit_reg, name="bell") + qc.h(qubit_reg[0]) + qc.cx(qubit_reg[0], qubit_reg[1]) + qc.measure(qubit_reg, clbit_reg) + + job = self.backend.run(transpile(qc)) + result = job.result() + self.assertIsInstance(result, Result) + + def test_basicprovider_execute_two(self): + """Test Compiler and run.""" + qubit_reg = QuantumRegister(2, name="q") + clbit_reg = ClassicalRegister(2, name="c") + qc = QuantumCircuit(qubit_reg, clbit_reg, name="bell") + qc.h(qubit_reg[0]) + qc.cx(qubit_reg[0], qubit_reg[1]) + qc.measure(qubit_reg, clbit_reg) + qc_extra = QuantumCircuit(qubit_reg, clbit_reg, name="extra") + qc_extra.measure(qubit_reg, clbit_reg) + job = self.backend.run(transpile([qc, qc_extra])) + result = job.result() + self.assertIsInstance(result, Result) + + def test_basicprovider_num_qubits(self): + """Test BasicProviderError is raised if num_qubits too large to simulate.""" + qc = QuantumCircuit(50, 1) + qc.x(0) + qc.measure(0, 0) + with self.assertRaises(BasicProviderError): + self.backend.run(qc) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/test/python/providers/basic_provider/test_basic_simulator.py b/test/python/providers/basic_provider/test_basic_simulator.py new file mode 100644 index 000000000000..6e0f4e470854 --- /dev/null +++ b/test/python/providers/basic_provider/test_basic_simulator.py @@ -0,0 +1,369 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Test basic simulator.""" + +import os +import unittest + +import numpy as np + +from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister +from qiskit.compiler import transpile, assemble +from qiskit.providers.basic_provider import BasicSimulator +from qiskit.test import QiskitTestCase +from qiskit.qasm2 import dumps + +from . import BasicProviderBackendTestMixin + + +class TestBasicSimulator(QiskitTestCase, BasicProviderBackendTestMixin): + """Test the basic provider simulator.""" + + def setUp(self): + super().setUp() + self.backend = BasicSimulator() + bell = QuantumCircuit(2, 2) + bell.h(0) + bell.cx(0, 1) + bell.measure([0, 1], [0, 1]) + self.circuit = bell + + self.seed = 88 + self.backend = BasicSimulator() + qasm_dir = os.path.join( + os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "qasm" + ) + qasm_filename = os.path.join(qasm_dir, "example.qasm") + qcirc = QuantumCircuit.from_qasm_file(qasm_filename) + qcirc.name = "test" + self.transpiled_circuit = transpile(qcirc, backend=self.backend) + self.qobj = assemble(self.transpiled_circuit, shots=1000, seed_simulator=self.seed) + + def test_basic_simulator_single_shot(self): + """Test single shot run.""" + shots = 1 + result = self.backend.run( + self.transpiled_circuit, shots=shots, seed_simulator=self.seed + ).result() + self.assertEqual(result.success, True) + + def test_measure_sampler_repeated_qubits(self): + """Test measure sampler if qubits measured more than once.""" + shots = 100 + qr = QuantumRegister(2, "qr") + cr = ClassicalRegister(4, "cr") + circuit = QuantumCircuit(qr, cr) + circuit.x(qr[1]) + circuit.measure(qr[0], cr[0]) + circuit.measure(qr[1], cr[1]) + circuit.measure(qr[1], cr[2]) + circuit.measure(qr[0], cr[3]) + target = {"0110": shots} + job = self.backend.run( + transpile(circuit, self.backend), shots=shots, seed_simulator=self.seed + ) + result = job.result() + counts = result.get_counts(0) + self.assertEqual(counts, target) + + def test_measure_sampler_single_qubit(self): + """Test measure sampler if single-qubit is measured.""" + shots = 100 + num_qubits = 5 + qr = QuantumRegister(num_qubits, "qr") + cr = ClassicalRegister(1, "cr") + + for qubit in range(num_qubits): + circuit = QuantumCircuit(qr, cr) + circuit.x(qr[qubit]) + circuit.measure(qr[qubit], cr[0]) + target = {"1": shots} + job = self.backend.run( + transpile(circuit, self.backend), shots=shots, seed_simulator=self.seed + ) + result = job.result() + counts = result.get_counts(0) + self.assertEqual(counts, target) + + def test_measure_sampler_partial_qubit(self): + """Test measure sampler if single-qubit is measured.""" + shots = 100 + num_qubits = 5 + qr = QuantumRegister(num_qubits, "qr") + cr = ClassicalRegister(4, "cr") + + # ░ ░ ░ ┌─┐ ░ + # qr_0: ──────░─────░─────░─┤M├─░──── + # ┌───┐ ░ ░ ┌─┐ ░ └╥┘ ░ + # qr_1: ┤ X ├─░─────░─┤M├─░──╫──░──── + # └───┘ ░ ░ └╥┘ ░ ║ ░ + # qr_2: ──────░─────░──╫──░──╫──░──── + # ┌───┐ ░ ┌─┐ ░ ║ ░ ║ ░ ┌─┐ + # qr_3: ┤ X ├─░─┤M├─░──╫──░──╫──░─┤M├ + # └───┘ ░ └╥┘ ░ ║ ░ ║ ░ └╥┘ + # qr_4: ──────░──╫──░──╫──░──╫──░──╫─ + # ░ ║ ░ ║ ░ ║ ░ ║ + # cr: 4/═════════╩═════╩═════╩═════╩═ + # 1 0 2 3 + circuit = QuantumCircuit(qr, cr) + circuit.x(qr[3]) + circuit.x(qr[1]) + circuit.barrier(qr) + circuit.measure(qr[3], cr[1]) + circuit.barrier(qr) + circuit.measure(qr[1], cr[0]) + circuit.barrier(qr) + circuit.measure(qr[0], cr[2]) + circuit.barrier(qr) + circuit.measure(qr[3], cr[3]) + target = {"1011": shots} + job = self.backend.run( + transpile(circuit, self.backend), shots=shots, seed_simulator=self.seed + ) + result = job.result() + counts = result.get_counts(0) + self.assertEqual(counts, target) + + def test_basic_simulator(self): + """Test data counts output for single circuit run against reference.""" + result = self.backend.run( + self.transpiled_circuit, shots=1000, seed_simulator=self.seed + ).result() + shots = 1024 + threshold = 0.04 * shots + counts = result.get_counts("test") + target = { + "100 100": shots / 8, + "011 011": shots / 8, + "101 101": shots / 8, + "111 111": shots / 8, + "000 000": shots / 8, + "010 010": shots / 8, + "110 110": shots / 8, + "001 001": shots / 8, + } + self.assertDictAlmostEqual(counts, target, threshold) + + def test_if_statement(self): + """Test if statements.""" + shots = 100 + qr = QuantumRegister(3, "qr") + cr = ClassicalRegister(3, "cr") + + # ┌───┐┌─┐ ┌─┐ + # qr_0: ┤ X ├┤M├──────────┤M├────── + # ├───┤└╥┘┌─┐ └╥┘┌─┐ + # qr_1: ┤ X ├─╫─┤M├────────╫─┤M├─── + # └───┘ ║ └╥┘ ┌───┐ ║ └╥┘┌─┐ + # qr_2: ──────╫──╫──┤ X ├──╫──╫─┤M├ + # ║ ║ └─╥─┘ ║ ║ └╥┘ + # ║ ║ ┌──╨──┐ ║ ║ ║ + # cr: 3/══════╩══╩═╡ 0x3 ╞═╩══╩══╩═ + # 0 1 └─────┘ 0 1 2 + circuit_if_true = QuantumCircuit(qr, cr) + circuit_if_true.x(qr[0]) + circuit_if_true.x(qr[1]) + circuit_if_true.measure(qr[0], cr[0]) + circuit_if_true.measure(qr[1], cr[1]) + circuit_if_true.x(qr[2]).c_if(cr, 0x3) + circuit_if_true.measure(qr[0], cr[0]) + circuit_if_true.measure(qr[1], cr[1]) + circuit_if_true.measure(qr[2], cr[2]) + + # ┌───┐┌─┐ ┌─┐ + # qr_0: ┤ X ├┤M├───────┤M├────── + # └┬─┬┘└╥┘ └╥┘┌─┐ + # qr_1: ─┤M├──╫─────────╫─┤M├─── + # └╥┘ ║ ┌───┐ ║ └╥┘┌─┐ + # qr_2: ──╫───╫──┤ X ├──╫──╫─┤M├ + # ║ ║ └─╥─┘ ║ ║ └╥┘ + # ║ ║ ┌──╨──┐ ║ ║ ║ + # cr: 3/══╩═══╩═╡ 0x3 ╞═╩══╩══╩═ + # 1 0 └─────┘ 0 1 2 + circuit_if_false = QuantumCircuit(qr, cr) + circuit_if_false.x(qr[0]) + circuit_if_false.measure(qr[0], cr[0]) + circuit_if_false.measure(qr[1], cr[1]) + circuit_if_false.x(qr[2]).c_if(cr, 0x3) + circuit_if_false.measure(qr[0], cr[0]) + circuit_if_false.measure(qr[1], cr[1]) + circuit_if_false.measure(qr[2], cr[2]) + job = self.backend.run( + transpile([circuit_if_true, circuit_if_false], self.backend), + shots=shots, + seed_simulator=self.seed, + ) + result = job.result() + counts_if_true = result.get_counts(circuit_if_true) + counts_if_false = result.get_counts(circuit_if_false) + self.assertEqual(counts_if_true, {"111": 100}) + self.assertEqual(counts_if_false, {"001": 100}) + + def test_bit_cif_crossaffect(self): + """Test if bits in a classical register other than + the single conditional bit affect the conditioned operation.""" + # ┌───┐ ┌─┐ + # q0_0: ────────┤ H ├──────────┤M├ + # ┌───┐ └─╥─┘ ┌─┐ └╥┘ + # q0_1: ┤ X ├─────╫──────┤M├────╫─ + # ├───┤ ║ └╥┘┌─┐ ║ + # q0_2: ┤ X ├─────╫───────╫─┤M├─╫─ + # └───┘┌────╨─────┐ ║ └╥┘ ║ + # c0: 3/═════╡ c0_0=0x1 ╞═╩══╩══╬═ + # └──────────┘ 1 2 ║ + # c1: 1/════════════════════════╩═ + # 0 + shots = 100 + qr = QuantumRegister(3) + cr = ClassicalRegister(3) + cr1 = ClassicalRegister(1) + circuit = QuantumCircuit(qr, cr, cr1) + circuit.x([qr[1], qr[2]]) + circuit.measure(qr[1], cr[1]) + circuit.measure(qr[2], cr[2]) + circuit.h(qr[0]).c_if(cr[0], True) + circuit.measure(qr[0], cr1[0]) + job = self.backend.run( + transpile(circuit, self.backend), shots=shots, seed_simulator=self.seed + ) + result = job.result().get_counts() + target = {"0 110": 100} + self.assertEqual(result, target) + + def test_teleport(self): + """Test teleportation as in tutorials""" + # ┌─────────┐ ┌───┐ ░ ┌─┐ + # qr_0: ┤ Ry(π/4) ├───────■──┤ H ├─░─┤M├──────────────────── + # └──┬───┬──┘ ┌─┴─┐└───┘ ░ └╥┘┌─┐ + # qr_1: ───┤ H ├─────■──┤ X ├──────░──╫─┤M├───────────────── + # └───┘ ┌─┴─┐└───┘ ░ ║ └╥┘ ┌───┐ ┌───┐ ┌─┐ + # qr_2: ───────────┤ X ├───────────░──╫──╫──┤ Z ├──┤ X ├─┤M├ + # └───┘ ░ ║ ║ └─╥─┘ └─╥─┘ └╥┘ + # ║ ║ ┌──╨──┐ ║ ║ + # cr0: 1/═════════════════════════════╩══╬═╡ 0x1 ╞═══╬════╬═ + # 0 ║ └─────┘┌──╨──┐ ║ + # cr1: 1/════════════════════════════════╩════════╡ 0x1 ╞═╬═ + # 0 └─────┘ ║ + # cr2: 1/═════════════════════════════════════════════════╩═ + # 0 + self.log.info("test_teleport") + pi = np.pi + shots = 4000 + qr = QuantumRegister(3, "qr") + cr0 = ClassicalRegister(1, "cr0") + cr1 = ClassicalRegister(1, "cr1") + cr2 = ClassicalRegister(1, "cr2") + circuit = QuantumCircuit(qr, cr0, cr1, cr2, name="teleport") + circuit.h(qr[1]) + circuit.cx(qr[1], qr[2]) + circuit.ry(pi / 4, qr[0]) + circuit.cx(qr[0], qr[1]) + circuit.h(qr[0]) + circuit.barrier(qr) + circuit.measure(qr[0], cr0[0]) + circuit.measure(qr[1], cr1[0]) + circuit.z(qr[2]).c_if(cr0, 1) + circuit.x(qr[2]).c_if(cr1, 1) + circuit.measure(qr[2], cr2[0]) + job = self.backend.run( + transpile(circuit, self.backend), shots=shots, seed_simulator=self.seed + ) + results = job.result() + data = results.get_counts("teleport") + alice = { + "00": data["0 0 0"] + data["1 0 0"], + "01": data["0 1 0"] + data["1 1 0"], + "10": data["0 0 1"] + data["1 0 1"], + "11": data["0 1 1"] + data["1 1 1"], + } + bob = { + "0": data["0 0 0"] + data["0 1 0"] + data["0 0 1"] + data["0 1 1"], + "1": data["1 0 0"] + data["1 1 0"] + data["1 0 1"] + data["1 1 1"], + } + self.log.info("test_teleport: circuit:") + self.log.info(dumps(circuit)) + self.log.info("test_teleport: data %s", data) + self.log.info("test_teleport: alice %s", alice) + self.log.info("test_teleport: bob %s", bob) + alice_ratio = 1 / np.tan(pi / 8) ** 2 + bob_ratio = bob["0"] / float(bob["1"]) + error = abs(alice_ratio - bob_ratio) / alice_ratio + self.log.info("test_teleport: relative error = %s", error) + self.assertLess(error, 0.05) + + def test_memory(self): + """Test memory.""" + # ┌───┐ ┌─┐ + # qr_0: ┤ H ├──■─────┤M├─── + # └───┘┌─┴─┐ └╥┘┌─┐ + # qr_1: ─────┤ X ├────╫─┤M├ + # └┬─┬┘ ║ └╥┘ + # qr_2: ──────┤M├─────╫──╫─ + # ┌───┐ └╥┘ ┌─┐ ║ ║ + # qr_3: ┤ X ├──╫──┤M├─╫──╫─ + # └───┘ ║ └╥┘ ║ ║ + # cr0: 2/══════╬═══╬══╩══╩═ + # ║ ║ 0 1 + # ║ ║ + # cr1: 2/══════╩═══╩═══════ + # 0 1 + qr = QuantumRegister(4, "qr") + cr0 = ClassicalRegister(2, "cr0") + cr1 = ClassicalRegister(2, "cr1") + circ = QuantumCircuit(qr, cr0, cr1) + circ.h(qr[0]) + circ.cx(qr[0], qr[1]) + circ.x(qr[3]) + circ.measure(qr[0], cr0[0]) + circ.measure(qr[1], cr0[1]) + circ.measure(qr[2], cr1[0]) + circ.measure(qr[3], cr1[1]) + + shots = 50 + job = self.backend.run( + transpile(circ, self.backend), shots=shots, seed_simulator=self.seed, memory=True + ) + result = job.result() + memory = result.get_memory() + self.assertEqual(len(memory), shots) + for mem in memory: + self.assertIn(mem, ["10 00", "10 11"]) + + def test_unitary(self): + """Test unitary gate instruction""" + max_qubits = 4 + x_mat = np.array([[0, 1], [1, 0]]) + # Test 1 to max_qubits for random n-qubit unitary gate + for i in range(max_qubits): + num_qubits = i + 1 + # Apply X gate to all qubits + multi_x = x_mat + for _ in range(i): + multi_x = np.kron(multi_x, x_mat) + # Target counts + shots = 1024 + target_counts = {num_qubits * "1": shots} + # Test circuit + qr = QuantumRegister(num_qubits, "qr") + cr = ClassicalRegister(num_qubits, "cr") + circuit = QuantumCircuit(qr, cr) + circuit.unitary(multi_x, qr) + circuit.measure(qr, cr) + job = self.backend.run(transpile(circuit, self.backend), shots=shots) + result = job.result() + counts = result.get_counts(0) + self.assertEqual(counts, target_counts) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/python/providers/basic_provider/test_multi_registers_convention.py b/test/python/providers/basic_provider/test_multi_registers_convention.py new file mode 100644 index 000000000000..a3dddbe0f5aa --- /dev/null +++ b/test/python/providers/basic_provider/test_multi_registers_convention.py @@ -0,0 +1,46 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017, 2023. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Test executing multiple-register circuits on BasicProvider.""" + +from qiskit import transpile +from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister +from qiskit.providers.basic_provider import BasicProvider +from qiskit.test import QiskitTestCase + + +class TestCircuitMultiRegs(QiskitTestCase): + """QuantumCircuit Qasm tests.""" + + def test_circuit_multi(self): + """Test circuit multi regs declared at start.""" + qreg0 = QuantumRegister(2, "q0") + creg0 = ClassicalRegister(2, "c0") + qreg1 = QuantumRegister(2, "q1") + creg1 = ClassicalRegister(2, "c1") + circ = QuantumCircuit(qreg0, qreg1, creg0, creg1) + circ.x(qreg0[1]) + circ.x(qreg1[0]) + + meas = QuantumCircuit(qreg0, qreg1, creg0, creg1) + meas.measure(qreg0, creg0) + meas.measure(qreg1, creg1) + + qc = circ.compose(meas) + + backend_sim = BasicProvider().get_backend("basic_simulator") + + result = backend_sim.run(transpile(qc, seed_transpiler=34342)).result() + counts = result.get_counts(qc) + target = {"01 10": 1024} + + self.assertEqual(counts, target) diff --git a/test/python/qobj/test_qobj_identifiers.py b/test/python/qobj/test_qobj_identifiers.py index c4624d17dd0e..0fd695c7e56b 100644 --- a/test/python/qobj/test_qobj_identifiers.py +++ b/test/python/qobj/test_qobj_identifiers.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2018. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -22,7 +22,7 @@ class TestQobjIdentifiers(QiskitTestCase): - """Check the Qobj compiled for different backends create names properly""" + """Check the Qobj create names properly""" def setUp(self): super().setUp() @@ -35,19 +35,7 @@ def setUp(self): self.cr_name = cr.name self.circuits = [qc] - def test_builtin_qasm_simulator_py(self): - qobj = assemble(self.circuits) - exp = qobj.experiments[0] - self.assertIn(self.qr_name, (x[0] for x in exp.header.qubit_labels)) - self.assertIn(self.cr_name, (x[0] for x in exp.header.clbit_labels)) - - def test_builtin_qasm_simulator(self): - qobj = assemble(self.circuits) - exp = qobj.experiments[0] - self.assertIn(self.qr_name, (x[0] for x in exp.header.qubit_labels)) - self.assertIn(self.cr_name, (x[0] for x in exp.header.clbit_labels)) - - def test_builtin_unitary_simulator_py(self): + def test_qobj_identifiers(self): qobj = assemble(self.circuits) exp = qobj.experiments[0] self.assertIn(self.qr_name, (x[0] for x in exp.header.qubit_labels)) diff --git a/test/python/quantum_info/states/test_statevector.py b/test/python/quantum_info/states/test_statevector.py index a7228d6bf5d2..34d3df5e3967 100644 --- a/test/python/quantum_info/states/test_statevector.py +++ b/test/python/quantum_info/states/test_statevector.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2019. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -25,7 +25,7 @@ from qiskit import QuantumRegister, QuantumCircuit from qiskit import transpile from qiskit.circuit.library import HGate, QFT, GlobalPhaseGate -from qiskit.providers.basicaer import QasmSimulatorPy +from qiskit.providers.basic_provider import BasicSimulator from qiskit.utils import optionals from qiskit.quantum_info.random import random_unitary, random_statevector, random_pauli @@ -1168,7 +1168,7 @@ def test_probabilities_qargs(self, qargs): probs = state.probabilities(qargs) # Estimate target probs from simulator measurement - sim = QasmSimulatorPy() + sim = BasicSimulator() shots = 5000 seed = 100 circ = transpile(state_circ, sim) diff --git a/test/python/quantum_info/test_analyzation.py b/test/python/quantum_info/test_analyzation.py index fe44862402cb..332b8c1461c3 100644 --- a/test/python/quantum_info/test_analyzation.py +++ b/test/python/quantum_info/test_analyzation.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2018. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -14,7 +14,8 @@ import unittest -from qiskit import BasicAer, QuantumCircuit, ClassicalRegister, QuantumRegister, transpile +from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, transpile +from qiskit.providers.basic_provider import BasicSimulator from qiskit.quantum_info.analysis.average import average_data from qiskit.quantum_info.analysis.make_observable import make_dict_observable from qiskit.quantum_info.analysis import hellinger_fidelity @@ -34,7 +35,7 @@ def test_average_data_dict_observable(self): qc.measure(qr[0], cr[0]) qc.measure(qr[1], cr[1]) shots = 10000 - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() result = backend.run(qc, shots=shots).result() counts = result.get_counts(qc) observable = {"00": 1, "11": 1, "01": -1, "10": -1} @@ -59,7 +60,7 @@ def test_average_data_list_observable(self): qc.measure(qr[1], cr[1]) qc.measure(qr[2], cr[2]) shots = 10000 - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() result = backend.run(qc, shots=shots).result() counts = result.get_counts(qc) observable = [1, -1, -1, 1, -1, 1, 1, -1] @@ -85,7 +86,7 @@ def test_average_data_matrix_observable(self): qc.measure(qr[0], cr[0]) qc.measure(qr[1], cr[1]) shots = 10000 - backend = BasicAer.get_backend("qasm_simulator") + backend = BasicSimulator() result = backend.run(qc, shots=shots).result() counts = result.get_counts(qc) observable = [[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]] @@ -132,7 +133,7 @@ def test_hellinger_fidelity_same(self): qc.cx(1, 0) qc.measure(range(5), range(5)) - sim = BasicAer.get_backend("qasm_simulator") + sim = BasicSimulator() res = sim.run(qc).result() @@ -185,7 +186,7 @@ def test_hellinger_fidelity_no_overlap(self): qc2.cx(1, 0) qc2.measure(range(5), range(5)) - sim = BasicAer.get_backend("qasm_simulator") + sim = BasicSimulator() res1 = sim.run(qc).result() res2 = sim.run(transpile(qc2, sim)).result() diff --git a/test/python/synthesis/test_local_invariance.py b/test/python/synthesis/test_local_invariance.py index fa881ef8d157..8219782992db 100644 --- a/test/python/synthesis/test_local_invariance.py +++ b/test/python/synthesis/test_local_invariance.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2019. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -16,10 +16,10 @@ import unittest from numpy.testing import assert_allclose -from qiskit import QuantumCircuit, QuantumRegister, transpile +from qiskit.circuit import QuantumCircuit, QuantumRegister from qiskit.test import QiskitTestCase -from qiskit.providers.basicaer import UnitarySimulatorPy from qiskit.synthesis.two_qubit.local_invariance import two_qubit_local_invariants +from qiskit.quantum_info import Operator class TestLocalInvariance(QiskitTestCase): @@ -29,18 +29,17 @@ def test_2q_local_invariance_simple(self): """Check the local invariance parameters for known simple cases. """ - sim = UnitarySimulatorPy() qr = QuantumRegister(2, name="q") qc = QuantumCircuit(qr) - U = sim.run(qc).result().get_unitary() + U = Operator(qc) vec = two_qubit_local_invariants(U) assert_allclose(vec, [1, 0, 3]) qr = QuantumRegister(2, name="q") qc = QuantumCircuit(qr) qc.cx(qr[1], qr[0]) - U = sim.run(qc).result().get_unitary() + U = Operator(qc) vec = two_qubit_local_invariants(U) assert_allclose(vec, [0, 0, 1]) @@ -48,14 +47,15 @@ def test_2q_local_invariance_simple(self): qc = QuantumCircuit(qr) qc.cx(qr[1], qr[0]) qc.cx(qr[0], qr[1]) - U = sim.run(qc).result().get_unitary() + U = Operator(qc) vec = two_qubit_local_invariants(U) assert_allclose(vec, [0, 0, -1]) qr = QuantumRegister(2, name="q") qc = QuantumCircuit(qr) qc.swap(qr[1], qr[0]) - U = sim.run(transpile(qc, sim)).result().get_unitary() + U = Operator(qc) + vec = two_qubit_local_invariants(U) assert_allclose(vec, [-1, 0, -3]) diff --git a/test/python/tools/monitor/test_job_monitor.py b/test/python/tools/monitor/test_job_monitor.py index 95a93e65ea76..bc1bca0b32f3 100644 --- a/test/python/tools/monitor/test_job_monitor.py +++ b/test/python/tools/monitor/test_job_monitor.py @@ -15,7 +15,7 @@ import io import unittest from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit -from qiskit import BasicAer +from qiskit import BasicAer # pylint: disable=no-name-in-module from qiskit import execute from qiskit.tools.monitor import job_monitor from qiskit.test import QiskitTestCase diff --git a/test/python/transpiler/test_mappers.py b/test/python/transpiler/test_mappers.py index 4c56b9dedb53..95dc84d9975f 100644 --- a/test/python/transpiler/test_mappers.py +++ b/test/python/transpiler/test_mappers.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2018. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -73,7 +73,8 @@ def test_a_common_test(self): import sys from qiskit import execute -from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit, BasicAer +from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit +from qiskit.providers.basic_provider import BasicSimulator from qiskit.transpiler import PassManager from qiskit.transpiler.passes import BasicSwap, LookaheadSwap, StochasticSwap, SabreSwap from qiskit.transpiler.passes import SetLayout @@ -110,7 +111,7 @@ def create_passmanager(self, coupling_map, initial_layout=None): def create_backend(self): """Returns a Backend.""" - return BasicAer.get_backend("qasm_simulator") + return BasicSimulator() def generate_ground_truth(self, transpiled_result, filename): """Generates the expected result into a file. diff --git a/test/python/transpiler/test_naming_transpiled_circuits.py b/test/python/transpiler/test_naming_transpiled_circuits.py index ce6f6e6e50d9..6385e9fca180 100644 --- a/test/python/transpiler/test_naming_transpiled_circuits.py +++ b/test/python/transpiler/test_naming_transpiled_circuits.py @@ -15,7 +15,7 @@ import unittest from qiskit.circuit import QuantumCircuit from qiskit.compiler import transpile -from qiskit import BasicAer +from qiskit.providers.basic_provider import BasicSimulator from qiskit.transpiler.exceptions import TranspilerError from qiskit.test import QiskitTestCase @@ -26,7 +26,7 @@ class TestNamingTranspiledCircuits(QiskitTestCase): def setUp(self): super().setUp() self.basis_gates = ["u1", "u2", "u3", "cx"] - self.backend = BasicAer.get_backend("qasm_simulator") + self.backend = BasicSimulator() self.circuit0 = QuantumCircuit(name="circuit0") self.circuit1 = QuantumCircuit(name="circuit1") diff --git a/test/python/transpiler/test_passmanager_config.py b/test/python/transpiler/test_passmanager_config.py index 96721e1884a3..02e2d886f2ad 100644 --- a/test/python/transpiler/test_passmanager_config.py +++ b/test/python/transpiler/test_passmanager_config.py @@ -82,11 +82,12 @@ def test_from_backendv1_inst_map_is_none(self): def test_simulator_backend_v1(self): """Test that from_backend() works with backendv1 simulator.""" - backend = QasmSimulatorPy() - config = PassManagerConfig.from_backend(backend) - self.assertIsInstance(config, PassManagerConfig) - self.assertIsNone(config.inst_map) - self.assertIsNone(config.coupling_map) + with self.assertRaises(DeprecationWarning): + backend = QasmSimulatorPy() + config = PassManagerConfig.from_backend(backend) + self.assertIsInstance(config, PassManagerConfig) + self.assertIsNone(config.inst_map) + self.assertIsNone(config.coupling_map) def test_invalid_user_option(self): """Test from_backend() with an invalid user option.""" diff --git a/test/python/transpiler/test_stage_plugin.py b/test/python/transpiler/test_stage_plugin.py index 1279fae467e8..54dd56e1ebd9 100644 --- a/test/python/transpiler/test_stage_plugin.py +++ b/test/python/transpiler/test_stage_plugin.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2022. +# (C) Copyright IBM 2022, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -29,7 +29,7 @@ passmanager_stage_plugins, ) from qiskit.transpiler.exceptions import TranspilerError -from qiskit.providers.basicaer import QasmSimulatorPy +from qiskit.providers.basic_provider import BasicSimulator class TestStagePassManagerPlugin(QiskitTestCase): @@ -110,6 +110,6 @@ def test_routing_plugins(self, optimization_level, routing_method): optimization_level=optimization_level, routing_method=routing_method, ) - backend = QasmSimulatorPy() + backend = BasicSimulator() counts = backend.run(tqc, shots=1000).result().get_counts() self.assertDictAlmostEqual(counts, {"0000": 500, "1111": 500}, delta=100) diff --git a/test/randomized/test_synthesis.py b/test/randomized/test_synthesis.py index 6bc95204d1d1..9f0619a0c296 100644 --- a/test/randomized/test_synthesis.py +++ b/test/randomized/test_synthesis.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2017, 2019. +# (C) Copyright IBM 2017, 2023. # # This code is licensed under the Apache License, Version 2.0. You may # obtain a copy of this license in the LICENSE.txt file in the root directory @@ -18,7 +18,7 @@ from qiskit.circuit import QuantumCircuit, QuantumRegister from qiskit.circuit.library import UnitaryGate -from qiskit.providers.basicaer import UnitarySimulatorPy +from qiskit.quantum_info import Operator from qiskit.quantum_info.random import random_unitary from qiskit.synthesis.two_qubit.two_qubit_decompose import ( two_qubit_cnot_decompose, @@ -63,8 +63,8 @@ def test_exact_supercontrolled_decompose_random(self, seeds): decomposer = TwoQubitBasisDecomposer(UnitaryGate(basis_unitary)) self.check_exact_decomposition(random_unitary(4, seed=seeds[4]).data, decomposer) - @given(strategies.tuples(*[rotation] * 6), seed) - def test_cx_equivalence_0cx_random(self, rnd, seed): + @given(strategies.tuples(*[rotation] * 6)) + def test_cx_equivalence_0cx_random(self, rnd): """Check random circuits with 0 cx gates locally equivalent to identity.""" qr = QuantumRegister(2, name="q") qc = QuantumCircuit(qr) @@ -72,12 +72,11 @@ def test_cx_equivalence_0cx_random(self, rnd, seed): qc.u(rnd[0], rnd[1], rnd[2], qr[0]) qc.u(rnd[3], rnd[4], rnd[5], qr[1]) - sim = UnitarySimulatorPy() - unitary = sim.run(qc, seed_simulator=seed).result().get_unitary() + unitary = Operator(qc) self.assertEqual(two_qubit_cnot_decompose.num_basis_gates(unitary), 0) - @given(strategies.tuples(*[rotation] * 12), seed) - def test_cx_equivalence_1cx_random(self, rnd, seed): + @given(strategies.tuples(*[rotation] * 12)) + def test_cx_equivalence_1cx_random(self, rnd): """Check random circuits with 1 cx gates locally equivalent to a cx.""" qr = QuantumRegister(2, name="q") qc = QuantumCircuit(qr) @@ -90,12 +89,11 @@ def test_cx_equivalence_1cx_random(self, rnd, seed): qc.u(rnd[6], rnd[7], rnd[8], qr[0]) qc.u(rnd[9], rnd[10], rnd[11], qr[1]) - sim = UnitarySimulatorPy() - unitary = sim.run(qc, seed_simulator=seed).result().get_unitary() + unitary = Operator(qc) self.assertEqual(two_qubit_cnot_decompose.num_basis_gates(unitary), 1) - @given(strategies.tuples(*[rotation] * 18), seed) - def test_cx_equivalence_2cx_random(self, rnd, seed): + @given(strategies.tuples(*[rotation] * 18)) + def test_cx_equivalence_2cx_random(self, rnd): """Check random circuits with 2 cx gates locally equivalent to some circuit with 2 cx.""" qr = QuantumRegister(2, name="q") qc = QuantumCircuit(qr) @@ -113,12 +111,11 @@ def test_cx_equivalence_2cx_random(self, rnd, seed): qc.u(rnd[12], rnd[13], rnd[14], qr[0]) qc.u(rnd[15], rnd[16], rnd[17], qr[1]) - sim = UnitarySimulatorPy() - unitary = sim.run(qc, seed_simulator=seed).result().get_unitary() + unitary = Operator(qc) self.assertEqual(two_qubit_cnot_decompose.num_basis_gates(unitary), 2) - @given(strategies.tuples(*[rotation] * 24), seed) - def test_cx_equivalence_3cx_random(self, rnd, seed): + @given(strategies.tuples(*[rotation] * 24)) + def test_cx_equivalence_3cx_random(self, rnd): """Check random circuits with 3 cx gates are outside the 0, 1, and 2 qubit regions.""" qr = QuantumRegister(2, name="q") qc = QuantumCircuit(qr) @@ -141,8 +138,7 @@ def test_cx_equivalence_3cx_random(self, rnd, seed): qc.u(rnd[18], rnd[19], rnd[20], qr[0]) qc.u(rnd[21], rnd[22], rnd[23], qr[1]) - sim = UnitarySimulatorPy() - unitary = sim.run(qc, seed_simulator=seed).result().get_unitary() + unitary = Operator(qc) self.assertEqual(two_qubit_cnot_decompose.num_basis_gates(unitary), 3) diff --git a/test/visual/mpl/graph/test_graph_matplotlib_drawer.py b/test/visual/mpl/graph/test_graph_matplotlib_drawer.py index fe3a6260d83f..9bc87457bb41 100644 --- a/test/visual/mpl/graph/test_graph_matplotlib_drawer.py +++ b/test/visual/mpl/graph/test_graph_matplotlib_drawer.py @@ -18,7 +18,6 @@ from contextlib import contextmanager from pathlib import Path -from qiskit import BasicAer, transpile from qiskit.test import QiskitTestCase from qiskit import QuantumCircuit from qiskit.utils import optionals @@ -33,6 +32,7 @@ FakeMumbai, FakeManhattan, ) +from qiskit.quantum_info import Statevector if optionals.HAS_MATPLOTLIB: from matplotlib.pyplot import close as mpl_close @@ -100,10 +100,8 @@ def test_plot_bloch_multivector(self): circuit = QuantumCircuit(1) circuit.h(0) - # getting the state using backend - backend = BasicAer.get_backend("statevector_simulator") - result = backend.run(circuit).result() - state = result.get_statevector(circuit) + # getting the state using quantum_info + state = Statevector(circuit) fname = "bloch_multivector.png" self.graph_state_drawer(state=state, output="bloch", filename=fname) @@ -122,10 +120,8 @@ def test_plot_state_hinton(self): circuit = QuantumCircuit(1) circuit.x(0) - # getting the state using backend - backend = BasicAer.get_backend("statevector_simulator") - result = backend.run(circuit).result() - state = result.get_statevector(circuit) + # getting the state using quantum_info + state = Statevector(circuit) fname = "hinton.png" self.graph_state_drawer(state=state, output="hinton", filename=fname) @@ -144,10 +140,8 @@ def test_plot_state_qsphere(self): circuit = QuantumCircuit(1) circuit.x(0) - # getting the state using backend - backend = BasicAer.get_backend("statevector_simulator") - result = backend.run(circuit).result() - state = result.get_statevector(circuit) + # getting the state using quantum_info + state = Statevector(circuit) fname = "qsphere.png" self.graph_state_drawer(state=state, output="qsphere", filename=fname) @@ -166,10 +160,8 @@ def test_plot_state_city(self): circuit = QuantumCircuit(1) circuit.x(0) - # getting the state using backend - backend = BasicAer.get_backend("statevector_simulator") - result = backend.run(circuit).result() - state = result.get_statevector(circuit) + # getting the state using quantum_info + state = Statevector(circuit) fname = "state_city.png" self.graph_state_drawer(state=state, output="city", filename=fname) @@ -188,10 +180,8 @@ def test_plot_state_paulivec(self): circuit = QuantumCircuit(1) circuit.x(0) - # getting the state using backend - backend = BasicAer.get_backend("statevector_simulator") - result = backend.run(circuit).result() - state = result.get_statevector(circuit) + # getting the state using quantum_info + state = Statevector(circuit) fname = "paulivec.png" self.graph_state_drawer(state=state, output="paulivec", filename=fname) @@ -646,10 +636,8 @@ def test_plot_bloch_multivector_figsize_improvements(self): circuit.h(1) circuit.sxdg(2) - # getting the state using backend - backend = BasicAer.get_backend("statevector_simulator") - result = backend.run(transpile(circuit, backend)).result() - state = result.get_statevector(circuit) + # getting the state using quantum_info + state = Statevector(circuit) fname = "bloch_multivector_figsize_improvements.png" self.graph_state_drawer(