def test_set_program_description(client_constructor): grpc_client = setup_mock_(client_constructor) result = quantum.QuantumProgram(name='projects/proj/programs/prog') grpc_client.update_quantum_program.return_value = result client = EngineClient() assert client.set_program_description('proj', 'prog', 'A program') == result grpc_client.update_quantum_program.assert_called_with( quantum.UpdateQuantumProgramRequest( name='projects/proj/programs/prog', quantum_program=quantum.QuantumProgram( name='projects/proj/programs/prog', description='A program' ), update_mask=FieldMask(paths=['description']), ) ) assert client.set_program_description('proj', 'prog', '') == result grpc_client.update_quantum_program.assert_called_with( quantum.UpdateQuantumProgramRequest( name='projects/proj/programs/prog', quantum_program=quantum.QuantumProgram(name='projects/proj/programs/prog'), update_mask=FieldMask(paths=['description']), ) )
def test_set_program_labels(client_constructor): grpc_client = setup_mock_(client_constructor) grpc_client.get_quantum_program.return_value = quantum.QuantumProgram( labels={'color': 'red', 'weather': 'sun', 'run': '1'}, label_fingerprint='hash' ) result = quantum.QuantumProgram(name='projects/proj/programs/prog') grpc_client.update_quantum_program.return_value = result client = EngineClient() labels = {'hello': 'world', 'color': 'blue', 'run': '1'} assert client.set_program_labels('proj', 'prog', labels) == result grpc_client.update_quantum_program.assert_called_with( quantum.UpdateQuantumProgramRequest( name='projects/proj/programs/prog', quantum_program=quantum.QuantumProgram( name='projects/proj/programs/prog', labels=labels, label_fingerprint='hash' ), update_mask=FieldMask(paths=['labels']), ) ) assert client.set_program_labels('proj', 'prog', {}) == result grpc_client.update_quantum_program.assert_called_with( quantum.UpdateQuantumProgramRequest( name='projects/proj/programs/prog', quantum_program=quantum.QuantumProgram( name='projects/proj/programs/prog', label_fingerprint='hash' ), update_mask=FieldMask(paths=['labels']), ) )
def test_description(get_program): program = cg.EngineProgram( 'a', 'b', EngineContext(), _program=quantum.QuantumProgram(description='hello') ) assert program.description() == 'hello' get_program.return_value = quantum.QuantumProgram(description='hello') assert cg.EngineProgram('a', 'b', EngineContext()).description() == 'hello' get_program.assert_called_once_with('a', 'b', False)
def test_set_labels(set_program_labels): program = cg.EngineProgram('a', 'b', EngineContext()) set_program_labels.return_value = quantum.QuantumProgram(labels={'a': '1', 'b': '1'}) assert program.set_labels({'a': '1', 'b': '1'}).labels() == {'a': '1', 'b': '1'} set_program_labels.assert_called_with('a', 'b', {'a': '1', 'b': '1'}) set_program_labels.return_value = quantum.QuantumProgram() assert program.set_labels({}).labels() == {} set_program_labels.assert_called_with('a', 'b', {})
def test_set_description(set_program_description): program = cg.EngineProgram('a', 'b', EngineContext()) set_program_description.return_value = quantum.QuantumProgram(description='world') assert program.set_description('world').description() == 'world' set_program_description.assert_called_with('a', 'b', 'world') set_program_description.return_value = quantum.QuantumProgram(description='') assert program.set_description('').description() == '' set_program_description.assert_called_with('a', 'b', '')
def test_remove_labels(remove_program_labels): program = cg.EngineProgram( 'a', 'b', EngineContext(), _program=quantum.QuantumProgram(labels={'a': '1', 'b': '1'}) ) assert program.labels() == {'a': '1', 'b': '1'} remove_program_labels.return_value = quantum.QuantumProgram(labels={'b': '1'}) assert program.remove_labels(['a']).labels() == {'b': '1'} remove_program_labels.assert_called_with('a', 'b', ['a']) remove_program_labels.return_value = quantum.QuantumProgram(labels={}) assert program.remove_labels(['a', 'b', 'c']).labels() == {} remove_program_labels.assert_called_with('a', 'b', ['a', 'b', 'c'])
def test_add_labels(add_program_labels): program = cg.EngineProgram( 'a', 'b', EngineContext(), _program=quantum.QuantumProgram(labels={}) ) assert program.labels() == {} add_program_labels.return_value = quantum.QuantumProgram(labels={'a': '1'}) assert program.add_labels({'a': '1'}).labels() == {'a': '1'} add_program_labels.assert_called_with('a', 'b', {'a': '1'}) add_program_labels.return_value = quantum.QuantumProgram(labels={'a': '2', 'b': '1'}) assert program.add_labels({'a': '2', 'b': '1'}).labels() == {'a': '2', 'b': '1'} add_program_labels.assert_called_with('a', 'b', {'a': '2', 'b': '1'})
def test_list_program(client_constructor): grpc_client = setup_mock_(client_constructor) results = [ quantum.QuantumProgram(name='projects/proj/programs/prog1'), quantum.QuantumProgram(name='projects/proj/programs/prog2'), ] grpc_client.list_quantum_programs.return_value = results client = EngineClient() assert client.list_programs(project_id='proj') == results grpc_client.list_quantum_programs.assert_called_with( quantum.ListQuantumProgramsRequest(parent='projects/proj', filter='') )
def test_run_circuit_failed_missing_processor_name(client): client().create_program.return_value = ( 'prog', quantum.QuantumProgram(name='projects/proj/programs/prog'), ) client().create_job.return_value = ( 'job-id', quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'}), ) client().get_job.return_value = quantum.QuantumJob( name='projects/proj/programs/prog/jobs/job-id', execution_status={ 'state': 'FAILURE', 'failure': { 'error_code': 'SYSTEM_ERROR', 'error_message': 'Not good' }, }, ) engine = cg.Engine(project_id='proj') with pytest.raises( RuntimeError, match='Job projects/proj/programs/prog/jobs/job-id on processor' ' UNKNOWN failed. SYSTEM_ERROR: Not good', ): engine.run(program=_CIRCUIT)
def test_sampler(client): client().create_program.return_value = ( 'prog', quantum.QuantumProgram(name='projects/proj/programs/prog'), ) client().create_job.return_value = ( 'job-id', quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'}), ) client().get_job.return_value = quantum.QuantumJob( execution_status={'state': 'SUCCESS'}, update_time=_to_timestamp('2019-07-09T23:39:59Z')) client().get_job_results.return_value = quantum.QuantumResult( result=util.pack_any(_RESULTS_V2)) processor = cg.EngineProcessor('proj', 'mysim', EngineContext()) sampler = processor.get_sampler() results = sampler.run_sweep( program=_CIRCUIT, params=[cirq.ParamResolver({'a': 1}), cirq.ParamResolver({'a': 2})]) assert len(results) == 2 for i, v in enumerate([1, 2]): assert results[i].repetitions == 1 assert results[i].params.param_dict == {'a': v} assert results[i].measurements == {'q': np.array([[0]], dtype='uint8')} assert client().create_program.call_args[0][0] == 'proj'
def test_list_programs(list_programs): prog1 = quantum.QuantumProgram( name='projects/proj/programs/prog-YBGR48THF3JHERZW200804') prog2 = quantum.QuantumProgram( name='projects/otherproj/programs/prog-V3ZRTV6TTAFNTYJV200804') list_programs.return_value = [prog1, prog2] result = cg.Engine(project_id='proj').list_programs() list_programs.assert_called_once_with('proj', created_after=None, created_before=None, has_labels=None) assert [(p.program_id, p.project_id, p._program) for p in result] == [ ('prog-YBGR48THF3JHERZW200804', 'proj', prog1), ('prog-V3ZRTV6TTAFNTYJV200804', 'otherproj', prog2), ]
async def create_program_async( self, project_id: str, program_id: Optional[str], code: any_pb2.Any, description: Optional[str] = None, labels: Optional[Dict[str, str]] = None, ) -> Tuple[str, quantum.QuantumProgram]: """Creates a Quantum Engine program. Args: project_id: A project_id of the parent Google Cloud Project. program_id: Unique ID of the program within the parent project. code: Properly serialized program code. description: An optional description to set on the program. labels: Optional set of labels to set on the program. Returns: Tuple of created program id and program """ parent_name = _project_name(project_id) program_name = _program_name_from_ids(project_id, program_id) if program_id else '' program = quantum.QuantumProgram(name=program_name, code=code) if description: program.description = description if labels: program.labels.update(labels) request = quantum.CreateQuantumProgramRequest( parent=parent_name, quantum_program=program, overwrite_existing_source_code=False ) program = await self._send_request_async(self.grpc_client.create_quantum_program, request) return _ids_from_program_name(program.name)[1], program
def test_get_circuit_v1(get_program_async): program = cg.EngineProgram('a', 'b', EngineContext()) get_program_async.return_value = quantum.QuantumProgram( code=util.pack_any(v1.program_pb2.Program()) ) with pytest.raises(ValueError, match='v1 Program is not supported'): program.get_circuit()
def test_get_circuit_unsupported_program_type(get_program): program = cg.EngineProgram('a', 'b', EngineContext()) get_program.return_value = quantum.QuantumProgram( code=any_pb2.Any(type_url='type.googleapis.com/unknown.proto') ) with pytest.raises(ValueError, match='unknown.proto'): program.get_circuit()
def test_get_circuit_v2(get_program): circuit = cirq.Circuit( cirq.X(cirq.GridQubit(5, 2)) ** 0.5, cirq.measure(cirq.GridQubit(5, 2), key='result') ) program = cg.EngineProgram('a', 'b', EngineContext()) get_program.return_value = quantum.QuantumProgram(code=_PROGRAM_V2) assert program.get_circuit() == circuit get_program.assert_called_once_with('a', 'b', True)
def test_update_time(get_program): program = cg.EngineProgram('a', 'b', EngineContext()) get_program.return_value = quantum.QuantumProgram( update_time=timestamp_pb2.Timestamp(seconds=1581515101) ) assert program.update_time() == datetime.datetime( 2020, 2, 12, 13, 45, 1, tzinfo=datetime.timezone.utc ) get_program.assert_called_once_with('a', 'b', False)
def test_get_circuit_v2_unknown_gateset(get_program): program = cg.EngineProgram('a', 'b', EngineContext()) get_program.return_value = quantum.QuantumProgram( code=util.pack_any( v2.program_pb2.Program(language=v2.program_pb2.Language(gate_set="BAD_GATESET")) ) ) with pytest.raises(ValueError, match='BAD_GATESET'): program.get_circuit()
def test_create_time(): program = cg.EngineProgram( 'a', 'b', EngineContext(), _program=quantum.QuantumProgram(create_time=timestamp_pb2.Timestamp(seconds=1581515101)), ) assert program.create_time() == datetime.datetime( 2020, 2, 12, 13, 45, 1, tzinfo=datetime.timezone.utc )
async def _set_program_labels_async( self, project_id: str, program_id: str, labels: Dict[str, str], fingerprint: str ) -> quantum.QuantumProgram: program_resource_name = _program_name_from_ids(project_id, program_id) request = quantum.UpdateQuantumProgramRequest( name=program_resource_name, quantum_program=quantum.QuantumProgram( name=program_resource_name, labels=labels, label_fingerprint=fingerprint ), update_mask=field_mask_pb2.FieldMask(paths=['labels']), ) return await self._send_request_async(self.grpc_client.update_quantum_program, request)
def test_get_circuit_batch(get_program): circuit = cirq.Circuit( cirq.X(cirq.GridQubit(5, 2)) ** 0.5, cirq.measure(cirq.GridQubit(5, 2), key='result') ) program = cg.EngineProgram('a', 'b', EngineContext()) get_program.return_value = quantum.QuantumProgram(code=_BATCH_PROGRAM_V2) with pytest.raises(ValueError, match='A program number must be specified'): program.get_circuit() with pytest.raises(ValueError, match='Only 1 in the batch but index 1 was specified'): program.get_circuit(1) assert program.get_circuit(0) == circuit get_program.assert_called_once_with('a', 'b', True)
def setup_run_circuit_with_result_(client, result): client().create_program.return_value = ( 'prog', quantum.QuantumProgram(name='projects/proj/programs/prog'), ) client().create_job.return_value = ( 'job-id', quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'}), ) client().get_job.return_value = quantum.QuantumJob( execution_status={'state': 'SUCCESS'}, update_time=_DT) client().get_job_results.return_value = quantum.QuantumResult( result=result)
def test_remove_program_labels(client_constructor): grpc_client = setup_mock_(client_constructor) existing = quantum.QuantumProgram( labels={'color': 'red', 'weather': 'sun', 'run': '1'}, label_fingerprint='hash' ) grpc_client.get_quantum_program.return_value = existing result = quantum.QuantumProgram(name='projects/proj/programs/prog') grpc_client.update_quantum_program.return_value = result client = EngineClient() assert client.remove_program_labels('proj', 'prog', ['other']) == existing assert grpc_client.update_quantum_program.call_count == 0 assert client.remove_program_labels('proj', 'prog', ['hello', 'weather']) == result grpc_client.update_quantum_program.assert_called_with( quantum.UpdateQuantumProgramRequest( name='projects/proj/programs/prog', quantum_program=quantum.QuantumProgram( name='projects/proj/programs/prog', labels={'color': 'red', 'run': '1'}, label_fingerprint='hash', ), update_mask=FieldMask(paths=['labels']), ) ) assert client.remove_program_labels('proj', 'prog', ['color', 'weather', 'run']) == result grpc_client.update_quantum_program.assert_called_with( quantum.UpdateQuantumProgramRequest( name='projects/proj/programs/prog', quantum_program=quantum.QuantumProgram( name='projects/proj/programs/prog', label_fingerprint='hash' ), update_mask=FieldMask(paths=['labels']), ) )
def test_get_batch_size(get_program): # Has to fetch from engine if not _program specified. program = cg.EngineProgram('a', 'b', EngineContext(), result_type=ResultType.Batch) get_program.return_value = quantum.QuantumProgram(code=_BATCH_PROGRAM_V2) assert program.batch_size() == 1 # If _program specified, uses that value. program = cg.EngineProgram( 'a', 'b', EngineContext(), _program=quantum.QuantumProgram(code=_BATCH_PROGRAM_V2), result_type=ResultType.Batch, ) assert program.batch_size() == 1 with pytest.raises(ValueError, match='ResultType.Program'): program = cg.EngineProgram('a', 'b', EngineContext(), result_type=ResultType.Program) _ = program.batch_size() with pytest.raises(ValueError, match='cirq.google.api.v2.Program'): get_program.return_value = quantum.QuantumProgram(code=_PROGRAM_V2) program = cg.EngineProgram('a', 'b', EngineContext(), result_type=ResultType.Batch) _ = program.batch_size()
def test_run_batch_no_sweeps(create_job): # Running with no sweeps is fine. Uses program's batch size to create # proper empty sweeps. create_job.return_value = ('kittens', quantum.QuantumJob()) program = cg.EngineProgram( 'my-meow', 'my-meow', _program=quantum.QuantumProgram(code=_BATCH_PROGRAM_V2), context=EngineContext(), result_type=ResultType.Batch, ) job = program.run_batch(job_id='steve', repetitions=10, processor_ids=['lazykitty']) assert job._job == quantum.QuantumJob() batch_run_context = v2.batch_pb2.BatchRunContext() create_job.call_args[1]['run_context'].Unpack(batch_run_context) assert len(batch_run_context.run_contexts) == 1
def test_get_program(client_constructor): grpc_client = setup_mock_(client_constructor) result = quantum.QuantumProgram(name='projects/proj/programs/prog') grpc_client.get_quantum_program.return_value = result client = EngineClient() assert client.get_program('proj', 'prog', False) == result grpc_client.get_quantum_program.assert_called_with( quantum.GetQuantumProgramRequest(name='projects/proj/programs/prog', return_code=False) ) assert client.get_program('proj', 'prog', True) == result grpc_client.get_quantum_program.assert_called_with( quantum.GetQuantumProgramRequest(name='projects/proj/programs/prog', return_code=True) )
def test_run_circuit_timeout(patched_time_sleep, client): client().create_program.return_value = ( 'prog', quantum.QuantumProgram(name='projects/proj/programs/prog'), ) client().create_job.return_value = ( 'job-id', quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'}), ) client().get_job.return_value = quantum.QuantumJob( name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'RUNNING'}) engine = cg.Engine(project_id='project-id', timeout=600) with pytest.raises(RuntimeError, match='Timed out'): engine.run(program=_CIRCUIT)
def test_run_batch(client): client().create_program.return_value = ( 'prog', quantum.QuantumProgram(name='projects/proj/programs/prog'), ) client().create_job.return_value = ( 'job-id', quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'}), ) client().get_job.return_value = quantum.QuantumJob( execution_status={'state': 'SUCCESS'}, update_time=_to_timestamp('2019-07-09T23:39:59Z')) client().get_job_results.return_value = quantum.QuantumResult( result=_BATCH_RESULTS_V2) processor = cg.EngineProcessor('a', 'p', EngineContext()) job = processor.run_batch( programs=[_CIRCUIT, _CIRCUIT], job_id='job-id', params_list=[cirq.Points('a', [1, 2]), cirq.Points('a', [3, 4])], ) results = job.results() assert len(results) == 4 for i, v in enumerate([1, 2, 3, 4]): assert results[i].repetitions == 1 assert results[i].params.param_dict == {'a': v} assert results[i].measurements == {'q': np.array([[0]], dtype='uint8')} for result in results: assert result.job_id == job.id() client().create_program.assert_called_once() client().create_job.assert_called_once() run_context = v2.batch_pb2.BatchRunContext() client().create_job.call_args[1]['run_context'].Unpack(run_context) assert len(run_context.run_contexts) == 2 for idx, rc in enumerate(run_context.run_contexts): sweeps = rc.parameter_sweeps assert len(sweeps) == 1 assert sweeps[0].repetitions == 1 if idx == 0: assert sweeps[0].sweep.single_sweep.points.points == [1.0, 2.0] if idx == 1: assert sweeps[0].sweep.single_sweep.points.points == [3.0, 4.0] client().get_job.assert_called_once() client().get_job_results.assert_called_once()
def test_run_circuit_timeout(client): client().create_program_async.return_value = ( 'prog', quantum.QuantumProgram(name='projects/proj/programs/prog'), ) client().create_job_async.return_value = ( 'job-id', quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'}), ) client().get_job_async.return_value = quantum.QuantumJob( name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'RUNNING'}) engine = cg.Engine(project_id='project-id', timeout=1) with pytest.raises(TimeoutError): engine.run(program=_CIRCUIT)
def test_run_sweep_params(client): client().create_program.return_value = ( 'prog', quantum.QuantumProgram(name='projects/proj/programs/prog'), ) client().create_job.return_value = ( 'job-id', quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'}), ) client().get_job.return_value = quantum.QuantumJob( execution_status={'state': 'SUCCESS'}, update_time=_to_timestamp('2019-07-09T23:39:59Z')) client().get_job_results.return_value = quantum.QuantumResult( result=util.pack_any(_RESULTS_V2)) processor = cg.EngineProcessor('a', 'p', EngineContext()) job = processor.run_sweep( program=_CIRCUIT, params=[cirq.ParamResolver({'a': 1}), cirq.ParamResolver({'a': 2})]) results = job.results() assert len(results) == 2 for i, v in enumerate([1, 2]): assert results[i].repetitions == 1 assert results[i].params.param_dict == {'a': v} assert results[i].measurements == {'q': np.array([[0]], dtype='uint8')} for result in results: assert result.job_id == job.id() assert result.job_finished_time is not None assert results == cirq.read_json(json_text=cirq.to_json(results)) client().create_program.assert_called_once() client().create_job.assert_called_once() run_context = v2.run_context_pb2.RunContext() client().create_job.call_args[1]['run_context'].Unpack(run_context) sweeps = run_context.parameter_sweeps assert len(sweeps) == 2 for i, v in enumerate([1.0, 2.0]): assert sweeps[i].repetitions == 1 assert sweeps[i].sweep.sweep_function.sweeps[ 0].single_sweep.points.points == [v] client().get_job.assert_called_once() client().get_job_results.assert_called_once()
def test_run_calibration(client): client().create_program_async.return_value = ( 'prog', quantum.QuantumProgram(name='projects/proj/programs/prog'), ) client().create_job_async.return_value = ( 'job-id', quantum.QuantumJob( name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'} ), ) client().get_job_async.return_value = quantum.QuantumJob(execution_status={'state': 'SUCCESS'}) client().get_job_results_async.return_value = quantum.QuantumResult( result=_CALIBRATION_RESULTS_V2 ) q1 = cirq.GridQubit(2, 3) q2 = cirq.GridQubit(2, 4) layer1 = cg.CalibrationLayer('xeb', cirq.Circuit(cirq.CZ(q1, q2)), {'num_layers': 42}) layer2 = cg.CalibrationLayer( 'readout', cirq.Circuit(cirq.measure(q1, q2)), {'num_samples': 4242} ) processor = cg.EngineProcessor('proj', 'mysim', EngineContext()) job = processor.run_calibration(layers=[layer1, layer2], job_id='job-id') results = job.calibration_results() assert len(results) == 2 assert results[0].code == v2.calibration_pb2.SUCCESS assert results[0].error_message == 'First success' assert results[0].token == 'abc123' assert len(results[0].metrics) == 1 assert len(results[0].metrics['fidelity']) == 1 assert results[0].metrics['fidelity'][(q1, q2)] == [0.75] assert results[1].code == v2.calibration_pb2.SUCCESS assert results[1].error_message == 'Second success' # assert label is correct client().create_job_async.assert_called_once_with( project_id='proj', program_id='prog', job_id='job-id', processor_ids=['mysim'], run_context=util.pack_any(v2.run_context_pb2.RunContext()), description=None, labels={'calibration': ''}, )