Example #1
0
    def test_from_tensor(self, item):
        """Check from_tensor assuming convert_to_tensor works."""

        item_nested_tensorized = util.convert_to_tensor([[item, item],
                                                         [item, item]])
        item_flat_tensorized = util.convert_to_tensor([item, item])
        item_nested_cycled = util.convert_to_tensor(
            util.from_tensor(item_nested_tensorized))

        self.assertAllEqual(item_nested_tensorized, item_nested_cycled)
        item_flat_cycled = util.convert_to_tensor(
            util.from_tensor(item_flat_tensorized))
        self.assertAllEqual(item_flat_tensorized, item_flat_cycled)
Example #2
0
 def test_from_tensor_errors(self):
     """test that from_tensor fails when it should."""
     with self.assertRaisesRegex(TypeError,
                                 expected_regex='Error decoding item'):
         util.from_tensor(
             tf.convert_to_tensor([
                 'bad',
                 serializer.serialize_circuit(
                     cirq.Circuit()).SerializeToString()
             ]))
     with self.assertRaisesRegex(TypeError,
                                 expected_regex='Error decoding item'):
         util.from_tensor(
             tf.convert_to_tensor([
                 serializer.serialize_circuit(
                     cirq.Circuit()).SerializeToString() + b'bad'
             ]))
     with self.assertRaisesRegex(TypeError, expected_regex='single type'):
         util.from_tensor(
             tf.convert_to_tensor([
                 serializer.serialize_circuit(
                     cirq.Circuit()).SerializeToString(),
                 serializer.serialize_paulisum(
                     cirq.X(BITS[0]) + cirq.Y(BITS[1])).SerializeToString()
             ]))
     with self.assertRaisesRegex(TypeError,
                                 expected_regex='received bad type'):
         util.from_tensor("junk")
 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.0),
         cirq.Y(bit)**(sympy.Symbol('alpha') * 3.0),
         cirq.Z(bit)**(sympy.Symbol('alpha') * 4.0),
     )
     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.0),
         cirq.Y(bit)**(sympy.Symbol('alpha') * 3.0),
         cirq.Z(bit)**(sympy.Symbol('alpha') * 4.0),
     )
     correct_01 = cirq.Circuit(
         cirq.X(bit)**(sympy.Symbol('alpha') * 2.0),
         cirq.Y(bit)**(sympy.Symbol('new') * 3.0),
         cirq.Z(bit)**(sympy.Symbol('alpha') * 4.0),
     )
     correct_02 = cirq.Circuit(
         cirq.X(bit)**(sympy.Symbol('alpha') * 2.0),
         cirq.Y(bit)**(sympy.Symbol('alpha') * 3.0),
         cirq.Z(bit)**(sympy.Symbol('new') * 4.0),
     )
     self.assertEqual(correct_00, output[0][0][0])
     self.assertEqual(correct_01, output[0][0][1])
     self.assertEqual(correct_02, output[0][0][2])
Example #4
0
 def test_simple_case(self):
     """Test trivial case."""
     bit = cirq.GridQubit(0, 0)
     circuit = cirq.Circuit(
         cirq.X(bit)**sympy.Symbol('alpha'),
         cirq.Y(bit)**sympy.Symbol('alpha'),
         cirq.Z(bit)**sympy.Symbol('alpha'),
     )
     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'),
         cirq.Y(bit)**sympy.Symbol('alpha'),
         cirq.Z(bit)**sympy.Symbol('alpha'),
     )
     correct_01 = cirq.Circuit(
         cirq.X(bit)**sympy.Symbol('alpha'),
         cirq.Y(bit)**sympy.Symbol('new'),
         cirq.Z(bit)**sympy.Symbol('alpha'),
     )
     correct_02 = cirq.Circuit(
         cirq.X(bit)**sympy.Symbol('alpha'),
         cirq.Y(bit)**sympy.Symbol('alpha'),
         cirq.Z(bit)**sympy.Symbol('new'),
     )
     self.assertEqual(correct_00, output[0][0][0])
     self.assertEqual(correct_01, output[0][0][1])
     self.assertEqual(correct_02, output[0][0][2])
Example #5
0
    def test_append_circuit(self, max_n_bits, symbols, n_circuits):
        """Generate a bunch of circuits of different lengths acting on different
        numbers of qubits and append them using our op, checking that results
        are consistant with the native cirq method.
        """
        base_circuits = []
        circuits_to_append = []
        qubits = cirq.GridQubit.rect(1, max_n_bits)
        other_qubits = cirq.GridQubit.rect(2, max_n_bits)

        base_circuits, _ = util.random_symbol_circuit_resolver_batch(
            qubits, symbols, n_circuits, include_scalars=False)

        circuits_to_append, _ = util.random_symbol_circuit_resolver_batch(
            other_qubits, symbols, n_circuits, include_scalars=False)

        serialized_base_circuits = util.convert_to_tensor(base_circuits)
        serialized_circuits_to_append = util.convert_to_tensor(
            circuits_to_append)

        tfq_results = tfq_utility_ops.append_circuit(
            serialized_base_circuits, serialized_circuits_to_append)

        tfq_results = util.from_tensor(tfq_results)
        cirq_results = [
            a + b for a, b in zip(base_circuits, circuits_to_append)
        ]
        self.assertAllEqual(util.convert_to_tensor(tfq_results),
                            util.convert_to_tensor(cirq_results))
Example #6
0
    def test_resolve_parameters_consistency_basic(self):
        """Compare tfq op to cirq resolving."""
        qubits = cirq.GridQubit.rect(1, 4)
        circuit = cirq.Circuit()
        symbols = []
        for n, q in enumerate(qubits):
            new_bit = sympy.Symbol("bit_{}".format(n))
            circuit += cirq.X(q)**new_bit
            symbols.append(new_bit)
        symbol_names = [str(s) for s in symbols]

        bitstring_list = [[0, 0, 0, 0], [0, 1, 0, 1], [1, 0, 1, 1]]
        circuit_list = []
        resolver_list = []
        for bitstring in bitstring_list:
            resolve_dict = {}
            for s, b in zip(symbols, bitstring):
                resolve_dict[s] = b
            resolver_list.append(cirq.ParamResolver(resolve_dict))
            circuit_list.append(circuit)

        test_resolved_circuits = util.from_tensor(
            tfq_utility_ops.resolve_parameters(
                util.convert_to_tensor(circuit_list), symbol_names,
                np.asarray(bitstring_list)))

        expected_resolved_circuits = []
        for circuit, resolver in zip(circuit_list, resolver_list):
            expected_resolved_circuits.append(
                cirq.resolve_parameters(circuit, resolver))

        for exp_c, test_c in zip(expected_resolved_circuits,
                                 test_resolved_circuits):
            self.assertAllEqual(exp_c, test_c)
Example #7
0
 def test_moment_preservation(self):
     """Test Moment-structure preservation."""
     t = sympy.Symbol('t')
     r = sympy.Symbol('r')
     qubits = cirq.GridQubit.rect(1, 6)
     circuit_batch = [
         cirq.Circuit(
             cirq.Moment([cirq.H(q) for q in qubits]),
             cirq.Moment([
                 cirq.X(qubits[4]),
                 cirq.PhasedXPowGate(phase_exponent=np.random.random() *
                                     t).on(qubits[5]),
                 cirq.ISwapPowGate(exponent=np.random.random() * t).on(
                     qubits[0], qubits[1]),
                 cirq.FSimGate(theta=np.random.random() * t,
                               phi=np.random.random() * r).on(
                                   qubits[2], qubits[3])
             ]), cirq.Moment([cirq.H(q) for q in qubits]))
     ]
     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()}
     self.assertAllClose(cirq.unitary(
         cirq.resolve_parameters(circuit_batch[0], rand_resolver)),
                         cirq.unitary(
                             cirq.resolve_parameters(decomposed_programs[0],
                                                     rand_resolver)),
                         atol=1e-5)
     # Check if the Moments are conserved.
     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)
Example #8
0
    def test_addcircuit_modify(self):
        """Test that a addcircuit layer correctly modifies input circuits."""
        bits = cirq.GridQubit.rect(1, 20)
        circuit_a = cirq.testing.random_circuit(bits, 10, 0.9,
                                                util.get_supported_gates())
        circuit_b = cirq.testing.random_circuit(bits, 10, 0.9,
                                                util.get_supported_gates())

        expected_append = util.convert_to_tensor([circuit_a + circuit_b])
        expected_prepend = util.convert_to_tensor([circuit_b + circuit_a])

        append_layer = elementary.AddCircuit()
        prepend_layer = elementary.AddCircuit()

        actual_append = util.convert_to_tensor(
            util.from_tensor(append_layer(circuit_a, append=circuit_b)))
        actual_prepend = util.convert_to_tensor(
            util.from_tensor(prepend_layer(circuit_a, prepend=circuit_b)))

        self.assertEqual(expected_append.numpy()[0], actual_append.numpy()[0])
        self.assertEqual(expected_prepend.numpy()[0],
                         actual_prepend.numpy()[0])
Example #9
0
 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_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)
Example #11
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)
    def _parse_pauli_sums(pauli_sums, n_programs, n_ops):
        """Helper function to parse given pauli sums to collect observable
        coefficients.
        Currently `cirq.PauliSum` is not subscriptable, which means it is not
        possible to construct a uniform-shape tensor whose elements are
        consistently matched to `cirq.PauliString` inside of given `PauliSum`
        because the order of `PauliString`'s can be different whenever accessed.
        So, the current version of _parse_pauli_sums only consider a `PauliSum`
        to be sampled, not a `PauliString`. The observable coefficients are then
        sum of the absolute value of coefficients of `PauliString`'s in the
        `PauliSum`.
        Args:
            pauli_sums : `tf.Tensor` of strings with shape [n_programs, n_ops]
                representing output observables for each program.
            n_programs: `tf.Tensor` of the number of programs.
            n_ops: `tf.Tensor` of the number of pauli sums.
        Returns:
            observable_coeff_: `tf.Tensor` of real numbers. This involves the
                coefficients of Pauli sum terms of the first PauliString.
                It is directly used to calculate probabilities.
                [n_programs, n_ops]
        """
        pauli_sums = util.from_tensor(pauli_sums)

        def get_pauli_sum_coeff(i):

            def get_i_pauli_sum_coeff(j):

                # Because PauliSum object is not subscriptable, use for-loop.
                # pauli_sums[i][j] : j-th `PauliSum` of i-th program.
                return tf.reduce_sum(
                    tf.abs([
                        pstring.coefficient.real for pstring in pauli_sums[i][j]
                    ]))

            return tf.map_fn(get_i_pauli_sum_coeff,
                             tf.range(n_ops),
                             dtype=tf.float32)

        observable_coeff = tf.map_fn(get_pauli_sum_coeff,
                                     tf.range(n_programs),
                                     dtype=tf.float32)

        return observable_coeff
    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))
Example #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))
Example #15
0
    def test_get_gradient_circuits(self):
        """Test that the correct objects are returned."""

        diff = parameter_shift.ParameterShift()

        # Circuits to differentiate.
        symbols = [sympy.Symbol("s0"), sympy.Symbol("s1")]
        q0 = cirq.GridQubit(0, 0)
        q1 = cirq.GridQubit(1, 2)
        input_programs = util.convert_to_tensor([
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**symbols[0],
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(cirq.Y(q1)**symbols[1]),
        ])
        input_symbol_names = tf.constant([str(s) for s in symbols])
        input_symbol_values = tf.constant([[1.5, -2.7], [-0.3, 0.9]])

        # First, for each symbol `s`, check how many times `s` appears in each
        # program `p`, `n_ps`. Let `n_param_gates` be the maximum of `n_ps` over
        # all symbols and programs. Then, the shape of `batch_programs` will be
        # [n_programs, n_symbols * n_param_gates * n_shifts], where `n_shifts`
        # is 2 because we decompose into gates with 2 eigenvalues. For row index
        # `p` we have for column indices between `i * n_param_gates * n_shifts`
        # and `(i + 1) * n_param_gates * n_shifts`, the first `n_pi * 2`
        # programs are parameter shifted versions of `input_programs[p]` and the
        # remaining programs are empty.
        # Here, `n_param_gates` is 2.
        impurity_symbol_name = "_impurity_for_param_shift"
        impurity_symbol = sympy.Symbol(impurity_symbol_name)
        expected_batch_programs_0 = util.convert_to_tensor([
            cirq.Circuit(
                cirq.X(q0)**impurity_symbol,
                cirq.Y(q0)**symbols[0],
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(
                cirq.X(q0)**impurity_symbol,
                cirq.Y(q0)**symbols[0],
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**impurity_symbol,
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**impurity_symbol,
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**symbols[0],
                cirq.ry(impurity_symbol)(q1)),
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**symbols[0],
                cirq.ry(impurity_symbol)(q1)),
            cirq.Circuit(),
            cirq.Circuit()
        ])
        expected_batch_programs_1 = util.convert_to_tensor([
            cirq.Circuit(),
            cirq.Circuit(),
            cirq.Circuit(),
            cirq.Circuit(),
            cirq.Circuit(cirq.Y(q1)**impurity_symbol),
            cirq.Circuit(cirq.Y(q1)**impurity_symbol),
            cirq.Circuit(),
            cirq.Circuit()
        ])
        expected_batch_programs = tf.stack(
            [expected_batch_programs_0, expected_batch_programs_1])

        # The new symbols are the old ones, with an extra used for shifting.
        expected_new_symbol_names = tf.concat(
            [input_symbol_names,
             tf.constant([impurity_symbol_name])], 0)

        # The batch symbol values are the input symbol values, tiled and with
        # shifted values appended. Locations that have empty programs should
        # also have zero for the shift.
        # The shifted values are the original value plus 1/2 divided by the
        # `exponent_scalar` of the gate.
        expected_batch_symbol_values = tf.constant(
            [[[1.5, -2.7, 1.5 + 0.5], [1.5, -2.7, 1.5 - 0.5],
              [1.5, -2.7, 1.5 + 0.5], [1.5, -2.7, 1.5 - 0.5],
              [1.5, -2.7, -2.7 + np.pi / 2], [1.5, -2.7, -2.7 - np.pi / 2],
              [1.5, -2.7, -2.7], [1.5, -2.7, -2.7]],
             [[-0.3, 0.9, -0.3], [-0.3, 0.9, -0.3], [-0.3, 0.9, -0.3],
              [-0.3, 0.9, -0.3], [-0.3, 0.9, 0.9 + 0.5],
              [-0.3, 0.9, 0.9 - 0.5], [-0.3, 0.9, 0.9], [-0.3, 0.9, 0.9]]])

        # Empty program locations are given zero weight.
        expected_batch_weights = tf.constant(
            [[[np.pi / 2, -np.pi / 2, np.pi / 2, -np.pi / 2],
              [0.5, -0.5, 0.0, 0.0]],
             [[0.0, 0.0, 0.0, 0.0], [np.pi / 2, -np.pi / 2, 0.0, 0.0]]])

        expected_batch_mapper = tf.constant([[[0, 1, 2, 3], [4, 5, 6, 7]],
                                             [[0, 1, 2, 3], [4, 5, 6, 7]]])

        (test_batch_programs, test_new_symbol_names, test_batch_symbol_values,
         test_batch_weights, test_batch_mapper) = diff.get_gradient_circuits(
             input_programs, input_symbol_names, input_symbol_values)
        for i in range(tf.shape(input_programs)[0]):
            self.assertAllEqual(util.from_tensor(expected_batch_programs[i]),
                                util.from_tensor(test_batch_programs[i]))
        self.assertAllEqual(expected_new_symbol_names, test_new_symbol_names)
        self.assertAllClose(expected_batch_symbol_values,
                            test_batch_symbol_values,
                            atol=1e-5)
        self.assertAllClose(expected_batch_weights,
                            test_batch_weights,
                            atol=1e-5)
        self.assertAllEqual(expected_batch_mapper, test_batch_mapper)
Example #16
0
    def test_complex_pad(self):
        """Test trickier padding."""
        bit = cirq.GridQubit(0, 0)
        bit2 = cirq.GridQubit(0, 1)
        circuit = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('alpha'),
            cirq.Y(bit)**sympy.Symbol('alpha'),
            cirq.Z(bit)**sympy.Symbol('alpha'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        circuit2 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('beta'),
            cirq.Y(bit)**sympy.Symbol('beta'),
            cirq.Z(bit)**sympy.Symbol('beta'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        circuit3 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('alpha'),
            cirq.Y(bit)**sympy.Symbol('alpha'),
            cirq.Z(bit)**sympy.Symbol('alpha'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        inputs = util.convert_to_tensor([circuit, circuit2, circuit3])
        symbols = tf.convert_to_tensor(['alpha', 'beta', 'gamma'])
        new = tf.convert_to_tensor(['new', 'old', 'nothing'])
        res = tfq_ps_util_ops.tfq_ps_symbol_replace(inputs, symbols, new)
        output = util.from_tensor(res)

        correct_000 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('new'),
            cirq.Y(bit)**sympy.Symbol('alpha'),
            cirq.Z(bit)**sympy.Symbol('alpha'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        correct_001 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('alpha'),
            cirq.Y(bit)**sympy.Symbol('new'),
            cirq.Z(bit)**sympy.Symbol('alpha'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        correct_002 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('alpha'),
            cirq.Y(bit)**sympy.Symbol('alpha'),
            cirq.Z(bit)**sympy.Symbol('new'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        correct_003 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('alpha'),
            cirq.Y(bit)**sympy.Symbol('alpha'),
            cirq.Z(bit)**sympy.Symbol('alpha'),
            cirq.XX(bit, bit2)**sympy.Symbol('new'))

        self.assertEqual(correct_000, output[0][0][0])
        self.assertEqual(correct_001, output[0][0][1])
        self.assertEqual(correct_002, output[0][0][2])
        self.assertEqual(correct_003, output[0][0][3])

        self.assertEqual(correct_000, output[2][0][0])
        self.assertEqual(correct_001, output[2][0][1])
        self.assertEqual(correct_002, output[2][0][2])
        self.assertEqual(correct_003, output[2][0][3])

        correct_110 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('old'),
            cirq.Y(bit)**sympy.Symbol('beta'),
            cirq.Z(bit)**sympy.Symbol('beta'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        correct_111 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('beta'),
            cirq.Y(bit)**sympy.Symbol('old'),
            cirq.Z(bit)**sympy.Symbol('beta'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        correct_112 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('beta'),
            cirq.Y(bit)**sympy.Symbol('beta'),
            cirq.Z(bit)**sympy.Symbol('old'),
            cirq.XX(bit, bit2)**sympy.Symbol('alpha'))
        correct_113 = cirq.Circuit()

        self.assertEqual(correct_110, output[1][1][0])
        self.assertEqual(correct_111, output[1][1][1])
        self.assertEqual(correct_112, output[1][1][2])
        self.assertEqual(correct_113, output[1][1][3])

        correct_100 = cirq.Circuit(
            cirq.X(bit)**sympy.Symbol('beta'),
            cirq.Y(bit)**sympy.Symbol('beta'),
            cirq.Z(bit)**sympy.Symbol('beta'),
            cirq.XX(bit, bit2)**sympy.Symbol('new'))
        correct_101 = cirq.Circuit()
        correct_102 = cirq.Circuit()
        correct_103 = cirq.Circuit()

        self.assertEqual(correct_100, output[1][0][0])
        self.assertEqual(correct_101, output[1][0][1])
        self.assertEqual(correct_102, output[1][0][2])
        self.assertEqual(correct_103, output[1][0][3])

        correct_220 = cirq.Circuit()
        correct_221 = cirq.Circuit()
        correct_222 = cirq.Circuit()
        correct_223 = cirq.Circuit()

        self.assertEqual(correct_220, output[2][2][0])
        self.assertEqual(correct_221, output[2][2][1])
        self.assertEqual(correct_222, output[2][2][2])
        self.assertEqual(correct_223, output[2][2][3])

        correct = cirq.Circuit()
        for i in range(3):
            for j in range(3):
                for k in range(3):
                    if i != j and (not (i == 2 and j == 0)) \
                        and (not (i == 1 and j == 0)):
                        self.assertEqual(correct, output[i][j][k])
Example #17
0
    def test_decompose_with_complex_circuit(self):
        """Test decompose with complex circuit."""
        names = ['CLAE', 'HRYV', 'IRKB', 'LKRV', 'PJOU', 'CJKX', 'NASW']
        # Test circuit has a Moment with 1) FSimGate & PhasedXPowGate,
        # 2) PhasedXPowGate & ISwapPowGate and 3) FSimGate & ISwapPowGate.
        # Be careful, they are not decomposed if not parameterized.
        circuit_batch = [
            cirq.Circuit([
                cirq.Moment(operations=[
                    cirq.FSimGate(theta=0.10338130973488413 *
                                  sympy.Symbol('CLAE'),
                                  phi=0.10338130973488413 *
                                  sympy.Symbol('IRKB')).
                    on(cirq.GridQubit(0, 2), cirq.GridQubit(0, 3)),
                    cirq.PhasedXPowGate(phase_exponent=1.0,
                                        exponent=0.86426029696045281 *
                                        sympy.Symbol('HRYV')).on(
                                            cirq.GridQubit(0, 1)),
                ]),
                cirq.Moment(operations=[
                    cirq.Y.on(cirq.GridQubit(0, 3)),
                    cirq.Z.on(cirq.GridQubit(0, 0)),
                    cirq.FSimGate(theta=1, phi=1).on(cirq.GridQubit(0, 1),
                                                     cirq.GridQubit(0, 2)),
                ]),
                cirq.Moment(operations=[
                    (cirq.CNOT**(0.92874230274398684 * sympy.Symbol('IRKB'))
                    ).on(cirq.GridQubit(0, 1), cirq.GridQubit(0, 2)),
                ]),
                cirq.Moment(operations=[
                    cirq.PhasedXPowGate(phase_exponent=sympy.Symbol('PJOU'),
                                        exponent=0.2081415255258906 *
                                        sympy.Symbol('LKRV')).on(
                                            cirq.GridQubit(0, 2)),
                    (cirq.ISWAP**(0.32860954996781722 * sympy.Symbol('PJOU'))
                    ).on(cirq.GridQubit(0, 1), cirq.GridQubit(0, 3)),
                ]),
                cirq.Moment(operations=[
                    cirq.PhasedXPowGate(phase_exponent=sympy.Symbol('CJKX')).on(
                        cirq.GridQubit(0, 1)),
                    cirq.ZZ.on(cirq.GridQubit(0, 0), cirq.GridQubit(0, 3)),
                    (cirq.X**(0.6826594585474709 *
                              sympy.Symbol('HRYV'))).on(cirq.GridQubit(0, 2)),
                ]),
                cirq.Moment(operations=[
                    (cirq.ZZ**(0.18781276022427218 * sympy.Symbol('PJOU'))
                    ).on(cirq.GridQubit(0, 0), cirq.GridQubit(0, 3)),
                ]),
                cirq.Moment(operations=[
                    cirq.Y.on(cirq.GridQubit(0, 0)),
                ]),
                cirq.Moment(operations=[
                    cirq.FSimGate(theta=0.13793763138552417 *
                                  sympy.Symbol('CJKX'),
                                  phi=0.13793763138552417 *
                                  sympy.Symbol('PJOU')).
                    on(cirq.GridQubit(0, 2), cirq.GridQubit(0, 3)),
                    (cirq.ISWAP**(0.028165738453673095 * sympy.Symbol('NASW'))
                    ).on(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)),
                ]),
                cirq.Moment(operations=[
                    cirq.FSimGate(theta=0.74356520426349459 *
                                  sympy.Symbol('CJKX'),
                                  phi=0.74356520426349459 *
                                  sympy.Symbol('NASW')).
                    on(cirq.GridQubit(0, 3), cirq.GridQubit(0, 0)),
                ]),
                cirq.Moment(operations=[
                    cirq.CNOT.on(cirq.GridQubit(0, 0), cirq.GridQubit(0, 2)),
                    cirq.SWAP.on(cirq.GridQubit(0, 3), cirq.GridQubit(0, 1)),
                ]),
                cirq.Moment(operations=[
                    cirq.H.on(cirq.GridQubit(0, 3)),
                    cirq.H.on(cirq.GridQubit(0, 2)),
                    cirq.CNOT.on(cirq.GridQubit(0, 1), cirq.GridQubit(0, 0)),
                ]),
                cirq.Moment(operations=[
                    cirq.CNOT.on(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)),
                    cirq.YY.on(cirq.GridQubit(0, 2), cirq.GridQubit(0, 3)),
                ]),
                cirq.Moment(operations=[
                    cirq.CZ.on(cirq.GridQubit(0, 1), cirq.GridQubit(0, 0)),
                    cirq.CNOT.on(cirq.GridQubit(0, 2), cirq.GridQubit(0, 3)),
                ]),
                cirq.Moment(operations=[
                    cirq.FSimGate(theta=1, phi=1).on(cirq.GridQubit(0, 0),
                                                     cirq.GridQubit(0, 2)),
                    cirq.CNOT.on(cirq.GridQubit(0, 3), cirq.GridQubit(0, 1)),
                ]),
                cirq.Moment(operations=[
                    cirq.FSimGate(theta=1, phi=1).on(cirq.GridQubit(0, 0),
                                                     cirq.GridQubit(0, 3)),
                    cirq.SWAP.on(cirq.GridQubit(0, 2), cirq.GridQubit(0, 1)),
                ]),
                cirq.Moment(operations=[
                    cirq.Y.on(cirq.GridQubit(0, 0)),
                    cirq.PhasedXPowGate(
                        phase_exponent=1.0).on(cirq.GridQubit(0, 2)),
                    cirq.FSimGate(theta=1, phi=1).on(cirq.GridQubit(0, 1),
                                                     cirq.GridQubit(0, 3)),
                ]),
            ])
        ]

        # Decompose programs.
        inputs = util.convert_to_tensor(circuit_batch)
        outputs = tfq_ps_util_ops.tfq_ps_decompose(inputs)
        decomposed_programs = util.from_tensor(outputs)
        self.assertEqual(len(decomposed_programs), len(circuit_batch))

        # Original programs has parameterized ISP, PXP, FSIM, but this result
        # has no such gates at all. All parameterized gates have at most two
        # eigenvalues. There are still ISwap and PhasedX(1.0) because they are
        # not parameterized, which doesn't affect ParameterShift differentiation
        # at all.
        for program in decomposed_programs:
            for moment in program:
                for gate_op in moment:
                    # Consider parameterized gates only
                    if cirq.is_parameterized(gate_op.gate):
                        # Check I. The gate should have _eigen_components.
                        self.assertTrue(
                            hasattr(gate_op.gate, '_eigen_components'))
                        # Check II. The gate should have two eigen values.
                        self.assertEqual(len(gate_op.gate._eigen_components()),
                                         2, gate_op.gate)
        # 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 = {name: np.random.random() for name in names}
        self.assertAllClose(cirq.unitary(
            cirq.resolve_parameters(circuit_batch[0], rand_resolver)),
                            cirq.unitary(
                                cirq.resolve_parameters(decomposed_programs[0],
                                                        rand_resolver)),
                            atol=1e-5)
Example #18
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)))