def setUp(self) -> None:
     super().setUp()
     self.seed = 97
     backend = BasicAer.get_backend('qasm_simulator')
     q_instance = QuantumInstance(backend, seed_simulator=self.seed, seed_transpiler=self.seed)
     self.sampler = CircuitSampler(q_instance, attach_results=True)
     self.expect = PauliExpectation()
Ejemplo n.º 2
0
    def _eval_op(self, state, op, quantum_instance):
        if isinstance(op, WeightedPauliOperator):
            op = op.to_opflow()

        # if the operator is empty we simply return 0
        if op == 0:
            # Note, that for some reason the individual results need to be wrapped in lists.
            # See also: VQE._eval_aux_ops()
            return [0.j]

        exp = ~StateFn(op) @ state  # <state|op|state>

        if quantum_instance is not None:
            try:
                sampler = CircuitSampler(quantum_instance)
                result = sampler.convert(exp).eval()
            except ValueError:
                # TODO make this cleaner. The reason for it being here is that some quantum
                # instances can lead to non-positive statevectors which the Qiskit circuit
                # Initializer is unable to handle.
                result = exp.eval()
        else:
            result = exp.eval()

        # Note, that for some reason the individual results need to be wrapped in lists.
        # See also: VQE._eval_aux_ops()
        return [result]
Ejemplo n.º 3
0
def get_exp(H, circ):
    psi = CircuitStateFn(circ)
    backend = Aer.get_backend('statevector_simulator')
    measurable_expression = StateFn(H, is_measurement=True).compose(psi)
    expectation = AerPauliExpectation().convert(measurable_expression)
    sampler = CircuitSampler(backend).convert(expectation)
    return sampler.eval().real
Ejemplo n.º 4
0
    def quantum_instance(self, quantum_instance: Union[QuantumInstance, BaseBackend]) -> None:
        """ set quantum_instance """
        super(VQE, self.__class__).quantum_instance.__set__(self, quantum_instance)

        self._circuit_sampler = CircuitSampler(self._quantum_instance)
        # Expectation was not passed by user, try to create one
        if not self._user_valid_expectation:
            self._try_set_expectation_value_from_factory()
Ejemplo n.º 5
0
def expectation(wavefn, operator, backend):
    """Returns the expectation value of an operator with the provided wavefunction using the provided backend"""
    exp = ExpectationFactory.build(operator=operator, backend=backend)
    composed_circuit = exp.convert(StateFn(operator,
                                           is_measurement=True)).compose(
                                               CircuitStateFn(wavefn))
    sampler = CircuitSampler(backend)
    vals = sampler.convert(composed_circuit).eval()
    return np.real(vals)
Ejemplo n.º 6
0
    def test_circuit_sampler2(self, method):
        """Test the probability gradient with the circuit sampler

        dp0/da = cos(a)sin(b) / 2
        dp1/da = - cos(a)sin(b) / 2
        dp0/db = sin(a)cos(b) / 2
        dp1/db = - sin(a)cos(b) / 2
        """

        a = Parameter('a')
        b = Parameter('b')
        params = [a, b]

        q = QuantumRegister(1)
        qc = QuantumCircuit(q)
        qc.h(q)
        qc.rz(params[0], q[0])
        qc.rx(params[1], q[0])

        op = CircuitStateFn(primitive=qc, coeff=1.)

        shots = 8000
        if method == 'fin_diff':
            np.random.seed(8)
            prob_grad = Gradient(grad_method=method,
                                 epsilon=shots**(-1 / 6.)).convert(
                                     operator=op, params=params)
        else:
            prob_grad = Gradient(grad_method=method).convert(operator=op,
                                                             params=params)
        values_dict = [{
            a: [np.pi / 4],
            b: [0]
        }, {
            params[0]: [np.pi / 4],
            params[1]: [np.pi / 4]
        }, {
            params[0]: [np.pi / 2],
            params[1]: [np.pi]
        }]
        correct_values = [[[0, 0],
                           [1 / (2 * np.sqrt(2)), -1 / (2 * np.sqrt(2))]],
                          [[1 / 4, -1 / 4], [1 / 4, -1 / 4]],
                          [[0, 0], [-1 / 2, 1 / 2]]]

        backend = BasicAer.get_backend('qasm_simulator')
        q_instance = QuantumInstance(backend=backend, shots=shots)

        for i, value_dict in enumerate(values_dict):
            sampler = CircuitSampler(backend=q_instance).convert(
                prob_grad, params=value_dict)
            result = sampler.eval()
            np.testing.assert_array_almost_equal(result[0],
                                                 correct_values[i],
                                                 decimal=1)
Ejemplo n.º 7
0
    def test_circuit_sampler(self, method):
        """Test the gradient with circuit sampler

        Tr(|psi><psi|Z) = sin(a)sin(b)
        Tr(|psi><psi|X) = cos(a)
        d<H>/da = - 0.5 sin(a) - 1 cos(a)sin(b)
        d<H>/db = - 1 sin(a)cos(b)
        """

        ham = 0.5 * X - 1 * Z
        a = Parameter('a')
        b = Parameter('b')
        params = [a, b]

        q = QuantumRegister(1)
        qc = QuantumCircuit(q)
        qc.h(q)
        qc.rz(params[0], q[0])
        qc.rx(params[1], q[0])
        op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.)

        shots = 8000
        if method == 'fin_diff':
            np.random.seed(8)
            state_grad = Gradient(grad_method=method,
                                  epsilon=shots**(-1 / 6.)).convert(
                                      operator=op, params=params)
        else:
            state_grad = Gradient(grad_method=method).convert(operator=op,
                                                              params=params)
        values_dict = [{
            a: np.pi / 4,
            b: np.pi
        }, {
            params[0]: np.pi / 4,
            params[1]: np.pi / 4
        }, {
            params[0]: np.pi / 2,
            params[1]: np.pi / 4
        }]
        correct_values = [[-0.5 / np.sqrt(2), 1 / np.sqrt(2)],
                          [-0.5 / np.sqrt(2) - 0.5, -1 / 2.],
                          [-0.5, -1 / np.sqrt(2)]]

        backend = BasicAer.get_backend('qasm_simulator')
        q_instance = QuantumInstance(backend=backend, shots=shots)

        for i, value_dict in enumerate(values_dict):
            sampler = CircuitSampler(backend=q_instance).convert(
                state_grad, params={k: [v]
                                    for k, v in value_dict.items()})
            np.testing.assert_array_almost_equal(sampler.eval()[0],
                                                 correct_values[i],
                                                 decimal=1)
Ejemplo n.º 8
0
    def quantum_instance(self, quantum_instance: Union[QuantumInstance, BaseBackend]) -> None:
        """ set quantum_instance """
        super(VVQE, self.__class__).quantum_instance.__set__(self, quantum_instance)

        if self._circuit_sampler is None:
            self._circuit_sampler = CircuitSampler(self._quantum_instance)
        else:
            self._circuit_sampler.quantum_instance = self._quantum_instance

        if self._expectation is None:
            self._try_set_expectation_value_from_factory()
Ejemplo n.º 9
0
    def test_ibmq_grouped_pauli_expectation(self):
        """ pauli expect op vector state vector test """
        from qiskit import IBMQ
        p = IBMQ.load_account()
        backend = p.get_backend('ibmq_qasm_simulator')
        paulis_op = ListOp([X, Y, 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 = CircuitSampler(backend).convert(converted_meas)
        np.testing.assert_array_almost_equal(sampled.eval(), valids, decimal=1)
Ejemplo n.º 10
0
    def _eval_aux_ops(self, threshold=1e-12):
        # Create new CircuitSampler to avoid breaking existing one's caches.
        sampler = CircuitSampler(self.quantum_instance)

        aux_op_meas = self.expectation.convert(StateFn(self.aux_operators, is_measurement=True))
        aux_op_expect = aux_op_meas.compose(CircuitStateFn(self.get_optimal_circuit()))
        values = np.real(sampler.convert(aux_op_expect).eval())

        # Discard values below threshold
        aux_op_results = (values * (np.abs(values) > threshold))
        # Deal with the aux_op behavior where there can be Nones or Zero qubit Paulis in the list
        self._ret['aux_ops'] = [None if is_none else [result]
                                for (is_none, result) in zip(self._aux_op_nones, aux_op_results)]
        self._ret['aux_ops'] = np.array([self._ret['aux_ops']])
    def setUp(self) -> None:
        super().setUp()
        try:
            from qiskit import Aer

            self.seed = 97
            self.backend = Aer.get_backend('qasm_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_expectation_param_qobj(self):
        """ Test PauliExpectation with param_qobj """
        q_instance = QuantumInstance(self.backend,
                                     seed_simulator=self.seed,
                                     seed_transpiler=self.seed,
                                     shots=20000)
        qubit_op = (1 * I ^ I) + (2 * I ^ Z) + (3 * Z ^ I) + (4 * Z ^ Z) + (
            5 * X ^ X)
        var_form = RealAmplitudes(qubit_op.num_qubits)
        ansatz_circuit_op = CircuitStateFn(var_form)
        observable = PauliExpectation().convert(~StateFn(qubit_op))
        expect_op = observable.compose(ansatz_circuit_op).reduce()
        params1 = {}
        params2 = {}
        for param in var_form.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)
Ejemplo n.º 13
0
 def test_is_measurement_correctly_propagated(self):
     """Test if is_measurement property of StateFn is propagated to converted StateFn."""
     backend = Aer.get_backend('qasm_simulator')
     q_instance = QuantumInstance(backend)  # no seeds needed since no values are compared
     state = Plus
     sampler = CircuitSampler(q_instance).convert(~state @ state)
     self.assertTrue(sampler.oplist[0].is_measurement)
Ejemplo n.º 14
0
    def _eval_aux_ops(self, threshold=1e-12):
        # Create new CircuitSampler to avoid breaking existing one's caches.
        sampler = CircuitSampler(self.quantum_instance)

        aux_op_meas = self.expectation.convert(StateFn(self.aux_operators, is_measurement=True))
        aux_op_expect = aux_op_meas.compose(CircuitStateFn(self.get_optimal_circuit()))
        values = np.real(sampler.convert(aux_op_expect).eval())

        # Discard values below threshold
        aux_op_results = (values * (np.abs(values) > threshold))
        # Deal with the aux_op behavior where there can be Nones or Zero qubit Paulis in the list
        self._ret['aux_ops'] = [None if is_none else [result]
                                for (is_none, result) in zip(self._aux_op_nones, aux_op_results)]
        # As this has mixed types, since it can included None, it needs to explicitly pass object
        # data type to avoid numpy 1.19 warning message about implicit conversion being deprecated
        self._ret['aux_ops'] = np.array([self._ret['aux_ops']], dtype=object)
Ejemplo n.º 15
0
    def test_grouped_pauli_expectation(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)
        wf = CX @ (H ^ I) @ Zero
        expect_op = PauliExpectation(group_paulis=False).convert(~StateFn(two_qubit_H2) @ wf)
        self.sampler._extract_circuitstatefns(expect_op)
        num_circuits_ungrouped = len(self.sampler._circuit_ops_cache)
        self.assertEqual(num_circuits_ungrouped, 5)

        expect_op_grouped = PauliExpectation(group_paulis=True).convert(~StateFn(two_qubit_H2) @ wf)
        sampler = CircuitSampler(BasicAer.get_backend('statevector_simulator'))
        sampler._extract_circuitstatefns(expect_op_grouped)
        num_circuits_grouped = len(sampler._circuit_ops_cache)
        self.assertEqual(num_circuits_grouped, 2)
Ejemplo n.º 16
0
    def test_parameter_binding_on_listop(self):
        """Test passing a ListOp with differing parameters works with the circuit sampler."""
        x, y = Parameter('x'), Parameter('y')

        circuit1 = QuantumCircuit(1)
        circuit1.p(0.2, 0)
        circuit2 = QuantumCircuit(1)
        circuit2.p(x, 0)
        circuit3 = QuantumCircuit(1)
        circuit3.p(y, 0)

        bindings = {x: -0.4, y: 0.4}
        listop = ListOp(
            [StateFn(circuit) for circuit in [circuit1, circuit2, circuit3]])

        sampler = CircuitSampler(Aer.get_backend('qasm_simulator'))
        sampled = sampler.convert(listop, params=bindings)

        self.assertTrue(all(len(op.parameters) == 0 for op in sampled.oplist))
Ejemplo n.º 17
0
    def test_coefficients_correctly_propagated(self):
        """Test that the coefficients in SummedOp and states are correctly used."""
        with self.subTest('zero coeff in SummedOp'):
            op = 0 * (I + Z)
            state = Plus
            self.assertEqual((~StateFn(op) @ state).eval(), 0j)

        backend = Aer.get_backend('qasm_simulator')
        op = I
        with self.subTest('zero coeff in summed StateFn and CircuitSampler'):
            state = 0 * (Plus + Minus)
            sampler = CircuitSampler(backend).convert(~StateFn(op) @ state)
            self.assertEqual(sampler.eval(), 0j)

        with self.subTest(
                'coeff gets squared in CircuitSampler shot-based readout'):
            state = (Plus + Minus) / numpy.sqrt(2)
            sampler = CircuitSampler(backend).convert(~StateFn(op) @ state)
            self.assertAlmostEqual(sampler.eval(), 1 + 0j)
Ejemplo n.º 18
0
 def setUp(self) -> None:
     super().setUp()
     backend = BasicAer.get_backend('qasm_simulator')
     self.sampler = CircuitSampler(backend, attach_results=True)
     self.expect = PauliExpectation()
Ejemplo n.º 19
0
class TestPauliExpectation(QiskitAquaTestCase):
    """Pauli Change of Basis Expectation tests."""

    def setUp(self) -> None:
        super().setUp()
        backend = BasicAer.get_backend('qasm_simulator')
        self.sampler = CircuitSampler(backend, attach_results=True)
        self.expect = PauliExpectation()

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

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

    def test_pauli_expect_single(self):
        """ pauli expect single test """
        paulis = [Z, X, Y, 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()
            self.assertAlmostEqual(converted_meas.eval(), matmulmean, delta=.1)

            sampled = self.sampler.convert(converted_meas)
            self.assertAlmostEqual(sampled.eval(), matmulmean, delta=.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)
        np.testing.assert_array_almost_equal(plus_mean.eval(), [1, 0, 0, 1], decimal=1)
        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)
        np.testing.assert_array_almost_equal(minus_mean.eval(), [-1, 0, 0, 1], decimal=1)
        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)
        np.testing.assert_array_almost_equal(zero_mean.eval(), [0, 0, 1, 1], decimal=1)
        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) * (.5 ** .5)
        sum_zero_mean = (converted_meas @ sum_zero)
        np.testing.assert_array_almost_equal(sum_zero_mean.eval(), [0, 0, 1, 1], decimal=1)
        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, 1], decimal=1)

        for i, op in enumerate(paulis_op.oplist):
            mat_op = op.to_matrix()
            np.testing.assert_array_almost_equal(zero_mean.eval()[i],
                                                 Zero.adjoint().to_matrix() @
                                                 mat_op @ Zero.to_matrix(),
                                                 decimal=1)
            np.testing.assert_array_almost_equal(plus_mean.eval()[i],
                                                 Plus.adjoint().to_matrix() @
                                                 mat_op @ Plus.to_matrix(),
                                                 decimal=1)
            np.testing.assert_array_almost_equal(minus_mean.eval()[i],
                                                 Minus.adjoint().to_matrix() @
                                                 mat_op @ Minus.to_matrix(),
                                                 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)
        np.testing.assert_array_almost_equal(converted_meas.eval(), [0, 0, 1, -1], decimal=1)

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

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

    def test_pauli_expect_op_vector_state_vector(self):
        """ pauli expect op vector state vector test """
        paulis_op = ListOp([X, Y, 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)
        np.testing.assert_array_almost_equal(converted_meas.eval(), valids, decimal=1)

        sampled = self.sampler.convert(converted_meas)
        np.testing.assert_array_almost_equal(sampled.eval(), valids, decimal=1)

    def test_not_to_matrix_called(self):
        """ 45 qubit calculation - literally will not work if to_matrix is
            somehow called (in addition to massive=False throwing an error)"""

        qs = 45
        states_op = ListOp([Zero ^ qs,
                            One ^ qs,
                            (Zero ^ qs) + (One ^ qs)])
        paulis_op = ListOp([Z ^ qs,
                            (I ^ Z ^ I) ^ int(qs / 3)])

        converted_meas = self.expect.convert(~StateFn(paulis_op) @ states_op)
        np.testing.assert_array_almost_equal(converted_meas.eval(), [[1, -1, 0], [1, -1, 0]])

    def test_grouped_pauli_expectation(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)
        wf = CX @ (H ^ I) @ Zero
        expect_op = PauliExpectation(group_paulis=False).convert(~StateFn(two_qubit_H2) @ wf)
        self.sampler._extract_circuitstatefns(expect_op)
        num_circuits_ungrouped = len(self.sampler._circuit_ops_cache)
        self.assertEqual(num_circuits_ungrouped, 5)

        expect_op_grouped = PauliExpectation(group_paulis=True).convert(~StateFn(two_qubit_H2) @ wf)
        sampler = CircuitSampler(BasicAer.get_backend('statevector_simulator'))
        sampler._extract_circuitstatefns(expect_op_grouped)
        num_circuits_grouped = len(sampler._circuit_ops_cache)
        self.assertEqual(num_circuits_grouped, 2)

    @unittest.skip(reason="IBMQ testing not available in general.")
    def test_ibmq_grouped_pauli_expectation(self):
        """ pauli expect op vector state vector test """
        from qiskit import IBMQ
        p = IBMQ.load_account()
        backend = p.get_backend('ibmq_qasm_simulator')
        paulis_op = ListOp([X, Y, 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 = CircuitSampler(backend).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, .5**.5, (1 + .5**.5), 1],
                                             decimal=1)
Ejemplo n.º 20
0
class TestAerPauliExpectation(QiskitAquaTestCase):
    """Pauli Change of Basis Expectation tests."""
    def setUp(self) -> None:
        super().setUp()
        backend = Aer.get_backend('qasm_simulator')
        self.sampler = CircuitSampler(backend, attach_results=True)
        self.expect = AerPauliExpectation()

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

        converted_meas = self.expect.convert(~StateFn(op) @ wf)
        sampled = self.sampler.convert(converted_meas)
        self.assertAlmostEqual(sampled.eval(), 0, delta=.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=.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)
        # TODO bug with Aer's Y
        np.testing.assert_array_almost_equal(sampled_zero.eval(), [0, 1, 1, 1],
                                             decimal=1)

        sum_zero = (Plus + Minus) * (.5**.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, .5**.5, (1 + .5**.5), 1],
                                             decimal=1)

    def test_parameterized_qobj(self):
        """ Test direct-to-aer parameter passing in Qobj header. """
        pass
class TestAerPauliExpectation(QiskitAquaTestCase):
    """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('qasm_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=.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=.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) * (.5**.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, .5**.5, (1 + .5**.5), 1],
                                             decimal=1)

    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)

        var_form = RealAmplitudes()
        var_form.num_qubits = 2

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

        def generate_parameters(num):
            param_bindings = {}
            for param in var_form.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.assertAlmostEqual(actual_sampled, expect_sampled, delta=.1)

        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=20000)
        qubit_op = (1 * I ^ I) + (2 * I ^ Z) + (3 * Z ^ I) + (4 * Z ^ Z) + (
            5 * X ^ X)
        var_form = RealAmplitudes(qubit_op.num_qubits)
        ansatz_circuit_op = CircuitStateFn(var_form)
        observable = PauliExpectation().convert(~StateFn(qubit_op))
        expect_op = observable.compose(ansatz_circuit_op).reduce()
        params1 = {}
        params2 = {}
        for param in var_form.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)
Ejemplo n.º 22
0
class TestMatrixExpectation(QiskitAquaTestCase):
    """Pauli Change of Basis Expectation tests."""

    def setUp(self) -> None:
        super().setUp()
        self.seed = 97
        backend = BasicAer.get_backend('statevector_simulator')
        q_instance = QuantumInstance(backend, seed_simulator=self.seed, seed_transpiler=self.seed)
        self.sampler = CircuitSampler(q_instance, attach_results=True)
        self.expect = MatrixExpectation()

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

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

    def test_pauli_expect_single(self):
        """ pauli expect single test """
        paulis = [Z, X, Y, 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()
            self.assertAlmostEqual(converted_meas.eval(), matmulmean, delta=.1)

            sampled = self.sampler.convert(converted_meas)
            self.assertAlmostEqual(sampled.eval(), matmulmean, delta=.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)
        np.testing.assert_array_almost_equal(plus_mean.eval(), [1, 0, 0, 1], decimal=1)
        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)
        np.testing.assert_array_almost_equal(minus_mean.eval(), [-1, 0, 0, 1], decimal=1)
        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)
        np.testing.assert_array_almost_equal(zero_mean.eval(), [0, 0, 1, 1], decimal=1)
        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) * (.5 ** .5)
        sum_zero_mean = (converted_meas @ sum_zero)
        np.testing.assert_array_almost_equal(sum_zero_mean.eval(), [0, 0, 1, 1], decimal=1)
        sampled_zero = self.sampler.convert(sum_zero)
        np.testing.assert_array_almost_equal((converted_meas @ sampled_zero).eval(), [0, 0, 1, 1],
                                             decimal=1)

        for i, op in enumerate(paulis_op.oplist):
            mat_op = op.to_matrix()
            np.testing.assert_array_almost_equal(zero_mean.eval()[i],
                                                 Zero.adjoint().to_matrix() @
                                                 mat_op @ Zero.to_matrix(),
                                                 decimal=1)
            np.testing.assert_array_almost_equal(plus_mean.eval()[i],
                                                 Plus.adjoint().to_matrix() @
                                                 mat_op @ Plus.to_matrix(),
                                                 decimal=1)
            np.testing.assert_array_almost_equal(minus_mean.eval()[i],
                                                 Minus.adjoint().to_matrix() @
                                                 mat_op @ Minus.to_matrix(),
                                                 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)
        np.testing.assert_array_almost_equal(converted_meas.eval(), [0, 0, 1, -1], decimal=1)

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

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

    def test_pauli_expect_op_vector_state_vector(self):
        """ pauli expect op vector state vector test """
        paulis_op = ListOp([X, Y, 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))
        np.testing.assert_array_almost_equal((converted_meas @ states_op).eval(), valids, decimal=1)

        sampled = self.sampler.convert(states_op)
        np.testing.assert_array_almost_equal((converted_meas @ 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, .5**.5, (1 + .5**.5), 1],
                                             decimal=1)
Ejemplo n.º 23
0
# %% another way of calculating expectation


# define your backend or quantum instance (where you can add settings)
backend = Aer.get_backend('qasm_simulator')
q_instance = QuantumInstance(backend, shots=1024)

# define the state to sample
measurable_expression = StateFn(op, is_measurement=True).compose(psi)

# convert to expectation value
expectation = PauliExpectation().convert(measurable_expression)

# get state sampler (you can also pass the backend directly)
sampler = CircuitSampler(q_instance).convert(expectation)

# evaluate
print('Sampled:', sampler.eval().real)

# %%

print(qc)
print('Hamiltonian of Ising model:')
print(H.print_details())

# %% Randomly sample Clifford circuits and calculate <H> for each one.
# (E.g. only change single qubit gates, not their locations in the circuit)

# import random
# import quimb.tensor as qtn
Ejemplo n.º 24
0
class VQE(VQAlgorithm, MinimumEigensolver):
    r"""The Variational Quantum Eigensolver algorithm.

    `VQE <https://arxiv.org/abs/1304.3061>`__ is a hybrid algorithm that uses a
    variational technique and interleaves quantum and classical computations in order to find
    the minimum eigenvalue of the Hamiltonian :math:`H` of a given system.

    An instance of VQE requires defining two algorithmic sub-components:
    a trial state (ansatz) from Aqua's :mod:`~qiskit.aqua.components.variational_forms`, and one
    of the classical :mod:`~qiskit.aqua.components.optimizers`. The ansatz is varied, via its set
    of parameters, by the optimizer, such that it works towards a state, as determined by the
    parameters applied to the variational form, that will result in the minimum expectation value
    being measured of the input operator (Hamiltonian).

    An optional array of parameter values, via the *initial_point*, may be provided as the
    starting point for the search of the minimum eigenvalue. This feature is particularly useful
    such as when there are reasons to believe that the solution point is close to a particular
    point.  As an example, when building the dissociation profile of a molecule,
    it is likely that using the previous computed optimal solution as the starting
    initial point for the next interatomic distance is going to reduce the number of iterations
    necessary for the variational algorithm to converge.  Aqua provides an
    `initial point tutorial <https://github.com/Qiskit/qiskit-tutorials-community/blob/master
    /chemistry/h2_vqe_initial_point.ipynb>`__ detailing this use case.

    The length of the *initial_point* list value must match the number of the parameters
    expected by the variational form being used. If the *initial_point* is left at the default
    of ``None``, then VQE will look to the variational form for a preferred value, based on its
    given initial state. If the variational form returns ``None``,
    then a random point will be generated within the parameter bounds set, as per above.
    If the variational form provides ``None`` as the lower bound, then VQE
    will default it to :math:`-2\pi`; similarly, if the variational form returns ``None``
    as the upper bound, the default value will be :math:`2\pi`.

    .. note::

        The VQE stores the parameters of ``var_form`` sorted by name to map the values
        provided by the optimizer to the circuit. This is done to ensure reproducible results,
        for example such that running the optimization twice with same random seeds yields the
        same result. Also, the ``optimal_point`` of the result object can be used as initial
        point of another VQE run by passing it as ``initial_point`` to the initializer.

    """
    def __init__(
        self,
        operator: Optional[Union[OperatorBase, LegacyBaseOperator]] = None,
        var_form: Optional[Union[QuantumCircuit, VariationalForm]] = None,
        optimizer: Optional[Optimizer] = None,
        initial_point: Optional[np.ndarray] = None,
        expectation: Optional[ExpectationBase] = None,
        include_custom: bool = False,
        max_evals_grouped: int = 1,
        aux_operators: Optional[List[Optional[Union[
            OperatorBase, LegacyBaseOperator]]]] = None,
        callback: Optional[Callable[[int, np.ndarray, float, float],
                                    None]] = None,
        quantum_instance: Optional[Union[QuantumInstance, BaseBackend,
                                         Backend]] = None
    ) -> None:
        """

        Args:
            operator: Qubit operator of the Observable
            var_form: A parameterized circuit used as Ansatz for the wave function.
            optimizer: A classical optimizer.
            initial_point: An optional initial point (i.e. initial parameter values)
                for the optimizer. If ``None`` then VQE will look to the variational form for a
                preferred point and if not will simply compute a random one.
            expectation: The Expectation converter for taking the average value of the
                Observable over the var_form state function. When ``None`` (the default) an
                :class:`~qiskit.aqua.operators.expectations.ExpectationFactory` is used to select
                an appropriate expectation based on the operator and backend. When using Aer
                qasm_simulator backend, with paulis, it is however much faster to leverage custom
                Aer function for the computation but, although VQE performs much faster
                with it, the outcome is ideal, with no shot noise, like using a state vector
                simulator. If you are just looking for the quickest performance when choosing Aer
                qasm_simulator and the lack of shot noise is not an issue then set `include_custom`
                parameter here to ``True`` (defaults to ``False``).
            include_custom: When `expectation` parameter here is None setting this to ``True`` will
                allow the factory to include the custom Aer pauli expectation.
            max_evals_grouped: Max number of evaluations performed simultaneously. Signals the
                given optimizer that more than one set of parameters can be supplied so that
                potentially the expectation values can be computed in parallel. Typically this is
                possible when a finite difference gradient is used by the optimizer such that
                multiple points to compute the gradient can be passed and if computed in parallel
                improve overall execution time.
            aux_operators: Optional list of auxiliary operators to be evaluated with the
                eigenstate of the minimum eigenvalue main result and their expectation values
                returned. For instance in chemistry these can be dipole operators, total particle
                count operators so we can get values for these at the ground state.
            callback: a callback that can access the intermediate data during the optimization.
                Four parameter values are passed to the callback as follows during each evaluation
                by the optimizer for its current set of parameters as it works towards the minimum.
                These are: the evaluation count, the optimizer parameters for the
                variational form, the evaluated mean and the evaluated standard deviation.`
            quantum_instance: Quantum Instance or Backend
        """
        validate_min('max_evals_grouped', max_evals_grouped, 1)
        if var_form is None:
            var_form = RealAmplitudes()

        if optimizer is None:
            optimizer = SLSQP()

        # set the initial point to the preferred parameters of the variational form
        if initial_point is None and hasattr(var_form,
                                             'preferred_init_points'):
            initial_point = var_form.preferred_init_points

        self._max_evals_grouped = max_evals_grouped
        self._circuit_sampler = None  # type: Optional[CircuitSampler]
        self._expectation = expectation
        self._user_valid_expectation = self._expectation is not None
        self._include_custom = include_custom
        self._expect_op = None
        self._operator = None

        super().__init__(var_form=var_form,
                         optimizer=optimizer,
                         cost_fn=self._energy_evaluation,
                         initial_point=initial_point,
                         quantum_instance=quantum_instance)
        self._ret = None  # type: Dict[str, Any]
        self._eval_time = None
        self._optimizer.set_max_evals_grouped(max_evals_grouped)
        self._callback = callback

        if operator is not None:
            self.operator = operator
        self.aux_operators = aux_operators

        self._eval_count = 0
        logger.info(self.print_settings())

    @property
    def operator(self) -> Optional[OperatorBase]:
        """ Returns operator """
        return self._operator

    @operator.setter
    def operator(self, operator: Union[OperatorBase,
                                       LegacyBaseOperator]) -> None:
        """ set operator """
        if isinstance(operator, LegacyBaseOperator):
            operator = operator.to_opflow()
        self._operator = operator
        self._expect_op = None
        self._check_operator_varform()
        # Expectation was not passed by user, try to create one
        if not self._user_valid_expectation:
            self._try_set_expectation_value_from_factory()

    def _try_set_expectation_value_from_factory(self) -> None:
        if self.operator is not None and self.quantum_instance is not None:
            self._set_expectation(
                ExpectationFactory.build(operator=self.operator,
                                         backend=self.quantum_instance,
                                         include_custom=self._include_custom))

    def _set_expectation(self, exp: ExpectationBase) -> None:
        self._expectation = exp
        self._user_valid_expectation = False
        self._expect_op = None

    @QuantumAlgorithm.quantum_instance.setter
    def quantum_instance(
        self, quantum_instance: Union[QuantumInstance, BaseBackend,
                                      Backend]) -> None:
        """ set quantum_instance """
        super(VQE,
              self.__class__).quantum_instance.__set__(self, quantum_instance)

        self._circuit_sampler = CircuitSampler(
            self._quantum_instance,
            param_qobj=is_aer_provider(self._quantum_instance.backend))

        # Expectation was not passed by user, try to create one
        if not self._user_valid_expectation:
            self._try_set_expectation_value_from_factory()

    @property
    def expectation(self) -> ExpectationBase:
        """ The expectation value algorithm used to construct the expectation measurement from
        the observable. """
        return self._expectation

    @expectation.setter
    def expectation(self, exp: ExpectationBase) -> None:
        self._set_expectation(exp)
        self._user_valid_expectation = self._expectation is not None

    @property
    def aux_operators(self) -> Optional[List[Optional[OperatorBase]]]:
        """ Returns aux operators """
        return self._aux_operators

    @aux_operators.setter
    def aux_operators(
        self, aux_operators: Optional[
            Union[OperatorBase, LegacyBaseOperator,
                  List[Optional[Union[OperatorBase, LegacyBaseOperator]]]]]
    ) -> None:
        """ Set aux operators """
        if aux_operators is None:
            aux_operators = []
        elif not isinstance(aux_operators, list):
            aux_operators = [aux_operators]

        # We need to handle the array entries being Optional i.e. having value None
        self._aux_op_nones = [op is None for op in aux_operators]
        if aux_operators:
            zero_op = I.tensorpower(self.operator.num_qubits) * 0.0
            converted = []
            for op in aux_operators:
                if op is None:
                    converted.append(zero_op)
                elif isinstance(op, LegacyBaseOperator):
                    converted.append(op.to_opflow())
                else:
                    converted.append(op)

            # For some reason Chemistry passes aux_ops with 0 qubits and paulis sometimes.
            aux_operators = [zero_op if op == 0 else op for op in converted]

        self._aux_operators = aux_operators  # type: List

    def _check_operator_varform(self):
        """Check that the number of qubits of operator and variational form match."""
        if self.operator is not None and self.var_form is not None:
            if self.operator.num_qubits != self.var_form.num_qubits:
                # try to set the number of qubits on the variational form, if possible
                try:
                    self.var_form.num_qubits = self.operator.num_qubits
                    self._var_form_params = sorted(self.var_form.parameters,
                                                   key=lambda p: p.name)
                except AttributeError as ex:
                    raise AquaError(
                        "The number of qubits of the variational form does not match "
                        "the operator, and the variational form does not allow setting "
                        "the number of qubits using `num_qubits`.") from ex

    @VQAlgorithm.optimizer.setter  # type: ignore
    def optimizer(self, optimizer: Optimizer):
        """ Sets optimizer """
        super(VQE, self.__class__).optimizer.__set__(self,
                                                     optimizer)  # type: ignore
        if optimizer is not None:
            optimizer.set_max_evals_grouped(self._max_evals_grouped)

    @property
    def setting(self):
        """Prepare the setting of VQE as a string."""
        ret = "Algorithm: {}\n".format(self.__class__.__name__)
        params = ""
        for key, value in self.__dict__.items():
            if key[0] == "_":
                if "initial_point" in key and value is None:
                    params += "-- {}: {}\n".format(key[1:], "Random seed")
                else:
                    params += "-- {}: {}\n".format(key[1:], value)
        ret += "{}".format(params)
        return ret

    def print_settings(self):
        """
        Preparing the setting of VQE into a string.

        Returns:
            str: the formatted setting of VQE
        """
        ret = "\n"
        ret += "==================== Setting of {} ============================\n".format(
            self.__class__.__name__)
        ret += "{}".format(self.setting)
        ret += "===============================================================\n"
        if hasattr(self._var_form, 'setting'):
            ret += "{}".format(self._var_form.setting)
        elif hasattr(self._var_form, 'print_settings'):
            ret += "{}".format(self._var_form.print_settings())
        elif isinstance(self._var_form, QuantumCircuit):
            ret += "var_form is a custom circuit"
        else:
            ret += "var_form has not been set"
        ret += "===============================================================\n"
        ret += "{}".format(self._optimizer.setting)
        ret += "===============================================================\n"
        return ret

    def construct_expectation(
        self, parameter: Union[List[float], List[Parameter], np.ndarray]
    ) -> OperatorBase:
        r"""
        Generate the ansatz circuit and expectation value measurement, and return their
        runnable composition.

        Args:
            parameter: Parameters for the ansatz circuit.

        Returns:
            The Operator equalling the measurement of the ansatz :class:`StateFn` by the
            Observable's expectation :class:`StateFn`.

        Raises:
            AquaError: If no operator has been provided.
        """
        if self.operator is None:
            raise AquaError("The operator was never provided.")

        # ensure operator and varform are compatible
        self._check_operator_varform()

        if isinstance(self.var_form, QuantumCircuit):
            param_dict = dict(zip(self._var_form_params,
                                  parameter))  # type: Dict
            wave_function = self.var_form.assign_parameters(param_dict)
        else:
            wave_function = self.var_form.construct_circuit(parameter)

        # Expectation was never created, try to create one
        if self._expectation is None:
            self._try_set_expectation_value_from_factory()

        # If setting the expectation failed, raise an Error:
        if self._expectation is None:
            raise AquaError(
                'No expectation set and could not automatically set one, please '
                'try explicitly setting an expectation or specify a backend so it '
                'can be chosen automatically.')

        observable_meas = self.expectation.convert(
            StateFn(self.operator, is_measurement=True))
        ansatz_circuit_op = CircuitStateFn(wave_function)
        return observable_meas.compose(ansatz_circuit_op).reduce()

    def construct_circuit(
        self, parameter: Union[List[float], List[Parameter], np.ndarray]
    ) -> List[QuantumCircuit]:
        """Return the circuits used to compute the expectation value.

        Args:
            parameter: Parameters for the ansatz circuit.

        Returns:
            A list of the circuits used to compute the expectation value.
        """
        expect_op = self.construct_expectation(parameter).to_circuit_op()

        circuits = []

        # recursively extract circuits
        def extract_circuits(op):
            if isinstance(op, CircuitStateFn):
                circuits.append(op.primitive)
            elif isinstance(op, ListOp):
                for op_i in op.oplist:
                    extract_circuits(op_i)

        extract_circuits(expect_op)

        return circuits

    @classmethod
    def supports_aux_operators(cls) -> bool:
        return True

    def _run(self) -> 'VQEResult':
        """Run the algorithm to compute the minimum eigenvalue.

        Returns:
            The result of the VQE algorithm as ``VQEResult``.

        Raises:
            AquaError: Wrong setting of operator and backend.
        """
        if self.operator is None:
            raise AquaError("The operator was never provided.")

        self._check_operator_varform()

        self._quantum_instance.circuit_summary = True

        self._eval_count = 0
        vqresult = self.find_minimum(initial_point=self.initial_point,
                                     var_form=self.var_form,
                                     cost_fn=self._energy_evaluation,
                                     optimizer=self.optimizer)

        # TODO remove all former dictionary logic
        self._ret = {}
        self._ret['num_optimizer_evals'] = vqresult.optimizer_evals
        self._ret['min_val'] = vqresult.optimal_value
        self._ret['opt_params'] = vqresult.optimal_point
        self._ret['eval_time'] = vqresult.optimizer_time
        self._ret['opt_params_dict'] = vqresult.optimal_parameters

        if self._ret['num_optimizer_evals'] is not None and \
                self._eval_count >= self._ret['num_optimizer_evals']:
            self._eval_count = self._ret['num_optimizer_evals']
        self._eval_time = self._ret['eval_time']
        logger.info(
            'Optimization complete in %s seconds.\nFound opt_params %s in %s evals',
            self._eval_time, self._ret['opt_params'], self._eval_count)
        self._ret['eval_count'] = self._eval_count

        result = VQEResult()
        result.combine(vqresult)
        result.eigenvalue = vqresult.optimal_value + 0j
        result.eigenstate = self.get_optimal_vector()

        self._ret['energy'] = self.get_optimal_cost()
        self._ret['eigvals'] = np.asarray([self._ret['energy']])
        self._ret['eigvecs'] = np.asarray([result.eigenstate])

        if len(self.aux_operators) > 0:
            self._eval_aux_ops()
            # TODO remove when ._ret is deprecated
            result.aux_operator_eigenvalues = self._ret['aux_ops'][0]

        result.cost_function_evals = self._eval_count

        return result

    def _eval_aux_ops(self, threshold=1e-12):
        # Create new CircuitSampler to avoid breaking existing one's caches.
        sampler = CircuitSampler(self.quantum_instance)

        aux_op_meas = self.expectation.convert(
            StateFn(ListOp(self.aux_operators), is_measurement=True))
        aux_op_expect = aux_op_meas.compose(
            CircuitStateFn(self.get_optimal_circuit()))
        values = np.real(sampler.convert(aux_op_expect).eval())

        # Discard values below threshold
        aux_op_results = (values * (np.abs(values) > threshold))
        # Deal with the aux_op behavior where there can be Nones or Zero qubit Paulis in the list
        self._ret['aux_ops'] = [
            None if is_none else [result]
            for (is_none, result) in zip(self._aux_op_nones, aux_op_results)
        ]
        # As this has mixed types, since it can included None, it needs to explicitly pass object
        # data type to avoid numpy 1.19 warning message about implicit conversion being deprecated
        self._ret['aux_ops'] = np.array([self._ret['aux_ops']], dtype=object)

    def compute_minimum_eigenvalue(
        self,
        operator: Optional[Union[OperatorBase, LegacyBaseOperator]] = None,
        aux_operators: Optional[List[Optional[Union[
            OperatorBase, LegacyBaseOperator]]]] = None
    ) -> MinimumEigensolverResult:
        super().compute_minimum_eigenvalue(operator, aux_operators)
        return self._run()

    def _energy_evaluation(
        self, parameters: Union[List[float],
                                np.ndarray]) -> Union[float, List[float]]:
        """Evaluate energy at given parameters for the variational form.

        This is the objective function to be passed to the optimizer that is used for evaluation.

        Args:
            parameters: The parameters for the variational form.

        Returns:
            Energy of the hamiltonian of each parameter.


        Raises:
            RuntimeError: If the variational form has no parameters.
        """
        if not self._expect_op:
            self._expect_op = self.construct_expectation(self._var_form_params)

        num_parameters = self.var_form.num_parameters
        if self._var_form.num_parameters == 0:
            raise RuntimeError('The var_form cannot have 0 parameters.')

        parameter_sets = np.reshape(parameters, (-1, num_parameters))
        # Create dict associating each parameter with the lists of parameterization values for it
        param_bindings = dict(
            zip(self._var_form_params,
                parameter_sets.transpose().tolist()))  # type: Dict

        start_time = time()
        sampled_expect_op = self._circuit_sampler.convert(
            self._expect_op, params=param_bindings)
        means = np.real(sampled_expect_op.eval())

        if self._callback is not None:
            variance = np.real(
                self._expectation.compute_variance(sampled_expect_op))
            estimator_error = np.sqrt(variance /
                                      self.quantum_instance.run_config.shots)
            for i, param_set in enumerate(parameter_sets):
                self._eval_count += 1
                self._callback(self._eval_count, param_set, means[i],
                               estimator_error[i])
        else:
            self._eval_count += len(means)

        end_time = time()
        logger.info(
            'Energy evaluation returned %s - %.5f (ms), eval count: %s', means,
            (end_time - start_time) * 1000, self._eval_count)

        return means if len(means) > 1 else means[0]

    def get_optimal_cost(self) -> float:
        """Get the minimal cost or energy found by the VQE."""
        if 'opt_params' not in self._ret:
            raise AquaError("Cannot return optimal cost before running the "
                            "algorithm to find optimal params.")
        return self._ret['min_val']

    def get_optimal_circuit(self) -> QuantumCircuit:
        """Get the circuit with the optimal parameters."""
        if 'opt_params' not in self._ret:
            raise AquaError("Cannot find optimal circuit before running the "
                            "algorithm to find optimal params.")
        if isinstance(self.var_form, VariationalForm):
            return self._var_form.construct_circuit(self._ret['opt_params'])
        return self.var_form.assign_parameters(self._ret['opt_params_dict'])

    def get_optimal_vector(self) -> Union[List[float], Dict[str, int]]:
        """Get the simulation outcome of the optimal circuit. """
        # pylint: disable=import-outside-toplevel
        from qiskit.aqua.utils.run_circuits import find_regs_by_name

        if 'opt_params' not in self._ret:
            raise AquaError("Cannot find optimal vector before running the "
                            "algorithm to find optimal params.")
        qc = self.get_optimal_circuit()
        if self._quantum_instance.is_statevector:
            ret = self._quantum_instance.execute(qc)
            self._ret['min_vector'] = ret.get_statevector(qc)
        else:
            c = ClassicalRegister(qc.width(), name='c')
            q = find_regs_by_name(qc, 'q')
            qc.add_register(c)
            qc.barrier(q)
            qc.measure(q, c)
            ret = self._quantum_instance.execute(qc)
            self._ret['min_vector'] = ret.get_counts(qc)
        return self._ret['min_vector']

    @property
    def optimal_params(self) -> List[float]:
        """The optimal parameters for the variational form."""
        if 'opt_params' not in self._ret:
            raise AquaError(
                "Cannot find optimal params before running the algorithm.")
        return self._ret['opt_params']
    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)

        var_form = RealAmplitudes()
        var_form.num_qubits = 2

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

        def generate_parameters(num):
            param_bindings = {}
            for param in var_form.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.assertAlmostEqual(actual_sampled, expect_sampled, delta=.1)

        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)