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

        # 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))
    def test_correctness_with_symbols(self, n_qubits, batch_size,
                                      inner_dim_size):
        """Tests that inner_product works with symbols."""
        symbol_names = ['alpha', 'beta', 'gamma']
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, batch_size)

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

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

        programs = util.convert_to_tensor(circuit_batch)
        other_programs = util.convert_to_tensor(other_batch)
        symbol_names = tf.convert_to_tensor(symbol_names,
                                            dtype=tf.dtypes.string)
        symbol_values = tf.convert_to_tensor(symbol_values_array)

        out = fidelity_op.fidelity(programs, symbol_names, symbol_values,
                                   other_programs)

        out_arr = np.empty((batch_size, inner_dim_size), dtype=np.complex64)
        for i in range(batch_size):
            final_circuit = cirq.resolve_parameters(circuit_batch[i],
                                                    resolver_batch[i])
            final_wf = cirq.final_state_vector(final_circuit)
            for j in range(inner_dim_size):
                internal_wf = cirq.final_state_vector(other_batch[i][j])
                out_arr[i][j] = np.abs(np.vdot(final_wf, internal_wf))**2

        self.assertAllClose(out, out_arr, atol=1e-5)
        self.assertDTypeEqual(out, tf.float32.as_numpy_dtype)
Exemple #4
0
    def test_calculate_unitary_consistency(self, n_qubits, unitary_op):
        """Test that calculate_unitary works with symbols."""
        unitary_op = tfq_unitary_op.get_unitary_op()
        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 = unitary_op(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)
    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)
Exemple #6
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)
Exemple #7
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)
Exemple #8
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)
Exemple #10
0
    def test_noisy_expectation_inputs(self):
        """Make sure noisy 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, include_channels=True)

        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)
        num_samples = [[10]] * batch_size

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

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

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

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

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'pauli_sums must be rank 2.'):
            # pauli_sums tensor has too few dimensions.
            noisy_sampled_expectation_op.sampled_expectation(
                util.convert_to_tensor(circuit_batch),
                symbol_names, symbol_values_array,
                util.convert_to_tensor(list(pauli_sums)), num_samples)

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

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'num_samples must be rank 2'):
            # num_samples tensor has the wrong shape.
            noisy_sampled_expectation_op.sampled_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]),
                [num_samples])

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'num_samples must be rank 2'):
            # num_samples tensor has the wrong shape.
            noisy_sampled_expectation_op.sampled_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]),
                num_samples[0])

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

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

        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)
            noisy_sampled_expectation_op.sampled_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in new_pauli_sums]),
                num_samples)

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

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

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

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

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

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

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

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='do not match'):
            # wrong op size.
            noisy_sampled_expectation_op.sampled_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]), num_samples)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'greater than 0'):
            # pylint: disable=too-many-function-args
            noisy_sampled_expectation_op.sampled_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array,
                util.convert_to_tensor([[x] for x in pauli_sums]),
                [[-1]] * batch_size)
            # pylint: enable=too-many-function-args

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='do not match'):
            # wrong symbol_values size.
            noisy_sampled_expectation_op.sampled_expectation(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array[:int(batch_size * 0.5)],
                util.convert_to_tensor([[x] for x in pauli_sums]), num_samples)
    def test_adj_grad_inputs(self):
        """Make sure that 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)
        upstream_grads = np.ones((batch_size, len(symbol_names)))

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

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

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

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

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

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

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

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

        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_adj_grad_op.tfq_adj_grad(
                util.convert_to_tensor(circuit_batch), symbol_names,
                tf.convert_to_tensor(symbol_values_array),
                util.convert_to_tensor([[x] for x in new_pauli_sums]),
                tf.convert_to_tensor(upstream_grads))

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

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

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

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

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

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

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

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

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='rank 2'):
            # wrong grad shape.
            tfq_adj_grad_op.tfq_adj_grad(
                util.convert_to_tensor(circuit_batch), symbol_names,
                tf.convert_to_tensor(symbol_values_array),
                util.convert_to_tensor([[x] for x in pauli_sums]),
                tf.convert_to_tensor([upstream_grads]))

        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                expected_regex='gradients and circuits do not match'):
            # wrong grad batch size.
            tfq_adj_grad_op.tfq_adj_grad(
                util.convert_to_tensor(circuit_batch), symbol_names,
                tf.convert_to_tensor(symbol_values_array),
                util.convert_to_tensor([[x] for x in pauli_sums]),
                tf.convert_to_tensor([[0 for i in range(len(symbol_names))]]))

        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                expected_regex='gradients and pauli sum dimension do not match'
        ):
            # wrong grad inner size.
            tfq_adj_grad_op.tfq_adj_grad(
                util.convert_to_tensor(circuit_batch), symbol_names,
                tf.convert_to_tensor(symbol_values_array),
                util.convert_to_tensor([[x] for x in pauli_sums]),
                tf.convert_to_tensor([[0, 0]
                                      for _ in range(len(circuit_batch))]))

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='cirq.Channel'):
            # attempting to use noisy circuit.
            noisy_circuit = cirq.Circuit(cirq.depolarize(0.3).on_each(*qubits))
            tfq_adj_grad_op.tfq_adj_grad(
                util.convert_to_tensor([noisy_circuit for _ in circuit_batch]),
                symbol_names, tf.convert_to_tensor(symbol_values_array),
                util.convert_to_tensor([[x] for x in pauli_sums]),
                tf.convert_to_tensor(upstream_grads))
Exemple #12
0
def _get_mixed_batch(qubits, symbols, size):
    circuit1, resolver1 = util.random_circuit_resolver_batch(qubits, size // 2)
    circuit2, resolver2 = util.random_symbol_circuit_resolver_batch(
        qubits, symbols, size // 2)
    return circuit1 + circuit2, resolver1 + resolver2
Exemple #13
0
    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)

        # 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):
                    tg = test_o.gate
                    eg = exp_o.gate
                    self.assertEqual(type(tg), type(eg))
                    # TODO(zaqqwerty): simplify parsing when cirq build parser
                    # see core/serialize/serializer.py
                    if isinstance(tg, cirq.IdentityGate):
                        # all identity gates are the same
                        continue
                    elif isinstance(tg, cirq.EigenGate):
                        self._compare_gate_parameters(tg._global_shift,
                                                      eg._global_shift)
                        self._compare_gate_parameters(tg._exponent,
                                                      eg._exponent)
                    elif isinstance(tg, cirq.FSimGate):
                        self._compare_gate_parameters(tg.theta, eg.theta)
                        self._compare_gate_parameters(tg.phi, eg.phi)
                    elif isinstance(
                            tg, (cirq.PhasedXPowGate, cirq.PhasedISwapPowGate)):
                        self._compare_gate_parameters(tg._global_shift,
                                                      eg._global_shift)
                        self._compare_gate_parameters(tg._exponent,
                                                      eg._exponent)
                        self._compare_gate_parameters(tg._phase_exponent,
                                                      eg._phase_exponent)
                    else:
                        self.assertTrue(False,
                                        msg="Some gate in the randomizer "
                                        "is not being checked: "
                                        "{}".format(type(tg)))
Exemple #14
0
    def gradients_vs_cirq_finite_difference(self, differentiator, op, n_qubits,
                                            n_programs, n_ops, symbol_names,
                                            stochastic_cost_eps):
        """Compare TFQ differentiators to fine-grained noiseless cirq finite
        differencing with a larger margin of error."""

        # TODO (jaeyoo): cleanup this hacky wordkaround so variable
        #   assignment doesn't need to take place like this.
        differentiator.stochastic_cost, eps = stochastic_cost_eps
        differentiator.refresh()
        op = differentiator.generate_differentiable_op(analytic_op=op)

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

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

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

        # calculate tfq gradient
        symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
        programs = util.convert_to_tensor(circuit_batch)
        ops = util.convert_to_tensor(psums)

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

        def _get_gradient():
            with tf.GradientTape() as g:
                g.watch(symbol_values_tensor)
                expectations = op(programs, tf.convert_to_tesor(symbol_names),
                                  symbol_values_tensor, ops)
            return g.gradient(expectations, symbol_values_tensor)

        def _abs_diff(grad, mask):
            return np.sum(np.abs(grad - cirq_grads * mask))

        def _get_nonzero_mask(grad):
            return (grad.numpy() != 0.0).astype(np.float32)

        # Get the non-zero mask because a few initial gradients have not sampled
        # zero values.
        tfq_grads_1 = _get_gradient()
        mask_1 = _get_nonzero_mask(tfq_grads_1)

        if not np.allclose(tfq_grads_1, cirq_grads * mask_1, atol=eps):
            tfq_grads_2 = 0.5 * (tfq_grads_1 + _get_gradient())
            mask_2 = _get_nonzero_mask(tfq_grads_2)
            # Check if the 2nd error becomes smaller that 1st one.
            if not _abs_diff(tfq_grads_1, mask_1) > _abs_diff(
                    tfq_grads_2, mask_2):
                cnt = 2
                tfq_grads = (cnt * tfq_grads_2 + _get_gradient()) / (cnt + 1)
                while (cnt < 10
                       and not np.allclose(cirq_grads, tfq_grads, atol=eps)):
                    cnt += 1
                    tfq_grads = (cnt * tfq_grads + _get_gradient()) / (cnt + 1)
                self.assertAllClose(cirq_grads, tfq_grads, atol=eps)
Exemple #15
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(tf.errors.InvalidArgumentError,
                                    'rank 1. Got 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(tf.errors.InvalidArgumentError,
                                    'rank 1. Got 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(tf.errors.InvalidArgumentError,
                                    'rank 2. Got 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(tf.errors.InvalidArgumentError,
                                    'rank 2. Got 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(tf.errors.InvalidArgumentError,
                                    'rank 1. Got rank 2'):
            # 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, 'Cannot convert'):
            # 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, 'Cannot convert'):
            # 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, 'junk'):
            # 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)
            # pylint: enable=no-value-for-parameter

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='do not match'):
            # wrong symbol_values size.
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor(circuit_batch), symbol_names,
                symbol_values_array[:int(batch_size * 0.5)], num_samples)

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    expected_regex='cirq.Channel'):
            # attempting to use noisy circuit.
            noisy_circuit = cirq.Circuit(cirq.depolarize(0.3).on_each(*qubits))
            tfq_simulate_ops.tfq_simulate_samples(
                util.convert_to_tensor([noisy_circuit for _ in circuit_batch]),
                symbol_names, symbol_values_array, [num_samples])
    def test_gradients_vs_cirq_finite_difference(self, differentiator_num_runs,
                                                 n_qubits, n_programs, n_ops,
                                                 symbol_names, eps):
        """Convergence tests on SGDifferentiator variants."""

        # TODO(trevormccrt): remove this once I build the user-facing op
        #  interface
        differentiator, num_runs = differentiator_num_runs
        differentiator.refresh()
        op = differentiator.generate_differentiable_op(
            analytic_op=tfq_simulate_ops.tfq_simulate_expectation)

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

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

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

        # calculate tfq gradient
        symbol_values_tensor = tf.convert_to_tensor(symbol_values_array)
        programs = util.convert_to_tensor(circuit_batch)
        ops = util.convert_to_tensor(psums)

        def _get_gradient():
            with tf.GradientTape() as g:
                g.watch(symbol_values_tensor)
                expectations = op(programs, symbol_names, symbol_values_tensor,
                                  ops)
            return tf.cast(g.gradient(expectations, symbol_values_tensor),
                           dtype=tf.float64)

        # warm-up & initialize tfq_grads.
        grads_sum = _get_gradient()
        tfq_grads = grads_sum

        # calculate gradients in cirq using a very simple forward differencing
        # scheme
        cirq_grads = _cirq_simple_finite_difference(circuit_batch,
                                                    resolver_batch,
                                                    symbol_names, psums)
        cnt = 1
        # Since self.assertAllClose() has more strict atol than that of
        # np.allclose(), it is required to set smaller value to np.allclose()
        total_time = 0
        while cnt < num_runs and (not np.allclose(
                tfq_grads, cirq_grads, atol=eps * 0.9)):
            cnt = cnt + 1
            s = time.time()
            grads_sum = grads_sum + _get_gradient()
            total_time += time.time() - s
            tfq_grads = grads_sum / cnt

        self.assertAllClose(cirq_grads, tfq_grads, atol=eps)
        print('Passed: count {}, total_time {} ({}sec/shot)'.format(
            cnt, total_time, total_time / cnt))