diff --git a/.github/workflows/tests_linux.yml b/.github/workflows/tests_linux.yml index 576a9c04b5..b76043bf6a 100644 --- a/.github/workflows/tests_linux.yml +++ b/.github/workflows/tests_linux.yml @@ -127,7 +127,7 @@ jobs: tests-json-input: runs-on: ${{ matrix.os }} needs: [sdist, lint] - timeout-minutes: 30 + timeout-minutes: 45 strategy: matrix: python-version: [3.9] diff --git a/.github/workflows/tests_mac.yml b/.github/workflows/tests_mac.yml index ecf89900c3..21cc092d1b 100644 --- a/.github/workflows/tests_mac.yml +++ b/.github/workflows/tests_mac.yml @@ -130,7 +130,7 @@ jobs: tests-json-input: runs-on: ${{ matrix.os }} needs: [sdist, lint] - timeout-minutes: 40 + timeout-minutes: 45 strategy: matrix: python-version: [3.9] diff --git a/.github/workflows/tests_windows.yml b/.github/workflows/tests_windows.yml index 3858581344..b8816e8279 100644 --- a/.github/workflows/tests_windows.yml +++ b/.github/workflows/tests_windows.yml @@ -128,7 +128,7 @@ jobs: tests-json-input: runs-on: ${{ matrix.os }} needs: ["lint"] - timeout-minutes: 30 + timeout-minutes: 45 strategy: matrix: python-version: [3.9] diff --git a/qiskit/providers/aer/backends/aer_simulator.py b/qiskit/providers/aer/backends/aer_simulator.py index 322bd55696..54f79523be 100644 --- a/qiskit/providers/aer/backends/aer_simulator.py +++ b/qiskit/providers/aer/backends/aer_simulator.py @@ -481,8 +481,8 @@ def _default_options(cls): return Options( # Global options shots=1024, - method=None, - device=None, + method='automatic', + device='CPU', precision="double", zero_threshold=1e-10, validation_threshold=None, @@ -498,8 +498,10 @@ def _default_options(cls): fusion_threshold=14, accept_distributed_results=None, blocking_qubits=None, + blocking_enable=False, memory=None, noise_model=None, + seed_simulator=None, # statevector options statevector_parallel_threshold=14, statevector_sample_measure_opt=10, diff --git a/qiskit/providers/aer/backends/aerbackend.py b/qiskit/providers/aer/backends/aerbackend.py index 38ea67df4c..b5780eeafb 100644 --- a/qiskit/providers/aer/backends/aerbackend.py +++ b/qiskit/providers/aer/backends/aerbackend.py @@ -136,18 +136,6 @@ def run(self, and direct kwarg's should be used for options to pass them to ``run_options``. """ - if isinstance(circuits, (QasmQobj, PulseQobj)): - warnings.warn('Using a qobj for run() is deprecated and will be ' - 'removed in a future release.', - PendingDeprecationWarning, - stacklevel=2) - qobj = circuits - else: - options_dict = {} - for key, value in self.options.__dict__.items(): - if value is not None: - options_dict[key] = value - qobj = assemble(circuits, self, **options_dict) # DEPRECATED if backend_options is not None: warnings.warn( @@ -158,9 +146,19 @@ def run(self, DeprecationWarning, stacklevel=3) + if isinstance(circuits, (QasmQobj, PulseQobj)): + warnings.warn('Using a qobj for run() is deprecated and will be ' + 'removed in a future release.', + PendingDeprecationWarning, + stacklevel=2) + qobj = circuits + else: + qobj = assemble(circuits, self) + # Add backend options to the Job qobj - qobj = self._format_qobj( + self._add_options_to_qobj( qobj, backend_options=backend_options, **run_options) + # Optional validation if validate: self._validate(qobj) @@ -253,9 +251,10 @@ def _run_job(self, job_id, qobj, backend_options, noise_model, validate): # type check to swap them back if not isinstance(job_id, str) and isinstance(qobj, str): job_id, qobj = qobj, job_id - run_qobj = self._format_qobj(qobj, backend_options=backend_options, - noise_model=noise_model) - return self._run(run_qobj, job_id) + self._add_options_to_qobj(qobj, + backend_options=backend_options, + noise_model=noise_model) + return self._run(qobj, job_id) def _run(self, qobj, job_id=''): """Run a job""" @@ -372,9 +371,9 @@ def _set_defaults_option(self, key, value): elif key in self._options_defaults: self._options_defaults.pop(key) - def _format_qobj(self, qobj, - backend_options=None, # DEPRECATED - **run_options): + def _add_options_to_qobj(self, qobj, + backend_options=None, # DEPRECATED + **run_options): """Return execution sim config dict from backend options.""" # Add options to qobj config overriding any existing fields config = qobj.config @@ -395,24 +394,6 @@ def _format_qobj(self, qobj, return qobj - def _run_config( - self, - backend_options=None, # DEPRECATED - **run_options): - """Return execution sim config dict from backend options.""" - # Get sim config - run_config = self._options.copy() - - # DEPRECATED backend options - if backend_options is not None: - for key, val in backend_options.items(): - run_config[key] = val - - # Override with run-time options - for key, val in run_options.items(): - run_config[key] = val - return run_config - def __repr__(self): """String representation of an AerBackend.""" name = self.__class__.__name__ diff --git a/src/controllers/aer_controller.hpp b/src/controllers/aer_controller.hpp index 26c938b64d..35ff6e4085 100755 --- a/src/controllers/aer_controller.hpp +++ b/src/controllers/aer_controller.hpp @@ -124,6 +124,17 @@ class Controller { // Simulation precision enum class Precision { Double, Single }; + const std::unordered_map method_names_ = { + {Method::automatic, "automatic"}, + {Method::statevector, "statevector"}, + {Method::density_matrix, "density_matrix"}, + {Method::matrix_product_state, "matrix_product_state"}, + {Method::stabilizer, "stabilizer"}, + {Method::extended_stabilizer, "extended_stabilizer"}, + {Method::unitary, "unitary"}, + {Method::superop, "superop"} + }; + //----------------------------------------------------------------------- // Config //----------------------------------------------------------------------- @@ -1844,7 +1855,7 @@ void Controller::run_circuit_helper(const Circuit &circ, // Output data container result.set_config(config); - result.metadata.add(state.name(), "method"); + result.metadata.add(method_names_.at(method), "method"); if (method == Method::statevector || method == Method::density_matrix || method == Method::unitary) { result.metadata.add(sim_device_name_, "device"); diff --git a/test/terra/backends/aer_simulator/test_options.py b/test/terra/backends/aer_simulator/test_options.py new file mode 100644 index 0000000000..9318edd2ca --- /dev/null +++ b/test/terra/backends/aer_simulator/test_options.py @@ -0,0 +1,92 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2018, 2021. +# +# 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. +""" +AerSimualtor options tests +""" + +from ddt import ddt +from qiskit import QuantumCircuit, transpile +from .aer_simulator_test_case import ( + AerSimulatorTestCase, supported_methods) + + +@ddt +class TestOptions(AerSimulatorTestCase): + """Tests of AerSimulator options""" + + @supported_methods( + ['automatic', 'stabilizer', 'statevector', 'density_matrix', + 'matrix_product_state', 'extended_stabilizer']) + def test_seed_simulator_option_measure(self, method, device): + """Test seed_simulator option fixes measurement outcomes""" + backend = self.backend(method=method, device=device, + seed_simulator=111) + qc = QuantumCircuit(2) + qc.h([0, 1]) + qc.reset(0) + qc.measure_all() + qc = transpile(qc, backend) + + counts1 = backend.run(qc).result().get_counts(0) + counts2 = backend.run(qc).result().get_counts(0) + + self.assertEqual(counts1, counts2) + + @supported_methods( + ['automatic', 'stabilizer', 'statevector', 'density_matrix', + 'matrix_product_state', 'extended_stabilizer']) + def test_seed_simulator_run_option_measure(self, method, device): + """Test seed_simulator option fixes measurement outcomes""" + backend = self.backend(method=method, device=device) + qc = QuantumCircuit(2) + qc.h([0, 1]) + qc.reset(0) + qc.measure_all() + qc = transpile(qc, backend) + seed = 1234 + counts1 = backend.run(qc, seed_simulator=seed).result().get_counts(0) + counts2 = backend.run(qc, seed_simulator=seed).result().get_counts(0) + self.assertEqual(counts1, counts2) + + @supported_methods( + ['automatic', 'stabilizer', 'statevector', 'density_matrix', + 'matrix_product_state', 'extended_stabilizer', 'unitary', 'superop']) + def test_method(self, method, device): + """Test seed_simulator option fixes measurement outcomes""" + backend = self.backend(method=method, device=device) + qc = QuantumCircuit(1) + qc.x(0) + qc = transpile(qc, backend) + + # Target simulation method + if method == 'automatic': + target = 'stabilizer' + else: + target = method + + result = backend.run(qc).result() + value = result.results[0].metadata.get('method', None) + self.assertEqual(value, target) + + @supported_methods( + ['automatic', 'stabilizer', 'statevector', 'density_matrix', + 'matrix_product_state', 'extended_stabilizer', 'unitary', 'superop']) + def test_device(self, method, device): + """Test seed_simulator option fixes measurement outcomes""" + backend = self.backend(method=method, device=device) + qc = QuantumCircuit(1) + qc.x(0) + qc = transpile(qc, backend) + + result = backend.run(qc).result() + value = result.results[0].metadata.get('device', None) + self.assertEqual(value, device) diff --git a/test/terra/extensions/test_wrappers.py b/test/terra/extensions/test_wrappers.py index 2612320bc8..6099effddd 100644 --- a/test/terra/extensions/test_wrappers.py +++ b/test/terra/extensions/test_wrappers.py @@ -50,7 +50,8 @@ def _create_qobj(self, backend, noise_model=None): qobj = assemble(transpile(circuit, backend), backend) opts = {'max_parallel_threads': 1, 'library_dir': LIBRARY_DIR} - return backend._format_qobj(qobj, **opts, noise_model=noise_model) + backend._add_options_to_qobj(qobj, **opts, noise_model=noise_model) + return qobj def _map_and_test(self, cfunc, qobj): n = 2