From 8097897a8781474060cbc5402810ecc64de1b69d Mon Sep 17 00:00:00 2001 From: Manoel Marques Date: Mon, 3 May 2021 13:12:21 -0400 Subject: [PATCH 1/3] Add support on QuantumInstance/run_circuits for Backends that don't handle QasmQobj (#6299) * Support BackendV1 * Add error mitigation logic. Co-authored-by: Matthew Treinish * Fix run_circuits calls * add unit tests * Update qiskit/utils/run_circuits.py Add check for providers that don't support it. Co-authored-by: Matthew Treinish * Add error mitigation test Co-authored-by: Matthew Treinish Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit a0ed7ff73a279dce09d3fb1f138cf9eec760146e) --- qiskit/utils/backend_utils.py | 11 +- qiskit/utils/measurement_error_mitigation.py | 57 +++++- qiskit/utils/quantum_instance.py | 149 +++++++++++---- qiskit/utils/run_circuits.py | 181 +++++++++++++++++++ test/python/algorithms/test_backendv1.py | 128 +++++++++++++ 5 files changed, 482 insertions(+), 44 deletions(-) create mode 100644 test/python/algorithms/test_backendv1.py diff --git a/qiskit/utils/backend_utils.py b/qiskit/utils/backend_utils.py index 034905afe08a..9e4f9b43d269 100644 --- a/qiskit/utils/backend_utils.py +++ b/qiskit/utils/backend_utils.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2018, 2020. +# (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 @@ -75,7 +75,10 @@ def is_aer_provider(backend): """ if has_aer(): from qiskit.providers.aer import AerProvider - return isinstance(backend.provider(), AerProvider) + if isinstance(backend.provider(), AerProvider): + return True + from qiskit.providers.aer.backends.aerbackend import AerBackend + return isinstance(backend, AerBackend) return False @@ -129,6 +132,10 @@ def is_statevector_backend(backend): Returns: bool: True is statevector """ + if has_aer(): + from qiskit.providers.aer.backends import StatevectorSimulator + if isinstance(backend, StatevectorSimulator): + return True return backend.name().startswith('statevector') if backend is not None else False diff --git a/qiskit/utils/measurement_error_mitigation.py b/qiskit/utils/measurement_error_mitigation.py index 2e0369e8e03e..2046af19792d 100644 --- a/qiskit/utils/measurement_error_mitigation.py +++ b/qiskit/utils/measurement_error_mitigation.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2019, 2020. +# (C) Copyright IBM 2019, 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 @@ -17,6 +17,8 @@ from qiskit import compiler from ..exceptions import QiskitError, MissingOptionalLibraryError +# pylint: disable=invalid-name + def get_measured_qubits(transpiled_circuits): """ @@ -39,7 +41,7 @@ def get_measured_qubits(transpiled_circuits): for inst, qargs, _ in qc.data: if inst.name != 'measure': continue - measured_qubits.append(qargs[0][1]) + measured_qubits.append(qargs[0].index) measured_qubits_str = '_'.join([str(x) for x in measured_qubits]) if measured_qubits_str not in qubit_mappings: qubit_mappings[measured_qubits_str] = [] @@ -93,7 +95,56 @@ def get_measured_qubits_from_qobj(qobj): return sorted(qubit_index), qubit_mappings -# pylint: disable=invalid-name +def build_measurement_error_mitigation_circuits(qubit_list, fitter_cls, backend, + backend_config=None, compile_config=None): + """Build measurement error mitigation circuits + Args: + qubit_list (list[int]): list of ordered qubits used in the algorithm + fitter_cls (callable): CompleteMeasFitter or TensoredMeasFitter + backend (BaseBackend): backend instance + backend_config (dict, optional): configuration for backend + compile_config (dict, optional): configuration for compilation + Returns: + QasmQobj: the Qobj with calibration circuits at the beginning + list[str]: the state labels for build MeasFitter + list[str]: the labels of the calibration circuits + Raises: + QiskitError: when the fitter_cls is not recognizable. + MissingOptionalLibraryError: Qiskit-Ignis not installed + """ + try: + from qiskit.ignis.mitigation.measurement import (complete_meas_cal, + CompleteMeasFitter, TensoredMeasFitter) + except ImportError as ex: + raise MissingOptionalLibraryError( + libname='qiskit-ignis', + name='build_measurement_error_mitigation_qobj', + pip_install='pip install qiskit-ignis') from ex + + circlabel = 'mcal' + + if not qubit_list: + raise QiskitError("The measured qubit list can not be [].") + + if fitter_cls == CompleteMeasFitter: + meas_calibs_circuits, state_labels = \ + complete_meas_cal(qubit_list=range(len(qubit_list)), circlabel=circlabel) + elif fitter_cls == TensoredMeasFitter: + # TODO support different calibration + raise QiskitError("Does not support TensoredMeasFitter yet.") + else: + raise QiskitError("Unknown fitter {}".format(fitter_cls)) + + # the provided `qubit_list` would be used as the initial layout to + # assure the consistent qubit mapping used in the main circuits. + + tmp_compile_config = copy.deepcopy(compile_config) + tmp_compile_config['initial_layout'] = qubit_list + t_meas_calibs_circuits = compiler.transpile(meas_calibs_circuits, backend, + **backend_config, **tmp_compile_config) + return t_meas_calibs_circuits, state_labels, circlabel + + def build_measurement_error_mitigation_qobj(qubit_list, fitter_cls, backend, backend_config=None, compile_config=None, run_config=None): diff --git a/qiskit/utils/quantum_instance.py b/qiskit/utils/quantum_instance.py index f031e11520ec..ba99cb427f2e 100644 --- a/qiskit/utils/quantum_instance.py +++ b/qiskit/utils/quantum_instance.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2018, 2020. +# (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 @@ -22,6 +22,7 @@ from qiskit.utils import circuit_utils from qiskit.exceptions import QiskitError from .backend_utils import (is_ibmq_provider, + is_aer_provider, is_statevector_backend, is_simulator_backend, is_local_backend, @@ -295,20 +296,31 @@ def execute(self, TODO: Maybe we can combine the circuits for the main ones and calibration circuits before assembling to the qobj. """ - from qiskit.utils.run_circuits import run_qobj + from qiskit.utils.run_circuits import run_qobj, run_circuits from qiskit.utils.measurement_error_mitigation import \ - (get_measured_qubits_from_qobj, build_measurement_error_mitigation_qobj) + (get_measured_qubits_from_qobj, get_measured_qubits, + build_measurement_error_mitigation_circuits, + build_measurement_error_mitigation_qobj) # maybe compile if not had_transpiled: circuits = self.transpile(circuits) + # fix for providers that don't support QasmQobj until a bigger refactor happens + from qiskit.providers import BackendV1 + circuit_job = isinstance(self._backend, BackendV1) and \ + not is_aer_provider(self._backend) and \ + not is_basicaer_provider(self._backend) and \ + not is_ibmq_provider(self._backend) + # assemble - qobj = self.assemble(circuits) + if not circuit_job: + qobj = self.assemble(circuits) if self._meas_error_mitigation_cls is not None: - qubit_index, qubit_mappings = get_measured_qubits_from_qobj(qobj) + qubit_index, qubit_mappings = get_measured_qubits(circuits) \ + if circuit_job else get_measured_qubits_from_qobj(qobj) qubit_index_str = '_'.join([str(x) for x in qubit_index]) + \ "_{}".format(self._meas_error_mitigation_shots or self._run_config.shots) meas_error_mitigation_fitter, timestamp = \ @@ -337,39 +349,84 @@ def execute(self, meas_error_mitigation_fitter is None if build_cals_matrix: - logger.info("Updating qobj with the circuits for measurement error mitigation.") - use_different_shots = not ( - self._meas_error_mitigation_shots is None - or self._meas_error_mitigation_shots == self._run_config.shots) - temp_run_config = copy.deepcopy(self._run_config) - if use_different_shots: - temp_run_config.shots = self._meas_error_mitigation_shots - - cals_qobj, state_labels, circuit_labels = \ - build_measurement_error_mitigation_qobj(qubit_index, - self._meas_error_mitigation_cls, - self._backend, - self._backend_config, - self._compile_config, - temp_run_config) - if use_different_shots or is_aer_qasm(self._backend): - cals_result = run_qobj(cals_qobj, self._backend, self._qjob_config, - self._backend_options, - self._noise_config, - self._skip_qobj_validation, self._job_callback) - self._time_taken += cals_result.time_taken - result = run_qobj(qobj, self._backend, self._qjob_config, - self._backend_options, self._noise_config, - self._skip_qobj_validation, self._job_callback) - self._time_taken += result.time_taken + if circuit_job: + logger.info("Updating to also run measurement error mitigation.") + use_different_shots = not ( + self._meas_error_mitigation_shots is None + or self._meas_error_mitigation_shots == self._run_config.shots) + temp_run_config = copy.deepcopy(self._run_config) + if use_different_shots: + temp_run_config.shots = self._meas_error_mitigation_shots + cal_circuits, state_labels, circuit_labels = \ + build_measurement_error_mitigation_circuits( + qubit_index, + self._meas_error_mitigation_cls, + self._backend, + self._backend_config, + self._compile_config) + if use_different_shots: + cals_result = run_circuits(cal_circuits, + self._backend, + qjob_config=self._qjob_config, + backend_options=self._backend_options, + noise_config=self._noise_config, + run_config=self._run_config.to_dict(), + job_callback=self._job_callback) + self._time_taken += cals_result.time_taken + result = run_circuits(circuits, + self._backend, + qjob_config=self.qjob_config, + backend_options=self.backend_options, + noise_config=self._noise_config, + run_config=self.run_config.to_dict(), + job_callback=self._job_callback) + self._time_taken += result.time_taken + else: + circuits[0:0] = cal_circuits + result = run_circuits(circuits, + self._backend, + qjob_config=self.qjob_config, + backend_options=self.backend_options, + noise_config=self._noise_config, + run_config=self.run_config.to_dict(), + job_callback=self._job_callback) + self._time_taken += result.time_taken + cals_result = result + else: - # insert the calibration circuit into main qobj if the shots are the same - qobj.experiments[0:0] = cals_qobj.experiments - result = run_qobj(qobj, self._backend, self._qjob_config, - self._backend_options, self._noise_config, - self._skip_qobj_validation, self._job_callback) - self._time_taken += result.time_taken - cals_result = result + logger.info("Updating qobj with the circuits for measurement error mitigation.") + use_different_shots = not ( + self._meas_error_mitigation_shots is None + or self._meas_error_mitigation_shots == self._run_config.shots) + temp_run_config = copy.deepcopy(self._run_config) + if use_different_shots: + temp_run_config.shots = self._meas_error_mitigation_shots + + cals_qobj, state_labels, circuit_labels = \ + build_measurement_error_mitigation_qobj(qubit_index, + self._meas_error_mitigation_cls, + self._backend, + self._backend_config, + self._compile_config, + temp_run_config) + if use_different_shots or is_aer_qasm(self._backend): + cals_result = run_qobj(cals_qobj, self._backend, self._qjob_config, + self._backend_options, + self._noise_config, + self._skip_qobj_validation, self._job_callback) + self._time_taken += cals_result.time_taken + result = run_qobj(qobj, self._backend, self._qjob_config, + self._backend_options, self._noise_config, + self._skip_qobj_validation, self._job_callback) + self._time_taken += result.time_taken + else: + # insert the calibration circuit into main qobj if the shots are the same + qobj.experiments[0:0] = cals_qobj.experiments + result = run_qobj(qobj, self._backend, self._qjob_config, + self._backend_options, self._noise_config, + self._skip_qobj_validation, self._job_callback) + self._time_taken += result.time_taken + cals_result = result logger.info("Building calibration matrix for measurement error mitigation.") meas_error_mitigation_fitter = \ @@ -380,7 +437,14 @@ def execute(self, self._meas_error_mitigation_fitters[qubit_index_str] = \ (meas_error_mitigation_fitter, time.time()) else: - result = run_qobj(qobj, self._backend, self._qjob_config, + result = run_circuits(circuits, + self._backend, + qjob_config=self.qjob_config, + backend_options=self.backend_options, + noise_config=self._noise_config, + run_config=self._run_config.to_dict(), + job_callback=self._job_callback) if circuit_job else \ + run_qobj(qobj, self._backend, self._qjob_config, self._backend_options, self._noise_config, self._skip_qobj_validation, self._job_callback) self._time_taken += result.time_taken @@ -406,7 +470,14 @@ def execute(self, result.results[n] = tmp_result.results[i] else: - result = run_qobj(qobj, self._backend, self._qjob_config, + result = run_circuits(circuits, + self._backend, + qjob_config=self.qjob_config, + backend_options=self.backend_options, + noise_config=self._noise_config, + run_config=self._run_config.to_dict(), + job_callback=self._job_callback) if circuit_job else \ + run_qobj(qobj, self._backend, self._qjob_config, self._backend_options, self._noise_config, self._skip_qobj_validation, self._job_callback) self._time_taken += result.time_taken diff --git a/qiskit/utils/run_circuits.py b/qiskit/utils/run_circuits.py index de8f2af94b53..c9895be31361 100644 --- a/qiskit/utils/run_circuits.py +++ b/qiskit/utils/run_circuits.py @@ -381,3 +381,184 @@ def run_on_backend(backend: Union[Backend, BaseBackend], else: job = backend.run(qobj, **backend_options, **noise_config) return job + + +def run_circuits(circuits: Union[QuantumCircuit, List[QuantumCircuit]], + backend: Union[Backend, BaseBackend], + qjob_config: Dict, + backend_options: Optional[Dict] = None, + noise_config: Optional[Dict] = None, + run_config: Optional[Dict] = None, + job_callback: Optional[Callable] = None) -> Result: + """ + An execution wrapper with Qiskit-Terra, with job auto recover capability. + + The auto-recovery feature is only applied for non-simulator backend. + This wrapper will try to get the result no matter how long it takes. + + Args: + circuits: circuits to execute + backend: backend instance + qjob_config: configuration for quantum job object + backend_options: backend options + noise_config: configuration for noise model + run_config: configuration for run + job_callback: callback used in querying info of the submitted job, and + providing the following arguments: + job_id, job_status, queue_position, job + + Returns: + Result object + + Raises: + QiskitError: Any error except for JobError raised by Qiskit Terra + """ + backend_options = backend_options or {} + noise_config = noise_config or {} + run_config = run_config or {} + with_autorecover = not is_simulator_backend(backend) + + job, job_id = _safe_submit_circuits(circuits, + backend, + qjob_config=qjob_config, + backend_options=backend_options, + noise_config=noise_config, + run_config=run_config) + result = None + if with_autorecover: + logger.info("Backend status: %s", backend.status()) + logger.info("There is one jobs are submitted: id: %s", job_id) + while True: + logger.info("Running job id: %s", job_id) + # try to get result if possible + while True: + job_status = _safe_get_job_status(job, job_id) + queue_position = 0 + if job_status in JOB_FINAL_STATES: + # do callback again after the job is in the final states + if job_callback is not None: + job_callback(job_id, job_status, queue_position, job) + break + if job_status == JobStatus.QUEUED and hasattr(job, queue_position): + queue_position = job.queue_position() + logger.info("Job id: %s is queued at position %s", job_id, queue_position) + else: + logger.info("Job id: %s, status: %s", job_id, job_status) + if job_callback is not None: + job_callback(job_id, job_status, queue_position, job) + time.sleep(qjob_config['wait']) + + # get result after the status is DONE + if job_status == JobStatus.DONE: + while True: + result = job.result() + if result.success: + logger.info("COMPLETED: job id: %s", job_id) + break + + logger.warning("FAILURE: Job id: %s", job_id) + logger.warning("Job (%s) is completed anyway, retrieve result " + "from backend again.", job_id) + job = backend.retrieve_job(job_id) + break + # for other cases, resubmit the circuit until the result is available. + # since if there is no result returned, there is no way algorithm can do any process + if job_status == JobStatus.CANCELLED: + logger.warning("FAILURE: Job id: %s is cancelled. Re-submit the circuits.", + job_id) + elif job_status == JobStatus.ERROR: + logger.warning("FAILURE: Job id: %s encounters the error. " + "Error is : %s. Re-submit the circuits.", + job_id, job.error_message()) + else: + logging.warning("FAILURE: Job id: %s. Unknown status: %s. " + "Re-submit the circuits.", job_id, job_status) + + job, job_id = _safe_submit_circuits(circuits, + backend, + qjob_config=qjob_config, + backend_options=backend_options, + noise_config=noise_config, + run_config=run_config) + else: + result = job.result() + + # If result was not successful then raise an exception with either the status msg or + # extra information if this was an Aer partial result return + if not result.success: + msg = result.status + if result.status == 'PARTIAL COMPLETED': + # Aer can return partial results which Aqua algorithms cannot process and signals + # using partial completed status where each returned result has a success and status. + # We use the status from the first result that was not successful + for res in result.results: + if not res.success: + msg += ', ' + res.status + break + raise QiskitError('Circuit execution failed: {}'.format(msg)) + + if not hasattr(result, 'time_taken'): + setattr(result, 'time_taken', 0.) + + return result + + +def _safe_submit_circuits(circuits: Union[QuantumCircuit, List[QuantumCircuit]], + backend: Union[Backend, BaseBackend], + qjob_config: Dict, + backend_options: Dict, + noise_config: Dict, + run_config: Dict) -> Tuple[BaseJob, str]: + # assure get job ids + while True: + try: + job = _run_circuits_on_backend(backend, + circuits, + backend_options=backend_options, + noise_config=noise_config, + run_config=run_config) + job_id = job.job_id() + break + except QiskitError as ex: + failure_warn = True + if is_ibmq_provider(backend): + try: + from qiskit.providers.ibmq import IBMQBackendJobLimitError + except ImportError as ex1: + raise MissingOptionalLibraryError( + libname='qiskit-ibmq-provider', + name='_safe_submit_circuits', + pip_install='pip install qiskit-ibmq-provider') from ex1 + if isinstance(ex, IBMQBackendJobLimitError): + + oldest_running = backend.jobs(limit=1, descending=False, + status=['QUEUED', 'VALIDATING', 'RUNNING']) + if oldest_running: + oldest_running = oldest_running[0] + logger.warning("Job limit reached, waiting for job %s to finish " + "before submitting the next one.", oldest_running.job_id()) + failure_warn = False # Don't issue a second warning. + try: + oldest_running.wait_for_final_state(timeout=qjob_config['timeout'], + wait=qjob_config['wait']) + except Exception: # pylint: disable=broad-except + # If the wait somehow fails or times out, we'll just re-try + # the job submit and see if it works now. + pass + if failure_warn: + logger.warning("FAILURE: Can not get job id, Resubmit the qobj to get job id. " + "Terra job error: %s ", ex) + except Exception as ex: # pylint: disable=broad-except + logger.warning("FAILURE: Can not get job id, Resubmit the qobj to get job id." + "Error: %s ", ex) + + return job, job_id + + +def _run_circuits_on_backend(backend: Union[Backend, BaseBackend], + circuits: Union[QuantumCircuit, List[QuantumCircuit]], + backend_options: Dict, + noise_config: Dict, + run_config: Dict) -> BaseJob: + """ run on backend """ + return backend.run(circuits, **backend_options, **noise_config, **run_config) diff --git a/test/python/algorithms/test_backendv1.py b/test/python/algorithms/test_backendv1.py new file mode 100644 index 000000000000..dd49d25f00ab --- /dev/null +++ b/test/python/algorithms/test_backendv1.py @@ -0,0 +1,128 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 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. + +""" Test Providers that support BackendV1 interface """ + +import unittest +from test.python.algorithms import QiskitAlgorithmsTestCase +from qiskit import QuantumCircuit +from qiskit.test.mock import FakeProvider +from qiskit.utils import QuantumInstance, algorithm_globals +from qiskit.algorithms import (Shor, VQE, + Grover, AmplificationProblem) +from qiskit.opflow import X, Z, I +from qiskit.algorithms.optimizers import SPSA +from qiskit.circuit.library import TwoLocal, EfficientSU2 + + +class TestBackendV1(QiskitAlgorithmsTestCase): + """test BackendV1 interface """ + + def setUp(self): + super().setUp() + self._provider = FakeProvider() + self._qasm = self._provider.get_backend('fake_qasm_simulator') + self.seed = 50 + + def test_shor_factoring(self): + """ shor factoring test """ + n_v = 15 + factors = [3, 5] + qasm_simulator = QuantumInstance(self._qasm, + shots=1000, + seed_simulator=self.seed, + seed_transpiler=self.seed) + shor = Shor(quantum_instance=qasm_simulator) + result = shor.factor(N=n_v) + self.assertListEqual(result.factors[0], factors) + self.assertTrue(result.total_counts >= result.successful_counts) + + def test_vqe_qasm(self): + """Test the VQE on QASM simulator.""" + h2_op = -1.052373245772859 * (I ^ I) \ + + 0.39793742484318045 * (I ^ Z) \ + - 0.39793742484318045 * (Z ^ I) \ + - 0.01128010425623538 * (Z ^ Z) \ + + 0.18093119978423156 * (X ^ X) + optimizer = SPSA(maxiter=300, last_avg=5) + wavefunction = TwoLocal(rotation_blocks='ry', entanglement_blocks='cz') + qasm_simulator = QuantumInstance(self._qasm, + shots=1024, + seed_simulator=self.seed, + seed_transpiler=self.seed) + vqe = VQE(ansatz=wavefunction, + optimizer=optimizer, + max_evals_grouped=1, + quantum_instance=qasm_simulator) + + result = vqe.compute_minimum_eigenvalue(operator=h2_op) + self.assertAlmostEqual(result.eigenvalue.real, -1.86, delta=0.05) + + def test_run_circuit_oracle(self): + """Test execution with a quantum circuit oracle""" + oracle = QuantumCircuit(2) + oracle.cz(0, 1) + problem = AmplificationProblem(oracle, is_good_state=['11']) + qi = QuantumInstance(self._provider.get_backend('fake_yorktown'), + seed_simulator=12, + seed_transpiler=32) + grover = Grover(quantum_instance=qi) + result = grover.amplify(problem) + self.assertIn(result.top_measurement, ['11']) + + def test_measurement_error_mitigation_with_vqe(self): + """ measurement error mitigation test with vqe """ + try: + from qiskit.ignis.mitigation.measurement import CompleteMeasFitter + from qiskit.providers.aer import noise + except ImportError as ex: + self.skipTest("Package doesn't appear to be installed. Error: '{}'".format(str(ex))) + return + + algorithm_globals.random_seed = 0 + + # build noise model + noise_model = noise.NoiseModel() + read_err = noise.errors.readout_error.ReadoutError([[0.9, 0.1], [0.25, 0.75]]) + noise_model.add_all_qubit_readout_error(read_err) + + backend = self._qasm + + quantum_instance = QuantumInstance( + backend=backend, + seed_simulator=167, + seed_transpiler=167, + noise_model=noise_model, + measurement_error_mitigation_cls=CompleteMeasFitter + ) + + h2_hamiltonian = -1.052373245772859 * (I ^ I) \ + + 0.39793742484318045 * (I ^ Z) \ + - 0.39793742484318045 * (Z ^ I) \ + - 0.01128010425623538 * (Z ^ Z) \ + + 0.18093119978423156 * (X ^ X) + optimizer = SPSA(maxiter=200) + ansatz = EfficientSU2(2, reps=1) + + vqe = VQE( + ansatz=ansatz, + optimizer=optimizer, + quantum_instance=quantum_instance + ) + result = vqe.compute_minimum_eigenvalue(operator=h2_hamiltonian) + self.assertGreater(quantum_instance.time_taken, 0.) + quantum_instance.reset_execution_results() + self.assertAlmostEqual(result.eigenvalue.real, -1.86, delta=0.05) + + +if __name__ == '__main__': + unittest.main() From 6e6bee16859db2546317cc07721d88732eea1628 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 3 May 2021 14:33:40 -0400 Subject: [PATCH 2/3] Remove tests that depend on BackendV1 fake backends 2 of the tests added in #6299 depend on the fake backends in qiskit.test.mock being strict BackendV1 backends (that reject qobj) and also having other aspects of the interface implemented (mainly run kwargs). However the change which updated the fake backends to use BackendV1 (#6286) is not backportable as it's an API change, so these tests are runnable in stable/0.17. This commit just removes these tests because even if we could get them running without #6286 we wouldn't be actually testing the v1 interface (which is their purpose). --- test/python/algorithms/test_backendv1.py | 56 ------------------------ 1 file changed, 56 deletions(-) diff --git a/test/python/algorithms/test_backendv1.py b/test/python/algorithms/test_backendv1.py index dd49d25f00ab..4b6648f2bb5c 100644 --- a/test/python/algorithms/test_backendv1.py +++ b/test/python/algorithms/test_backendv1.py @@ -67,62 +67,6 @@ def test_vqe_qasm(self): result = vqe.compute_minimum_eigenvalue(operator=h2_op) self.assertAlmostEqual(result.eigenvalue.real, -1.86, delta=0.05) - def test_run_circuit_oracle(self): - """Test execution with a quantum circuit oracle""" - oracle = QuantumCircuit(2) - oracle.cz(0, 1) - problem = AmplificationProblem(oracle, is_good_state=['11']) - qi = QuantumInstance(self._provider.get_backend('fake_yorktown'), - seed_simulator=12, - seed_transpiler=32) - grover = Grover(quantum_instance=qi) - result = grover.amplify(problem) - self.assertIn(result.top_measurement, ['11']) - - def test_measurement_error_mitigation_with_vqe(self): - """ measurement error mitigation test with vqe """ - try: - from qiskit.ignis.mitigation.measurement import CompleteMeasFitter - from qiskit.providers.aer import noise - except ImportError as ex: - self.skipTest("Package doesn't appear to be installed. Error: '{}'".format(str(ex))) - return - - algorithm_globals.random_seed = 0 - - # build noise model - noise_model = noise.NoiseModel() - read_err = noise.errors.readout_error.ReadoutError([[0.9, 0.1], [0.25, 0.75]]) - noise_model.add_all_qubit_readout_error(read_err) - - backend = self._qasm - - quantum_instance = QuantumInstance( - backend=backend, - seed_simulator=167, - seed_transpiler=167, - noise_model=noise_model, - measurement_error_mitigation_cls=CompleteMeasFitter - ) - - h2_hamiltonian = -1.052373245772859 * (I ^ I) \ - + 0.39793742484318045 * (I ^ Z) \ - - 0.39793742484318045 * (Z ^ I) \ - - 0.01128010425623538 * (Z ^ Z) \ - + 0.18093119978423156 * (X ^ X) - optimizer = SPSA(maxiter=200) - ansatz = EfficientSU2(2, reps=1) - - vqe = VQE( - ansatz=ansatz, - optimizer=optimizer, - quantum_instance=quantum_instance - ) - result = vqe.compute_minimum_eigenvalue(operator=h2_hamiltonian) - self.assertGreater(quantum_instance.time_taken, 0.) - quantum_instance.reset_execution_results() - self.assertAlmostEqual(result.eigenvalue.real, -1.86, delta=0.05) - if __name__ == '__main__': unittest.main() From d083e731e4658ade084200d34947bb92cbdd1a49 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 3 May 2021 14:56:13 -0400 Subject: [PATCH 3/3] Fix lint --- test/python/algorithms/test_backendv1.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/python/algorithms/test_backendv1.py b/test/python/algorithms/test_backendv1.py index 4b6648f2bb5c..7249af0dfa9d 100644 --- a/test/python/algorithms/test_backendv1.py +++ b/test/python/algorithms/test_backendv1.py @@ -14,14 +14,12 @@ import unittest from test.python.algorithms import QiskitAlgorithmsTestCase -from qiskit import QuantumCircuit from qiskit.test.mock import FakeProvider -from qiskit.utils import QuantumInstance, algorithm_globals -from qiskit.algorithms import (Shor, VQE, - Grover, AmplificationProblem) +from qiskit.utils import QuantumInstance +from qiskit.algorithms import Shor, VQE from qiskit.opflow import X, Z, I from qiskit.algorithms.optimizers import SPSA -from qiskit.circuit.library import TwoLocal, EfficientSU2 +from qiskit.circuit.library import TwoLocal class TestBackendV1(QiskitAlgorithmsTestCase):