Beispiel #1
0
 def test_sampling_output_padding(self, all_n_qubits, n_samples):
     """Check that the sampling ops pad outputs correctly"""
     op = tfq_simulate_ops.tfq_simulate_samples
     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_iswap_gate_test(self):
     """Test 1 ISwapPowGate decomposition."""
     t = sympy.Symbol('t')
     qubits = cirq.GridQubit.rect(1, 2)
     circuit = cirq.Circuit(
         cirq.ISwapPowGate(exponent=np.random.random() * t).on(*qubits))
     inputs = util.convert_to_tensor([circuit])
     outputs = tfq_ps_util_ops.tfq_ps_decompose(inputs)
     decomposed_programs = util.from_tensor(outputs)
     rand_resolver = {'t': np.random.random()}
     self.assertAllClose(
         cirq.unitary(cirq.resolve_parameters(circuit, rand_resolver)),
         cirq.unitary(
             cirq.resolve_parameters(decomposed_programs[0],
                                     rand_resolver)),
         atol=1e-5)
    def test_expectation_op_error(self):
        """Test that expectation errors within underlying ops correctly."""

        bit = cirq.GridQubit(0, 0)
        symbol = sympy.Symbol('alpha')
        test_pstring = cirq.Z(bit)
        test_psum = cirq.PauliSum.from_pauli_strings([test_pstring])
        symb_circuit = cirq.Circuit(cirq.H(bit)**symbol)
        reg_circuit = cirq.Circuit(cirq.H(bit))

        with self.assertRaisesRegex(Exception,
                                    expected_regex="Could not find symbol"):
            # No symbol matchups.
            expectation.Expectation()([symb_circuit], operators=test_psum)

        with self.assertRaisesRegex(Exception,
                                    expected_regex="Unparseable proto"):
            # Proto is unparseable.
            expectation.Expectation()([reg_circuit],
                                      operators=tf.convert_to_tensor(
                                          [['bad_operator']]))

        with self.assertRaisesRegex(Exception, expected_regex="rank 2"):
            # Operators has wrong rank.
            expectation.Expectation()([reg_circuit],
                                      operators=util.convert_to_tensor(
                                          [test_psum]))

        with self.assertRaisesRegex(Exception, expected_regex="rank 2"):
            # symbol_values has wrong rank.
            expectation.Expectation()([symb_circuit],
                                      symbol_names=[symbol],
                                      symbol_values=[0.5],
                                      operators=test_psum)

        with self.assertRaisesRegex(Exception, expected_regex="do not match."):
            # Wrong batch size for pauli operators.
            expectation.Expectation()(symb_circuit,
                                      symbol_names=[symbol],
                                      operators=[[test_psum], [test_psum]])

        with self.assertRaisesRegex(Exception, expected_regex="do not match."):
            # Wrong batch_size for symbol values.
            expectation.Expectation()([symb_circuit],
                                      symbol_names=[symbol],
                                      symbol_values=np.zeros((3, 1)),
                                      operators=test_psum)
    def test_allowed_cases(self):
        """Ensure all allowed input combinations are upgraded correctly."""
        qubits = cirq.GridQubit.rect(1, 2)

        # Test all symbol-filled circuit configurations
        names_symbol_list = list(sympy.symbols("s0:2"))
        names_string_list = [str(s) for s in names_symbol_list]
        names_symbol_tuple = tuple(names_symbol_list)
        names_string_tuple = tuple(names_string_list)
        names_tensor = tf.convert_to_tensor(names_string_list,
                                            dtype=tf.dtypes.string)
        circuit_alone = cirq.Circuit(
            cirq.H(qubits[0])**names_symbol_list[0],
            cirq.X(qubits[1])**names_symbol_list[1])
        circuit_list = [circuit_alone for _ in range(3)]
        circuit_tuple = tuple(circuit_list)
        circuit_tensor = util.convert_to_tensor(circuit_list)
        values_list = [[1], [2], [3]]
        values_tuple = tuple(values_list)
        values_ndarray = np.array(values_list)
        values_tensor = tf.convert_to_tensor(values_list,
                                             dtype=tf.dtypes.float32)
        for names in [
                names_symbol_list, names_string_list, names_symbol_tuple,
                names_string_tuple, names_tensor
        ]:
            for circuit in [
                    circuit_alone, circuit_list, circuit_tuple, circuit_tensor
            ]:
                for values in [
                        values_list, values_tuple, values_ndarray, values_tensor
                ]:
                    circuit_test, names_test, values_test = \
                        input_checks.expand_circuits(circuit, names, values)
                    self.assertAllEqual(circuit_test, circuit_tensor)
                    self.assertAllEqual(names_test, names_tensor)
                    self.assertAllEqual(values_test, values_tensor)

        # Test the case of empty symbols
        names_tensor = tf.convert_to_tensor([], dtype=tf.dtypes.string)
        values_tensor = tf.convert_to_tensor([[]] * 3, dtype=tf.dtypes.float32)
        for circuit in [circuit_list, circuit_tuple, circuit_tensor]:
            circuit_test, names_test, values_test = \
                input_checks.expand_circuits(circuit)
            self.assertAllEqual(circuit_test, circuit_tensor)
            self.assertAllEqual(names_test, names_tensor)
            self.assertAllEqual(values_test, values_tensor)
    def test_expand_circuits_error(self):
        """Test that expand_circuits errors on bad arguments."""

        # Valid test constants
        qubit = cirq.GridQubit(0, 0)
        symbol = sympy.Symbol('alpha')
        names_tensor = tf.convert_to_tensor([str(symbol)],
                                            dtype=tf.dtypes.string)
        circuit_tensor = util.convert_to_tensor(
            [cirq.Circuit(cirq.H(qubit)**symbol)])
        values_tensor = tf.convert_to_tensor([[0.5]], dtype=tf.dtypes.float32)

        # Bad circuit arg
        with self.assertRaisesRegex(TypeError,
                                    expected_regex="circuits cannot be parsed"):
            input_checks.expand_circuits('junk',
                                         symbol_names=names_tensor,
                                         symbol_values=values_tensor)

        # Bad name arg
        with self.assertRaisesRegex(TypeError,
                                    expected_regex="string or sympy.Symbol"):
            input_checks.expand_circuits(circuit_tensor,
                                         symbol_names=[symbol, 5.0],
                                         symbol_values=values_tensor)
        with self.assertRaisesRegex(TypeError,
                                    expected_regex="string or sympy.Symbol"):
            input_checks.expand_circuits(circuit_tensor,
                                         symbol_names=[[]],
                                         symbol_values=values_tensor)
        with self.assertRaisesRegex(ValueError,
                                    expected_regex="must be unique."):
            input_checks.expand_circuits(circuit_tensor,
                                         symbol_names=[symbol, symbol],
                                         symbol_values=values_tensor)
        with self.assertRaisesRegex(
                TypeError, expected_regex="symbol_names cannot be parsed"):
            input_checks.expand_circuits(circuit_tensor,
                                         symbol_names='junk',
                                         symbol_values=values_tensor)

        # Bad value arg
        with self.assertRaisesRegex(
                TypeError, expected_regex="symbol_values cannot be parsed"):
            input_checks.expand_circuits(circuit_tensor,
                                         symbol_names=names_tensor,
                                         symbol_values='junk')
    def test_more_complex_moment_preservation(self):
        """Test Moment-structure preservation."""
        circuit_batch = _complex_test_circuit()
        inputs = util.convert_to_tensor(circuit_batch)
        outputs = tfq_ps_util_ops.tfq_ps_decompose(inputs)
        decomposed_programs = util.from_tensor(outputs)
        # Now all programs don't have ISWAP & PhasedXPowGate because ISWAP has
        # 3 eigenvalues and PhasedXPowGate doesn't have _eigen_components.
        # Check if two programs are identical.
        rand_resolver = {'t': np.random.random(), 'r': np.random.random()}
        for i in range(3):
            self.assertAllClose(cirq.unitary(
                cirq.resolve_parameters(circuit_batch[i], rand_resolver)),
                                cirq.unitary(
                                    cirq.resolve_parameters(
                                        decomposed_programs[i],
                                        rand_resolver)),
                                atol=1e-5)
        # Check if the Moments are conserved.
        # Circuit 1.
        max_decomposed_length = 3
        n_non_decomposed_moments = 2
        self.assertEqual(len(decomposed_programs[0]),
                         n_non_decomposed_moments + max_decomposed_length)
        # Total length of Moments = 5
        # The non-decomposed moments should be the same.
        self.assertEqual(decomposed_programs[0][0], circuit_batch[0][0])
        self.assertEqual(decomposed_programs[0][-1], circuit_batch[0][-1])
        # Check paralellized decompose gates in Moment[1]~[3].
        # The target ops are replaced by the first decomposition gates. It means
        # the first Moment has exactly the same number of gate ops.
        self.assertEqual(len(decomposed_programs[0][1]),
                         len(circuit_batch[0][1]))
        # From the second Moments, the Moments only have decomposition gates.
        # In this example, two ISwapPowGate & one PhasedXPowGate are located.
        # Since PhasedXPowGate, ISwapPowGate, FSimGate has 3, 2, 3 result gates
        # Moment[2] have 3 gate ops and Moment[3] have 2 gate ops.
        self.assertEqual(len(decomposed_programs[0][2]), 3)
        self.assertEqual(len(decomposed_programs[0][3]), 2)

        # Circuit 2. two FSimGates.
        self.assertEqual(len(decomposed_programs[1]),
                         2 * max_decomposed_length)

        # Circuit 3. one PXP between two ISwapPowGates.
        self.assertEqual(len(decomposed_programs[2]), max_decomposed_length)
 def test_allowed_cases(self):
     """Confirm that allowed inputs are upgraded correctly."""
     batch_dim = 3
     bare_string = cirq.Z(cirq.GridQubit(0, 0))
     bare_sum = cirq.PauliSum.from_pauli_strings([bare_string])
     bare_list = [bare_string]
     bare_tuple = tuple(bare_list)
     shaped_list = [[bare_string]] * batch_dim
     shaped_tuple = tuple(shaped_list)
     op_tensor_single = util.convert_to_tensor([[bare_string]])
     op_tensor = tf.tile(op_tensor_single, [batch_dim, 1])
     for op in [
             bare_string, bare_sum, bare_list, bare_tuple, shaped_list,
             shaped_tuple, op_tensor
     ]:
         op_test = input_checks.expand_operators(op, batch_dim)
         self.assertAllEqual(op_test, op_tensor)
Beispiel #8
0
 def test_phased_x_pow_gate_test(self):
     """Test 1 PhasedXPowGate decomposition."""
     t = sympy.Symbol('t')
     r = sympy.Symbol('r')
     q = cirq.GridQubit(0, 0)
     circuit = cirq.Circuit(
         cirq.PhasedXPowGate(phase_exponent=np.random.random() * r,
                             exponent=np.random.random() * t).on(q))
     inputs = util.convert_to_tensor([circuit])
     outputs = tfq_ps_util_ops.tfq_ps_decompose(inputs)
     decomposed_programs = util.from_tensor(outputs)
     rand_resolver = {'t': np.random.random(), 'r': np.random.random()}
     self.assertAllClose(cirq.unitary(
         cirq.resolve_parameters(circuit, rand_resolver)),
                         cirq.unitary(
                             cirq.resolve_parameters(decomposed_programs[0],
                                                     rand_resolver)),
                         atol=1e-5)
Beispiel #9
0
    def test_state_output(self, backend_output):
        """Check that any output type is as expected.

        This layer only allows for 2 different outputs, depending on whether a
        wavefuntion or density matrix simulator is used. Therefore any pre or
        post processing done inside the layers should not cause output from the
        layer to structurally deviate from what is expected.
        """
        backend = backend_output[0]
        output = backend_output[1]
        state_executor = state.State(backend=backend)
        bits = cirq.GridQubit.rect(1, 2)
        circuit = cirq.Circuit()
        circuit.append(cirq.H.on(bits[0]))
        circuit.append(cirq.CNOT(bits[0], bits[1]))
        programs = util.convert_to_tensor([circuit, circuit])
        layer_output = state_executor(programs).to_list()
        self.assertAllClose(layer_output, [output, output])
def _example_circuit_helper(n_qubits, n_programs):
    n_shifts = 2
    symbol_names = ['a', 'b']
    n_symbols = len(symbol_names)
    sympy_symbols = [sympy.Symbol(s) for s in symbol_names]
    coeff = [1.0, -2.0, 3.0, -4.0, 5.0]
    q = cirq.GridQubit.rect(1, n_qubits)
    c = cirq.Circuit([
        cirq.Rz(coeff[i] * sympy_symbols[i % 2]).on(q[i])
        for i in range(n_qubits)
    ])
    circuit_batch = [c] * n_programs
    symbol_values_array = np.array([[i for i, _ in enumerate(symbol_names)]
                                    for _ in range(n_programs)],
                                   dtype=np.float32)

    symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
    programs = util.convert_to_tensor(circuit_batch)
    return programs, symbol_values_tensor, n_symbols, n_shifts
    def test_simulate_state_large(self, op_and_sim):
        """Test a reasonably large and complex circuit."""
        op, sim = op_and_sim
        symbol_names = []
        circuit_batch, resolver_batch = \
            util.random_circuit_resolver_batch(
                cirq.GridQubit.rect(4, 4), 5)

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

        op_states = op(util.convert_to_tensor(circuit_batch), symbol_names,
                       symbol_values_array).to_list()

        cirq_states = batch_util.batch_calculate_state(circuit_batch,
                                                       resolver_batch, sim)

        self.assertAllClose(cirq_states, op_states, atol=1e-5, rtol=1e-5)
    def test_sampling(self, op_and_sim, n_qubits, symbol_names):
        """Compare sampling with tfq ops and Cirq."""
        op = op_and_sim[0]
        sim = op_and_sim[1]
        qubits = cirq.GridQubit.rect(1, n_qubits)
        n_samples = int((2**n_qubits) * 1000)

        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, BATCH_SIZE, n_moments=30)
        for i in range(BATCH_SIZE):
            circuit_batch[i] += cirq.Circuit(
                *[cirq.H(qubit) for qubit in qubits])

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

        op_samples = np.array(
            op(util.convert_to_tensor(circuit_batch), symbol_names,
               symbol_values_array, [n_samples]).to_list())

        op_histograms = [
            np.histogram(
                sample.dot(1 << np.arange(sample.shape[-1] - 1, -1, -1)),
                range=(0, 2**len(qubits)),
                bins=2**len(qubits))[0] for sample in op_samples
        ]

        cirq_samples = batch_util.batch_sample(circuit_batch, resolver_batch,
                                               n_samples, sim)

        cirq_histograms = [
            np.histogram(
                sample.dot(1 << np.arange(sample.shape[-1] - 1, -1, -1)),
                range=(0, 2**len(qubits)),
                bins=2**len(qubits))[0] for sample in cirq_samples
        ]

        for a, b in zip(op_histograms, cirq_histograms):
            self.assertLess(stats.entropy(a + 1e-8, b + 1e-8), 0.005)
    def test_resolve_parameters_consistency(self, n_qubits, symbol_names):
        """Compare tfq op to cirq resolving for randomized circuits."""

        # Get random circuit batches
        qubits = cirq.GridQubit.rect(1, n_qubits)
        batch_size = 15
        n_moments = 15
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, batch_size,
                n_moments=n_moments,
                include_channels=True,
                include_scalars=True)

        # Remove one of the symbols from the resolvers
        symbol_names_partial = symbol_names[1:]
        symbol_values_array_partial = np.array(
            [[resolver[symbol] for symbol in symbol_names_partial]
             for resolver in resolver_batch])
        resolver_batch_partial = [
            cirq.ParamResolver(
                {symbol: resolver[symbol]
                 for symbol in symbol_names_partial})
            for resolver in resolver_batch
        ]

        # Resolve in two ways and compare results
        test_resolved_circuits = util.from_tensor(
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch), symbol_names_partial,
                symbol_values_array_partial))
        expected_resolved_circuits = []
        for circuit, resolver in zip(circuit_batch, resolver_batch_partial):
            expected_resolved_circuits.append(
                cirq.resolve_parameters(circuit, resolver))
        # TODO(zaqqwerty): Find a way to eliminate parsing.
        for test_c, exp_c in zip(test_resolved_circuits,
                                 expected_resolved_circuits):
            for test_m, exp_m in zip(test_c, exp_c):
                for test_o, exp_o in zip(test_m, exp_m):
                    self.assertTrue(
                        util.gate_approx_eq(test_o.gate, exp_o.gate))
Beispiel #14
0
 def test_weight_coefficient(self):
     """Test that scalar multiples of trivial case work."""
     bit = cirq.GridQubit(0, 0)
     circuit = cirq.Circuit(
         cirq.X(bit)**(sympy.Symbol('alpha') * 2.4),
         cirq.Y(bit)**(sympy.Symbol('alpha') * 3.4),
         cirq.Z(bit)**(sympy.Symbol('alpha') * 4.4),
     )
     inputs = util.convert_to_tensor([circuit])
     symbols = tf.convert_to_tensor(['alpha'])
     new = tf.convert_to_tensor(['new'])
     res = tfq_ps_util_ops.tfq_ps_symbol_replace(inputs, symbols, new)
     output = util.from_tensor(res)
     correct_00 = cirq.Circuit(
         cirq.X(bit)**(sympy.Symbol('new') * 2.4),
         cirq.Y(bit)**(sympy.Symbol('alpha') * 3.4),
         cirq.Z(bit)**(sympy.Symbol('alpha') * 4.4),
     )
     correct_01 = cirq.Circuit(
         cirq.X(bit)**(sympy.Symbol('alpha') * 2.4),
         cirq.Y(bit)**(sympy.Symbol('new') * 3.4),
         cirq.Z(bit)**(sympy.Symbol('alpha') * 4.4),
     )
     correct_02 = cirq.Circuit(
         cirq.X(bit)**(sympy.Symbol('alpha') * 2.4),
         cirq.Y(bit)**(sympy.Symbol('alpha') * 3.4),
         cirq.Z(bit)**(sympy.Symbol('new') * 4.4),
     )
     for i, c in enumerate([correct_00, correct_01, correct_02]):
         u1 = cirq.unitary(
             cirq.resolve_parameters(c,
                                     param_resolver={
                                         'alpha': 1.23,
                                         'new': 4.56
                                     }))
         u2 = cirq.unitary(
             cirq.resolve_parameters(output[0][0][i],
                                     param_resolver={
                                         'alpha': 1.23,
                                         'new': 4.56
                                     }))
         self.assertTrue(cirq.approx_eq(u1, u2, atol=1e-5))
def _example_ops_helper(n_programs, n_ops):
    coeffs = [[1.0, -2.0, 3.0], [-4.0, 5.0]]
    n_qubits = 3
    q = cirq.GridQubit.rect(1, n_qubits)
    cirq_op_list = [cirq.X, cirq.Y, cirq.Z]

    def get_term_with_coefficient(coeff_list):
        # Test with multiple `cirq.PauliString`'s
        return [
            cirq.PauliString({
                q[i]: cirq_op_list[i],
            }, coefficient=coeff) for i, coeff in enumerate(coeff_list)
        ]

    psums = [[
        cirq.PauliSum.from_pauli_strings(get_term_with_coefficient(coeffs[i]))
        for i in range(n_ops)
    ] for _ in range(n_programs)]
    ops = util.convert_to_tensor(psums)
    return ops, psums, coeffs
Beispiel #16
0
 def test_many_symbols(self):
     """Ensure that padding with few values and many symbols works."""
     bit = cirq.GridQubit(0, 0)
     circuits = [
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('alpha') * 2.0)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('beta') * 6)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('alpha') * 5.0)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('gamma') * 8)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('delta') * 9))
     ]
     inputs = util.convert_to_tensor(circuits)
     symbols = tf.convert_to_tensor(['alpha', 'beta', 'gamma', 'delta'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(
         res,
         np.array([[[2.0], [0.0], [0.0], [0.0]], [[0.0], [6.0], [0.0],
                                                  [0.0]],
                   [[5.0], [0.0], [0.0], [0.0]], [[0.0], [0.0], [8.0],
                                                  [0.0]],
                   [[0.0], [0.0], [0.0], [9.0]]]))
Beispiel #17
0
 def test_many_values(self):
     """Ensure that padding with few symbols and many values works."""
     bit = cirq.GridQubit(0, 0)
     circuits = [
         cirq.Circuit(
             cirq.X(bit)**(sympy.Symbol('alpha') * 2.0),
             cirq.Y(bit)**(sympy.Symbol('alpha') * 3.0),
             cirq.Z(bit)**(sympy.Symbol('alpha')),
             cirq.X(bit)**(sympy.Symbol('alpha') * 4.0)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('alpha') * 9.0)),
         cirq.Circuit(cirq.X(bit)**sympy.Symbol('beta'))
     ]
     inputs = util.convert_to_tensor(circuits)
     symbols = tf.convert_to_tensor(['alpha', 'beta'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(
         res,
         np.array([[[2.0, 3.0, 1.0, 4.0], [0.0, 0.0, 0.0, 0.0]],
                   [[9.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]],
                   [[0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0]]]))
Beispiel #18
0
    def test_calculate_unitary_consistency(self, n_qubits):
        """Test that calculate_unitary works with symbols."""
        qubits = cirq.GridQubit.rect(1, n_qubits)
        symbols = ['alpha', 'beta', 'gamma']
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(qubits, symbols, 25)

        values = np.empty((len(circuit_batch), len(symbols)))
        for i in range(len(circuit_batch)):
            for j in range(len(symbols)):
                values[i][j] = resolver_batch[i][symbols[j]]

        tfq_results = tfq_unitary_op.calculate_unitary(
            util.convert_to_tensor(circuit_batch), symbols, values)

        results = []
        for circuit, resolver in zip(circuit_batch, resolver_batch):
            resolved_circuit = cirq.resolve_parameters(circuit, resolver)
            results.append(cirq.unitary(resolved_circuit))

        self.assertAllClose(tfq_results, results, atol=1e-5)
Beispiel #19
0
    def test_simulate_state_with_symbols(self, op_and_sim, n_qubits,
                                         symbol_names):
        """Compute states using cirq and tfq with symbols."""
        op = op_and_sim[0]
        sim = op_and_sim[1]

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

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

        op_states = op(util.convert_to_tensor(circuit_batch), symbol_names,
                       symbol_values_array).to_list()

        cirq_states = batch_util.batch_calculate_state(circuit_batch,
                                                       resolver_batch, sim)

        self.assertAllClose(cirq_states, op_states, atol=1e-5, rtol=1e-5)
Beispiel #20
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)
    def test_dnn_qnn_dnn(self, backend):
        """Train a fully hybrid network using an Expectation layer.

        Train the network to output +-5 given an input of 1 or 0. This tests
        that everything works when Expectation layer is a middle layers.
        """
        noisy = backend == 'noisy'
        bit = cirq.GridQubit(0, 0)
        symbols = sympy.symbols('x, y, z')
        circuits = util.convert_to_tensor(
            [_gen_single_bit_rotation_problem(bit, symbols, noisy)] * 2)
        data_in = np.array([[1], [0]], dtype=np.float32)
        data_out = np.array([[5], [-5]], dtype=np.float32)

        classical_input = tf.keras.Input(shape=(1,))
        circuit_input = tf.keras.Input(shape=(), dtype=tf.dtypes.string)
        d1 = tf.keras.layers.Dense(10)(classical_input)
        d2 = tf.keras.layers.Dense(3)(d1)
        reps = 1000 if noisy else None
        quantum = expectation.Expectation(backend=backend)(
            circuit_input,
            symbol_names=symbols,
            symbol_values=d2,
            operators=cirq.Z(bit),
            repetitions=reps)
        d3 = tf.keras.layers.Dense(1)(quantum)

        model = tf.keras.Model(inputs=[circuit_input, classical_input],
                               outputs=d3)

        model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.05),
                      loss=tf.keras.losses.mean_squared_error)
        history = model.fit(x=[circuits, data_in],
                            y=data_out,
                            batch_size=2,
                            epochs=300)
        tol = 5e-2 if noisy else 1e-3
        self.assertAllClose(history.history['loss'][-1], 0, atol=tol)
    def test_simple_param_value_input(self, backend):
        """Train a densely connected hybrid model.

        This model will put a qubit in the zero or one state from a random state
        given the input zero or one. This tests the input signature:
        Expectation([input_value_batch]).
        """
        noisy = backend == 'noisy'
        bit = cirq.GridQubit(0, 0)
        symbols = sympy.symbols('x y z')
        circuit = _gen_single_bit_rotation_problem(bit, symbols, noisy)

        inputs = tf.keras.Input(shape=(1,), dtype=tf.dtypes.float64)
        datum = tf.keras.Input(shape=(), dtype=tf.dtypes.string)
        l1 = tf.keras.layers.Dense(10)(inputs)
        l2 = tf.keras.layers.Dense(3)(l1)
        reps = 1000 if noisy else None
        outputs = expectation.Expectation(backend=backend)(
            datum,
            symbol_names=symbols,
            operators=cirq.Z(bit),
            symbol_values=l2,
            repetitions=reps)
        model = tf.keras.Model(inputs=[datum, inputs], outputs=outputs)

        data_in = np.array([[1], [0]], dtype=np.float32)
        data_out = np.array([[1], [-1]], dtype=np.float32)

        model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.05),
                      loss=tf.keras.losses.mean_squared_error)

        circuits = util.convert_to_tensor([circuit, circuit])

        history = model.fit(x=[circuits, data_in], y=data_out, epochs=100)
        tol = 5e-2 if noisy else 1e-3
        self.assertAllClose(history.history['loss'][-1], 0, atol=tol)
Beispiel #23
0
    def test_sampling_empty(self, op_and_sim, n_qubits, symbol_names):
        """Test empty circuits for sampling using cirq and tfq."""
        op = op_and_sim[0]
        sim = op_and_sim[1]
        qubits = cirq.GridQubit.rect(1, n_qubits)
        n_samples = int((2**n_qubits) * 1000)

        circuit_batch = [cirq.Circuit() for _ in range(BATCH_SIZE)]
        resolver_batch = [cirq.ParamResolver({}) for _ in range(BATCH_SIZE)]

        symbol_values_array = np.array([[0.0 for _ in symbol_names]
                                        for _ in resolver_batch])

        op_samples = np.array(
            op(util.convert_to_tensor(circuit_batch), symbol_names,
               symbol_values_array, [n_samples]).to_list())

        op_histograms = [
            np.histogram(
                sample.dot(1 << np.arange(sample.shape[-1] - 1, -1, -1)),
                range=(0, 2**len(qubits)),
                bins=2**len(qubits))[0] for sample in op_samples
        ]

        cirq_samples = batch_util.batch_sample(circuit_batch, resolver_batch,
                                               n_samples, sim)

        cirq_histograms = [
            np.histogram(
                sample.dot(1 << np.arange(sample.shape[-1] - 1, -1, -1)),
                range=(0, 2**len(qubits)),
                bins=2**len(qubits))[0] for sample in cirq_samples
        ]

        for a, b in zip(op_histograms, cirq_histograms):
            self.assertLess(stats.entropy(a + 1e-8, b + 1e-8), 0.005)
    def test_sampled_expectation_op_error(self):
        """Test that expectation errors within underlying ops correctly."""
        # Note the expected_regex is left blank here since there is a
        # discrepancy between the error strings provided between backends.
        bit = cirq.GridQubit(0, 0)
        symbol = sympy.Symbol('alpha')
        test_pstring = cirq.Z(bit)
        test_psum = cirq.PauliSum.from_pauli_strings([test_pstring])
        symb_circuit = cirq.Circuit(cirq.H(bit)**symbol)
        reg_circuit = cirq.Circuit(cirq.H(bit))

        with self.assertRaisesRegex(Exception, expected_regex="pauli_sums"):
            # Operators has wrong rank. Parse error.
            sampled_expectation.SampledExpectation()(
                [reg_circuit],
                operators=util.convert_to_tensor([test_psum]),
                repetitions=1)

        with self.assertRaisesRegex(Exception, expected_regex="symbol_values"):
            # symbol_values has wrong rank.
            sampled_expectation.SampledExpectation()([symb_circuit],
                                                     symbol_names=[symbol],
                                                     symbol_values=[0.5],
                                                     operators=test_psum,
                                                     repetitions=1)

        with self.assertRaisesRegex(
                Exception,
                expected_regex="Number of circuits and PauliSums do not match"
        ):
            # Wrong batch size for pauli operators.
            sampled_expectation.SampledExpectation()(symb_circuit,
                                                     symbol_names=[symbol],
                                                     operators=[[test_psum],
                                                                [test_psum]],
                                                     repetitions=1)

        with self.assertRaisesRegex(
                Exception,
                expected_regex="Number of circuits and PauliSums do not match"
        ):
            # Wrong batch size for pauli operators.
            sampled_expectation.SampledExpectation()(reg_circuit,
                                                     operators=[[test_psum],
                                                                [test_psum]],
                                                     repetitions=1)

        with self.assertRaisesRegex(Exception,
                                    expected_regex="greater than 0"):
            # Wrong repetitions.
            sampled_expectation.SampledExpectation()(reg_circuit,
                                                     operators=test_psum,
                                                     repetitions=-1)

        with self.assertRaisesRegex(
                Exception,
                expected_regex="num_samples and pauli_sums do not match"):
            # Wrong second dimension size for repetitions & pauli operators.
            sampled_expectation.SampledExpectation()(reg_circuit,
                                                     operators=test_psum,
                                                     repetitions=[5, 4, 3])
Beispiel #25
0
    def __init__(
        self,
        model_circuit,
        operators,
        *,
        repetitions=None,
        backend='noiseless',
        differentiator=None,
        initializer=tf.keras.initializers.RandomUniform(0, 2 * np.pi),
        regularizer=None,
        constraint=None,
        **kwargs,
    ):
        """Instantiate this layer.

        Create a layer that will output expectation values of the given
        operators when fed quantum data to it's input layer. This layer will
        accept one input tensor representing a quantum data source (these
        circuits must not contain any symbols) and append the model_circuit to
        them, execute them and then finally output the expectation values.


        model_circuit: `cirq.Circuit` containing `sympy.Symbols` that will be
            used as the model which will be fed quantum data inputs.
        operators: `cirq.PauliSum` or Python `list` of `cirq.PauliSum` objects
            used as observables at the end of the model circuit.
        repetitions: Optional Python `int` indicating how many samples to use
            when estimating expectation values.  If `None` analytic expectation
            calculation is used.
        backend: Optional Backend to use to simulate states. Defaults to
            the noiseless TensorFlow simulator, however users may also
            specify a preconfigured cirq simulation object to use instead.
            If a cirq object is given it must inherit either
            `cirq.sim.simulator.SimulatesExpectationValues` if analytic
            expectations are desired or `cirq.Sampler` if sampled expectations
            are desired.
        differentiator: Optional `tfq.differentiator` object to specify how
            gradients of `model_circuit` should be calculated.
        initializer: Optional `tf.keras.initializer` object to specify how the
            symbols in `model_circuit` should be initialized when creating
            the managed variables.
        regularizer: Optional `tf.keras.regularizer` object applied to the
            managed variables parameterizing `model_circuit`.
        constraint: Optional `tf.keras.constraint` object applied to the
            managed variables parameterizing `model_circuit`.
        """
        super().__init__(**kwargs)

        # Ingest model_circuit.
        if not isinstance(model_circuit, cirq.Circuit):
            raise TypeError("model_circuit must be a cirq.Circuit object."
                            " Given: {}".format(model_circuit))

        self._symbols_list = list(
            sorted(util.get_circuit_symbols(model_circuit)))
        self._symbols = tf.constant([str(x) for x in self._symbols_list])

        self._model_circuit = util.convert_to_tensor([model_circuit])
        if len(self._symbols_list) == 0:
            raise ValueError("model_circuit has no sympy.Symbols. Please "
                             "provide a circuit that contains symbols so "
                             "that their values can be trained.")

        # Ingest operators.
        if isinstance(operators, (cirq.PauliString, cirq.PauliSum)):
            operators = [operators]
        if not isinstance(operators, (list, np.ndarray, tuple)):
            raise TypeError("operators must be a cirq.PauliSum or "
                            "cirq.PauliString, or a list, tuple, "
                            "or np.array containing them. "
                            "Got {}.".format(type(operators)))
        if not all([
                isinstance(op, (cirq.PauliString, cirq.PauliSum))
                for op in operators
        ]):
            raise TypeError("Each element in operators to measure "
                            "must be a cirq.PauliString"
                            " or cirq.PauliSum")
        self._operators = util.convert_to_tensor([operators])

        # Ingest and promote repetitions.
        self._analytic = False
        if repetitions is None:
            self._analytic = True
        if not self._analytic and not isinstance(repetitions,
                                                 numbers.Integral):
            raise TypeError("repetitions must be a positive integer value."
                            " Given: ".format(repetitions))
        if not self._analytic and repetitions <= 0:
            raise ValueError("Repetitions must be greater than zero.")
        if not self._analytic:
            self._repetitions = tf.constant(
                [[repetitions for _ in range(len(operators))]],
                dtype=tf.dtypes.int32)

        # Set backend and differentiator.
        if backend == 'noisy':
            raise ValueError("noisy backend value is not supported in "
                             "tfq.layers.PQC. Please use tfq.layers.NoisyPQC "
                             "instead.")

        not_default = backend is not 'noiseless'
        not_default &= backend is not None  # legacy backend=None support.
        if not isinstance(
                backend,
                cirq.Sampler) and repetitions is not None and not_default:
            raise TypeError("provided backend does not inherit cirq.Sampler "
                            "and repetitions!=None. Please provide a backend "
                            "that inherits cirq.Sampler or set "
                            "repetitions=None.")
        if not isinstance(backend,
                          cirq.sim.simulator.SimulatesExpectationValues
                          ) and repetitions is None and not_default:
            raise TypeError(
                "provided backend does not inherit "
                "cirq.sim.simulator.SimulatesExpectationValues and "
                "repetitions=None. Please provide a backend that "
                "inherits "
                "cirq.sim.simulator.SimulatesExpectationValues.")
        if self._analytic:
            self._executor = expectation.Expectation(
                backend=backend, differentiator=differentiator)
        else:
            self._executor = sampled_expectation.SampledExpectation(
                backend=backend, differentiator=differentiator)

        self._append_layer = elementary.AddCircuit()

        # Set additional parameter controls.
        self.initializer = tf.keras.initializers.get(initializer)
        self.regularizer = tf.keras.regularizers.get(regularizer)
        self.constraint = tf.keras.constraints.get(constraint)

        # Weight creation is not placed in a Build function because the number
        # of weights is independent of the input shape.
        self.parameters = self.add_weight('parameters',
                                          shape=self._symbols.shape,
                                          initializer=self.initializer,
                                          regularizer=self.regularizer,
                                          constraint=self.constraint,
                                          dtype=tf.float32,
                                          trainable=True)
    def test_resolve_parameters_input_checking(self):
        """Check that the resolve parameters op has correct input checking."""
        n_qubits = 5
        batch_size = 5
        symbol_names = ['alpha']
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, batch_size)

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

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'must be rank 1'):
            # programs tensor has the wrong shape (too many dims).
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor([circuit_batch]), symbol_names,
                symbol_values_array)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'must be rank 1'):
            # programs tensor has the wrong shape (too few dims).
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch)[0], symbol_names,
                symbol_values_array)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'must be rank 1'):
            # symbol_names tensor has the wrong shape (too many dims).
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch),
                np.array([symbol_names]), symbol_values_array)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'must be rank 1'):
            # symbol_names tensor has the wrong shape (too few dims).
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch), symbol_names[0],
                symbol_values_array)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_values must be rank 2'):
            # symbol_values tensor has the wrong shape (too many dims).
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch), symbol_names,
                np.array([symbol_values_array]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_values must be rank 2'):
            # symbol_values tensor has the wrong shape (too few dims).
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array[0])

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Unparseable proto'):
            # programs tensor has the right type, but invalid value.
            tfq_utility_ops.resolve_parameters(['junk'] * batch_size,
                                               symbol_names,
                                               symbol_values_array)

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # programs tensor has the wrong type.
            tfq_utility_ops.resolve_parameters([1] * batch_size, symbol_names,
                                               symbol_values_array)

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # symbol_names tensor has the wrong type.
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch), [1],
                symbol_values_array)

        with self.assertRaisesRegex(tf.errors.UnimplementedError,
                                    'Cast string to float is not supported'):
            # symbol_values tensor has the wrong type.
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch), symbol_names,
                [['junk']] * batch_size)

        with self.assertRaisesRegex(TypeError, 'missing'):
            # too few tensors.
            # pylint: disable=no-value-for-parameter
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_batch), symbol_names)
Beispiel #27
0
    def test_simulate_samples_inputs(self):
        """Make sure the sample op fails gracefully on bad inputs."""
        n_qubits = 5
        batch_size = 5
        num_samples = 10
        symbol_names = ['alpha']
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, batch_size)

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

        with self.assertRaisesRegex(ValueError, 'rank 1 but is rank 2'):
            # programs tensor has the wrong shape.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor([circuit_batch]), symbol_names,
                symbol_values_array, [num_samples])

        with self.assertRaisesRegex(ValueError, 'rank 1 but is rank 2'):
            # symbol_names tensor has the wrong shape.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch),
                np.array([symbol_names]), symbol_values_array, [num_samples])

        with self.assertRaisesRegex(ValueError, 'rank 2 but is rank 3'):
            # symbol_values tensor has the wrong shape.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), symbol_names,
                np.array([symbol_values_array]), [num_samples])

        with self.assertRaisesRegex(ValueError, 'rank 2 but is rank 1'):
            # symbol_values tensor has the wrong shape 2.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array[0], [num_samples])

        with self.assertRaisesRegex(ValueError, 'rank 0 but is rank 1'):
            # num_samples tensor has the wrong shape.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array, [[num_samples]])

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Unparseable proto'):
            # programs tensor has the right type, but invalid value.
            tfq_simulate_ops.tfq_simulate_samples(['junk'] * batch_size,
                                                  symbol_names,
                                                  symbol_values_array,
                                                  [num_samples])

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Could not find symbol in parameter map'):
            # symbol_names tensor has the right type, but invalid value.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), ['junk'],
                symbol_values_array, [num_samples])

        with self.assertRaisesRegex(TypeError, 'Expected string'):
            # programs tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_samples([1] * batch_size,
                                                  symbol_names,
                                                  symbol_values_array,
                                                  [num_samples])

        with self.assertRaisesRegex(TypeError, 'Expected string'):
            # programs tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), [1],
                symbol_values_array, [num_samples])

        with self.assertRaisesRegex(tf.errors.UnimplementedError,
                                    'Cast string to float is not supported'):
            # programs tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), symbol_names,
                [['junk']] * batch_size, [num_samples])

        with self.assertRaisesRegex(Exception, 'not supported'):
            # num_samples tensor has the wrong shape.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array, ['junk'])

        with self.assertRaisesRegex(TypeError, 'missing'):
            # too few tensors.
            # pylint: disable=no-value-for-parameter
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array)
Beispiel #28
0
    def test_simulate_expectation_inputs(self):
        """Make sure the the expectation op fails gracefully on bad inputs."""
        n_qubits = 5
        batch_size = 5
        symbol_names = ['alpha']
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, batch_size)

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

        pauli_sums = util.random_pauli_sums(qubits, 3, batch_size)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'programs must be rank 1'):
            # Circuit tensor has too many dimensions.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor([circuit_batch]), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_names must be rank 1.'):
            # symbol_names tensor has too many dimensions.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch),
                np.array([symbol_names]), symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_values must be rank 2.'):
            # symbol_values_array tensor has too many dimensions.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                np.array([symbol_values_array]),
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_values must be rank 2.'):
            # symbol_values_array tensor has too few dimensions.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array[0],
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'pauli_sums must be rank 2.'):
            # pauli_sums tensor has too few dimensions.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([x for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'pauli_sums must be rank 2.'):
            # pauli_sums tensor has too many dimensions.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[[x]] for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Unparseable proto'):
            # circuit tensor has the right type but invalid values.
            tfq_simulate_ops.tfq_simulate_expectation(
                ['junk'] * batch_size, symbol_names, symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Could not find symbol in parameter map'):
            # symbol_names tensor has the right type but invalid values.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), ['junk'],
                symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'qubits not found in circuit'):
            # pauli_sums tensor has the right type but invalid values.
            new_qubits = [cirq.GridQubit(5, 5), cirq.GridQubit(9, 9)]
            new_pauli_sums = util.random_pauli_sums(new_qubits, 2, batch_size)
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in new_pauli_sums]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Unparseable proto'):
            # pauli_sums tensor has the right type but invalid values 2.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array, [['junk']] * batch_size)

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # circuits tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_expectation(
                [1.0] * batch_size, symbol_names, symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # symbol_names tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), [0.1234],
                symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(tf.errors.UnimplementedError, ''):
            # symbol_values tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                [['junk']] * batch_size,
                util.convert_to_tensor([[x] for x in pauli_sums]))

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # pauli_sums tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array, [[1.0]] * batch_size)

        with self.assertRaisesRegex(TypeError, 'missing'):
            # we are missing an argument.
            # pylint: disable=no-value-for-parameter
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array)
            # pylint: enable=no-value-for-parameter

        with self.assertRaisesRegex(TypeError, 'positional arguments'):
            # pylint: disable=too-many-function-args
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]), [])

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='do not match'):
            # wrong op size.
            tfq_simulate_ops.tfq_simulate_expectation(
                util.convert_to_tensor([cirq.Circuit()]), symbol_names,
                symbol_values_array.astype(np.float64),
                util.convert_to_tensor([[x] for x in pauli_sums]))

        res = tfq_simulate_ops.tfq_simulate_expectation(
            util.convert_to_tensor([cirq.Circuit() for _ in pauli_sums]),
            symbol_names, symbol_values_array.astype(np.float64),
            util.convert_to_tensor([[x] for x in pauli_sums]))
        self.assertDTypeEqual(res, np.float32)
Beispiel #29
0
    def test_simulate_state_inputs(self):
        """Make sure the state op fails gracefully on bad inputs."""
        n_qubits = 5
        batch_size = 5
        symbol_names = ['alpha']
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, batch_size)

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

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'programs must be rank 1'):
            # programs tensor has the wrong shape.
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor([circuit_batch]), symbol_names,
                symbol_values_array)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_names must be rank 1'):
            # symbol_names tensor has the wrong shape.
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor(circuit_batch),
                np.array([symbol_names]), symbol_values_array)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_values must be rank 2'):
            # symbol_values tensor has the wrong shape.
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor(circuit_batch), symbol_names,
                np.array([symbol_values_array]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_values must be rank 2'):
            # symbol_values tensor has the wrong shape 2.
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array[0])

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Unparseable proto'):
            # programs tensor has the right type, but invalid value.
            tfq_simulate_ops.tfq_simulate_state(['junk'] * batch_size,
                                                symbol_names,
                                                symbol_values_array)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Could not find symbol in parameter map'):
            # symbol_names tensor has the right type, but invalid value.
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor(circuit_batch), ['junk'],
                symbol_values_array)

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # programs tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_state([1] * batch_size, symbol_names,
                                                symbol_values_array)

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # symbol_names tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor(circuit_batch), [1],
                symbol_values_array)

        with self.assertRaisesRegex(tf.errors.UnimplementedError, ''):
            # symbol_values tensor has the wrong type.
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor(circuit_batch), symbol_names,
                [['junk']] * batch_size)

        with self.assertRaisesRegex(TypeError, 'missing'):
            # too few tensors.
            # pylint: disable=no-value-for-parameter
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor(circuit_batch), symbol_names)
            # pylint: enable=no-value-for-parameter

        # TODO (mbbrough): determine if we should allow extra arguments ?
        with self.assertRaisesRegex(TypeError, 'positional arguments'):
            # pylint: disable=too-many-function-args
            tfq_simulate_ops.tfq_simulate_state(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array, [])
    def test_inner_product_inputs(self):
        """Make sure that inner_product fails gracefully on bad inputs."""
        n_qubits = 5
        batch_size = 5
        symbol_names = ['alpha']
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, batch_size)

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

        other_batch = [
            util.random_circuit_resolver_batch(qubits, 3)[0]
            for i in range(batch_size)
        ]

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'programs must be rank 1'):
            # Circuit tensor has too many dimensions.
            inner_product_op.inner_product(
                util.convert_to_tensor([circuit_batch]), symbol_names,
                symbol_values_array, util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_names must be rank 1.'):
            # symbol_names tensor has too many dimensions.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch),
                np.array([symbol_names]), symbol_values_array,
                util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_values must be rank 2.'):
            # symbol_values_array tensor has too many dimensions.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                np.array([symbol_values_array]),
                util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'symbol_values must be rank 2.'):
            # symbol_values_array tensor has too few dimensions.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array[0], util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'other_programs must be rank 2.'):
            # other_programs tensor has too few dimensions.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array, util.convert_to_tensor(circuit_batch))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'other_programs must be rank 2.'):
            # pauli_sums tensor has too many dimensions.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in other_batch]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Unparseable proto'):
            # circuit tensor has the right type but invalid values.
            inner_product_op.inner_product(['junk'] * batch_size, symbol_names,
                                           symbol_values_array,
                                           util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'Could not find symbol in parameter map'):
            # symbol_names tensor has the right type but invalid values.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), ['junk'],
                symbol_values_array, util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'not found in reference circuit'):
            # other_programs tensor has the right type but operates on
            # qubits that the reference ciruit doesn't have.
            new_qubits = [cirq.GridQubit(5, 5), cirq.GridQubit(9, 9)]
            new_circuits, _ = util.random_circuit_resolver_batch(
                new_qubits, batch_size)
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in new_circuits]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'not found in paired circuit'):
            # other_programs tensor has the right type but operates on
            # qubits that the reference ciruit doesn't have.
            new_qubits = cirq.GridQubit.rect(1, n_qubits - 1)
            new_circuits, _ = util.random_circuit_resolver_batch(
                new_qubits, batch_size)
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in new_circuits]))

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # circuits tensor has the wrong type.
            inner_product_op.inner_product([1.0] * batch_size, symbol_names,
                                           symbol_values_array,
                                           util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # symbol_names tensor has the wrong type.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), [0.1234],
                symbol_values_array, util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(tf.errors.UnimplementedError, ''):
            # symbol_values tensor has the wrong type.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                [['junk']] * batch_size, util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(TypeError, 'Cannot convert'):
            # other_programs tensor has the wrong type.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array, [[1.0]] * batch_size)

        with self.assertRaisesRegex(TypeError, 'missing'):
            # we are missing an argument.
            # pylint: disable=no-value-for-parameter
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array)
            # pylint: enable=no-value-for-parameter

        with self.assertRaisesRegex(TypeError, 'positional arguments'):
            # pylint: disable=too-many-function-args
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array, util.convert_to_tensor(other_batch), [])

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='do not match'):
            # batch programs has wrong batch size.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor(other_batch[:int(batch_size * 0.5)]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='do not match'):
            # batch programs has wrong batch size.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array[::int(batch_size * 0.5)],
                util.convert_to_tensor(other_batch))

        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                expected_regex='Found symbols in other_programs'):
            # other_programs has symbols.
            inner_product_op.inner_product(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in circuit_batch]))

        res = inner_product_op.inner_product(
            util.convert_to_tensor(circuit_batch), symbol_names,
            symbol_values_array.astype(np.float64),
            util.convert_to_tensor(other_batch))
        self.assertDTypeEqual(res, np.complex64)