Exemple #1
0
    def __init__(self,
                 input_size: int,
                 hidden_size: int,
                 n_qubits: int = 4,
                 n_qlayers: int = 1,
                 batch_first=True,
                 backend='statevector_simulator'):
        super(QLSTM, self).__init__()

        self.input_size = input_size
        self.hidden_size = hidden_size
        self.concat_size = input_size + hidden_size
        self.n_qubits = n_qubits
        self.n_qlayers = n_qlayers
        self.batch_first = batch_first

        self.clayer_in = nn.Linear(self.concat_size, n_qubits)
        self.clayer_out = nn.Linear(self.n_qubits, self.hidden_size)

        self.qi = QuantumInstance(Aer.get_backend('statevector_simulator'))
        feature_map = ZZFeatureMap(self.n_qubits)
        ansatz = RealAmplitudes(self.n_qubits, reps=self.n_qlayers)

        self.qnn1 = TwoLayerQNN(self.n_qubits,
                                feature_map,
                                ansatz,
                                exp_val=AerPauliExpectation(),
                                quantum_instance=self.qi)
        self.qnn2 = TwoLayerQNN(self.n_qubits,
                                feature_map,
                                ansatz,
                                exp_val=AerPauliExpectation(),
                                quantum_instance=self.qi)
        self.qnn3 = TwoLayerQNN(self.n_qubits,
                                feature_map,
                                ansatz,
                                exp_val=AerPauliExpectation(),
                                quantum_instance=self.qi)
        self.qnn4 = TwoLayerQNN(self.n_qubits,
                                feature_map,
                                ansatz,
                                exp_val=AerPauliExpectation(),
                                quantum_instance=self.qi)

        self.qlayer = {
            'forget': TorchConnector(self.qnn1),
            'input': TorchConnector(self.qnn2),
            'update': TorchConnector(self.qnn3),
            'output': TorchConnector(self.qnn4)
        }
Exemple #2
0
    def setUp(self) -> None:
        super().setUp()
        try:
            from qiskit import Aer

            self.seed = 97
            self.backend = Aer.get_backend("aer_simulator")
            q_instance = QuantumInstance(
                self.backend, seed_simulator=self.seed, seed_transpiler=self.seed
            )
            self.sampler = CircuitSampler(q_instance, attach_results=True)
            self.expect = AerPauliExpectation()
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest("Aer doesn't appear to be installed. Error: '{}'".format(str(ex)))
            return
    def test_eval_op_qasm_aer(self):
        """Regression tests against https://github.com/Qiskit/qiskit-nature/issues/53."""
        try:
            # pylint: disable=import-outside-toplevel
            # pylint: disable=unused-import
            from qiskit import Aer

            backend = Aer.get_backend("aer_simulator")
        except ImportError as ex:  # pylint: disable=broad-except
            self.skipTest(f"Aer doesn't appear to be installed. Error: '{str(ex)}'")
            return

        solver = VQEUCCFactory(
            optimizer=SLSQP(maxiter=100),
            expectation=AerPauliExpectation(),
            include_custom=True,
            quantum_instance=QuantumInstance(
                backend=backend,
                seed_simulator=algorithm_globals.random_seed,
                seed_transpiler=algorithm_globals.random_seed,
            ),
        )
        calc = GroundStateEigensolver(self.qubit_converter, solver)
        res_qasm = calc.solve(self.electronic_structure_problem)

        hamiltonian = self.electronic_structure_problem.second_q_ops()[0]
        qubit_op = self.qubit_converter.map(hamiltonian)

        ansatz = solver.get_solver(self.electronic_structure_problem, self.qubit_converter).ansatz
        circuit = ansatz.assign_parameters(res_qasm.raw_result.optimal_point)
        mean = calc.evaluate_operators(circuit, qubit_op)

        self.assertAlmostEqual(res_qasm.eigenenergies[0], mean[0].real)
Exemple #4
0
    def test_vqe_expectation_select(self):
        """Test expectation selection with Aer's qasm_simulator."""
        try:
            # pylint: disable=import-outside-toplevel
            from qiskit import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')

        with self.subTest('Defaults'):
            vqe = VQE(self.h2_op, quantum_instance=backend)
            self.assertIsInstance(vqe.expectation, PauliExpectation)

        with self.subTest('Include custom'):
            vqe = VQE(self.h2_op,
                      include_custom=True,
                      quantum_instance=backend)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)

        with self.subTest('Set explicitly'):
            vqe = VQE(self.h2_op,
                      expectation=AerPauliExpectation(),
                      quantum_instance=backend)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)
Exemple #5
0
    def test_vqe_expectation_select(self):
        """Test expectation selection with Aer's qasm_simulator."""
        try:
            from qiskit.providers.aer import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')

        with self.subTest('Defaults'):
            vqe = VQE(quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, PauliExpectation)

        with self.subTest('Include custom'):
            vqe = VQE(include_custom=True, quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)

        with self.subTest('Set explicitly'):
            vqe = VQE(expectation=AerPauliExpectation(),
                      quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)
Exemple #6
0
    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQE using Aer's qasm_simulator snapshot mode."""
        try:
            from qiskit.providers.aer import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')
        optimizer = L_BFGS_B()
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            shots=1,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed)
        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  expectation=AerPauliExpectation(),
                  quantum_instance=quantum_instance)

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)
    def test_eval_op_qasm_aer(self):
        """Regression tests against https://github.com/Qiskit/qiskit-nature/issues/53."""

        backend = qiskit.providers.aer.Aer.get_backend("aer_simulator")

        solver = VQEUCCFactory(
            optimizer=SLSQP(maxiter=100),
            expectation=AerPauliExpectation(),
            include_custom=True,
            quantum_instance=QuantumInstance(
                backend=backend,
                seed_simulator=algorithm_globals.random_seed,
                seed_transpiler=algorithm_globals.random_seed,
            ),
        )
        calc = GroundStateEigensolver(self.qubit_converter, solver)
        res_qasm = calc.solve(self.electronic_structure_problem)

        hamiltonian = self.electronic_structure_problem.second_q_ops()[
            self.electronic_structure_problem.main_property_name]
        qubit_op = self.qubit_converter.map(hamiltonian)

        ansatz = solver.get_solver(self.electronic_structure_problem,
                                   self.qubit_converter).ansatz
        circuit = ansatz.assign_parameters(res_qasm.raw_result.optimal_point)
        mean = calc.evaluate_operators(circuit, qubit_op)

        self.assertAlmostEqual(res_qasm.eigenenergies[0], mean[0].real)
    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQD using Aer's qasm_simulator snapshot mode."""

        backend = Aer.get_backend("aer_simulator")
        optimizer = COBYLA(maxiter=400)
        wavefunction = self.ryrz_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            shots=100,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqd = VQD(
            k=2,
            ansatz=wavefunction,
            optimizer=optimizer,
            expectation=AerPauliExpectation(),
            quantum_instance=quantum_instance,
        )

        result = vqd.compute_eigenvalues(operator=self.test_op)
        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.test_results,
                                             decimal=1)
Exemple #9
0
 def test_list_pauli_sum(self):
     """Test AerPauliExpectation for ListOp[PauliSumOp]"""
     test_op = ListOp([PauliSumOp.from_list([("XX", 1), ("ZI", 3), ("ZZ", 5)])])
     observable = AerPauliExpectation().convert(~StateFn(test_op))
     self.assertIsInstance(observable, ListOp)
     self.assertIsInstance(observable[0], CircuitStateFn)
     self.assertTrue(observable[0].is_measurement)
    def test_uccsd_hf_aer_qasm_snapshot(self):
        """uccsd hf test with Aer qasm simulator snapshot."""
        try:
            # pylint: disable=import-outside-toplevel
            from qiskit import Aer

            backend = Aer.get_backend("aer_simulator")
        except ImportError as ex:  # pylint: disable=broad-except
            self.skipTest(f"Aer doesn't appear to be installed. Error: '{str(ex)}'")
            return

        ansatz = self._prepare_uccsd_hf(self.qubit_converter)

        optimizer = SPSA(maxiter=200, last_avg=5)
        solver = VQE(
            ansatz=ansatz,
            optimizer=optimizer,
            expectation=AerPauliExpectation(),
            quantum_instance=QuantumInstance(backend=backend),
        )

        gsc = GroundStateEigensolver(self.qubit_converter, solver)

        result = gsc.solve(self.electronic_structure_problem)
        self.assertAlmostEqual(result.total_energies[0], self.reference_energy, places=3)
Exemple #11
0
    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQE using Aer's qasm_simulator snapshot mode."""
        try:
            # pylint: disable=import-outside-toplevel
            from qiskit import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')
        optimizer = L_BFGS_B()
        wavefunction = self.ry_wavefunction

        vqe = VQE(self.h2_op,
                  wavefunction,
                  optimizer,
                  expectation=AerPauliExpectation())

        quantum_instance = QuantumInstance(
            backend,
            shots=1,
            seed_simulator=aqua_globals.random_seed,
            seed_transpiler=aqua_globals.random_seed)
        result = vqe.run(quantum_instance)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)
    def test_aux_operator_std_dev_aer_pauli(self):
        """Test non-zero standard deviations of aux operators with AerPauliExpectation."""
        wavefunction = self.ry_wavefunction
        vqe = VQE(
            ansatz=wavefunction,
            expectation=AerPauliExpectation(),
            optimizer=COBYLA(maxiter=0),
            quantum_instance=QuantumInstance(
                backend=Aer.get_backend("qasm_simulator"),
                shots=1,
                seed_simulator=algorithm_globals.random_seed,
                seed_transpiler=algorithm_globals.random_seed,
            ),
        )

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = [aux_op1, aux_op2]
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0],
                               2.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0],
                               0.6698863565455391,
                               places=6)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1],
                               0.0,
                               places=6)

        # Go again with additional None and zero operators
        aux_ops = [*aux_ops, None, 0]
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues), 4)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0],
                               2.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0],
                               0.6036400943063891,
                               places=6)
        self.assertEqual(result.aux_operator_eigenvalues[2][0], 0.0)
        self.assertEqual(result.aux_operator_eigenvalues[3][0], 0.0)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1],
                               0.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[2][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[3][1], 0.0)
    def test_setters_getters(self):
        """ Test Getter/Setter """

        # quantum instance
        self.assertEqual(self._vqe_uccsd_factory.quantum_instance,
                         self.quantum_instance)
        self._vqe_uccsd_factory.quantum_instance = None
        self.assertEqual(self._vqe_uccsd_factory.quantum_instance, None)

        # optimizer
        self.assertEqual(self._vqe_uccsd_factory.optimizer, None)
        optimizer = COBYLA()
        self._vqe_uccsd_factory.optimizer = optimizer
        self.assertEqual(self._vqe_uccsd_factory.optimizer, optimizer)

        # initial point
        self.assertEqual(self._vqe_uccsd_factory.initial_point, None)
        initial_point = [1, 2, 3]
        self._vqe_uccsd_factory.initial_point = initial_point
        self.assertEqual(self._vqe_uccsd_factory.initial_point, initial_point)

        # expectation
        self.assertEqual(self._vqe_uccsd_factory.expectation, None)
        expectation = AerPauliExpectation()
        self._vqe_uccsd_factory.expectation = expectation
        self.assertEqual(self._vqe_uccsd_factory.expectation, expectation)

        # include_custom
        self.assertEqual(self._vqe_uccsd_factory.include_custom, False)
        self._vqe_uccsd_factory.include_custom = True
        self.assertEqual(self._vqe_uccsd_factory.include_custom, True)

        # method_singles
        self.assertEqual(self._vqe_uccsd_factory.method_singles, 'both')
        self._vqe_uccsd_factory.method_singles = 'alpha'
        self.assertEqual(self._vqe_uccsd_factory.method_singles, 'alpha')

        # method_doubles
        self.assertEqual(self._vqe_uccsd_factory.method_doubles, 'ucc')
        self._vqe_uccsd_factory.method_doubles = 'succ'
        self.assertEqual(self._vqe_uccsd_factory.method_doubles, 'succ')

        # excitation_type
        self.assertEqual(self._vqe_uccsd_factory.excitation_type, 'sd')
        self._vqe_uccsd_factory.excitation_type = 's'
        self.assertEqual(self._vqe_uccsd_factory.excitation_type, 's')

        # same_spin_doubles
        self.assertEqual(self._vqe_uccsd_factory.same_spin_doubles, True)
        self._vqe_uccsd_factory.same_spin_doubles = False
        self.assertEqual(self._vqe_uccsd_factory.same_spin_doubles, False)
Exemple #14
0
 def deprecation_setters_getters(self):
     """
     Test Getter/Setter for the deprecated properties.
     Can be removed once the properties are removed.
     """
     with warnings.catch_warnings():
         warnings.filterwarnings("ignore", category=DeprecationWarning)
         self.auxiliary_tester(
             "Quantum Instance",
             "quantum_instance",
             (self.quantum_instance, self.quantum_instance_2),
         )
         self.auxiliary_tester("Expectation", "expectation", (None, AerPauliExpectation()))
         self.auxiliary_tester("Include Custom", "include_custom", (False, True))
         self.auxiliary_tester("Callback", "callback", (None, None))
         self.auxiliary_tester_isinstance("Optimizer", "optimizer", (SLSQP, COBYLA))
 def test_with_gradient(self, optimizer):
     """Test VQE using Gradient()."""
     quantum_instance = QuantumInstance(
         backend=Aer.get_backend("qasm_simulator"),
         shots=1,
         seed_simulator=algorithm_globals.random_seed,
         seed_transpiler=algorithm_globals.random_seed,
     )
     vqe = VQE(
         ansatz=self.ry_wavefunction,
         optimizer=optimizer,
         gradient=Gradient(),
         expectation=AerPauliExpectation(),
         quantum_instance=quantum_instance,
         max_evals_grouped=1000,
     )
     vqe.compute_minimum_eigenvalue(operator=self.h2_op)
    def __init__(self, h, w, outputs):
        super(DQN, self).__init__()
        # We did a lot of experimentation with model sizes and types, so we decided to leave some
        # of our attempts here
        #1
        # self.conv1 = nn.Conv2d(1, 16, kernel_size=5, stride=2)
        # self.bn1 = nn.BatchNorm2d(16)
        # self.conv2 = nn.Conv2d(16, 32, kernel_size=5, stride=2)
        # self.bn2 = nn.BatchNorm2d(32)
        # self.conv3 = nn.Conv2d(32, 32, kernel_size=5, stride=2)
        # self.bn3 = nn.BatchNorm2d(32)

        #2
        # # Number of Linear input connections depends on output of conv2d layers
        # # and therefore the input image size, so compute it.
        # def conv2d_size_out(size, kernel_size = 5, stride = 2):
        #     return (size - (kernel_size - 1) - 1) // stride  + 1
        # convw = conv2d_size_out(conv2d_size_out(conv2d_size_out(w)))
        # convh = conv2d_size_out(conv2d_size_out(conv2d_size_out(h)))
        # linear_input_size = convw * convh * 32

        #3
        # self.conv1 = nn.Conv2d(1, 128, kernel_size=2, stride=1, padding=1)
        # self.bn1 = nn.BatchNorm2d(128)
        # self.conv2 = nn.Conv2d(128, 256, kernel_size=5, stride=1, padding=1)
        # self.bn2 = nn.BatchNorm2d(256)
        # self.fcl1 = nn.Linear(12544,5000)
        # self.fcl2 = nn.Linear(5000, 64)
        qi = QuantumInstance(Aer.get_backend('statevector_simulator'))

        feature_map = ZZFeatureMap(4)
        ansatz = RealAmplitudes(4, reps=1)
        qnn = TwoLayerQNN(4,
                          feature_map,
                          ansatz,
                          exp_val=AerPauliExpectation(),
                          quantum_instance=qi)

        #4
        # Our final network choice. It is wide enough to capture a lot of detail but not too
        # large to have problems with vanishing gradients on such a small sample size
        self.conv1 = nn.Conv2d(1, 256, kernel_size=2, stride=1, padding=1)
        self.bn1 = nn.BatchNorm2d(256)
        self.fcl1 = nn.Linear(20736, 10000)
        self.fcl2 = nn.Linear(10000, 4)
        self.qnn = TorchConnector(qnn)
    def test_setters_getters(self):
        """Test Getter/Setter"""

        with self.subTest("Quantum Instance"):
            self.assertEqual(self._vqe_ucc_factory.quantum_instance,
                             self.quantum_instance)
            self._vqe_ucc_factory.quantum_instance = None
            self.assertEqual(self._vqe_ucc_factory.quantum_instance, None)

        with self.subTest("Optimizer"):
            self.assertEqual(self._vqe_ucc_factory.optimizer, None)
            optimizer = COBYLA()
            self._vqe_ucc_factory.optimizer = optimizer
            self.assertEqual(self._vqe_ucc_factory.optimizer, optimizer)

        with self.subTest("Initial Point"):
            self.assertEqual(self._vqe_ucc_factory.initial_point, None)
            initial_point = [1, 2, 3]
            self._vqe_ucc_factory.initial_point = initial_point
            self.assertEqual(self._vqe_ucc_factory.initial_point,
                             initial_point)

        with self.subTest("Expectation"):
            self.assertEqual(self._vqe_ucc_factory.expectation, None)
            expectation = AerPauliExpectation()
            self._vqe_ucc_factory.expectation = expectation
            self.assertEqual(self._vqe_ucc_factory.expectation, expectation)

        with self.subTest("Include Custom"):
            self.assertEqual(self._vqe_ucc_factory.include_custom, False)
            self._vqe_ucc_factory.include_custom = True
            self.assertEqual(self._vqe_ucc_factory.include_custom, True)

        with self.subTest("Ansatz"):
            self.assertEqual(self._vqe_ucc_factory.ansatz, None)
            ansatz = UCCSD()
            self._vqe_ucc_factory.ansatz = ansatz
            self.assertTrue(isinstance(self._vqe_ucc_factory.ansatz, UCCSD))

        with self.subTest("Initial State"):
            self.assertEqual(self._vqe_ucc_factory.initial_state, None)
            initial_state = HartreeFock(4, (1, 1), self.converter)
            self._vqe_ucc_factory.initial_state = initial_state
            self.assertEqual(self._vqe_ucc_factory.initial_state,
                             initial_state)
    def test_uccsd_hf_aer_qasm_snapshot(self):
        """ uccsd hf test with Aer qasm_simulator snapshot. """
        try:
            # pylint: disable=import-outside-toplevel
            from qiskit import Aer
            backend = Aer.get_backend('qasm_simulator')
        except ImportError as ex:  # pylint: disable=broad-except
            self.skipTest("Aer doesn't appear to be installed. Error: '{}'".format(str(ex)))
            return
        optimizer = SPSA(maxiter=200, last_avg=5)
        solver = VQE(var_form=self.var_form, optimizer=optimizer,
                     expectation=AerPauliExpectation(),
                     quantum_instance=QuantumInstance(backend=backend))

        gsc = GroundStateEigensolver(self.fermionic_transformation, solver)

        result = gsc.solve(self.driver)
        self.assertAlmostEqual(result.total_energies[0], self.reference_energy, places=3)
Exemple #19
0
    def test_vqe_expectation_select(self):
        """Test expectation selection with Aer's qasm_simulator."""
        backend = Aer.get_backend("aer_simulator")

        with self.subTest("Defaults"):
            vqe = VQE(quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, PauliExpectation)

        with self.subTest("Include custom"):
            vqe = VQE(include_custom=True, quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)

        with self.subTest("Set explicitly"):
            vqe = VQE(expectation=AerPauliExpectation(),
                      quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)
    def test_uccsd_hf_aer_qasm_snapshot(self):
        """uccsd hf test with Aer qasm simulator snapshot."""

        backend = qiskit.providers.aer.Aer.get_backend("aer_simulator")

        ansatz = self._prepare_uccsd_hf(self.qubit_converter)

        optimizer = SPSA(maxiter=200, last_avg=5)
        solver = VQE(
            ansatz=ansatz,
            optimizer=optimizer,
            expectation=AerPauliExpectation(),
            quantum_instance=QuantumInstance(backend=backend),
        )

        gsc = GroundStateEigensolver(self.qubit_converter, solver)

        result = gsc.solve(self.electronic_structure_problem)
        self.assertAlmostEqual(result.total_energies[0],
                               self.reference_energy,
                               places=3)
Exemple #21
0
    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQE using Aer's qasm_simulator snapshot mode."""

        backend = Aer.get_backend("aer_simulator")
        optimizer = L_BFGS_B()
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            shots=1,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            expectation=AerPauliExpectation(),
            quantum_instance=quantum_instance,
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy, places=6)
Exemple #22
0
class TestVQE(QiskitAlgorithmsTestCase):
    """ Test VQE """
    def setUp(self):
        super().setUp()
        self.seed = 50
        algorithm_globals.random_seed = self.seed
        self.h2_op = -1.052373245772859 * (I ^ I) \
            + 0.39793742484318045 * (I ^ Z) \
            - 0.39793742484318045 * (Z ^ I) \
            - 0.01128010425623538 * (Z ^ Z) \
            + 0.18093119978423156 * (X ^ X)
        self.h2_energy = -1.85727503

        self.ryrz_wavefunction = TwoLocal(rotation_blocks=['ry', 'rz'],
                                          entanglement_blocks='cz')
        self.ry_wavefunction = TwoLocal(rotation_blocks='ry',
                                        entanglement_blocks='cz')

        self.qasm_simulator = QuantumInstance(
            BasicAer.get_backend('qasm_simulator'),
            shots=1024,
            seed_simulator=self.seed,
            seed_transpiler=self.seed)
        self.statevector_simulator = QuantumInstance(
            BasicAer.get_backend('statevector_simulator'),
            shots=1,
            seed_simulator=self.seed,
            seed_transpiler=self.seed)

    def test_basic_aer_statevector(self):
        """Test the VQE on BasicAer's statevector simulator."""
        wavefunction = self.ryrz_wavefunction
        vqe = VQE(ansatz=wavefunction,
                  optimizer=L_BFGS_B(),
                  quantum_instance=QuantumInstance(
                      BasicAer.get_backend('statevector_simulator'),
                      basis_gates=['u1', 'u2', 'u3', 'cx', 'id'],
                      coupling_map=[[0, 1]],
                      seed_simulator=algorithm_globals.random_seed,
                      seed_transpiler=algorithm_globals.random_seed))

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        with self.subTest(msg='test eigenvalue'):
            self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy)

        with self.subTest(msg='test dimension of optimal point'):
            self.assertEqual(len(result.optimal_point), 16)

        with self.subTest(msg='assert cost_function_evals is set'):
            self.assertIsNotNone(result.cost_function_evals)

        with self.subTest(msg='assert optimizer_time is set'):
            self.assertIsNotNone(result.optimizer_time)

    def test_circuit_input(self):
        """Test running the VQE on a plain QuantumCircuit object."""
        wavefunction = QuantumCircuit(2).compose(EfficientSU2(2))
        optimizer = SLSQP(maxiter=50)
        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  quantum_instance=self.statevector_simulator)
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=5)

    @data(
        (MatrixExpectation(), 1),
        (AerPauliExpectation(), 1),
        (PauliExpectation(), 2),
    )
    @unpack
    def test_construct_circuit(self, expectation, num_circuits):
        """Test construct circuits returns QuantumCircuits and the right number of them."""
        try:
            wavefunction = EfficientSU2(2, reps=1)
            vqe = VQE(ansatz=wavefunction, expectation=expectation)
            params = [0] * wavefunction.num_parameters
            circuits = vqe.construct_circuit(parameter=params,
                                             operator=self.h2_op)

            self.assertEqual(len(circuits), num_circuits)
            for circuit in circuits:
                self.assertIsInstance(circuit, QuantumCircuit)
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
            return

    def test_missing_varform_params(self):
        """Test specifying a variational form with no parameters raises an error."""
        circuit = QuantumCircuit(self.h2_op.num_qubits)
        vqe = VQE(
            ansatz=circuit,
            quantum_instance=BasicAer.get_backend('statevector_simulator'))
        with self.assertRaises(RuntimeError):
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)

    @data(
        (SLSQP(maxiter=50), 5, 4),
        (SPSA(maxiter=150), 3, 2),  # max_evals_grouped=n or =2 if n>2
    )
    @unpack
    def test_max_evals_grouped(self, optimizer, places, max_evals_grouped):
        """ VQE Optimizers test """
        vqe = VQE(ansatz=self.ryrz_wavefunction,
                  optimizer=optimizer,
                  max_evals_grouped=max_evals_grouped,
                  quantum_instance=self.statevector_simulator)
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=places)

    def test_basic_aer_qasm(self):
        """Test the VQE on BasicAer's QASM simulator."""
        optimizer = SPSA(maxiter=300, last_avg=5)
        wavefunction = self.ry_wavefunction

        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  max_evals_grouped=1,
                  quantum_instance=self.qasm_simulator)

        # TODO benchmark this later.
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real, -1.86823, places=2)

    def test_qasm_aux_operators_normalized(self):
        """Test VQE with qasm_simulator returns normalized aux_operator eigenvalues."""
        wavefunction = self.ry_wavefunction
        vqe = VQE(ansatz=wavefunction, quantum_instance=self.qasm_simulator)
        _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        opt_params = [
            3.50437328, 3.87415376, 0.93684363, 5.92219622, -1.53527887,
            1.87941418, -4.5708326, 0.70187027
        ]

        vqe._ret.optimal_point = opt_params
        vqe._ret.optimal_parameters = \
            dict(zip(sorted(wavefunction.parameters, key=lambda p: p.name), opt_params))

        optimal_vector = vqe.get_optimal_vector()
        self.assertAlmostEqual(sum([v**2 for v in optimal_vector.values()]),
                               1.0,
                               places=4)

    def test_with_aer_statevector(self):
        """Test VQE with Aer's statevector_simulator."""
        try:
            from qiskit.providers.aer import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('statevector_simulator')
        wavefunction = self.ry_wavefunction
        optimizer = L_BFGS_B()

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed)
        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  max_evals_grouped=1,
                  quantum_instance=quantum_instance)

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)

    def test_with_aer_qasm(self):
        """Test VQE with Aer's qasm_simulator."""
        try:
            from qiskit.providers.aer import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')
        optimizer = SPSA(maxiter=200, last_avg=5)
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed)

        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  expectation=PauliExpectation(),
                  quantum_instance=quantum_instance)

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        self.assertAlmostEqual(result.eigenvalue.real, -1.86305, places=2)

    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQE using Aer's qasm_simulator snapshot mode."""
        try:
            from qiskit.providers.aer import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')
        optimizer = L_BFGS_B()
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            shots=1,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed)
        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  expectation=AerPauliExpectation(),
                  quantum_instance=quantum_instance)

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)

    def test_with_two_qubit_reduction(self):
        """Test the VQE using TwoQubitReduction."""
        qubit_op = PauliSumOp.from_list([
            ("IIII", -0.8105479805373266),
            ("IIIZ", 0.17218393261915552),
            ("IIZZ", -0.22575349222402472),
            ("IZZI", 0.1721839326191556),
            ("ZZII", -0.22575349222402466),
            ("IIZI", 0.1209126326177663),
            ("IZZZ", 0.16892753870087912),
            ("IXZX", -0.045232799946057854),
            ("ZXIX", 0.045232799946057854),
            ("IXIX", 0.045232799946057854),
            ("ZXZX", -0.045232799946057854),
            ("ZZIZ", 0.16614543256382414),
            ("IZIZ", 0.16614543256382414),
            ("ZZZZ", 0.17464343068300453),
            ("ZIZI", 0.1209126326177663),
        ])
        tapered_qubit_op = TwoQubitReduction(num_particles=2).convert(qubit_op)
        for simulator in [self.qasm_simulator, self.statevector_simulator]:
            with self.subTest(f"Test for {simulator}."):
                vqe = VQE(
                    self.ry_wavefunction,
                    SPSA(maxiter=300, last_avg=5),
                    quantum_instance=simulator,
                )
                result = vqe.compute_minimum_eigenvalue(tapered_qubit_op)
                energy = -1.868 if simulator == self.qasm_simulator else self.h2_energy
                self.assertAlmostEqual(result.eigenvalue.real,
                                       energy,
                                       places=2)

    def test_callback(self):
        """Test the callback on VQE."""
        history = {'eval_count': [], 'parameters': [], 'mean': [], 'std': []}

        def store_intermediate_result(eval_count, parameters, mean, std):
            history['eval_count'].append(eval_count)
            history['parameters'].append(parameters)
            history['mean'].append(mean)
            history['std'].append(std)

        optimizer = COBYLA(maxiter=3)
        wavefunction = self.ry_wavefunction

        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  callback=store_intermediate_result,
                  quantum_instance=self.qasm_simulator)
        vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        self.assertTrue(
            all(isinstance(count, int) for count in history['eval_count']))
        self.assertTrue(
            all(isinstance(mean, float) for mean in history['mean']))
        self.assertTrue(all(isinstance(std, float) for std in history['std']))
        for params in history['parameters']:
            self.assertTrue(all(isinstance(param, float) for param in params))

    def test_reuse(self):
        """Test re-using a VQE algorithm instance."""
        vqe = VQE()
        with self.subTest(msg='assert running empty raises AlgorithmError'):
            with self.assertRaises(AlgorithmError):
                _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        ansatz = TwoLocal(rotation_blocks=['ry', 'rz'],
                          entanglement_blocks='cz')
        vqe.ansatz = ansatz
        with self.subTest(msg='assert missing operator raises AlgorithmError'):
            with self.assertRaises(AlgorithmError):
                _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        vqe.quantum_instance = self.statevector_simulator
        with self.subTest(msg='assert VQE works once all info is available'):
            result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertAlmostEqual(result.eigenvalue.real,
                                   self.h2_energy,
                                   places=5)

        operator = PrimitiveOp(
            np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 2, 0], [0, 0, 0,
                                                                  3]]))

        with self.subTest(msg='assert minimum eigensolver interface works'):
            result = vqe.compute_minimum_eigenvalue(operator=operator)
            self.assertAlmostEqual(result.eigenvalue.real, -1.0, places=5)

    def test_vqe_optimizer(self):
        """ Test running same VQE twice to re-use optimizer, then switch optimizer """
        vqe = VQE(optimizer=SLSQP(),
                  quantum_instance=QuantumInstance(
                      BasicAer.get_backend('statevector_simulator')))

        def run_check():
            result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertAlmostEqual(result.eigenvalue.real,
                                   -1.85727503,
                                   places=5)

        run_check()

        with self.subTest('Optimizer re-use'):
            run_check()

        with self.subTest('Optimizer replace'):
            vqe.optimizer = L_BFGS_B()
            run_check()

    def test_vqe_expectation_select(self):
        """Test expectation selection with Aer's qasm_simulator."""
        try:
            from qiskit.providers.aer import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')

        with self.subTest('Defaults'):
            vqe = VQE(quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, PauliExpectation)

        with self.subTest('Include custom'):
            vqe = VQE(include_custom=True, quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)

        with self.subTest('Set explicitly'):
            vqe = VQE(expectation=AerPauliExpectation(),
                      quantum_instance=backend)
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)

    @data(MatrixExpectation(), None)
    def test_backend_change(self, user_expectation):
        """Test that VQE works when backend changes."""
        vqe = VQE(
            ansatz=TwoLocal(rotation_blocks=['ry', 'rz'],
                            entanglement_blocks='cz'),
            optimizer=SLSQP(maxiter=2),
            expectation=user_expectation,
            quantum_instance=BasicAer.get_backend('statevector_simulator'))
        result0 = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        if user_expectation is not None:
            with self.subTest('User expectation kept.'):
                self.assertEqual(vqe.expectation, user_expectation)
        else:
            with self.subTest('Expectation created.'):
                self.assertIsInstance(vqe.expectation, ExpectationBase)
        try:
            vqe.quantum_instance = BasicAer.get_backend('qasm_simulator')
        except Exception as ex:  # pylint: disable=broad-except
            self.fail("Failed to change backend. Error: '{}'".format(str(ex)))
            return

        result1 = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        if user_expectation is not None:
            with self.subTest(
                    'Change backend with user expectation, it is kept.'):
                self.assertEqual(vqe.expectation, user_expectation)
        else:
            with self.subTest(
                    'Change backend without user expectation, one created.'):
                self.assertIsInstance(vqe.expectation, ExpectationBase)

        with self.subTest('Check results.'):
            self.assertEqual(len(result0.optimal_point),
                             len(result1.optimal_point))
class TestVQD(QiskitAlgorithmsTestCase):
    """Test VQD"""
    def setUp(self):
        super().setUp()
        self.seed = 50
        algorithm_globals.random_seed = self.seed
        self.h2_op = (-1.052373245772859 * (I ^ I) + 0.39793742484318045 *
                      (I ^ Z) - 0.39793742484318045 * (Z ^ I) -
                      0.01128010425623538 * (Z ^ Z) + 0.18093119978423156 *
                      (X ^ X))
        self.h2_energy = -1.85727503
        self.h2_energy_excited = [-1.85727503, -1.24458455]

        self.test_op = MatrixOp(np.diagflat([3, 5, -1, 0.8, 0.2, 2, 1,
                                             -3])).to_pauli_op()
        self.test_results = [-3, -1]

        self.ryrz_wavefunction = TwoLocal(rotation_blocks=["ry", "rz"],
                                          entanglement_blocks="cz",
                                          reps=1)
        self.ry_wavefunction = TwoLocal(rotation_blocks="ry",
                                        entanglement_blocks="cz")

        self.qasm_simulator = QuantumInstance(
            BasicAer.get_backend("qasm_simulator"),
            shots=2048,
            seed_simulator=self.seed,
            seed_transpiler=self.seed,
        )
        self.statevector_simulator = QuantumInstance(
            BasicAer.get_backend("statevector_simulator"),
            shots=1,
            seed_simulator=self.seed,
            seed_transpiler=self.seed,
        )

    def test_basic_aer_statevector(self):
        """Test the VQD on BasicAer's statevector simulator."""
        wavefunction = self.ryrz_wavefunction
        vqd = VQD(
            k=2,
            ansatz=wavefunction,
            optimizer=COBYLA(),
            quantum_instance=QuantumInstance(
                BasicAer.get_backend("statevector_simulator"),
                basis_gates=["u1", "u2", "u3", "cx", "id"],
                coupling_map=[[0, 1]],
                seed_simulator=algorithm_globals.random_seed,
                seed_transpiler=algorithm_globals.random_seed,
            ),
        )

        result = vqd.compute_eigenvalues(operator=self.h2_op)

        with self.subTest(msg="test eigenvalue"):
            np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                                 self.h2_energy_excited,
                                                 decimal=1)

        with self.subTest(msg="test dimension of optimal point"):
            self.assertEqual(len(result.optimal_point[-1]), 8)

        with self.subTest(msg="assert cost_function_evals is set"):
            self.assertIsNotNone(result.cost_function_evals)

        with self.subTest(msg="assert optimizer_time is set"):
            self.assertIsNotNone(result.optimizer_time)

    def test_mismatching_num_qubits(self):
        """Ensuring circuit and operator mismatch is caught"""
        wavefunction = QuantumCircuit(1)
        optimizer = SLSQP(maxiter=50)
        vqd = VQD(
            k=1,
            ansatz=wavefunction,
            optimizer=optimizer,
            quantum_instance=self.statevector_simulator,
        )
        with self.assertRaises(AlgorithmError):
            _ = vqd.compute_eigenvalues(operator=self.h2_op)

    @data(
        (MatrixExpectation(), 1),
        (AerPauliExpectation(), 1),
        (PauliExpectation(), 2),
    )
    @unpack
    def test_construct_circuit(self, expectation, num_circuits):
        """Test construct circuits returns QuantumCircuits and the right number of them."""
        try:
            wavefunction = EfficientSU2(2, reps=1)
            vqd = VQD(k=2, ansatz=wavefunction, expectation=expectation)
            params = [0] * wavefunction.num_parameters
            circuits = vqd.construct_circuit(parameter=params,
                                             operator=self.h2_op)

            self.assertEqual(len(circuits), num_circuits)
            for circuit in circuits:
                self.assertIsInstance(circuit, QuantumCircuit)
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
            return

    def test_missing_varform_params(self):
        """Test specifying a variational form with no parameters raises an error."""
        circuit = QuantumCircuit(self.h2_op.num_qubits)
        vqd = VQD(
            k=1,
            ansatz=circuit,
            quantum_instance=BasicAer.get_backend("statevector_simulator"))
        with self.assertRaises(RuntimeError):
            vqd.compute_eigenvalues(operator=self.h2_op)

    def test_basic_aer_qasm(self):
        """Test the VQD on BasicAer's QASM simulator."""
        optimizer = COBYLA(maxiter=1000)
        wavefunction = self.ry_wavefunction

        vqd = VQD(
            ansatz=wavefunction,
            optimizer=optimizer,
            max_evals_grouped=1,
            quantum_instance=self.qasm_simulator,
        )

        # TODO benchmark this later.
        result = vqd.compute_eigenvalues(operator=self.h2_op)
        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.h2_energy_excited,
                                             decimal=1)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_statevector(self):
        """Test VQD with Aer's statevector_simulator."""
        backend = Aer.get_backend("aer_simulator_statevector")
        wavefunction = self.ry_wavefunction
        optimizer = L_BFGS_B()

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqd = VQD(
            k=2,
            ansatz=wavefunction,
            optimizer=optimizer,
            max_evals_grouped=1,
            quantum_instance=quantum_instance,
        )

        result = vqd.compute_eigenvalues(operator=self.h2_op)
        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.h2_energy_excited,
                                             decimal=2)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_qasm(self):
        """Test VQD with Aer's qasm_simulator."""
        backend = Aer.get_backend("aer_simulator")
        optimizer = COBYLA(maxiter=1000)
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )

        vqd = VQD(
            k=2,
            ansatz=wavefunction,
            optimizer=optimizer,
            expectation=PauliExpectation(),
            quantum_instance=quantum_instance,
        )

        result = vqd.compute_eigenvalues(operator=self.h2_op)

        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.h2_energy_excited,
                                             decimal=1)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQD using Aer's qasm_simulator snapshot mode."""

        backend = Aer.get_backend("aer_simulator")
        optimizer = COBYLA(maxiter=400)
        wavefunction = self.ryrz_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            shots=100,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqd = VQD(
            k=2,
            ansatz=wavefunction,
            optimizer=optimizer,
            expectation=AerPauliExpectation(),
            quantum_instance=quantum_instance,
        )

        result = vqd.compute_eigenvalues(operator=self.test_op)
        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.test_results,
                                             decimal=1)

    def test_callback(self):
        """Test the callback on VQD."""
        history = {"eval_count": [], "parameters": [], "mean": [], "std": []}

        def store_intermediate_result(eval_count, parameters, mean, std):
            history["eval_count"].append(eval_count)
            history["parameters"].append(parameters)
            history["mean"].append(mean)
            history["std"].append(std)

        optimizer = COBYLA(maxiter=3)
        wavefunction = self.ry_wavefunction

        vqd = VQD(
            ansatz=wavefunction,
            optimizer=optimizer,
            callback=store_intermediate_result,
            quantum_instance=self.qasm_simulator,
        )
        vqd.compute_eigenvalues(operator=self.h2_op)

        self.assertTrue(
            all(isinstance(count, int) for count in history["eval_count"]))
        self.assertTrue(
            all(isinstance(mean, float) for mean in history["mean"]))
        self.assertTrue(all(isinstance(std, float) for std in history["std"]))
        for params in history["parameters"]:
            self.assertTrue(all(isinstance(param, float) for param in params))

    def test_reuse(self):
        """Test re-using a VQD algorithm instance."""
        vqd = VQD(k=1)
        with self.subTest(msg="assert running empty raises AlgorithmError"):
            with self.assertRaises(AlgorithmError):
                _ = vqd.compute_eigenvalues(operator=self.h2_op)

        ansatz = TwoLocal(rotation_blocks=["ry", "rz"],
                          entanglement_blocks="cz")
        vqd.ansatz = ansatz
        with self.subTest(msg="assert missing operator raises AlgorithmError"):
            with self.assertRaises(AlgorithmError):
                _ = vqd.compute_eigenvalues(operator=self.h2_op)

        vqd.expectation = MatrixExpectation()
        vqd.quantum_instance = self.statevector_simulator
        with self.subTest(msg="assert VQE works once all info is available"):
            result = vqd.compute_eigenvalues(operator=self.h2_op)
            np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                                 self.h2_energy,
                                                 decimal=2)

        operator = PrimitiveOp(
            np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 2, 0], [0, 0, 0,
                                                                  3]]))

        with self.subTest(msg="assert minimum eigensolver interface works"):
            result = vqd.compute_eigenvalues(operator=operator)
            self.assertAlmostEqual(result.eigenvalues.real[0], -1.0, places=5)

    def test_vqd_optimizer(self):
        """Test running same VQD twice to re-use optimizer, then switch optimizer"""
        vqd = VQD(
            k=2,
            optimizer=SLSQP(),
            quantum_instance=QuantumInstance(
                BasicAer.get_backend("statevector_simulator")),
        )

        def run_check():
            result = vqd.compute_eigenvalues(operator=self.h2_op)
            np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                                 self.h2_energy_excited,
                                                 decimal=3)

        run_check()

        with self.subTest("Optimizer re-use"):
            run_check()

        with self.subTest("Optimizer replace"):
            vqd.optimizer = L_BFGS_B()
            run_check()

    @data(MatrixExpectation(), None)
    def test_backend_change(self, user_expectation):
        """Test that VQE works when backend changes."""
        vqd = VQD(
            k=1,
            ansatz=TwoLocal(rotation_blocks=["ry", "rz"],
                            entanglement_blocks="cz"),
            optimizer=SLSQP(maxiter=2),
            expectation=user_expectation,
            quantum_instance=BasicAer.get_backend("statevector_simulator"),
        )
        result0 = vqd.compute_eigenvalues(operator=self.h2_op)
        if user_expectation is not None:
            with self.subTest("User expectation kept."):
                self.assertEqual(vqd.expectation, user_expectation)

        vqd.quantum_instance = BasicAer.get_backend("qasm_simulator")

        # works also if no expectation is set, since it will be determined automatically
        result1 = vqd.compute_eigenvalues(operator=self.h2_op)

        if user_expectation is not None:
            with self.subTest(
                    "Change backend with user expectation, it is kept."):
                self.assertEqual(vqd.expectation, user_expectation)

        with self.subTest("Check results."):
            self.assertEqual(len(result0.optimal_point),
                             len(result1.optimal_point))

    def test_set_ansatz_to_none(self):
        """Tests that setting the ansatz to None results in the default behavior"""
        vqd = VQD(
            k=1,
            ansatz=self.ryrz_wavefunction,
            optimizer=L_BFGS_B(),
            quantum_instance=self.statevector_simulator,
        )
        vqd.ansatz = None
        self.assertIsInstance(vqd.ansatz, RealAmplitudes)

    def test_set_optimizer_to_none(self):
        """Tests that setting the optimizer to None results in the default behavior"""
        vqd = VQD(
            k=1,
            ansatz=self.ryrz_wavefunction,
            optimizer=L_BFGS_B(),
            quantum_instance=self.statevector_simulator,
        )
        vqd.optimizer = None
        self.assertIsInstance(vqd.optimizer, SLSQP)

    def test_aux_operators_list(self):
        """Test list-based aux_operators."""
        wavefunction = self.ry_wavefunction
        vqd = VQD(k=2,
                  ansatz=wavefunction,
                  quantum_instance=self.statevector_simulator)

        # Start with an empty list
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=[])
        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.h2_energy_excited,
                                             decimal=2)
        self.assertIsNone(result.aux_operator_eigenvalues)

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = [aux_op1, aux_op2]
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=aux_ops)
        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.h2_energy_excited,
                                             decimal=2)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0],
                               2,
                               places=2)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0],
                               0,
                               places=2)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1], 0.0)

        # Go again with additional None and zero operators
        extra_ops = [*aux_ops, None, 0]
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=extra_ops)
        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.h2_energy_excited,
                                             decimal=2)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0],
                               2,
                               places=2)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0],
                               0,
                               places=2)
        self.assertEqual(result.aux_operator_eigenvalues[0][2][0], 0.0)
        self.assertEqual(result.aux_operator_eigenvalues[0][3][0], 0.0)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1], 0.0)
        self.assertEqual(result.aux_operator_eigenvalues[0][3][1], 0.0)

    def test_aux_operators_dict(self):
        """Test dictionary compatibility of aux_operators"""
        wavefunction = self.ry_wavefunction
        vqd = VQD(ansatz=wavefunction,
                  quantum_instance=self.statevector_simulator)

        # Start with an empty dictionary
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators={})
        np.testing.assert_array_almost_equal(result.eigenvalues.real,
                                             self.h2_energy_excited,
                                             decimal=2)
        self.assertIsNone(result.aux_operator_eigenvalues)

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = {"aux_op1": aux_op1, "aux_op2": aux_op2}
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=aux_ops)
        self.assertEqual(len(result.eigenvalues), 2)
        self.assertEqual(len(result.eigenstates), 2)
        self.assertEqual(result.eigenvalues.dtype, np.complex128)
        self.assertAlmostEqual(result.eigenvalues[0], -1.85727503)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        self.assertEqual(len(result.aux_operator_eigenvalues[0]), 2)
        # expectation values
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["aux_op1"][0], 2, places=6)
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["aux_op2"][0], 0, places=1)
        # standard deviations
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["aux_op1"][1], 0.0)
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["aux_op2"][1], 0.0)

        # Go again with additional None and zero operators
        extra_ops = {**aux_ops, "None_operator": None, "zero_operator": 0}
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=extra_ops)
        self.assertEqual(len(result.eigenvalues), 2)
        self.assertEqual(len(result.eigenstates), 2)
        self.assertEqual(result.eigenvalues.dtype, np.complex128)
        self.assertAlmostEqual(result.eigenvalues[0], -1.85727503)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        self.assertEqual(len(result.aux_operator_eigenvalues[0]), 3)
        # expectation values
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["aux_op1"][0], 2, places=6)
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["aux_op2"][0], 0, places=6)
        self.assertEqual(
            result.aux_operator_eigenvalues[0]["zero_operator"][0], 0.0)
        self.assertTrue(
            "None_operator" not in result.aux_operator_eigenvalues[0].keys())
        # standard deviations
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["aux_op1"][1], 0.0)
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["aux_op2"][1], 0.0)
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues[0]["zero_operator"][1], 0.0)

    def test_aux_operator_std_dev_pauli(self):
        """Test non-zero standard deviations of aux operators with PauliExpectation."""
        wavefunction = self.ry_wavefunction
        vqd = VQD(
            ansatz=wavefunction,
            expectation=PauliExpectation(),
            initial_point=[
                1.70256666,
                -5.34843975,
                -0.39542903,
                5.99477786,
                -2.74374986,
                -4.85284669,
                0.2442925,
                -1.51638917,
            ],
            optimizer=COBYLA(maxiter=0),
            quantum_instance=self.qasm_simulator,
        )

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = [aux_op1, aux_op2]
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0],
                               2.0,
                               places=1)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0],
                               0.0019531249999999445,
                               places=1)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1],
                               0.015183867579396111,
                               places=1)

        # Go again with additional None and zero operators
        aux_ops = [*aux_ops, None, 0]
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues[0]), 4)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0],
                               2.0,
                               places=1)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0],
                               0.0019531249999999445,
                               places=1)
        self.assertEqual(result.aux_operator_eigenvalues[0][2][0], 0.0)
        self.assertEqual(result.aux_operator_eigenvalues[0][3][0], 0.0)
        # # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1],
                               0.01548658094658011,
                               places=1)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][2][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][3][1], 0.0)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_aux_operator_std_dev_aer_pauli(self):
        """Test non-zero standard deviations of aux operators with AerPauliExpectation."""
        wavefunction = self.ry_wavefunction
        vqd = VQD(
            ansatz=wavefunction,
            expectation=AerPauliExpectation(),
            optimizer=COBYLA(maxiter=0),
            quantum_instance=QuantumInstance(
                backend=Aer.get_backend("qasm_simulator"),
                shots=1,
                seed_simulator=algorithm_globals.random_seed,
                seed_transpiler=algorithm_globals.random_seed,
            ),
        )

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = [aux_op1, aux_op2]
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0],
                               2.0,
                               places=1)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0],
                               0.6698863565455391,
                               places=1)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1],
                               0.0,
                               places=6)

        # Go again with additional None and zero operators
        aux_ops = [*aux_ops, None, 0]
        result = vqd.compute_eigenvalues(self.h2_op, aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues[-1]), 4)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][0],
                               2.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][0],
                               0.6036400943063891,
                               places=6)
        self.assertEqual(result.aux_operator_eigenvalues[0][2][0], 0.0)
        self.assertEqual(result.aux_operator_eigenvalues[0][3][0], 0.0)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1][1],
                               0.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][2][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][3][1], 0.0)
class TestVQE(QiskitAlgorithmsTestCase):
    """Test VQE"""
    def setUp(self):
        super().setUp()
        self.seed = 50
        algorithm_globals.random_seed = self.seed
        self.h2_op = (-1.052373245772859 * (I ^ I) + 0.39793742484318045 *
                      (I ^ Z) - 0.39793742484318045 * (Z ^ I) -
                      0.01128010425623538 * (Z ^ Z) + 0.18093119978423156 *
                      (X ^ X))
        self.h2_energy = -1.85727503

        self.ryrz_wavefunction = TwoLocal(rotation_blocks=["ry", "rz"],
                                          entanglement_blocks="cz")
        self.ry_wavefunction = TwoLocal(rotation_blocks="ry",
                                        entanglement_blocks="cz")

        self.qasm_simulator = QuantumInstance(
            BasicAer.get_backend("qasm_simulator"),
            shots=1024,
            seed_simulator=self.seed,
            seed_transpiler=self.seed,
        )
        self.statevector_simulator = QuantumInstance(
            BasicAer.get_backend("statevector_simulator"),
            shots=1,
            seed_simulator=self.seed,
            seed_transpiler=self.seed,
        )

    def test_basic_aer_statevector(self):
        """Test the VQE on BasicAer's statevector simulator."""
        wavefunction = self.ryrz_wavefunction
        vqe = VQE(
            ansatz=wavefunction,
            optimizer=L_BFGS_B(),
            quantum_instance=QuantumInstance(
                BasicAer.get_backend("statevector_simulator"),
                basis_gates=["u1", "u2", "u3", "cx", "id"],
                coupling_map=[[0, 1]],
                seed_simulator=algorithm_globals.random_seed,
                seed_transpiler=algorithm_globals.random_seed,
            ),
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        with self.subTest(msg="test eigenvalue"):
            self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy)

        with self.subTest(msg="test dimension of optimal point"):
            self.assertEqual(len(result.optimal_point), 16)

        with self.subTest(msg="assert cost_function_evals is set"):
            self.assertIsNotNone(result.cost_function_evals)

        with self.subTest(msg="assert optimizer_time is set"):
            self.assertIsNotNone(result.optimizer_time)

    def test_circuit_input(self):
        """Test running the VQE on a plain QuantumCircuit object."""
        wavefunction = QuantumCircuit(2).compose(EfficientSU2(2))
        optimizer = SLSQP(maxiter=50)
        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  quantum_instance=self.statevector_simulator)
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=5)

    @data(
        (MatrixExpectation(), 1),
        (AerPauliExpectation(), 1),
        (PauliExpectation(), 2),
    )
    @unpack
    def test_construct_circuit(self, expectation, num_circuits):
        """Test construct circuits returns QuantumCircuits and the right number of them."""
        try:
            wavefunction = EfficientSU2(2, reps=1)
            vqe = VQE(ansatz=wavefunction, expectation=expectation)
            params = [0] * wavefunction.num_parameters
            circuits = vqe.construct_circuit(parameter=params,
                                             operator=self.h2_op)

            self.assertEqual(len(circuits), num_circuits)
            for circuit in circuits:
                self.assertIsInstance(circuit, QuantumCircuit)
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
            return

    def test_missing_varform_params(self):
        """Test specifying a variational form with no parameters raises an error."""
        circuit = QuantumCircuit(self.h2_op.num_qubits)
        vqe = VQE(
            ansatz=circuit,
            quantum_instance=BasicAer.get_backend("statevector_simulator"))
        with self.assertRaises(RuntimeError):
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)

    @data(
        (SLSQP(maxiter=50), 5, 4),
        (SPSA(maxiter=150), 2, 2),  # max_evals_grouped=n or =2 if n>2
    )
    @unpack
    def test_max_evals_grouped(self, optimizer, places, max_evals_grouped):
        """VQE Optimizers test"""
        vqe = VQE(
            ansatz=self.ryrz_wavefunction,
            optimizer=optimizer,
            max_evals_grouped=max_evals_grouped,
            quantum_instance=self.statevector_simulator,
        )
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=places)

    def test_basic_aer_qasm(self):
        """Test the VQE on BasicAer's QASM simulator."""
        optimizer = SPSA(maxiter=300, last_avg=5)
        wavefunction = self.ry_wavefunction

        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            max_evals_grouped=1,
            quantum_instance=self.qasm_simulator,
        )

        # TODO benchmark this later.
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real, -1.86823, places=2)

    def test_qasm_eigenvector_normalized(self):
        """Test VQE with qasm_simulator returns normalized eigenvector."""
        wavefunction = self.ry_wavefunction
        vqe = VQE(ansatz=wavefunction, quantum_instance=self.qasm_simulator)
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        amplitudes = list(result.eigenstate.values())
        self.assertAlmostEqual(np.linalg.norm(amplitudes), 1.0, places=4)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_statevector(self):
        """Test VQE with Aer's statevector_simulator."""
        backend = Aer.get_backend("aer_simulator_statevector")
        wavefunction = self.ry_wavefunction
        optimizer = L_BFGS_B()

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            max_evals_grouped=1,
            quantum_instance=quantum_instance,
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_qasm(self):
        """Test VQE with Aer's qasm_simulator."""
        backend = Aer.get_backend("aer_simulator")
        optimizer = SPSA(maxiter=200, last_avg=5)
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )

        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            expectation=PauliExpectation(),
            quantum_instance=quantum_instance,
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        self.assertAlmostEqual(result.eigenvalue.real, -1.86305, places=2)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQE using Aer's qasm_simulator snapshot mode."""

        backend = Aer.get_backend("aer_simulator")
        optimizer = L_BFGS_B()
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            shots=1,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            expectation=AerPauliExpectation(),
            quantum_instance=quantum_instance,
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    @data(
        CG(maxiter=1),
        L_BFGS_B(maxfun=1),
        P_BFGS(maxfun=1, max_processes=0),
        SLSQP(maxiter=1),
        TNC(maxiter=1),
    )
    def test_with_gradient(self, optimizer):
        """Test VQE using Gradient()."""
        quantum_instance = QuantumInstance(
            backend=Aer.get_backend("qasm_simulator"),
            shots=1,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqe = VQE(
            ansatz=self.ry_wavefunction,
            optimizer=optimizer,
            gradient=Gradient(),
            expectation=AerPauliExpectation(),
            quantum_instance=quantum_instance,
            max_evals_grouped=1000,
        )
        vqe.compute_minimum_eigenvalue(operator=self.h2_op)

    def test_with_two_qubit_reduction(self):
        """Test the VQE using TwoQubitReduction."""
        qubit_op = PauliSumOp.from_list([
            ("IIII", -0.8105479805373266),
            ("IIIZ", 0.17218393261915552),
            ("IIZZ", -0.22575349222402472),
            ("IZZI", 0.1721839326191556),
            ("ZZII", -0.22575349222402466),
            ("IIZI", 0.1209126326177663),
            ("IZZZ", 0.16892753870087912),
            ("IXZX", -0.045232799946057854),
            ("ZXIX", 0.045232799946057854),
            ("IXIX", 0.045232799946057854),
            ("ZXZX", -0.045232799946057854),
            ("ZZIZ", 0.16614543256382414),
            ("IZIZ", 0.16614543256382414),
            ("ZZZZ", 0.17464343068300453),
            ("ZIZI", 0.1209126326177663),
        ])
        tapered_qubit_op = TwoQubitReduction(num_particles=2).convert(qubit_op)
        for simulator in [self.qasm_simulator, self.statevector_simulator]:
            with self.subTest(f"Test for {simulator}."):
                vqe = VQE(
                    self.ry_wavefunction,
                    SPSA(maxiter=300, last_avg=5),
                    quantum_instance=simulator,
                )
                result = vqe.compute_minimum_eigenvalue(tapered_qubit_op)
                energy = -1.868 if simulator == self.qasm_simulator else self.h2_energy
                self.assertAlmostEqual(result.eigenvalue.real,
                                       energy,
                                       places=2)

    def test_callback(self):
        """Test the callback on VQE."""
        history = {"eval_count": [], "parameters": [], "mean": [], "std": []}

        def store_intermediate_result(eval_count, parameters, mean, std):
            history["eval_count"].append(eval_count)
            history["parameters"].append(parameters)
            history["mean"].append(mean)
            history["std"].append(std)

        optimizer = COBYLA(maxiter=3)
        wavefunction = self.ry_wavefunction

        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            callback=store_intermediate_result,
            quantum_instance=self.qasm_simulator,
        )
        vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        self.assertTrue(
            all(isinstance(count, int) for count in history["eval_count"]))
        self.assertTrue(
            all(isinstance(mean, float) for mean in history["mean"]))
        self.assertTrue(all(isinstance(std, float) for std in history["std"]))
        for params in history["parameters"]:
            self.assertTrue(all(isinstance(param, float) for param in params))

    def test_reuse(self):
        """Test re-using a VQE algorithm instance."""
        vqe = VQE()
        with self.subTest(msg="assert running empty raises AlgorithmError"):
            with self.assertRaises(AlgorithmError):
                _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        ansatz = TwoLocal(rotation_blocks=["ry", "rz"],
                          entanglement_blocks="cz")
        vqe.ansatz = ansatz
        with self.subTest(msg="assert missing operator raises AlgorithmError"):
            with self.assertRaises(AlgorithmError):
                _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        vqe.expectation = MatrixExpectation()
        vqe.quantum_instance = self.statevector_simulator
        with self.subTest(msg="assert VQE works once all info is available"):
            result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertAlmostEqual(result.eigenvalue.real,
                                   self.h2_energy,
                                   places=5)

        operator = PrimitiveOp(
            np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 2, 0], [0, 0, 0,
                                                                  3]]))

        with self.subTest(msg="assert minimum eigensolver interface works"):
            result = vqe.compute_minimum_eigenvalue(operator=operator)
            self.assertAlmostEqual(result.eigenvalue.real, -1.0, places=5)

    def test_vqe_optimizer(self):
        """Test running same VQE twice to re-use optimizer, then switch optimizer"""
        vqe = VQE(
            optimizer=SLSQP(),
            quantum_instance=QuantumInstance(
                BasicAer.get_backend("statevector_simulator")),
        )

        def run_check():
            result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertAlmostEqual(result.eigenvalue.real,
                                   -1.85727503,
                                   places=5)

        run_check()

        with self.subTest("Optimizer re-use"):
            run_check()

        with self.subTest("Optimizer replace"):
            vqe.optimizer = L_BFGS_B()
            run_check()

    @data(MatrixExpectation(), None)
    def test_backend_change(self, user_expectation):
        """Test that VQE works when backend changes."""
        vqe = VQE(
            ansatz=TwoLocal(rotation_blocks=["ry", "rz"],
                            entanglement_blocks="cz"),
            optimizer=SLSQP(maxiter=2),
            expectation=user_expectation,
            quantum_instance=BasicAer.get_backend("statevector_simulator"),
        )
        result0 = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        if user_expectation is not None:
            with self.subTest("User expectation kept."):
                self.assertEqual(vqe.expectation, user_expectation)

        vqe.quantum_instance = BasicAer.get_backend("qasm_simulator")

        # works also if no expectation is set, since it will be determined automatically
        result1 = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        if user_expectation is not None:
            with self.subTest(
                    "Change backend with user expectation, it is kept."):
                self.assertEqual(vqe.expectation, user_expectation)

        with self.subTest("Check results."):
            self.assertEqual(len(result0.optimal_point),
                             len(result1.optimal_point))

    def test_batch_evaluate_with_qnspsa(self):
        """Test batch evaluating with QNSPSA works."""
        ansatz = TwoLocal(2,
                          rotation_blocks=["ry", "rz"],
                          entanglement_blocks="cz")

        wrapped_backend = BasicAer.get_backend("qasm_simulator")
        inner_backend = BasicAer.get_backend("statevector_simulator")

        callcount = {"count": 0}

        def wrapped_run(circuits, **kwargs):
            kwargs["callcount"]["count"] += 1
            return inner_backend.run(circuits)

        wrapped_backend.run = partial(wrapped_run, callcount=callcount)

        fidelity = QNSPSA.get_fidelity(ansatz, backend=wrapped_backend)
        qnspsa = QNSPSA(fidelity, maxiter=5)

        vqe = VQE(
            ansatz=ansatz,
            optimizer=qnspsa,
            max_evals_grouped=100,
            quantum_instance=wrapped_backend,
        )
        _ = vqe.compute_minimum_eigenvalue(Z ^ Z)

        # 1 calibration + 1 stddev estimation + 1 initial blocking
        # + 5 (1 loss + 1 fidelity + 1 blocking) + 1 return loss + 1 VQE eval
        expected = 1 + 1 + 1 + 5 * 3 + 1 + 1

        self.assertEqual(callcount["count"], expected)

    def test_set_ansatz_to_none(self):
        """Tests that setting the ansatz to None results in the default behavior"""
        vqe = VQE(
            ansatz=self.ryrz_wavefunction,
            optimizer=L_BFGS_B(),
            quantum_instance=self.statevector_simulator,
        )
        vqe.ansatz = None
        self.assertIsInstance(vqe.ansatz, RealAmplitudes)

    def test_set_optimizer_to_none(self):
        """Tests that setting the optimizer to None results in the default behavior"""
        vqe = VQE(
            ansatz=self.ryrz_wavefunction,
            optimizer=L_BFGS_B(),
            quantum_instance=self.statevector_simulator,
        )
        vqe.optimizer = None
        self.assertIsInstance(vqe.optimizer, SLSQP)

    def test_optimizer_scipy_callable(self):
        """Test passing a SciPy optimizer directly as callable."""
        vqe = VQE(
            optimizer=partial(scipy_minimize,
                              method="L-BFGS-B",
                              options={"maxiter": 2}),
            quantum_instance=self.statevector_simulator,
        )
        result = vqe.compute_minimum_eigenvalue(Z)
        self.assertEqual(result.cost_function_evals, 20)

    def test_optimizer_callable(self):
        """Test passing a optimizer directly as callable."""
        ansatz = RealAmplitudes(1, reps=1)
        vqe = VQE(ansatz=ansatz,
                  optimizer=_mock_optimizer,
                  quantum_instance=self.statevector_simulator)
        result = vqe.compute_minimum_eigenvalue(Z)
        self.assertTrue(
            np.all(result.optimal_point == np.zeros(ansatz.num_parameters)))

    def test_aux_operators_list(self):
        """Test list-based aux_operators."""
        wavefunction = self.ry_wavefunction
        vqe = VQE(ansatz=wavefunction,
                  quantum_instance=self.statevector_simulator)

        # Start with an empty list
        result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators=[])
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)
        self.assertIsNone(result.aux_operator_eigenvalues)

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = [aux_op1, aux_op2]
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=aux_ops)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0],
                               2,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0],
                               0,
                               places=6)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.0)

        # Go again with additional None and zero operators
        extra_ops = [*aux_ops, None, 0]
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=extra_ops)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)
        self.assertEqual(len(result.aux_operator_eigenvalues), 4)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0],
                               2,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0],
                               0,
                               places=6)
        self.assertEqual(result.aux_operator_eigenvalues[2][0], 0.0)
        self.assertEqual(result.aux_operator_eigenvalues[3][0], 0.0)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[2][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[3][1], 0.0)

    def test_aux_operators_dict(self):
        """Test dictionary compatibility of aux_operators"""
        wavefunction = self.ry_wavefunction
        vqe = VQE(ansatz=wavefunction,
                  quantum_instance=self.statevector_simulator)

        # Start with an empty dictionary
        result = vqe.compute_minimum_eigenvalue(self.h2_op, aux_operators={})
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)
        self.assertIsNone(result.aux_operator_eigenvalues)

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = {"aux_op1": aux_op1, "aux_op2": aux_op2}
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=aux_ops)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues["aux_op1"][0],
                               2,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues["aux_op2"][0],
                               0,
                               places=6)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues["aux_op1"][1],
                               0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues["aux_op2"][1],
                               0.0)

        # Go again with additional None and zero operators
        extra_ops = {**aux_ops, "None_operator": None, "zero_operator": 0}
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=extra_ops)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)
        self.assertEqual(len(result.aux_operator_eigenvalues), 3)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues["aux_op1"][0],
                               2,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues["aux_op2"][0],
                               0,
                               places=6)
        self.assertEqual(result.aux_operator_eigenvalues["zero_operator"][0],
                         0.0)
        self.assertTrue(
            "None_operator" not in result.aux_operator_eigenvalues.keys())
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues["aux_op1"][1],
                               0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues["aux_op2"][1],
                               0.0)
        self.assertAlmostEqual(
            result.aux_operator_eigenvalues["zero_operator"][1], 0.0)

    def test_aux_operator_std_dev_pauli(self):
        """Test non-zero standard deviations of aux operators with PauliExpectation."""
        wavefunction = self.ry_wavefunction
        vqe = VQE(
            ansatz=wavefunction,
            expectation=PauliExpectation(),
            optimizer=COBYLA(maxiter=0),
            quantum_instance=self.qasm_simulator,
        )

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = [aux_op1, aux_op2]
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0],
                               2.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0],
                               0.6796875,
                               places=6)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1],
                               0.02534712219145965,
                               places=6)

        # Go again with additional None and zero operators
        aux_ops = [*aux_ops, None, 0]
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues), 4)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0],
                               2.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0],
                               0.57421875,
                               places=6)
        self.assertEqual(result.aux_operator_eigenvalues[2][0], 0.0)
        self.assertEqual(result.aux_operator_eigenvalues[3][0], 0.0)
        # # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1],
                               0.026562146577166837,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[2][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[3][1], 0.0)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_aux_operator_std_dev_aer_pauli(self):
        """Test non-zero standard deviations of aux operators with AerPauliExpectation."""
        wavefunction = self.ry_wavefunction
        vqe = VQE(
            ansatz=wavefunction,
            expectation=AerPauliExpectation(),
            optimizer=COBYLA(maxiter=0),
            quantum_instance=QuantumInstance(
                backend=Aer.get_backend("qasm_simulator"),
                shots=1,
                seed_simulator=algorithm_globals.random_seed,
                seed_transpiler=algorithm_globals.random_seed,
            ),
        )

        # Go again with two auxiliary operators
        aux_op1 = PauliSumOp.from_list([("II", 2.0)])
        aux_op2 = PauliSumOp.from_list([("II", 0.5), ("ZZ", 0.5), ("YY", 0.5),
                                        ("XX", -0.5)])
        aux_ops = [aux_op1, aux_op2]
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues), 2)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0],
                               2.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0],
                               0.6698863565455391,
                               places=6)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1],
                               0.0,
                               places=6)

        # Go again with additional None and zero operators
        aux_ops = [*aux_ops, None, 0]
        result = vqe.compute_minimum_eigenvalue(self.h2_op,
                                                aux_operators=aux_ops)
        self.assertEqual(len(result.aux_operator_eigenvalues), 4)
        # expectation values
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][0],
                               2.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][0],
                               0.6036400943063891,
                               places=6)
        self.assertEqual(result.aux_operator_eigenvalues[2][0], 0.0)
        self.assertEqual(result.aux_operator_eigenvalues[3][0], 0.0)
        # standard deviations
        self.assertAlmostEqual(result.aux_operator_eigenvalues[0][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[1][1],
                               0.0,
                               places=6)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[2][1], 0.0)
        self.assertAlmostEqual(result.aux_operator_eigenvalues[3][1], 0.0)

    def test_2step_transpile(self):
        """Test the two-step transpiler pass."""
        # count how often the pass for parameterized circuits is called
        pre_counter = LogPass("pre_passmanager")
        pre_pass = PassManager(pre_counter)
        config = PassManagerConfig(basis_gates=["u3", "cx"])
        pre_pass += level_1_pass_manager(config)

        # ... and the pass for bound circuits
        bound_counter = LogPass("bound_pass_manager")
        bound_pass = PassManager(bound_counter)

        quantum_instance = QuantumInstance(
            backend=BasicAer.get_backend("statevector_simulator"),
            basis_gates=["u3", "cx"],
            pass_manager=pre_pass,
            bound_pass_manager=bound_pass,
        )

        optimizer = SPSA(maxiter=5, learning_rate=0.01, perturbation=0.01)

        vqe = VQE(optimizer=optimizer, quantum_instance=quantum_instance)
        _ = vqe.compute_minimum_eigenvalue(Z)

        with self.assertLogs(logger, level="INFO") as cm:
            _ = vqe.compute_minimum_eigenvalue(Z)

        expected = [
            "pre_passmanager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "bound_pass_manager",
            "pre_passmanager",
            "bound_pass_manager",
        ]
        self.assertEqual([record.message for record in cm.records], expected)

    def test_construct_eigenstate_from_optpoint(self):
        """Test constructing the eigenstate from the optimal point, if the default ansatz is used."""

        # use Hamiltonian yielding more than 11 parameters in the default ansatz
        hamiltonian = Z ^ Z ^ Z
        optimizer = SPSA(maxiter=1, learning_rate=0.01, perturbation=0.01)
        quantum_instance = QuantumInstance(
            backend=BasicAer.get_backend("statevector_simulator"),
            basis_gates=["u3", "cx"])
        vqe = VQE(optimizer=optimizer, quantum_instance=quantum_instance)
        result = vqe.compute_minimum_eigenvalue(hamiltonian)

        optimal_circuit = vqe.ansatz.bind_parameters(result.optimal_point)
        self.assertTrue(Statevector(result.eigenstate).equiv(optimal_circuit))
Exemple #25
0
class TestVQE(QiskitAlgorithmsTestCase):
    """Test VQE"""
    def setUp(self):
        super().setUp()
        self.seed = 50
        algorithm_globals.random_seed = self.seed
        self.h2_op = (-1.052373245772859 * (I ^ I) + 0.39793742484318045 *
                      (I ^ Z) - 0.39793742484318045 * (Z ^ I) -
                      0.01128010425623538 * (Z ^ Z) + 0.18093119978423156 *
                      (X ^ X))
        self.h2_energy = -1.85727503

        self.ryrz_wavefunction = TwoLocal(rotation_blocks=["ry", "rz"],
                                          entanglement_blocks="cz")
        self.ry_wavefunction = TwoLocal(rotation_blocks="ry",
                                        entanglement_blocks="cz")

        self.qasm_simulator = QuantumInstance(
            BasicAer.get_backend("qasm_simulator"),
            shots=1024,
            seed_simulator=self.seed,
            seed_transpiler=self.seed,
        )
        self.statevector_simulator = QuantumInstance(
            BasicAer.get_backend("statevector_simulator"),
            shots=1,
            seed_simulator=self.seed,
            seed_transpiler=self.seed,
        )

    def test_basic_aer_statevector(self):
        """Test the VQE on BasicAer's statevector simulator."""
        wavefunction = self.ryrz_wavefunction
        vqe = VQE(
            ansatz=wavefunction,
            optimizer=L_BFGS_B(),
            quantum_instance=QuantumInstance(
                BasicAer.get_backend("statevector_simulator"),
                basis_gates=["u1", "u2", "u3", "cx", "id"],
                coupling_map=[[0, 1]],
                seed_simulator=algorithm_globals.random_seed,
                seed_transpiler=algorithm_globals.random_seed,
            ),
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        with self.subTest(msg="test eigenvalue"):
            self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy)

        with self.subTest(msg="test dimension of optimal point"):
            self.assertEqual(len(result.optimal_point), 16)

        with self.subTest(msg="assert cost_function_evals is set"):
            self.assertIsNotNone(result.cost_function_evals)

        with self.subTest(msg="assert optimizer_time is set"):
            self.assertIsNotNone(result.optimizer_time)

    def test_circuit_input(self):
        """Test running the VQE on a plain QuantumCircuit object."""
        wavefunction = QuantumCircuit(2).compose(EfficientSU2(2))
        optimizer = SLSQP(maxiter=50)
        vqe = VQE(ansatz=wavefunction,
                  optimizer=optimizer,
                  quantum_instance=self.statevector_simulator)
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=5)

    @data(
        (MatrixExpectation(), 1),
        (AerPauliExpectation(), 1),
        (PauliExpectation(), 2),
    )
    @unpack
    def test_construct_circuit(self, expectation, num_circuits):
        """Test construct circuits returns QuantumCircuits and the right number of them."""
        try:
            wavefunction = EfficientSU2(2, reps=1)
            vqe = VQE(ansatz=wavefunction, expectation=expectation)
            params = [0] * wavefunction.num_parameters
            circuits = vqe.construct_circuit(parameter=params,
                                             operator=self.h2_op)

            self.assertEqual(len(circuits), num_circuits)
            for circuit in circuits:
                self.assertIsInstance(circuit, QuantumCircuit)
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
            return

    def test_missing_varform_params(self):
        """Test specifying a variational form with no parameters raises an error."""
        circuit = QuantumCircuit(self.h2_op.num_qubits)
        vqe = VQE(
            ansatz=circuit,
            quantum_instance=BasicAer.get_backend("statevector_simulator"))
        with self.assertRaises(RuntimeError):
            vqe.compute_minimum_eigenvalue(operator=self.h2_op)

    @data(
        (SLSQP(maxiter=50), 5, 4),
        (SPSA(maxiter=150), 3, 2),  # max_evals_grouped=n or =2 if n>2
    )
    @unpack
    def test_max_evals_grouped(self, optimizer, places, max_evals_grouped):
        """VQE Optimizers test"""
        with self.assertWarns(DeprecationWarning):
            vqe = VQE(
                ansatz=self.ryrz_wavefunction,
                optimizer=optimizer,
                max_evals_grouped=max_evals_grouped,
                quantum_instance=self.statevector_simulator,
                sort_parameters_by_name=True,
            )
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=places)

    def test_basic_aer_qasm(self):
        """Test the VQE on BasicAer's QASM simulator."""
        optimizer = SPSA(maxiter=300, last_avg=5)
        wavefunction = self.ry_wavefunction

        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            max_evals_grouped=1,
            quantum_instance=self.qasm_simulator,
        )

        # TODO benchmark this later.
        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real, -1.86823, places=2)

    def test_qasm_aux_operators_normalized(self):
        """Test VQE with qasm_simulator returns normalized aux_operator eigenvalues."""
        wavefunction = self.ry_wavefunction
        vqe = VQE(ansatz=wavefunction, quantum_instance=self.qasm_simulator)
        _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        opt_params = [
            3.50437328,
            3.87415376,
            0.93684363,
            5.92219622,
            -1.53527887,
            1.87941418,
            -4.5708326,
            0.70187027,
        ]

        vqe._ret.optimal_point = opt_params
        vqe._ret.optimal_parameters = dict(
            zip(sorted(wavefunction.parameters, key=lambda p: p.name),
                opt_params))

        with self.assertWarns(DeprecationWarning):
            optimal_vector = vqe.get_optimal_vector()

        self.assertAlmostEqual(sum(v**2 for v in optimal_vector.values()),
                               1.0,
                               places=4)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_statevector(self):
        """Test VQE with Aer's statevector_simulator."""
        backend = Aer.get_backend("aer_simulator_statevector")
        wavefunction = self.ry_wavefunction
        optimizer = L_BFGS_B()

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            max_evals_grouped=1,
            quantum_instance=quantum_instance,
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_qasm(self):
        """Test VQE with Aer's qasm_simulator."""
        backend = Aer.get_backend("aer_simulator")
        optimizer = SPSA(maxiter=200, last_avg=5)
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )

        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            expectation=PauliExpectation(),
            quantum_instance=quantum_instance,
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        self.assertAlmostEqual(result.eigenvalue.real, -1.86305, places=2)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQE using Aer's qasm_simulator snapshot mode."""

        backend = Aer.get_backend("aer_simulator")
        optimizer = L_BFGS_B()
        wavefunction = self.ry_wavefunction

        quantum_instance = QuantumInstance(
            backend,
            shots=1,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            expectation=AerPauliExpectation(),
            quantum_instance=quantum_instance,
        )

        result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)

    @unittest.skipUnless(has_aer(),
                         "qiskit-aer doesn't appear to be installed.")
    @data(
        CG(maxiter=1),
        L_BFGS_B(maxfun=1),
        P_BFGS(maxfun=1, max_processes=0),
        SLSQP(maxiter=1),
        TNC(maxiter=1),
    )
    def test_with_gradient(self, optimizer):
        """Test VQE using Gradient()."""
        quantum_instance = QuantumInstance(
            backend=Aer.get_backend("qasm_simulator"),
            shots=1,
            seed_simulator=algorithm_globals.random_seed,
            seed_transpiler=algorithm_globals.random_seed,
        )
        vqe = VQE(
            ansatz=self.ry_wavefunction,
            optimizer=optimizer,
            gradient=Gradient(),
            expectation=AerPauliExpectation(),
            quantum_instance=quantum_instance,
            max_evals_grouped=1000,
        )
        vqe.compute_minimum_eigenvalue(operator=self.h2_op)

    def test_with_two_qubit_reduction(self):
        """Test the VQE using TwoQubitReduction."""
        qubit_op = PauliSumOp.from_list([
            ("IIII", -0.8105479805373266),
            ("IIIZ", 0.17218393261915552),
            ("IIZZ", -0.22575349222402472),
            ("IZZI", 0.1721839326191556),
            ("ZZII", -0.22575349222402466),
            ("IIZI", 0.1209126326177663),
            ("IZZZ", 0.16892753870087912),
            ("IXZX", -0.045232799946057854),
            ("ZXIX", 0.045232799946057854),
            ("IXIX", 0.045232799946057854),
            ("ZXZX", -0.045232799946057854),
            ("ZZIZ", 0.16614543256382414),
            ("IZIZ", 0.16614543256382414),
            ("ZZZZ", 0.17464343068300453),
            ("ZIZI", 0.1209126326177663),
        ])
        tapered_qubit_op = TwoQubitReduction(num_particles=2).convert(qubit_op)
        for simulator in [self.qasm_simulator, self.statevector_simulator]:
            with self.subTest(f"Test for {simulator}."):
                vqe = VQE(
                    self.ry_wavefunction,
                    SPSA(maxiter=300, last_avg=5),
                    quantum_instance=simulator,
                )
                result = vqe.compute_minimum_eigenvalue(tapered_qubit_op)
                energy = -1.868 if simulator == self.qasm_simulator else self.h2_energy
                self.assertAlmostEqual(result.eigenvalue.real,
                                       energy,
                                       places=2)

    def test_callback(self):
        """Test the callback on VQE."""
        history = {"eval_count": [], "parameters": [], "mean": [], "std": []}

        def store_intermediate_result(eval_count, parameters, mean, std):
            history["eval_count"].append(eval_count)
            history["parameters"].append(parameters)
            history["mean"].append(mean)
            history["std"].append(std)

        optimizer = COBYLA(maxiter=3)
        wavefunction = self.ry_wavefunction

        vqe = VQE(
            ansatz=wavefunction,
            optimizer=optimizer,
            callback=store_intermediate_result,
            quantum_instance=self.qasm_simulator,
        )
        vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        self.assertTrue(
            all(isinstance(count, int) for count in history["eval_count"]))
        self.assertTrue(
            all(isinstance(mean, float) for mean in history["mean"]))
        self.assertTrue(all(isinstance(std, float) for std in history["std"]))
        for params in history["parameters"]:
            self.assertTrue(all(isinstance(param, float) for param in params))

    def test_reuse(self):
        """Test re-using a VQE algorithm instance."""
        vqe = VQE()
        with self.subTest(msg="assert running empty raises AlgorithmError"):
            with self.assertRaises(AlgorithmError):
                _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        ansatz = TwoLocal(rotation_blocks=["ry", "rz"],
                          entanglement_blocks="cz")
        vqe.ansatz = ansatz
        with self.subTest(msg="assert missing operator raises AlgorithmError"):
            with self.assertRaises(AlgorithmError):
                _ = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        vqe.expectation = MatrixExpectation()
        vqe.quantum_instance = self.statevector_simulator
        with self.subTest(msg="assert VQE works once all info is available"):
            result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertAlmostEqual(result.eigenvalue.real,
                                   self.h2_energy,
                                   places=5)

        operator = PrimitiveOp(
            np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 2, 0], [0, 0, 0,
                                                                  3]]))

        with self.subTest(msg="assert minimum eigensolver interface works"):
            result = vqe.compute_minimum_eigenvalue(operator=operator)
            self.assertAlmostEqual(result.eigenvalue.real, -1.0, places=5)

    def test_vqe_optimizer(self):
        """Test running same VQE twice to re-use optimizer, then switch optimizer"""
        vqe = VQE(
            optimizer=SLSQP(),
            quantum_instance=QuantumInstance(
                BasicAer.get_backend("statevector_simulator")),
        )

        def run_check():
            result = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
            self.assertAlmostEqual(result.eigenvalue.real,
                                   -1.85727503,
                                   places=5)

        run_check()

        with self.subTest("Optimizer re-use"):
            run_check()

        with self.subTest("Optimizer replace"):
            vqe.optimizer = L_BFGS_B()
            run_check()

    @data(MatrixExpectation(), None)
    def test_backend_change(self, user_expectation):
        """Test that VQE works when backend changes."""
        vqe = VQE(
            ansatz=TwoLocal(rotation_blocks=["ry", "rz"],
                            entanglement_blocks="cz"),
            optimizer=SLSQP(maxiter=2),
            expectation=user_expectation,
            quantum_instance=BasicAer.get_backend("statevector_simulator"),
        )
        result0 = vqe.compute_minimum_eigenvalue(operator=self.h2_op)
        if user_expectation is not None:
            with self.subTest("User expectation kept."):
                self.assertEqual(vqe.expectation, user_expectation)

        vqe.quantum_instance = BasicAer.get_backend("qasm_simulator")

        # works also if no expectation is set, since it will be determined automatically
        result1 = vqe.compute_minimum_eigenvalue(operator=self.h2_op)

        if user_expectation is not None:
            with self.subTest(
                    "Change backend with user expectation, it is kept."):
                self.assertEqual(vqe.expectation, user_expectation)

        with self.subTest("Check results."):
            self.assertEqual(len(result0.optimal_point),
                             len(result1.optimal_point))

    def test_batch_evaluate_with_qnspsa(self):
        """Test batch evaluating with QNSPSA works."""
        ansatz = TwoLocal(2,
                          rotation_blocks=["ry", "rz"],
                          entanglement_blocks="cz")

        wrapped_backend = BasicAer.get_backend("qasm_simulator")
        inner_backend = BasicAer.get_backend("statevector_simulator")

        callcount = {"count": 0}

        def wrapped_run(circuits, **kwargs):
            kwargs["callcount"]["count"] += 1
            return inner_backend.run(circuits)

        wrapped_backend.run = partial(wrapped_run, callcount=callcount)

        fidelity = QNSPSA.get_fidelity(ansatz, backend=wrapped_backend)
        qnspsa = QNSPSA(fidelity, maxiter=5)

        vqe = VQE(
            ansatz=ansatz,
            optimizer=qnspsa,
            max_evals_grouped=100,
            quantum_instance=wrapped_backend,
        )
        _ = vqe.compute_minimum_eigenvalue(Z ^ Z)

        # 1 calibration + 1 stddev estimation + 1 initial blocking
        # + 5 (1 loss + 1 fidelity + 1 blocking) + 1 return loss + 1 VQE eval
        expected = 1 + 1 + 1 + 5 * 3 + 1 + 1

        self.assertEqual(callcount["count"], expected)
 def test_unsupported_expectation(self):
     """Assert passing an AerPauliExpectation raises an error."""
     expecation = AerPauliExpectation()
     with self.assertRaises(NotImplementedError):
         _ = CVaRExpectation(alpha=1, expectation=expecation)
Exemple #27
0
class TestVQE(QiskitAlgorithmsTestCase):
    """ Test VQE """
    def setUp(self):
        super().setUp()
        self.seed = 50
        aqua_globals.random_seed = self.seed
        self.h2_op = -1.052373245772859 * (I ^ I) \
            + 0.39793742484318045 * (I ^ Z) \
            - 0.39793742484318045 * (Z ^ I) \
            - 0.01128010425623538 * (Z ^ Z) \
            + 0.18093119978423156 * (X ^ X)
        self.h2_energy = -1.85727503

        self.ryrz_wavefunction = TwoLocal(rotation_blocks=['ry', 'rz'],
                                          entanglement_blocks='cz')
        self.ry_wavefunction = TwoLocal(rotation_blocks='ry',
                                        entanglement_blocks='cz')

        self.qasm_simulator = QuantumInstance(
            BasicAer.get_backend('qasm_simulator'),
            shots=1024,
            seed_simulator=self.seed,
            seed_transpiler=self.seed)
        self.statevector_simulator = QuantumInstance(
            BasicAer.get_backend('statevector_simulator'),
            shots=1,
            seed_simulator=self.seed,
            seed_transpiler=self.seed)

    def test_basic_aer_statevector(self):
        """Test the VQE on BasicAer's statevector simulator."""
        wavefunction = self.ryrz_wavefunction
        vqe = VQE(self.h2_op, wavefunction, L_BFGS_B())

        result = vqe.run(
            QuantumInstance(BasicAer.get_backend('statevector_simulator'),
                            basis_gates=['u1', 'u2', 'u3', 'cx', 'id'],
                            coupling_map=[[0, 1]],
                            seed_simulator=aqua_globals.random_seed,
                            seed_transpiler=aqua_globals.random_seed))

        with self.subTest(msg='test eigenvalue'):
            self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy)

        with self.subTest(msg='test dimension of optimal point'):
            self.assertEqual(len(result.optimal_point), 16)

        with self.subTest(msg='assert cost_function_evals is set'):
            self.assertIsNotNone(result.cost_function_evals)

        with self.subTest(msg='assert optimizer_time is set'):
            self.assertIsNotNone(result.optimizer_time)

    def test_circuit_input(self):
        """Test running the VQE on a plain QuantumCircuit object."""
        wavefunction = QuantumCircuit(2).compose(EfficientSU2(2))
        optimizer = SLSQP(maxiter=50)
        vqe = VQE(self.h2_op, wavefunction, optimizer=optimizer)
        result = vqe.run(self.statevector_simulator)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=5)

    @data(
        (MatrixExpectation(), 1),
        (AerPauliExpectation(), 1),
        (PauliExpectation(), 2),
    )
    @unpack
    def test_construct_circuit(self, expectation, num_circuits):
        """Test construct circuits returns QuantumCircuits and the right number of them."""
        try:
            wavefunction = EfficientSU2(2, reps=1)
            vqe = VQE(self.h2_op, wavefunction, expectation=expectation)
            params = [0] * wavefunction.num_parameters
            circuits = vqe.construct_circuit(params)

            self.assertEqual(len(circuits), num_circuits)
            for circuit in circuits:
                self.assertIsInstance(circuit, QuantumCircuit)
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
            return

    def test_legacy_operator(self):
        """Test the VQE accepts and converts the legacy WeightedPauliOperator."""
        pauli_dict = {
            'paulis': [{
                "coeff": {
                    "imag": 0.0,
                    "real": -1.052373245772859
                },
                "label": "II"
            }, {
                "coeff": {
                    "imag": 0.0,
                    "real": 0.39793742484318045
                },
                "label": "IZ"
            }, {
                "coeff": {
                    "imag": 0.0,
                    "real": -0.39793742484318045
                },
                "label": "ZI"
            }, {
                "coeff": {
                    "imag": 0.0,
                    "real": -0.01128010425623538
                },
                "label": "ZZ"
            }, {
                "coeff": {
                    "imag": 0.0,
                    "real": 0.18093119978423156
                },
                "label": "XX"
            }]
        }
        h2_op = WeightedPauliOperator.from_dict(pauli_dict)
        vqe = VQE(h2_op)
        self.assertEqual(vqe.operator, self.h2_op)

    def test_missing_varform_params(self):
        """Test specifying a variational form with no parameters raises an error."""
        circuit = QuantumCircuit(self.h2_op.num_qubits)
        vqe = VQE(self.h2_op, circuit)
        with self.assertRaises(RuntimeError):
            vqe.run(BasicAer.get_backend('statevector_simulator'))

    @data(
        (SLSQP(maxiter=50), 5, 4),
        (SPSA(maxiter=150), 3, 2),  # max_evals_grouped=n or =2 if n>2
    )
    @unpack
    def test_max_evals_grouped(self, optimizer, places, max_evals_grouped):
        """ VQE Optimizers test """
        vqe = VQE(self.h2_op,
                  self.ryrz_wavefunction,
                  optimizer,
                  max_evals_grouped=max_evals_grouped,
                  quantum_instance=self.statevector_simulator)
        result = vqe.run()
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=places)

    def test_basic_aer_qasm(self):
        """Test the VQE on BasicAer's QASM simulator."""
        optimizer = SPSA(maxiter=300, last_avg=5)
        wavefunction = self.ry_wavefunction

        vqe = VQE(self.h2_op, wavefunction, optimizer, max_evals_grouped=1)

        # TODO benchmark this later.
        result = vqe.run(self.qasm_simulator)
        self.assertAlmostEqual(result.eigenvalue.real, -1.86823, places=2)

    def test_qasm_aux_operators_normalized(self):
        """Test VQE with qasm_simulator returns normalized aux_operator eigenvalues."""
        wavefunction = self.ry_wavefunction
        vqe = VQE(self.h2_op,
                  wavefunction,
                  quantum_instance=self.qasm_simulator)

        opt_params = [
            3.50437328, 3.87415376, 0.93684363, 5.92219622, -1.53527887,
            1.87941418, -4.5708326, 0.70187027
        ]

        vqe._ret = {}
        vqe._ret['opt_params'] = opt_params
        vqe._ret['opt_params_dict'] = \
            dict(zip(sorted(wavefunction.parameters, key=lambda p: p.name), opt_params))

        optimal_vector = vqe.get_optimal_vector()
        self.assertAlmostEqual(sum([v**2 for v in optimal_vector.values()]),
                               1.0,
                               places=4)

    def test_with_aer_statevector(self):
        """Test VQE with Aer's statevector_simulator."""
        try:
            # pylint: disable=import-outside-toplevel
            from qiskit import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('statevector_simulator')
        wavefunction = self.ry_wavefunction
        optimizer = L_BFGS_B()

        vqe = VQE(self.h2_op, wavefunction, optimizer, max_evals_grouped=1)

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=aqua_globals.random_seed,
            seed_transpiler=aqua_globals.random_seed)
        result = vqe.run(quantum_instance)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)

    def test_with_aer_qasm(self):
        """Test VQE with Aer's qasm_simulator."""
        try:
            # pylint: disable=import-outside-toplevel
            from qiskit import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')
        optimizer = SPSA(maxiter=200, last_avg=5)
        wavefunction = self.ry_wavefunction

        vqe = VQE(self.h2_op,
                  wavefunction,
                  optimizer,
                  expectation=PauliExpectation())

        quantum_instance = QuantumInstance(
            backend,
            seed_simulator=aqua_globals.random_seed,
            seed_transpiler=aqua_globals.random_seed)
        result = vqe.run(quantum_instance)
        self.assertAlmostEqual(result.eigenvalue.real, -1.86305, places=2)

    def test_with_aer_qasm_snapshot_mode(self):
        """Test the VQE using Aer's qasm_simulator snapshot mode."""
        try:
            # pylint: disable=import-outside-toplevel
            from qiskit import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')
        optimizer = L_BFGS_B()
        wavefunction = self.ry_wavefunction

        vqe = VQE(self.h2_op,
                  wavefunction,
                  optimizer,
                  expectation=AerPauliExpectation())

        quantum_instance = QuantumInstance(
            backend,
            shots=1,
            seed_simulator=aqua_globals.random_seed,
            seed_transpiler=aqua_globals.random_seed)
        result = vqe.run(quantum_instance)
        self.assertAlmostEqual(result.eigenvalue.real,
                               self.h2_energy,
                               places=6)

    def test_callback(self):
        """Test the callback on VQE."""
        history = {'eval_count': [], 'parameters': [], 'mean': [], 'std': []}

        def store_intermediate_result(eval_count, parameters, mean, std):
            history['eval_count'].append(eval_count)
            history['parameters'].append(parameters)
            history['mean'].append(mean)
            history['std'].append(std)

        optimizer = COBYLA(maxiter=3)
        wavefunction = self.ry_wavefunction

        vqe = VQE(self.h2_op,
                  wavefunction,
                  optimizer,
                  callback=store_intermediate_result)
        vqe.run(self.qasm_simulator)

        self.assertTrue(
            all(isinstance(count, int) for count in history['eval_count']))
        self.assertTrue(
            all(isinstance(mean, float) for mean in history['mean']))
        self.assertTrue(all(isinstance(std, float) for std in history['std']))
        for params in history['parameters']:
            self.assertTrue(all(isinstance(param, float) for param in params))

    def test_reuse(self):
        """Test re-using a VQE algorithm instance."""
        vqe = VQE()
        with self.subTest(msg='assert running empty raises AlgorithmError'):
            with self.assertRaises(AlgorithmError):
                _ = vqe.run()

        var_form = TwoLocal(rotation_blocks=['ry', 'rz'],
                            entanglement_blocks='cz')
        vqe.var_form = var_form
        with self.subTest(msg='assert missing operator raises AlgorithmError'):
            with self.assertRaises(AlgorithmError):
                _ = vqe.run()

        vqe.operator = self.h2_op
        with self.subTest(msg='assert missing backend raises AlgorithmError'):
            with self.assertRaises(AlgorithmError):
                _ = vqe.run()

        vqe.quantum_instance = self.statevector_simulator
        with self.subTest(msg='assert VQE works once all info is available'):
            result = vqe.run()
            self.assertAlmostEqual(result.eigenvalue.real,
                                   self.h2_energy,
                                   places=5)

        operator = PrimitiveOp(
            np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 2, 0], [0, 0, 0,
                                                                  3]]))

        with self.subTest(msg='assert minimum eigensolver interface works'):
            result = vqe.compute_minimum_eigenvalue(operator)
            self.assertAlmostEqual(result.eigenvalue.real, -1.0, places=5)

    def test_vqe_optimizer(self):
        """ Test running same VQE twice to re-use optimizer, then switch optimizer """
        vqe = VQE(self.h2_op,
                  optimizer=SLSQP(),
                  quantum_instance=QuantumInstance(
                      BasicAer.get_backend('statevector_simulator')))

        def run_check():
            result = vqe.compute_minimum_eigenvalue()
            self.assertAlmostEqual(result.eigenvalue.real,
                                   -1.85727503,
                                   places=5)

        run_check()

        with self.subTest('Optimizer re-use'):
            run_check()

        with self.subTest('Optimizer replace'):
            vqe.optimizer = L_BFGS_B()
            run_check()

    def test_vqe_expectation_select(self):
        """Test expectation selection with Aer's qasm_simulator."""
        try:
            # pylint: disable=import-outside-toplevel
            from qiskit import Aer
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest(
                "Aer doesn't appear to be installed. Error: '{}'".format(
                    str(ex)))
            return
        backend = Aer.get_backend('qasm_simulator')

        with self.subTest('Defaults'):
            vqe = VQE(self.h2_op, quantum_instance=backend)
            self.assertIsInstance(vqe.expectation, PauliExpectation)

        with self.subTest('Include custom'):
            vqe = VQE(self.h2_op,
                      include_custom=True,
                      quantum_instance=backend)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)

        with self.subTest('Set explicitly'):
            vqe = VQE(self.h2_op,
                      expectation=AerPauliExpectation(),
                      quantum_instance=backend)
            self.assertIsInstance(vqe.expectation, AerPauliExpectation)

    @unittest.skip(reason="IBMQ testing not available in general.")
    def test_ibmq(self):
        """ IBMQ VQE Test """
        from qiskit import IBMQ
        provider = IBMQ.load_account()
        backend = provider.get_backend('ibmq_qasm_simulator')
        ansatz = TwoLocal(rotation_blocks=['ry', 'rz'],
                          entanglement_blocks='cz')

        opt = SLSQP(maxiter=1)
        opt.set_max_evals_grouped(100)
        vqe = VQE(self.h2_op, ansatz, SLSQP(maxiter=2))

        result = vqe.run(backend)
        print(result)
        self.assertAlmostEqual(result.eigenvalue.real, self.h2_energy)
        np.testing.assert_array_almost_equal(result.eigenvalue.real,
                                             self.h2_energy, 5)
        self.assertEqual(len(result.optimal_point), 16)
        self.assertIsNotNone(result.cost_function_evals)
        self.assertIsNotNone(result.optimizer_time)

    @data(MatrixExpectation(), None)
    def test_backend_change(self, user_expectation):
        """Test that VQE works when backend changes."""
        vqe = VQE(
            operator=self.h2_op,
            var_form=TwoLocal(rotation_blocks=['ry', 'rz'],
                              entanglement_blocks='cz'),
            optimizer=SLSQP(maxiter=2),
            expectation=user_expectation,
            quantum_instance=BasicAer.get_backend('statevector_simulator'))
        result0 = vqe.run()
        if user_expectation is not None:
            with self.subTest('User expectation kept.'):
                self.assertEqual(vqe.expectation, user_expectation)
        else:
            with self.subTest('Expectation created.'):
                self.assertIsInstance(vqe.expectation, ExpectationBase)
        try:
            vqe.set_backend(BasicAer.get_backend('qasm_simulator'))
        except Exception as ex:  # pylint: disable=broad-except
            self.fail("Failed to change backend. Error: '{}'".format(str(ex)))
            return

        result1 = vqe.run()
        if user_expectation is not None:
            with self.subTest(
                    'Change backend with user expectation, it is kept.'):
                self.assertEqual(vqe.expectation, user_expectation)
        else:
            with self.subTest(
                    'Change backend without user expectation, one created.'):
                self.assertIsInstance(vqe.expectation, ExpectationBase)

        with self.subTest('Check results.'):
            self.assertEqual(len(result0.optimal_point),
                             len(result1.optimal_point))
Exemple #28
0
class TestAerPauliExpectation(QiskitOpflowTestCase):
    """Pauli Change of Basis Expectation tests."""

    def setUp(self) -> None:
        super().setUp()
        try:
            from qiskit import Aer

            self.seed = 97
            self.backend = Aer.get_backend("aer_simulator")
            q_instance = QuantumInstance(
                self.backend, seed_simulator=self.seed, seed_transpiler=self.seed
            )
            self.sampler = CircuitSampler(q_instance, attach_results=True)
            self.expect = AerPauliExpectation()
        except Exception as ex:  # pylint: disable=broad-except
            self.skipTest("Aer doesn't appear to be installed. Error: '{}'".format(str(ex)))
            return

    def test_pauli_expect_pair(self):
        """pauli expect pair test"""
        op = Z ^ Z
        # wvf = (Pl^Pl) + (Ze^Ze)
        wvf = CX @ (H ^ I) @ Zero

        converted_meas = self.expect.convert(~StateFn(op) @ wvf)
        sampled = self.sampler.convert(converted_meas)
        self.assertAlmostEqual(sampled.eval(), 0, delta=0.1)

    def test_pauli_expect_single(self):
        """pauli expect single test"""
        # TODO bug in Aer with Y measurements
        # paulis = [Z, X, Y, I]
        paulis = [Z, X, I]
        states = [Zero, One, Plus, Minus, S @ Plus, S @ Minus]
        for pauli, state in itertools.product(paulis, states):
            converted_meas = self.expect.convert(~StateFn(pauli) @ state)
            matmulmean = state.adjoint().to_matrix() @ pauli.to_matrix() @ state.to_matrix()
            sampled = self.sampler.convert(converted_meas)
            self.assertAlmostEqual(sampled.eval(), matmulmean, delta=0.1)

    def test_pauli_expect_op_vector(self):
        """pauli expect op vector test"""
        paulis_op = ListOp([X, Y, Z, I])
        converted_meas = self.expect.convert(~StateFn(paulis_op))

        plus_mean = converted_meas @ Plus
        sampled_plus = self.sampler.convert(plus_mean)
        np.testing.assert_array_almost_equal(sampled_plus.eval(), [1, 0, 0, 1], decimal=1)

        minus_mean = converted_meas @ Minus
        sampled_minus = self.sampler.convert(minus_mean)
        np.testing.assert_array_almost_equal(sampled_minus.eval(), [-1, 0, 0, 1], decimal=1)

        zero_mean = converted_meas @ Zero
        sampled_zero = self.sampler.convert(zero_mean)
        np.testing.assert_array_almost_equal(sampled_zero.eval(), [0, 0, 1, 1], decimal=1)

        sum_zero = (Plus + Minus) * (0.5 ** 0.5)
        sum_zero_mean = converted_meas @ sum_zero
        sampled_zero_mean = self.sampler.convert(sum_zero_mean)
        # !!NOTE!!: Depolarizing channel (Sampling) means interference
        # does not happen between circuits in sum, so expectation does
        # not equal expectation for Zero!!
        np.testing.assert_array_almost_equal(sampled_zero_mean.eval(), [0, 0, 0, 2], decimal=1)

    def test_pauli_expect_state_vector(self):
        """pauli expect state vector test"""
        states_op = ListOp([One, Zero, Plus, Minus])

        paulis_op = X
        converted_meas = self.expect.convert(~StateFn(paulis_op) @ states_op)
        sampled = self.sampler.convert(converted_meas)

        # Small test to see if execution results are accessible
        for composed_op in sampled:
            self.assertIn("counts", composed_op[0].execution_results)

        np.testing.assert_array_almost_equal(sampled.eval(), [0, 0, 1, -1], decimal=1)

    def test_pauli_expect_op_vector_state_vector(self):
        """pauli expect op vector state vector test"""
        # TODO Bug in Aer with Y Measurements!!
        # paulis_op = ListOp([X, Y, Z, I])
        paulis_op = ListOp([X, Z, I])
        states_op = ListOp([One, Zero, Plus, Minus])

        valids = [
            [+0, 0, 1, -1],
            # [+0, 0, 0, 0],
            [-1, 1, 0, -0],
            [+1, 1, 1, 1],
        ]
        converted_meas = self.expect.convert(~StateFn(paulis_op) @ states_op)
        sampled = self.sampler.convert(converted_meas)
        np.testing.assert_array_almost_equal(sampled.eval(), valids, decimal=1)

    def test_multi_representation_ops(self):
        """Test observables with mixed representations"""
        mixed_ops = ListOp([X.to_matrix_op(), H, H + I, X])
        converted_meas = self.expect.convert(~StateFn(mixed_ops))

        plus_mean = converted_meas @ Plus
        sampled_plus = self.sampler.convert(plus_mean)
        np.testing.assert_array_almost_equal(
            sampled_plus.eval(), [1, 0.5 ** 0.5, (1 + 0.5 ** 0.5), 1], decimal=1
        )

    @unittest.skip("Skip until https://github.com/Qiskit/qiskit-aer/issues/1249 is closed.")
    def test_parameterized_qobj(self):
        """grouped pauli expectation test"""
        two_qubit_h2 = (
            (-1.052373245772859 * I ^ I)
            + (0.39793742484318045 * I ^ Z)
            + (-0.39793742484318045 * Z ^ I)
            + (-0.01128010425623538 * Z ^ Z)
            + (0.18093119978423156 * X ^ X)
        )

        aer_sampler = CircuitSampler(
            self.sampler.quantum_instance, param_qobj=True, attach_results=True
        )

        ansatz = RealAmplitudes()
        ansatz.num_qubits = 2

        observable_meas = self.expect.convert(StateFn(two_qubit_h2, is_measurement=True))
        ansatz_circuit_op = CircuitStateFn(ansatz)
        expect_op = observable_meas.compose(ansatz_circuit_op).reduce()

        def generate_parameters(num):
            param_bindings = {}
            for param in ansatz.parameters:
                values = []
                for _ in range(num):
                    values.append(np.random.rand())
                param_bindings[param] = values
            return param_bindings

        def validate_sampler(ideal, sut, param_bindings):
            expect_sampled = ideal.convert(expect_op, params=param_bindings).eval()
            actual_sampled = sut.convert(expect_op, params=param_bindings).eval()
            self.assertTrue(
                np.allclose(actual_sampled, expect_sampled),
                "%s != %s" % (actual_sampled, expect_sampled),
            )

        def get_circuit_templates(sampler):
            return sampler._transpiled_circ_templates

        def validate_aer_binding_used(templates):
            self.assertIsNotNone(templates)

        def validate_aer_templates_reused(prev_templates, cur_templates):
            self.assertIs(prev_templates, cur_templates)

        validate_sampler(self.sampler, aer_sampler, generate_parameters(1))
        cur_templates = get_circuit_templates(aer_sampler)

        validate_aer_binding_used(cur_templates)

        prev_templates = cur_templates
        validate_sampler(self.sampler, aer_sampler, generate_parameters(2))
        cur_templates = get_circuit_templates(aer_sampler)

        validate_aer_templates_reused(prev_templates, cur_templates)

        prev_templates = cur_templates
        validate_sampler(self.sampler, aer_sampler, generate_parameters(2))  # same num of params
        cur_templates = get_circuit_templates(aer_sampler)

        validate_aer_templates_reused(prev_templates, cur_templates)

    def test_pauli_expectation_param_qobj(self):
        """Test PauliExpectation with param_qobj"""
        q_instance = QuantumInstance(
            self.backend, seed_simulator=self.seed, seed_transpiler=self.seed, shots=10000
        )
        qubit_op = (0.1 * I ^ I) + (0.2 * I ^ Z) + (0.3 * Z ^ I) + (0.4 * Z ^ Z) + (0.5 * X ^ X)
        ansatz = RealAmplitudes(qubit_op.num_qubits)
        ansatz_circuit_op = CircuitStateFn(ansatz)
        observable = PauliExpectation().convert(~StateFn(qubit_op))
        expect_op = observable.compose(ansatz_circuit_op).reduce()
        params1 = {}
        params2 = {}
        for param in ansatz.parameters:
            params1[param] = [0]
            params2[param] = [0, 0]

        sampler1 = CircuitSampler(backend=q_instance, param_qobj=False)
        samples1 = sampler1.convert(expect_op, params=params1)
        val1 = np.real(samples1.eval())[0]
        samples2 = sampler1.convert(expect_op, params=params2)
        val2 = np.real(samples2.eval())
        sampler2 = CircuitSampler(backend=q_instance, param_qobj=True)
        samples3 = sampler2.convert(expect_op, params=params1)
        val3 = np.real(samples3.eval())
        samples4 = sampler2.convert(expect_op, params=params2)
        val4 = np.real(samples4.eval())

        np.testing.assert_array_almost_equal([val1] * 2, val2, decimal=2)
        np.testing.assert_array_almost_equal(val1, val3, decimal=2)
        np.testing.assert_array_almost_equal([val1] * 2, val4, decimal=2)

    def test_list_pauli_sum(self):
        """Test AerPauliExpectation for ListOp[PauliSumOp]"""
        test_op = ListOp([PauliSumOp.from_list([("XX", 1), ("ZI", 3), ("ZZ", 5)])])
        observable = AerPauliExpectation().convert(~StateFn(test_op))
        self.assertIsInstance(observable, ListOp)
        self.assertIsInstance(observable[0], CircuitStateFn)
        self.assertTrue(observable[0].is_measurement)

    def test_pauli_expectation_non_hermite_op(self):
        """Test PauliExpectation for non hermitian operator"""
        exp = ~StateFn(1j * Z) @ One
        self.assertEqual(self.sampler.convert(self.expect.convert(exp)).eval(), 1j)