def simulate_sweep( self, program: Union[Circuit, Schedule], params: Sweepable = ParamResolver({}), qubit_order: ops.QubitOrderOrList = ops.QubitOrder.DEFAULT, initial_state: Union[int, np.ndarray] = 0, extensions: Extensions = None) -> List[XmonSimulateTrialResult]: """Simulates the entire supplied Circuit. Args: program: The circuit or schedule to simulate. params: Parameters to run with the program. qubit_order: Determines the canonical ordering of the qubits used to define the order of amplitudes in the wave function. initial_state: If an int, the state is set to the computational basis state corresponding to this state. Otherwise if this is a np.ndarray it is the full initial state. In this case it must be the correct size, be normalized (an L2 norm of 1), and be safely castable to a np.complex64. extensions: Extensions that will be applied while trying to decompose the circuit's gates into XmonGates. If None, this uses the default of xmon_gate_ext. Returns: List of XmonSimulatorTrialResults for this run, one for each possible parameter resolver. """ circuit = (program if isinstance(program, Circuit) else program.to_circuit()) param_resolvers = self._to_resolvers(params or ParamResolver({})) trial_results = [] # type: List[XmonSimulateTrialResult] qubit_order = ops.QubitOrder.as_qubit_order(qubit_order) for param_resolver in param_resolvers: xmon_circuit, _ = self._to_xmon_circuit( circuit, param_resolver, extensions or xmon_gate_ext) measurements = {} # type: Dict[str, np.ndarray] all_step_results = _simulator_iterator(xmon_circuit, self.options, qubit_order, initial_state) step_result = None for step_result in all_step_results: for k, v in step_result.measurements.items(): measurements[k] = np.array(v, dtype=bool) if step_result: final_state = step_result.state() else: # Empty circuit, so final state should be initial state. num_qubits = len(qubit_order.order_for(circuit.all_qubits())) final_state = xmon_stepper.decode_initial_state( initial_state, num_qubits) trial_results.append( XmonSimulateTrialResult(params=param_resolver, measurements=measurements, final_state=final_state)) return trial_results
def run_sweep(self, program: Union[Circuit, Schedule], params: Sweepable = ParamResolver({}), repetitions: int = 1, qubit_order: ops.QubitOrderOrList = ops.QubitOrder.DEFAULT, extensions: Extensions = None) -> List[TrialResult]: """Runs the entire supplied Circuit, mimicking the quantum hardware. If one wants access to the wave function (both setting and getting), the "simulate" methods should be used. The initial state of the run methods is the all zeros state in the computational basis. Args: program: The circuit or schedule to simulate. params: Parameters to run with the program. repetitions: The number of repetitions to simulate. qubit_order: Determines the canonical ordering of the qubits used to define the order of amplitudes in the wave function. extensions: Extensions that will be applied while trying to decompose the circuit's gates into XmonGates. If None, this uses the default of xmon_gate_ext. Returns: TrialResult list for this run; one for each possible parameter resolver. """ circuit = (program if isinstance(program, Circuit) else program.to_circuit()) param_resolvers = self._to_resolvers(params or ParamResolver({})) trial_results = [] # type: List[TrialResult] qubit_order = ops.QubitOrder.as_qubit_order(qubit_order) for param_resolver in param_resolvers: xmon_circuit, keys = self._to_xmon_circuit( circuit, param_resolver, extensions or xmon_gate_ext) if xmon_circuit.are_all_measurements_terminal(): measurements = self._run_sweep_sample(xmon_circuit, repetitions, qubit_order) else: measurements = self._run_sweep_repeat(keys, xmon_circuit, repetitions, qubit_order) trial_results.append( TrialResult(params=param_resolver, repetitions=repetitions, measurements={ k: np.array(v) for k, v in measurements.items() })) return trial_results
def run( self, *, # Force keyword args. program: Union[Circuit, Schedule], job_config: Optional[JobConfig] = None, param_resolver: ParamResolver = ParamResolver({}), repetitions: int = 1, priority: int = 50, target_route: str = '/xmonsim') -> TrialResult: """Runs the supplied Circuit or Schedule via Quantum Engine. Args: program: The Circuit or Schedule to execute. If a circuit is provided, a moment by moment schedule will be used. job_config: Configures the names of programs and jobs. param_resolver: Parameters to run with the program. repetitions: The number of repetitions to simulate. priority: The priority to run at, 0-100. target_route: The engine route to run against. Returns: A single TrialResult for this run. """ return list( self.run_sweep(program=program, job_config=job_config, params=[param_resolver], repetitions=repetitions, priority=priority, target_route=target_route))[0]
def run( self, *, # Force keyword args. program: Program, job_config: Optional[JobConfig] = None, param_resolver: ParamResolver = ParamResolver({}), repetitions: int = 1, priority: int = 50, processor_ids: Sequence[str] = ('xmonsim', ), gate_set: SerializableGateSet = gate_sets.XMON) -> TrialResult: """Runs the supplied Circuit or Schedule via Quantum Engine. Args: program: The Circuit or Schedule to execute. If a circuit is provided, a moment by moment schedule will be used. job_config: Configures the names of programs and jobs. param_resolver: Parameters to run with the program. repetitions: The number of repetitions to simulate. priority: The priority to run at, 0-100. processor_ids: The engine processors to run against. gate_set: The gate set used to serialize the circuit. The gate set must be supported by the selected processor. Returns: A single TrialResult for this run. """ return list( self.run_sweep(program=program, job_config=job_config, params=[param_resolver], repetitions=repetitions, priority=priority, processor_ids=processor_ids, gate_set=gate_set))[0]
def run( self, program: Union[Circuit, Schedule], job_config: Optional[JobConfig] = None, device: Device = None, param_resolver: ParamResolver = ParamResolver({}), repetitions: int = 1, priority: int = 50, target_route: str = '/xmonsim', ) -> TrialResult: """Runs the supplied Circuit or Schedule via Quantum Engine. Args: program: The Circuit or Schedule to execute. If a circuit is provided, a moment by moment schedule will be used. job_config: Configures the names of programs and jobs. device: The device on which to run a circuit. The circuit will be validated against this device before sending to the engine. If device is None, no validation will be done. Can only be supplied if program is a Circuit, otherwise the device from the Schedule will be used. param_resolver: Parameters to run with the program. repetitions: The number of repetitions to simulate. priority: The priority to run at, 0-100. target_route: The engine route to run against. Returns: A single TrialResult for this run. """ return list( self.run_sweep(program, job_config, device, [param_resolver], repetitions, priority, target_route))[0]
def simulate_moment_steps( self, program: Circuit, options: 'XmonOptions' = None, qubit_order: ops.QubitOrderOrList = ops.QubitOrder.DEFAULT, initial_state: Union[int, np.ndarray] = 0, param_resolver: ParamResolver = None, extensions: Extensions = None) -> Iterator['XmonStepResult']: """Returns an iterator of XmonStepResults for each moment simulated. Args: program: The Circuit to simulate. options: XmonOptions configuring the simulation. qubit_order: Determines the canonical ordering of the qubits used to define the order of amplitudes in the wave function. initial_state: If an int, the state is set to the computational basis state corresponding to this state. Otherwise if this is a np.ndarray it is the full initial state. In this case it must be the correct size, be normalized (an L2 norm of 1), and be safely castable to a np.complex64. param_resolver: A ParamResolver for determining values of Symbols. extensions: Extensions that will be applied while trying to decompose the circuit's gates into XmonGates. If None, this uses the default of xmon_gate_ext. Returns: SimulatorIterator that steps through the simulation, simulating each moment and returning a XmonStepResult for each moment. """ param_resolver = param_resolver or ParamResolver({}) xmon_circuit, _ = self._to_xmon_circuit(program, param_resolver, extensions or xmon_gate_ext) return _simulator_iterator(xmon_circuit, options or XmonOptions(), qubit_order, initial_state)
def simulate( self, circuit: Circuit, param_resolver: ParamResolver = ParamResolver({}), qubit_order: ops.QubitOrderOrList = ops.QubitOrder.DEFAULT, initial_state: Union[int, np.ndarray] = 0, extensions: Extensions = None, ) -> XmonSimulateTrialResult: """Simulates the entire supplied Circuit. This method returns the final wave function. Args: circuit: The circuit to simulate. param_resolver: Parameters to run with the program. qubit_order: Determines the canonical ordering of the qubits used to define the order of amplitudes in the wave function. initial_state: If an int, the state is set to the computational basis state corresponding to this state. Otherwise if this is a np.ndarray it is the full initial state. In this case it must be the correct size, be normalized (an L2 norm of 1), and be safely castable to a np.complex64. extensions: Extensions that will be applied while trying to decompose the circuit's gates into XmonGates. If None, this uses the default of xmon_gate_ext. Returns: XmonSimulateTrialResults for the simulation. Includes the final wave function. """ return self.simulate_sweep(circuit, [param_resolver], qubit_order, initial_state, extensions or xmon_gate_ext)[0]
def run( self, circuit: Circuit, param_resolver: ParamResolver = ParamResolver({}), repetitions: int = 1, qubit_order: ops.QubitOrderOrList = ops.QubitOrder.DEFAULT, extensions: Extensions = None, ) -> TrialResult: """Runs the entire supplied Circuit, mimicking the quantum hardware. If one wants access to the wave function (both setting and getting), the "simulate" methods should be used. The initial state of the run methods is the all zeros state in the computational basis. Args: circuit: The circuit to simulate. param_resolver: Parameters to run with the program. repetitions: The number of repetitions to simulate. qubit_order: Determines the canonical ordering of the qubits used to define the order of amplitudes in the wave function. extensions: Extensions that will be applied while trying to decompose the circuit's gates into XmonGates. If None, this uses the default of xmon_gate_ext. Returns: TrialResult for a run. """ return self.run_sweep(circuit, [param_resolver], repetitions, qubit_order, extensions or xmon_gate_ext)[0]
def get_job_results(self, job_resource_name: str) -> List[TrialResult]: """Returns the actual results (not metadata) of a completed job. Params: job_resource_name: A string of the form `projects/project_id/programs/program_id/jobs/job_id`. Returns: An iterable over the TrialResult, one per parameter in the parameter sweep. """ response = self.service.projects().programs().jobs().getResult( parent=job_resource_name).execute() trial_results = [] for sweep_result in response['result']['sweepResults']: sweep_repetitions = sweep_result['repetitions'] key_sizes = [(m['key'], len(m['qubits'])) for m in sweep_result['measurementKeys']] for result in sweep_result['parameterizedResults']: data = base64.standard_b64decode(result['measurementResults']) measurements = unpack_results(data, sweep_repetitions, key_sizes) trial_results.append(TrialResult( params=ParamResolver( result.get('params', {}).get('assignments', {})), repetitions=sweep_repetitions, measurements=measurements)) return trial_results
def test_cz_parameterize(): parameterized_gate = cg.Exp11Gate(half_turns=Symbol('a')) assert parameterized_gate.is_parameterized() with pytest.raises(ValueError): _ = parameterized_gate.matrix() resolver = ParamResolver({'a': 0.1}) resolved_gate = parameterized_gate.with_parameters_resolved_by(resolver) assert resolved_gate == cg.Exp11Gate(half_turns=0.1)
def _get_job_results_v1(self, result: Dict[str, Any]) -> List[TrialResult]: trial_results = [] for sweep_result in result['sweepResults']: sweep_repetitions = sweep_result['repetitions'] key_sizes = [(m['key'], len(m['qubits'])) for m in sweep_result['measurementKeys']] for result in sweep_result['parameterizedResults']: data = base64.standard_b64decode(result['measurementResults']) measurements = api_v1.unpack_results(data, sweep_repetitions, key_sizes) trial_results.append( TrialResult.from_single_parameter_set( params=ParamResolver( result.get('params', {}).get('assignments', {})), measurements=measurements)) return trial_results
def create_job( self, *, # Force keyword args. program_name: str, job_config: Optional[JobConfig] = None, params: Sweepable = None, repetitions: int = 1, priority: int = 500, processor_ids: Sequence[str] = ('xmonsim',), gate_set: SerializableGateSet = gate_sets.XMON) -> 'EngineJob': # Check program to run and program parameters. if not 0 <= priority < 1000: raise ValueError('priority must be between 0 and 1000') job_config = self.implied_job_config(job_config) sweeps = study.to_sweeps(params or ParamResolver({})) run_context = self._serialize_run_context(sweeps, repetitions) # Create job. request = { 'name': '%s/jobs/%s' % (program_name, job_config.job_id), 'output_config': { 'gcs_results_location': { 'uri': job_config.gcs_results } }, 'scheduling_config': { 'priority': priority, 'processor_selector': { 'processor_names': [ 'projects/%s/processors/%s' % (self.project_id, processor_id) for processor_id in processor_ids ] } }, 'run_context': run_context } response = self.service.projects().programs().jobs().create( parent=program_name, body=request).execute() return EngineJob(job_config, response, self)
def run( self, *, # Force keyword args. program: Program, program_id: Optional[str] = None, job_config: Optional[JobConfig] = None, param_resolver: ParamResolver = ParamResolver({}), repetitions: int = 1, priority: int = 50, processor_ids: Sequence[str] = ('xmonsim',), gate_set: SerializableGateSet = gate_sets.XMON) -> TrialResult: """Runs the supplied Circuit or Schedule via Quantum Engine. Args: program: The Circuit or Schedule to execute. If a circuit is provided, a moment by moment schedule will be used. program_id: A user-provided identifier for the program. This must be unique within the Google Cloud project being used. If this parameter is not provided, a random id of the format 'prog-######' will be generated. job_config: Configures the names and properties of jobs. param_resolver: Parameters to run with the program. repetitions: The number of repetitions to simulate. priority: The priority to run at, 0-100. processor_ids: The engine processors that should be candidates to run the program. Only one of these will be scheduled for execution. gate_set: The gate set used to serialize the circuit. The gate set must be supported by the selected processor. Returns: A single TrialResult for this run. """ return list( self.run_sweep(program=program, program_id=program_id, job_config=job_config, params=[param_resolver], repetitions=repetitions, priority=priority, processor_ids=processor_ids, gate_set=gate_set))[0]
def run( self, *, # Force keyword args. job_config: Optional[JobConfig] = None, param_resolver: ParamResolver = ParamResolver({}), repetitions: int = 1, priority: int = 50, processor_ids: Sequence[str] = ('xmonsim', ) ) -> TrialResult: """Runs the supplied Circuit or Schedule via Quantum Engine. Args: program: A Quantum Engine-wrapped Circuit or Schedule object. This may be generated with create_program() or get_program(). program_id: A user-provided identifier for the program. This must be unique within the Google Cloud project being used. If this parameter is not provided, a random id of the format 'prog-######' will be generated. program_id: A user-defined identifer for the program. This must be unique within the project specified on the Engine instance. job_config: Configures the names of programs and jobs. param_resolver: Parameters to run with the program. repetitions: The number of repetitions to simulate. priority: The priority to run at, 0-100. processor_ids: The engine processors that should be candidates to run the program. Only one of these will be scheduled for execution. Returns: A single TrialResult for this run. """ return list( self.run_sweep(job_config=job_config, params=[param_resolver], repetitions=repetitions, priority=priority, processor_ids=processor_ids))[0]
def _resolve_parameters_(self, resolver: ParamResolver): self.parameter = resolver.value_of(self.parameter) return self
def run_sweep( self, *, # Force keyword args. program: Program, job_config: Optional[JobConfig] = None, params: Sweepable = None, repetitions: int = 1, priority: int = 500, processor_ids: Sequence[str] = ('xmonsim', ), gate_set: SerializableGateSet = gate_sets.XMON) -> 'EngineJob': """Runs the supplied Circuit or Schedule via Quantum Engine. In contrast to run, this runs across multiple parameter sweeps, and does not block until a result is returned. Args: program: The Circuit or Schedule to execute. If a circuit is provided, a moment by moment schedule will be used. job_config: Configures the names of programs and jobs. params: Parameters to run with the program. repetitions: The number of circuit repetitions to run. priority: The priority to run at, 0-100. processor_ids: The engine processors to run against. gate_set: The gate set used to serialize the circuit. The gate set must be supported by the selected processor Returns: An EngineJob. If this is iterated over it returns a list of TrialResults, one for each parameter sweep. """ job_config = self.implied_job_config(job_config) # Check program to run and program parameters. if not 0 <= priority < 1000: raise ValueError('priority must be between 0 and 1000') sweeps = study.to_sweeps(params or ParamResolver({})) if self.proto_version == ProtoVersion.V1: code, run_context = self._serialize_program_v1( program, sweeps, repetitions) elif self.proto_version == ProtoVersion.V2: code, run_context = self._serialize_program_v2( program, sweeps, repetitions, gate_set) else: raise ValueError('invalid proto version: {}'.format( self.proto_version)) # Create program. request = { 'name': 'projects/%s/programs/%s' % ( self.project_id, job_config.program_id, ), 'gcs_code_location': { 'uri': job_config.gcs_program }, 'code': code, } response = self.service.projects().programs().create( parent='projects/%s' % self.project_id, body=request).execute() # Create job. request = { 'name': '%s/jobs/%s' % (response['name'], job_config.job_id), 'output_config': { 'gcs_results_location': { 'uri': job_config.gcs_results } }, 'scheduling_config': { 'priority': priority, 'processor_selector': { 'processor_names': [ 'projects/%s/processors/%s' % (self.project_id, processor_id) for processor_id in processor_ids ] } }, 'run_context': run_context } response = self.service.projects().programs().jobs().create( parent=response['name'], body=request).execute() return EngineJob(job_config, response, self)
def run_sweep( self, program: Union[Circuit, Schedule], job_config: Optional[JobConfig] = None, device: Device = None, params: Sweepable = None, repetitions: int = 1, priority: int = 500, target_route: str = '/xmonsim', ) -> 'EngineJob': """Runs the supplied Circuit or Schedule via Quantum Engine. In contrast to run, this runs across multiple parameter sweeps, and does not block until a result is returned. Args: program: The Circuit or Schedule to execute. If a circuit is provided, a moment by moment schedule will be used. job_config: Configures the names of programs and jobs. device: The device on which to run a circuit. The circuit will be validated against this device before sending to the engine. If device is None, no validation will be done. Can only be supplied if program is a Circuit, otherwise the device from the Schedule will be used. params: Parameters to run with the program. repetitions: The number of circuit repetitions to run. priority: The priority to run at, 0-100. target_route: The engine route to run against. Returns: An EngineJob. If this is iterated over it returns a list of TrialResults, one for each parameter sweep. """ job_config = self.implied_job_config(job_config) schedule = self.program_as_schedule(program, device) # Check program to run and program parameters. if not 0 <= priority < 1000: raise ValueError('priority must be between 0 and 1000') schedule.device.validate_schedule(schedule) # Create program. sweeps = _sweepable_to_sweeps(params or ParamResolver({})) proto_program = program_pb2.Program() for sweep in sweeps: sweep_proto = proto_program.parameter_sweeps.add() sweep_to_proto(sweep, sweep_proto) sweep_proto.repetitions = repetitions program_dict = MessageToDict(proto_program) program_dict['operations'] = [ MessageToDict(op) for op in schedule_to_proto(schedule) ] code = {'@type': 'type.googleapis.com/cirq.api.google.v1.Program'} code.update(program_dict) request = { 'name': 'projects/%s/programs/%s' % ( job_config.project_id, job_config.program_id, ), 'gcs_code_location': { 'uri': job_config.gcs_program }, 'code': code, } response = self.service.projects().programs().create( parent='projects/%s' % job_config.project_id, body=request).execute() # Create job. request = { 'name': '%s/jobs/%s' % (response['name'], job_config.job_id), 'output_config': { 'gcs_results_location': { 'uri': job_config.gcs_results } }, 'scheduling_config': { 'priority': priority, 'target_route': target_route }, } response = self.service.projects().programs().jobs().create( parent=response['name'], body=request).execute() return EngineJob(job_config, response, self)
def run_sweep( self, *, # Force keyword args. program: Union[circuits.Circuit, Schedule], job_config: Optional[JobConfig] = None, params: Sweepable = None, repetitions: int = 1, priority: int = 500, processor_ids: Sequence[str] = ('xmonsim',)) -> 'EngineJob': """Runs the supplied Circuit or Schedule via Quantum Engine. In contrast to run, this runs across multiple parameter sweeps, and does not block until a result is returned. Args: program: The Circuit or Schedule to execute. If a circuit is provided, a moment by moment schedule will be used. job_config: Configures the names of programs and jobs. params: Parameters to run with the program. repetitions: The number of circuit repetitions to run. priority: The priority to run at, 0-100. processor_ids: The engine processors to run against. Returns: An EngineJob. If this is iterated over it returns a list of TrialResults, one for each parameter sweep. """ job_config = self.implied_job_config(job_config) schedule = self.program_as_schedule(program) # Check program to run and program parameters. if not 0 <= priority < 1000: raise ValueError('priority must be between 0 and 1000') schedule.device.validate_schedule(schedule) # Create program. sweeps = _sweepable_to_sweeps(params or ParamResolver({})) program_dict = {} # type: Dict[str, Any] program_dict['parameter_sweeps'] = [ sweep_to_proto_dict(sweep, repetitions) for sweep in sweeps] program_dict['operations'] = [op for op in schedule_to_proto_dicts(schedule)] code = { '@type': 'type.googleapis.com/cirq.api.google.v1.Program'} code.update(program_dict) request = { 'name': 'projects/%s/programs/%s' % (job_config.project_id, job_config.program_id,), 'gcs_code_location': {'uri': job_config.gcs_program}, 'code': code, } response = self.service.projects().programs().create( parent='projects/%s' % job_config.project_id, body=request).execute() # Create job. request = { 'name': '%s/jobs/%s' % (response['name'], job_config.job_id), 'output_config': { 'gcs_results_location': { 'uri': job_config.gcs_results } }, 'scheduling_config': { 'priority': priority, 'processor_selector': { 'processor_names': [ 'projects/%s/processors/%s' % (job_config.project_id, processor_id) for processor_id in processor_ids ] } }, } response = self.service.projects().programs().jobs().create( parent=response['name'], body=request).execute() return EngineJob(job_config, response, self)
def _resolve_parameters_(self, resolver: ParamResolver, recursive: bool): self.parameter = resolver.value_of(self.parameter, recursive) return self
def with_parameters_resolved_by(self, param_resolver: study.ParamResolver ) -> 'PauliStringPhasor': return self._with_half_turns( param_resolver.value_of(self.half_turns))
def _resolve_parameters_( self, param_resolver: study.ParamResolver) -> 'PauliStringPhasor': return self._with_half_turns(param_resolver.value_of(self.half_turns))
def test_partial_reflection_gate_with_parameters_resolved_by(): gate = DummyGate(half_turns=Symbol('a')) resolver = ParamResolver({'a': 0.1}) resolved_gate = gate.with_parameters_resolved_by(resolver) assert resolved_gate.half_turns == 0.1