Hide keyboard shortcuts

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. 

13 

14from __future__ import annotations 

15 

16import json 

17from dataclasses import dataclass 

18from typing import Any, Counter, Dict 

19 

20import numpy as np 

21 

22 

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. 

28 

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 """ 

46 

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 

55 

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 

65 

66 @staticmethod 

67 def measurement_counts_from_measurements(measurements: np.ndarray) -> Counter: 

68 """ 

69 Creates measurement counts from measurements 

70 

71 Args: 

72 measurements (numpy.ndarray): 2d array - row is shot, column is qubit. 

73 

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) 

82 

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 

89 

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. 

94 

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()) 

101 

102 for key, count in measurement_counts.items(): 

103 measurement_probabilities[key] = count / shots 

104 return measurement_probabilities 

105 

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 

112 

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 

118 

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) 

132 

133 @staticmethod 

134 def from_dict(result: Dict[str, Any]): 

135 """ 

136 Create GateModelQuantumTaskResult from dict. 

137 

138 Args: 

139 result (Dict[str, Any]): Results dict with GateModelQuantumTaskResult attributes as keys 

140 

141 Returns: 

142 GateModelQuantumTaskResult: A GateModelQuantumTaskResult based on the given dict 

143 

144 Raises: 

145 ValueError: If neither "Measurements" nor "MeasurementProbabilities" is a key 

146 in the result dict 

147 

148 Note: 

149 For the "StateVector" key, the value should be of type Dict[str, complex]; 

150 each bitstring's amplitude is a Python complex number. 

151 """ 

152 return GateModelQuantumTaskResult._from_dict_internal(result) 

153 

154 @staticmethod 

155 def from_string(result: str) -> GateModelQuantumTaskResult: 

156 """ 

157 Create GateModelQuantumTaskResult from string. 

158 

159 Args: 

160 result (str): JSON object string, with GateModelQuantumTaskResult attributes as keys. 

161 

162 Returns: 

163 GateModelQuantumTaskResult: A GateModelQuantumTaskResult based on the given string 

164 

165 Raises: 

166 ValueError: If neither "Measurements" nor "MeasurementProbabilities" is a key 

167 in the result dict 

168 

169 Note: 

170 For the "StateVector" key, the value should be of type Dict[str, List[float, float]]; 

171 each bitstring's amplitude is represented by a two-element list, with first element 

172 the real component and second element the imaginary component. 

173 """ 

174 json_obj = json.loads(result) 

175 state_vector = json_obj.get("StateVector", None) 

176 if state_vector: 

177 for state in state_vector: 

178 state_vector[state] = complex(*state_vector[state]) 

179 return GateModelQuantumTaskResult._from_dict_internal(json_obj) 

180 

181 @classmethod 

182 def _from_dict_internal(cls, result: Dict[str, Any]): 

183 task_metadata = result["TaskMetadata"] 

184 state_vector = result.get("StateVector", None) 

185 if "Measurements" in result: 

186 measurements = np.asarray(result["Measurements"], dtype=int) 

187 m_counts = GateModelQuantumTaskResult.measurement_counts_from_measurements(measurements) 

188 m_probs = GateModelQuantumTaskResult.measurement_probabilities_from_measurement_counts( 

189 m_counts 

190 ) 

191 measurements_copied_from_device = True 

192 m_counts_copied_from_device = False 

193 m_probabilities_copied_from_device = False 

194 elif "MeasurementProbabilities" in result: 

195 shots = task_metadata["Shots"] 

196 m_probs = result["MeasurementProbabilities"] 

197 measurements = GateModelQuantumTaskResult.measurements_from_measurement_probabilities( 

198 m_probs, shots 

199 ) 

200 m_counts = GateModelQuantumTaskResult.measurement_counts_from_measurements(measurements) 

201 measurements_copied_from_device = False 

202 m_counts_copied_from_device = False 

203 m_probabilities_copied_from_device = True 

204 else: 

205 raise ValueError( 

206 'One of "Measurements" or "MeasurementProbabilities" must be in the results dict' 

207 ) 

208 return cls( 

209 state_vector=state_vector, 

210 task_metadata=task_metadata, 

211 measurements=measurements, 

212 measurement_counts=m_counts, 

213 measurement_probabilities=m_probs, 

214 measurements_copied_from_device=measurements_copied_from_device, 

215 measurement_counts_copied_from_device=m_counts_copied_from_device, 

216 measurement_probabilities_copied_from_device=m_probabilities_copied_from_device, 

217 )