Coverage for src/braket/tasks/gate_model_quantum_task_result.py : 99%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Copyright 2019-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"). You
4# may not use this file except in compliance with the License. A copy of
5# the License is located at
6#
7# http://aws.amazon.com/apache2.0/
8#
9# or in the "license" file accompanying this file. This file is
10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11# ANY KIND, either express or implied. See the License for the specific
12# language governing permissions and limitations under the License.
14from __future__ import annotations
16import json
17from dataclasses import dataclass
18from typing import Any, Counter, Dict
20import numpy as np
23@dataclass
24class GateModelQuantumTaskResult:
25 """
26 Result of a gate model quantum task execution. This class is intended
27 to be initialized by a QuantumTask class.
29 Args:
30 measurements (numpy.ndarray): 2d array - row is shot, column is qubit.
31 measurement_counts (Counter): A Counter of measurements. Key is the measurements
32 in a big endian binary string. Value is the number of times that measurement occurred.
33 measurement_probabilities (Dict[str, float]): A dictionary of probabilistic results.
34 Key is the measurements in a big endian binary string.
35 Value is the probability the measurement occurred.
36 measurements_copied_from_device (bool): flag whether `measurements` were copied from device.
37 If false, `measurements` are calculated from device data.
38 measurement_counts_copied_from_device (bool): flag whether `measurement_counts` were copied
39 from device. If false, `measurement_counts` are calculated from device data.
40 measurement_probabilities_copied_from_device (bool): flag whether
41 `measurement_probabilities` were copied from device. If false,
42 `measurement_probabilities` are calculated from device data.
43 task_metadata (Dict[str, Any]): Dictionary of task metadata.
44 state_vector (Dict[str, complex]): Dictionary where Key is state and Value is amplitude.
45 """
47 measurements: np.ndarray
48 measurement_counts: Counter
49 measurement_probabilities: Dict[str, float]
50 measurements_copied_from_device: bool
51 measurement_counts_copied_from_device: bool
52 measurement_probabilities_copied_from_device: bool
53 task_metadata: Dict[str, Any]
54 state_vector: Dict[str, complex] = None
56 def __eq__(self, other) -> bool:
57 if isinstance(other, GateModelQuantumTaskResult):
58 # __eq__ on numpy arrays results in an array of booleans and therefore can't use
59 # the default dataclass __eq__ implementation. Override equals to check if all
60 # elements in the array are equal.
61 self_fields = (self.task_metadata, self.state_vector)
62 other_fields = (other.task_metadata, other.state_vector)
63 return (self.measurements == other.measurements).all() and self_fields == other_fields
64 return NotImplemented
66 @staticmethod
67 def measurement_counts_from_measurements(measurements: np.ndarray) -> Counter:
68 """
69 Creates measurement counts from measurements
71 Args:
72 measurements (numpy.ndarray): 2d array - row is shot, column is qubit.
74 Returns:
75 Counter: A Counter of measurements. Key is the measurements in a big endian binary
76 string. Value is the number of times that measurement occurred.
77 """
78 bitstrings = []
79 for j in range(len(measurements)):
80 bitstrings.append("".join([str(element) for element in measurements[j]]))
81 return Counter(bitstrings)
83 @staticmethod
84 def measurement_probabilities_from_measurement_counts(
85 measurement_counts: Counter,
86 ) -> Dict[str, float]:
87 """
88 Creates measurement probabilities from measurement counts
90 Args:
91 measurement_counts (Counter): A Counter of measurements. Key is the measurements
92 in a big endian binary string. Value is the number of times that measurement
93 occurred.
95 Returns:
96 Dict[str, float]: A dictionary of probabilistic results. Key is the measurements
97 in a big endian binary string. Value is the probability the measurement occurred.
98 """
99 measurement_probabilities = {}
100 shots = sum(measurement_counts.values())
102 for key, count in measurement_counts.items():
103 measurement_probabilities[key] = count / shots
104 return measurement_probabilities
106 @staticmethod
107 def measurements_from_measurement_probabilities(
108 measurement_probabilities: Dict[str, float], shots: int
109 ) -> np.ndarray:
110 """
111 Creates measurements from measurement probabilities
113 Args:
114 measurement_probabilities (Dict[str, float]): A dictionary of probabilistic results.
115 Key is the measurements in a big endian binary string.
116 Value is the probability the measurement occurred.
117 shots (int): number of iterations on device
119 Returns:
120 Dict[str, float]: A dictionary of probabilistic results.
121 Key is the measurements in a big endian binary string.
122 Value is the probability the measurement occurred.
123 """
124 measurements_list = []
125 for bitstring in measurement_probabilities:
126 measurement = list(bitstring)
127 individual_measurement_list = [measurement] * int(
128 round(measurement_probabilities[bitstring] * shots)
129 )
130 measurements_list.extend(individual_measurement_list)
131 return np.asarray(measurements_list, dtype=int)
133 @staticmethod
134 def from_string(result: str) -> GateModelQuantumTaskResult:
135 """
136 Create GateModelQuantumTaskResult from string
138 Args:
139 result (str): JSON object string, with GateModelQuantumTaskResult attributes as keys.
141 Returns:
142 GateModelQuantumTaskResult: A GateModelQuantumTaskResult based on a string
143 """
144 json_obj = json.loads(result)
145 task_metadata = json_obj["TaskMetadata"]
146 state_vector = json_obj.get("StateVector", None)
147 if state_vector:
148 for state in state_vector:
149 state_vector[state] = complex(*state_vector[state])
150 if "Measurements" in json_obj:
151 measurements = np.asarray(json_obj["Measurements"], dtype=int)
152 m_counts = GateModelQuantumTaskResult.measurement_counts_from_measurements(measurements)
153 m_probs = GateModelQuantumTaskResult.measurement_probabilities_from_measurement_counts(
154 m_counts
155 )
156 measurements_copied_from_device = True
157 m_counts_copied_from_device = False
158 m_probabilities_copied_from_device = False
159 elif "MeasurementProbabilities" in json_obj: 159 ↛ 169line 159 didn't jump to line 169, because the condition on line 159 was never false
160 shots = task_metadata["Shots"]
161 m_probs = json_obj["MeasurementProbabilities"]
162 measurements = GateModelQuantumTaskResult.measurements_from_measurement_probabilities(
163 m_probs, shots
164 )
165 m_counts = GateModelQuantumTaskResult.measurement_counts_from_measurements(measurements)
166 measurements_copied_from_device = False
167 m_counts_copied_from_device = False
168 m_probabilities_copied_from_device = True
169 return GateModelQuantumTaskResult(
170 state_vector=state_vector,
171 task_metadata=task_metadata,
172 measurements=measurements,
173 measurement_counts=m_counts,
174 measurement_probabilities=m_probs,
175 measurements_copied_from_device=measurements_copied_from_device,
176 measurement_counts_copied_from_device=m_counts_copied_from_device,
177 measurement_probabilities_copied_from_device=m_probabilities_copied_from_device,
178 )