@@ -48,77 +48,79 @@ def __init__(
48
48
self , control_values : Sequence [Union [int , Collection [int ], Type ['ControlValues' ]]]
49
49
):
50
50
if len (control_values ) == 0 :
51
- self .vals = cast (Tuple [Tuple [int , ...], ...], (()))
52
- self .num_variables = 0
53
- self .nxt = None
54
- self .itr = None
51
+ self ._vals = cast (Tuple [Tuple [int , ...], ...], (()))
52
+ self ._num_variables = 0
53
+ self ._nxt = None
55
54
return
56
- self .itr = None
57
- self .nxt = None
55
+ self ._nxt = None
58
56
59
57
if len (control_values ) > 1 :
60
- self .nxt = ControlValues (control_values [1 :])
58
+ self ._nxt = ControlValues (control_values [1 :])
61
59
62
60
if isinstance (control_values [0 ], ControlValues ):
63
61
aux = control_values [0 ].copy ()
64
- aux .product (self .nxt )
65
- self .vals , self .num_variables , self .nxt = aux .vals , aux .num_variables , aux .nxt
66
- self .vals = cast (Tuple [Tuple [int , ...], ...], self .vals )
62
+ aux .product (self ._nxt )
63
+ self ._vals , self ._num_variables , self ._nxt = aux ._vals , aux ._num_variables , aux ._nxt
64
+ self ._vals = cast (Tuple [Tuple [int , ...], ...], self ._vals )
67
65
return
68
66
69
67
val = control_values [0 ]
70
68
if isinstance (val , int ):
71
- self .vals = _from_int (val )
69
+ self ._vals = _from_int (val )
72
70
elif isinstance (val , (list , tuple )):
73
71
if isinstance (val [0 ], int ):
74
- self .vals = _from_sequence_int (val )
72
+ self ._vals = _from_sequence_int (val )
75
73
else :
76
- self .vals = _from_sequence_sequence (val )
74
+ self ._vals = _from_sequence_sequence (val )
77
75
else :
78
76
raise TypeError (f'{ val } is of Unsupported type { type (val )} ' )
79
- self .num_variables = len (self .vals [0 ])
77
+ self ._num_variables = len (self ._vals [0 ])
80
78
81
79
def product (self , other ):
82
- # Cartesian product of all combinations in self x other
80
+ """Sets self to be the cartesian product of all combinations in self x other.
81
+
82
+ Args:
83
+ other: A ControlValues object
84
+ """
83
85
if other is None :
84
86
return
85
87
other = other .copy ()
86
88
cur = self
87
- while cur .nxt is not None :
88
- cur = cur .nxt
89
- cur .nxt = other
89
+ while cur ._nxt is not None :
90
+ cur = cur ._nxt
91
+ cur ._nxt = other
90
92
91
93
def __call__ (self ):
92
94
return self .__iter__ ()
93
95
94
96
def __iter__ (self ):
95
- nxt = self .nxt if self .nxt else lambda : [()]
96
- if self .num_variables :
97
- self . itr = itertools .product (self .vals , nxt ())
97
+ nxt = self ._nxt if self ._nxt else lambda : [()]
98
+ if self ._num_variables :
99
+ return itertools .product (self ._vals , nxt ())
98
100
else :
99
- self .itr = itertools .product (* (), nxt ())
100
- return self .itr
101
+ return itertools .product (* (), nxt ())
101
102
102
103
def copy (self ):
103
- if self .num_variables == 0 :
104
+ """Returns a deep copy of the object."""
105
+ if self ._num_variables == 0 :
104
106
new_copy = ControlValues ([])
105
107
else :
106
108
new_copy = ControlValues (
107
109
[
108
- copy .deepcopy (self .vals ),
110
+ copy .deepcopy (self ._vals ),
109
111
]
110
112
)
111
- new_copy .nxt = None
112
- if self .nxt :
113
- new_copy .nxt = self .nxt .copy ()
113
+ new_copy ._nxt = None
114
+ if self ._nxt :
115
+ new_copy ._nxt = self ._nxt .copy ()
114
116
return new_copy
115
117
116
118
def __len__ (self ):
117
119
cur = self
118
120
num_variables = 0
119
121
while cur is not None :
120
- num_variables += cur .num_variables
121
- cur = cur .nxt
122
+ num_variables += cur ._num_variables
123
+ cur = cur ._nxt
122
124
return num_variables
123
125
124
126
def __getitem__ (self , key ):
@@ -131,9 +133,9 @@ def __getitem__(self, key):
131
133
if not 0 <= key < num_variables :
132
134
key = key % num_variables
133
135
cur = self
134
- while cur .num_variables <= key :
135
- key -= cur .num_variables
136
- cur = cur .nxt
136
+ while cur ._num_variables <= key :
137
+ key -= cur ._num_variables
138
+ cur = cur ._nxt
137
139
return cur
138
140
139
141
def __eq__ (self , other ):
@@ -147,33 +149,55 @@ def __eq__(self, other):
147
149
return self_values == other_values
148
150
149
151
def identifier (self , companions : Sequence [Union [int , 'cirq.Qid' ]]):
152
+ """Returns an identifier that pairs the control_values with their counterparts
153
+ in the companion sequence (e.g. sequence of the control qubits ids)
154
+
155
+ Args:
156
+ companions: sequence of the same length as the number of control qubits.
157
+
158
+ Returns:
159
+ Tuple of pairs of the control values paired with its corresponding companion.
160
+ """
150
161
companions = tuple (companions )
151
162
controls = []
152
163
cur = cast (Optional [ControlValues ], self )
153
164
while cur is not None :
154
- controls .append ((cur .vals , companions [: cur .num_variables ]))
155
- companions = companions [cur .num_variables :]
156
- cur = cur .nxt
165
+ controls .append ((cur ._vals , companions [: cur ._num_variables ]))
166
+ companions = companions [cur ._num_variables :]
167
+ cur = cur ._nxt
157
168
return tuple (controls )
158
169
159
- def check_dimentionality (
170
+ def check_dimensionality (
160
171
self ,
161
172
qid_shape : Optional [Union [Tuple [int , ...], List [int ]]] = None ,
162
173
controls : Optional [Union [Tuple ['cirq.Qid' , ...], List ['cirq.Qid' ]]] = None ,
163
174
offset = 0 ,
164
175
):
165
- if self .num_variables == 0 :
176
+ """Checks the dimentionality of control values with respect to qid_shape or controls.
177
+ *At least one of qid_shape and controls must be provided.
178
+ *if both are provided then controls is ignored*
179
+
180
+ Args:
181
+ qid_shape: Sequence of shapes of the control qubits.
182
+ controls: Sequence of Qids.
183
+ offset: starting index.
184
+ Raises:
185
+ ValueError:
186
+ - if none of qid_shape or controls are provided or both are empty.
187
+ - if one of the control values violates the shape of its qubit.
188
+ """
189
+ if self ._num_variables == 0 :
166
190
return
167
191
if qid_shape is None and controls is None :
168
192
raise ValueError ('At least one of qid_shape or controls has to be not given.' )
169
193
if controls is not None :
170
194
controls = tuple (controls )
171
195
if (qid_shape is None or len (qid_shape ) == 0 ) and controls is not None :
172
- qid_shape = tuple (q .dimension for q in controls [: self .num_variables ])
196
+ qid_shape = tuple (q .dimension for q in controls [: self ._num_variables ])
173
197
qid_shape = cast (Tuple [int ], qid_shape )
174
- for product in self .vals :
198
+ for product in self ._vals :
175
199
product = flatten (product )
176
- for i in range (self .num_variables ):
200
+ for i in range (self ._num_variables ):
177
201
if not 0 <= product [i ] < qid_shape [i ]:
178
202
message = (
179
203
'Control values <{!r}> outside of range ' 'for control qubit number <{!r}>.'
@@ -185,40 +209,59 @@ def check_dimentionality(
185
209
)
186
210
raise ValueError (message )
187
211
188
- if self .nxt is not None :
189
- self .nxt . check_dimentionality (
190
- qid_shape = qid_shape [self .num_variables :],
191
- controls = controls [self .num_variables :] if controls else None ,
192
- offset = offset + self .num_variables ,
212
+ if self ._nxt is not None :
213
+ self ._nxt . check_dimensionality (
214
+ qid_shape = qid_shape [self ._num_variables :],
215
+ controls = controls [self ._num_variables :] if controls else None ,
216
+ offset = offset + self ._num_variables ,
193
217
)
194
218
195
219
def are_same_value (self , value : int = 1 ):
196
- for product in self .vals :
220
+ for product in self ._vals :
197
221
product = flatten (product )
198
222
if not all (v == value for v in product ):
199
223
return False
200
- if self .nxt is not None :
201
- return self .nxt .are_same_value (value )
224
+ if self ._nxt is not None :
225
+ return self ._nxt .are_same_value (value )
202
226
return True
203
227
204
228
def arrangements (self ):
229
+ """Returns a list of the control values.
230
+
231
+ Returns:
232
+ lists containing the control values whose product is the list of all
233
+ possible combinations of the control values.
234
+ """
205
235
_arrangements = []
206
236
cur = self
207
237
while cur is not None :
208
- if cur .num_variables == 1 :
209
- _arrangements .append (flatten (cur .vals ))
238
+ if cur ._num_variables == 1 :
239
+ _arrangements .append (flatten (cur ._vals ))
210
240
else :
211
- _arrangements .append (tuple (flatten (product ) for product in cur .vals ))
212
- cur = cur .nxt
241
+ _arrangements .append (tuple (flatten (product ) for product in cur ._vals ))
242
+ cur = cur ._nxt
213
243
return _arrangements
214
244
215
245
def pop (self ):
216
- if self .nxt is None :
246
+ """Removes the last control values combination."""
247
+ if self ._nxt is None :
217
248
return None
218
- self .nxt = self .nxt .pop ()
249
+ self ._nxt = self ._nxt .pop ()
219
250
return self
220
251
221
252
253
+ def to_control_values (
254
+ values : Union [ControlValues , Sequence [Union [int , Collection [int ]]]]
255
+ ) -> ControlValues :
256
+ if not isinstance (values , ControlValues ):
257
+ # Convert to sorted tuples
258
+ return ControlValues (
259
+ tuple ((val ,) if isinstance (val , int ) else tuple (sorted (val )) for val in values )
260
+ )
261
+ else :
262
+ return values
263
+
264
+
222
265
class FreeVars (ControlValues ):
223
266
pass
224
267
0 commit comments