def test_bad_priority(build): eng = cg.Engine(api_key="key", proto_version=cg.engine.engine.ProtoVersion.V2) with pytest.raises(ValueError, match='priority must be'): eng.run(program=cirq.Circuit(), job_config=cg.JobConfig('project-id', gcs_prefix='gs://bucket/folder'), priority=1001)
def test_implied_job_config_project_id(build): eng = cg.Engine(api_key="key") with pytest.raises(ValueError, match='project id'): _ = eng.implied_job_config(None) with pytest.raises(ValueError, match='project id'): _ = eng.implied_job_config(cg.JobConfig()) assert eng.implied_job_config( cg.JobConfig(project_id='specific')).project_id == 'specific' eng_with = cg.Engine(api_key="key", default_project_id='default') # Fallback to default. assert eng_with.implied_job_config(None).project_id == 'default' # Override default. assert eng_with.implied_job_config( cg.JobConfig(project_id='specific')).project_id == 'specific'
def test_missing_latest_calibration(client_constructor): client = mock.Mock() client_constructor.return_value = client client.get_quantum_calibration.side_effect = exceptions.NotFound('') calibration = cg.Engine(project_id='myproject').get_latest_calibration('x') assert client.get_quantum_calibration.call_args[0][ 0] == 'projects/myproject/processors/x/calibrations/current' assert not calibration
def test_alternative_api_and_key(build): disco = ('https://secret.googleapis.com/$discovery/rest?version=vfooo' '&key=my-key') cg.Engine(project_id='project-id', discovery_url=disco) build.assert_called_with(mock.ANY, mock.ANY, discoveryServiceUrl=disco, requestBuilder=mock.ANY)
def test_engine_str(): engine = cg.Engine( 'proj', proto_version=cg.engine.engine.ProtoVersion.V2, service_args={'args': 'test'}, verbose=True, ) assert str(engine) == 'Engine(project_id=\'proj\')'
def test_run_circuit(build): service = mock.Mock() build.return_value = service programs = service.projects().programs() jobs = programs.jobs() programs.create().execute.return_value = { 'name': 'projects/project-id/programs/test' } jobs.create().execute.return_value = { 'name': 'projects/project-id/programs/test/jobs/test', 'executionStatus': { 'state': 'READY' } } jobs.get().execute.return_value = { 'name': 'projects/project-id/programs/test/jobs/test', 'executionStatus': { 'state': 'SUCCESS' } } jobs.getResult().execute.return_value = {'result': _A_RESULT} engine = cg.Engine(project_id='project-id') result = engine.run(program=_CIRCUIT, job_config=cg.JobConfig('job-id'), processor_ids=['mysim']) assert result.repetitions == 1 assert result.params.param_dict == {'a': 1} assert result.measurements == {'q': np.array([[0]], dtype='uint8')} build.assert_called_with( 'quantum', 'v1alpha1', discoveryServiceUrl=('https://{api}.googleapis.com' '/$discovery/rest?version=' '{apiVersion}'), requestBuilder=mock.ANY) assert programs.create.call_args[1]['parent'] == 'projects/project-id' assert jobs.create.call_args[1] == { 'parent': 'projects/project-id/programs/test', 'body': { 'name': 'projects/project-id/programs/test/jobs/job-id', 'scheduling_config': { 'priority': 50, 'processor_selector': { 'processor_names': ['projects/project-id/processors/mysim'] } }, 'run_context': { '@type': 'type.googleapis.com/cirq.google.api.v1.RunContext', 'parameter_sweeps': [{ 'repetitions': 1 }] } } } assert jobs.get().execute.call_count == 1 assert jobs.getResult().execute.call_count == 1
def test_create_engine(client): with pytest.raises( ValueError, match='provide context or proto_version, service_args and verbose'): cg.Engine('proj', proto_version=cg.engine.engine.ProtoVersion.V2, service_args={'args': 'test'}, verbose=True, context=mock.Mock()) assert cg.Engine( 'proj', proto_version=cg.engine.engine.ProtoVersion.V2, service_args={ 'args': 'test' }, verbose=True).context.proto_version == cg.engine.engine.ProtoVersion.V2 assert client.called_with({'args': 'test'}, True)
def test_api_doesnt_retry_not_found_errors(client_constructor): client = mock.Mock() client_constructor.return_value = client client.get_quantum_program.side_effect = exceptions.NotFound('not found') engine = cg.Engine(project_id='project-id') with pytest.raises(cg.engine.engine.EngineException, match='not found'): engine.get_program('foo') assert client.get_quantum_program.call_count == 1
def test_missing_device_specification(client_constructor): client = mock.Mock() client_constructor.return_value = client client.get_quantum_processor.return_value = qtypes.QuantumProcessor() device_spec = cg.Engine( project_id='myproject').get_device_specification('x') assert client.get_quantum_processor.call_args[0][ 0] == 'projects/myproject/processors/x' assert device_spec == v2.device_pb2.DeviceSpecification()
def test_latest_calibration(client_constructor): client = mock.Mock() client_constructor.return_value = client client.get_quantum_calibration.return_value = _CALIBRATION calibration = cg.Engine(project_id='myproject').get_latest_calibration('x') assert client.get_quantum_calibration.call_args[0][ 0] == 'projects/myproject/processors/x/calibrations/current' assert calibration.timestamp == 1562544000021 assert set(calibration.keys()) == set(['xeb', 't1', 'globalMetric'])
def test_bad_job_config_inference_order(build): eng = cg.Engine(project_id='project-id') config = cg.JobConfig() with pytest.raises(ValueError): eng._infer_gcs_results(config) eng._infer_gcs_prefix(config) eng._infer_gcs_results(config)
def test_missing_latest_calibration(build): service = mock.Mock() build.return_value = service calibrations = service.projects().processors().calibrations() calibrations.list().execute.return_value = {} calibration = cg.Engine(project_id='myproject').get_latest_calibration('x') assert calibrations.list.call_args[1][ 'parent'] == 'projects/myproject/processors/x' assert not calibration
def test_no_gate_set(): circuit = cirq.Circuit(device=cg.Sycamore) engine = cg.Engine(project_id='project-id') with pytest.raises(ValueError, match='No gate set'): engine.run(program=circuit) with pytest.raises(ValueError, match='No gate set'): engine.run_sweep(program=circuit) with pytest.raises(ValueError, match='No gate set'): engine.create_program(program=circuit)
def test_run_sweep_params_old_proto(build): service = mock.Mock() build.return_value = service programs = service.projects().programs() jobs = programs.jobs() results_old_proto = copy.deepcopy(_RESULTS) results_old_proto[ '@type'] = 'type.googleapis.com/cirq.api.google.v1.Result' programs.create().execute.return_value = { 'name': 'projects/project-id/programs/test' } jobs.create().execute.return_value = { 'name': 'projects/project-id/programs/test/jobs/test', 'executionStatus': { 'state': 'READY' } } jobs.get().execute.return_value = { 'name': 'projects/project-id/programs/test/jobs/test', 'executionStatus': { 'state': 'SUCCESS' } } jobs.getResult().execute.return_value = {'result': results_old_proto} engine = cg.Engine(project_id='project-id') job = engine.run_sweep( program=_CIRCUIT, job_config=cg.JobConfig('project-id'), 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')} build.assert_called_with( 'quantum', 'v1alpha1', discoveryServiceUrl=('https://{api}.googleapis.com' '/$discovery/rest?version=' '{apiVersion}'), requestBuilder=mock.ANY) assert programs.create.call_args[1]['parent'] == 'projects/project-id' sweeps = jobs.create.call_args[1]['body']['run_context'][ 'parameter_sweeps'] assert len(sweeps) == 2 for i, v in enumerate([1, 2]): assert sweeps[i]['repetitions'] == 1 assert sweeps[i]['sweep']['factors'][0]['sweeps'][0]['points'][ 'points'] == [v] assert jobs.create.call_args[1][ 'parent'] == 'projects/project-id/programs/test' assert jobs.get().execute.call_count == 1 assert jobs.getResult().execute.call_count == 1
def test_run_sweep_v2_new_proto(build): service = mock.Mock() build.return_value = service programs = service.projects().programs() jobs = programs.jobs() programs.create().execute.return_value = { 'name': 'projects/project-id/programs/test' } jobs.create().execute.return_value = { 'name': 'projects/project-id/programs/test/jobs/test', 'executionStatus': { 'state': 'READY' } } jobs.get().execute.return_value = { 'name': 'projects/project-id/programs/test/jobs/test', 'executionStatus': { 'state': 'SUCCESS' } } results_new_proto = copy.deepcopy(_RESULTS_V2) results_new_proto[ '@type'] = 'type.googleapis.com/cirq.google.api.v2.Result' jobs.getResult().execute.return_value = {'result': results_new_proto} engine = cg.Engine( project_id='project-id', proto_version=cg.engine.engine.ProtoVersion.V2, ) job = engine.run_sweep(program=_SCHEDULE, job_config=cg.JobConfig( 'project-id', gcs_prefix='gs://bucket/folder'), params=cirq.Points('a', [1, 2])) results = job.results() assert engine.proto_version == cg.engine.engine.ProtoVersion.V2 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')} build.assert_called_with( 'quantum', 'v1alpha1', discoveryServiceUrl=('https://{api}.googleapis.com' '/$discovery/rest?version=' '{apiVersion}'), requestBuilder=mock.ANY) assert programs.create.call_args[1]['parent'] == 'projects/project-id' sweeps = jobs.create.call_args[1]['body']['run_context']['parameterSweeps'] assert len(sweeps) == 1 assert sweeps[0]['repetitions'] == 1 assert sweeps[0]['sweep']['singleSweep']['points']['points'] == [1, 2] assert jobs.create.call_args[1][ 'parent'] == 'projects/project-id/programs/test' assert jobs.get().execute.call_count == 1 assert jobs.getResult().execute.call_count == 1
def test_missing_latest_calibration(build): service = mock.Mock() build.return_value = service calibrations = service.projects().processors().calibrations() calibrations.list().execute.return_value = {} processor_name = 'projects/p/processors/x' calibration = cg.Engine( api_key="key").get_latest_calibration(processor_name) assert calibrations.list.call_args[1]['parent'] == processor_name assert not calibration
def test_list_processors(list_processors): processor1 = qtypes.QuantumProcessor( name='projects/proj/processors/xmonsim') processor2 = qtypes.QuantumProcessor( name='projects/proj/processors/gmonsim') list_processors.return_value = [processor1, processor2] result = cg.Engine(project_id='proj').list_processors() list_processors.assert_called_once_with('proj') assert [p.processor_id for p in result] == ['xmonsim', 'gmonsim']
def test_schedule_device_validation_fails(build): scheduled_op = cirq.ScheduledOperation(time=None, duration=cirq.Duration(), operation=cirq.H.on( cirq.NamedQubit("dorothy"))) schedule = cirq.Schedule(device=cg.Foxtail, scheduled_operations=[scheduled_op]) with pytest.raises(ValueError): cg.Engine(project_id='project-id').run(program=schedule)
def test_circuit_device_validation_fails(build): circuit = cirq.Circuit(device=cg.Foxtail) # Purposefully create an invalid Circuit by fiddling with internal bits. # This simulates a failure in the incremental checks. circuit._moments.append(cirq.Moment([cirq.Z(cirq.NamedQubit("dorothy"))])) with pytest.raises(ValueError, match='Unsupported qubit type'): cg.Engine(project_id='project-id').run( program=circuit, job_config=cg.JobConfig('project-id'))
def test_get_program(client_constructor): client = mock.Mock() client_constructor.return_value = client fake_result = qtypes.QuantumProgram(name='project/my-project/program/foo') client.get_quantum_program.return_value = fake_result result = cg.Engine(project_id='my-project').get_program('foo') assert client.get_quantum_program.call_args[0][ 0] == 'projects/my-project/programs/foo' assert result == fake_result
def test_create_program(client_constructor): client = mock.Mock() client_constructor.return_value = client fake_result = qtypes.QuantumProgram(name='project/my-project/program/foo') client.create_quantum_program.return_value = fake_result result = cg.Engine(project_id='my-project').create_program(_CIRCUIT, 'foo') assert client.create_quantum_program.call_args[0][ 1].name == 'projects/my-project/programs/foo' assert result.resource_name == fake_result.name
def test_create_program(build): service = mock.Mock() build.return_value = service programs = service.projects().programs() fake_result = {'name': 'project/my-project/program/foo'} programs.create().execute.return_value = fake_result result = cg.Engine(project_id='my-project').create_program(_CIRCUIT, 'foo') assert programs.create.call_args[1]['body']['name'] == ( 'projects/my-project/programs/foo') assert result.resource_name == fake_result['name']
def test_get_program(build): service = mock.Mock() build.return_value = service programs = service.projects().programs() fake_result = ({'name': 'project/my-project/program/foo'}) programs.get().execute.return_value = fake_result result = cg.Engine(project_id='my-project').get_program('foo') assert programs.get.call_args[1]['name'] == ( 'projects/my-project/programs/foo') assert result == fake_result
def test_api_doesnt_retry_404_errors(build): service = mock.Mock() build.return_value = service getProgram = service.projects().programs().get() content = '{"error": {"message": "not found", "code": 404}}'.encode('utf-8') getProgram.execute.side_effect = HttpError(mock.Mock(), content) engine = cg.Engine(project_id='project-id') with pytest.raises(cg.engine.engine.EngineException, match='not found'): engine.get_program('foo') assert getProgram.execute.call_count == 1
def test_bad_priority(client_constructor): client = mock.Mock() client_constructor.return_value = client client.create_quantum_program.return_value = qtypes.QuantumProgram( name='projects/project-id/programs/test') engine = cg.Engine(project_id='project-id', proto_version=cg.engine.engine.ProtoVersion.V2) with pytest.raises(ValueError, match='priority must be'): engine.run(program=_CIRCUIT, priority=1001)
def test_bad_priority(build): service = mock.Mock() build.return_value = service programs = service.projects().programs() programs.create().execute.return_value = { 'name': 'projects/project-id/programs/test' } engine = cg.Engine(project_id='project-id', proto_version=cg.engine.engine.ProtoVersion.V2) with pytest.raises(ValueError, match='priority must be'): engine.run(program=_CIRCUIT, priority=1001)
def test_circuit_device_validation_fails(): circuit = cirq.Circuit(device=cg.Foxtail) # Purposefully create an invalid Circuit by fiddling with internal bits. # This simulates a failure in the incremental checks. circuit._moments.append(cirq.Moment([cirq.Z(cirq.NamedQubit("dorothy"))])) engine = cg.Engine(project_id='project-id') with pytest.raises(ValueError, match='Unsupported qubit type'): engine.run_sweep(program=circuit, gate_set=cg.XMON) with pytest.raises(ValueError, match='Unsupported qubit type'): engine.create_program(circuit, gate_set=cg.XMON)
def test_api_retry_connection_reset(build): service = mock.Mock() build.return_value = service getProgram = service.projects().programs().get() getProgram.execute.side_effect = ConnectionResetError() engine = cg.Engine(project_id='project-id') with pytest.raises(TimeoutError, match='Reached max retry attempts.*Lost connection'): engine.max_retry_delay = 1 # 1 second engine.get_program('foo') assert getProgram.execute.call_count > 1
def test_run_multiple_times(build): service = mock.Mock() build.return_value = service programs = service.projects().programs() jobs = programs.jobs() programs.create().execute.return_value = { 'name': 'projects/project-id/programs/test' } jobs.create().execute.return_value = { 'name': 'projects/project-id/programs/test/jobs/test', 'executionStatus': { 'state': 'READY' } } jobs.get().execute.return_value = { 'name': 'projects/project-id/programs/test/jobs/test', 'executionStatus': { 'state': 'SUCCESS' } } jobs.getResult().execute.return_value = {'result': _RESULTS} engine = cg.Engine(project_id='project-id') program = engine.create_program(program=_SCHEDULE) program.run(param_resolver=cirq.ParamResolver({'a': 1})) sweeps1 = jobs.create.call_args[1]['body']['run_context'][ 'parameter_sweeps'] job2 = program.run_sweep(repetitions=2, params=cirq.Points('a', [3, 4])) sweeps2 = jobs.create.call_args[1]['body']['run_context'][ 'parameter_sweeps'] results = job2.results() assert engine.proto_version == cg.engine.engine.ProtoVersion.V1 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')} build.assert_called_with( 'quantum', 'v1alpha1', discoveryServiceUrl=('https://{api}.googleapis.com' '/$discovery/rest?version=' '{apiVersion}'), requestBuilder=mock.ANY) assert len(sweeps1) == 1 assert sweeps1[0]['repetitions'] == 1 assert sweeps1[0]['sweep']['factors'][0]['sweeps'][0]['points'][ 'points'] == [1] assert len(sweeps2) == 1 assert sweeps2[0]['repetitions'] == 2 assert sweeps2[0]['sweep']['factors'][0]['sweeps'][0]['points'][ 'points'] == [3, 4] assert jobs.get().execute.call_count == 2 assert jobs.getResult().execute.call_count == 2
def test_schedule_device_validation_fails(build): scheduled_op = cirq.ScheduledOperation(time=None, duration=None, operation=cirq.H.on( cirq.NamedQubit("dorothy"))) schedule = cirq.Schedule(device=cg.Foxtail, scheduled_operations=[scheduled_op]) with pytest.raises(ValueError): cg.Engine(api_key="key").run(program=schedule, job_config=cg.JobConfig('project-id'))