14
14
15
15
"""Functionality for grouping and validating Cirq Gates"""
16
16
17
+ import warnings
17
18
from typing import Any , Callable , cast , Dict , FrozenSet , List , Optional , Type , TYPE_CHECKING , Union
19
+
20
+ from cirq import _compat , protocols , value
18
21
from cirq .ops import global_phase_op , op_tree , raw_types
19
- from cirq import protocols , value
20
22
21
23
if TYPE_CHECKING :
22
24
import cirq
@@ -201,12 +203,20 @@ class Gateset:
201
203
validation purposes.
202
204
"""
203
205
206
+ @_compat .deprecated_parameter (
207
+ deadline = 'v0.16' ,
208
+ fix = 'To accept global phase gates, add cirq.GlobalPhaseGate to the list of *gates passed '
209
+ 'to the constructor. By default, global phase gates will not be accepted by the '
210
+ 'gateset' ,
211
+ parameter_desc = 'accept_global_phase_op' ,
212
+ match = lambda args , kwargs : 'accept_global_phase_op' in kwargs ,
213
+ )
204
214
def __init__ (
205
215
self ,
206
216
* gates : Union [Type [raw_types .Gate ], raw_types .Gate , GateFamily ],
207
217
name : Optional [str ] = None ,
208
218
unroll_circuit_op : bool = True ,
209
- accept_global_phase_op : bool = True ,
219
+ accept_global_phase_op : Optional [ bool ] = None ,
210
220
) -> None :
211
221
"""Init Gateset.
212
222
@@ -225,17 +235,36 @@ def __init__(
225
235
name: (Optional) Name for the Gateset. Useful for description.
226
236
unroll_circuit_op: If True, `cirq.CircuitOperation` is recursively
227
237
validated by validating the underlying `cirq.Circuit`.
228
- accept_global_phase_op: If True, `cirq.GlobalPhaseOperation` is accepted.
238
+ accept_global_phase_op: If True, a `GateFamily` accepting
239
+ `cirq.GlobalPhaseGate` will be included. If None,
240
+ `cirq.GlobalPhaseGate` will not modify the input `*gates`.
241
+ If False, `cirq.GlobalPhaseGate` will be removed from the
242
+ gates. This parameter defaults to None (a breaking change from
243
+ v0.14.1) and will be removed in v0.16.
229
244
"""
230
245
self ._name = name
231
246
self ._unroll_circuit_op = unroll_circuit_op
232
- self ._accept_global_phase_op = accept_global_phase_op
247
+ if accept_global_phase_op :
248
+ gates = gates + (global_phase_op .GlobalPhaseGate ,)
233
249
self ._instance_gate_families : Dict [raw_types .Gate , GateFamily ] = {}
234
250
self ._type_gate_families : Dict [Type [raw_types .Gate ], GateFamily ] = {}
235
251
self ._gates_repr_str = ", " .join ([_gate_str (g , repr ) for g in gates ])
236
252
unique_gate_list : List [GateFamily ] = list (
237
253
dict .fromkeys (g if isinstance (g , GateFamily ) else GateFamily (gate = g ) for g in gates )
238
254
)
255
+ if accept_global_phase_op is False :
256
+ unique_gate_list = [
257
+ g for g in unique_gate_list if g .gate is not global_phase_op .GlobalPhaseGate
258
+ ]
259
+ elif accept_global_phase_op is None :
260
+ if not any (g .gate is global_phase_op .GlobalPhaseGate for g in unique_gate_list ):
261
+ warnings .warn (
262
+ 'v0.14.1 is the last release `cirq.GlobalPhaseGate` is included by default. If'
263
+ ' you were relying on this behavior, you can include a `cirq.GlobalPhaseGate`'
264
+ ' in your `*gates`. If not, then you can ignore this warning. It will be'
265
+ ' removed in v0.16'
266
+ )
267
+
239
268
for g in unique_gate_list :
240
269
if type (g ) == GateFamily :
241
270
if isinstance (g .gate , raw_types .Gate ):
@@ -253,6 +282,12 @@ def name(self) -> Optional[str]:
253
282
def gates (self ) -> FrozenSet [GateFamily ]:
254
283
return self ._gates
255
284
285
+ @_compat .deprecated_parameter (
286
+ deadline = 'v0.16' ,
287
+ fix = 'Add a global phase gate to the Gateset' ,
288
+ parameter_desc = 'accept_global_phase_op' ,
289
+ match = lambda args , kwargs : 'accept_global_phase_op' in kwargs ,
290
+ )
256
291
def with_params (
257
292
self ,
258
293
* ,
@@ -268,7 +303,12 @@ def with_params(
268
303
name: New name for the Gateset.
269
304
unroll_circuit_op: If True, new Gateset will recursively validate
270
305
`cirq.CircuitOperation` by validating the underlying `cirq.Circuit`.
271
- accept_global_phase_op: If True, new Gateset will accept `cirq.GlobalPhaseOperation`.
306
+ accept_global_phase_op: If True, a `GateFamily` accepting
307
+ `cirq.GlobalPhaseGate` will be included. If None,
308
+ `cirq.GlobalPhaseGate` will not modify the input `*gates`.
309
+ If False, `cirq.GlobalPhaseGate` will be removed from the
310
+ gates. This parameter defaults to None (a breaking change from
311
+ v0.14.1) and will be removed in v0.16.
272
312
273
313
Returns:
274
314
`self` if all new values are None or identical to the values of current Gateset.
@@ -280,19 +320,23 @@ def val_if_none(var: Any, val: Any) -> Any:
280
320
281
321
name = val_if_none (name , self ._name )
282
322
unroll_circuit_op = val_if_none (unroll_circuit_op , self ._unroll_circuit_op )
283
- accept_global_phase_op = val_if_none ( accept_global_phase_op , self . _accept_global_phase_op )
323
+ global_phase_family = GateFamily ( gate = global_phase_op . GlobalPhaseGate )
284
324
if (
285
325
name == self ._name
286
326
and unroll_circuit_op == self ._unroll_circuit_op
287
- and accept_global_phase_op == self ._accept_global_phase_op
327
+ and (
328
+ accept_global_phase_op is True
329
+ and global_phase_family in self .gates
330
+ or accept_global_phase_op is False
331
+ and not any (g .gate is global_phase_op .GlobalPhaseGate for g in self .gates )
332
+ or accept_global_phase_op is None
333
+ )
288
334
):
289
335
return self
290
- return Gateset (
291
- * self .gates ,
292
- name = name ,
293
- unroll_circuit_op = cast (bool , unroll_circuit_op ),
294
- accept_global_phase_op = cast (bool , accept_global_phase_op ),
295
- )
336
+ gates = self .gates
337
+ if accept_global_phase_op :
338
+ gates = gates .union ({global_phase_family })
339
+ return Gateset (* gates , name = name , unroll_circuit_op = cast (bool , unroll_circuit_op ))
296
340
297
341
def __contains__ (self , item : Union [raw_types .Gate , raw_types .Operation ]) -> bool :
298
342
"""Check for containment of a given Gate/Operation in this Gateset.
@@ -326,9 +370,6 @@ def __contains__(self, item: Union[raw_types.Gate, raw_types.Operation]) -> bool
326
370
g = item if isinstance (item , raw_types .Gate ) else item .gate
327
371
assert g is not None , f'`item`: { item } must be a gate or have a valid `item.gate`'
328
372
329
- if isinstance (g , global_phase_op .GlobalPhaseGate ):
330
- return self ._accept_global_phase_op
331
-
332
373
if g in self ._instance_gate_families :
333
374
assert item in self ._instance_gate_families [g ], (
334
375
f"{ item } instance matches { self ._instance_gate_families [g ]} but "
@@ -394,16 +435,15 @@ def _validate_operation(self, op: raw_types.Operation) -> bool:
394
435
return False
395
436
396
437
def _value_equality_values_ (self ) -> Any :
397
- return (self .gates , self .name , self ._unroll_circuit_op , self . _accept_global_phase_op )
438
+ return (self .gates , self .name , self ._unroll_circuit_op )
398
439
399
440
def __repr__ (self ) -> str :
400
441
name_str = f'name = "{ self .name } ", ' if self .name is not None else ''
401
442
return (
402
443
f'cirq.Gateset('
403
444
f'{ self ._gates_repr_str } , '
404
445
f'{ name_str } '
405
- f'unroll_circuit_op = { self ._unroll_circuit_op } ,'
406
- f'accept_global_phase_op = { self ._accept_global_phase_op } )'
446
+ f'unroll_circuit_op = { self ._unroll_circuit_op } )'
407
447
)
408
448
409
449
def __str__ (self ) -> str :
@@ -417,16 +457,17 @@ def _json_dict_(self) -> Dict[str, Any]:
417
457
'gates' : self ._unique_gate_list ,
418
458
'name' : self .name ,
419
459
'unroll_circuit_op' : self ._unroll_circuit_op ,
420
- 'accept_global_phase_op' : self ._accept_global_phase_op ,
421
460
}
422
461
423
462
@classmethod
424
- def _from_json_dict_ (
425
- cls , gates , name , unroll_circuit_op , accept_global_phase_op , ** kwargs
426
- ) -> 'Gateset' :
427
- return cls (
428
- * gates ,
429
- name = name ,
430
- unroll_circuit_op = unroll_circuit_op ,
431
- accept_global_phase_op = accept_global_phase_op ,
432
- )
463
+ def _from_json_dict_ (cls , gates , name , unroll_circuit_op , ** kwargs ) -> 'Gateset' :
464
+ if 'accept_global_phase_op' in kwargs :
465
+ accept_global_phase_op = kwargs ['accept_global_phase_op' ]
466
+ global_phase_family = GateFamily (gate = global_phase_op .GlobalPhaseGate )
467
+ if accept_global_phase_op is True :
468
+ gates .append (global_phase_family )
469
+ elif accept_global_phase_op is False :
470
+ gates = [
471
+ family for family in gates if family .gate is not global_phase_op .GlobalPhaseGate
472
+ ]
473
+ return cls (* gates , name = name , unroll_circuit_op = unroll_circuit_op )
0 commit comments