Esempio n. 1
0
    def __init__(self, backend='noiseless', differentiator=None, **kwargs):
        """Instantiate this Layer.

        Create a layer that will output expectation values gained from
        simulating a quantum circuit.

        Args:
            backend: Optional Backend to use to simulate states. Defaults to
                the 'noiseless' simulator, options include {'noiseless',
                'noisy'}. In the noisy case a `repetitions` call argument
                must be provided. Users may also specify a preconfigured cirq
                object to use instead, which must inherit
                `cirq.sim.simulator.SimulatesExpectationValues`.
            differentiator: Optional Differentiator to use to calculate analytic
                derivative values of given operators_to_measure and circuit,
                which must inherit `tfq.differentiators.Differentiator` and
                implements `differentiate_analytic` method. Defaults to None,
                which uses `tfq.differentiators.ParameterShift()`. If
                `backend` is also 'noiseless' then default is
                `tfq.differentiators.Adjoint`.

        """
        super().__init__(**kwargs)

        # Ingest backend.
        if not isinstance(
            backend, cirq.sim.simulator.SimulatesExpectationValues) and \
                isinstance(backend, cirq.Sampler):
            raise TypeError("Backend implements cirq.Sampler but not "
                            "cirq.sim.simulator.SimulatesExpectationValues. "
                            "Please use SampledExpectation instead.")
        used_op = None
        self.noisy = False
        if backend == 'noiseless':
            backend = None

        # Ingest differentiator.
        if differentiator is None:
            differentiator = parameter_shift.ParameterShift()
            if backend is None:
                differentiator = adjoint.Adjoint()

        if not isinstance(differentiator, diff.Differentiator):
            raise TypeError("Differentiator must inherit from "
                            "tfq.differentiators.Differentiator")

        if backend == 'noisy':
            used_op = noisy_expectation_op.expectation
            self._expectation_op = differentiator.generate_differentiable_op(
                sampled_op=used_op)
            self.noisy = True
        else:
            used_op = circuit_execution_ops.get_expectation_op(backend=backend)
            self._expectation_op = differentiator.generate_differentiable_op(
                analytic_op=used_op)

        self._w = None
    def test_gradient_circuits_grad_comparison(self, differentiator, n_qubits,
                                               n_programs, n_ops,
                                               symbol_names):
        """Test that analytic gradient agrees with the one from grad circuits"""
        # Get random circuits to check.
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                cirq.GridQubit.rect(1, n_qubits), symbol_names, n_programs)
        psums = [
            util.random_pauli_sums(qubits, 1, n_ops) for _ in circuit_batch
        ]

        # Convert to tensors.
        symbol_names_array = np.array(symbol_names)
        symbol_values_array = np.array(
            [[resolver[symbol] for symbol in symbol_names]
             for resolver in resolver_batch],
            dtype=np.float32)
        symbol_names_tensor = tf.convert_to_tensor(symbol_names_array)
        symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
        programs = util.convert_to_tensor(circuit_batch)
        ops_tensor = util.convert_to_tensor(psums)

        # Get gradients using expectations of gradient circuits.
        (batch_programs, new_symbol_names, batch_symbol_values, batch_weights,
         batch_mapper) = differentiator.get_gradient_circuits(
             programs, symbol_names_tensor, symbol_values_tensor)
        analytic_op = circuit_execution_ops.get_expectation_op()
        batch_pauli_sums = tf.tile(tf.expand_dims(ops_tensor, 1),
                                   [1, tf.shape(batch_programs)[1], 1])
        n_batch_programs = tf.reduce_prod(tf.shape(batch_programs))
        n_symbols = len(symbol_names)
        batch_expectations = analytic_op(
            tf.reshape(batch_programs, [n_batch_programs]), new_symbol_names,
            tf.reshape(batch_symbol_values, [n_batch_programs, n_symbols]),
            tf.reshape(batch_pauli_sums, [n_batch_programs, n_ops]))
        batch_expectations = tf.reshape(batch_expectations,
                                        tf.shape(batch_pauli_sums))

        batch_jacobian = tf.map_fn(
            lambda x: tf.einsum('km,kmp->kp', x[0], tf.gather(x[1], x[2])),
            (batch_weights, batch_expectations, batch_mapper),
            fn_output_signature=tf.float32)
        grad_manual = tf.reduce_sum(batch_jacobian, -1)

        # Get gradients using autodiff.
        differentiator.refresh()
        differentiable_op = differentiator.generate_differentiable_op(
            analytic_op=analytic_op)
        with tf.GradientTape() as g:
            g.watch(symbol_values_tensor)
            exact_outputs = differentiable_op(programs, symbol_names_tensor,
                                              symbol_values_tensor, ops_tensor)
        grad_auto = g.gradient(exact_outputs, symbol_values_tensor)
        self.assertAllClose(grad_manual, grad_auto)
Esempio n. 3
0
    def test_analytic_functional(self, diff):
        """Test that the differentiate_analytic function WORKS."""
        differentiable_op = diff.generate_differentiable_op(
            analytic_op=circuit_execution_ops.get_expectation_op())
        circuit, names, values, ops, _, true_f, true_g = _simple_op_inputs()
        with tf.GradientTape() as g:
            g.watch(values)
            res = differentiable_op(circuit, names, values, ops)

        # Just check that it computes without failing.
        self.assertAllClose(true_f, res, atol=1e-2, rtol=1e-2)
        self.assertAllClose(true_g,
                            g.gradient(res, values),
                            atol=1e-2,
                            rtol=1e-2)
    def test_parameter_shift_analytic(self):
        """Test if ParameterShift.differentiate_analytical doesn't crash before
        running."""
        programs, names, values, ops, _, true_f, true_g = \
        _simple_op_inputs()

        ps = parameter_shift.ParameterShift()
        op = ps.generate_differentiable_op(
            analytic_op=circuit_execution_ops.get_expectation_op())

        with tf.GradientTape() as g:
            g.watch(values)
            expectations = op(programs, names, values, ops)
        grads = g.gradient(expectations, values)
        self.assertAllClose(expectations, true_f, atol=1e-2, rtol=1e-2)
        self.assertAllClose(grads, true_g, atol=1e-2, rtol=1e-2)
    def test_stochastic_differentiator_call_analytic(self, coordinate,
                                                     generator, cost, uniform):
        """Test if SGDifferentiator.differentiate_analytical doesn't crash
            before running."""
        programs, names, values, ops, _, true_f, true_g = \
        _simple_op_inputs()
        diff = stochastic_differentiator.SGDifferentiator(
            coordinate, generator, cost, uniform)
        op = diff.generate_differentiable_op(
            analytic_op=circuit_execution_ops.get_expectation_op())

        with tf.GradientTape() as g:
            g.watch(values)
            expectations = op(programs, names, values, ops)
        grads = g.gradient(expectations, values)
        self.assertAllClose(expectations, true_f, atol=1e-2, rtol=1e-2)
        self.assertAllClose(grads, true_g, atol=1e-2, rtol=1e-2)
Esempio n. 6
0
    def __init__(self, backend=None, differentiator=None, **kwargs):
        """Instantiate this Layer.

        Create a layer that will output expectation values gained from
        simulating a quantum circuit.

        Args:
            backend: Optional Backend to use to simulate states. Defaults to
                the native TensorFlow simulator (None), however users may also
                specify a preconfigured cirq object to use instead, which must
                inherit `cirq.sim.simulator.SimulatesExpectationValues`.
            differentiator: Optional Differentiator to use to calculate analytic
                derivative values of given operators_to_measure and circuit,
                which must inherit `tfq.differentiators.Differentiator` and
                implements `differentiate_analytic` method. Defaults to None,
                which uses `linear_combination.ForwardDifference()`. If
                `backend` is also None then default is
                `tfq.differentiators.Adjoint`.

        """
        super().__init__(**kwargs)

        # Ingest backend.
        if not isinstance(
            backend, cirq.sim.simulator.SimulatesExpectationValues) and \
                isinstance(backend, cirq.Sampler):
            raise TypeError("Backend implements cirq.Sampler but not "
                            "cirq.sim.simulator.SimulatesExpectationValues. "
                            "Please use SampledExpectation instead.")

        # Ingest differentiator.
        if differentiator is None:
            differentiator = linear_combination.ForwardDifference()
            if backend is None:
                differentiator = adjoint.Adjoint()

        if not isinstance(differentiator, diff.Differentiator):
            raise TypeError("Differentiator must inherit from "
                            "tfq.differentiators.Differentiator")

        self._expectation_op = differentiator.generate_differentiable_op(
            analytic_op=circuit_execution_ops.get_expectation_op(
                backend=backend))

        self._w = None
Esempio n. 7
0
 def test_get_expectation_inputs(self):
     """Test that get expectation only accepts inputs it should."""
     circuit_execution_ops.get_expectation_op()
     circuit_execution_ops.get_expectation_op(backend=cirq.Simulator())
     circuit_execution_ops.get_expectation_op(
         backend=cirq.DensityMatrixSimulator())
     circuit_execution_ops.get_expectation_op()
     with self.assertRaisesRegex(NotImplementedError,
                                 expected_regex='Sample-based'):
         mock_engine = mock.Mock()
         circuit_execution_ops.get_expectation_op(
             cirq.google.QuantumEngineSampler(engine=mock_engine,
                                              processor_id='test',
                                              gate_set=cirq.google.XMON))
     with self.assertRaisesRegex(
             TypeError, expected_regex="a Cirq.SimulatesFinalState"):
         circuit_execution_ops.get_expectation_op(backend="junk")
Esempio n. 8
0
from absl.testing import parameterized
from scipy import stats
import cirq

from tensorflow_quantum.core.ops import batch_util, circuit_execution_ops
from tensorflow_quantum.python import util

# Number of random circuits to use in a test batch.
BATCH_SIZE = 15

# These get used everywhere
WF_SIM = cirq.sim.sparse_simulator.Simulator()
DM_SIM = cirq.sim.density_matrix_simulator.DensityMatrixSimulator()

EXPECTATION_OPS = [
    circuit_execution_ops.get_expectation_op(backend=None),
    circuit_execution_ops.get_expectation_op(backend=WF_SIM),
    circuit_execution_ops.get_expectation_op(backend=DM_SIM)
]

SAMPLING_OPS = [
    circuit_execution_ops.get_sampling_op(backend=None),
    circuit_execution_ops.get_sampling_op(backend=WF_SIM),
    circuit_execution_ops.get_sampling_op(backend=DM_SIM)
]

STATE_OPS = [
    circuit_execution_ops.get_state_op(backend=None),
    circuit_execution_ops.get_state_op(backend=WF_SIM),
    circuit_execution_ops.get_state_op(backend=DM_SIM)
]
from absl.testing import parameterized
from scipy import stats
import cirq

from tensorflow_quantum.core.ops import batch_util, circuit_execution_ops
from tensorflow_quantum.python import util

# Number of random circuits to use in a test batch.
BATCH_SIZE = 15

# These get used everywhere
WF_SIM = cirq.sim.sparse_simulator.Simulator()
DM_SIM = cirq.sim.density_matrix_simulator.DensityMatrixSimulator()

EXPECTATION_OPS = [
    circuit_execution_ops.get_expectation_op(backend=None,
                                             quantum_concurrent=True),
    circuit_execution_ops.get_expectation_op(backend=WF_SIM,
                                             quantum_concurrent=True),
    circuit_execution_ops.get_expectation_op(backend=DM_SIM,
                                             quantum_concurrent=True),
    # For timing interests C++ backend is tested in quantum_concurrent mode.
    circuit_execution_ops.get_expectation_op(backend=None,
                                             quantum_concurrent=False)
]

SAMPLING_OPS = [
    circuit_execution_ops.get_sampling_op(backend=None,
                                          quantum_concurrent=True),
    circuit_execution_ops.get_sampling_op(backend=WF_SIM,
                                          quantum_concurrent=True),
    circuit_execution_ops.get_sampling_op(backend=DM_SIM,
Esempio n. 10
0
class AnalyticGradientCorrectnessTest(tf.test.TestCase,
                                      parameterized.TestCase):
    """Test correctness of the differentiators to reference cirq algorithm."""
    @parameterized.parameters(
        list(
            util.kwargs_cartesian_product(**{
                'differentiator': ANALYTIC_DIFFS,
                'op': ANALYTIC_OPS
            })) + [{
                'differentiator': adjoint.Adjoint(),
                'op': circuit_execution_ops.get_expectation_op()
            }])
    def test_backprop(self, differentiator, op):
        """Test that gradients are correctly backpropagated through a quantum
        circuit via comparison to analytical results.
        """
        differentiator.refresh()
        op = differentiator.generate_differentiable_op(analytic_op=op)

        def exact_grad(theta):
            new_theta = 2 * np.pi * theta
            return -2 * np.pi * np.sin(new_theta) * np.exp(np.cos(new_theta))

        bit = cirq.GridQubit(0, 0)
        circuits = util.convert_to_tensor(
            [cirq.Circuit(cirq.X(bit)**sympy.Symbol('rx')) for _ in range(2)])
        pstring = util.convert_to_tensor([[
            cirq.PauliSum.from_pauli_strings([cirq.PauliString({bit: cirq.Z})])
        ] for _ in circuits])
        base_rot_angles = tf.constant([[0.25], [0.125]])
        with tf.GradientTape() as g:
            g.watch(base_rot_angles)
            input_angles = 2 * base_rot_angles
            exp_res = tf.exp(
                op(circuits, tf.convert_to_tensor(['rx']), input_angles,
                   pstring))

        grad = g.gradient(exp_res, base_rot_angles)
        exact = [[exact_grad(0.25)], [exact_grad(0.125)]]

        # will this be too tight? time will tell.
        self.assertAllClose(exact, grad.numpy(), rtol=0.01, atol=0.01)

    @parameterized.parameters(
        list(
            util.kwargs_cartesian_product(
                **{
                    'differentiator': ANALYTIC_DIFFS,
                    'op': ANALYTIC_OPS,
                    'n_qubits': [5],
                    'n_programs': [3],
                    'n_ops': [3],
                    'symbol_names': [['a', 'b']]
                })) + [{
                    'differentiator': adjoint.Adjoint(),
                    'op': circuit_execution_ops.get_expectation_op(),
                    'n_qubits': 10,
                    'n_programs': 5,
                    'n_ops': 3,
                    'symbol_names': ['a', 'b']
                }])
    def test_gradients_vs_cirq_finite_difference(self, differentiator, op,
                                                 n_qubits, n_programs, n_ops,
                                                 symbol_names):
        """Compare TFQ differentiators to fine-grained noiseless cirq finite
        differencing.
        """
        differentiator.refresh()
        op = differentiator.generate_differentiable_op(analytic_op=op)

        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                cirq.GridQubit.rect(1, n_qubits), symbol_names, n_programs)

        psums = [
            util.random_pauli_sums(qubits, 1, n_ops) for _ in circuit_batch
        ]

        symbol_values_array = np.array(
            [[resolver[symbol] for symbol in symbol_names]
             for resolver in resolver_batch],
            dtype=np.float32)

        # calculate tfq gradient
        symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
        programs = util.convert_to_tensor(circuit_batch)
        ops = util.convert_to_tensor(psums)
        with tf.GradientTape() as g:
            g.watch(symbol_values_tensor)
            expectations = op(programs, tf.convert_to_tensor(symbol_names),
                              symbol_values_tensor, ops)
        tfq_grads = g.gradient(expectations, symbol_values_tensor)

        # calculate gradients in cirq using a very simple forward differencing
        # scheme
        cirq_grads = _cirq_simple_finite_difference(circuit_batch,
                                                    resolver_batch,
                                                    symbol_names, psums)

        # will this be too tight? time will tell.
        self.assertAllClose(cirq_grads, tfq_grads, rtol=2e-2, atol=2e-2)

    @parameterized.parameters(
        list(
            util.kwargs_cartesian_product(**{
                'differentiator': ANALYTIC_DIFFS,
                'op': ANALYTIC_OPS,
            })) + [{
                'differentiator': adjoint.Adjoint(),
                'op': circuit_execution_ops.get_expectation_op(),
            }])
    def test_analytic_value_with_simple_circuit(self, differentiator, op):
        """Test the value of differentiator with simple circuit."""
        # Get an expectation op, with this differentiator attached.
        differentiator.refresh()
        op = differentiator.generate_differentiable_op(analytic_op=op)
        qubit = cirq.GridQubit(0, 0)
        circuit = util.convert_to_tensor(
            [cirq.Circuit(cirq.X(qubit)**sympy.Symbol('alpha'))])
        psums = util.convert_to_tensor([[cirq.Z(qubit)]])
        symbol_values_array = np.array([[0.123]], dtype=np.float32)
        # Calculate tfq gradient.
        symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
        with tf.GradientTape() as g:
            g.watch(symbol_values_tensor)
            expectations = op(circuit, tf.convert_to_tensor(['alpha']),
                              symbol_values_tensor, psums)
        grads = g.gradient(expectations, symbol_values_tensor)
        ground_truth_grads = np.array([[-1.1839752]])
        self.assertAllClose(ground_truth_grads, grads, rtol=1e-2, atol=1e-2)

    @parameterized.parameters(
        list(
            util.kwargs_cartesian_product(**{
                'differentiator': ANALYTIC_DIFFS,
                'op': ANALYTIC_OPS,
            })) + [{
                'differentiator': adjoint.Adjoint(),
                'op': circuit_execution_ops.get_expectation_op(),
            }])
    def test_empty_circuit_grad(self, differentiator, op):
        """Test that providing no circuits will fail gracefully."""
        differentiator.refresh()
        op = differentiator.generate_differentiable_op(analytic_op=op)
        circuit = tf.convert_to_tensor([], dtype=tf.string)
        psums = tf.raw_ops.Empty(shape=(0, 0), dtype=tf.string)

        # Calculate tfq gradient.
        symbol_values_tensor = tf.raw_ops.Empty(shape=(0, 0), dtype=tf.float32)
        symbol_names_tensor = tf.convert_to_tensor([], dtype=tf.string)
        with tf.GradientTape() as g:
            g.watch(symbol_values_tensor)
            expectations = op(circuit, symbol_names_tensor,
                              symbol_values_tensor, psums)
        grads = g.gradient(expectations, symbol_values_tensor)
        self.assertShapeEqual(grads.numpy(),
                              tf.raw_ops.Empty(shape=(0, 0), dtype=tf.float32))
Esempio n. 11
0
    linear_combination.ForwardDifference(error_order=2, grid_spacing=0.0001),
    linear_combination.CentralDifference(grid_spacing=0.0001),
    linear_combination.CentralDifference(error_order=4, grid_spacing=0.0001),
    parameter_shift.ParameterShift(),
]

SAMPLED_DIFFS = [
    linear_combination.ForwardDifference(grid_spacing=0.05),
    linear_combination.CentralDifference(grid_spacing=0.05),
    parameter_shift.ParameterShift(),
]

SAMPLED_DIFFS_TOLS = [0.5, 0.5, 0.2]

ANALYTIC_OPS = [
    circuit_execution_ops.get_expectation_op(cirq.sim.Simulator()),  # WF
    circuit_execution_ops.get_expectation_op()  # C++
]

SAMPLED_OPS = [
    circuit_execution_ops.get_sampled_expectation_op(
        cirq.sim.Simulator()),  # WF
    circuit_execution_ops.get_sampled_expectation_op()  # C++
]


def _cirq_simple_finite_difference(circuit_batch,
                                   resolvers,
                                   symbol_names,
                                   op_batch,
                                   grid_spacing=0.0001):
Esempio n. 12
0
class GradientCorrectnessTest(tf.test.TestCase, parameterized.TestCase):
    """Test correctness of the differentiators to reference cirq algorithm."""
    @parameterized.parameters(
        list(
            util.kwargs_cartesian_product(
                **{
                    'differentiator': DIFFS + STOCHASTIC_DIFFS,
                    'op': OPS,
                    'stochastic_cost': [False, True]
                })) + [{
                    'differentiator': adjoint.Adjoint(),
                    'op': circuit_execution_ops.get_expectation_op(),
                    'stochastic_cost': False
                }])
    def test_backprop(self, differentiator, op, stochastic_cost):
        """Test that gradients are correctly backpropagated through a quantum
        circuit via comparison to analytical results.
        """
        # hack to add stoachastic cost. TODO (jaeyoo): remove this hack.
        differentiator.stochastic_cost = stochastic_cost
        differentiator.refresh()
        op = differentiator.generate_differentiable_op(analytic_op=op)

        def exact_grad(theta):
            new_theta = 2 * np.pi * theta
            return -2 * np.pi * np.sin(new_theta) * np.exp(np.cos(new_theta))

        bit = cirq.GridQubit(0, 0)
        circuits = util.convert_to_tensor(
            [cirq.Circuit(cirq.X(bit)**sympy.Symbol('rx')) for _ in range(2)])
        pstring = util.convert_to_tensor([[
            cirq.PauliSum.from_pauli_strings([cirq.PauliString({bit: cirq.Z})])
        ] for _ in circuits])
        base_rot_angles = tf.constant([[0.25], [0.125]])
        with tf.GradientTape() as g:
            g.watch(base_rot_angles)
            input_angles = 2 * base_rot_angles
            exp_res = tf.exp(
                op(circuits, tf.convert_to_tensor(['rx']), input_angles,
                   pstring))

        grad = g.gradient(exp_res, base_rot_angles)
        exact = [[exact_grad(0.25)], [exact_grad(0.125)]]

        # will this be too tight? time will tell.
        self.assertAllClose(exact, grad.numpy(), rtol=0.01, atol=0.01)

    @parameterized.parameters(
        list(
            util.kwargs_cartesian_product(
                **{
                    'differentiator': DIFFS,
                    'op': OPS,
                    'n_qubits': [5],
                    'n_programs': [3],
                    'n_ops': [3],
                    'symbol_names': [['a', 'b']]
                })) + [{
                    'differentiator': adjoint.Adjoint(),
                    'op': circuit_execution_ops.get_expectation_op(),
                    'n_qubits': 5,
                    'n_programs': 5,
                    'n_ops': 3,
                    'symbol_names': ['a', 'b']
                }])
    def test_gradients_vs_cirq_finite_difference(self, differentiator, op,
                                                 n_qubits, n_programs, n_ops,
                                                 symbol_names):
        """Compare TFQ differentiators to fine-grained noiseless cirq finite
        differencing.
        DISCLAIMER : the consistency of STOCHASTIC_DIFFS is hard to be checked.
        Its expectation value should be checked, but it takes long time because
        SGDifferentiator is not optimized. Until optimized, the consistency
        will be performed in benchmarks/scripts/differentiators:convergence_test
        TODO(jaeyoo) : move convergence_test here once SGDifferentiator is
         optimized.
        """
        differentiator.refresh()
        op = differentiator.generate_differentiable_op(analytic_op=op)

        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                cirq.GridQubit.rect(1, n_qubits), symbol_names, n_programs)

        psums = [
            util.random_pauli_sums(qubits, 1, n_ops) for _ in circuit_batch
        ]

        symbol_values_array = np.array(
            [[resolver[symbol] for symbol in symbol_names]
             for resolver in resolver_batch],
            dtype=np.float32)

        # calculate tfq gradient
        symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
        programs = util.convert_to_tensor(circuit_batch)
        ops = util.convert_to_tensor(psums)
        with tf.GradientTape() as g:
            g.watch(symbol_values_tensor)
            expectations = op(programs, tf.convert_to_tensor(symbol_names),
                              symbol_values_tensor, ops)
        tfq_grads = g.gradient(expectations, symbol_values_tensor)

        # calculate gradients in cirq using a very simple forward differencing
        # scheme
        cirq_grads = _cirq_simple_finite_difference(circuit_batch,
                                                    resolver_batch,
                                                    symbol_names, psums)

        # will this be too tight? time will tell.
        self.assertAllClose(cirq_grads, tfq_grads, rtol=1e-2, atol=1e-2)

    @parameterized.parameters(
        list(
            util.kwargs_cartesian_product(
                **{
                    'differentiator': DIFFS + STOCHASTIC_DIFFS,
                    'op': OPS,
                    'stochastic_cost': [False, True]
                })) + [{
                    'differentiator': adjoint.Adjoint(),
                    'op': circuit_execution_ops.get_expectation_op(),
                    'stochastic_cost': False
                }])
    def test_analytic_value_with_simple_circuit(self, differentiator, op,
                                                stochastic_cost):
        """Test the value of differentiator with simple circuit.
        Since there are only one symbol, one gate and one op, there is only one
        samling result, STOCHATIC_DIFFS shows the same result with that of
        deterministic differentiators."""
        # Get an expectation op, with this differentiator attached.
        differentiator.refresh()
        differentiator.stochastic_cost = stochastic_cost
        op = differentiator.generate_differentiable_op(analytic_op=op)
        qubit = cirq.GridQubit(0, 0)
        circuit = util.convert_to_tensor(
            [cirq.Circuit(cirq.X(qubit)**sympy.Symbol('alpha'))])
        psums = util.convert_to_tensor([[cirq.Z(qubit)]])
        symbol_values_array = np.array([[0.123]], dtype=np.float32)
        # Calculate tfq gradient.
        symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
        with tf.GradientTape() as g:
            g.watch(symbol_values_tensor)
            expectations = op(circuit, tf.convert_to_tensor(['alpha']),
                              symbol_values_tensor, psums)
        grads = g.gradient(expectations, symbol_values_tensor)
        ground_truth_grads = np.array([[-1.1839752]])
        self.assertAllClose(ground_truth_grads, grads, rtol=1e-2, atol=1e-2)
Esempio n. 13
0
    stochastic_differentiator.SGDifferentiator(stochastic_coordinate=False,
                                               stochastic_generator=False,
                                               stochastic_cost=False),
    stochastic_differentiator.SGDifferentiator(stochastic_coordinate=True,
                                               stochastic_generator=False,
                                               stochastic_cost=False),
    stochastic_differentiator.SGDifferentiator(stochastic_coordinate=False,
                                               stochastic_generator=True,
                                               stochastic_cost=False),
    stochastic_differentiator.SGDifferentiator(stochastic_coordinate=True,
                                               stochastic_generator=True,
                                               stochastic_cost=False),
]

OPS = [
    circuit_execution_ops.get_expectation_op(cirq.sim.Simulator()),  # WF
    circuit_execution_ops.get_expectation_op(
        cirq.DensityMatrixSimulator()),  # DM
    circuit_execution_ops.get_expectation_op()  # C++
]


def _cirq_simple_finite_difference(circuit_batch,
                                   resolvers,
                                   symbol_names,
                                   op_batch,
                                   grid_spacing=0.0001):
    """A simple finite difference code that calculates the gradient of a
    batch of circuits using cirq."""
    simulator = cirq.sim.Simulator()