示例#1
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])
 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])
    def test_error(self):
        """Ensure that errors happen with bad inputs."""
        bit = cirq.GridQubit(0, 0)
        circuit = cirq.Circuit(cirq.X(bit)**(sympy.Symbol('alpha') * 2))
        inputs = util.convert_to_tensor([[circuit]])
        symbols = tf.convert_to_tensor(['test'])
        replacements = tf.convert_to_tensor(['nothing'])
        with self.assertRaisesRegex(Exception,
                                    expected_regex='rank 1. Got rank 2.'):
            tfq_ps_util_ops.tfq_ps_symbol_replace(inputs, symbols,
                                                  replacements)

        inputs = tf.convert_to_tensor(['junk'])
        with self.assertRaisesRegex(Exception,
                                    expected_regex='Unparseable proto:'):
            tfq_ps_util_ops.tfq_ps_symbol_replace(inputs, symbols,
                                                  replacements)

        inputs = util.convert_to_tensor([circuit])
        symbols = tf.convert_to_tensor([['test']])
        replacements = tf.convert_to_tensor(['nothing'])
        with self.assertRaisesRegex(Exception,
                                    expected_regex='rank 1. Got rank 2.'):
            tfq_ps_util_ops.tfq_ps_symbol_replace(inputs, symbols,
                                                  replacements)

        symbols = tf.convert_to_tensor(['test'])
        replacements = tf.convert_to_tensor([['nothing']])
        with self.assertRaisesRegex(Exception,
                                    expected_regex='rank 1. Got rank 2.'):
            tfq_ps_util_ops.tfq_ps_symbol_replace(inputs, symbols,
                                                  replacements)

        symbols = tf.convert_to_tensor(['test'])
        replacements = tf.convert_to_tensor(['nothing', 'too long'])
        with self.assertRaisesRegex(
                Exception,
                expected_regex=
                'symbols.shape is not equal to replacement_symbols.shape'):
            tfq_ps_util_ops.tfq_ps_symbol_replace(inputs, symbols,
                                                  replacements)
示例#4
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))
示例#5
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])
def parse_programs(programs,
                   symbol_names,
                   symbol_values,
                   n_symbols,
                   n_shifts=2):
    """Helper function to get parameter-shifted programs after parsing programs.


    It follows:
    1. Decomposes given programs with `tfq_ps_decompose` c++ op.
    2. Construct new_programs with parameter-shifted copies of decomposed
        programs by `tfq_ps_symbol_replace` c++ op.
    3. Weights and shifts are also obtained by `tfq_ps_weights_from_symbols`
    3. Transpose the results to fed them into TensorFlow Quantum simulator.

    Args:
        programs: `tf.Tensor` of strings with shape [n_programs] containing
            the string representations of the circuits to be executed.
        symbol_names: `tf.Tensor` of strings with shape [n_symbols], which
            is used to specify the order in which the values in
            `symbol_values` should be placed inside of the circuits in
            `programs`.
        symbol_values: `tf.Tensor` of real numbers with shape
            [n_programs, n_symbols] specifying parameter values to resolve
            into the circuits specified by programs, following the ordering
            dictated by `symbol_names`.
        n_symbols: `tf.Tensor` of a positive integer representing the number of
            symbols.
        n_shifts: `tf.Tensor` of a positive integer representing the number of
            parameter-shift terms. Defaults to 2.

    Returns:
        new_programs: the new programs whose program has only one gate with
            impurity parameter-shift symbol name.
            [n_symbols, n_programs, n_param_gates, n_shifts]
        weights: parameter-shift coefficients of estimated observables.
            [n_symbols, n_programs, n_param_gates, n_shifts]
        shifts: parameter-shifted values (= matrix of symbol_values +/-shift)
            [n_symbols, n_programs, n_param_gates, n_shifts]
        n_param_gates: bypass of input n_param_gates to export it outside
    """
    decomposed_programs = tfq_ps_util_ops.tfq_ps_decompose(programs)
    delta_eig = 2.0

    # Collecting doped programs with impurity sympy.Symbol from all programs
    # with parameterized gates.
    impurity = tf.tile(tf.convert_to_tensor([PARAMETER_IMPURITY_NAME]),
                       [n_symbols])
    symbols = tf.convert_to_tensor(symbol_names)

    # Doping impurity sympy.Symbol into programs per gate per symbol.
    new_programs = tf.tile(
        tf.expand_dims(tf.transpose(
            tfq_ps_util_ops.tfq_ps_symbol_replace(decomposed_programs, symbols,
                                                  impurity), [1, 0, 2]),
                       axis=-1), [1, 1, 1, n_shifts])
    n_param_gates = tf.cast(tf.gather(tf.shape(new_programs), 2),
                            dtype=tf.int32)

    # This is a tensor of the `exponent_scalar`s of the shifted gates.
    coeff = tf.expand_dims(tf.transpose(
        tfq_ps_util_ops.tfq_ps_weights_from_symbols(decomposed_programs,
                                                    symbols), [1, 0, 2]),
                           axis=-1)

    weights_plus = coeff * np.pi * 0.5 * 0.5 * delta_eig
    weights = tf.concat([weights_plus, -weights_plus], axis=-1)
    shifts_plus = tf.math.divide_no_nan(tf.math.divide(1.0, delta_eig), coeff)

    val = tf.tile(
        tf.expand_dims(tf.expand_dims(tf.transpose(symbol_values, [1, 0]),
                                      axis=-1),
                       axis=-1), [1, 1, n_param_gates, n_shifts])

    shifts = val + tf.concat([shifts_plus, -shifts_plus], axis=-1)

    return new_programs, weights, shifts, n_param_gates