cirq-core 1.5.0.dev20250129170403__py3-none-any.whl → 1.5.0.dev20250130015503__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.dev20250129170403"
31
+ __version__ = "1.5.0.dev20250130015503"
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.dev20250129170403"
6
+ assert cirq.__version__ == "1.5.0.dev20250130015503"
@@ -204,11 +204,12 @@ class CircuitOperation(ops.Operation):
204
204
  )
205
205
 
206
206
  self._repeat_until = repeat_until
207
- if self._repeat_until:
207
+ mapped_repeat_until = self._mapped_repeat_until
208
+ if mapped_repeat_until:
208
209
  if self._use_repetition_ids or self._repetitions != 1:
209
210
  raise ValueError('Cannot use repetitions with repeat_until')
210
211
  if protocols.measurement_key_objs(self._mapped_single_loop()).isdisjoint(
211
- self._repeat_until.keys
212
+ mapped_repeat_until.keys
212
213
  ):
213
214
  raise ValueError('Infinite loop: condition is not modified in subcircuit.')
214
215
 
@@ -266,7 +267,9 @@ class CircuitOperation(ops.Operation):
266
267
  'repetition_ids': self.repetition_ids,
267
268
  'parent_path': self.parent_path,
268
269
  'extern_keys': self._extern_keys,
269
- 'use_repetition_ids': True if 'repetition_ids' in changes else self.use_repetition_ids,
270
+ 'use_repetition_ids': (
271
+ True if changes.get('repetition_ids') is not None else self.use_repetition_ids
272
+ ),
270
273
  'repeat_until': self.repeat_until,
271
274
  **changes,
272
275
  }
@@ -347,8 +350,9 @@ class CircuitOperation(ops.Operation):
347
350
  if not protocols.control_keys(self.circuit)
348
351
  else protocols.control_keys(self._mapped_single_loop())
349
352
  )
350
- if self.repeat_until is not None:
351
- keys |= frozenset(self.repeat_until.keys) - self._measurement_key_objs_()
353
+ mapped_repeat_until = self._mapped_repeat_until
354
+ if mapped_repeat_until is not None:
355
+ keys |= frozenset(mapped_repeat_until.keys) - self._measurement_key_objs_()
352
356
  return keys
353
357
 
354
358
  def _control_keys_(self) -> FrozenSet['cirq.MeasurementKey']:
@@ -362,11 +366,8 @@ class CircuitOperation(ops.Operation):
362
366
 
363
367
  def _parameter_names_generator(self) -> Iterator[str]:
364
368
  yield from protocols.parameter_names(self.repetitions)
365
- for symbol in protocols.parameter_symbols(self.circuit):
366
- for name in protocols.parameter_names(
367
- protocols.resolve_parameters(symbol, self.param_resolver, recursive=False)
368
- ):
369
- yield name
369
+ yield from protocols.parameter_names(self._mapped_repeat_until)
370
+ yield from protocols.parameter_names(self._mapped_any_loop)
370
371
 
371
372
  @cached_property
372
373
  def _mapped_any_loop(self) -> 'cirq.Circuit':
@@ -389,6 +390,26 @@ class CircuitOperation(ops.Operation):
389
390
  circuit, self.parent_path, bindable_keys=self._extern_keys
390
391
  )
391
392
 
393
+ @cached_property
394
+ def _mapped_repeat_until(self) -> Optional['cirq.Condition']:
395
+ """Applies measurement_key_map, param_resolver, and current scope to repeat_until."""
396
+ repeat_until = self.repeat_until
397
+ if not repeat_until:
398
+ return repeat_until
399
+ if self.measurement_key_map:
400
+ repeat_until = protocols.with_measurement_key_mapping(
401
+ repeat_until, self.measurement_key_map
402
+ )
403
+ if self.param_resolver:
404
+ repeat_until = protocols.resolve_parameters(
405
+ repeat_until, self.param_resolver, recursive=False
406
+ )
407
+ return protocols.with_rescoped_keys(
408
+ repeat_until,
409
+ self.parent_path,
410
+ bindable_keys=self._extern_keys | self._measurement_key_objs,
411
+ )
412
+
392
413
  def mapped_circuit(self, deep: bool = False) -> 'cirq.Circuit':
393
414
  """Applies all maps to the contained circuit and returns the result.
394
415
 
@@ -425,12 +446,13 @@ class CircuitOperation(ops.Operation):
425
446
  return self.mapped_circuit(deep=False).all_operations()
426
447
 
427
448
  def _act_on_(self, sim_state: 'cirq.SimulationStateBase') -> bool:
428
- if self.repeat_until:
449
+ mapped_repeat_until = self._mapped_repeat_until
450
+ if mapped_repeat_until:
429
451
  circuit = self._mapped_single_loop()
430
452
  while True:
431
453
  for op in circuit.all_operations():
432
454
  protocols.act_on(op, sim_state)
433
- if self.repeat_until.resolve(sim_state.classical_data):
455
+ if mapped_repeat_until.resolve(sim_state.classical_data):
434
456
  break
435
457
  else:
436
458
  for op in self._decompose_():
@@ -806,7 +828,9 @@ class CircuitOperation(ops.Operation):
806
828
  by param_values.
807
829
  """
808
830
  new_params = {}
809
- for k in protocols.parameter_symbols(self.circuit):
831
+ for k in protocols.parameter_symbols(self.circuit) | protocols.parameter_symbols(
832
+ self.repeat_until
833
+ ):
810
834
  v = self.param_resolver.value_of(k, recursive=False)
811
835
  v = protocols.resolve_parameters(v, param_values, recursive=recursive)
812
836
  if v != k:
@@ -332,6 +332,28 @@ def test_repeat(add_measurements: bool, use_default_ids_for_initial_rep: bool) -
332
332
  assert op_base.repeat(2.99999999999).repetitions == 3
333
333
 
334
334
 
335
+ def test_replace_repetition_ids() -> None:
336
+ a, b = cirq.LineQubit.range(2)
337
+ circuit = cirq.Circuit(cirq.H(a), cirq.CX(a, b), cirq.M(b, key='mb'), cirq.M(a, key='ma'))
338
+ op = cirq.CircuitOperation(circuit.freeze())
339
+ assert op.repetitions == 1
340
+ assert not op.use_repetition_ids
341
+
342
+ op2 = op.replace(repetitions=2)
343
+ assert op2.repetitions == 2
344
+ assert not op2.use_repetition_ids
345
+
346
+ op3 = op.replace(repetitions=3, repetition_ids=None)
347
+ assert op3.repetitions == 3
348
+ assert not op3.use_repetition_ids
349
+
350
+ # Passing `repetition_ids` will also enable `use_repetition_ids`
351
+ op4 = op.replace(repetitions=4, repetition_ids=['a', 'b', 'c', 'd'])
352
+ assert op4.repetitions == 4
353
+ assert op4.use_repetition_ids
354
+ assert op4.repetition_ids == ['a', 'b', 'c', 'd']
355
+
356
+
335
357
  @pytest.mark.parametrize('add_measurements', [True, False])
336
358
  @pytest.mark.parametrize('use_repetition_ids', [True, False])
337
359
  @pytest.mark.parametrize('initial_reps', [0, 1, 2, 3])
@@ -1217,4 +1239,57 @@ def test_repeat_until_error():
1217
1239
  )
1218
1240
 
1219
1241
 
1242
+ def test_repeat_until_protocols():
1243
+ q = cirq.LineQubit(0)
1244
+ op = cirq.CircuitOperation(
1245
+ cirq.FrozenCircuit(cirq.H(q) ** sympy.Symbol('p'), cirq.measure(q, key='a')),
1246
+ repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol('a'), 0)),
1247
+ )
1248
+ scoped = cirq.with_rescoped_keys(op, ('0',))
1249
+ # Ensure the _repeat_until has been mapped, the measurement has been mapped to the same key,
1250
+ # and the control keys of the subcircuit is empty (because the control key of the condition is
1251
+ # bound to the measurement).
1252
+ assert scoped._mapped_repeat_until.keys == (cirq.MeasurementKey('a', ('0',)),)
1253
+ assert cirq.measurement_key_objs(scoped) == {cirq.MeasurementKey('a', ('0',))}
1254
+ assert not cirq.control_keys(scoped)
1255
+ mapped = cirq.with_measurement_key_mapping(scoped, {'a': 'b'})
1256
+ assert mapped._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('0',)),)
1257
+ assert cirq.measurement_key_objs(mapped) == {cirq.MeasurementKey('b', ('0',))}
1258
+ assert not cirq.control_keys(mapped)
1259
+ prefixed = cirq.with_key_path_prefix(mapped, ('1',))
1260
+ assert prefixed._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('1', '0')),)
1261
+ assert cirq.measurement_key_objs(prefixed) == {cirq.MeasurementKey('b', ('1', '0'))}
1262
+ assert not cirq.control_keys(prefixed)
1263
+ setpath = cirq.with_key_path(prefixed, ('2',))
1264
+ assert setpath._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('2',)),)
1265
+ assert cirq.measurement_key_objs(setpath) == {cirq.MeasurementKey('b', ('2',))}
1266
+ assert not cirq.control_keys(setpath)
1267
+ resolved = cirq.resolve_parameters(setpath, {'p': 1})
1268
+ assert resolved._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('2',)),)
1269
+ assert cirq.measurement_key_objs(resolved) == {cirq.MeasurementKey('b', ('2',))}
1270
+ assert not cirq.control_keys(resolved)
1271
+
1272
+
1273
+ def test_inner_repeat_until_simulate():
1274
+ sim = cirq.Simulator()
1275
+ q = cirq.LineQubit(0)
1276
+ inner_loop = cirq.CircuitOperation(
1277
+ cirq.FrozenCircuit(cirq.H(q), cirq.measure(q, key="inner_loop")),
1278
+ repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol("inner_loop"), 0)),
1279
+ )
1280
+ outer_loop = cirq.Circuit(inner_loop, cirq.X(q), cirq.measure(q, key="outer_loop"))
1281
+ circuit = cirq.Circuit(
1282
+ cirq.CircuitOperation(
1283
+ cirq.FrozenCircuit(outer_loop), repetitions=2, use_repetition_ids=True
1284
+ )
1285
+ )
1286
+ result = sim.run(circuit, repetitions=1)
1287
+ assert all(len(v) == 1 and v[0] == 1 for v in result.records['0:inner_loop'][0][:-1])
1288
+ assert result.records['0:inner_loop'][0][-1] == [0]
1289
+ assert result.records['0:outer_loop'] == [[[1]]]
1290
+ assert all(len(v) == 1 and v[0] == 1 for v in result.records['1:inner_loop'][0][:-1])
1291
+ assert result.records['1:inner_loop'][0][-1] == [0]
1292
+ assert result.records['1:outer_loop'] == [[[1]]]
1293
+
1294
+
1220
1295
  # TODO: Operation has a "gate" property. What is this for a CircuitOperation?
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cirq-core
3
- Version: 1.5.0.dev20250129170403
3
+ Version: 1.5.0.dev20250130015503
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=g1SwSxTTMRqe0SCQLN4jCqEoiAGb7QqZlMPwn2FHAWQ,1206
8
- cirq/_version_test.py,sha256=JJvDW9aVU9QjyAclatis4-vc9z7aHTqYlpp0ZW4Yshc,147
7
+ cirq/_version.py,sha256=Z3MeetPG8uFdenZ8lUi6QnXnRi17cW83EK8ooyUVaqU,1206
8
+ cirq/_version_test.py,sha256=z9D3sbZSuBjDrgV9H6P-omFuNl3Tu0cKLKbtrPGAz-8,147
9
9
  cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
10
10
  cirq/json_resolver_cache.py,sha256=p-vEOa-8GQ2cFIAdze-kd6C1un1uRvtujVPljVKaHBg,13557
11
11
  cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
@@ -17,8 +17,8 @@ cirq/circuits/_box_drawing_character_data_test.py,sha256=XO94z0piwZRHaNZHTf-5tKH
17
17
  cirq/circuits/_bucket_priority_queue.py,sha256=hxFuii2fKD8G6EKT_aVLEsA7FmSfqFXPwIbA0KsoSC4,6745
18
18
  cirq/circuits/_bucket_priority_queue_test.py,sha256=t6u_hG7K2e2WKWrgCsKxNRtp4ghKwiCrp0_WSY0W25k,5288
19
19
  cirq/circuits/circuit.py,sha256=nbWC95tzQlm69JmvFJdJMwzDOia_s0pah8tH4i9u1Ug,118173
20
- cirq/circuits/circuit_operation.py,sha256=MaQ6fPt1HctEE31fVaUDtl9MqOmoTyt3m2HYeGCdIaM,35440
21
- cirq/circuits/circuit_operation_test.py,sha256=7ezTwTY2RaAchjfXOJythVrxs6Rom317gC0AUBe0GVM,45259
20
+ cirq/circuits/circuit_operation.py,sha256=ebI2KBvQLcBYgjQXKO6y6jB2EDLgwtxdZBRs3hSYaLM,36438
21
+ cirq/circuits/circuit_operation_test.py,sha256=SFyM12Ky7-OVwl-jK3OTMMN0DD5hR6tWfx_v7m6HUMo,48866
22
22
  cirq/circuits/circuit_test.py,sha256=BZjwavIekWR2hgG1yV0Acgt7-Q05cOjugozrLgYdx7k,161268
23
23
  cirq/circuits/frozen_circuit.py,sha256=qSbLHqIszCbVipNZQy4N829v_mWf8N2926cYRzpxGqE,9243
24
24
  cirq/circuits/frozen_circuit_test.py,sha256=rHyii8hLhOQ6jdA8dC1OcYPGnyeBC4uY5Q53XspkkCk,4133
@@ -1202,8 +1202,8 @@ cirq/work/sampler.py,sha256=bE5tmVkcR6cZZMLETxDfHehdsYUMbx2RvBeIBetehI4,19187
1202
1202
  cirq/work/sampler_test.py,sha256=hL2UWx3dz2ukZVNxWftiKVvJcQoLplLZdQm-k1QcA40,13282
1203
1203
  cirq/work/zeros_sampler.py,sha256=x1C7cup66a43n-3tm8QjhiqJa07qcJW10FxNp9jJ59Q,2356
1204
1204
  cirq/work/zeros_sampler_test.py,sha256=JIkpBBFPJe5Ba4142vzogyWyboG1Q1ZAm0UVGgOoZn8,3279
1205
- cirq_core-1.5.0.dev20250129170403.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1206
- cirq_core-1.5.0.dev20250129170403.dist-info/METADATA,sha256=clZcpQi-Nc34xIBgsUaiId0cvJ_5WpR1BErlWzJMi3E,3239
1207
- cirq_core-1.5.0.dev20250129170403.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
1208
- cirq_core-1.5.0.dev20250129170403.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1209
- cirq_core-1.5.0.dev20250129170403.dist-info/RECORD,,
1205
+ cirq_core-1.5.0.dev20250130015503.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1206
+ cirq_core-1.5.0.dev20250130015503.dist-info/METADATA,sha256=-pHqgurSc5x5vO1o8MvoRkzRl1QgSLjhSxEBZJFoNrg,3239
1207
+ cirq_core-1.5.0.dev20250130015503.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
1208
+ cirq_core-1.5.0.dev20250130015503.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1209
+ cirq_core-1.5.0.dev20250130015503.dist-info/RECORD,,