cirq-core 1.5.0.dev20241220195200__py3-none-any.whl → 1.5.0.dev20241221000556__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cirq-core might be problematic. Click here for more details.

cirq/_version.py CHANGED
@@ -28,4 +28,4 @@ if sys.version_info < (3, 10, 0): # pragma: no cover
28
28
  'of cirq (e.g. "python -m pip install cirq==1.1.*")'
29
29
  )
30
30
 
31
- __version__ = "1.5.0.dev20241220195200"
31
+ __version__ = "1.5.0.dev20241221000556"
cirq/_version_test.py CHANGED
@@ -3,4 +3,4 @@ import cirq
3
3
 
4
4
 
5
5
  def test_version():
6
- assert cirq.__version__ == "1.5.0.dev20241220195200"
6
+ assert cirq.__version__ == "1.5.0.dev20241221000556"
@@ -24,22 +24,134 @@ from cirq import ops
24
24
 
25
25
  CZGaugeSelector = GaugeSelector(
26
26
  gauges=[
27
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.I, pre_q1=ops.I, post_q0=ops.I, post_q1=ops.I),
28
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.I, pre_q1=ops.X, post_q0=ops.Z, post_q1=ops.X),
29
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.I, pre_q1=ops.Y, post_q0=ops.Z, post_q1=ops.Y),
30
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.I, pre_q1=ops.Z, post_q0=ops.I, post_q1=ops.Z),
31
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.X, pre_q1=ops.I, post_q0=ops.X, post_q1=ops.Z),
32
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.X, pre_q1=ops.X, post_q0=ops.Y, post_q1=ops.Y),
33
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.X, pre_q1=ops.Y, post_q0=ops.Y, post_q1=ops.X),
34
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.X, pre_q1=ops.Z, post_q0=ops.X, post_q1=ops.I),
35
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Y, pre_q1=ops.I, post_q0=ops.Y, post_q1=ops.Z),
36
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Y, pre_q1=ops.X, post_q0=ops.X, post_q1=ops.Y),
37
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Y, pre_q1=ops.Y, post_q0=ops.X, post_q1=ops.X),
38
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Y, pre_q1=ops.Z, post_q0=ops.Y, post_q1=ops.I),
39
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Z, pre_q1=ops.I, post_q0=ops.Z, post_q1=ops.I),
40
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Z, pre_q1=ops.X, post_q0=ops.I, post_q1=ops.X),
41
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Z, pre_q1=ops.Y, post_q0=ops.I, post_q1=ops.Y),
42
- ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Z, pre_q1=ops.Z, post_q0=ops.Z, post_q1=ops.Z),
27
+ ConstantGauge(
28
+ two_qubit_gate=CZ,
29
+ pre_q0=ops.I,
30
+ pre_q1=ops.I,
31
+ post_q0=ops.I,
32
+ post_q1=ops.I,
33
+ support_sweep=True,
34
+ ),
35
+ ConstantGauge(
36
+ two_qubit_gate=CZ,
37
+ pre_q0=ops.I,
38
+ pre_q1=ops.X,
39
+ post_q0=ops.Z,
40
+ post_q1=ops.X,
41
+ support_sweep=True,
42
+ ),
43
+ ConstantGauge(
44
+ two_qubit_gate=CZ,
45
+ pre_q0=ops.I,
46
+ pre_q1=ops.Y,
47
+ post_q0=ops.Z,
48
+ post_q1=ops.Y,
49
+ support_sweep=True,
50
+ ),
51
+ ConstantGauge(
52
+ two_qubit_gate=CZ,
53
+ pre_q0=ops.I,
54
+ pre_q1=ops.Z,
55
+ post_q0=ops.I,
56
+ post_q1=ops.Z,
57
+ support_sweep=True,
58
+ ),
59
+ ConstantGauge(
60
+ two_qubit_gate=CZ,
61
+ pre_q0=ops.X,
62
+ pre_q1=ops.I,
63
+ post_q0=ops.X,
64
+ post_q1=ops.Z,
65
+ support_sweep=True,
66
+ ),
67
+ ConstantGauge(
68
+ two_qubit_gate=CZ,
69
+ pre_q0=ops.X,
70
+ pre_q1=ops.X,
71
+ post_q0=ops.Y,
72
+ post_q1=ops.Y,
73
+ support_sweep=True,
74
+ ),
75
+ ConstantGauge(
76
+ two_qubit_gate=CZ,
77
+ pre_q0=ops.X,
78
+ pre_q1=ops.Y,
79
+ post_q0=ops.Y,
80
+ post_q1=ops.X,
81
+ support_sweep=True,
82
+ ),
83
+ ConstantGauge(
84
+ two_qubit_gate=CZ,
85
+ pre_q0=ops.X,
86
+ pre_q1=ops.Z,
87
+ post_q0=ops.X,
88
+ post_q1=ops.I,
89
+ support_sweep=True,
90
+ ),
91
+ ConstantGauge(
92
+ two_qubit_gate=CZ,
93
+ pre_q0=ops.Y,
94
+ pre_q1=ops.I,
95
+ post_q0=ops.Y,
96
+ post_q1=ops.Z,
97
+ support_sweep=True,
98
+ ),
99
+ ConstantGauge(
100
+ two_qubit_gate=CZ,
101
+ pre_q0=ops.Y,
102
+ pre_q1=ops.X,
103
+ post_q0=ops.X,
104
+ post_q1=ops.Y,
105
+ support_sweep=True,
106
+ ),
107
+ ConstantGauge(
108
+ two_qubit_gate=CZ,
109
+ pre_q0=ops.Y,
110
+ pre_q1=ops.Y,
111
+ post_q0=ops.X,
112
+ post_q1=ops.X,
113
+ support_sweep=True,
114
+ ),
115
+ ConstantGauge(
116
+ two_qubit_gate=CZ,
117
+ pre_q0=ops.Y,
118
+ pre_q1=ops.Z,
119
+ post_q0=ops.Y,
120
+ post_q1=ops.I,
121
+ support_sweep=True,
122
+ ),
123
+ ConstantGauge(
124
+ two_qubit_gate=CZ,
125
+ pre_q0=ops.Z,
126
+ pre_q1=ops.I,
127
+ post_q0=ops.Z,
128
+ post_q1=ops.I,
129
+ support_sweep=True,
130
+ ),
131
+ ConstantGauge(
132
+ two_qubit_gate=CZ,
133
+ pre_q0=ops.Z,
134
+ pre_q1=ops.X,
135
+ post_q0=ops.I,
136
+ post_q1=ops.X,
137
+ support_sweep=True,
138
+ ),
139
+ ConstantGauge(
140
+ two_qubit_gate=CZ,
141
+ pre_q0=ops.Z,
142
+ pre_q1=ops.Y,
143
+ post_q0=ops.I,
144
+ post_q1=ops.Y,
145
+ support_sweep=True,
146
+ ),
147
+ ConstantGauge(
148
+ two_qubit_gate=CZ,
149
+ pre_q0=ops.Z,
150
+ pre_q1=ops.Z,
151
+ post_q0=ops.Z,
152
+ post_q1=ops.Z,
153
+ support_sweep=True,
154
+ ),
43
155
  ]
44
156
  )
45
157
 
@@ -21,3 +21,4 @@ from cirq.transformers.gauge_compiling.gauge_compiling_test_utils import GaugeTe
21
21
  class TestCZGauge(GaugeTester):
22
22
  two_qubit_gate = cirq.CZ
23
23
  gauge_transformer = CZGaugeTransformer
24
+ sweep_must_pass = True
@@ -14,17 +14,24 @@
14
14
 
15
15
  """Creates the abstraction for gauge compiling as a cirq transformer."""
16
16
 
17
- from typing import Callable, Tuple, Optional, Sequence, Union, List
17
+ from typing import Callable, Dict, Tuple, Optional, Sequence, Union, List
18
+ from itertools import count
19
+ from dataclasses import dataclass
18
20
  import abc
19
21
  import itertools
20
22
  import functools
23
+ import sympy
21
24
 
22
- from dataclasses import dataclass
23
25
  from attrs import frozen, field
24
26
  import numpy as np
25
27
 
26
28
  from cirq.transformers import transformer_api
27
29
  from cirq import ops, circuits
30
+ from cirq.study import sweepable
31
+ from cirq.protocols import unitary_protocol
32
+ from cirq.protocols.has_unitary_protocol import has_unitary
33
+ from cirq.study.sweeps import Points, Zip
34
+ from cirq.transformers.analytical_decompositions import single_qubit_decompositions
28
35
 
29
36
 
30
37
  class Gauge(abc.ABC):
@@ -72,6 +79,7 @@ class ConstantGauge(Gauge):
72
79
  default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
73
80
  )
74
81
  swap_qubits: bool = False
82
+ support_sweep: bool = False
75
83
 
76
84
  def sample(self, gate: ops.Gate, prng: np.random.Generator) -> "ConstantGauge":
77
85
  return self
@@ -201,6 +209,100 @@ class GaugeTransformer:
201
209
  new_moments.extend(_build_moments(right))
202
210
  return circuits.Circuit.from_moments(*new_moments)
203
211
 
212
+ def as_sweep(
213
+ self,
214
+ circuit: circuits.AbstractCircuit,
215
+ *,
216
+ N: int,
217
+ context: Optional[transformer_api.TransformerContext] = None,
218
+ prng: Optional[np.random.Generator] = None,
219
+ ) -> Tuple[circuits.AbstractCircuit, sweepable.Sweepable]:
220
+ """Generates a parameterized circuit with *N* sets of sweepable parameters.
221
+
222
+ Args:
223
+ circuit: The input circuit to be processed by gauge compiling.
224
+ N: The number of parameter sets to generate.
225
+ context: A `cirq.TransformerContext` storing common configurable options for
226
+ the transformers.
227
+ prng: A pseudo-random number generator to select a gauge within a gauge cluster.
228
+ """
229
+
230
+ rng = np.random.default_rng() if prng is None else prng
231
+ if context is None:
232
+ context = transformer_api.TransformerContext(deep=False)
233
+ if context.deep:
234
+ raise ValueError('GaugeTransformer cannot be used with deep=True')
235
+ new_moments: List[List[ops.Operation]] = [] # Store parameterized circuits.
236
+ values_by_params: Dict[str, List[float]] = {} # map from symbol name to N values.
237
+ symbol_count = count()
238
+ # Map from "((pre|post),$qid,$moment_id)" to gate parameters.
239
+ # E.g. {(post,q1,2): {"x_exponent": "x1", "z_exponent": "z1", "axis_phase": "a1"}}
240
+ symbols_by_loc: Dict[Tuple[str, ops.Qid, int], Dict[str, sympy.Symbol]] = {}
241
+
242
+ def single_qubit_next_symbol() -> Dict[str, sympy.Symbol]:
243
+ sid = next(symbol_count)
244
+ return _parameterize(1, sid)
245
+
246
+ # Build parameterized circuit.
247
+ for moment_id, moment in enumerate(circuit):
248
+ center_moment: List[ops.Operation] = []
249
+ left_moment: List[ops.Operation] = []
250
+ right_moment: List[ops.Operation] = []
251
+ for op in moment:
252
+ if isinstance(op, ops.TaggedOperation) and set(op.tags).intersection(
253
+ context.tags_to_ignore
254
+ ):
255
+ center_moment.append(op)
256
+ continue
257
+ if op.gate is not None and op in self.target:
258
+ # Build symbols for the gauge, for a 2-qubit gauge, symbols will be built for
259
+ # pre/post q0/q1 and the new 2-qubit gate if the 2-qubit gate is updated in
260
+ # the gauge compiling.
261
+ center_moment.append(op)
262
+ for prefix, q in itertools.product(["pre", "post"], op.qubits):
263
+ xza_by_symbols = single_qubit_next_symbol() # xza in phased xz gate.
264
+ loc = (prefix, q, moment_id)
265
+ symbols_by_loc[loc] = xza_by_symbols
266
+ new_op = ops.PhasedXZGate(**xza_by_symbols).on(q)
267
+ for symbol in xza_by_symbols.values():
268
+ values_by_params.update({str(symbol): []})
269
+ if prefix == "pre":
270
+ left_moment.append(new_op)
271
+ else:
272
+ right_moment.append(new_op)
273
+ else:
274
+ center_moment.append(op)
275
+ new_moments.extend(
276
+ [moment for moment in [left_moment, center_moment, right_moment] if moment]
277
+ )
278
+
279
+ # Assign values for parameters via randomly chosen GaugeSelector.
280
+ for _ in range(N):
281
+ for moment_id, moment in enumerate(circuit):
282
+ for op in moment:
283
+ if isinstance(op, ops.TaggedOperation) and set(op.tags).intersection(
284
+ context.tags_to_ignore
285
+ ):
286
+ continue
287
+ if op.gate is not None and len(op.qubits) == 2 and op in self.target:
288
+ gauge = self.gauge_selector(rng).sample(op.gate, rng)
289
+ if not gauge.support_sweep:
290
+ raise NotImplementedError(
291
+ f"as_sweep isn't supported for {gauge.two_qubit_gate} gauge"
292
+ )
293
+ # Get the params of pre/post q0/q1 gates.
294
+ for pre_or_post, idx in itertools.product(["pre", "post"], [0, 1]):
295
+ symbols = symbols_by_loc[(pre_or_post, op.qubits[idx], moment_id)]
296
+ gates = getattr(gauge, f"{pre_or_post}_q{idx}")
297
+ phxz_params = _gate_sequence_to_phxz_params(gates, symbols)
298
+ for key, value in phxz_params.items():
299
+ values_by_params[key].append(value)
300
+ sweeps: List[Points] = [
301
+ Points(key=key, points=values) for key, values in values_by_params.items()
302
+ ]
303
+
304
+ return circuits.Circuit.from_moments(*new_moments), Zip(*sweeps)
305
+
204
306
 
205
307
  def _build_moments(operation_by_qubits: List[List[ops.Operation]]) -> List[List[ops.Operation]]:
206
308
  """Builds moments from a list of operations grouped by qubits.
@@ -212,3 +314,50 @@ def _build_moments(operation_by_qubits: List[List[ops.Operation]]) -> List[List[
212
314
  for moment in itertools.zip_longest(*operation_by_qubits):
213
315
  moments.append([op for op in moment if op is not None])
214
316
  return moments
317
+
318
+
319
+ def _parameterize(num_qubits: int, symbol_id: int) -> Dict[str, sympy.Symbol]:
320
+ """Returns symbolized parameters for the gate."""
321
+
322
+ if num_qubits == 1: # Convert single qubit gate to parameterized PhasedXZGate.
323
+ phased_xz_params = {
324
+ "x_exponent": sympy.Symbol(f"x{symbol_id}"),
325
+ "z_exponent": sympy.Symbol(f"z{symbol_id}"),
326
+ "axis_phase_exponent": sympy.Symbol(f"a{symbol_id}"),
327
+ }
328
+ return phased_xz_params
329
+ raise NotImplementedError("parameterization for non single qubit gates is not supported yet")
330
+
331
+
332
+ def _gate_sequence_to_phxz_params(
333
+ gates: Tuple[ops.Gate, ...], xza_by_symbols: Dict[str, sympy.Symbol]
334
+ ) -> Dict[str, float]:
335
+ for gate in gates:
336
+ if not has_unitary(gate) or gate.num_qubits() != 1:
337
+ raise ValueError(
338
+ "Invalid gate sequence to be converted to PhasedXZGate."
339
+ f"Found incompatiable gate {gate} in sequence."
340
+ )
341
+ phxz = (
342
+ single_qubit_decompositions.single_qubit_matrix_to_phxz(
343
+ functools.reduce(
344
+ np.matmul, [unitary_protocol.unitary(gate) for gate in reversed(gates)]
345
+ )
346
+ )
347
+ or ops.I
348
+ )
349
+ if phxz is ops.I: # Identity gate
350
+ return {
351
+ str(xza_by_symbols["x_exponent"]): 0.0,
352
+ str(xza_by_symbols["z_exponent"]): 0.0,
353
+ str(xza_by_symbols["axis_phase_exponent"]): 0.0,
354
+ }
355
+ # Check the gate type, needs to be a PhasedXZ gate.
356
+ if not isinstance(phxz, ops.PhasedXZGate):
357
+ raise ValueError("Failed to convert the gate sequence to a PhasedXZ gate.")
358
+ if phxz is not None:
359
+ return {
360
+ str(xza_by_symbols["x_exponent"]): phxz.x_exponent,
361
+ str(xza_by_symbols["z_exponent"]): phxz.z_exponent,
362
+ str(xza_by_symbols["axis_phase_exponent"]): phxz.axis_phase_exponent,
363
+ }
@@ -12,10 +12,17 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import unittest.mock
15
16
  import pytest
16
17
  import numpy as np
17
18
  import cirq
18
- from cirq.transformers.gauge_compiling import GaugeTransformer, CZGaugeTransformer
19
+ from cirq.transformers.gauge_compiling import (
20
+ GaugeTransformer,
21
+ CZGaugeTransformer,
22
+ ConstantGauge,
23
+ GaugeSelector,
24
+ )
25
+ from cirq.transformers.analytical_decompositions import single_qubit_decompositions
19
26
 
20
27
 
21
28
  def test_deep_transformation_not_supported():
@@ -25,10 +32,19 @@ def test_deep_transformation_not_supported():
25
32
  cirq.Circuit(), context=cirq.TransformerContext(deep=True)
26
33
  )
27
34
 
35
+ with pytest.raises(ValueError, match="cannot be used with deep=True"):
36
+ _ = GaugeTransformer(target=cirq.CZ, gauge_selector=lambda _: None).as_sweep(
37
+ cirq.Circuit(), context=cirq.TransformerContext(deep=True), N=1
38
+ )
39
+
28
40
 
29
41
  def test_ignore_tags():
30
42
  c = cirq.Circuit(cirq.CZ(*cirq.LineQubit.range(2)).with_tags('foo'))
31
43
  assert c == CZGaugeTransformer(c, context=cirq.TransformerContext(tags_to_ignore={"foo"}))
44
+ parameterized_circuit, _ = CZGaugeTransformer.as_sweep(
45
+ c, context=cirq.TransformerContext(tags_to_ignore={"foo"}), N=1
46
+ )
47
+ assert c == parameterized_circuit
32
48
 
33
49
 
34
50
  def test_target_can_be_gateset():
@@ -39,3 +55,71 @@ def test_target_can_be_gateset():
39
55
  )
40
56
  want = cirq.Circuit(cirq.Y.on_each(qs), cirq.CZ(*qs), cirq.X.on_each(qs))
41
57
  assert transformer(c, prng=np.random.default_rng(0)) == want
58
+
59
+
60
+ def test_as_sweep_multi_pre_or_multi_post():
61
+ transformer = GaugeTransformer(
62
+ target=cirq.CZ,
63
+ gauge_selector=GaugeSelector(
64
+ gauges=[
65
+ ConstantGauge(
66
+ two_qubit_gate=cirq.CZ,
67
+ support_sweep=True,
68
+ pre_q0=[cirq.X, cirq.X],
69
+ post_q0=[cirq.Z],
70
+ pre_q1=[cirq.Y],
71
+ post_q1=[cirq.Y, cirq.Y, cirq.Y],
72
+ )
73
+ ]
74
+ ),
75
+ )
76
+ qs = cirq.LineQubit.range(2)
77
+ input_circuit = cirq.Circuit(cirq.CZ(*qs))
78
+ parameterized_circuit, sweeps = transformer.as_sweep(input_circuit, N=1)
79
+
80
+ for params in sweeps:
81
+ compiled_circuit = cirq.resolve_parameters(parameterized_circuit, params)
82
+ cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
83
+ input_circuit, compiled_circuit, qubit_map={q: q for q in input_circuit.all_qubits()}
84
+ )
85
+
86
+
87
+ def test_as_sweep_invalid_gauge_sequence():
88
+ transfomer = GaugeTransformer(
89
+ target=cirq.CZ,
90
+ gauge_selector=GaugeSelector(
91
+ gauges=[
92
+ ConstantGauge(
93
+ two_qubit_gate=cirq.CZ,
94
+ support_sweep=True,
95
+ pre_q0=[cirq.measure],
96
+ post_q0=[cirq.Z],
97
+ pre_q1=[cirq.X],
98
+ post_q1=[cirq.Z],
99
+ )
100
+ ]
101
+ ),
102
+ )
103
+ qs = cirq.LineQubit.range(2)
104
+ c = cirq.Circuit(cirq.CZ(*qs))
105
+ with pytest.raises(ValueError, match="Invalid gate sequence to be converted to PhasedXZGate."):
106
+ transfomer.as_sweep(c, N=1)
107
+
108
+
109
+ def test_as_sweep_convert_to_phxz_failed():
110
+ qs = cirq.LineQubit.range(2)
111
+ c = cirq.Circuit(cirq.CZ(*qs))
112
+
113
+ def mock_single_qubit_matrix_to_phxz(*args, **kwargs):
114
+ # Return an non PhasedXZ gate, so we expect errors from as_sweep().
115
+ return cirq.X
116
+
117
+ with unittest.mock.patch.object(
118
+ single_qubit_decompositions,
119
+ "single_qubit_matrix_to_phxz",
120
+ new=mock_single_qubit_matrix_to_phxz,
121
+ ):
122
+ with pytest.raises(
123
+ ValueError, match="Failed to convert the gate sequence to a PhasedXZ gate."
124
+ ):
125
+ _ = CZGaugeTransformer.as_sweep(c, context=cirq.TransformerContext(), N=1)
@@ -27,6 +27,7 @@ class GaugeTester:
27
27
  two_qubit_gate: cirq.Gate
28
28
  gauge_transformer: GaugeTransformer
29
29
  must_fail: bool = False
30
+ sweep_must_pass: bool = False
30
31
 
31
32
  @pytest.mark.parametrize(
32
33
  ['generation_seed', 'transformation_seed'],
@@ -73,6 +74,42 @@ class GaugeTester:
73
74
  else:
74
75
  _check_equivalent_with_error_message(c, nc, gauge)
75
76
 
77
+ def test_sweep(self):
78
+ qubits = cirq.LineQubit.range(3)
79
+
80
+ if not self.sweep_must_pass:
81
+ with pytest.raises(NotImplementedError):
82
+ self.gauge_transformer.as_sweep(
83
+ cirq.Circuit(cirq.Moment(self.two_qubit_gate(*qubits[:2]))), N=1
84
+ )
85
+ return
86
+
87
+ input_circuit = cirq.Circuit(
88
+ cirq.Moment(cirq.H(qubits[0])),
89
+ cirq.Moment(self.two_qubit_gate(*qubits[:2])),
90
+ cirq.Moment(self.two_qubit_gate(*qubits[1:])),
91
+ cirq.Moment([cirq.H(q) for q in qubits]),
92
+ cirq.Moment([cirq.measure(q) for q in qubits]),
93
+ )
94
+
95
+ n_samples = 5
96
+ parameterized_circuit, sweeps = self.gauge_transformer.as_sweep(input_circuit, N=n_samples)
97
+
98
+ # Check the parameterized circuit and N set of parameters.
99
+ assert cirq.is_parameterized(parameterized_circuit)
100
+ simulator = cirq.Simulator()
101
+ results = simulator.run_sweep(parameterized_circuit, sweeps)
102
+ assert len(results) == n_samples
103
+
104
+ # Check compilied circuits have the same unitary as the orig circuit.
105
+ for params in sweeps:
106
+ compiled_circuit = cirq.resolve_parameters(parameterized_circuit, params)
107
+ cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
108
+ input_circuit[:-1],
109
+ compiled_circuit[:-1],
110
+ qubit_map={q: q for q in input_circuit.all_qubits()},
111
+ )
112
+
76
113
 
77
114
  def _check_equivalent_with_error_message(c: cirq.AbstractCircuit, nc: cirq.AbstractCircuit, gauge):
78
115
  try:
@@ -26,7 +26,15 @@ class ExampleGate(cirq.testing.TwoQubitGate):
26
26
  return self.unitary
27
27
 
28
28
 
29
+ class ExampleSweepGate(cirq.testing.TwoQubitGate):
30
+ unitary = cirq.unitary(cirq.CZ)
31
+
32
+ def _unitary_(self) -> np.ndarray:
33
+ return self.unitary
34
+
35
+
29
36
  _EXAMPLE_TARGET = ExampleGate()
37
+ _EXAMPLE_SWEEP_TARGET = ExampleSweepGate()
30
38
 
31
39
  _GOOD_TRANSFORMER = GaugeTransformer(
32
40
  target=_EXAMPLE_TARGET,
@@ -40,6 +48,22 @@ _BAD_TRANSFORMER = GaugeTransformer(
40
48
  ),
41
49
  )
42
50
 
51
+ _TRANSFORMER_WITH_SWEEP = GaugeTransformer(
52
+ target=_EXAMPLE_SWEEP_TARGET,
53
+ gauge_selector=GaugeSelector(
54
+ gauges=[
55
+ ConstantGauge(
56
+ two_qubit_gate=_EXAMPLE_SWEEP_TARGET,
57
+ pre_q0=cirq.Z,
58
+ pre_q1=cirq.Z,
59
+ post_q0=cirq.Z,
60
+ post_q1=cirq.Z,
61
+ support_sweep=True,
62
+ )
63
+ ]
64
+ ),
65
+ )
66
+
43
67
 
44
68
  class TestValidTransformer(GaugeTester):
45
69
  two_qubit_gate = _EXAMPLE_TARGET
@@ -50,3 +74,9 @@ class TestInvalidTransformer(GaugeTester):
50
74
  two_qubit_gate = _EXAMPLE_TARGET
51
75
  gauge_transformer = _BAD_TRANSFORMER
52
76
  must_fail = True
77
+
78
+
79
+ class TestSweep(GaugeTester):
80
+ two_qubit_gate = _EXAMPLE_SWEEP_TARGET
81
+ gauge_transformer = _TRANSFORMER_WITH_SWEEP
82
+ sweep_must_pass = True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cirq-core
3
- Version: 1.5.0.dev20241220195200
3
+ Version: 1.5.0.dev20241221000556
4
4
  Summary: A framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
5
5
  Home-page: http://github.com/quantumlib/cirq
6
6
  Author: The Cirq Developers
@@ -4,8 +4,8 @@ cirq/_compat_test.py,sha256=Qq3ZcfgD-Nb81cEppQdJqhAyrVqXKtfXZYGXT0p-Wh0,34718
4
4
  cirq/_doc.py,sha256=yDyWUD_2JDS0gShfGRb-rdqRt9-WeL7DhkqX7np0Nko,2879
5
5
  cirq/_import.py,sha256=p9gMHJscbtDDkfHOaulvd3Aer0pwUF5AXpL89XR8dNw,8402
6
6
  cirq/_import_test.py,sha256=6K_v0riZJXOXUphHNkGA8MY-JcmGlezFaGmvrNhm3OQ,1015
7
- cirq/_version.py,sha256=dPaa8yrdK5buJFr5S5fOt0KpPJ-F-HoYxSDqDBco1_w,1206
8
- cirq/_version_test.py,sha256=j8wRMiv7LlOfF9JlQcW5gYoN0x3c1fws-8ub4E-LOFU,147
7
+ cirq/_version.py,sha256=OqoCeE--Ab9NG2PKQn-oiComWbF_Pgw1sRYHYc8sEY0,1206
8
+ cirq/_version_test.py,sha256=UMG2gtNTe_70vsxwkOgm2BvpCnF9uav4WLuoPUqXTjY,147
9
9
  cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
10
10
  cirq/json_resolver_cache.py,sha256=03MVo6Y-UYrzt9CKHmwpiBLN2ixL6uSU-OWnKZXfG7k,13302
11
11
  cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
@@ -1092,12 +1092,12 @@ cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py,sha256=85Mbu
1092
1092
  cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py,sha256=F_XpM4ApYHxV6hbWnV3C7Ud9L1BnpvBHBXShPh2mP3k,25397
1093
1093
  cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py,sha256=eKOzjWkR7xs-CL2oPj__nWXR0LL9oO42wEHibnvWq-o,20618
1094
1094
  cirq/transformers/gauge_compiling/__init__.py,sha256=ZF53ZtYRJeKsVJYjKc_QrAqE1pyd8FFmmb6Wo8JdgQs,1385
1095
- cirq/transformers/gauge_compiling/cz_gauge.py,sha256=TNZviXFu4j-lCF87QMGYVdb2RC_ePHLdI6FRCqh9go4,2550
1096
- cirq/transformers/gauge_compiling/cz_gauge_test.py,sha256=_2RMzwuMoqytgsVZEET2m6QsGoZ2_uWgBfSGGvhZEWo,854
1097
- cirq/transformers/gauge_compiling/gauge_compiling.py,sha256=7jUg2MHVX2V8SzH7r27e_BUUA_p5l15-Qv8lLlhGasQ,7948
1098
- cirq/transformers/gauge_compiling/gauge_compiling_test.py,sha256=xVeoaaMuenlp_pxqmZO89kJEeBV0iapK7-JDTUuC7Lg,1565
1099
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py,sha256=6mpF2ftcDtWQEsZNr-m16GkDOn5WBWV08JB4ZS5rf8M,3408
1100
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py,sha256=HQw1xeko9OAD0PCuKcehUiy8mbxeRza4nE-6E8MGVME,1584
1095
+ cirq/transformers/gauge_compiling/cz_gauge.py,sha256=pJ41uVaUltigKLIayxr0XMqTYEs0zUDnaWD-tp65pPk,4198
1096
+ cirq/transformers/gauge_compiling/cz_gauge_test.py,sha256=sHEgEEI_z9-Ka5ChN2JmtoYcEHhNYHysOjGJzaaKkoA,881
1097
+ cirq/transformers/gauge_compiling/gauge_compiling.py,sha256=MyzYcgr0vl0pzOq41jkzmrM6COsDg7e2iU_xQcUoQ20,15063
1098
+ cirq/transformers/gauge_compiling/gauge_compiling_test.py,sha256=Nm0Uxqrq1Y5puQep9UpKXK2zg9a3Dx2NSFArIxeawUg,4444
1099
+ cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py,sha256=7RNZ6-xQ1iKjoNWTokgok7xTCeAnrQUzbpdBhdJZEfY,4933
1100
+ cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py,sha256=cWEAP1EWbpHNp7wQPXLyT413raoG3aIg8aFod_aXAtQ,2340
1101
1101
  cirq/transformers/gauge_compiling/iswap_gauge.py,sha256=UGJ_061h65Rfgb9LWREjxC8OSt01ZqP9TGnacL8VAuk,3500
1102
1102
  cirq/transformers/gauge_compiling/iswap_gauge_test.py,sha256=HEIIwKlX5ixau1e_etSUj5NvYOVTT-Gc3kuHcyKAeJ4,866
1103
1103
  cirq/transformers/gauge_compiling/spin_inversion_gauge.py,sha256=gfjSlQdo13GfBPlrkQoHPWWzouiV7yYr7JAaB85NSGY,1086
@@ -1189,8 +1189,8 @@ cirq/work/sampler.py,sha256=bE5tmVkcR6cZZMLETxDfHehdsYUMbx2RvBeIBetehI4,19187
1189
1189
  cirq/work/sampler_test.py,sha256=hL2UWx3dz2ukZVNxWftiKVvJcQoLplLZdQm-k1QcA40,13282
1190
1190
  cirq/work/zeros_sampler.py,sha256=x1C7cup66a43n-3tm8QjhiqJa07qcJW10FxNp9jJ59Q,2356
1191
1191
  cirq/work/zeros_sampler_test.py,sha256=JIkpBBFPJe5Ba4142vzogyWyboG1Q1ZAm0UVGgOoZn8,3279
1192
- cirq_core-1.5.0.dev20241220195200.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1193
- cirq_core-1.5.0.dev20241220195200.dist-info/METADATA,sha256=yAQPpmLOdT_gJeAKrLe6S17oCv5xxFWM8SGAm1oDpOI,1992
1194
- cirq_core-1.5.0.dev20241220195200.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
1195
- cirq_core-1.5.0.dev20241220195200.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1196
- cirq_core-1.5.0.dev20241220195200.dist-info/RECORD,,
1192
+ cirq_core-1.5.0.dev20241221000556.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1193
+ cirq_core-1.5.0.dev20241221000556.dist-info/METADATA,sha256=P70dL9Vm3tnlLFwyneVhZiRBS6axK3zAqZcEOrgNckg,1992
1194
+ cirq_core-1.5.0.dev20241221000556.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
1195
+ cirq_core-1.5.0.dev20241221000556.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1196
+ cirq_core-1.5.0.dev20241221000556.dist-info/RECORD,,