Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions src/braket/tasks/gate_model_quantum_task_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)

Expand All @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading