diff --git a/src/braket/tasks/gate_model_quantum_task_result.py b/src/braket/tasks/gate_model_quantum_task_result.py index 9591fe187..0b945cb5c 100644 --- a/src/braket/tasks/gate_model_quantum_task_result.py +++ b/src/braket/tasks/gate_model_quantum_task_result.py @@ -64,20 +64,22 @@ class GateModelQuantumTaskResult: This is calculated from `measurements` and the IR of the circuit program when `shots>0`. measurements (numpy.ndarray | None): 2d array - row is shot and column is qubit. - Default is None. Only available when shots > 0. The qubits in `measurements` - are the ones in `GateModelQuantumTaskResult.measured_qubits`. + Default is None. Only available when shots > 0 and the result does not report + `outputs`. The qubits in `measurements` are the ones in + `GateModelQuantumTaskResult.measured_qubits`. measured_qubits (list[int] | None): The indices of the measured qubits. Default - is None. Only available when shots > 0. Indicates which qubits are in - `measurements`. + is None. Only available when shots > 0 and the result does not report `outputs`. + Indicates which qubits are in `measurements`. measurement_counts (Counter | None): A `Counter` of measurements. Key is the measurements in a big endian binary string. Value is the number of times that measurement occurred. - Default is None. Only available when shots > 0. Note that the keys in `Counter` are - unordered. + Default is None. Only available when shots > 0 and the result does not report + `outputs`. Note that the keys in `Counter` are unordered. measurement_probabilities (dict[str, float] | None): A dictionary of probabilistic results. Key is the measurements in a big endian binary string. Value is the probability the measurement occurred. - Default is None. Only available when shots > 0. + Default is None. Only available when shots > 0 and the result does not report + `outputs`. measurements_copied_from_device (bool | None): flag whether `measurements` were copied from device. If false, `measurements` are calculated from device data. Default is None. Only available when shots > 0. @@ -225,8 +227,8 @@ def from_object(result: GateModelTaskResult) -> GateModelQuantumTaskResult: GateModelQuantumTaskResult: A GateModelQuantumTaskResult based on the given dict Raises: - ValueError: If neither "Measurements" nor "MeasurementProbabilities" is a key - in the result dict + ValueError: If none of "measurements", "measurementProbabilities" or "outputs" + is populated in the result """ return GateModelQuantumTaskResult._from_object_internal(result) @@ -241,8 +243,8 @@ def from_string(result: str) -> GateModelQuantumTaskResult: GateModelQuantumTaskResult: A GateModelQuantumTaskResult based on the given string Raises: - ValueError: If neither "Measurements" nor "MeasurementProbabilities" is a key - in the result dict + ValueError: If none of "measurements", "measurementProbabilities" or "outputs" + is populated in the result """ obj = GateModelTaskResult.parse_raw(result) GateModelQuantumTaskResult.cast_result_types(obj) @@ -281,10 +283,15 @@ def _from_object_internal_computational_basis_sampling( measurements_copied_from_device = False m_counts_copied_from_device = False m_probabilities_copied_from_device = True + elif result.outputs is not None: + measurements = m_counts = m_probs = None + measurements_copied_from_device = False + m_counts_copied_from_device = False + m_probabilities_copied_from_device = False else: raise ValueError( - 'One of "measurements" or "measurementProbabilities" must be populated in', - " the result obj", + 'One of "measurements", "measurementProbabilities" or "outputs" must be ' + "populated in the result object" ) measured_qubits = result.measuredQubits if result.resultTypes: 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 bd51c3f8d..51dfd2be9 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 @@ -509,9 +509,40 @@ def test_get_value_by_result_type_value_error(result_obj_4): result.get_value_by_result_type(ResultType.Probability(target=[0, 1])) -@pytest.mark.xfail(raises=ValueError) def test_shots_no_measurements_no_measurement_probs(malformatted_results_1): - GateModelQuantumTaskResult.from_string(malformatted_results_1) + with pytest.raises( + ValueError, + match='One of "measurements", "measurementProbabilities" or "outputs" must be populated', + ): + GateModelQuantumTaskResult.from_string(malformatted_results_1) + + +@pytest.fixture +def outputs_only_result(task_metadata_shots, additional_metadata_openqasm): + return GateModelTaskResult( + outputs=[{"c": [0, 0]}, {"c": [1, 1]}], + taskMetadata=task_metadata_shots, + additionalMetadata=additional_metadata_openqasm, + ) + + +def test_from_object_outputs_only(outputs_only_result): + result = GateModelQuantumTaskResult.from_object(outputs_only_result) + assert result.outputs == [{"c": [0, 0]}, {"c": [1, 1]}] + assert result.measurements is None + assert result.measured_qubits is None + assert result.measurement_counts is None + assert result.measurement_probabilities is None + assert result.result_types == [] + assert not result.measurements_copied_from_device + assert not result.measurement_counts_copied_from_device + assert not result.measurement_probabilities_copied_from_device + + +def test_from_string_outputs_only(outputs_only_result): + result = GateModelQuantumTaskResult.from_string(outputs_only_result.json()) + assert result.outputs == [{"c": [0, 0]}, {"c": [1, 1]}] + assert result.measurements is None @pytest.mark.parametrize("ir_result,expected_result", test_ir_results)