Ejemplo n.º 1
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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
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
        c = np.cos(a) + 1
        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)
Ejemplo n.º 4
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) @ 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)
Ejemplo n.º 5
0
    def test_prob_grad(self, method):
        """Test the probability gradient

        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.)

        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]]]
        for i, value_dict in enumerate(values_dict):
            for j, prob_grad_result in enumerate(prob_grad.assign_parameters(value_dict).eval()):
                np.testing.assert_array_almost_equal(prob_grad_result,
                                                     correct_values[i][j], decimal=1)
Ejemplo n.º 6
0
    def test_state_gradient5(self, method):
        """Test the state gradient

        Tr(|psi><psi|Z) = sin(a0)sin(a1)
        Tr(|psi><psi|X) = cos(a0)
        d<H>/da0 = - 0.5 sin(a0) - 1 cos(a0)sin(a1)
        d<H>/da1 = - 1 sin(a0)cos(a1)
        """

        ham = 0.5 * X - 1 * Z
        a = ParameterVector('a', 2)
        params = a

        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.)

        state_grad = Gradient(grad_method=method).convert(operator=op, params=params)
        values_dict = [{a: [np.pi / 4, np.pi]}, {a: [np.pi / 4, np.pi / 4]},
                       {a: [np.pi / 2, 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)]]

        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)
Ejemplo n.º 7
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)
Ejemplo n.º 8
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.º 9
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.º 10
0
    def test_jax_chain_rule(self, method: str, autograd: bool):
        """Test the chain rule functionality using Jax

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

        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])

        def combo_fn(x):
            return jnp.power(x[0], 2) + jnp.cos(x[1])

        def grad_combo_fn(x):
            return np.array([2 * x[0], -np.sin(x[1])])

        op = ListOp([
            ~StateFn(X) @ CircuitStateFn(primitive=qc, coeff=1.),
            ~StateFn(Z) @ CircuitStateFn(primitive=qc, coeff=1.)
        ],
                    combo_fn=combo_fn,
                    grad_combo_fn=None if autograd else grad_combo_fn)

        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 = [[-1., 0.], [-1.2397, -0.2397], [0, -0.45936]]
        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)
Ejemplo n.º 11
0
    def test_vqe(self):
        """Test VQE with gradients"""
        method = 'lin_comb'
        backend = 'qasm_simulator'
        q_instance = QuantumInstance(BasicAer.get_backend(backend), seed_simulator=79,
                                     seed_transpiler=2)
        # Define the Hamiltonian
        h2_hamiltonian = -1.05 * (I ^ I) + 0.39 * (I ^ Z) - 0.39 * (Z ^ I) \
                         - 0.01 * (Z ^ Z) + 0.18 * (X ^ X)
        h2_energy = -1.85727503

        # Define the Ansatz
        wavefunction = QuantumCircuit(2)
        params = ParameterVector('theta', length=8)
        itr = iter(params)
        wavefunction.ry(next(itr), 0)
        wavefunction.ry(next(itr), 1)
        wavefunction.rz(next(itr), 0)
        wavefunction.rz(next(itr), 1)
        wavefunction.cx(0, 1)
        wavefunction.ry(next(itr), 0)
        wavefunction.ry(next(itr), 1)
        wavefunction.rz(next(itr), 0)
        wavefunction.rz(next(itr), 1)

        # Conjugate Gradient algorithm
        optimizer = CG(maxiter=10)

        grad = Gradient(grad_method=method)

        # Gradient callable
        vqe = VQE(h2_hamiltonian, wavefunction, optimizer=optimizer, gradient=grad)

        result = vqe.run(q_instance)
        np.testing.assert_almost_equal(result['optimal_value'], h2_energy, decimal=0)
Ejemplo n.º 12
0
    def test_gradient_ryy(self, method):
        # pylint: disable=wrong-spelling-in-comment
        """Test the state gradient for YY rotation
        """
        ham = Y ^ Y
        a = Parameter('a')

        q = QuantumRegister(2)
        qc = QuantumCircuit(q)
        qc.ryy(a, q[0], q[1])

        op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.)
        state_grad = Gradient(grad_method=method).convert(operator=op, params=a)
        values_dict = [{a: np.pi / 8}, {a: np.pi}]
        correct_values = [[0], [0]]
        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)
Ejemplo n.º 13
0
 def test_qgan_training_analytic_gradients(self):
     """Test QGAN training with analytic gradients"""
     self.qgan.set_generator(self.generator_circuit)
     numeric_results = self.qgan.run(self.qi_qasm)
     self.qgan.set_generator(self.generator_circuit,
                             generator_gradient=Gradient('param_shift'))
     analytic_results = self.qgan.run(self.qi_qasm)
     self.assertAlmostEqual(numeric_results['rel_entr'],
                            analytic_results['rel_entr'], delta=0.1)
Ejemplo n.º 14
0
    def test_gradient_rzx(self, method):
        """Test the state gradient for ZX rotation
        """
        ham = Z ^ Z
        a = Parameter('a')

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

        op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.)
        params = [a]
        state_grad = Gradient(grad_method=method).convert(operator=op, params=params)
        values_dict = [{a: np.pi / 8}, {a: np.pi / 2}]
        correct_values = [[0.], [0.]]
        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)
Ejemplo n.º 15
0
    def test_gradient_wrapper(self, backend):
        """Test the gradient wrapper for probability gradients
        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
        """
        method = 'param_shift'
        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
        backend = BasicAer.get_backend(backend)
        q_instance = QuantumInstance(backend=backend, shots=shots)
        if method == 'fin_diff':
            np.random.seed(8)
            prob_grad = Gradient(grad_method=method,
                                 epsilon=shots**(-1 / 6.)).gradient_wrapper(
                                     operator=op,
                                     bind_params=params,
                                     backend=q_instance)
        else:
            prob_grad = Gradient(grad_method=method).gradient_wrapper(
                operator=op, bind_params=params, backend=q_instance)
        values = [[np.pi / 4, 0], [np.pi / 4, np.pi / 4], [np.pi / 2, 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]]]
        for i, value in enumerate(values):
            result = prob_grad(value)
            np.testing.assert_array_almost_equal(result,
                                                 correct_values[i],
                                                 decimal=1)
Ejemplo n.º 16
0
    def test_grad(self):
        """Test taking the gradient of parameter expressions."""
        x, y = Parameter('x'), Parameter('y')
        with self.subTest('linear'):
            expr = 2 * x + y

            grad = Gradient.parameter_expression_grad(expr, x)
            self.assertEqual(grad, 2)

            grad = Gradient.parameter_expression_grad(expr, y)
            self.assertEqual(grad, 1)

        with self.subTest('polynomial'):
            expr = x * x * x - x * y + y * y

            grad = Gradient.parameter_expression_grad(expr, x)
            self.assertEqual(grad, 3 * x * x - y)

            grad = Gradient.parameter_expression_grad(expr, y)
            self.assertEqual(grad, -1 * x + 2 * y)
Ejemplo n.º 17
0
    def test_gradient_u(self, method):
        """Test the state gradient for U
        Tr(|psi><psi|Z) = - 0.5 sin(a)cos(c)
        Tr(|psi><psi|X) = cos^2(a/2) cos(b+c) - sin^2(a/2) cos(b-c)
        """

        ham = 0.5 * X - 1 * Z
        a = Parameter('a')
        b = Parameter('b')
        c = Parameter('c')

        q = QuantumRegister(1)
        qc = QuantumCircuit(q)
        qc.h(q)
        qc.u(a, b, c, q[0])

        op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.)
        params = [a, b, c]
        state_grad = Gradient(grad_method=method).convert(operator=op,
                                                          params=params)
        values_dict = [{
            a: np.pi / 4,
            b: 0,
            c: 0
        }, {
            a: np.pi / 4,
            b: np.pi / 4,
            c: np.pi / 4
        }]
        correct_values = [[0.3536, 0, 0], [0.3232, -0.42678, -0.92678]]
        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)

        # Tr(|psi><psi|Z) = - 0.5 sin(a)cos(c)
        # Tr(|psi><psi|X) = cos^2(a/2) cos(b+c) - sin^2(a/2) cos(b-c)
        # dTr(|psi><psi|H)/da = 0.5(cos(2a)) + 0.5()

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

        op = ~StateFn(ham) @ CircuitStateFn(primitive=qc, coeff=1.)
        params = [a]
        state_grad = Gradient(grad_method=method).convert(operator=op,
                                                          params=params)
        values_dict = [{a: np.pi / 4}, {a: np.pi / 2}]
        correct_values = [[-1.03033], [-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)
Ejemplo n.º 18
0
 def test_converted_to_float_if_bound(self):
     """Test the gradient is a float when no free symbols are left."""
     x = Parameter('x')
     expr = 2 * x + 1
     grad = Gradient.parameter_expression_grad(expr, x)
     self.assertIsInstance(grad, float)