def translate_result( braket_result: GateModelQuantumTaskResult, observable: Observable, targets: List[int], supported_result_types: FrozenSet[str], ) -> Any: """Translates a Braket result into the corresponding PennyLane return type value. Args: braket_result (GateModelQuantumTaskResult): The Braket result to translate. observable (Observable): The PennyLane observable associated with the result. targets (List[int]): The qubits in the result. supported_result_types (FrozenSet[str]): The result types supported by the device. Returns: Any: The translated return value. Note: Hamiltonian results will be summed over all terms. """ translated = translate_result_type(observable, targets, supported_result_types) if isinstance(observable, qml.Hamiltonian): coeffs, _ = observable.terms() return sum( coeff * braket_result.get_value_by_result_type(result_type) for coeff, result_type in zip(coeffs, translated) ) else: return braket_result.get_value_by_result_type(translated)
def test_from_object_equal_to_from_string(result_obj_1, result_str_1, result_str_3): assert GateModelQuantumTaskResult.from_object( result_obj_1) == GateModelQuantumTaskResult.from_string(result_str_1) assert GateModelQuantumTaskResult.from_object( GateModelTaskResult.parse_raw(result_str_3) ) == GateModelQuantumTaskResult.from_string(result_str_3)
def test_equality(result_str_1, result_str_2): result_1 = GateModelQuantumTaskResult.from_string(result_str_1) result_2 = GateModelQuantumTaskResult.from_string(result_str_1) other_result = GateModelQuantumTaskResult.from_string(result_str_2) non_result = "not a quantum task result" assert result_1 == result_2 assert result_1 is not result_2 assert result_1 != other_result assert result_1 != non_result
def test_calculate_ir_results(ir_result, expected_result): ir_string = jaqcd.Program( instructions=[jaqcd.H(target=i) for i in range(4)], results=[ir_result] ).json() measured_qubits = [0, 1, 2, 3] measurements = np.array( [ [0, 0, 1, 0], [1, 1, 1, 1], [1, 0, 0, 1], [0, 0, 1, 0], [1, 1, 1, 1], [0, 1, 1, 1], [0, 0, 0, 1], [0, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 1], ] ) result_types = GateModelQuantumTaskResult._calculate_result_types( ir_string, measurements, measured_qubits ) assert len(result_types) == 1 assert result_types[0].type == ir_result assert np.allclose(result_types[0].value, expected_result)
def test_run_gate_model(): dummy = DummyCircuitSimulator() sim = LocalSimulator(dummy) task = sim.run(Circuit().h(0).cnot(0, 1), 10) dummy.assert_shots(10) dummy.assert_qubits(2) assert task.result() == GateModelQuantumTaskResult.from_object(GATE_MODEL_RESULT)
def test_result_circuit_cached(circuit_task): _mock_metadata(circuit_task._aws_session, "COMPLETED") expected = GateModelQuantumTaskResult.from_string( MockS3.MOCK_S3_RESULT_GATE_MODEL) circuit_task._result = expected assert circuit_task.result() == expected assert not circuit_task._aws_session.retrieve_s3_object_body.called
def test_async_result(circuit_task): def set_result_from_callback(future): # Set the result_from_callback variable in the enclosing functions scope nonlocal result_from_callback result_from_callback = future.result() _mock_metadata(circuit_task._aws_session, "RUNNING") _mock_s3(circuit_task._aws_session, MockS3.MOCK_S3_RESULT_GATE_MODEL) future = circuit_task.async_result() # test the different ways to get the result from async # via callback result_from_callback = None future.add_done_callback(set_result_from_callback) # via asyncio waiting for result _mock_metadata(circuit_task._aws_session, "COMPLETED") event_loop = asyncio.get_event_loop() result_from_waiting = event_loop.run_until_complete(future) # via future.result(). Note that this would fail if the future is not complete. result_from_future = future.result() expected = GateModelQuantumTaskResult.from_string(MockS3.MOCK_S3_RESULT_GATE_MODEL) assert result_from_callback == expected assert result_from_waiting == expected assert result_from_future == expected
def test_measurement_probabilities_from_measurement_counts(): counts = {"00": 1, "01": 1, "10": 1, "11": 97} probabilities = {"00": 0.01, "01": 0.01, "10": 0.01, "11": 0.97} m_probabilities = GateModelQuantumTaskResult.measurement_probabilities_from_measurement_counts( counts) assert m_probabilities == probabilities
def test_measurement_counts_from_measurements(): measurements: np.ndarray = np.array([[1, 0, 1, 0], [0, 0, 0, 0], [1, 0, 1, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 1, 0]]) measurement_counts = GateModelQuantumTaskResult.measurement_counts_from_measurements( measurements) expected_counts: Counter = {"1010": 3, "0000": 1, "1000": 2} assert expected_counts == measurement_counts
def test_result_is_cached(circuit_task, result_string): _mock_metadata(circuit_task._aws_session, "COMPLETED") _mock_s3(circuit_task._aws_session, result_string) circuit_task.result() _mock_s3(circuit_task._aws_session, "") expected = GateModelQuantumTaskResult.from_string(MockS3.MOCK_S3_RESULT_GATE_MODEL) assert circuit_task.result() == expected
def test_result_type_skips_computation_already_populated(calculate_result_types_mocked): result_str = json.dumps( { "braketSchemaHeader": { "name": "braket.task_result.gate_model_task_result", "version": "1", }, "measurements": [[0]], "resultTypes": [ {"type": {"observable": ["z"], "targets": [0], "type": "variance"}, "value": 12.0} ], "measuredQubits": [0], "taskMetadata": { "braketSchemaHeader": {"name": "braket.task_result.task_metadata", "version": "1"}, "id": "arn:aws:braket:us-east-1:1234567890:quantum-task/22a238b2-ae96", "shots": 1, "deviceId": "arn:aws:braket:::device/quantum-simulator/amazon/dm1", "deviceParameters": { "braketSchemaHeader": { "name": "braket.device_schema.simulators." "gate_model_simulator_device_parameters", "version": "1", }, "paradigmParameters": { "braketSchemaHeader": { "name": "braket.device_schema.gate_model_parameters", "version": "1", }, "qubitCount": 1, "disableQubitRewiring": False, }, }, "createdAt": "2022-01-12T06:05:22.633Z", "endedAt": "2022-01-12T06:05:24.136Z", "status": "COMPLETED", }, "additionalMetadata": { "action": { "braketSchemaHeader": {"name": "braket.ir.openqasm.program", "version": "1"}, "source": "\nqubit[1] q;\nh q[0];\n#pragma braket result variance z(q[0])\n", }, "simulatorMetadata": { "braketSchemaHeader": { "name": "braket.task_result.simulator_metadata", "version": "1", }, "executionDuration": 16, }, }, } ) res = GateModelQuantumTaskResult.from_string(result_str) assert ( res.get_value_by_result_type(ResultType.Variance(observable=Observable.Z(), target=[0])) == 12 ) calculate_result_types_mocked.assert_not_called()
def test_from_object_result_types(result_obj_5): result_obj = result_obj_5 task_result = GateModelQuantumTaskResult.from_object(result_obj) expected_measurements = np.asarray(result_obj.measurements, dtype=int) assert np.array2string(task_result.measurements) == np.array2string(expected_measurements) assert np.allclose(task_result.values[0], np.array([0.6, 0.4])) assert task_result.values[1] == [0.4, 0.2, -0.2, -0.4] assert task_result.result_types[0].type == jaqcd.Probability(targets=[1]) assert task_result.result_types[1].type == jaqcd.Expectation(observable=["z"])
def _(circuit: Circuit, simulator: BraketSimulator, shots, *args, **kwargs): if DeviceActionType.JAQCD not in simulator.properties.action: raise NotImplementedError( f"{type(simulator)} does not support qubit gate-based programs") validate_circuit_and_shots(circuit, shots) program = circuit.to_ir() qubits = circuit.qubit_count results = simulator.run(program, qubits, shots, *args, **kwargs) return GateModelQuantumTaskResult.from_object(results)
def _(program: Program, simulator: BraketSimulator, shots: Optional[int] = None, *args, **kwargs): if DeviceActionType.OPENQASM not in simulator.properties.action: raise NotImplementedError( f"{type(simulator)} does not support OpenQASM programs") results = simulator.run(program, shots, *args, **kwargs) return GateModelQuantumTaskResult.from_object(results)
def test_translate_result(): result_dict = _result_meta() result_dict["resultTypes"] = [ {"type": {"targets": [0], "type": "probability"}, "value": [0.5, 0.5]} ] targets = [0] result_dict["measuredQubits"]: targets result = GateModelQuantumTaskResult.from_string(json.dumps(result_dict)) mp = MeasurementProcess(ObservableReturnTypes.Probability, wires=Wires([0])) translated = translate_result(result, mp, targets, frozenset()) assert (translated == result.result_types[0].value).all()
def test_measurements_from_measurement_probabilities(): shots = 5 probabilities = {"00": 0.2, "01": 0.2, "10": 0.2, "11": 0.4} measurements_list = [["0", "0"], ["0", "1"], ["1", "0"], ["1", "1"], ["1", "1"]] expected_results = np.asarray(measurements_list, dtype=int) measurements = GateModelQuantumTaskResult.measurements_from_measurement_probabilities( probabilities, shots) assert np.allclose(measurements, expected_results)
def test_from_string_simulator_only(result_obj_4, result_str_4): result_obj = result_obj_4 result = GateModelQuantumTaskResult.from_string(result_str_4) assert len(result.result_types) == len(result_obj.resultTypes) for i in range(len(result.result_types)): rt = result.result_types[i] expected_rt = result_obj.resultTypes[i] assert rt.type == expected_rt.type if isinstance(rt.value, np.ndarray): assert np.allclose(rt.value, expected_rt.value) else: assert rt.value == expected_rt.value
def test_from_string_measurement_probabilities(result_str_3): result_obj = GateModelTaskResult.parse_raw(result_str_3) task_result = GateModelQuantumTaskResult.from_string(result_str_3) assert task_result.measurement_probabilities == result_obj.measurementProbabilities shots = 100 measurement_list = [list("011000") for _ in range(shots)] expected_measurements = np.asarray(measurement_list, dtype=int) assert np.allclose(task_result.measurements, expected_measurements) assert task_result.measurement_counts == Counter(["011000" for x in range(shots)]) assert not task_result.measurement_counts_copied_from_device assert task_result.measurement_probabilities_copied_from_device assert not task_result.measurements_copied_from_device
def test_timeout_completed(aws_session): _mock_metadata(aws_session, "RUNNING") _mock_s3(aws_session, MockS3.MOCK_S3_RESULT_GATE_MODEL) # Setup the poll timing such that the timeout will occur after one API poll quantum_task = AwsQuantumTask( "foo:bar:arn", aws_session, poll_timeout_seconds=0.5, poll_interval_seconds=1, ) assert quantum_task.result() is None _mock_metadata(aws_session, "COMPLETED") assert quantum_task.state() == "COMPLETED" assert quantum_task.result() == GateModelQuantumTaskResult.from_string( MockS3.MOCK_S3_RESULT_GATE_MODEL) # Cached status is still COMPLETED, so result should be fetched _mock_metadata(aws_session, "RUNNING") quantum_task._result = None assert quantum_task.result() == GateModelQuantumTaskResult.from_string( MockS3.MOCK_S3_RESULT_GATE_MODEL)
def test_result_circuit(circuit_task): _mock_metadata(circuit_task._aws_session, "COMPLETED") _mock_s3(circuit_task._aws_session, MockS3.MOCK_S3_RESULT_GATE_MODEL) expected = GateModelQuantumTaskResult.from_string( MockS3.MOCK_S3_RESULT_GATE_MODEL) assert circuit_task.result() == expected s3_bucket = circuit_task.metadata()["outputS3Bucket"] s3_object_key = circuit_task.metadata()["outputS3Directory"] circuit_task._aws_session.retrieve_s3_object_body.assert_called_with( s3_bucket, f"{s3_object_key}/results.json")
def test_from_string_measurements(result_str_1): result_obj = GateModelTaskResult.parse_raw(result_str_1) task_result = GateModelQuantumTaskResult.from_string(result_str_1) expected_measurements = np.asarray(result_obj.measurements, dtype=int) assert task_result.task_metadata == result_obj.taskMetadata assert task_result.additional_metadata == result_obj.additionalMetadata assert np.array2string(task_result.measurements) == np.array2string(expected_measurements) assert not task_result.measurement_counts_copied_from_device assert not task_result.measurement_probabilities_copied_from_device assert task_result.measurements_copied_from_device assert task_result.measured_qubits == result_obj.measuredQubits assert task_result.values == [] assert task_result.result_types == []
def test_get_value_by_result_type(result_obj_4): result = GateModelQuantumTaskResult.from_object(result_obj_4) assert np.allclose( result.get_value_by_result_type(ResultType.Probability(target=0)), result.values[0] ) assert np.allclose(result.get_value_by_result_type(ResultType.StateVector()), result.values[1]) assert ( result.get_value_by_result_type(ResultType.Expectation(observable=Observable.Y(), target=0)) == result.values[2] ) assert ( result.get_value_by_result_type(ResultType.Variance(observable=Observable.Y(), target=0)) == result.values[3] ) assert result.get_value_by_result_type(ResultType.Amplitude(state=["00"])) == result.values[4]
def test_run_program_model(): dummy = DummyProgramSimulator() sim = LocalSimulator(dummy) task = sim.run( Program(source=""" qubit[2] q; bit[2] c; h q[0]; cnot q[0], q[1]; c = measure q; """)) assert task.result() == GateModelQuantumTaskResult.from_object( GATE_MODEL_RESULT)
def test_successful(mock_create): task_mock = Mock() type(task_mock).id = PropertyMock(side_effect=uuid.uuid4) task_mock.state.return_value = "COMPLETED" result = GateModelQuantumTaskResult.from_string(MockS3.MOCK_S3_RESULT_GATE_MODEL) task_mock.result.return_value = result mock_create.return_value = task_mock batch_size = 15 batch = AwsQuantumTaskBatch( Mock(), "foo", _circuits(batch_size), S3_TARGET, 1000, max_parallel=10 ) assert batch.size == batch_size assert not batch.unfinished assert not batch.unsuccessful assert batch.results() == [result for _ in range(batch_size)]
def test_retry(mock_create): bad_task_mock = Mock() type(bad_task_mock).id = PropertyMock(side_effect=uuid.uuid4) bad_task_mock.state.return_value = random.choice(["CANCELLED", "FAILED"]) bad_task_mock.result.return_value = None good_task_mock = Mock() # task id already mocked when setting up bad_task_mock good_task_mock.state.return_value = "COMPLETED" result = GateModelQuantumTaskResult.from_string( MockS3.MOCK_S3_RESULT_GATE_MODEL) good_task_mock.result.return_value = result mock_create.side_effect = [ bad_task_mock, good_task_mock, bad_task_mock, good_task_mock ] batch = AwsQuantumTaskBatch( Mock(), "foo", [Circuit().h(0).cnot(0, 1), Circuit().h(1).cnot(0, 1)], S3_TARGET, 1000, max_parallel=10, ) assert not batch.unfinished assert batch.results(max_retries=0) == [None, result] # Retrying should get rid of the failures assert batch.results(fail_unsuccessful=True, max_retries=3, use_cached_value=False) == [ result, result, ] assert batch.unsuccessful == set() # Don't retry if there's nothing to retry mock_create.side_effect = [bad_task_mock] assert batch.retry_unsuccessful_tasks() assert batch.unsuccessful == set() # Error if called before there are any results batch._results = None with pytest.raises(RuntimeError): batch.retry_unsuccessful_tasks()
def test_translate_result_hamiltonian(): result_dict = _result_meta() result_dict["resultTypes"] = [ { "type": {"observable": ["x", "y"], "targets": [0, 1], "type": "expectation"}, "value": 2.0, }, { "type": {"observable": ["x"], "targets": [1], "type": "expectation"}, "value": 3.0, }, ] targets = [0, 1] result_dict["measuredQubits"]: targets result = GateModelQuantumTaskResult.from_string(json.dumps(result_dict)) ham = qml.Hamiltonian((2, 1), (qml.PauliX(0) @ qml.PauliY(1), qml.PauliX(1))) ham.return_type = ObservableReturnTypes.Expectation translated = translate_result(result, ham, targets, frozenset()) expected = 2 * result.result_types[0].value + result.result_types[1].value assert translated == expected
def test_result_cached_future(circuit_task, result_string): _mock_metadata(circuit_task._aws_session, "COMPLETED") _mock_s3(circuit_task._aws_session, result_string) circuit_task.result() _mock_s3(circuit_task._aws_session, "") expected = GateModelQuantumTaskResult.from_string( MockS3.MOCK_S3_RESULT_GATE_MODEL) assert circuit_task.result() == expected @pytest.mark.parametrize( "status, result", [ ("COMPLETED", GateModelQuantumTaskResult.from_string( MockS3.MOCK_S3_RESULT_GATE_MODEL)), ("FAILED", None), ], ) def test_async_result(circuit_task, status, result): def set_result_from_callback(future): # Set the result_from_callback variable in the enclosing functions scope nonlocal result_from_callback result_from_callback = future.result() _mock_metadata(circuit_task._aws_session, "RUNNING") _mock_s3(circuit_task._aws_session, MockS3.MOCK_S3_RESULT_GATE_MODEL) future = circuit_task.async_result() # test the different ways to get the result from async
def _(result: GateModelTaskResult) -> GateModelQuantumTaskResult: GateModelQuantumTaskResult.cast_result_types(result) return GateModelQuantumTaskResult.from_object(result)
def test_execute_all_samples(mock_run): result = GateModelQuantumTaskResult.from_string( json.dumps({ "braketSchemaHeader": { "name": "braket.task_result.gate_model_task_result", "version": "1", }, "measurements": [[0, 0, 1], [1, 0, 1], [1, 1, 0], [0, 0, 0]], "resultTypes": [ { "type": { "observable": ["h", "i"], "targets": [0, 1], "type": "sample" }, "value": [1, -1, 1, 1], }, { "type": { "observable": [[[[0.0, 0.0], [1.0, 0.0]], [[1.0, 0.0], [0.0, 0.0]]]], "targets": [2], "type": "sample", }, "value": [1, -1, 1, 1], }, ], "measuredQubits": [0, 1, 3], "taskMetadata": { "braketSchemaHeader": { "name": "braket.task_result.task_metadata", "version": "1", }, "id": "task_arn", "shots": 0, "deviceId": "default", }, "additionalMetadata": { "action": { "braketSchemaHeader": { "name": "braket.ir.jaqcd.program", "version": "1" }, "instructions": [{ "control": 0, "target": 1, "type": "cnot" }], }, }, })) task = Mock() task.result.return_value = result mock_run.return_value = task dev = _aws_device(wires=3) with QuantumTape() as circuit: qml.Hadamard(wires=0) qml.CNOT(wires=[0, 1]) qml.sample(qml.Hadamard(0) @ qml.Identity(1)) qml.sample(qml.Hermitian(np.array([[0, 1], [1, 0]]), wires=[2])) assert dev.execute(circuit).shape == (2, 4)
RESULT = GateModelQuantumTaskResult.from_string( json.dumps({ "braketSchemaHeader": { "name": "braket.task_result.gate_model_task_result", "version": "1", }, "measurements": [[0, 0, 0, 0], [1, 1, 1, 1], [1, 1, 0, 0], [0, 0, 1, 1]], "resultTypes": [ { "type": { "targets": [0], "type": "probability" }, "value": [0.5, 0.5] }, { "type": { "observable": ["x"], "targets": [1], "type": "expectation" }, "value": 0.0, }, { "type": { "observable": ["y"], "targets": [2], "type": "variance" }, "value": 0.1 }, { "type": { "observable": ["z"], "targets": [3], "type": "sample" }, "value": [1, -1, 1, 1], }, ], "measuredQubits": [0, 1, 2, 3], "taskMetadata": { "braketSchemaHeader": { "name": "braket.task_result.task_metadata", "version": "1" }, "id": "task_arn", "shots": 0, "deviceId": "default", }, "additionalMetadata": { "action": { "braketSchemaHeader": { "name": "braket.ir.jaqcd.program", "version": "1" }, "instructions": [{ "control": 0, "target": 1, "type": "cnot" }], }, }, }))