cirq-core 1.2.0.dev20230717232332__py3-none-any.whl → 1.3.0__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.
- cirq/__init__.py +5 -0
- cirq/_compat.py +26 -11
- cirq/_compat_test.py +37 -3
- cirq/_version.py +31 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/circuit.py +106 -32
- cirq/circuits/circuit_operation.py +2 -2
- cirq/circuits/circuit_operation_test.py +1 -1
- cirq/circuits/circuit_test.py +109 -3
- cirq/circuits/frozen_circuit.py +80 -5
- cirq/circuits/frozen_circuit_test.py +47 -2
- cirq/circuits/qasm_output_test.py +9 -9
- cirq/conftest.py +1 -2
- cirq/contrib/acquaintance/devices.py +1 -1
- cirq/contrib/hacks/disable_validation_test.py +1 -1
- cirq/contrib/noise_models/noise_models.py +1 -2
- cirq/contrib/paulistring/clifford_optimize.py +1 -1
- cirq/contrib/paulistring/clifford_target_gateset_test.py +4 -4
- cirq/contrib/qcircuit/qcircuit_pdf.py +1 -1
- cirq/contrib/quimb/density_matrix.py +2 -3
- cirq/contrib/quimb/grid_circuits.py +3 -3
- cirq/contrib/quimb/state_vector.py +3 -5
- cirq/contrib/routing/utils.py +1 -2
- cirq/contrib/svg/svg.py +4 -6
- cirq/devices/grid_qubit.py +49 -38
- cirq/devices/grid_qubit_test.py +1 -3
- cirq/devices/insertion_noise_model.py +21 -1
- cirq/devices/insertion_noise_model_test.py +6 -0
- cirq/devices/line_qubit.py +67 -40
- cirq/devices/named_topologies.py +8 -14
- cirq/devices/noise_properties.py +1 -1
- cirq/devices/noise_utils.py +7 -5
- cirq/devices/noise_utils_test.py +7 -0
- cirq/experiments/fidelity_estimation_test.py +1 -1
- cirq/experiments/qubit_characterizations.py +6 -5
- cirq/experiments/random_quantum_circuit_generation.py +1 -1
- cirq/experiments/random_quantum_circuit_generation_test.py +28 -1
- cirq/experiments/readout_confusion_matrix.py +6 -6
- cirq/experiments/xeb_fitting.py +3 -5
- cirq/experiments/xeb_fitting_test.py +2 -2
- cirq/experiments/xeb_sampling.py +1 -1
- cirq/interop/quirk/url_to_circuit.py +40 -38
- cirq/json_resolver_cache.py +2 -0
- cirq/linalg/decompositions.py +6 -5
- cirq/ops/__init__.py +2 -0
- cirq/ops/classically_controlled_operation.py +1 -1
- cirq/ops/clifford_gate.py +9 -9
- cirq/ops/clifford_gate_test.py +3 -4
- cirq/ops/common_channels.py +2 -5
- cirq/ops/common_channels_test.py +3 -5
- cirq/ops/common_gates_test.py +7 -7
- cirq/ops/controlled_operation_test.py +2 -2
- cirq/ops/dense_pauli_string.py +3 -0
- cirq/ops/eigen_gate_test.py +1 -3
- cirq/ops/fourier_transform.py +1 -2
- cirq/ops/fsim_gate.py +1 -1
- cirq/ops/gate_features_test.py +2 -2
- cirq/ops/gate_operation_test.py +1 -2
- cirq/ops/greedy_qubit_manager.py +86 -0
- cirq/ops/greedy_qubit_manager_test.py +98 -0
- cirq/ops/linear_combinations.py +1 -1
- cirq/ops/named_qubit.py +55 -18
- cirq/ops/parity_gates.py +65 -18
- cirq/ops/parity_gates_test.py +41 -2
- cirq/ops/pauli_gates.py +2 -2
- cirq/ops/pauli_string.py +3 -4
- cirq/ops/pauli_string_raw_types_test.py +3 -3
- cirq/ops/pauli_string_test.py +3 -4
- cirq/ops/random_gate_channel_test.py +3 -3
- cirq/ops/raw_types.py +1 -1
- cirq/ops/raw_types_test.py +5 -5
- cirq/ops/three_qubit_gates.py +12 -8
- cirq/protocols/act_on_protocol_test.py +9 -9
- cirq/protocols/apply_channel_protocol.py +9 -6
- cirq/protocols/apply_unitary_protocol_test.py +1 -1
- cirq/protocols/equal_up_to_global_phase_protocol_test.py +2 -2
- cirq/protocols/has_stabilizer_effect_protocol.py +52 -6
- cirq/protocols/has_stabilizer_effect_protocol_test.py +21 -8
- cirq/protocols/has_unitary_protocol_test.py +1 -3
- cirq/protocols/json_serialization.py +6 -6
- cirq/protocols/json_serialization_test.py +7 -14
- cirq/protocols/json_test_data/InsertionNoiseModel.json +91 -0
- cirq/protocols/json_test_data/InsertionNoiseModel.repr +4 -0
- cirq/protocols/json_test_data/OpIdentifier.json +45 -10
- cirq/protocols/json_test_data/OpIdentifier.repr +7 -1
- cirq/protocols/json_test_data/spec.py +4 -0
- cirq/protocols/measurement_key_protocol_test.py +1 -1
- cirq/protocols/unitary_protocol_test.py +13 -16
- cirq/qis/clifford_tableau.py +7 -8
- cirq/qis/measures.py +1 -1
- cirq/qis/states.py +2 -3
- cirq/sim/__init__.py +2 -0
- cirq/sim/classical_simulator.py +107 -0
- cirq/sim/classical_simulator_test.py +207 -0
- cirq/sim/clifford/clifford_simulator_test.py +7 -7
- cirq/sim/clifford/stabilizer_simulation_state.py +2 -2
- cirq/sim/clifford/stabilizer_state_ch_form.py +7 -7
- cirq/sim/density_matrix_simulation_state.py +19 -4
- cirq/sim/density_matrix_simulator_test.py +5 -13
- cirq/sim/simulation_state_test.py +13 -14
- cirq/sim/simulator_test.py +6 -9
- cirq/sim/state_vector_simulation_state.py +1 -1
- cirq/study/resolver.py +41 -41
- cirq/study/resolver_test.py +13 -12
- cirq/testing/__init__.py +4 -1
- cirq/testing/circuit_compare.py +1 -1
- cirq/testing/circuit_compare_test.py +11 -11
- cirq/testing/consistent_controlled_gate_op.py +15 -1
- cirq/testing/consistent_controlled_gate_op_test.py +12 -3
- cirq/testing/consistent_decomposition.py +0 -1
- cirq/testing/consistent_protocols.py +6 -1
- cirq/testing/consistent_protocols_test.py +5 -10
- cirq/testing/consistent_qasm.py +2 -4
- cirq/testing/consistent_qasm_test.py +2 -3
- cirq/testing/consistent_specified_has_unitary_test.py +1 -3
- cirq/testing/equals_tester.py +1 -1
- cirq/testing/equals_tester_test.py +5 -5
- cirq/testing/equivalent_repr_eval_test.py +1 -3
- cirq/testing/gate_features_test.py +6 -6
- cirq/testing/order_tester_test.py +1 -3
- cirq/testing/random_circuit_test.py +1 -3
- cirq/transformers/__init__.py +3 -0
- cirq/transformers/analytical_decompositions/__init__.py +1 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +1 -2
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +2 -5
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +38 -0
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +18 -0
- cirq/transformers/expand_composite_test.py +4 -4
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +1 -1
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +1 -2
- cirq/transformers/merge_k_qubit_gates_test.py +2 -2
- cirq/transformers/qubit_management_transformers.py +177 -0
- cirq/transformers/qubit_management_transformers_test.py +250 -0
- cirq/transformers/routing/route_circuit_cqc.py +23 -4
- cirq/transformers/routing/route_circuit_cqc_test.py +42 -0
- cirq/transformers/stratify.py +10 -11
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +10 -10
- cirq/transformers/target_gatesets/cz_gateset_test.py +8 -10
- cirq/transformers/transformer_primitives.py +138 -28
- cirq/value/abc_alt_test.py +4 -4
- cirq/value/duration.py +68 -37
- cirq/value/duration_test.py +2 -0
- cirq/value/measurement_key_test.py +1 -1
- cirq/value/product_state.py +4 -8
- cirq/value/value_equality_attr.py +12 -5
- cirq/vis/heatmap.py +7 -4
- cirq/vis/heatmap_test.py +14 -4
- cirq/vis/histogram.py +4 -4
- cirq/vis/state_histogram.py +10 -6
- cirq/vis/state_histogram_test.py +2 -0
- cirq/work/observable_measurement_data_test.py +1 -1
- cirq/work/observable_measurement_test.py +2 -2
- cirq/work/zeros_sampler.py +1 -1
- {cirq_core-1.2.0.dev20230717232332.dist-info → cirq_core-1.3.0.dist-info}/METADATA +11 -19
- {cirq_core-1.2.0.dev20230717232332.dist-info → cirq_core-1.3.0.dist-info}/RECORD +158 -150
- {cirq_core-1.2.0.dev20230717232332.dist-info → cirq_core-1.3.0.dist-info}/WHEEL +1 -1
- {cirq_core-1.2.0.dev20230717232332.dist-info → cirq_core-1.3.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.2.0.dev20230717232332.dist-info → cirq_core-1.3.0.dist-info}/top_level.txt +0 -0
cirq/circuits/circuit_test.py
CHANGED
|
@@ -23,7 +23,6 @@ import pytest
|
|
|
23
23
|
import sympy
|
|
24
24
|
|
|
25
25
|
import cirq
|
|
26
|
-
import cirq.testing
|
|
27
26
|
from cirq import circuits
|
|
28
27
|
from cirq import ops
|
|
29
28
|
from cirq.testing.devices import ValidatingTestDevice
|
|
@@ -72,19 +71,32 @@ moment_and_op_type_validating_device = _MomentAndOpTypeValidatingDeviceType()
|
|
|
72
71
|
|
|
73
72
|
def test_from_moments():
|
|
74
73
|
a, b, c, d = cirq.LineQubit.range(4)
|
|
75
|
-
|
|
74
|
+
moment = cirq.Moment(cirq.Z(a), cirq.Z(b))
|
|
75
|
+
subcircuit = cirq.FrozenCircuit.from_moments(cirq.X(c), cirq.Y(d))
|
|
76
|
+
circuit = cirq.Circuit.from_moments(
|
|
77
|
+
moment,
|
|
78
|
+
subcircuit,
|
|
76
79
|
[cirq.X(a), cirq.Y(b)],
|
|
77
80
|
[cirq.X(c)],
|
|
78
81
|
[],
|
|
79
82
|
cirq.Z(d),
|
|
80
83
|
[cirq.measure(a, b, key='ab'), cirq.measure(c, d, key='cd')],
|
|
81
|
-
)
|
|
84
|
+
)
|
|
85
|
+
assert circuit == cirq.Circuit(
|
|
86
|
+
cirq.Moment(cirq.Z(a), cirq.Z(b)),
|
|
87
|
+
cirq.Moment(
|
|
88
|
+
cirq.CircuitOperation(
|
|
89
|
+
cirq.FrozenCircuit(cirq.Moment(cirq.X(c)), cirq.Moment(cirq.Y(d)))
|
|
90
|
+
)
|
|
91
|
+
),
|
|
82
92
|
cirq.Moment(cirq.X(a), cirq.Y(b)),
|
|
83
93
|
cirq.Moment(cirq.X(c)),
|
|
84
94
|
cirq.Moment(),
|
|
85
95
|
cirq.Moment(cirq.Z(d)),
|
|
86
96
|
cirq.Moment(cirq.measure(a, b, key='ab'), cirq.measure(c, d, key='cd')),
|
|
87
97
|
)
|
|
98
|
+
assert circuit[0] is moment
|
|
99
|
+
assert circuit[1].operations[0].circuit is subcircuit
|
|
88
100
|
|
|
89
101
|
|
|
90
102
|
def test_alignment():
|
|
@@ -4521,6 +4533,100 @@ def test_freeze_not_relocate_moments():
|
|
|
4521
4533
|
assert [mc is fc for mc, fc in zip(c, f)] == [True, True]
|
|
4522
4534
|
|
|
4523
4535
|
|
|
4536
|
+
def test_freeze_is_cached():
|
|
4537
|
+
q = cirq.q(0)
|
|
4538
|
+
c = cirq.Circuit(cirq.X(q), cirq.measure(q))
|
|
4539
|
+
f0 = c.freeze()
|
|
4540
|
+
f1 = c.freeze()
|
|
4541
|
+
assert f1 is f0
|
|
4542
|
+
|
|
4543
|
+
c.append(cirq.Y(q))
|
|
4544
|
+
f2 = c.freeze()
|
|
4545
|
+
f3 = c.freeze()
|
|
4546
|
+
assert f2 is not f1
|
|
4547
|
+
assert f3 is f2
|
|
4548
|
+
|
|
4549
|
+
c[-1] = cirq.Moment(cirq.Y(q))
|
|
4550
|
+
f4 = c.freeze()
|
|
4551
|
+
f5 = c.freeze()
|
|
4552
|
+
assert f4 is not f3
|
|
4553
|
+
assert f5 is f4
|
|
4554
|
+
|
|
4555
|
+
|
|
4556
|
+
@pytest.mark.parametrize(
|
|
4557
|
+
"circuit, mutate",
|
|
4558
|
+
[
|
|
4559
|
+
(
|
|
4560
|
+
cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))),
|
|
4561
|
+
lambda c: c.__setitem__(0, cirq.Moment(cirq.Y(cirq.q(0)))),
|
|
4562
|
+
),
|
|
4563
|
+
(cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))), lambda c: c.__delitem__(0)),
|
|
4564
|
+
(cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))), lambda c: c.__imul__(2)),
|
|
4565
|
+
(
|
|
4566
|
+
cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))),
|
|
4567
|
+
lambda c: c.insert(1, cirq.Y(cirq.q(0))),
|
|
4568
|
+
),
|
|
4569
|
+
(
|
|
4570
|
+
cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))),
|
|
4571
|
+
lambda c: c.insert_into_range([cirq.Y(cirq.q(1)), cirq.M(cirq.q(1))], 0, 2),
|
|
4572
|
+
),
|
|
4573
|
+
(
|
|
4574
|
+
cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))),
|
|
4575
|
+
lambda c: c.insert_at_frontier([cirq.Y(cirq.q(0)), cirq.Y(cirq.q(1))], 1),
|
|
4576
|
+
),
|
|
4577
|
+
(
|
|
4578
|
+
cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))),
|
|
4579
|
+
lambda c: c.batch_replace([(0, cirq.X(cirq.q(0)), cirq.Y(cirq.q(0)))]),
|
|
4580
|
+
),
|
|
4581
|
+
(
|
|
4582
|
+
cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0), cirq.q(1))),
|
|
4583
|
+
lambda c: c.batch_insert_into([(0, cirq.X(cirq.q(1)))]),
|
|
4584
|
+
),
|
|
4585
|
+
(
|
|
4586
|
+
cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))),
|
|
4587
|
+
lambda c: c.batch_insert([(1, cirq.Y(cirq.q(0)))]),
|
|
4588
|
+
),
|
|
4589
|
+
(
|
|
4590
|
+
cirq.Circuit(cirq.X(cirq.q(0)), cirq.M(cirq.q(0))),
|
|
4591
|
+
lambda c: c.clear_operations_touching([cirq.q(0)], [0]),
|
|
4592
|
+
),
|
|
4593
|
+
],
|
|
4594
|
+
)
|
|
4595
|
+
def test_mutation_clears_cached_attributes(circuit, mutate):
|
|
4596
|
+
cached_attributes = [
|
|
4597
|
+
"_all_qubits",
|
|
4598
|
+
"_frozen",
|
|
4599
|
+
"_is_measurement",
|
|
4600
|
+
"_is_parameterized",
|
|
4601
|
+
"_parameter_names",
|
|
4602
|
+
]
|
|
4603
|
+
|
|
4604
|
+
for attr in cached_attributes:
|
|
4605
|
+
assert getattr(circuit, attr) is None, f"{attr=} is not None"
|
|
4606
|
+
|
|
4607
|
+
# Check that attributes are cached after getting them.
|
|
4608
|
+
qubits = circuit.all_qubits()
|
|
4609
|
+
frozen = circuit.freeze()
|
|
4610
|
+
is_measurement = cirq.is_measurement(circuit)
|
|
4611
|
+
is_parameterized = cirq.is_parameterized(circuit)
|
|
4612
|
+
parameter_names = cirq.parameter_names(circuit)
|
|
4613
|
+
|
|
4614
|
+
for attr in cached_attributes:
|
|
4615
|
+
assert getattr(circuit, attr) is not None, f"{attr=} is None"
|
|
4616
|
+
|
|
4617
|
+
# Check that getting again returns same object.
|
|
4618
|
+
assert circuit.all_qubits() is qubits
|
|
4619
|
+
assert circuit.freeze() is frozen
|
|
4620
|
+
assert cirq.is_measurement(circuit) is is_measurement
|
|
4621
|
+
assert cirq.is_parameterized(circuit) is is_parameterized
|
|
4622
|
+
assert cirq.parameter_names(circuit) is parameter_names
|
|
4623
|
+
|
|
4624
|
+
# Check that attributes are cleared after mutation.
|
|
4625
|
+
mutate(circuit)
|
|
4626
|
+
for attr in cached_attributes:
|
|
4627
|
+
assert getattr(circuit, attr) is None, f"{attr=} is not None"
|
|
4628
|
+
|
|
4629
|
+
|
|
4524
4630
|
def test_factorize_one_factor():
|
|
4525
4631
|
circuit = cirq.Circuit()
|
|
4526
4632
|
q0, q1, q2 = cirq.LineQubit.range(3)
|
cirq/circuits/frozen_circuit.py
CHANGED
|
@@ -12,7 +12,17 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""An immutable version of the Circuit data structure."""
|
|
15
|
-
from typing import
|
|
15
|
+
from typing import (
|
|
16
|
+
AbstractSet,
|
|
17
|
+
FrozenSet,
|
|
18
|
+
Hashable,
|
|
19
|
+
Iterable,
|
|
20
|
+
Iterator,
|
|
21
|
+
Sequence,
|
|
22
|
+
Tuple,
|
|
23
|
+
TYPE_CHECKING,
|
|
24
|
+
Union,
|
|
25
|
+
)
|
|
16
26
|
|
|
17
27
|
import numpy as np
|
|
18
28
|
|
|
@@ -34,7 +44,10 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
|
|
|
34
44
|
"""
|
|
35
45
|
|
|
36
46
|
def __init__(
|
|
37
|
-
self,
|
|
47
|
+
self,
|
|
48
|
+
*contents: 'cirq.OP_TREE',
|
|
49
|
+
strategy: 'cirq.InsertStrategy' = InsertStrategy.EARLIEST,
|
|
50
|
+
tags: Sequence[Hashable] = (),
|
|
38
51
|
) -> None:
|
|
39
52
|
"""Initializes a frozen circuit.
|
|
40
53
|
|
|
@@ -47,9 +60,14 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
|
|
|
47
60
|
strategy: When initializing the circuit with operations and moments
|
|
48
61
|
from `contents`, this determines how the operations are packed
|
|
49
62
|
together.
|
|
63
|
+
tags: A sequence of any type of object that is useful to attach metadata
|
|
64
|
+
to this circuit as long as the type is hashable. If you wish the
|
|
65
|
+
resulting circuit to be eventually serialized into JSON, you should
|
|
66
|
+
also restrict the tags to be JSON serializable.
|
|
50
67
|
"""
|
|
51
68
|
base = Circuit(contents, strategy=strategy)
|
|
52
69
|
self._moments = tuple(base.moments)
|
|
70
|
+
self._tags = tuple(tags)
|
|
53
71
|
|
|
54
72
|
@classmethod
|
|
55
73
|
def _from_moments(cls, moments: Iterable['cirq.Moment']) -> 'FrozenCircuit':
|
|
@@ -61,10 +79,41 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
|
|
|
61
79
|
def moments(self) -> Sequence['cirq.Moment']:
|
|
62
80
|
return self._moments
|
|
63
81
|
|
|
82
|
+
def freeze(self) -> 'cirq.FrozenCircuit':
|
|
83
|
+
return self
|
|
84
|
+
|
|
85
|
+
def unfreeze(self, copy: bool = True) -> 'cirq.Circuit':
|
|
86
|
+
return Circuit.from_moments(*self)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def tags(self) -> Tuple[Hashable, ...]:
|
|
90
|
+
"""Returns a tuple of the Circuit's tags."""
|
|
91
|
+
return self._tags
|
|
92
|
+
|
|
93
|
+
@_compat.cached_property
|
|
94
|
+
def untagged(self) -> 'cirq.FrozenCircuit':
|
|
95
|
+
"""Returns the underlying FrozenCircuit without any tags."""
|
|
96
|
+
return self._from_moments(self._moments) if self.tags else self
|
|
97
|
+
|
|
98
|
+
def with_tags(self, *new_tags: Hashable) -> 'cirq.FrozenCircuit':
|
|
99
|
+
"""Creates a new tagged `FrozenCircuit` with `self.tags` and `new_tags` combined."""
|
|
100
|
+
if not new_tags:
|
|
101
|
+
return self
|
|
102
|
+
new_circuit = FrozenCircuit(tags=self.tags + new_tags)
|
|
103
|
+
new_circuit._moments = self._moments
|
|
104
|
+
return new_circuit
|
|
105
|
+
|
|
64
106
|
@_compat.cached_method
|
|
65
107
|
def __hash__(self) -> int:
|
|
66
108
|
# Explicitly cached for performance
|
|
67
|
-
return hash((self.moments,))
|
|
109
|
+
return hash((self.moments, self.tags))
|
|
110
|
+
|
|
111
|
+
def __eq__(self, other):
|
|
112
|
+
super_eq = super().__eq__(other)
|
|
113
|
+
if super_eq is not True:
|
|
114
|
+
return super_eq
|
|
115
|
+
other_tags = other.tags if isinstance(other, FrozenCircuit) else ()
|
|
116
|
+
return self.tags == other_tags
|
|
68
117
|
|
|
69
118
|
def __getstate__(self):
|
|
70
119
|
# Don't save hash when pickling; see #3777.
|
|
@@ -130,11 +179,23 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
|
|
|
130
179
|
|
|
131
180
|
@_compat.cached_method
|
|
132
181
|
def _is_parameterized_(self) -> bool:
|
|
133
|
-
return super()._is_parameterized_()
|
|
182
|
+
return super()._is_parameterized_() or any(
|
|
183
|
+
protocols.is_parameterized(tag) for tag in self.tags
|
|
184
|
+
)
|
|
134
185
|
|
|
135
186
|
@_compat.cached_method
|
|
136
187
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
137
|
-
|
|
188
|
+
tag_params = {name for tag in self.tags for name in protocols.parameter_names(tag)}
|
|
189
|
+
return super()._parameter_names_() | tag_params
|
|
190
|
+
|
|
191
|
+
def _resolve_parameters_(
|
|
192
|
+
self, resolver: 'cirq.ParamResolver', recursive: bool
|
|
193
|
+
) -> 'cirq.FrozenCircuit':
|
|
194
|
+
resolved_circuit = super()._resolve_parameters_(resolver, recursive)
|
|
195
|
+
resolved_tags = [
|
|
196
|
+
protocols.resolve_parameters(tag, resolver, recursive) for tag in self.tags
|
|
197
|
+
]
|
|
198
|
+
return resolved_circuit.with_tags(*resolved_tags)
|
|
138
199
|
|
|
139
200
|
def _measurement_key_names_(self) -> FrozenSet[str]:
|
|
140
201
|
return self.all_measurement_key_names()
|
|
@@ -161,6 +222,20 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
|
|
|
161
222
|
except:
|
|
162
223
|
return NotImplemented
|
|
163
224
|
|
|
225
|
+
def _repr_args(self) -> str:
|
|
226
|
+
moments_repr = super()._repr_args()
|
|
227
|
+
tag_repr = ','.join(_compat.proper_repr(t) for t in self._tags)
|
|
228
|
+
return f'{moments_repr}, tags=[{tag_repr}]' if self.tags else moments_repr
|
|
229
|
+
|
|
230
|
+
def _json_dict_(self):
|
|
231
|
+
attribute_names = ['moments', 'tags'] if self.tags else ['moments']
|
|
232
|
+
ret = protocols.obj_to_dict_helper(self, attribute_names)
|
|
233
|
+
return ret
|
|
234
|
+
|
|
235
|
+
@classmethod
|
|
236
|
+
def _from_json_dict_(cls, moments, *, tags=(), **kwargs):
|
|
237
|
+
return cls(moments, strategy=InsertStrategy.EARLIEST, tags=tags)
|
|
238
|
+
|
|
164
239
|
def concat_ragged(
|
|
165
240
|
*circuits: 'cirq.AbstractCircuit', align: Union['cirq.Alignment', str] = Alignment.LEFT
|
|
166
241
|
) -> 'cirq.FrozenCircuit':
|
|
@@ -17,25 +17,39 @@ Behavior shared with Circuit is tested with parameters in circuit_test.py.
|
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
19
|
import pytest
|
|
20
|
+
import sympy
|
|
20
21
|
|
|
21
22
|
import cirq
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
def test_from_moments():
|
|
25
26
|
a, b, c, d = cirq.LineQubit.range(4)
|
|
26
|
-
|
|
27
|
+
moment = cirq.Moment(cirq.Z(a), cirq.Z(b))
|
|
28
|
+
subcircuit = cirq.FrozenCircuit.from_moments(cirq.X(c), cirq.Y(d))
|
|
29
|
+
circuit = cirq.FrozenCircuit.from_moments(
|
|
30
|
+
moment,
|
|
31
|
+
subcircuit,
|
|
27
32
|
[cirq.X(a), cirq.Y(b)],
|
|
28
33
|
[cirq.X(c)],
|
|
29
34
|
[],
|
|
30
35
|
cirq.Z(d),
|
|
31
36
|
[cirq.measure(a, b, key='ab'), cirq.measure(c, d, key='cd')],
|
|
32
|
-
)
|
|
37
|
+
)
|
|
38
|
+
assert circuit == cirq.FrozenCircuit(
|
|
39
|
+
cirq.Moment(cirq.Z(a), cirq.Z(b)),
|
|
40
|
+
cirq.Moment(
|
|
41
|
+
cirq.CircuitOperation(
|
|
42
|
+
cirq.FrozenCircuit(cirq.Moment(cirq.X(c)), cirq.Moment(cirq.Y(d)))
|
|
43
|
+
)
|
|
44
|
+
),
|
|
33
45
|
cirq.Moment(cirq.X(a), cirq.Y(b)),
|
|
34
46
|
cirq.Moment(cirq.X(c)),
|
|
35
47
|
cirq.Moment(),
|
|
36
48
|
cirq.Moment(cirq.Z(d)),
|
|
37
49
|
cirq.Moment(cirq.measure(a, b, key='ab'), cirq.measure(c, d, key='cd')),
|
|
38
50
|
)
|
|
51
|
+
assert circuit[0] is moment
|
|
52
|
+
assert circuit[1].operations[0].circuit is subcircuit
|
|
39
53
|
|
|
40
54
|
|
|
41
55
|
def test_freeze_and_unfreeze():
|
|
@@ -74,3 +88,34 @@ def test_immutable():
|
|
|
74
88
|
match="(can't set attribute)|(property 'moments' of 'FrozenCircuit' object has no setter)",
|
|
75
89
|
):
|
|
76
90
|
c.moments = (cirq.Moment(cirq.H(q)), cirq.Moment(cirq.X(q)))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_tagged_circuits():
|
|
94
|
+
q = cirq.LineQubit(0)
|
|
95
|
+
ops = [cirq.X(q), cirq.H(q)]
|
|
96
|
+
tags = [sympy.Symbol("a"), "b"]
|
|
97
|
+
circuit = cirq.Circuit(ops)
|
|
98
|
+
frozen_circuit = cirq.FrozenCircuit(ops)
|
|
99
|
+
tagged_circuit = cirq.FrozenCircuit(ops, tags=tags)
|
|
100
|
+
# Test equality
|
|
101
|
+
assert tagged_circuit.tags == tuple(tags)
|
|
102
|
+
assert circuit == frozen_circuit != tagged_circuit
|
|
103
|
+
assert cirq.approx_eq(circuit, frozen_circuit)
|
|
104
|
+
assert cirq.approx_eq(frozen_circuit, tagged_circuit)
|
|
105
|
+
# Test hash
|
|
106
|
+
assert hash(frozen_circuit) != hash(tagged_circuit)
|
|
107
|
+
# Test _repr_ and _json_ round trips.
|
|
108
|
+
cirq.testing.assert_equivalent_repr(tagged_circuit)
|
|
109
|
+
cirq.testing.assert_json_roundtrip_works(tagged_circuit)
|
|
110
|
+
# Test utility methods and constructors
|
|
111
|
+
assert frozen_circuit.with_tags() is frozen_circuit
|
|
112
|
+
assert frozen_circuit.with_tags(*tags) == tagged_circuit
|
|
113
|
+
assert tagged_circuit.with_tags("c") == cirq.FrozenCircuit(ops, tags=[*tags, "c"])
|
|
114
|
+
assert tagged_circuit.untagged == frozen_circuit
|
|
115
|
+
assert frozen_circuit.untagged is frozen_circuit
|
|
116
|
+
# Test parameterized protocols
|
|
117
|
+
assert cirq.is_parameterized(frozen_circuit) is False
|
|
118
|
+
assert cirq.is_parameterized(tagged_circuit) is True
|
|
119
|
+
assert cirq.parameter_names(tagged_circuit) == {"a"}
|
|
120
|
+
# Tags are not propagated to diagrams yet.
|
|
121
|
+
assert str(frozen_circuit) == str(tagged_circuit)
|
|
@@ -248,18 +248,18 @@ def test_unsupported_operation():
|
|
|
248
248
|
|
|
249
249
|
|
|
250
250
|
def _all_operations(q0, q1, q2, q3, q4, include_measurements=True):
|
|
251
|
-
class
|
|
251
|
+
class ExampleOperation(cirq.Operation):
|
|
252
252
|
qubits = (q0,)
|
|
253
253
|
with_qubits = NotImplemented
|
|
254
254
|
|
|
255
255
|
def _qasm_(self, args: cirq.QasmArgs) -> str:
|
|
256
|
-
return '//
|
|
256
|
+
return '// Example operation\n'
|
|
257
257
|
|
|
258
258
|
def _decompose_(self):
|
|
259
259
|
# Only used by test_output_unitary_same_as_qiskit
|
|
260
|
-
return () #
|
|
260
|
+
return () # pragma: no cover
|
|
261
261
|
|
|
262
|
-
class
|
|
262
|
+
class ExampleCompositeOperation(cirq.Operation):
|
|
263
263
|
qubits = (q0,)
|
|
264
264
|
with_qubits = NotImplemented
|
|
265
265
|
|
|
@@ -267,7 +267,7 @@ def _all_operations(q0, q1, q2, q3, q4, include_measurements=True):
|
|
|
267
267
|
return cirq.X(self.qubits[0])
|
|
268
268
|
|
|
269
269
|
def __repr__(self):
|
|
270
|
-
return '
|
|
270
|
+
return 'ExampleCompositeOperation()'
|
|
271
271
|
|
|
272
272
|
return (
|
|
273
273
|
cirq.I(q0),
|
|
@@ -328,8 +328,8 @@ def _all_operations(q0, q1, q2, q3, q4, include_measurements=True):
|
|
|
328
328
|
)
|
|
329
329
|
if include_measurements
|
|
330
330
|
else (),
|
|
331
|
-
|
|
332
|
-
|
|
331
|
+
ExampleOperation(),
|
|
332
|
+
ExampleCompositeOperation(),
|
|
333
333
|
)
|
|
334
334
|
|
|
335
335
|
|
|
@@ -539,9 +539,9 @@ measure q[2] -> m_multi[1];
|
|
|
539
539
|
x q[2]; // Undo the inversion
|
|
540
540
|
measure q[3] -> m_multi[2];
|
|
541
541
|
|
|
542
|
-
//
|
|
542
|
+
// Example operation
|
|
543
543
|
|
|
544
|
-
// Operation:
|
|
544
|
+
// Operation: ExampleCompositeOperation()
|
|
545
545
|
x q[0];
|
|
546
546
|
"""
|
|
547
547
|
)
|
cirq/conftest.py
CHANGED
|
@@ -27,8 +27,7 @@ def pytest_configure(config):
|
|
|
27
27
|
|
|
28
28
|
def pytest_pyfunc_call(pyfuncitem):
|
|
29
29
|
if inspect.iscoroutinefunction(pyfuncitem._obj):
|
|
30
|
-
#
|
|
31
|
-
raise ValueError(
|
|
30
|
+
raise ValueError( # pragma: no cover
|
|
32
31
|
f'{pyfuncitem._obj.__name__} is a bare async function. '
|
|
33
32
|
f'It should be decorated with "@duet.sync".'
|
|
34
33
|
)
|
|
@@ -68,7 +68,7 @@ class _UnconstrainedAcquaintanceDevice(AcquaintanceDevice):
|
|
|
68
68
|
"""An acquaintance device with no constraints other than of the gate types."""
|
|
69
69
|
|
|
70
70
|
def __repr__(self) -> str:
|
|
71
|
-
return 'UnconstrainedAcquaintanceDevice' #
|
|
71
|
+
return 'UnconstrainedAcquaintanceDevice' # pragma: no cover
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
UnconstrainedAcquaintanceDevice = _UnconstrainedAcquaintanceDevice()
|
|
@@ -29,7 +29,7 @@ def test_disable_op_validation():
|
|
|
29
29
|
with pytest.raises(ValueError, match='mysterious and terrible'):
|
|
30
30
|
with disable_op_validation():
|
|
31
31
|
# This does not run - the with condition errors out first.
|
|
32
|
-
_ = cirq.H(q0, q1) #
|
|
32
|
+
_ = cirq.H(q0, q1) # pragma: no cover
|
|
33
33
|
|
|
34
34
|
# Passes, skipping validation.
|
|
35
35
|
with disable_op_validation(accept_debug_responsibility=True):
|
|
@@ -41,8 +41,7 @@ class DepolarizingNoiseModel(devices.NoiseModel):
|
|
|
41
41
|
self._prepend = prepend
|
|
42
42
|
|
|
43
43
|
def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']):
|
|
44
|
-
if validate_all_measurements(moment) or self.is_virtual_moment(moment):
|
|
45
|
-
# coverage: ignore
|
|
44
|
+
if validate_all_measurements(moment) or self.is_virtual_moment(moment): # pragma: no cover
|
|
46
45
|
return moment
|
|
47
46
|
|
|
48
47
|
output = [
|
|
@@ -161,7 +161,7 @@ def clifford_optimized_circuit(circuit: circuits.Circuit, atol: float = 1e-8) ->
|
|
|
161
161
|
else:
|
|
162
162
|
# Two CZ gates that share one qubit
|
|
163
163
|
# Pass through and keep looking
|
|
164
|
-
continue #
|
|
164
|
+
continue # pragma: no cover
|
|
165
165
|
# The above line is covered by test_remove_staggered_czs but the
|
|
166
166
|
# coverage checker disagrees.
|
|
167
167
|
return 0
|
|
@@ -182,11 +182,11 @@ def test_already_converted():
|
|
|
182
182
|
|
|
183
183
|
|
|
184
184
|
def test_ignore_unsupported_gate():
|
|
185
|
-
class
|
|
185
|
+
class UnsupportedGate(cirq.testing.TwoQubitGate):
|
|
186
186
|
pass
|
|
187
187
|
|
|
188
188
|
q0, q1 = cirq.LineQubit.range(2)
|
|
189
|
-
c_orig = cirq.Circuit(
|
|
189
|
+
c_orig = cirq.Circuit(UnsupportedGate()(q0, q1), cirq.X(q0) ** sympy.Symbol("theta"))
|
|
190
190
|
c_new = cirq.optimize_for_target_gateset(
|
|
191
191
|
c_orig, gateset=CliffordTargetGateset(), ignore_failures=True
|
|
192
192
|
)
|
|
@@ -194,11 +194,11 @@ def test_ignore_unsupported_gate():
|
|
|
194
194
|
|
|
195
195
|
|
|
196
196
|
def test_fail_unsupported_gate():
|
|
197
|
-
class
|
|
197
|
+
class UnsupportedGate(cirq.testing.TwoQubitGate):
|
|
198
198
|
pass
|
|
199
199
|
|
|
200
200
|
q0, q1 = cirq.LineQubit.range(2)
|
|
201
|
-
c_orig = cirq.Circuit(
|
|
201
|
+
c_orig = cirq.Circuit(UnsupportedGate()(q0, q1))
|
|
202
202
|
with pytest.raises(ValueError):
|
|
203
203
|
_ = cirq.optimize_for_target_gateset(
|
|
204
204
|
c_orig, gateset=CliffordTargetGateset(), ignore_failures=False
|
|
@@ -106,8 +106,7 @@ def circuit_to_density_matrix_tensors(
|
|
|
106
106
|
ValueError: If an op is encountered that cannot be converted.
|
|
107
107
|
"""
|
|
108
108
|
if qubits is None:
|
|
109
|
-
#
|
|
110
|
-
qubits = sorted(circuit.all_qubits())
|
|
109
|
+
qubits = sorted(circuit.all_qubits()) # pragma: no cover
|
|
111
110
|
qubits = tuple(qubits)
|
|
112
111
|
|
|
113
112
|
qubit_frontier: Dict[cirq.Qid, int] = {q: 0 for q in qubits}
|
|
@@ -190,7 +189,7 @@ def circuit_to_density_matrix_tensors(
|
|
|
190
189
|
)
|
|
191
190
|
kraus_frontier += 1
|
|
192
191
|
else:
|
|
193
|
-
raise ValueError(repr(op)) #
|
|
192
|
+
raise ValueError(repr(op)) # pragma: no cover
|
|
194
193
|
|
|
195
194
|
_positions(mi + 1, op.qubits)
|
|
196
195
|
return tensors, qubit_frontier, positions
|
|
@@ -54,12 +54,12 @@ def get_grid_moments(
|
|
|
54
54
|
for col in range(col_start + col_start_offset, col_end + col_end_offset, col_step):
|
|
55
55
|
node1 = (row, col)
|
|
56
56
|
if node1 not in problem_graph.nodes:
|
|
57
|
-
continue #
|
|
57
|
+
continue # pragma: no cover
|
|
58
58
|
node2 = get_neighbor(row, col)
|
|
59
59
|
if node2 not in problem_graph.nodes:
|
|
60
|
-
continue #
|
|
60
|
+
continue # pragma: no cover
|
|
61
61
|
if (node1, node2) not in problem_graph.edges:
|
|
62
|
-
continue #
|
|
62
|
+
continue # pragma: no cover
|
|
63
63
|
|
|
64
64
|
weight = problem_graph.edges[node1, node2].get('weight', 1)
|
|
65
65
|
yield two_qubit_gate(exponent=weight, global_shift=-0.5).on(
|
|
@@ -9,7 +9,6 @@ import quimb.tensor as qtn
|
|
|
9
9
|
import cirq
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
# coverage: ignore
|
|
13
12
|
def _get_quimb_version():
|
|
14
13
|
"""Returns the quimb version and parsed (major,minor) numbers if possible.
|
|
15
14
|
Returns:
|
|
@@ -18,7 +17,7 @@ def _get_quimb_version():
|
|
|
18
17
|
version = quimb.__version__
|
|
19
18
|
try:
|
|
20
19
|
return tuple(int(x) for x in version.split('.')), version
|
|
21
|
-
except:
|
|
20
|
+
except: # pragma: no cover
|
|
22
21
|
return (0, 0), version
|
|
23
22
|
|
|
24
23
|
|
|
@@ -59,7 +58,7 @@ def circuit_to_tensors(
|
|
|
59
58
|
corresponding to the |0> state.
|
|
60
59
|
"""
|
|
61
60
|
if qubits is None:
|
|
62
|
-
qubits = sorted(circuit.all_qubits()) #
|
|
61
|
+
qubits = sorted(circuit.all_qubits()) # pragma: no cover
|
|
63
62
|
|
|
64
63
|
qubit_frontier = {q: 0 for q in qubits}
|
|
65
64
|
positions = None
|
|
@@ -163,8 +162,7 @@ def tensor_expectation_value(
|
|
|
163
162
|
]
|
|
164
163
|
tn = qtn.TensorNetwork(tensors + end_bras)
|
|
165
164
|
if QUIMB_VERSION[0] < (1, 3):
|
|
166
|
-
#
|
|
167
|
-
warnings.warn(
|
|
165
|
+
warnings.warn( # pragma: no cover
|
|
168
166
|
f'quimb version {QUIMB_VERSION[1]} detected. Please use '
|
|
169
167
|
f'quimb>=1.3 for optimal performance in '
|
|
170
168
|
'`tensor_expectation_value`. '
|
cirq/contrib/routing/utils.py
CHANGED
|
@@ -96,8 +96,7 @@ def get_circuit_connectivity(circuit: 'cirq.Circuit') -> nx.Graph:
|
|
|
96
96
|
for op in circuit.all_operations():
|
|
97
97
|
n_qubits = len(op.qubits)
|
|
98
98
|
if n_qubits > 2:
|
|
99
|
-
#
|
|
100
|
-
raise ValueError(
|
|
99
|
+
raise ValueError( # pragma: no cover
|
|
101
100
|
f"Cannot build a graph out of a circuit that "
|
|
102
101
|
f"contains {n_qubits}-qubit operations"
|
|
103
102
|
)
|
cirq/contrib/svg/svg.py
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
from typing import TYPE_CHECKING, List, Tuple, cast, Dict
|
|
3
3
|
|
|
4
4
|
import matplotlib.textpath
|
|
5
|
+
import matplotlib.font_manager
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
if TYPE_CHECKING:
|
|
7
9
|
import cirq
|
|
8
10
|
|
|
9
11
|
QBLUE = '#1967d2'
|
|
10
|
-
FONT = "Arial"
|
|
12
|
+
FONT = matplotlib.font_manager.FontProperties(family="Arial")
|
|
11
13
|
EMPTY_MOMENT_COLWIDTH = float(21) # assumed default column width
|
|
12
14
|
|
|
13
15
|
|
|
@@ -140,12 +142,11 @@ def _fit_vertical(
|
|
|
140
142
|
return row_starts, row_heights, yi_map
|
|
141
143
|
|
|
142
144
|
|
|
143
|
-
def _debug_spacing(col_starts, row_starts):
|
|
145
|
+
def _debug_spacing(col_starts, row_starts): # pragma: no cover
|
|
144
146
|
"""Return a string suitable for inserting inside an <svg> tag that
|
|
145
147
|
draws green lines where columns and rows start. This is very useful
|
|
146
148
|
if you're developing this code and are debugging spacing issues.
|
|
147
149
|
"""
|
|
148
|
-
# coverage: ignore
|
|
149
150
|
t = ''
|
|
150
151
|
for i, cs in enumerate(col_starts):
|
|
151
152
|
t += (
|
|
@@ -198,7 +199,6 @@ def tdd_to_svg(
|
|
|
198
199
|
# qubits start at far left and their wires shall be blue
|
|
199
200
|
stroke = QBLUE
|
|
200
201
|
else:
|
|
201
|
-
# coverage: ignore
|
|
202
202
|
stroke = 'black'
|
|
203
203
|
t += f'<line x1="{x1}" x2="{x2}" y1="{y}" y2="{y}" stroke="{stroke}" stroke-width="1" />'
|
|
204
204
|
|
|
@@ -261,11 +261,9 @@ class SVGCircuit:
|
|
|
261
261
|
"""
|
|
262
262
|
|
|
263
263
|
def __init__(self, circuit: 'cirq.Circuit'):
|
|
264
|
-
# coverage: ignore
|
|
265
264
|
self.circuit = circuit
|
|
266
265
|
|
|
267
266
|
def _repr_svg_(self) -> str:
|
|
268
|
-
# coverage: ignore
|
|
269
267
|
return circuit_to_svg(self.circuit)
|
|
270
268
|
|
|
271
269
|
|