From 5ed43f3d1676a6e00cd1ea4be998a73c5800c269 Mon Sep 17 00:00:00 2001 From: Lauren Capelluto Date: Wed, 8 Nov 2023 15:30:02 -0500 Subject: [PATCH] feature: Add get_compiled_circuit convenience method (#787) * feature: Add get_compiled_circuit convenience method to GateModelQuantumTaskResult --- .../tasks/gate_model_quantum_task_result.py | 17 +++ .../test_gate_model_quantum_task_result.py | 112 ++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/src/braket/tasks/gate_model_quantum_task_result.py b/src/braket/tasks/gate_model_quantum_task_result.py index 453dcacfb..631ca45e7 100644 --- a/src/braket/tasks/gate_model_quantum_task_result.py +++ b/src/braket/tasks/gate_model_quantum_task_result.py @@ -134,6 +134,23 @@ def __eq__(self, other) -> bool: return self.task_metadata.id == other.task_metadata.id return NotImplemented + def get_compiled_circuit(self) -> Optional[str]: + """ + Get the compiled circuit, if one is available. + + Returns: + Optional[str]: The compiled circuit or None. + """ + metadata = self.additional_metadata + if not metadata: + return None + if metadata.rigettiMetadata: + return metadata.rigettiMetadata.compiledProgram + elif metadata.oqcMetadata: + return metadata.oqcMetadata.compiledProgram + else: + return None + @staticmethod def measurement_counts_from_measurements(measurements: np.ndarray) -> Counter: """ diff --git a/test/unit_tests/braket/tasks/test_gate_model_quantum_task_result.py b/test/unit_tests/braket/tasks/test_gate_model_quantum_task_result.py index 7a9ae3a20..8c0f8d9a9 100644 --- a/test/unit_tests/braket/tasks/test_gate_model_quantum_task_result.py +++ b/test/unit_tests/braket/tasks/test_gate_model_quantum_task_result.py @@ -26,6 +26,8 @@ ResultTypeValue, TaskMetadata, ) +from braket.task_result.oqc_metadata_v1 import OqcMetadata +from braket.task_result.rigetti_metadata_v1 import RigettiMetadata from braket.tasks import GateModelQuantumTaskResult @@ -61,6 +63,79 @@ def additional_metadata_openqasm(): return AdditionalMetadata(action=program) +@pytest.fixture +def quil_program(): + return """ +PRAGMA INITIAL_REWIRING "NAIVE" +RESET +DECLARE ro BIT[2] +PRAGMA PRESERVE_BLOCK +RX(1.5707963267948966) 0 +RX(1.5707963267948966) 7 +RZ(1.5707963267948966) 0 +RZ(1.5707963267948966) 7 +RX(-1.5707963267948966) 7 +CZ 0 7 +RZ(3.141592653589793) 7 +RX(1.5707963267948966) 7 +RZ(1.5707963267948966) 7 +RX(-1.5707963267948966) 7 +PRAGMA END_PRESERVE_BLOCK +MEASURE 0 ro[0] +MEASURE 7 ro[1] +""" + + +@pytest.fixture +def additional_metadata_rigetti(quil_program): + program = openqasm.Program( + source=""" + OPENQASM 3.0; + bit[2] b; + h $0; + cnot $0, $7; + b[0] = measure $0; + b[1] = measure $7; + """ + ) + rigetti_metadata = RigettiMetadata(compiledProgram=quil_program) + + return AdditionalMetadata(action=program, rigettiMetadata=rigetti_metadata) + + +@pytest.fixture +def qasm2_program(): + return """ + OPENQASM 2.0; + include "qelib1.inc"; + + qreg node[8]; + creg b[2]; + u3(0.5*pi,0.0*pi,1.0*pi) node[0]; + cx node[0],node[1]; + measure node[0] -> b[0]; + measure node[1] -> b[1]; + """ + + +@pytest.fixture +def additional_metadata_oqc(qasm2_program): + program = openqasm.Program( + source=""" + OPENQASM 3.0; + bit[2] b; + qubit[8] q; + h q[0]; + cnot q[0], q[7]; + b[0] = measure q[0]; + b[1] = measure q[7]; + """ + ) + oqc_metadata = OqcMetadata(compiledProgram=qasm2_program) + + return AdditionalMetadata(action=program, oqcMetadata=oqc_metadata) + + @pytest.fixture def result_obj_1(task_metadata_shots, additional_metadata): return GateModelTaskResult( @@ -71,6 +146,20 @@ def result_obj_1(task_metadata_shots, additional_metadata): ) +@pytest.fixture +def result_rigetti(result_obj_1, additional_metadata_rigetti): + result = GateModelQuantumTaskResult.from_object(result_obj_1) + result.additional_metadata = additional_metadata_rigetti + return result + + +@pytest.fixture +def result_oqc(result_obj_1, additional_metadata_oqc): + result = GateModelQuantumTaskResult.from_object(result_obj_1) + result.additional_metadata = additional_metadata_oqc + return result + + @pytest.fixture def result_str_1(result_obj_1): return result_obj_1.json() @@ -234,6 +323,29 @@ def test_openqasm_shots_calculate_result_types(openqasm_result_obj_shots): ] +def test_get_compiled_circuit_rigetti(result_rigetti, quil_program): + """Test get_compiled_circuit method.""" + assert result_rigetti.get_compiled_circuit() == quil_program + + +def test_get_compiled_circuit_oqc(result_oqc, qasm2_program): + """Test get_compiled_circuit method.""" + assert result_oqc.get_compiled_circuit() == qasm2_program + + +def test_get_compiled_circuit_no_qhp_metadata(result_obj_1): + """Test get_compiled_circuit method.""" + result = GateModelQuantumTaskResult.from_object(result_obj_1) + assert result.get_compiled_circuit() is None + + +def test_get_compiled_circuit_no_metadata(result_obj_1): + """Test that the method does not raise an error if metadata is missing.""" + result = GateModelQuantumTaskResult.from_object(result_obj_1) + result.additional_metadata = None + assert result.get_compiled_circuit() is None + + 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]]