コード例 #1
0
 def test_get_cirq_sampling_op(self):
     """Input check the wrapper for the cirq sampling op."""
     with self.assertRaisesRegex(TypeError, "must inherit cirq.Sampler."):
         cirq_ops._get_cirq_samples("junk")
     cirq_ops._get_cirq_samples()
     cirq_ops._get_cirq_samples(cirq.Simulator())
     cirq_ops._get_cirq_samples(cirq.DensityMatrixSimulator())
     mock_engine = mock.Mock()
     cirq_ops._get_cirq_samples(
         cirq.google.QuantumEngineSampler(engine=mock_engine,
                                          processor_id='test',
                                          gate_set=cirq.google.XMON))
コード例 #2
0
    def test_cirq_sampling_op_inputs(self):
        """test input checking in the cirq sampling op."""
        test_op = cirq_ops._get_cirq_samples(cirq.Simulator())

        bits = cirq.GridQubit.rect(1, 5)
        test_circuit = serializer.serialize_circuit(
            cirq.testing.random_circuit(bits, MOMENT_DEPTH,
                                        0.9)).SerializeToString()

        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'symbol_names tensor must be of type string'):
            _ = test_op([test_circuit], [0], [[0]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'programs tensor must be of type string'):
            _ = test_op([0], ['rx'], [[0]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'real-valued numeric tensor.'):
            _ = test_op([test_circuit], ['rx'], 'junk', [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'size of symbol_names tensor must match'):
            _ = test_op([test_circuit], ['rx'], [[1, 1]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'size of symbol_names tensor must match'):
            _ = test_op([test_circuit], ['rx', 'ry'], [[1]], [10])
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'num_samples tensor must be of integer type'):
            _ = test_op([test_circuit], ['rx'], [[1]], "junk")
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'num_samples tensor must have size 1'):
            _ = test_op([test_circuit], ['rx'], [[1]], [10, 10])

        _ = test_op([test_circuit], ['rx'], [[1]], [10])
        _ = test_op([test_circuit], [], [[]], [10])
コード例 #3
0
 def test_sample_empty_circuit(self):
     """Test empty circuits"""
     test_op = cirq_ops._get_cirq_samples(
         cirq.sim.sparse_simulator.Simulator())
     test_empty_circuit = serializer.serialize_circuit(
         cirq.Circuit()).SerializeToString()
     _ = test_op([test_empty_circuit], [], [[]], [10])
コード例 #4
0
    def test_get_cirq_samples_general(self):
        """Tests that a general cirq.Sampler is compatible with sampling."""

        class DummySampler(cirq.Sampler):
            """Mock general cirq.Sampler."""

            def run_sweep(self, program, params, repetitions):
                """Returns all ones in the correct sample shape."""
                return [
                    cirq.TrialResult(
                        params=param,
                        measurements={
                            'tfq':
                                np.array([[1] * len(program.all_qubits())] *
                                         repetitions,
                                         dtype=np.int32),
                        }) for param in cirq.to_resolvers(params)
                ]

        all_n_qubits = [1, 2, 3, 4, 5]
        max_n_qubits = max(all_n_qubits)
        n_samples = 2
        this_sampler = DummySampler()
        this_op = cirq_ops._get_cirq_samples(this_sampler)
        circuits = []
        for n_qubits in all_n_qubits:
            circuits.append(
                cirq.Circuit(*cirq.X.on_each(
                    *cirq.GridQubit.rect(1, n_qubits))))
        test_results = this_op(util.convert_to_tensor(circuits), [],
                               [[]] * len(circuits), [n_samples]).numpy()

        expected_results = []
        for n_qubits in all_n_qubits:
            expected_results += [
                [[-2] * (max_n_qubits - n_qubits) + [1] * n_qubits] * n_samples
            ]
        self.assertAllClose(expected_results, test_results)
コード例 #5
0
def get_sampling_op(backend=None):
    """Get a Tensorflow op that produces samples from given quantum circuits.

    This function produces a non-differentiable op that will calculate
    batches of circuit samples given tensor batches of `cirq.Circuit`s,
    parameter values, and a scalar telling the op how many samples to take.


    >>> # Simulate circuits with cirq.
    >>> my_op = tfq.get_sampling_op(backend=cirq.sim.Simulator())
    >>> # Simulate circuits with C++.
    >>> my_second_op = tfq.get_sampling_op()
    >>> # Prepare some inputs.
    >>> qubit = cirq.GridQubit(0, 0)
    >>> my_symbol = sympy.Symbol('alpha')
    >>> my_circuit_tensor = tfq.convert_to_tensor(
    ...     [cirq.Circuit(cirq.X(qubit)**my_symbol)])
    >>> my_values = np.array([[2.0]])
    >>> n_samples = np.array([10])
    >>> # This op can now be run to take samples.
    >>> output = my_second_op(
    ...     my_circuit_tensor, ['alpha'], my_values, n_samples)
    >>> output
    <tf.RaggedTensor [[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]]>


    Args:
        backend: Optional Python `object` that specifies what backend this op
            should use when evaluating circuits. Can be any `cirq.Sampler`. If
            not provided the default C++ sampling op is returned.

    Returns:
        A `callable` with the following signature:

        ```op(programs, symbol_names, symbol_values, num_samples)```

        programs: `tf.Tensor` of strings with shape [batch_size] containing
            the string representations of the circuits to be executed.
        symbol_names: `tf.Tensor` of strings with shape [n_params], which
            is used to specify the order in which the values in
            `symbol_values` should be placed inside of the circuits in
            `programs`.
        symbol_values: `tf.Tensor` of real numbers with shape
            [batch_size, n_params] specifying parameter values to resolve
            into the circuits specified by programs, following the ordering
            dictated by `symbol_names`.
        num_samples: `tf.Tensor` with one element indicating the number of
            samples to draw.

        Returns:
            `tf.Tensor` with shape
                [batch_size, num_samples, <ragged> n_qubits] that
                holds samples (as boolean values) for each circuit.
    """

    # TODO (mbbrough): investigate how the above docstring renders.
    if backend is None:
        return lambda programs, symbol_names, symbol_values, num_samples: \
        tfq_utility_ops.padded_to_ragged(TFQWavefunctionSimulator.samples(
            programs, symbol_names, symbol_values, num_samples))

    if isinstance(backend, (cirq.SimulatesSamples, cirq.Sampler)):
        return lambda programs, symbol_names, symbol_values, num_samples: \
        tfq_utility_ops.padded_to_ragged(cirq_ops._get_cirq_samples(backend)(
            programs, symbol_names, symbol_values, num_samples))

    raise TypeError("Backend {} is invalid. Expected a Cirq.Sampler "
                    "or None.".format(backend))
コード例 #6
0
def get_sampling_op(
    backend=None,
    *,
    quantum_concurrent=quantum_context.get_quantum_concurrent_op_mode()):
    """Get a Tensorflow op that produces samples from given quantum circuits.

    This function produces a non-differentiable op that will calculate
    batches of circuit samples given tensor batches of `cirq.Circuit`s,
    parameter values, and a scalar telling the op how many samples to take.


    >>> # Simulate circuits with cirq.
    >>> my_op = tfq.get_sampling_op(backend=cirq.sim.Simulator())
    >>> # Simulate circuits with C++.
    >>> my_second_op = tfq.get_sampling_op()
    >>> # Prepare some inputs.
    >>> qubit = cirq.GridQubit(0, 0)
    >>> my_symbol = sympy.Symbol('alpha')
    >>> my_circuit_tensor = tfq.convert_to_tensor(
    ...     [cirq.Circuit(cirq.X(qubit)**my_symbol)])
    >>> my_values = np.array([[2.0]])
    >>> n_samples = np.array([10])
    >>> # This op can now be run to take samples.
    >>> output = my_second_op(
    ...     my_circuit_tensor, ['alpha'], my_values, n_samples)
    >>> output
    <tf.RaggedTensor [[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]]>


    Args:
        backend: Optional Python `object` that specifies what backend this op
            should use when evaluating circuits. Can be any `cirq.Sampler`. If
            not provided the default C++ sampling op is returned.
        quantum_concurrent: Optional Python `bool`. True indicates that the
            returned op should not block graph level parallelism on itself when
            executing. False indicates that graph level parallelism on itself
            should be blocked. Defaults to value specified in
            `tfq.get_quantum_concurrent_op_mode` which defaults to True
            (no blocking). This flag is only needed for advanced users when
            using TFQ for very large simulations, or when running on a real
            chip.

    Returns:
        A `callable` with the following signature:

        ```op(programs, symbol_names, symbol_values, num_samples)```

        programs: `tf.Tensor` of strings with shape [batch_size] containing
            the string representations of the circuits to be executed.
        symbol_names: `tf.Tensor` of strings with shape [n_params], which
            is used to specify the order in which the values in
            `symbol_values` should be placed inside of the circuits in
            `programs`.
        symbol_values: `tf.Tensor` of real numbers with shape
            [batch_size, n_params] specifying parameter values to resolve
            into the circuits specified by programs, following the ordering
            dictated by `symbol_names`.
        num_samples: `tf.Tensor` with one element indicating the number of
            samples to draw.

        Returns:
            `tf.Tensor` with shape
                [batch_size, num_samples, <ragged> n_qubits] that
                holds samples (as boolean values) for each circuit.
    """

    # TODO (mbbrough): investigate how the above docstring renders.
    _check_quantum_concurrent(quantum_concurrent)

    op = None
    if backend is None:
        op = TFQWavefunctionSimulator.samples

    if isinstance(backend, cirq.Sampler):
        op = cirq_ops._get_cirq_samples(backend)

    if op is not None:
        if quantum_concurrent is True:
            # Return an op that does not block graph level parallelism.
            return lambda programs, symbol_names, symbol_values, num_samples: \
                tfq_utility_ops.padded_to_ragged(
                    op(programs, symbol_names, symbol_values, num_samples))

        return lambda programs, symbol_names, symbol_values, num_samples: \
            _GLOBAL_OP_LOCK.execute(lambda: tfq_utility_ops.padded_to_ragged(
                op(programs, symbol_names, symbol_values, num_samples)))

    raise TypeError("Backend {} is invalid. Expected a Cirq.Sampler "
                    "or None.".format(backend))
コード例 #7
0
 def test_sample_no_circuit(self):
     """Test empty tensors with no circuits at all."""
     test_op = cirq_ops._get_cirq_samples(cirq.Simulator())
     empty_programs = tf.raw_ops.Empty(shape=(0,), dtype=tf.string)
     empty_values = tf.raw_ops.Empty(shape=(0, 0), dtype=tf.float32)
     _ = test_op(empty_programs, [], empty_values, [1])
コード例 #8
0
class CirqSamplesTest(tf.test.TestCase, parameterized.TestCase):
    """Tests get_cirq_samples."""

    def test_get_cirq_sampling_op(self):
        """Input check the wrapper for the cirq sampling op."""
        with self.assertRaisesRegex(TypeError, "must inherit cirq.Sampler."):
            cirq_ops._get_cirq_samples("junk")
        cirq_ops._get_cirq_samples()
        cirq_ops._get_cirq_samples(cirq.Simulator())
        cirq_ops._get_cirq_samples(cirq.DensityMatrixSimulator())
        mock_engine = mock.Mock()
        cirq_ops._get_cirq_samples(
            cirq.google.QuantumEngineSampler(engine=mock_engine,
                                             processor_id='test',
                                             gate_set=cirq.google.XMON))

    def test_cirq_sampling_op_inputs(self):
        """test input checking in the cirq sampling op."""
        test_op = cirq_ops._get_cirq_samples(cirq.Simulator())

        bits = cirq.GridQubit.rect(1, 5)
        test_circuit = serializer.serialize_circuit(
            cirq.testing.random_circuit(bits, MOMENT_DEPTH,
                                        0.9)).SerializeToString()

        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'symbol_names tensor must be of type string'):
            _ = test_op([test_circuit], [0], [[0]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'programs tensor must be of type string'):
            _ = test_op([0], ['rx'], [[0]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'real-valued numeric tensor.'):
            _ = test_op([test_circuit], ['rx'], 'junk', [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'size of symbol_names tensor must match'):
            _ = test_op([test_circuit], ['rx'], [[1, 1]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'size of symbol_names tensor must match'):
            _ = test_op([test_circuit], ['rx', 'ry'], [[1]], [10])
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'num_samples tensor must be of integer type'):
            _ = test_op([test_circuit], ['rx'], [[1]], "junk")
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'num_samples tensor must have size 1'):
            _ = test_op([test_circuit], ['rx'], [[1]], [10, 10])

        _ = test_op([test_circuit], ['rx'], [[1]], [10])
        _ = test_op([test_circuit], [], [[]], [10])

    @parameterized.parameters([
        {
            'op': cirq_ops._get_cirq_samples(WF_SIM),
            'all_n_qubits': [2, 3],
            'n_samples': 10
        },
        {
            'op': cirq_ops._get_cirq_samples(DM_SIM),
            'all_n_qubits': [2, 3],
            'n_samples': 10
        },
        {
            'op': cirq_ops._get_cirq_samples(WF_SIM),
            'all_n_qubits': [2, 5, 8, 10],
            'n_samples': 10
        },
        {
            'op': cirq_ops._get_cirq_samples(DM_SIM),
            'all_n_qubits': [2, 5, 8, 10],
            'n_samples': 10
        },
    ])
    def test_sampling_output_padding(self, op, all_n_qubits, n_samples):
        """Check that the sampling ops pad outputs correctly"""
        circuits = []
        expected_outputs = []
        for n_qubits in all_n_qubits:
            this_expected_output = np.zeros((n_samples, max(all_n_qubits)))
            this_expected_output[:, max(all_n_qubits) - n_qubits:] = 1
            this_expected_output[:, :max(all_n_qubits) - n_qubits] = -2
            expected_outputs.append(this_expected_output)
            circuits.append(
                cirq.Circuit(*cirq.X.on_each(
                    *cirq.GridQubit.rect(1, n_qubits))))
        results = op(util.convert_to_tensor(circuits), [], [[]] * len(circuits),
                     [n_samples]).numpy()
        self.assertAllClose(expected_outputs, results)

    def test_sample_empty_circuit(self):
        """Test empty circuits"""
        test_op = cirq_ops._get_cirq_samples(cirq.Simulator())
        test_empty_circuit = serializer.serialize_circuit(
            cirq.Circuit()).SerializeToString()
        _ = test_op([test_empty_circuit], [], [[]], [10])

    def test_sample_no_circuit(self):
        """Test empty tensors with no circuits at all."""
        test_op = cirq_ops._get_cirq_samples(cirq.Simulator())
        empty_programs = tf.raw_ops.Empty(shape=(0,), dtype=tf.string)
        empty_values = tf.raw_ops.Empty(shape=(0, 0), dtype=tf.float32)
        _ = test_op(empty_programs, [], empty_values, [1])

    def test_get_cirq_samples_general(self):
        """Tests that a general cirq.Sampler is compatible with sampling."""

        class DummySampler(cirq.Sampler):
            """Mock general cirq.Sampler."""

            def run_sweep(self, program, params, repetitions):
                """Returns all ones in the correct sample shape."""
                return [
                    cirq.TrialResult(
                        params=param,
                        measurements={
                            'tfq':
                                np.array([[1] * len(program.all_qubits())] *
                                         repetitions,
                                         dtype=np.int32),
                        }) for param in cirq.to_resolvers(params)
                ]

        all_n_qubits = [1, 2, 3, 4, 5]
        max_n_qubits = max(all_n_qubits)
        n_samples = 2
        this_sampler = DummySampler()
        this_op = cirq_ops._get_cirq_samples(this_sampler)
        circuits = []
        for n_qubits in all_n_qubits:
            circuits.append(
                cirq.Circuit(*cirq.X.on_each(
                    *cirq.GridQubit.rect(1, n_qubits))))
        test_results = this_op(util.convert_to_tensor(circuits), [],
                               [[]] * len(circuits), [n_samples]).numpy()

        expected_results = []
        for n_qubits in all_n_qubits:
            expected_results += [
                [[-2] * (max_n_qubits - n_qubits) + [1] * n_qubits] * n_samples
            ]
        self.assertAllClose(expected_results, test_results)
コード例 #9
0
class CirqSamplesTest(tf.test.TestCase, parameterized.TestCase):
    """Tests get_cirq_samples."""

    def test_get_cirq_sampling_op(self):
        """Input check the wrapper for the cirq sampling op."""
        with self.assertRaisesRegex(TypeError,
                                    "simulator must inherit cirq.Sampler."):
            cirq_ops._get_cirq_samples("junk")
        cirq_ops._get_cirq_samples()
        cirq_ops._get_cirq_samples(cirq.sim.sparse_simulator.Simulator())
        cirq_ops._get_cirq_samples(
            cirq.sim.density_matrix_simulator.DensityMatrixSimulator())
        mock_engine = mock.Mock()
        cirq_ops._get_cirq_samples(
            cirq.google.QuantumEngineSampler(engine=mock_engine,
                                             processor_id='test',
                                             gate_set=cirq.google.XMON))

    def test_cirq_sampling_op_inputs(self):
        """test input checking in the cirq sampling op."""
        test_op = cirq_ops._get_cirq_samples(
            cirq.sim.sparse_simulator.Simulator())

        bits = cirq.GridQubit.rect(1, 5)
        test_circuit = serializer.serialize_circuit(
            cirq.testing.random_circuit(bits, MOMENT_DEPTH,
                                        0.9)).SerializeToString()

        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'symbol_names tensor must be of type string'):
            _ = test_op([test_circuit], [0], [[0]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'programs tensor must be of type string'):
            _ = test_op([0], ['rx'], [[0]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'real-valued numeric tensor.'):
            _ = test_op([test_circuit], ['rx'], 'junk', [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'size of symbol_names tensor must match'):
            _ = test_op([test_circuit], ['rx'], [[1, 1]], [10])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'size of symbol_names tensor must match'):
            _ = test_op([test_circuit], ['rx', 'ry'], [[1]], [10])
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'num_samples tensor must be of integer type'):
            _ = test_op([test_circuit], ['rx'], [[1]], "junk")
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'num_samples tensor must have size 1'):
            _ = test_op([test_circuit], ['rx'], [[1]], [10, 10])

        _ = test_op([test_circuit], ['rx'], [[1]], [10])
        _ = test_op([test_circuit], [], [[]], [10])

    @parameterized.parameters([
        {
            'op': cirq_ops._get_cirq_samples(WF_SIM),
            'all_n_qubits': [2, 3],
            'n_samples': 10
        },
        {
            'op': cirq_ops._get_cirq_samples(DM_SIM),
            'all_n_qubits': [2, 3],
            'n_samples': 10
        },
        {
            'op': cirq_ops._get_cirq_samples(WF_SIM),
            'all_n_qubits': [2, 5, 8, 10],
            'n_samples': 10
        },
        {
            'op': cirq_ops._get_cirq_samples(DM_SIM),
            'all_n_qubits': [2, 5, 8, 10],
            'n_samples': 10
        },
    ])
    def test_sampling_output_padding(self, op, all_n_qubits, n_samples):
        """Check that the sampling ops pad outputs correctly"""
        circuits = []
        expected_outputs = []
        for n_qubits in all_n_qubits:
            this_expected_output = np.zeros((n_samples, max(all_n_qubits)))
            this_expected_output[:, max(all_n_qubits) - n_qubits:] = 1
            this_expected_output[:, :max(all_n_qubits) - n_qubits] = -2
            expected_outputs.append(this_expected_output)
            circuits.append(
                cirq.Circuit(
                    *cirq.X.on_each(*cirq.GridQubit.rect(1, n_qubits))))
        results = op(util.convert_to_tensor(circuits), [], [[]] * len(circuits),
                     [n_samples]).numpy()
        self.assertAllClose(expected_outputs, results)

    def test_sample_empty_circuit(self):
        """Test empty circuits"""
        test_op = cirq_ops._get_cirq_samples(
            cirq.sim.sparse_simulator.Simulator())
        test_empty_circuit = serializer.serialize_circuit(
            cirq.Circuit()).SerializeToString()
        _ = test_op([test_empty_circuit], [], [[]], [10])