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 

16from typing import Any, Dict, List 

17 

18from braket.circuits.observable import Observable 

19from braket.circuits.qubit import QubitInput 

20from braket.circuits.qubit_set import QubitSet, QubitSetInput 

21 

22 

23class ResultType: 

24 """ 

25 Class `ResultType` represents a requested result type for the circuit. 

26 This class is considered the result type definition containing 

27 the metadata that defines what a requested result type is and what it does. 

28 """ 

29 

30 def __init__(self, ascii_symbols: List[str]): 

31 """ 

32 Args: 

33 ascii_symbols (List[str]): ASCII string symbols for the result type. This is used when 

34 printing a diagram of circuits. 

35 

36 Raises: 

37 ValueError: `ascii_symbols` is None 

38 """ 

39 

40 if ascii_symbols is None: 

41 raise ValueError("ascii_symbols must not be None") 

42 

43 self._ascii_symbols = ascii_symbols 

44 

45 @property 

46 def ascii_symbols(self) -> List[str]: 

47 """List[str]: Returns the ascii symbols for the requested result type.""" 

48 return self._ascii_symbols 

49 

50 @property 

51 def name(self) -> str: 

52 """ 

53 Returns the name of the result type 

54 

55 Returns: 

56 The name of the result type as a string 

57 """ 

58 return self.__class__.__name__ 

59 

60 def to_ir(self, *args, **kwargs) -> Any: 

61 """Returns IR object of the result type 

62 

63 Args: 

64 *args: Positional arguments 

65 **kwargs: Keyword arguments 

66 

67 Returns: 

68 IR object of the result type 

69 """ 

70 raise NotImplementedError("to_ir has not been implemented yet.") 

71 

72 def copy(self, target_mapping: Dict[QubitInput, QubitInput] = {}, target: QubitSetInput = None): 

73 """ 

74 Return a shallow copy of the result type. 

75 

76 Note: 

77 If `target_mapping` is specified, then `self.target` is mapped to the specified 

78 qubits. This is useful apply an instruction to a circuit and change the target qubits. 

79 

80 Args: 

81 target_mapping (dictionary[int or Qubit, int or Qubit], optional): A dictionary of 

82 qubit mappings to apply to the target. Key is the qubit in this `target` and the 

83 value is what the key is changed to. Default = {}. 

84 target (int, Qubit, or iterable of int / Qubit, optional): Target qubits for the new 

85 instruction. 

86 

87 Returns: 

88 ResultType: A shallow copy of the result type. 

89 

90 Raises: 

91 TypeError: If both `target_mapping` and `target` are supplied. 

92 

93 Examples: 

94 >>> result_type = ResultType.Probabilities(targets=[0]) 

95 >>> new_result_type = result_type.copy() 

96 >>> new_result_type.targets 

97 QubitSet(Qubit(0)) 

98 >>> new_result = result_type.copy(target_mapping={0: 5}) 

99 >>> new_result_type.target 

100 QubitSet(Qubit(5)) 

101 >>> new_result = result_type.copy(target=[5]) 

102 >>> new_result_type.target 

103 QubitSet(Qubit(5)) 

104 """ 

105 copy = self.__copy__() 

106 if target_mapping and target is not None: 

107 raise TypeError("Only 'target_mapping' or 'target' can be supplied, but not both.") 

108 elif target is not None: 

109 if hasattr(copy, "target"): 

110 copy.target = target 

111 else: 

112 if hasattr(copy, "target"): 

113 copy.target = self._target.map(target_mapping) 

114 return copy 

115 

116 @classmethod 

117 def register_result_type(cls, result_type: "ResultType"): 

118 """Register a result type implementation by adding it into the ResultType class. 

119 

120 Args: 

121 result_type (ResultType): ResultType instance to register. 

122 """ 

123 setattr(cls, result_type.__name__, result_type) 

124 

125 def __repr__(self) -> str: 

126 return f"{self.name}()" 

127 

128 

129class ObservableResultType(ResultType): 

130 """ 

131 Result types with observables and targets. 

132 If no targets are specified, the observable must only operate on 1 qubit and it 

133 will be applied to all qubits in parallel. Otherwise, the number of specified targets 

134 must be equivalent to the number of qubits the observable can be applied to. 

135 

136 See :mod:`braket.circuits.observables` module for all of the supported observables. 

137 """ 

138 

139 def __init__( 

140 self, ascii_symbols: List[str], observable: Observable, target: QubitSetInput = None 

141 ): 

142 """ 

143 Args: 

144 observable (Observable): the observable for the result type 

145 target (int, Qubit, or iterable of int / Qubit, optional): Target qubits that the 

146 result type is requested for. Default is None, which means the observable must 

147 only operate on 1 qubit and it will be applied to all qubits in parallel 

148 

149 Raises: 

150 ValueError: if target=None and the observable's qubit count is not 1. 

151 Or, if target!=None and the observable's qubit count and the number of target qubits 

152 are not equal. Or, if target!=None and the observable's qubit count and 

153 the number of ascii_symbols are not equal. 

154 """ 

155 super().__init__(ascii_symbols) 

156 self._observable = observable 

157 self._target = QubitSet(target) 

158 if not self._target: 

159 if self._observable.qubit_count != 1: 

160 raise ValueError( 

161 f"Observable {self._observable} must only operate on 1 qubit for target=None" 

162 ) 

163 else: 

164 if self._observable.qubit_count != len(self._target): 

165 raise ValueError( 

166 "Observable's qubit count and the number of target qubits must be equal" 

167 ) 

168 if self._observable.qubit_count != len(self.ascii_symbols): 

169 raise ValueError( 

170 "Observable's qubit count and the number of ASCII symbols must be equal" 

171 ) 

172 

173 @property 

174 def observable(self) -> Observable: 

175 return self._observable 

176 

177 @property 

178 def target(self) -> QubitSet: 

179 return self._target 

180 

181 @target.setter 

182 def target(self, target: QubitSetInput) -> None: 

183 self._target = QubitSet(target) 

184 

185 def __eq__(self, other) -> bool: 

186 if isinstance(other, ObservableResultType): 

187 return ( 

188 self.name == other.name 

189 and self.target == other.target 

190 and self.observable == other.observable 

191 ) 

192 return NotImplemented 

193 

194 def __repr__(self) -> str: 

195 return f"{self.name}(observable={self.observable}, target={self.target})" 

196 

197 def __copy__(self) -> ObservableResultType: 

198 return type(self)(observable=self.observable, target=self.target)