20
20
"""
21
21
22
22
import abc
23
+ import contextlib
23
24
import enum
24
25
import html
25
26
import itertools
26
27
import math
28
+ import re
29
+ import warnings
27
30
from collections import defaultdict
28
31
from typing import (
29
32
AbstractSet ,
50
53
import numpy as np
51
54
52
55
import cirq ._version
53
- from cirq import devices , ops , protocols , qis
56
+ from cirq import _compat , devices , ops , protocols , qis
54
57
from cirq .circuits ._bucket_priority_queue import BucketPriorityQueue
55
58
from cirq .circuits .circuit_operation import CircuitOperation
56
59
from cirq .circuits .insert_strategy import InsertStrategy
70
73
_DEVICE_DEP_MESSAGE = 'Attaching devices to circuits will no longer be supported.'
71
74
72
75
76
+ @contextlib .contextmanager
77
+ def _block_overlapping_deprecation ():
78
+ with warnings .catch_warnings ():
79
+ warnings .filterwarnings (
80
+ action = 'ignore' ,
81
+ category = DeprecationWarning ,
82
+ message = f'(.|\n )*{ re .escape (_DEVICE_DEP_MESSAGE )} (.|\n )*' ,
83
+ )
84
+ yield
85
+
86
+
73
87
class Alignment (enum .Enum ):
74
88
# Stop when left ends are lined up.
75
89
LEFT = 1
@@ -139,7 +153,10 @@ def freeze(self) -> 'cirq.FrozenCircuit':
139
153
140
154
if isinstance (self , FrozenCircuit ):
141
155
return self
142
- return FrozenCircuit (self , strategy = InsertStrategy .EARLIEST , device = self .device )
156
+
157
+ if self ._device == cirq .UNCONSTRAINED_DEVICE :
158
+ return FrozenCircuit (self , strategy = InsertStrategy .EARLIEST )
159
+ return FrozenCircuit (self , strategy = InsertStrategy .EARLIEST , device = self ._device )
143
160
144
161
def unfreeze (self , copy : bool = True ) -> 'cirq.Circuit' :
145
162
"""Creates a Circuit from this circuit.
@@ -149,23 +166,26 @@ def unfreeze(self, copy: bool = True) -> 'cirq.Circuit':
149
166
"""
150
167
if isinstance (self , Circuit ):
151
168
return Circuit .copy (self ) if copy else self
152
- return Circuit (self , strategy = InsertStrategy .EARLIEST , device = self .device )
169
+
170
+ if self ._device == cirq .UNCONSTRAINED_DEVICE :
171
+ return Circuit (self , strategy = InsertStrategy .EARLIEST )
172
+ return Circuit (self , strategy = InsertStrategy .EARLIEST , device = self ._device )
153
173
154
174
def __bool__ (self ):
155
175
return bool (self .moments )
156
176
157
177
def __eq__ (self , other ):
158
178
if not isinstance (other , AbstractCircuit ):
159
179
return NotImplemented
160
- return tuple (self .moments ) == tuple (other .moments ) and self .device == other .device
180
+ return tuple (self .moments ) == tuple (other .moments ) and self ._device == other ._device
161
181
162
182
def _approx_eq_ (self , other : Any , atol : Union [int , float ]) -> bool :
163
183
"""See `cirq.protocols.SupportsApproximateEquality`."""
164
184
if not isinstance (other , AbstractCircuit ):
165
185
return NotImplemented
166
186
return (
167
187
cirq .protocols .approx_eq (tuple (self .moments ), tuple (other .moments ), atol = atol )
168
- and self .device == other .device
188
+ and self ._device == other ._device
169
189
)
170
190
171
191
def __ne__ (self , other ) -> bool :
@@ -241,7 +261,7 @@ def __repr__(self) -> str:
241
261
args = []
242
262
if self .moments :
243
263
args .append (_list_repr_with_indented_item_lines (self .moments ))
244
- if self .device != devices .UNCONSTRAINED_DEVICE :
264
+ if self ._device != devices .UNCONSTRAINED_DEVICE :
245
265
args .append (f'device={ self .device !r} ' )
246
266
return f'cirq.{ cls_name } ({ ", " .join (args )} )'
247
267
@@ -1323,11 +1343,16 @@ def save_qasm(
1323
1343
self ._to_qasm_output (header , precision , qubit_order ).save (file_path )
1324
1344
1325
1345
def _json_dict_ (self ):
1326
- return protocols .obj_to_dict_helper (self , ['moments' , 'device' ])
1346
+ ret = protocols .obj_to_dict_helper (self , ['moments' , '_device' ])
1347
+ ret ['device' ] = ret ['_device' ]
1348
+ del ret ['_device' ]
1349
+ return ret
1327
1350
1328
1351
@classmethod
1329
1352
def _from_json_dict_ (cls , moments , device , ** kwargs ):
1330
- return cls (moments , strategy = InsertStrategy .EARLIEST , device = device )
1353
+ if device == cirq .UNCONSTRAINED_DEVICE :
1354
+ return cls (moments , strategy = InsertStrategy .EARLIEST )
1355
+ return cls (moments , device = device , strategy = InsertStrategy .EARLIEST )
1331
1356
1332
1357
def zip (
1333
1358
* circuits : 'cirq.AbstractCircuit' , align : Union ['cirq.Alignment' , str ] = Alignment .LEFT
@@ -1677,6 +1702,12 @@ class Circuit(AbstractCircuit):
1677
1702
independent 'factors' of the original Circuit.
1678
1703
"""
1679
1704
1705
+ @_compat .deprecated_parameter (
1706
+ deadline = 'v0.15' ,
1707
+ fix = _DEVICE_DEP_MESSAGE ,
1708
+ parameter_desc = 'device' ,
1709
+ match = lambda args , kwargs : 'device' in kwargs ,
1710
+ )
1680
1711
def __init__ (
1681
1712
self ,
1682
1713
* contents : 'cirq.OP_TREE' ,
@@ -1701,25 +1732,40 @@ def __init__(
1701
1732
self ._device = device
1702
1733
self .append (contents , strategy = strategy )
1703
1734
1704
- @property
1705
- def device (self ) -> 'cirq.Device' :
1735
+ @property # type: ignore
1736
+ @_compat .deprecated (
1737
+ deadline = 'v0.15' ,
1738
+ fix = _DEVICE_DEP_MESSAGE ,
1739
+ )
1740
+ def device (self ) -> devices .Device :
1706
1741
return self ._device
1707
1742
1708
- @device .setter
1743
+ @device .setter # type: ignore
1744
+ @_compat .deprecated (
1745
+ deadline = 'v0.15' ,
1746
+ fix = _DEVICE_DEP_MESSAGE ,
1747
+ )
1709
1748
def device (self , new_device : 'cirq.Device' ) -> None :
1710
1749
new_device .validate_circuit (self )
1711
1750
self ._device = new_device
1712
1751
1713
1752
def __copy__ (self ) -> 'cirq.Circuit' :
1714
1753
return self .copy ()
1715
1754
1716
- def copy (self ) -> 'cirq.Circuit' :
1717
- copied_circuit = Circuit (device = self ._device )
1755
+ def copy (self ) -> 'Circuit' :
1756
+ if self ._device == cirq .UNCONSTRAINED_DEVICE :
1757
+ copied_circuit = Circuit ()
1758
+ else :
1759
+ copied_circuit = Circuit (device = self ._device )
1718
1760
copied_circuit ._moments = self ._moments [:]
1719
1761
return copied_circuit
1720
1762
1721
- def _with_sliced_moments (self , moments : Iterable ['cirq.Moment' ]) -> 'cirq.Circuit' :
1722
- new_circuit = Circuit (device = self .device )
1763
+ def _with_sliced_moments (self , moments : Iterable ['cirq.Moment' ]) -> 'Circuit' :
1764
+ if self ._device == cirq .UNCONSTRAINED_DEVICE :
1765
+ new_circuit = Circuit ()
1766
+ else :
1767
+ new_circuit = Circuit (device = self ._device )
1768
+
1723
1769
new_circuit ._moments = list (moments )
1724
1770
return new_circuit
1725
1771
@@ -1759,8 +1805,8 @@ def __iadd__(self, other):
1759
1805
def __add__ (self , other ):
1760
1806
if isinstance (other , type (self )):
1761
1807
if (
1762
- devices .UNCONSTRAINED_DEVICE not in [self ._device , other .device ]
1763
- and self ._device != other .device
1808
+ devices .UNCONSTRAINED_DEVICE not in [self ._device , other ._device ]
1809
+ and self ._device != other ._device
1764
1810
):
1765
1811
raise ValueError ("Can't add circuits with incompatible devices." )
1766
1812
elif not isinstance (other , (ops .Operation , Iterable )):
@@ -1791,6 +1837,8 @@ def __imul__(self, repetitions: INT_TYPE):
1791
1837
def __mul__ (self , repetitions : INT_TYPE ):
1792
1838
if not isinstance (repetitions , (int , np .integer )):
1793
1839
return NotImplemented
1840
+ if self ._device == cirq .UNCONSTRAINED_DEVICE :
1841
+ return Circuit (self ._moments * int (repetitions ))
1794
1842
return Circuit (self ._moments * int (repetitions ), device = self ._device )
1795
1843
1796
1844
def __rmul__ (self , repetitions : INT_TYPE ):
@@ -1816,10 +1864,17 @@ def __pow__(self, exponent: int) -> 'cirq.Circuit':
1816
1864
if inv_moment is NotImplemented :
1817
1865
return NotImplemented
1818
1866
inv_moments .append (inv_moment )
1867
+
1868
+ if self ._device == cirq .UNCONSTRAINED_DEVICE :
1869
+ return cirq .Circuit (inv_moments )
1819
1870
return cirq .Circuit (inv_moments , device = self ._device )
1820
1871
1821
1872
__hash__ = None # type: ignore
1822
1873
1874
+ @_compat .deprecated (
1875
+ deadline = 'v0.15' ,
1876
+ fix = _DEVICE_DEP_MESSAGE ,
1877
+ )
1823
1878
def with_device (
1824
1879
self ,
1825
1880
new_device : 'cirq.Device' ,
@@ -1835,15 +1890,16 @@ def with_device(
1835
1890
Returns:
1836
1891
The translated circuit.
1837
1892
"""
1838
- return Circuit (
1839
- [
1840
- ops .Moment (
1841
- operation .transform_qubits (qubit_mapping ) for operation in moment .operations
1842
- )
1843
- for moment in self ._moments
1844
- ],
1845
- device = new_device ,
1846
- )
1893
+ with _block_overlapping_deprecation ():
1894
+ return Circuit (
1895
+ [
1896
+ ops .Moment (
1897
+ operation .transform_qubits (qubit_mapping ) for operation in moment .operations
1898
+ )
1899
+ for moment in self ._moments
1900
+ ],
1901
+ device = new_device ,
1902
+ )
1847
1903
1848
1904
def tetris_concat (
1849
1905
* circuits : 'cirq.AbstractCircuit' , align : Union ['cirq.Alignment' , str ] = Alignment .LEFT
@@ -1859,6 +1915,12 @@ def zip(
1859
1915
1860
1916
zip .__doc__ = AbstractCircuit .zip .__doc__
1861
1917
1918
+ @_compat .deprecated_parameter (
1919
+ deadline = 'v0.15' ,
1920
+ fix = _DEVICE_DEP_MESSAGE ,
1921
+ parameter_desc = 'new_device' ,
1922
+ match = lambda args , kwargs : 'new_device' in kwargs ,
1923
+ )
1862
1924
def transform_qubits (
1863
1925
self ,
1864
1926
qubit_map : Union [Dict ['cirq.Qid' , 'cirq.Qid' ], Callable [['cirq.Qid' ], 'cirq.Qid' ]],
@@ -1867,10 +1929,6 @@ def transform_qubits(
1867
1929
) -> 'cirq.Circuit' :
1868
1930
"""Returns the same circuit, but with different qubits.
1869
1931
1870
- Note that this method does essentially the same thing as
1871
- `cirq.Circuit.with_device`. It is included regardless because there are
1872
- also `transform_qubits` methods on `cirq.Operation` and `cirq.Moment`.
1873
-
1874
1932
Args:
1875
1933
qubit_map: A function or a dict mapping each current qubit into a desired
1876
1934
new qubit.
@@ -1891,9 +1949,17 @@ def transform_qubits(
1891
1949
transform = lambda q : qubit_map .get (q , q ) # type: ignore
1892
1950
else :
1893
1951
raise TypeError ('qubit_map must be a function or dict mapping qubits to qubits.' )
1894
- return self .with_device (
1895
- new_device = self .device if new_device is None else new_device , qubit_mapping = transform
1896
- )
1952
+
1953
+ op_list = [
1954
+ ops .Moment (operation .transform_qubits (transform ) for operation in moment .operations )
1955
+ for moment in self ._moments
1956
+ ]
1957
+
1958
+ if new_device is None and self ._device == devices .UNCONSTRAINED_DEVICE :
1959
+ return Circuit (op_list )
1960
+
1961
+ with _block_overlapping_deprecation ():
1962
+ return Circuit (op_list , device = self ._device if new_device is None else new_device )
1897
1963
1898
1964
def _prev_moment_available (self , op : 'cirq.Operation' , end_moment_index : int ) -> Optional [int ]:
1899
1965
last_available = end_moment_index
@@ -2309,8 +2375,10 @@ def _resolve_parameters_(
2309
2375
resolved_operations = _resolve_operations (moment .operations , resolver , recursive )
2310
2376
new_moment = ops .Moment (resolved_operations )
2311
2377
resolved_moments .append (new_moment )
2312
- resolved_circuit = Circuit (resolved_moments , device = self .device )
2313
- return resolved_circuit
2378
+ if self ._device == devices .UNCONSTRAINED_DEVICE :
2379
+ return Circuit (resolved_moments )
2380
+ with _block_overlapping_deprecation ():
2381
+ return Circuit (resolved_moments , device = self ._device )
2314
2382
2315
2383
@property
2316
2384
def moments (self ):
0 commit comments