diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2a6f245ee1..2bd6e3020c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -87,13 +87,18 @@ jobs: aer-test/bin/pip check shell: bash tests_linux: - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest + name: Linux Python ${{ matrix.python-version }}${{ matrix.qiskit-extra && format(' ({0})', matrix.qiskit-extra) }} needs: [sdist, lint] timeout-minutes: 60 strategy: matrix: python-version: [3.8, 3.9, "3.10", "3.11", "3.12.0"] - os: ["ubuntu-latest"] + qiskit-extra: [""] + include: + - python-version: "3.10" + qiskit-extra: "'qiskit>=1.0.0rc1'" + env: AER_THRUST_BACKEND: OMP QISKIT_TEST_CAPTURE_STREAMS: 1 @@ -116,17 +121,19 @@ jobs: ${{ runner.os }}-${{ matrix.python-version}}-pip-test- ${{ runner.os }}-${{ matrix.python-version}}-pip- ${{ runner.os }}-${{ matrix.python-version}}- - - name: Install Deps - run: python -m pip install -U -c constraints.txt -r requirements-dev.txt wheel - name: Install openblas run: | set -e sudo apt-get update sudo apt-get install -y libopenblas-dev shell: bash - - name: Install Aer + - name: Install Aer and dependencies run: | - python -m pip install -U . + python -m pip install -U \ + -c constraints.txt \ + -r requirements-dev.txt \ + ${{ matrix.qiskit-extra }} \ + . - name: Run Tests run: | set -e @@ -185,13 +192,13 @@ jobs: stestr run --slowest shell: bash tests_macos: - runs-on: ${{ matrix.os }} + runs-on: macOS-latest + name: macOS Python ${{ matrix.python-version }} needs: [sdist, lint] timeout-minutes: 60 strategy: matrix: python-version: [3.8, 3.9, "3.10", '3.11', "3.12.0"] - os: ["macOS-latest"] env: AER_THRUST_BACKEND: OMP QISKIT_TEST_CAPTURE_STREAMS: 1 @@ -214,12 +221,13 @@ jobs: ${{ runner.os }}-${{ matrix.python-version}}-pip-test- ${{ runner.os }}-${{ matrix.python-version}}-pip- ${{ runner.os }}-${{ matrix.python-version}}- - - name: Install Deps + - name: Install Aer and dependencies run: | set -e - pip install -U -c constraints.txt -r requirements-dev.txt - - name: Install Aer - run: python -m pip install -U . + pip install -U \ + -c constraints.txt \ + -r requirements-dev.txt \ + . - name: Run Tests run: | set -e @@ -228,13 +236,13 @@ jobs: stestr run --slowest shell: bash tests_windows: - runs-on: ${{ matrix.os }} + runs-on: windows-2019 + name: Windows Python ${{ matrix.python-version }} needs: ["lint", "sdist"] timeout-minutes: 60 strategy: matrix: python-version: [3.8, 3.9, "3.10", "3.11", "3.12.0"] - os: ["windows-2019"] env: AER_THRUST_BACKEND: OMP QISKIT_TEST_CAPTURE_STREAMS: 1 @@ -259,15 +267,22 @@ jobs: ${{ runner.os }}-${{ matrix.python-version}}- - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v1.0.2 - - name: Install Deps - run: python -m pip install -U -c constraints.txt -r requirements-dev.txt wheel build - - name: Install Aer Windows + - name: Build Aer Windows env: CMAKE_GENERATOR: "Visual Studio 16 2019" run: | set -e + pip install build python -I -m build --wheel - pip install -U dist/*.whl + shell: bash + - name: Install Aer and dependencies + run: | + set -e + shopt -s failglob + pip install -U \ + -c constraints.txt \ + -r requirements-dev.txt \ + dist/*.whl shell: bash - name: Run Tests env: diff --git a/.github/workflows/unit-tests-latest-qiskit.yml b/.github/workflows/unit-tests-latest-qiskit.yml index 425538529c..a0ecd9f7a1 100644 --- a/.github/workflows/unit-tests-latest-qiskit.yml +++ b/.github/workflows/unit-tests-latest-qiskit.yml @@ -31,19 +31,20 @@ jobs: ${{ runner.os }}-${{ matrix.python-version}}-pip-test- ${{ runner.os }}-${{ matrix.python-version}}-pip- ${{ runner.os }}-${{ matrix.python-version}}- - - name: Install Deps - run: | - python -m pip install -U -c constraints.txt -r requirements-dev.txt wheel - pip install -U git+https://github.com/Qiskit/qiskit.git - name: Install openblas run: | set -e sudo apt-get update sudo apt-get install -y libopenblas-dev shell: bash - - name: Install Aer + - name: Install dependencies and Aer run: | - python -m pip install -U . + python -m pip install -U setuptools wheel + python -m pip install -U \ + -c constraints.txt \ + -r requirements-dev.txt \ + 'git+https://github.com/Qiskit/qiskit.git@main' \ + . - name: Run Tests run: | set -e @@ -51,4 +52,4 @@ jobs: rm -rf qiskit_aer stestr run --slowest shell: bash - \ No newline at end of file + diff --git a/README.md b/README.md index 40492f4f3c..b579bd3a7a 100755 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ $ python ```python import qiskit from qiskit_aer import AerSimulator -from qiskit.providers.fake_provider import FakeManilaV2 +from qiskit_ibm_runtime import QiskitRuntimeService # Generate 3-qubit GHZ state circ = qiskit.QuantumCircuit(3) @@ -73,10 +73,10 @@ counts_ideal = result_ideal.get_counts(0) print('Counts(ideal):', counts_ideal) # Counts(ideal): {'000': 493, '111': 531} -# Construct a noisy simulator backend from an IBMQ backend -# This simulator backend will be automatically configured -# using the device configuration and noise model -backend = FakeManilaV2() +# Construct a simulator using a noise model +# from a real backend. +provider = QiskitRuntimeService() +backend = provider.get_backend("ibm_kyoto") aersim_backend = AerSimulator.from_backend(backend) # Perform noisy simulation diff --git a/test/terra/backends/aer_simulator/test_from_backend.py b/test/terra/backends/aer_simulator/test_from_backend.py deleted file mode 100644 index 0231f574f5..0000000000 --- a/test/terra/backends/aer_simulator/test_from_backend.py +++ /dev/null @@ -1,54 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2022 -# -# 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. -""" -AerSimulator Integration Tests -""" - -from test.terra.backends.simulator_test_case import SimulatorTestCase - -from qiskit.providers.fake_provider import FakeNairobi, FakeNairobiV2 -from qiskit.circuit import QuantumCircuit -from qiskit.compiler import transpile - -from qiskit_aer import AerSimulator - - -class TestAlgorithms(SimulatorTestCase): - """AerSimulator algorithm tests in the default basis""" - - def setUp(self): - super().setUp() - self.qc = QuantumCircuit(2) - self.qc.h(0) - self.qc.cx(0, 1) - self.qc.measure_all() - - def test_backend_v1(self): - """Test from_backend_v1 works.""" - backend = FakeNairobi() - sim_backend = AerSimulator.from_backend(backend) - tqc = transpile(self.qc, backend) - self.assertEqual( - backend.run(tqc, shots=1024, seed_simulator=12345678942).result().get_counts(), - sim_backend.run(tqc, shots=1024, seed_simulator=12345678942).result().get_counts(), - ) - - def test_backend_v2(self): - """Test from_backend_v2 works.""" - backend = FakeNairobiV2() - sim_backend = AerSimulator.from_backend(backend) - tqc = transpile(self.qc, backend) - self.assertDictAlmostEqual( - backend.run(tqc, shots=1024, seed_simulator=12345678942).result().get_counts(), - sim_backend.run(tqc, shots=1024, seed_simulator=12345678942).result().get_counts(), - delta=100, - ) diff --git a/test/terra/backends/aer_simulator/test_options.py b/test/terra/backends/aer_simulator/test_options.py index ca63207181..a387e6cd63 100644 --- a/test/terra/backends/aer_simulator/test_options.py +++ b/test/terra/backends/aer_simulator/test_options.py @@ -14,12 +14,18 @@ """ from ddt import ddt, data -from qiskit import QuantumCircuit, transpile from qiskit_aer.noise import NoiseModel from test.terra.backends.simulator_test_case import SimulatorTestCase, supported_methods + +import qiskit +from qiskit import QuantumCircuit, transpile from qiskit.quantum_info.random import random_unitary from qiskit.quantum_info import state_fidelity -from qiskit.providers.fake_provider import FakeMontreal + +if qiskit.__version__.startswith("0."): + from qiskit.providers.fake_provider import FakeAlmaden as Fake20QV1 +else: + from qiskit.providers.fake_provider import Fake20QV1 from qiskit_aer import AerSimulator @@ -299,8 +305,8 @@ def test_statevector_memory(self): def test_num_qubits(self, method): """Test number of qubits is correctly checked""" - num_qubits = FakeMontreal().configuration().num_qubits - backend = AerSimulator.from_backend(FakeMontreal(), method=method) + num_qubits = Fake20QV1().configuration().num_qubits + backend = AerSimulator.from_backend(Fake20QV1(), method=method) self.assertGreaterEqual(backend.configuration().num_qubits, num_qubits) def test_mps_svd_method(self): diff --git a/test/terra/backends/aer_simulator/test_truncate.py b/test/terra/backends/aer_simulator/test_truncate.py index eb98b10546..136623b9e5 100644 --- a/test/terra/backends/aer_simulator/test_truncate.py +++ b/test/terra/backends/aer_simulator/test_truncate.py @@ -9,8 +9,15 @@ AerSimulator Integration Tests """ from ddt import ddt + +import qiskit from qiskit import transpile, QuantumCircuit -from qiskit.providers.fake_provider import FakeQuito + +if qiskit.__version__.startswith("0."): + from qiskit.providers.fake_provider import FakeQuito as Fake5QV1 +else: + from qiskit.providers.fake_provider import Fake5QV1 + from qiskit_aer.noise import NoiseModel from test.terra.backends.simulator_test_case import SimulatorTestCase, supported_methods @@ -46,7 +53,7 @@ def create_circuit_for_truncate(self): return circuit def device_backend(self): - return FakeQuito() + return Fake5QV1() def test_truncate_ideal_sparse_circuit(self): """Test qubit truncation for large circuit with unused qubits.""" diff --git a/test/terra/noise/test_device_models.py b/test/terra/noise/test_device_models.py index aad6c1e38c..43d90fda91 100644 --- a/test/terra/noise/test_device_models.py +++ b/test/terra/noise/test_device_models.py @@ -16,29 +16,73 @@ import numpy as np from test.terra.common import QiskitAerTestCase -from qiskit.circuit.library.standard_gates import XGate -from qiskit.providers.fake_provider import FakeNairobi, FakeNairobiV2 -from qiskit.transpiler import Target, QubitProperties, InstructionProperties +import qiskit +from qiskit.circuit import library, Reset, Measure, Parameter +from qiskit.providers import convert_to_target +from qiskit.transpiler import CouplingMap, Target, QubitProperties, InstructionProperties + +if qiskit.__version__.startswith("0."): + from qiskit.providers.fake_provider import FakeQuito as Fake5QV1 +else: + from qiskit.providers.fake_provider import Fake5QV1 + from qiskit_aer.noise.device.models import basic_device_gate_errors from qiskit_aer.noise.errors.standard_errors import thermal_relaxation_error +def target_7q(): + """Build an arbitrary 7q ``Target`` with noisy instructions.""" + num_qubits = 7 + qubit_properties = [ + QubitProperties(t1=1.5e-4, t2=1.5e-4, frequency=4_700_000_000.0 + q * 50_000_000.0) + for q in range(num_qubits) + ] + target = Target(num_qubits=7, qubit_properties=qubit_properties) + for gate in (library.SXGate(), library.XGate(), library.RZGate(Parameter("a"))): + target.add_instruction( + gate, + properties={ + (q,): InstructionProperties(duration=50e-9, error=2e-4) for q in range(num_qubits) + }, + ) + target.add_instruction( + library.CXGate(), + properties={ + link: InstructionProperties(duration=300e-9, error=1e-3) + for link in CouplingMap.from_ring(num_qubits) + }, + ) + target.add_instruction( + Reset(), + properties={ + (q,): InstructionProperties(duration=4e-6, error=None) for q in range(num_qubits) + }, + ) + target.add_instruction( + Measure(), + properties={ + (q,): InstructionProperties(duration=3e-6, error=1.5e-2) for q in range(num_qubits) + }, + ) + return target + + class TestDeviceNoiseModel(QiskitAerTestCase): """Testing device noise model""" def test_basic_device_gate_errors_from_target(self): """Test if the resulting gate errors never include errors on non-gate instructions""" - target = FakeNairobiV2().target + target = target_7q() gate_errors = basic_device_gate_errors(target=target) errors_on_measure = [name for name, _, _ in gate_errors if name == "measure"] errors_on_reset = [name for name, _, _ in gate_errors if name == "reset"] self.assertEqual(len(errors_on_measure), 0) self.assertEqual(len(errors_on_reset), 7) - self.assertEqual(len(gate_errors), 40) + self.assertEqual(len(gate_errors), 42) def test_basic_device_gate_errors_from_target_with_non_operational_qubits(self): """Test if no thermal relaxation errors are generated for qubits with undefined T1 and T2.""" - target = FakeNairobiV2().target + target = target_7q() # tweak target to have non-operational qubits faulty_qubits = (1, 2) for q in faulty_qubits: @@ -47,7 +91,7 @@ def test_basic_device_gate_errors_from_target_with_non_operational_qubits(self): gate_errors = basic_device_gate_errors(target=target, gate_error=False) errors_on_sx = {qubits: error for name, qubits, error in gate_errors if name == "sx"} errors_on_cx = {qubits: error for name, qubits, error in gate_errors if name == "cx"} - self.assertEqual(len(gate_errors), 40) + self.assertEqual(len(gate_errors), 42) # check if no errors are added on sx gates on qubits without T1 and T2 definitions for q in faulty_qubits: self.assertTrue(errors_on_sx[(q,)].ideal()) @@ -56,8 +100,13 @@ def test_basic_device_gate_errors_from_target_with_non_operational_qubits(self): def test_basic_device_gate_errors_from_target_and_properties(self): """Test if the device same gate errors are produced both from target and properties""" - errors_from_properties = basic_device_gate_errors(properties=FakeNairobi().properties()) - errors_from_target = basic_device_gate_errors(target=FakeNairobiV2().target) + backend = Fake5QV1() + target = convert_to_target( + configuration=backend.configuration(), + properties=backend.properties(), + ) + errors_from_properties = basic_device_gate_errors(properties=backend.properties()) + errors_from_target = basic_device_gate_errors(target=target) self.assertEqual(len(errors_from_properties), len(errors_from_target)) errors_from_properties_s = sorted(errors_from_properties) errors_from_target_s = sorted(errors_from_target) @@ -71,7 +120,7 @@ def test_basic_device_gate_errors_from_target_and_properties(self): def test_basic_device_gate_errors_from_target_with_no_t2_value(self): """Test if gate errors are successfully created from a target with qubits not reporting T2. See https://github.com/Qiskit/qiskit-aer/issues/1896 for the details.""" - target = FakeNairobiV2().target + target = target_7q() target.qubit_properties[0].t2 = None basic_device_gate_errors(target=target) @@ -80,7 +129,7 @@ def test_non_zero_temperature(self): See https://github.com/Qiskit/qiskit-aer/issues/1937 for the details.""" t1, t2, frequency, duration = 1e-4, 1e-4, 5e9, 5e-8 target = Target(qubit_properties=[QubitProperties(t1=t1, t2=t2, frequency=frequency)]) - target.add_instruction(XGate(), {(0,): InstructionProperties(duration=duration)}) + target.add_instruction(library.XGate(), {(0,): InstructionProperties(duration=duration)}) errors = basic_device_gate_errors(target=target, gate_error=False, temperature=100) _, _, x_error = errors[0] no_excitation_error = thermal_relaxation_error(t1, t2, duration, excited_state_population=0) diff --git a/test/terra/noise/test_noise_model.py b/test/terra/noise/test_noise_model.py index d851288459..ebad6ffe75 100644 --- a/test/terra/noise/test_noise_model.py +++ b/test/terra/noise/test_noise_model.py @@ -29,21 +29,39 @@ from qiskit_aer.noise.errors.standard_errors import thermal_relaxation_error from qiskit_aer.utils.noise_transformation import transform_noise_model +import qiskit from qiskit.circuit import QuantumRegister, ClassicalRegister, QuantumCircuit from qiskit.circuit.library.generalized_gates import PauliGate from qiskit.circuit.library.standard_gates import IGate, XGate from qiskit.compiler import transpile -from qiskit.providers import QubitProperties -from qiskit.providers.fake_provider import ( - FakeBackend, - FakeAlmaden, - FakeLagos, - FakeSingapore, - FakeMumbai, - FakeKolkata, - FakeBackendV2, - FakeLagosV2, -) +from qiskit.transpiler import CouplingMap, Target +from qiskit.providers import QubitProperties, BackendV2, Options + +if qiskit.__version__.startswith("0."): + from qiskit.providers.fake_provider import ( + FakeBackend, + FakeAlmaden as Fake20QV1, + FakeMumbai as Fake27QPulseV1, + FakeLagosV2, + ) + + def fake_7q_v2(): + """Generate a dummy 7q V2 backend.""" + return FakeLagosV2() + +else: + from qiskit.providers.fake_provider import ( + FakeBackend, + Fake20QV1, + Fake27QPulseV1, + GenericBackendV2, + ) + + def fake_7q_v2(): + """Generate a dummy 7q V2 backend.""" + return GenericBackendV2(num_qubits=7, coupling_map=CouplingMap.from_ring(7), seed=0) + + from test.terra.common import QiskitAerTestCase @@ -197,62 +215,37 @@ def test_noise_models_not_equal(self): model2 = NoiseModel(basis_gates=["u3", "cx"]) model2.add_all_qubit_quantum_error(error, ["u3"], False) - def test_noise_model_from_backend_singapore(self): + def test_noise_model_from_backend_20(self): circ = QuantumCircuit(2) circ.x(0) circ.x(1) circ.measure_all() - backend = FakeSingapore() + backend = Fake20QV1() noise_model = NoiseModel.from_backend(backend) circ = transpile(circ, backend, optimization_level=0) result = AerSimulator().run(circ, noise_model=noise_model).result() self.assertTrue(result.success) - def test_noise_model_from_backend_almaden(self): + def test_noise_model_from_backend_27_pulse(self): circ = QuantumCircuit(2) circ.x(0) circ.x(1) circ.measure_all() - backend = FakeAlmaden() - noise_model = NoiseModel.from_backend(backend) - circ = transpile(circ, backend, optimization_level=0) - result = AerSimulator().run(circ, noise_model=noise_model).result() - self.assertTrue(result.success) - - def test_noise_model_from_mumbai(self): - circ = QuantumCircuit(2) - circ.x(0) - circ.x(1) - circ.measure_all() - - backend = FakeMumbai() + backend = Fake27QPulseV1() noise_model = NoiseModel.from_backend(backend) circ = transpile(circ, backend, optimization_level=0) result = AerSimulator().run(circ, noise_model=noise_model).result() self.assertTrue(result.success) def test_noise_model_from_backend_v2(self): - circ = QuantumCircuit(2) - circ.x(0) - circ.x(1) - circ.measure_all() - - backend = FakeBackendV2() - noise_model = NoiseModel.from_backend(backend) - self.assertEqual([0, 1], noise_model.noise_qubits) - circ = transpile(circ, backend, optimization_level=0) - result = AerSimulator().run(circ, noise_model=noise_model).result() - self.assertTrue(result.success) - - def test_noise_model_from_lagos_v2(self): circ = QuantumCircuit(2) circ.x(0) circ.cx(0, 1) circ.measure_all() - backend = FakeLagosV2() + backend = fake_7q_v2() noise_model = NoiseModel.from_backend(backend) self.assertEqual([0, 1, 2, 3, 4, 5, 6], noise_model.noise_qubits) circ = transpile(circ, backend, optimization_level=0) @@ -262,7 +255,7 @@ def test_noise_model_from_lagos_v2(self): def test_noise_model_from_backend_v2_with_non_operational_qubits(self): """Test if possible to create a noise model from backend with non-operational qubits. See issues #1779 and #1815 for the details.""" - backend = FakeLagosV2() + backend = fake_7q_v2() # tweak target to have non-operational qubits faulty_qubits = [0, 1] for qubit in faulty_qubits: @@ -342,9 +335,29 @@ def properties(self): def test_create_noise_model_without_user_warnings(self): """Test if never issue user warnings when creating a noise model from backend. See issue#1631 for the details.""" - # FakeKolkata has a qubit with T_2 > 2 * T_1 + + class BadlyCalibratedBackendV2(BackendV2): + """A backend with `t2 > 2*t1` due to awkward calibration statistics.""" + + @property + def target(self): + return Target( + num_qubits=1, qubit_properties=[QubitProperties(t1=1.2e-3, t2=2.5e-3)] + ) + + @property + def max_circuits(self): + return None + + @classmethod + def _default_options(cls): + return Options() + + def run(self, run_input, **options): + raise NotImplementedError + with warnings.catch_warnings(record=True) as warns: - NoiseModel.from_backend(FakeKolkata()) + NoiseModel.from_backend(BadlyCalibratedBackendV2()) user_warnings = [w for w in warns if issubclass(w.category, UserWarning)] self.assertEqual(len(user_warnings), 0) @@ -354,7 +367,7 @@ def test_noise_model_from_backend_properties(self): circ.x(1) circ.measure_all() - backend = FakeAlmaden() + backend = Fake20QV1() backend_propeties = backend.properties() noise_model = NoiseModel.from_backend_properties(backend_propeties) circ = transpile(circ, backend, optimization_level=0) @@ -388,7 +401,7 @@ def test_can_run_circuits_with_delay_noise(self): circ.cx(0, 1) circ.measure_all() - backend = FakeLagosV2() + backend = fake_7q_v2() noise_model = NoiseModel.from_backend(backend) qc = transpile(circ, backend, scheduling_method="alap") diff --git a/test/terra/states/test_aer_statevector.py b/test/terra/states/test_aer_statevector.py index 0797d6178e..0a78d681d5 100644 --- a/test/terra/states/test_aer_statevector.py +++ b/test/terra/states/test_aer_statevector.py @@ -14,17 +14,16 @@ """ import unittest -from math import pi -import numpy as np import logging from itertools import permutations from ddt import ddt, data + +import numpy as np from numpy.testing import assert_allclose from qiskit import transpile from qiskit.exceptions import QiskitError from qiskit.circuit import QuantumCircuit, QuantumRegister -from qiskit.providers.basicaer import QasmSimulatorPy from qiskit.quantum_info.random import random_unitary, random_statevector, random_pauli from qiskit.quantum_info.states import Statevector from qiskit.circuit.library import QuantumVolume @@ -35,13 +34,12 @@ from qiskit.visualization.state_visualization import state_to_latex from qiskit.circuit.library import QFT, HGate from qiskit.circuit.library import DiagonalGate +from qiskit.quantum_info.operators.predicates import ATOL_DEFAULT, RTOL_DEFAULT -from test.terra import common -from qiskit_aer import AerSimulator -from qiskit_aer.aererror import AerError -from qiskit_aer.noise import pauli_error, QuantumError +from qiskit_aer.noise import pauli_error from qiskit_aer.quantum_info.states import AerStatevector -from qiskit.quantum_info.operators.predicates import ATOL_DEFAULT, RTOL_DEFAULT + +from test.terra import common logger = logging.getLogger(__name__) @@ -1311,18 +1309,9 @@ def test_probabilities_qargs(self, qargs): probs = state.probabilities(qargs) # Estimate target probs from simulator measurement - sim = QasmSimulatorPy() - shots = 5000 - seed = 100 - circ = transpile(state_circ, sim) - circ.measure(qargs, range(nc)) - result = sim.run(circ, shots=shots, seed_simulator=seed).result() - target = np.zeros(2**nc, dtype=float) - for i, p in result.get_counts(0).int_outcomes().items(): - target[i] = p / shots - # Compare - delta = np.linalg.norm(probs - target) - self.assertLess(delta, 0.05) + terra_state = Statevector(state_circ) + terra_probs = terra_state.probabilities(qargs) + assert_allclose(probs, terra_probs) def test_global_phase(self): """Test global phase is handled correctly when evolving statevector."""