Ejemplo n.º 1
0
    def test_error(self):
        """Ensure if a symbol can't be found the op errors."""
        bit = cirq.GridQubit(0, 0)
        circuit = cirq.Circuit(cirq.X(bit)**(sympy.Symbol('delta') * 2))
        inputs = util.convert_to_tensor([circuit])
        symbols = tf.convert_to_tensor(['alpha', 'delta'])
        tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
        symbols = tf.convert_to_tensor(['alpha'])
        with self.assertRaisesRegex(Exception, expected_regex='sympy.Symbol'):
            tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)

        symbols = tf.convert_to_tensor([['delta']])
        with self.assertRaisesRegex(Exception,
                                    expected_regex='rank 1. Got rank 2.'):
            tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)

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

        inputs = util.convert_to_tensor([[circuit]])
        with self.assertRaisesRegex(Exception,
                                    expected_regex='rank 1. Got rank 2.'):
            tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
Ejemplo n.º 2
0
 def test_out_of_order(self):
     """Test that discovery order of symbols in circuits doesn't matter."""
     bit = cirq.GridQubit(0, 0)
     circuit = cirq.Circuit(
         cirq.X(bit)**(sympy.Symbol('alpha') * 2),
         cirq.Y(bit)**(sympy.Symbol('beta') * 3))
     inputs = util.convert_to_tensor([circuit])
     symbols = tf.convert_to_tensor(['alpha', 'beta'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(res, np.array([[[2.0], [3.0]]]))
     symbols = tf.convert_to_tensor(['beta', 'alpha'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(res, np.array([[[3.0], [2.0]]]))
Ejemplo n.º 3
0
 def test_padding_with_non_parameterized_gates(self):
     """Ensure that the padding is correct in a complex example."""
     bit = cirq.GridQubit(0, 0)
     circuits = [
         cirq.Circuit(
             cirq.X(bit)**(sympy.Symbol('alpha') * 2.0),
             cirq.Y(bit)**3.0,
             cirq.Z(bit)**(sympy.Symbol('beta') * 4.0),
         ),
         cirq.Circuit(
             cirq.X(bit)**(sympy.Symbol('alpha') * 2.0),
             cirq.Y(bit)**(sympy.Symbol('beta') * 3.0),
             cirq.Z(bit)**4.0,
         ),
         cirq.Circuit(
             cirq.X(bit)**2.0,
             cirq.Y(bit)**(sympy.Symbol('beta') * 3.0),
             cirq.Z(bit)**(sympy.Symbol('gamma') * 4.0),
         )
     ]
     inputs = util.convert_to_tensor(circuits)
     symbols = tf.convert_to_tensor(['alpha', 'beta', 'gamma'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(
         res,
         np.array([[[2.0], [4.0], [0.0]], [[2.0], [3.0], [0.0]],
                   [[0.0], [3.0], [4.0]]]))
Ejemplo n.º 4
0
 def test_ignorance(self):
     """Test ignorance of ISP, PXP, FSIM gates."""
     circuit_batch = _complex_test_circuit()
     inputs = util.convert_to_tensor(circuit_batch)
     symbols = tf.convert_to_tensor(['r', 't'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     # Because there are no weights to be gathered, the last dimension = 0
     self.assertAllClose(tf.shape(res), [len(circuit_batch), 2, 0])
Ejemplo n.º 5
0
 def test_rotation_gates(self):
     """Test that rotation gates work."""
     bit = cirq.GridQubit(0, 0)
     circuit = cirq.Circuit(cirq.rx(sympy.Symbol('alpha') * 5.0)(bit))
     inputs = util.convert_to_tensor([circuit])
     symbols = tf.convert_to_tensor(['alpha'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(res, np.array([[[5.0 / np.pi]]]))
Ejemplo n.º 6
0
 def test_simple(self):
     """Ensure that weight extraction works."""
     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(['alpha'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(res, np.array([[[2.0]]]))
Ejemplo n.º 7
0
 def test_empty(self):
     """Test empty circuit. and symbol free circuit. does nothing."""
     bit = cirq.GridQubit(0, 0)
     circuit = cirq.Circuit(cirq.X(bit))
     circuit2 = cirq.Circuit()
     inputs = util.convert_to_tensor([circuit, circuit2])
     symbols = tf.convert_to_tensor(['alpha'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(res, np.array([[[]], [[]]]))
Ejemplo n.º 8
0
 def test_many_symbols(self):
     """Ensure that padding with few values and many symbols works."""
     bit = cirq.GridQubit(0, 0)
     circuits = [
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('alpha') * 2.0)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('beta') * 6)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('alpha') * 5.0)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('gamma') * 8)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('delta') * 9))
     ]
     inputs = util.convert_to_tensor(circuits)
     symbols = tf.convert_to_tensor(['alpha', 'beta', 'gamma', 'delta'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(
         res,
         np.array([[[2.0], [0.0], [0.0], [0.0]], [[0.0], [6.0], [0.0],
                                                  [0.0]],
                   [[5.0], [0.0], [0.0], [0.0]], [[0.0], [0.0], [8.0],
                                                  [0.0]],
                   [[0.0], [0.0], [0.0], [9.0]]]))
Ejemplo n.º 9
0
 def test_many_values(self):
     """Ensure that padding with few symbols and many values works."""
     bit = cirq.GridQubit(0, 0)
     circuits = [
         cirq.Circuit(
             cirq.X(bit)**(sympy.Symbol('alpha') * 2.0),
             cirq.Y(bit)**(sympy.Symbol('alpha') * 3.0),
             cirq.Z(bit)**(sympy.Symbol('alpha')),
             cirq.X(bit)**(sympy.Symbol('alpha') * 4.0)),
         cirq.Circuit(cirq.X(bit)**(sympy.Symbol('alpha') * 9.0)),
         cirq.Circuit(cirq.X(bit)**sympy.Symbol('beta'))
     ]
     inputs = util.convert_to_tensor(circuits)
     symbols = tf.convert_to_tensor(['alpha', 'beta'])
     res = tfq_ps_util_ops.tfq_ps_weights_from_symbols(inputs, symbols)
     self.assertAllClose(
         res,
         np.array([[[2.0, 3.0, 1.0, 4.0], [0.0, 0.0, 0.0, 0.0]],
                   [[9.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]],
                   [[0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0]]]))
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