From 526d9fcee78b090a1fa532af1781ea0fde0d0685 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 1 Feb 2022 18:09:24 -0500 Subject: [PATCH] Fix QuantumInstance compatibility with BackendV2 (Qiskit/qiskit-terra#7563) * Fix QuantumInstance compatibility with BackendV2 This commit fixes compatibility with the QuantumInstance class when targetting a BackendV2 backend. When BackendV2 was introduced testing with the QuantumInstance (and therefore all of qiskit.algorithms) was neglected and there are several compatibility issues with the class around hard coded assumptions that the backend being wrapped was a BaseBackend or BackendV1 object. * Remove invalid test The tests for the QuantumInstance with BackendV2 were just ported over from the equivalent testing with BackendV1. However, one of those tests was to test error mitigation with a custom noise model which requires qiskit-aer. We can't test this without aer having been migrated to BackendV2. Until qiskit-aer is backendv2 enabled this commit just removes the test. * Remove unused imports * Remove duplicate backend version checks from QuantumInstance The QuantumInstance's is_simulator() and is_local() methods had duplicate checking on the backend version. This was an artifact of testing where in earlier revisions of this PR branch it was done in the QuantumInstance before being moved to the inner helper functions. Since the helper functions are updated to handle the version checking now we no longer need it in the QuantumInstance methods too. This commit removes this and just relies on the helper functions to do the version checking. * Use more descriptive local variable name for backend version This commit attempts to clarify how the version fields are used by naming the local variables backend_interface_version to make it clear what we're checking in that context. * Fix handling of statevector simulator check for BackendV2 This commit fixes the check for whether we're running with a statevector simulator (to determine whether we need to insert save_statevector instructions) to be BackendV2 compatible. This isn't strictly needed yet as qiskit-aer is still based on BackendV1, but this would cause a bug when it does switch to the newer backend version. This commit just gets in front of that potential issue so we don't have a bug in the future. * Use backend_interface_version everywhere There were a few straglers still using backend_version instead of backend_interface_version in the code. This commit updates all these instances so there is consistent naming around this inside the utils subpackage. * Fix handling of statevector simulator detection This commit fixes an oversight from an earlier development version that slipped through later revisions where the statevector simulator backend detection in the QuantumInstance class was hard coded to False for BackendV2. This was just meant as a temporary debugging step while getting the initial commit ready, but was never updated to remove this until now. * Actually commit local variable backend_interface_version renames * Fix typo Co-authored-by: Jake Lishman Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- test/test_backendv2.py | 100 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 test/test_backendv2.py diff --git a/test/test_backendv2.py b/test/test_backendv2.py new file mode 100644 index 00000000..e96d5d21 --- /dev/null +++ b/test/test_backendv2.py @@ -0,0 +1,100 @@ +# 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 BackendV2 interface """ + +import unittest +from test.python.algorithms import QiskitAlgorithmsTestCase +from qiskit import QuantumCircuit +from qiskit.test.mock import FakeProvider +from qiskit.test.mock.fake_backend_v2 import FakeBackendSimple +from qiskit.utils import QuantumInstance +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 + + +class TestBackendV2(QiskitAlgorithmsTestCase): + """test BackendV2 interface""" + + def setUp(self): + super().setUp() + self._provider = FakeProvider() + self._qasm = FakeBackendSimple() + 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_run_circuit_oracle_single_experiment_backend(self): + """Test execution with a quantum circuit oracle""" + oracle = QuantumCircuit(2) + oracle.cz(0, 1) + problem = AmplificationProblem(oracle, is_good_state=["11"]) + backend = self._provider.get_backend("fake_yorktown") + backend._configuration.max_experiments = 1 + 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"]) + + +if __name__ == "__main__": + unittest.main()