def test_get_circuit_symbols_error(self): """Make sure that the method errors where it should.""" for param in ['2', sympy.Symbol("X")]: # Passed an invalid parameter (not a cirq.Circuit). with self.assertRaisesRegex(TypeError, expected_regex='Expected a ' 'cirq.Circuit'): util.get_circuit_symbols(param)
def test_get_circuit_symbols_all(self): """Confirm that circuits have all the requested symbols.""" expected_symbols = ['alpha', 'beta', 'gamma', 'omega'] qubits = cirq.GridQubit.rect(1, 2) n_moments = 1 for _ in range(5): test_circuit = util.random_symbol_circuit(qubits, expected_symbols, n_moments) extracted_symbols = util.get_circuit_symbols(test_circuit) self.assertListEqual(sorted(extracted_symbols), sorted(expected_symbols))
def test_get_circuit_symbols(self): """Test that symbols can be extracted from circuits. This test will error out if get_supported_gates gets updated with new gates and the get_circuit function isn't updated. """ expected_symbols = ['alpha', 'beta', 'gamma', 'omega'] qubits = cirq.GridQubit.rect(1, 20) n_moments = 200 for _ in range(5): test_circuit = util.random_symbol_circuit(qubits, expected_symbols, n_moments) extracted_symbols = util.get_circuit_symbols(test_circuit) self.assertListEqual(sorted(extracted_symbols), sorted(expected_symbols))
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)
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 __init__(self, model_circuit, operators, *, repetitions=None, sample_based=None, differentiator=None, **kwargs): """Instantiate this layer. Create a layer that will output noisy 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: Python `int` indicating how many trajectories to use when estimating expectation values. sample_based: Python `bool` indicating whether to use sampling to estimate expectations or analytic calculations with each trajectory. 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 repetitions. if repetitions is None: raise ValueError("Value for repetitions must be provided when " "using noisy simulation.") if not isinstance(repetitions, numbers.Integral): raise TypeError("repetitions must be a positive integer value." " Given: ".format(repetitions)) if repetitions <= 0: raise ValueError("Repetitions must be greater than zero.") self._repetitions = tf.constant( [[repetitions for _ in range(len(operators))]], dtype=tf.dtypes.int32) # Ingest differentiator. if differentiator is None: differentiator = parameter_shift.ParameterShift() # Ingest and promote sample based. if sample_based is None: raise ValueError("Please specify sample_based=False for analytic " "calculations based on monte-carlo trajectories," " or sampled_based=True for measurement based " "noisy estimates.") if not isinstance(sample_based, bool): raise TypeError("sample_based must be either True or False." " received: {}".format(type(sample_based))) if not sample_based: self._executor = differentiator.generate_differentiable_op( sampled_op=noisy_expectation_op.expectation) else: self._executor = differentiator.generate_differentiable_op( sampled_op=noisy_sampled_expectation_op.sampled_expectation) self._append_layer = elementary.AddCircuit()
def __init__( self, model_circuit, *, initializer=tf.keras.initializers.RandomUniform(0, 2 * np.pi), regularizer=None, constraint=None, **kwargs, ): """ Instantiate this layer. Create a layer that will append/prepend a given (parameterized) circuit to the inputs. This layer will accept one input tensor representing a quantum data source (these circuits may contain some symbols) and append/prepend the model_circuit to them, and then output the assembled circuit tensor. model_circuit: `cirq.Circuit` containing `sympy.Symbols` that will be used as the model which will be fed quantum data inputs. If it is parameterized, the symbols it contains will be used as the trainable weights of this layer. 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 either `cirq.SimulatesFinalState` 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 when parameterizing `model_circuit`. constraint: (Optional) `tf.keras.constraint` object applied to the managed variables when 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)) # Get circuit symbols self._symbols_list = list( sorted(util.get_circuit_symbols(model_circuit))) self._symbols = tf.constant([str(x) for x in self._symbols_list]) # Convert `model_circuit` into tf.Tensor self._model_circuit = util.convert_to_tensor([model_circuit]) # 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)