def test_correctness_empty(self):
        """Tests the fidelity with empty circuits."""

        empty_circuit = util.convert_to_tensor([cirq.Circuit()])
        empty_symbols = tf.convert_to_tensor([], dtype=tf.dtypes.string)
        empty_values = tf.convert_to_tensor([[]])
        other_program = util.convert_to_tensor([[cirq.Circuit()]])

        out = fidelity_op.fidelity(empty_circuit, empty_symbols, empty_values,
                                   other_program)
        expected = np.array([[1.0]], dtype=np.complex64)
        self.assertAllClose(out, expected)
        self.assertDTypeEqual(out, tf.float32.as_numpy_dtype)

        qubit = cirq.GridQubit(0, 0)
        non_empty_circuit = util.convert_to_tensor(
            [cirq.Circuit(cirq.X(qubit))])
        empty_symbols = tf.convert_to_tensor([], dtype=tf.dtypes.string)
        empty_values = tf.convert_to_tensor([[]])
        other_program = util.convert_to_tensor([[cirq.Circuit()]])

        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'qubits not found'):
            fidelity_op.fidelity(non_empty_circuit, empty_symbols, empty_values,
                                 other_program)
    def test_tf_gradient_correctness_without_symbols(self, n_qubits, batch_size,
                                                     inner_dim_size):
        """Tests that tf.gradient of inner_product works without symbols."""
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, _ = \
            util.random_circuit_resolver_batch(
                qubits, batch_size)

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

        programs = util.convert_to_tensor(circuit_batch)
        other_programs = util.convert_to_tensor(other_batch)
        symbol_names = tf.convert_to_tensor([], dtype=tf.dtypes.string)
        symbol_values = tf.convert_to_tensor([[] for _ in range(batch_size)])

        with tf.GradientTape() as tape:
            tape.watch(symbol_values)
            ip = fidelity_op.fidelity(programs, symbol_names, symbol_values,
                                      other_programs)
        out = tape.gradient(ip, symbol_values)
        self.assertAllClose(out, tf.zeros_like(symbol_values), atol=1e-3)
        self.assertDTypeEqual(out, tf.float32.as_numpy_dtype)
    def test_tf_gradient_correctness_with_symbols(self, n_qubits, batch_size,
                                                  inner_dim_size):
        """Tests that tf.gradient of inner_product works with symbols."""
        symbol_names = ['alpha', 'beta', 'gamma']
        n_params = len(symbol_names)
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, resolver_batch = \
            util.random_symbol_circuit_resolver_batch(
                qubits, symbol_names, batch_size)

        other_batch = [0 for i in range(batch_size)]
        for i in range(len(other_batch)):
            other_batch[i] = copy.deepcopy(circuit_batch)
            for j in range(len(other_batch[i])):
                other_batch[i][j] = cirq.resolve_parameters(
                    circuit_batch[i], resolver_batch[i])

        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_tensor = tf.convert_to_tensor(symbol_names,
                                                   dtype=tf.dtypes.string)
        symbol_values = tf.convert_to_tensor(symbol_values_array)

        with tf.GradientTape() as tape:
            tape.watch(symbol_values)
            ip = fidelity_op.fidelity(programs, symbol_names_tensor,
                                      symbol_values, other_programs)
        out = tape.gradient(ip, symbol_values)

        out_arr = np.zeros((batch_size, n_params), dtype=np.complex64)
        # dx came from _GRAD_EPS of core/src/adj_util.cc
        dx = 5e-3
        for i in range(batch_size):
            for k, name in enumerate(symbol_names):
                if name in resolver_batch[i].param_dict:
                    new_resolver = copy.deepcopy(resolver_batch[i])
                    new_resolver.param_dict[name] += dx
                    final_circuit_p = cirq.resolve_parameters(
                        circuit_batch[i], new_resolver)
                    new_resolver = copy.deepcopy(resolver_batch[i])
                    new_resolver.param_dict[name] -= dx
                    final_circuit_m = cirq.resolve_parameters(
                        circuit_batch[i], new_resolver)
                    final_wf_p = cirq.final_state_vector(final_circuit_p)
                    final_wf_m = cirq.final_state_vector(final_circuit_m)
                    # Performs central finite difference.
                    for j in range(inner_dim_size):
                        internal_wf = cirq.final_state_vector(other_batch[i][j])
                        fid_p = cirq.fidelity(final_wf_p, internal_wf)
                        fid_m = cirq.fidelity(final_wf_m, internal_wf)
                        grad_fid = 0.5 * (fid_p - fid_m) / dx
                        out_arr[i][k] += grad_fid

        self.assertAllClose(out, out_arr, atol=1e-3)
        self.assertDTypeEqual(out, tf.float32.as_numpy_dtype)
    def test_correctness_without_symbols(self, n_qubits, batch_size,
                                         inner_dim_size):
        """Tests that inner_product works without symbols."""
        qubits = cirq.GridQubit.rect(1, n_qubits)
        circuit_batch, _ = \
            util.random_circuit_resolver_batch(
                qubits, batch_size)

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

        programs = util.convert_to_tensor(circuit_batch)
        other_programs = util.convert_to_tensor(other_batch)
        symbol_names = tf.convert_to_tensor([], dtype=tf.dtypes.string)
        symbol_values = tf.convert_to_tensor([[] for _ in range(batch_size)])

        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_wf = cirq.final_state_vector(circuit_batch[i])
            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 #5
0
    def test_correctness_no_circuit(self):
        """Test the inner product between no circuits."""

        empty_circuit = tf.raw_ops.Empty(shape=(0, ), dtype=tf.string)
        empty_symbols = tf.raw_ops.Empty(shape=(0, ), dtype=tf.string)
        empty_values = tf.raw_ops.Empty(shape=(0, 0), dtype=tf.float32)
        other_program = tf.raw_ops.Empty(shape=(0, 0), dtype=tf.string)

        out = fidelity_op.fidelity(empty_circuit, empty_symbols, empty_values,
                                   other_program)
        self.assertShapeEqual(np.zeros((0, 0)), out)
    def test_tf_gradient_correctness_no_circuit(self):
        """Test the inner product grad between no circuits."""

        empty_circuit = tf.raw_ops.Empty(shape=(0,), dtype=tf.string)
        empty_symbols = tf.raw_ops.Empty(shape=(0,), dtype=tf.string)
        empty_values = tf.raw_ops.Empty(shape=(0, 0), dtype=tf.float32)
        other_program = tf.raw_ops.Empty(shape=(0, 0), dtype=tf.string)

        with tf.GradientTape() as tape:
            tape.watch(empty_values)
            out = fidelity_op.fidelity(empty_circuit, empty_symbols,
                                       empty_values, other_program)

        self.assertShapeEqual(np.zeros((0, 0)), out)
        self.assertDTypeEqual(out, tf.float32.as_numpy_dtype)
    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)