def test_expectation_type_inputs_error(self):
        """Test that expectation errors within Keras call."""

        bit = cirq.GridQubit(0, 0)
        test_pstring = cirq.Z(bit)
        test_psum = cirq.PauliSum.from_pauli_strings([test_pstring])
        reg_circuit = cirq.Circuit(cirq.H(bit))

        with self.assertRaisesRegex(Exception,
                                    expected_regex="Unknown initializer"):
            expectation.Expectation()(reg_circuit,
                                      operators=test_psum,
                                      initializer='junk')

        with self.assertRaisesRegex(Exception,
                                    expected_regex="repetitions not provided"):
            expectation.Expectation(backend='noisy')(reg_circuit,
                                                     operators=test_psum)

        with self.assertRaisesRegex(Exception,
                                    expected_regex="cannot be parsed"):
            expectation.Expectation(backend='noisy')(reg_circuit,
                                                     operators=test_psum,
                                                     repetitions='junk')

        with self.assertRaisesRegex(Exception, expected_regex="noiseless"):
            expectation.Expectation(backend='noiseless')(reg_circuit,
                                                         operators=test_psum,
                                                         repetitions=1)
Esempio n. 2
0
    def test_dnn_qnn_dnn(self):
        """Train a fully hybrid network using an Expectation layer.

        Train the network to output +-5 given an input of 1 or 0. This tests
        that everything works when Expectation layer is a middle layers.
        """
        bit = cirq.GridQubit(0, 0)
        symbols = sympy.symbols('x, y, z')
        circuits = util.convert_to_tensor(
            [_gen_single_bit_rotation_problem(bit, symbols)] * 2)
        data_in = np.array([[1], [0]], dtype=np.float32)
        data_out = np.array([[5], [-5]], dtype=np.float32)

        classical_input = tf.keras.Input(shape=(1, ))
        circuit_input = tf.keras.Input(shape=(), dtype=tf.dtypes.string)
        d1 = tf.keras.layers.Dense(10)(classical_input)
        d2 = tf.keras.layers.Dense(3)(d1)
        quantum = expectation.Expectation()(circuit_input,
                                            symbol_names=symbols,
                                            symbol_values=d2,
                                            operators=cirq.Z(bit))
        d3 = tf.keras.layers.Dense(1)(quantum)

        model = tf.keras.Model(inputs=[circuit_input, classical_input],
                               outputs=d3)

        model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.05),
                      loss=tf.keras.losses.mean_squared_error)
        history = model.fit(x=[circuits, data_in],
                            y=data_out,
                            batch_size=2,
                            epochs=300)
        self.assertAllClose(history.history['loss'][-1], 0, atol=1e-3)
Esempio n. 3
0
    def test_simple_param_value_input(self):
        """Train a densely connected hybrid model.

        This model will put a qubit in the zero or one state from a random state
        given the input zero or one. This tests the input signature:
        Expectation([input_value_batch]).
        """
        bit = cirq.GridQubit(0, 0)
        symbols = sympy.symbols('x y z')
        circuit = _gen_single_bit_rotation_problem(bit, symbols)

        inputs = tf.keras.Input(shape=(1, ), dtype=tf.dtypes.float64)
        datum = tf.keras.Input(shape=(), dtype=tf.dtypes.string)
        l1 = tf.keras.layers.Dense(10)(inputs)
        l2 = tf.keras.layers.Dense(3)(l1)
        outputs = expectation.Expectation()(datum,
                                            symbol_names=symbols,
                                            operators=cirq.Z(bit),
                                            symbol_values=l2)
        model = tf.keras.Model(inputs=[datum, inputs], outputs=outputs)

        data_in = np.array([[1], [0]], dtype=np.float32)
        data_out = np.array([[1], [-1]], dtype=np.float32)

        model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.05),
                      loss=tf.keras.losses.mean_squared_error)

        circuits = util.convert_to_tensor([circuit, circuit])

        history = model.fit(x=[circuits, data_in], y=data_out, epochs=100)
        self.assertAllClose(history.history['loss'][-1], 0, atol=1e-3)
Esempio n. 4
0
    def test_expectation_instantiate_error(self):
        """Test that Expectation errors with bad inputs."""
        class MySampler(cirq.Sampler):
            """Class to test sampler detection in Expectation."""
            def run_sweep(self):
                """do nothing."""
                return

        with self.assertRaisesRegex(TypeError,
                                    expected_regex="SampledExpectation"):
            expectation.Expectation(backend=MySampler())

        with self.assertRaisesRegex(
                TypeError, expected_regex="SimulatesFinalState or None"):
            expectation.Expectation(backend='junk')

        with self.assertRaisesRegex(
                TypeError,
                expected_regex="tfq.differentiators.Differentiator"):
            expectation.Expectation(differentiator='junk')
Esempio n. 5
0
    def test_expectation_op_error(self):
        """Test that expectation errors within underlying ops correctly."""

        bit = cirq.GridQubit(0, 0)
        symbol = sympy.Symbol('alpha')
        test_pstring = cirq.Z(bit)
        test_psum = cirq.PauliSum.from_pauli_strings([test_pstring])
        symb_circuit = cirq.Circuit(cirq.H(bit)**symbol)
        reg_circuit = cirq.Circuit(cirq.H(bit))

        with self.assertRaisesRegex(Exception,
                                    expected_regex="Could not find symbol"):
            # No symbol matchups.
            expectation.Expectation()([symb_circuit], operators=test_psum)

        with self.assertRaisesRegex(Exception,
                                    expected_regex="Unparseable proto"):
            # Proto is unparseable.
            expectation.Expectation()([reg_circuit],
                                      operators=tf.convert_to_tensor(
                                          [['bad_operator']]))

        with self.assertRaisesRegex(Exception, expected_regex="rank 2"):
            # Operators has wrong rank.
            expectation.Expectation()([reg_circuit],
                                      operators=util.convert_to_tensor(
                                          [test_psum]))

        with self.assertRaisesRegex(Exception, expected_regex="rank 2"):
            # symbol_values has wrong rank.
            expectation.Expectation()([symb_circuit],
                                      symbol_names=[symbol],
                                      symbol_values=[0.5],
                                      operators=test_psum)

        with self.assertRaisesRegex(Exception, expected_regex="do not match."):
            # Wrong batch size for pauli operators.
            expectation.Expectation()(symb_circuit,
                                      symbol_names=[symbol],
                                      operators=[[test_psum], [test_psum]])
Esempio n. 6
0
    def test_expectation_type_inputs_error(self):
        """Test that expectation errors within Keras call."""

        bit = cirq.GridQubit(0, 0)
        test_pstring = cirq.Z(bit)
        test_psum = cirq.PauliSum.from_pauli_strings([test_pstring])
        reg_circuit = cirq.Circuit(cirq.H(bit))

        with self.assertRaisesRegex(Exception,
                                    expected_regex="Unknown initializer"):
            expectation.Expectation()(reg_circuit,
                                      operators=test_psum,
                                      initializer='junk')
Esempio n. 7
0
    def test_expectation_type_inputs_error(self):
        """Test that expectation errors within Keras call."""

        bit = cirq.GridQubit(0, 0)
        symbol = sympy.Symbol('alpha')
        test_pstring = cirq.Z(bit)
        test_psum = cirq.PauliSum.from_pauli_strings([test_pstring])
        symb_circuit = cirq.Circuit(cirq.H(bit)**symbol)
        reg_circuit = cirq.Circuit(cirq.H(bit))

        with self.assertRaisesRegex(TypeError,
                                    expected_regex="string or sympy.Symbol"):
            expectation.Expectation()(symb_circuit,
                                      symbol_names=[symbol, 5.0],
                                      operators=test_psum)

        with self.assertRaisesRegex(ValueError,
                                    expected_regex="must be unique."):
            expectation.Expectation()(symb_circuit,
                                      symbol_names=[symbol, symbol],
                                      operators=test_psum)

        with self.assertRaisesRegex(TypeError,
                                    expected_regex="cannot be parsed"):
            expectation.Expectation()(symb_circuit,
                                      symbol_names='junk',
                                      operators=test_psum)

        with self.assertRaisesRegex(TypeError,
                                    expected_regex="cannot be parsed"):
            expectation.Expectation()(symb_circuit,
                                      symbol_names=[symbol],
                                      symbol_values='junk',
                                      operators=test_psum)

        with self.assertRaisesRegex(TypeError,
                                    expected_regex="cannot be parsed"):
            expectation.Expectation()('junk',
                                      symbol_names=[symbol],
                                      symbol_values=[[0.5]],
                                      operators=test_psum)

        with self.assertRaisesRegex(RuntimeError,
                                    expected_regex="operators not provided"):
            expectation.Expectation()(symb_circuit,
                                      symbol_names=[symbol],
                                      symbol_values=[[0.5]])

        with self.assertRaisesRegex(Exception,
                                    expected_regex="Unknown initializer"):
            expectation.Expectation()(reg_circuit,
                                      operators=test_psum,
                                      initializer='junk')
 def test_expectation_instantiate(self):
     """Test that Expectation instantiates correctly."""
     expectation.Expectation()
     expectation.Expectation(backend=None)
     expectation.Expectation(backend='noisy')
     expectation.Expectation(backend='noiseless')
     expectation.Expectation(backend=cirq.Simulator())
     expectation.Expectation(
         differentiator=linear_combination.ForwardDifference())
Esempio n. 9
0
 def test_expectation_simple_tf_train(self):
     """Train a layer using standard tf (not keras).
     This is a subtle test that will work since we don't use keras compile.
     """
     bit = cirq.GridQubit(0, 0)
     circuit = \
         cirq.Circuit(cirq.Rx(sympy.Symbol('theta'))(bit))
     op = cirq.Z(bit)
     layer = expectation.Expectation()
     optimizer = tf.optimizers.Adam(learning_rate=0.05)
     for _ in range(200):
         with tf.GradientTape() as tape:
             circuit_out = layer(circuit,
                                 symbol_names=['theta'],
                                 operators=op)
             mse = tf.square(tf.reduce_sum(tf.subtract(circuit_out, -1)))
         grads = tape.gradient(mse, layer.trainable_weights)
         optimizer.apply_gradients(zip(grads, layer.trainable_weights))
     self.assertAllClose(mse.numpy(), 0, atol=1e-3)
    def test_simple_op_and_param_input(self, backend):
        """Test a simple operator and parameter input.

        Train a NN to put a qubit in the z+ or x+ states based on a classical
        binary input. This tests the input signature:
        Expectation([value_batch, operator_batch]).
        """
        noisy = backend == 'noisy'
        bit = cirq.GridQubit(0, 0)
        symbols = sympy.symbols('x, y, z')
        ops = util.convert_to_tensor([[cirq.Z(bit)], [cirq.X(bit)]])
        circuits = util.convert_to_tensor(
            [_gen_single_bit_rotation_problem(bit, symbols, noisy)] * 2)
        data_in = np.array([[1], [0]])
        data_out = np.array([[1], [1]])

        data_inp = tf.keras.Input(shape=(1), dtype=tf.dtypes.float32)
        op_inp = tf.keras.Input(shape=(1,), dtype=tf.dtypes.string)
        circuit_inp = tf.keras.Input(shape=(), dtype=tf.dtypes.string)
        dense_1 = tf.keras.layers.Dense(10)(data_inp)
        dense_2 = tf.keras.layers.Dense(3)(dense_1)
        reps = 1000 if noisy else None
        circuit_output = expectation.Expectation(backend=backend)(
            circuit_inp,
            symbol_names=symbols,
            symbol_values=dense_2,
            operators=op_inp,
            repetitions=reps)

        functional_model = tf.keras.Model(
            inputs=[data_inp, op_inp, circuit_inp], outputs=[circuit_output])

        functional_model.compile(
            optimizer=tf.keras.optimizers.Adam(learning_rate=0.05),
            loss=tf.keras.losses.mean_squared_error)
        history = functional_model.fit(x=[data_in, ops, circuits],
                                       y=data_out,
                                       batch_size=2,
                                       epochs=100)
        tol = 5e-2 if noisy else 1e-3
        self.assertAllClose(history.history['loss'][-1], 0, atol=tol)
    def test_simple_op_input(self, backend):
        """Test a simple operator input

        Learn qubit in the z+ state using two different measurement operators.
        This tests input signature Expectation([operator_batch])
        """
        noisy = backend == 'noisy'
        bit = cirq.GridQubit(0, 0)
        symbols = sympy.symbols('x, y, z')

        circuits = util.convert_to_tensor(
            [_gen_single_bit_rotation_problem(bit, symbols, noisy)] * 2)

        data_out = tf.convert_to_tensor(np.array([[1], [1]]))
        ops = util.convert_to_tensor([[cirq.Z(bit)], [cirq.Z(bit)]])

        circuit_input = tf.keras.Input(shape=(), dtype=tf.dtypes.string)
        op_input = tf.keras.Input(shape=(1,), dtype=tf.dtypes.string)

        reps = 1000 if noisy else None
        output = expectation.Expectation(backend=backend)(
            circuit_input,
            symbol_names=symbols,
            operators=op_input,
            initializer=tf.keras.initializers.RandomNormal(),
            repetitions=reps)

        model = tf.keras.Model(inputs=[circuit_input, op_input], outputs=output)

        model.compile(
            optimizer=tf.keras.optimizers.Adam(learning_rate=0.05),
            loss=tf.keras.losses.mean_squared_error,
        )
        history = model.fit(x=[circuits, ops],
                            y=data_out,
                            batch_size=2,
                            epochs=200)
        tol = 5e-2 if noisy else 1e-3
        self.assertAllClose(history.history['loss'][-1], 0, atol=tol)
Esempio n. 12
0
    def test_static_cases(self):
        """Run inputs through in complex cases."""

        bit = cirq.GridQubit(0, 0)
        symbol = sympy.Symbol('alpha')
        test_pstring = cirq.Z(bit)
        test_psum = cirq.PauliSum.from_pauli_strings([test_pstring])
        symb_circuit = cirq.Circuit(cirq.H(bit)**symbol)
        reg_circuit = cirq.Circuit(cirq.H(bit))

        # Passing a 2d operators input requires a 1d circuit input.
        expectation.Expectation()([reg_circuit, reg_circuit],
                                  operators=[[test_psum, test_psum],
                                             [test_psum, test_psum]])

        # Passing 2d operators along with other inputs.
        expectation.Expectation()([symb_circuit, symb_circuit],
                                  symbol_names=[symbol],
                                  operators=[[test_psum, test_psum],
                                             [test_psum, test_psum]])
        expectation.Expectation()([symb_circuit, symb_circuit],
                                  symbol_names=[symbol],
                                  symbol_values=[[0.5], [0.8]],
                                  operators=[[test_psum, test_psum],
                                             [test_psum, test_psum]])

        # Ensure tiling up of circuits works as expected.
        expectation.Expectation()(reg_circuit, operators=test_psum)
        expectation.Expectation()(reg_circuit,
                                  operators=[test_psum, test_psum])

        # Ensure tiling up of symbol_values works as expected.
        expectation.Expectation()(symb_circuit,
                                  symbol_names=[symbol],
                                  symbol_values=[[0.5], [0.8]],
                                  operators=test_psum)
        expectation.Expectation()(symb_circuit,
                                  symbol_names=[symbol],
                                  symbol_values=[[0.5]],
                                  operators=test_psum)
Esempio n. 13
0
    def __init__(
        self,
        model_circuit,
        operators,
        *,
        repetitions=None,
        backend='noiseless',
        differentiator=None,
        initializer=tf.keras.initializers.RandomUniform(0, 2 * np.pi),
        regularizer=None,
        constraint=None,
        **kwargs,
    ):
        """Instantiate this layer.

        Create a layer that will output expectation values of the given
        operators when fed quantum data to it's input layer. This layer will
        accept one input tensor representing a quantum data source (these
        circuits must not contain any symbols) and append the model_circuit to
        them, execute them and then finally output the expectation values.


        model_circuit: `cirq.Circuit` containing `sympy.Symbols` that will be
            used as the model which will be fed quantum data inputs.
        operators: `cirq.PauliSum` or Python `list` of `cirq.PauliSum` objects
            used as observables at the end of the model circuit.
        repetitions: Optional Python `int` indicating how many samples to use
            when estimating expectation values.  If `None` analytic expectation
            calculation is used.
        backend: Optional Backend to use to simulate states. Defaults to
            the noiseless TensorFlow simulator, however users may also
            specify a preconfigured cirq simulation object to use instead.
            If a cirq object is given it must inherit either
            `cirq.sim.simulator.SimulatesExpectationValues` if analytic
            expectations are desired or `cirq.Sampler` if sampled expectations
            are desired.
        differentiator: Optional `tfq.differentiator` object to specify how
            gradients of `model_circuit` should be calculated.
        initializer: Optional `tf.keras.initializer` object to specify how the
            symbols in `model_circuit` should be initialized when creating
            the managed variables.
        regularizer: Optional `tf.keras.regularizer` object applied to the
            managed variables parameterizing `model_circuit`.
        constraint: Optional `tf.keras.constraint` object applied to the
            managed variables parameterizing `model_circuit`.
        """
        super().__init__(**kwargs)

        # Ingest model_circuit.
        if not isinstance(model_circuit, cirq.Circuit):
            raise TypeError("model_circuit must be a cirq.Circuit object."
                            " Given: {}".format(model_circuit))

        self._symbols_list = list(
            sorted(util.get_circuit_symbols(model_circuit)))
        self._symbols = tf.constant([str(x) for x in self._symbols_list])

        self._model_circuit = util.convert_to_tensor([model_circuit])
        if len(self._symbols_list) == 0:
            raise ValueError("model_circuit has no sympy.Symbols. Please "
                             "provide a circuit that contains symbols so "
                             "that their values can be trained.")

        # Ingest operators.
        if isinstance(operators, (cirq.PauliString, cirq.PauliSum)):
            operators = [operators]
        if not isinstance(operators, (list, np.ndarray, tuple)):
            raise TypeError("operators must be a cirq.PauliSum or "
                            "cirq.PauliString, or a list, tuple, "
                            "or np.array containing them. "
                            "Got {}.".format(type(operators)))
        if not all([
                isinstance(op, (cirq.PauliString, cirq.PauliSum))
                for op in operators
        ]):
            raise TypeError("Each element in operators to measure "
                            "must be a cirq.PauliString"
                            " or cirq.PauliSum")
        self._operators = util.convert_to_tensor([operators])

        # Ingest and promote repetitions.
        self._analytic = False
        if repetitions is None:
            self._analytic = True
        if not self._analytic and not isinstance(repetitions,
                                                 numbers.Integral):
            raise TypeError("repetitions must be a positive integer value."
                            " Given: ".format(repetitions))
        if not self._analytic and repetitions <= 0:
            raise ValueError("Repetitions must be greater than zero.")
        if not self._analytic:
            self._repetitions = tf.constant(
                [[repetitions for _ in range(len(operators))]],
                dtype=tf.dtypes.int32)

        # Set backend and differentiator.
        if backend == 'noisy':
            raise ValueError("noisy backend value is not supported in "
                             "tfq.layers.PQC. Please use tfq.layers.NoisyPQC "
                             "instead.")

        not_default = backend is not 'noiseless'
        not_default &= backend is not None  # legacy backend=None support.
        if not isinstance(
                backend,
                cirq.Sampler) and repetitions is not None and not_default:
            raise TypeError("provided backend does not inherit cirq.Sampler "
                            "and repetitions!=None. Please provide a backend "
                            "that inherits cirq.Sampler or set "
                            "repetitions=None.")
        if not isinstance(backend,
                          cirq.sim.simulator.SimulatesExpectationValues
                          ) and repetitions is None and not_default:
            raise TypeError(
                "provided backend does not inherit "
                "cirq.sim.simulator.SimulatesExpectationValues and "
                "repetitions=None. Please provide a backend that "
                "inherits "
                "cirq.sim.simulator.SimulatesExpectationValues.")
        if self._analytic:
            self._executor = expectation.Expectation(
                backend=backend, differentiator=differentiator)
        else:
            self._executor = sampled_expectation.SampledExpectation(
                backend=backend, differentiator=differentiator)

        self._append_layer = elementary.AddCircuit()

        # Set additional parameter controls.
        self.initializer = tf.keras.initializers.get(initializer)
        self.regularizer = tf.keras.regularizers.get(regularizer)
        self.constraint = tf.keras.constraints.get(constraint)

        # Weight creation is not placed in a Build function because the number
        # of weights is independent of the input shape.
        self.parameters = self.add_weight('parameters',
                                          shape=self._symbols.shape,
                                          initializer=self.initializer,
                                          regularizer=self.regularizer,
                                          constraint=self.constraint,
                                          dtype=tf.float32,
                                          trainable=True)
Esempio n. 14
0
    def __init__(self,
                 model_circuit,
                 operators,
                 *,
                 repetitions=None,
                 backend=None,
                 differentiator=None,
                 **kwargs):
        """Instantiate this layer.

        Create a layer that will output expectation values of the given
        operators when fed quantum data to it's input layer. This layer will
        take two input tensors, one representing a quantum data source (these
        circuits must not contain any symbols) and the other representing
        control parameters for the model circuit that gets appended to the
        datapoints.

        model_circuit: `cirq.Circuit` containing `sympy.Symbols` that will be
            used as the model which will be fed quantum data inputs.
        operators: `cirq.PauliSum` or Python `list` of `cirq.PauliSum` objects
            used as observables at the end of the model circuit.
        repetitions: Optional Python `int` indicating how many samples to use
            when estimating expectation values. If `None` analytic expectation
            calculation is used.
        backend: Optional Backend to use to simulate states. Defaults to
            the native TensorFlow simulator (None), however users may also
            specify a preconfigured cirq simulation object to use instead.
            If a cirq object is given it must inherit `cirq.SimulatesFinalState`
            if `sampled_based` is True or it must inherit `cirq.Sampler` if
            `sample_based` is False.
        differentiator: Optional `tfq.differentiator` object to specify how
            gradients of `model_circuit` should be calculated.
        """
        super().__init__(**kwargs)
        # Ingest model_circuit.
        if not isinstance(model_circuit, cirq.Circuit):
            raise TypeError("model_circuit must be a cirq.Circuit object."
                            " Given: ".format(model_circuit))

        self._symbols_list = list(
            sorted(util.get_circuit_symbols(model_circuit)))
        self._symbols = tf.constant([str(x) for x in self._symbols_list])

        self._circuit = util.convert_to_tensor([model_circuit])

        if len(self._symbols_list) == 0:
            raise ValueError("model_circuit has no sympy.Symbols. Please "
                             "provide a circuit that contains symbols so "
                             "that their values can be trained.")

        # Ingest operators.
        if isinstance(operators, (cirq.PauliString, cirq.PauliSum)):
            operators = [operators]

        if not isinstance(operators, (list, np.ndarray, tuple)):
            raise TypeError("operators must be a cirq.PauliSum or "
                            "cirq.PauliString, or a list, tuple, "
                            "or np.array containing them. "
                            "Got {}.".format(type(operators)))
        if not all([
                isinstance(op, (cirq.PauliString, cirq.PauliSum))
                for op in operators
        ]):
            raise TypeError("Each element in operators to measure "
                            "must be a cirq.PauliString"
                            " or cirq.PauliSum")

        self._operators = util.convert_to_tensor([operators])

        # Ingest and promote reptitions.
        self._analytic = False
        if repetitions is None:
            self._analytic = True

        if not self._analytic and not isinstance(repetitions,
                                                 numbers.Integral):
            raise TypeError("repetitions must be a positive integer value."
                            " Given: ".format(repetitions))

        if not self._analytic and repetitions <= 0:
            raise ValueError("Repetitions must be greater than zero.")

        if not self._analytic:
            self._repetitions = tf.constant(
                [[repetitions for _ in range(len(operators))]],
                dtype=tf.dtypes.int32)

        if not isinstance(
                backend, cirq.Sampler
        ) and repetitions is not None and backend is not None:
            raise TypeError("provided backend does not inherit cirq.Sampler "
                            "and repetitions!=None. Please provide a backend "
                            "that inherits cirq.Sampler or set "
                            "repetitions=None.")

        if not isinstance(backend, cirq.SimulatesFinalState
                          ) and repetitions is None and backend is not None:
            raise TypeError("provided backend does not inherit "
                            "cirq.SimulatesFinalState and repetitions=None. "
                            "Please provide a backend that inherits "
                            "cirq.SimulatesFinalState.")

        # Ingest backend and differentiator.
        if self._analytic:
            self._layer = expectation.Expectation(
                backend=backend, differentiator=differentiator)
        else:
            self._layer = sampled_expectation.SampledExpectation(
                backend=backend, differentiator=differentiator)

        self._append_layer = elementary.AddCircuit()
    def test_static_cases_noisy(self):
        """Test that the noisy trajectory backend works in complex cases."""
        bit = cirq.GridQubit(0, 0)
        symbol = sympy.Symbol('alpha')
        test_pstring = cirq.Z(bit)
        test_psum = cirq.PauliSum.from_pauli_strings([test_pstring])
        symb_circuit = cirq.Circuit(cirq.H(bit)**symbol)
        reg_circuit = cirq.Circuit(cirq.H(bit))

        # Passing a 2d operators input requires a 1d circuit input.
        expectation.Expectation(backend='noisy')(
            [reg_circuit, reg_circuit],
            operators=[[test_psum, test_psum], [test_psum, test_psum]],
            repetitions=1)

        # Passing 2d operators along with other inputs.
        expectation.Expectation(backend='noisy')(
            [symb_circuit, symb_circuit],
            symbol_names=[symbol],
            operators=[[test_psum, test_psum], [test_psum, test_psum]],
            repetitions=1)
        expectation.Expectation(backend='noisy')(
            [symb_circuit, symb_circuit],
            symbol_names=[symbol],
            symbol_values=[[0.5], [0.8]],
            operators=[[test_psum, test_psum], [test_psum, test_psum]],
            repetitions=1)

        # Ensure tiling up of circuits works as expected.
        expectation.Expectation(backend='noisy')(reg_circuit,
                                                 operators=test_psum,
                                                 repetitions=1)
        expectation.Expectation(backend='noisy')(
            reg_circuit, operators=[test_psum, test_psum], repetitions=1)

        # Ensure tiling up of symbol_values works as expected.
        expectation.Expectation(backend='noisy')(symb_circuit,
                                                 symbol_names=[symbol],
                                                 symbol_values=[[0.5], [0.8]],
                                                 operators=test_psum,
                                                 repetitions=1)
        expectation.Expectation(backend='noisy')(symb_circuit,
                                                 symbol_names=[symbol],
                                                 symbol_values=[[0.5]],
                                                 operators=test_psum,
                                                 repetitions=1)

        # Test multiple operators with integer valued repetition.
        expectation.Expectation(backend='noisy')(
            symb_circuit,
            symbol_names=[symbol],
            symbol_values=[[0.5]],
            operators=[-1.0 * cirq.Z(bit),
                       cirq.X(bit) + 2.0 * cirq.Z(bit)],
            repetitions=1)
        expectation.Expectation(backend='noisy')(
            symb_circuit,
            symbol_names=[symbol],
            symbol_values=[[0.5]],
            operators=[-1.0 * cirq.Z(bit),
                       cirq.X(bit) + 2.0 * cirq.Z(bit)],
            repetitions=[5, 1])

        # Test 2d repetitions.
        expectation.Expectation(backend='noisy')(
            [symb_circuit, symb_circuit],
            symbol_names=[symbol],
            symbol_values=[[0.5], [0.4]],
            operators=[[
                -1.0 * cirq.Z(bit),
                cirq.X(bit) + 2.0 * cirq.Z(bit),
                cirq.Z(bit)
            ], [cirq.Z(bit), cirq.Z(bit), cirq.Z(bit)]],
            repetitions=[[1, 2, 3], [4, 5, 6]])