示例#1
0
    def test_parameter_binding_on_listop(self):
        """Test passing a ListOp with differing parameters works with the circuit sampler."""
        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
        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))
示例#2
0
    def test_adjoint_nonunitary_circuit_raises(self):
        """Test adjoint on a non-unitary circuit raises a OpflowError instead of CircuitError."""
        circuit = QuantumCircuit(1)
        circuit.reset(0)

        with self.assertRaises(OpflowError):
            _ = StateFn(circuit).adjoint()
示例#3
0
    def _eval_aux_ops(
        self,
        parameters: np.ndarray,
        aux_operators: List[OperatorBase],
        expectation: ExpectationBase,
        threshold: float = 1e-12,
    ) -> np.ndarray:
        # Create new CircuitSampler to avoid breaking existing one's caches.
        sampler = CircuitSampler(self.quantum_instance)

        aux_op_meas = expectation.convert(
            StateFn(ListOp(aux_operators), is_measurement=True))
        aux_op_expect = aux_op_meas.compose(
            CircuitStateFn(self.ansatz.bind_parameters(parameters)))
        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
        _aux_op_nones = [op is None for op in aux_operators]
        aux_operator_eigenvalues = [
            None if is_none else [result]
            for (is_none, result) in zip(_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
        aux_operator_eigenvalues = np.array([aux_operator_eigenvalues],
                                            dtype=object)
        return aux_operator_eigenvalues
示例#4
0
    def test_state_gradient4(self, method):
        """Test the state gradient 4
         Tr(|psi><psi|ZX) = -cos(a)
         daTr(|psi><psi|ZX) = sin(a)
        """

        ham = X ^ Z
        a = Parameter('a')
        params = a

        q = QuantumRegister(2)
        qc = QuantumCircuit(q)
        qc.x(q[0])
        qc.h(q[1])
        qc.crz(a, q[0], q[1])
        op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.)

        state_grad = Gradient(grad_method=method).convert(operator=op,
                                                          params=params)
        values_dict = [{a: np.pi / 4}, {a: 0}, {a: np.pi / 2}]
        correct_values = [1 / np.sqrt(2), 0, 1]

        for i, value_dict in enumerate(values_dict):
            np.testing.assert_array_almost_equal(
                state_grad.assign_parameters(value_dict).eval(),
                correct_values[i],
                decimal=1)
    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)
        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)
    def evaluate_operators(
        self,
        state: Union[str, dict, Result, list, np.ndarray, Statevector,
                     QuantumCircuit, Instruction, OperatorBase, ],
        operators: Union[PauliSumOp, OperatorBase, list, dict],
    ) -> Union[Optional[float], List[Optional[float]], Dict[
            str, List[Optional[float]]]]:
        """Evaluates additional operators at the given state.

        Args:
            state: any kind of input that can be used to specify a state. See also ``StateFn`` for
                   more details.
            operators: either a single, list or dictionary of ``PauliSumOp``s or any kind
                       of operator implementing the ``OperatorBase``.

        Returns:
            The expectation value of the given operator(s). The return type will be identical to the
            format of the provided operators.
        """
        if isinstance(self._solver, MinimumEigensolverFactory):
            # try to get a QuantumInstance from the solver
            quantum_instance = getattr(self._solver.minimum_eigensolver,
                                       "quantum_instance", None)
            # and try to get an Expectation from the solver
            expectation = getattr(self._solver.minimum_eigensolver,
                                  "expectation", None)
        else:
            quantum_instance = getattr(self._solver, "quantum_instance", None)
            expectation = getattr(self._solver, "expectation", None)

        if not isinstance(state, StateFn):
            state = StateFn(state)

        # handle all possible formats of operators
        # i.e. if a user gives us a dict of operators, we return the results equivalently, etc.
        if isinstance(operators, list):
            results = []  # type: ignore
            for op in operators:
                if op is None:
                    results.append(None)
                else:
                    results.append(
                        self._eval_op(state, op, quantum_instance,
                                      expectation))
        elif isinstance(operators, dict):
            results = {}  # type: ignore
            for name, op in operators.items():
                if op is None:
                    results[name] = None
                else:
                    results[name] = self._eval_op(state, op, quantum_instance,
                                                  expectation)
        else:
            if operators is None:
                results = None
            else:
                results = self._eval_op(state, operators, quantum_instance,
                                        expectation)

        return results
示例#7
0
    def test_operator_coefficient_gradient(self, method):
        """Test the operator coefficient gradient

        Tr( | psi > < psi | Z) = sin(a)sin(b)
        Tr( | psi > < psi | X) = cos(a)
        """
        a = Parameter("a")
        b = Parameter("b")
        q = QuantumRegister(1)
        qc = QuantumCircuit(q)
        qc.h(q)
        qc.rz(a, q[0])
        qc.rx(b, q[0])

        coeff_0 = Parameter("c_0")
        coeff_1 = Parameter("c_1")
        ham = coeff_0 * X + coeff_1 * Z
        op = StateFn(ham, is_measurement=True) @ CircuitStateFn(primitive=qc, coeff=1.0)
        gradient_coeffs = [coeff_0, coeff_1]
        coeff_grad = Gradient(grad_method=method).convert(op, gradient_coeffs)
        values_dict = [
            {coeff_0: 0.5, coeff_1: -1, a: np.pi / 4, b: np.pi},
            {coeff_0: 0.5, coeff_1: -1, a: np.pi / 4, b: np.pi / 4},
        ]
        correct_values = [[1 / np.sqrt(2), 0], [1 / np.sqrt(2), 1 / 2]]
        for i, value_dict in enumerate(values_dict):
            np.testing.assert_array_almost_equal(
                coeff_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=1
            )
示例#8
0
    def test_grad_combo_fn_chain_rule_nat_grad(self):
        """Test the chain rule for a custom gradient combo function."""
        np.random.seed(2)

        def combo_fn(x):
            amplitudes = x[0].primitive.data
            pdf = np.multiply(amplitudes, np.conj(amplitudes))
            return np.sum(np.log(pdf)) / (-len(amplitudes))

        def grad_combo_fn(x):
            amplitudes = x[0].primitive.data
            pdf = np.multiply(amplitudes, np.conj(amplitudes))
            grad = []
            for prob in pdf:
                grad += [-1 / prob]
            return grad

        try:
            qc = RealAmplitudes(2, reps=1)
            grad_op = ListOp([StateFn(qc)], combo_fn=combo_fn, grad_combo_fn=grad_combo_fn)
            grad = NaturalGradient(grad_method="lin_comb", regularization="ridge").convert(
                grad_op, qc.ordered_parameters
            )
            value_dict = dict(
                zip(qc.ordered_parameters, np.random.rand(len(qc.ordered_parameters)))
            )
            correct_values = [[0.20777236], [-18.92560338], [-15.89005475], [-10.44002031]]
            np.testing.assert_array_almost_equal(
                grad.assign_parameters(value_dict).eval(), correct_values, decimal=3
            )
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
示例#9
0
    def test_natural_gradient(self, method, regularization):
        """Test the natural gradient"""
        try:
            for params in (ParameterVector("a", 2), [Parameter("a"), Parameter("b")]):
                ham = 0.5 * X - 1 * Z

                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.0)
                nat_grad = NaturalGradient(
                    grad_method=method, regularization=regularization
                ).convert(operator=op)
                values_dict = [{params[0]: np.pi / 4, params[1]: np.pi / 2}]

                # reference values obtained by classically computing the natural gradients
                correct_values = [[-3.26, 1.63]] if regularization == "ridge" else [[-4.24, 0]]

                for i, value_dict in enumerate(values_dict):
                    np.testing.assert_array_almost_equal(
                        nat_grad.assign_parameters(value_dict).eval(), correct_values[i], decimal=1
                    )
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
    def _eval_op(self, state, op, quantum_instance, expectation):
        # 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.0j]

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

        if quantum_instance is not None:
            try:
                sampler = CircuitSampler(quantum_instance)
                if expectation is not None:
                    exp = expectation.convert(exp)
                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]
示例#11
0
    def test_state_gradient3(self, method):
        """Test the state gradient 3

        Tr(|psi><psi|Z) = sin(a)sin(c(a)) = sin(a)sin(cos(a)+1)
        Tr(|psi><psi|X) = cos(a)
        d<H>/da = - 0.5 sin(a) - 1 cos(a)sin(cos(a)+1) + 1 sin^2(a)cos(cos(a)+1)
        """
        ham = 0.5 * X - 1 * Z
        a = Parameter('a')
        # b = Parameter('b')
        params = a
        x = Symbol('x')
        expr = cos(x) + 1
        c = ParameterExpression({a: x}, expr)

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

        state_grad = Gradient(grad_method=method).convert(operator=op,
                                                          params=params)
        values_dict = [{a: np.pi / 4}, {a: 0}, {a: np.pi / 2}]
        correct_values = [-1.1220, -0.9093, 0.0403]
        for i, value_dict in enumerate(values_dict):
            np.testing.assert_array_almost_equal(
                state_grad.assign_parameters(value_dict).eval(),
                correct_values[i],
                decimal=1)
示例#12
0
    def test_natural_gradient(self, method, regularization):
        """Test the natural gradient"""
        try:
            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.)
            nat_grad = NaturalGradient(grad_method=method,
                                       regularization=regularization).convert(
                                           operator=op, params=params)
            values_dict = [{params[0]: np.pi / 4, params[1]: np.pi / 2}]
            correct_values = [[-2.36003979, 2.06503481]] \
                if regularization == 'ridge' else [[-4.2, 0]]
            for i, value_dict in enumerate(values_dict):
                np.testing.assert_array_almost_equal(
                    nat_grad.assign_parameters(value_dict).eval(),
                    correct_values[i],
                    decimal=0)
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
示例#13
0
    def test_grad_combo_fn_chain_rule(self, method):
        """
        Test the chain rule for a custom gradient combo function

        """
        np.random.seed(2)

        def combo_fn(x):
            amplitudes = x[0].primitive.data
            pdf = np.multiply(amplitudes, np.conj(amplitudes))
            return np.sum(np.log(pdf)) / (-len(amplitudes))

        def grad_combo_fn(x):
            amplitudes = x[0].primitive.data
            pdf = np.multiply(amplitudes, np.conj(amplitudes))
            grad = []
            for prob in pdf:
                grad += [-1 / prob]
            return grad

        qc = RealAmplitudes(2, reps=1)
        grad_op = ListOp([StateFn(qc)],
                         combo_fn=combo_fn,
                         grad_combo_fn=grad_combo_fn)
        grad = Gradient(grad_method=method).convert(grad_op,
                                                    qc.ordered_parameters)
        value_dict = dict(
            zip(qc.ordered_parameters,
                np.random.rand(len(qc.ordered_parameters))))
        correct_values = [[(-0.16666259133549044 + 0j)],
                          [(-7.244949702732864 + 0j)],
                          [(-2.979791752749964 + 0j)],
                          [(-5.310186078432614 + 0j)]]
        np.testing.assert_array_almost_equal(
            grad.assign_parameters(value_dict).eval(), correct_values)
示例#14
0
 def test_list_pauli_sum_op(self):
     """Test PauliExpectation for List[PauliSumOp]"""
     test_op = ListOp([~StateFn(PauliSumOp.from_list([("XX", 1), ("ZI", 3), ("ZZ", 5)]))])
     observable = self.expect.convert(test_op)
     self.assertIsInstance(observable, ListOp)
     self.assertIsInstance(observable[0][0][0].primitive, PauliSumOp)
     self.assertIsInstance(observable[0][1][0].primitive, PauliSumOp)
示例#15
0
    def test_natural_gradient4(self, grad_method, qfi_method, regularization):
        """Test the natural gradient 4"""

        # Avoid regularization = lasso intentionally because it does not converge
        try:
            ham = 0.5 * X - 1 * Z
            a = Parameter('a')
            params = a

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

            op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.)
            nat_grad = NaturalGradient(grad_method=grad_method,
                                       qfi_method=qfi_method,
                                       regularization=regularization).convert(
                                           operator=op, params=params)
            values_dict = [{a: np.pi / 4}]
            correct_values = [[0.]] if regularization == 'ridge' else [[
                -1.41421342
            ]]
            for i, value_dict in enumerate(values_dict):
                np.testing.assert_array_almost_equal(
                    nat_grad.assign_parameters(value_dict).eval(),
                    correct_values[i],
                    decimal=0)
        except MissingOptionalLibraryError as ex:
            self.skipTest(str(ex))
示例#16
0
    def test_gradient_p(self, method):
        """Test the state gradient for p
        |psi> = 1/sqrt(2)[[1, exp(ia)]]
        Tr(|psi><psi|Z) = 0
        Tr(|psi><psi|X) = cos(a)
        d<H>/da = - 0.5 sin(a)
        """
        ham = 0.5 * X - 1 * Z
        a = Parameter('a')
        params = a

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

        state_grad = Gradient(grad_method=method).convert(operator=op,
                                                          params=params)
        values_dict = [{a: np.pi / 4}, {a: 0}, {a: np.pi / 2}]
        correct_values = [-0.5 / np.sqrt(2), 0, -0.5]

        for i, value_dict in enumerate(values_dict):
            np.testing.assert_array_almost_equal(
                state_grad.assign_parameters(value_dict).eval(),
                correct_values[i],
                decimal=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)
示例#18
0
    def test_state_gradient2(self, method):
        """Test the state gradient 2

        Tr(|psi><psi|Z) = sin(a)sin(a)
        Tr(|psi><psi|X) = cos(a)
        d<H>/da = - 0.5 sin(a) - 2 cos(a)sin(a)
        """
        ham = 0.5 * X - 1 * Z
        a = Parameter('a')
        # b = Parameter('b')
        params = [a]

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

        state_grad = Gradient(grad_method=method).convert(operator=op,
                                                          params=params)
        values_dict = [{a: np.pi / 4}, {a: 0}, {a: np.pi / 2}]
        correct_values = [-1.353553, -0, -0.5]

        for i, value_dict in enumerate(values_dict):
            np.testing.assert_array_almost_equal(
                state_grad.assign_parameters(value_dict).eval(),
                correct_values[i],
                decimal=1)
    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.0)

        shots = 8000
        if method == "fin_diff":
            np.random.seed(8)
            state_grad = Gradient(grad_method=method,
                                  epsilon=shots**(-1 /
                                                  6.0)).convert(operator=op)
        else:
            state_grad = Gradient(grad_method=method).convert(operator=op)
        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],
            [-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)
示例#20
0
 def test_add_direct(self):
     """add direct test"""
     wf = StateFn({"101010": 0.5, "111111": 0.3}) + (Zero ^ 6)
     self.assertEqual(wf.primitive, {
         "101010": 0.5,
         "111111": 0.3,
         "000000": 1.0
     })
     wf = (4 * StateFn({
         "101010": 0.5,
         "111111": 0.3
     })) + ((3 + 0.1j) * (Zero ^ 6))
     self.assertEqual(wf.primitive, {
         "000000": (3 + 0.1j),
         "101010": (2 + 0j),
         "111111": (1.2 + 0j)
     })
 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)
示例#22
0
 def test_add_direct(self):
     """ add direct test """
     wf = StateFn({'101010': .5, '111111': .3}) + (Zero ^ 6)
     self.assertEqual(wf.primitive, {
         '101010': 0.5,
         '111111': 0.3,
         '000000': 1.0
     })
     wf = (4 * StateFn({
         '101010': .5,
         '111111': .3
     })) + ((3 + .1j) * (Zero ^ 6))
     self.assertEqual(wf.primitive, {
         '000000': (3 + 0.1j),
         '101010': (2 + 0j),
         '111111': (1.2 + 0j)
     })
示例#23
0
    def test_pauli_two_design(self, method):
        """Test SPSA on the Pauli two-design example."""
        circuit = PauliTwoDesign(3, reps=1, seed=1)
        parameters = list(circuit.parameters)
        obs = Z ^ Z ^ I
        expr = ~StateFn(obs) @ StateFn(circuit)

        initial_point = np.array([
            0.82311034, 0.02611798, 0.21077064, 0.61842177, 0.09828447,
            0.62013131
        ])

        def objective(x):
            return expr.bind_parameters(dict(zip(parameters, x))).eval().real

        settings = {"maxiter": 100, "blocking": True, "allowed_increase": 0}

        if method == "2spsa":
            settings["second_order"] = True
            settings["regularization"] = 0.01
            expected_nfev = settings["maxiter"] * 5 + 1
        elif method == "qnspsa":
            settings["fidelity"] = QNSPSA.get_fidelity(circuit)
            settings["regularization"] = 0.001
            settings["learning_rate"] = 0.05
            settings["perturbation"] = 0.05

            expected_nfev = settings["maxiter"] * 7 + 1
        else:
            expected_nfev = settings["maxiter"] * 3 + 1

        if method == "qnspsa":
            spsa = QNSPSA(**settings)
        else:
            spsa = SPSA(**settings)

        with self.assertWarns(DeprecationWarning):
            result = spsa.optimize(circuit.num_parameters,
                                   objective,
                                   initial_point=initial_point)

        with self.subTest("check final accuracy"):
            self.assertLess(result[1], -0.95)  # final loss

        with self.subTest("check number of function calls"):
            self.assertEqual(result[2], expected_nfev)  # function evaluations
示例#24
0
    def test_opflow_qnn_2_2(self, q_i):
        """ Test Opflow QNN with input/output dimension 2/2."""

        if q_i == 'sv':
            quantum_instance = self.sv_quantum_instance
        else:
            quantum_instance = self.qasm_quantum_instance

        # construct parametrized circuit
        params_1 = [Parameter('input1'), Parameter('weight1')]
        qc_1 = QuantumCircuit(1)
        qc_1.h(0)
        qc_1.ry(params_1[0], 0)
        qc_1.rx(params_1[1], 0)
        qc_sfn_1 = StateFn(qc_1)

        # construct cost operator
        h_1 = StateFn(PauliSumOp.from_list([('Z', 1.0), ('X', 1.0)]))

        # combine operator and circuit to objective function
        op_1 = ~h_1 @ qc_sfn_1

        # construct parametrized circuit
        params_2 = [Parameter('input2'), Parameter('weight2')]
        qc_2 = QuantumCircuit(1)
        qc_2.h(0)
        qc_2.ry(params_2[0], 0)
        qc_2.rx(params_2[1], 0)
        qc_sfn_2 = StateFn(qc_2)

        # construct cost operator
        h_2 = StateFn(PauliSumOp.from_list([('Z', 1.0), ('X', 1.0)]))

        # combine operator and circuit to objective function
        op_2 = ~h_2 @ qc_sfn_2

        op = ListOp([op_1, op_2])

        qnn = OpflowQNN(op, [params_1[0], params_2[0]],
                        [params_1[1], params_2[1]],
                        quantum_instance=quantum_instance)

        test_data = [np.array([1, 2]), np.array([[1, 2], [3, 4]])]

        # test model
        self.validate_output_shape(qnn, test_data)
    def test_overlap_qfi_raises_on_unsupported_gate(self):
        """Test the overlap QFI raises an appropriate error on multi-param unbound gates."""
        x = Parameter("x")
        circuit = QuantumCircuit(1)
        circuit.p(x, 0)

        with self.assertRaises(NotImplementedError):
            _ = QFI("overlap_diag").convert(StateFn(circuit), [x])
    def test_overlap_qfi_raises_on_multiparam(self):
        """Test the overlap QFI raises an appropriate error on multi-param unbound gates."""
        x = ParameterVector("x", 2)
        circuit = QuantumCircuit(1)
        circuit.u(x[0], x[1], 2, 0)

        with self.assertRaises(NotImplementedError):
            _ = QFI("overlap_diag").convert(StateFn(circuit), [x])
示例#27
0
    def construct_total_circuit_local(self, time_step):
        ## This function creates the circuit that will be used to evaluate overlap and its gradient, in a local fashion

        # First, create the Trotter step

        step_h = time_step * self.hamiltonian
        trotter = PauliTrotterEvolution(reps=1)
        U_dt = trotter.convert(step_h.exp_i()).to_circuit()

        l_circ = self.ansatz.assign_parameters({self.params_vec: self.left})
        r_circ = self.ansatz.assign_parameters({self.params_vec: self.right})

        ## Projector
        zero_prj = StateFn(projector_zero_local(self.hamiltonian.num_qubits),
                           is_measurement=True)
        state_wfn = zero_prj @ StateFn(r_circ + U_dt + l_circ.inverse())

        return state_wfn
示例#28
0
    def test_circuit_state_fn_from_dict_initialize(self):
        """state fn circuit from dict initialize test"""
        statedict = {"101": 0.5, "100": 0.1, "000": 0.2, "111": 0.5}
        sfc = CircuitStateFn.from_dict(statedict)
        self.assertIsInstance(sfc, CircuitStateFn)
        samples = sfc.sample()
        np.testing.assert_array_almost_equal(
            StateFn(statedict).to_matrix(),
            np.round(sfc.to_matrix(), decimals=1))
        for k, v in samples.items():
            self.assertIn(k, statedict)
            # It's ok if these are far apart because the dict is sampled.
            self.assertAlmostEqual(v, np.abs(statedict[k])**0.5, delta=0.5)

        # Follows same code path as above, but testing to be thorough
        sfc_vector = CircuitStateFn.from_vector(StateFn(statedict).to_matrix())
        np.testing.assert_array_almost_equal(
            StateFn(statedict).to_matrix(), sfc_vector.to_matrix())
示例#29
0
    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) * (0.5**0.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,
            )
示例#30
0
 def test_sampling(self):
     """state fn circuit from dict initialize test"""
     statedict = {
         "101": 0.5 + 1.0j,
         "100": 0.1 + 2.0j,
         "000": 0.2 + 0.0j,
         "111": 0.5 + 1.0j
     }
     sfc = CircuitStateFn.from_dict(statedict)
     circ_samples = sfc.sample()
     dict_samples = StateFn(statedict).sample()
     vec_samples = StateFn(statedict).to_matrix_op().sample()
     for k, v in circ_samples.items():
         self.assertIn(k, dict_samples)
         self.assertIn(k, vec_samples)
         # It's ok if these are far apart because the dict is sampled.
         self.assertAlmostEqual(v, np.abs(dict_samples[k])**0.5, delta=0.5)
         self.assertAlmostEqual(v, np.abs(vec_samples[k])**0.5, delta=0.5)