cirq-core 1.3.0.dev20231201141002__py3-none-any.whl → 1.4.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 +4 -0
- cirq/_compat.py +9 -11
- cirq/_compat_test.py +45 -56
- cirq/_version.py +31 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/circuit.py +13 -8
- cirq/circuits/circuit_operation.py +2 -1
- cirq/circuits/circuit_test.py +2 -2
- cirq/circuits/frozen_circuit.py +3 -2
- cirq/circuits/moment.py +12 -10
- cirq/circuits/qasm_output.py +5 -1
- cirq/circuits/qasm_output_test.py +25 -10
- cirq/contrib/qcircuit/qcircuit_diagram_info.py +9 -7
- cirq/contrib/quimb/mps_simulator_test.py +1 -1
- cirq/contrib/quimb/state_vector.py +9 -2
- cirq/contrib/svg/svg.py +2 -1
- cirq/contrib/svg/svg_test.py +1 -0
- cirq/devices/grid_qubit.py +85 -32
- cirq/devices/grid_qubit_test.py +22 -4
- cirq/devices/line_qubit.py +74 -26
- cirq/devices/line_qubit_test.py +19 -0
- cirq/devices/noise_utils.py +33 -31
- cirq/devices/noise_utils_test.py +1 -84
- cirq/devices/superconducting_qubits_noise_properties.py +7 -6
- cirq/experiments/__init__.py +8 -0
- cirq/experiments/qubit_characterizations.py +288 -44
- cirq/experiments/qubit_characterizations_test.py +61 -7
- cirq/experiments/random_quantum_circuit_generation.py +1 -1
- cirq/experiments/single_qubit_readout_calibration.py +132 -6
- cirq/experiments/single_qubit_readout_calibration_test.py +3 -1
- cirq/experiments/t1_decay_experiment.py +14 -7
- cirq/experiments/t1_decay_experiment_test.py +14 -26
- cirq/experiments/two_qubit_xeb.py +483 -0
- cirq/experiments/two_qubit_xeb_test.py +304 -0
- cirq/json_resolver_cache.py +2 -0
- cirq/linalg/decompositions.py +11 -13
- cirq/linalg/decompositions_test.py +1 -3
- cirq/linalg/diagonalize.py +5 -4
- cirq/linalg/predicates.py +8 -6
- cirq/linalg/transformations.py +2 -1
- cirq/linalg/transformations_test.py +1 -1
- cirq/ops/__init__.py +2 -0
- cirq/ops/clifford_gate.py +59 -16
- cirq/ops/common_gates_test.py +1 -2
- cirq/ops/control_values.py +4 -3
- cirq/ops/controlled_gate_test.py +1 -3
- cirq/ops/gate_operation.py +10 -1
- cirq/ops/named_qubit.py +74 -28
- cirq/ops/named_qubit_test.py +19 -0
- cirq/ops/parity_gates.py +5 -0
- cirq/ops/parity_gates_test.py +2 -10
- cirq/ops/pauli_gates.py +5 -2
- cirq/ops/pauli_string.py +2 -2
- cirq/ops/permutation_gate.py +16 -18
- cirq/ops/phased_iswap_gate_test.py +1 -3
- cirq/ops/phased_x_gate.py +1 -1
- cirq/ops/phased_x_z_gate.py +17 -1
- cirq/ops/phased_x_z_gate_test.py +24 -0
- cirq/ops/qid_util.py +4 -8
- cirq/ops/qubit_manager.py +7 -4
- cirq/ops/qubit_manager_test.py +20 -0
- cirq/ops/raw_types.py +5 -2
- cirq/ops/raw_types_test.py +14 -15
- cirq/ops/uniform_superposition_gate.py +123 -0
- cirq/ops/uniform_superposition_gate_test.py +94 -0
- cirq/protocols/approximate_equality_protocol_test.py +2 -2
- cirq/protocols/circuit_diagram_info_protocol.py +6 -4
- cirq/protocols/commutes_protocol.py +2 -4
- cirq/protocols/decompose_protocol.py +7 -12
- cirq/protocols/decompose_protocol_test.py +7 -3
- cirq/protocols/has_stabilizer_effect_protocol.py +1 -5
- cirq/protocols/has_stabilizer_effect_protocol_test.py +13 -4
- cirq/protocols/json_serialization.py +51 -181
- cirq/protocols/json_serialization_test.py +13 -47
- cirq/protocols/json_test_data/CircuitOperation.json +131 -148
- cirq/protocols/json_test_data/CircuitOperation.json_inward +55 -0
- cirq/protocols/json_test_data/CircuitOperation.repr_inward +6 -0
- cirq/protocols/json_test_data/FrozenCircuit.json +196 -210
- cirq/protocols/json_test_data/FrozenCircuit.json_inward +35 -0
- cirq/protocols/json_test_data/FrozenCircuit.repr_inward +4 -0
- cirq/protocols/json_test_data/UniformSuperpositionGate.json +5 -0
- cirq/protocols/json_test_data/UniformSuperpositionGate.repr +1 -0
- cirq/protocols/json_test_data/cirq.MSGate.json +4 -0
- cirq/protocols/json_test_data/cirq.MSGate.repr +1 -0
- cirq/protocols/json_test_data/spec.py +2 -0
- cirq/protocols/pow_protocol_test.py +1 -3
- cirq/protocols/resolve_parameters.py +4 -2
- cirq/qis/__init__.py +10 -0
- cirq/qis/clifford_tableau.py +8 -2
- cirq/qis/noise_utils.py +123 -0
- cirq/qis/noise_utils_test.py +97 -0
- cirq/sim/classical_simulator.py +227 -87
- cirq/sim/classical_simulator_test.py +135 -0
- cirq/sim/clifford/clifford_simulator_test.py +4 -2
- cirq/sim/mux.py +5 -3
- cirq/sim/simulation_product_state.py +15 -10
- cirq/sim/simulation_state.py +1 -1
- cirq/sim/simulation_state_test.py +2 -2
- cirq/sim/simulator_base.py +3 -3
- cirq/sim/state_vector_simulation_state.py +4 -4
- cirq/sim/state_vector_simulator.py +17 -2
- cirq/study/__init__.py +1 -0
- cirq/study/result.py +14 -0
- cirq/study/result_test.py +6 -0
- cirq/study/sweeps.py +4 -2
- cirq/study/sweeps_test.py +8 -0
- cirq/testing/__init__.py +6 -1
- cirq/testing/_compat_test_data/__init__.py +3 -3
- cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
- cirq/testing/circuit_compare.py +1 -1
- cirq/testing/consistent_qasm.py +6 -0
- cirq/testing/gate_features.py +10 -0
- cirq/testing/lin_alg_utils.py +5 -3
- cirq/transformers/__init__.py +15 -0
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +3 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +24 -0
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +17 -0
- cirq/transformers/dynamical_decoupling.py +122 -0
- cirq/transformers/dynamical_decoupling_test.py +123 -0
- cirq/transformers/gauge_compiling/__init__.py +26 -0
- cirq/transformers/gauge_compiling/cz_gauge.py +46 -0
- cirq/transformers/gauge_compiling/cz_gauge_test.py +23 -0
- cirq/transformers/gauge_compiling/gauge_compiling.py +214 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +41 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +83 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +52 -0
- cirq/transformers/gauge_compiling/iswap_gauge.py +105 -0
- cirq/transformers/gauge_compiling/iswap_gauge_test.py +23 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge.py +33 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge_test.py +37 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +64 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge_test.py +27 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +94 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge_test.py +22 -0
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +1 -0
- cirq/transformers/merge_k_qubit_gates_test.py +23 -23
- cirq/transformers/merge_single_qubit_gates_test.py +14 -14
- cirq/transformers/optimize_for_target_gateset.py +39 -17
- cirq/transformers/optimize_for_target_gateset_test.py +189 -39
- cirq/transformers/qubit_management_transformers.py +1 -1
- cirq/transformers/routing/visualize_routed_circuit_test.py +17 -17
- cirq/transformers/stratify_test.py +13 -13
- cirq/transformers/target_gatesets/compilation_target_gateset.py +26 -2
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +16 -16
- cirq/transformers/target_gatesets/cz_gateset.py +4 -0
- cirq/transformers/transformer_api.py +1 -2
- cirq/transformers/transformer_primitives.py +15 -14
- cirq/transformers/transformer_primitives_test.py +99 -72
- cirq/value/classical_data.py +6 -6
- cirq/value/value_equality_attr.py +4 -0
- cirq/work/sampler.py +3 -4
- cirq/work/sampler_test.py +25 -0
- {cirq_core-1.3.0.dev20231201141002.dist-info → cirq_core-1.4.0.dist-info}/METADATA +10 -19
- {cirq_core-1.3.0.dev20231201141002.dist-info → cirq_core-1.4.0.dist-info}/RECORD +157 -130
- {cirq_core-1.3.0.dev20231201141002.dist-info → cirq_core-1.4.0.dist-info}/WHEEL +1 -1
- {cirq_core-1.3.0.dev20231201141002.dist-info → cirq_core-1.4.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.3.0.dev20231201141002.dist-info → cirq_core-1.4.0.dist-info}/top_level.txt +0 -0
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from itertools import product
|
|
14
16
|
import numpy as np
|
|
15
17
|
import pytest
|
|
16
18
|
import cirq
|
|
@@ -77,6 +79,43 @@ def test_CCNOT():
|
|
|
77
79
|
np.testing.assert_equal(results, expected_results)
|
|
78
80
|
|
|
79
81
|
|
|
82
|
+
@pytest.mark.parametrize(['initial_state'], [(list(x),) for x in product([0, 1], repeat=4)])
|
|
83
|
+
def test_CCCX(initial_state):
|
|
84
|
+
CCCX = cirq.CCNOT.controlled()
|
|
85
|
+
qubits = cirq.LineQubit.range(4)
|
|
86
|
+
|
|
87
|
+
circuit = cirq.Circuit()
|
|
88
|
+
circuit.append(CCCX(*qubits))
|
|
89
|
+
circuit.append(cirq.measure(qubits, key='key'))
|
|
90
|
+
|
|
91
|
+
final_state = initial_state.copy()
|
|
92
|
+
final_state[-1] ^= all(final_state[:-1])
|
|
93
|
+
|
|
94
|
+
sim = cirq.ClassicalStateSimulator()
|
|
95
|
+
results = sim.simulate(circuit, initial_state=initial_state).measurements['key']
|
|
96
|
+
np.testing.assert_equal(results, final_state)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@pytest.mark.parametrize(['initial_state'], [(list(x),) for x in product([0, 1], repeat=3)])
|
|
100
|
+
def test_CSWAP(initial_state):
|
|
101
|
+
CSWAP = cirq.SWAP.controlled()
|
|
102
|
+
qubits = cirq.LineQubit.range(3)
|
|
103
|
+
circuit = cirq.Circuit()
|
|
104
|
+
|
|
105
|
+
circuit = cirq.Circuit()
|
|
106
|
+
circuit.append(CSWAP(*qubits))
|
|
107
|
+
circuit.append(cirq.measure(qubits, key='key'))
|
|
108
|
+
|
|
109
|
+
a, b, c = initial_state
|
|
110
|
+
if a:
|
|
111
|
+
b, c = c, b
|
|
112
|
+
final_state = [a, b, c]
|
|
113
|
+
|
|
114
|
+
sim = cirq.ClassicalStateSimulator()
|
|
115
|
+
results = sim.simulate(circuit, initial_state=initial_state).measurements['key']
|
|
116
|
+
np.testing.assert_equal(results, final_state)
|
|
117
|
+
|
|
118
|
+
|
|
80
119
|
def test_measurement_gate():
|
|
81
120
|
q0, q1 = cirq.LineQubit.range(2)
|
|
82
121
|
circuit = cirq.Circuit()
|
|
@@ -205,3 +244,99 @@ def test_compatible_measurement():
|
|
|
205
244
|
sim = cirq.ClassicalStateSimulator()
|
|
206
245
|
res = sim.run(c, repetitions=3).records
|
|
207
246
|
np.testing.assert_equal(res['key'], np.array([[[0, 0], [1, 1]]] * 3, dtype=np.uint8))
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def test_simulate_sweeps_param_resolver():
|
|
250
|
+
q0, q1 = cirq.LineQubit.range(2)
|
|
251
|
+
simulator = cirq.ClassicalStateSimulator()
|
|
252
|
+
for b0 in [0, 1]:
|
|
253
|
+
for b1 in [0, 1]:
|
|
254
|
+
circuit = cirq.Circuit(
|
|
255
|
+
(cirq.X ** sympy.Symbol('b0'))(q0), (cirq.X ** sympy.Symbol('b1'))(q1)
|
|
256
|
+
)
|
|
257
|
+
params = [
|
|
258
|
+
cirq.ParamResolver({'b0': b0, 'b1': b1}),
|
|
259
|
+
cirq.ParamResolver({'b0': b1, 'b1': b0}),
|
|
260
|
+
]
|
|
261
|
+
results = simulator.simulate_sweep(circuit, params=params)
|
|
262
|
+
|
|
263
|
+
assert results[0].params == params[0]
|
|
264
|
+
assert results[1].params == params[1]
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def test_create_partial_simulation_state_from_int_with_no_qubits():
|
|
268
|
+
sim = cirq.ClassicalStateSimulator()
|
|
269
|
+
initial_state = 5
|
|
270
|
+
qs = None
|
|
271
|
+
classical_data = cirq.value.ClassicalDataDictionaryStore()
|
|
272
|
+
with pytest.raises(ValueError):
|
|
273
|
+
sim._create_partial_simulation_state(
|
|
274
|
+
initial_state=initial_state, qubits=qs, classical_data=classical_data
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def test_create_partial_simulation_state_from_invalid_state():
|
|
279
|
+
sim = cirq.ClassicalStateSimulator()
|
|
280
|
+
initial_state = None
|
|
281
|
+
qs = cirq.LineQubit.range(2)
|
|
282
|
+
classical_data = cirq.value.ClassicalDataDictionaryStore()
|
|
283
|
+
with pytest.raises(ValueError):
|
|
284
|
+
sim._create_partial_simulation_state(
|
|
285
|
+
initial_state=initial_state, qubits=qs, classical_data=classical_data
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def test_create_partial_simulation_state_from_int():
|
|
290
|
+
sim = cirq.ClassicalStateSimulator()
|
|
291
|
+
initial_state = 15
|
|
292
|
+
qs = cirq.LineQubit.range(4)
|
|
293
|
+
classical_data = cirq.value.ClassicalDataDictionaryStore()
|
|
294
|
+
expected_result = [1, 1, 1, 1]
|
|
295
|
+
result = sim._create_partial_simulation_state(
|
|
296
|
+
initial_state=initial_state, qubits=qs, classical_data=classical_data
|
|
297
|
+
)._state.basis
|
|
298
|
+
assert result == expected_result
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def test_create_valid_partial_simulation_state_from_list():
|
|
302
|
+
sim = cirq.ClassicalStateSimulator()
|
|
303
|
+
initial_state = [1, 1, 1, 1]
|
|
304
|
+
qs = cirq.LineQubit.range(4)
|
|
305
|
+
classical_data = cirq.value.ClassicalDataDictionaryStore()
|
|
306
|
+
expected_result = [1, 1, 1, 1]
|
|
307
|
+
result = sim._create_partial_simulation_state(
|
|
308
|
+
initial_state=initial_state, qubits=qs, classical_data=classical_data
|
|
309
|
+
)._state.basis
|
|
310
|
+
assert result == expected_result
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def test_create_valid_partial_simulation_state_from_np():
|
|
314
|
+
sim = cirq.ClassicalStateSimulator()
|
|
315
|
+
initial_state = np.array([1, 1])
|
|
316
|
+
qs = cirq.LineQubit.range(2)
|
|
317
|
+
classical_data = cirq.value.ClassicalDataDictionaryStore()
|
|
318
|
+
sim_state = sim._create_partial_simulation_state(
|
|
319
|
+
initial_state=initial_state, qubits=qs, classical_data=classical_data
|
|
320
|
+
)
|
|
321
|
+
sim_state._act_on_fallback_(action=cirq.CX, qubits=qs)
|
|
322
|
+
result = sim_state._state.basis
|
|
323
|
+
expected_result = np.array([1, 0])
|
|
324
|
+
np.testing.assert_equal(result, expected_result)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def test_create_invalid_partial_simulation_state_from_np():
|
|
328
|
+
initial_state = np.array([[1, 1], [1, 1]])
|
|
329
|
+
qs = cirq.LineQubit.range(2)
|
|
330
|
+
classical_data = cirq.value.ClassicalDataDictionaryStore()
|
|
331
|
+
sim = cirq.ClassicalStateSimulator()
|
|
332
|
+
sim_state = sim._create_partial_simulation_state(
|
|
333
|
+
initial_state=initial_state, qubits=qs, classical_data=classical_data
|
|
334
|
+
)
|
|
335
|
+
with pytest.raises(ValueError):
|
|
336
|
+
sim_state._act_on_fallback_(action=cirq.CX, qubits=qs)
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def test_noise_model():
|
|
340
|
+
noise_model = cirq.NoiseModel.from_noise_model_like(cirq.depolarize(p=0.01))
|
|
341
|
+
with pytest.raises(ValueError):
|
|
342
|
+
cirq.ClassicalStateSimulator(noise=noise_model)
|
|
@@ -324,9 +324,11 @@ def test_clifford_circuit_SHSYSHS():
|
|
|
324
324
|
clifford_simulator = cirq.CliffordSimulator()
|
|
325
325
|
state_vector_simulator = cirq.Simulator()
|
|
326
326
|
|
|
327
|
+
# workaround until #6402 is resolved.
|
|
328
|
+
final_state_vector = state_vector_simulator.simulate(circuit).final_state_vector
|
|
329
|
+
final_state_vector /= np.linalg.norm(final_state_vector)
|
|
327
330
|
np.testing.assert_almost_equal(
|
|
328
|
-
clifford_simulator.simulate(circuit).final_state.state_vector(),
|
|
329
|
-
state_vector_simulator.simulate(circuit).final_state_vector,
|
|
331
|
+
clifford_simulator.simulate(circuit).final_state.state_vector(), final_state_vector
|
|
330
332
|
)
|
|
331
333
|
|
|
332
334
|
|
cirq/sim/mux.py
CHANGED
|
@@ -292,9 +292,11 @@ def final_density_matrix(
|
|
|
292
292
|
density_result = density_matrix_simulator.DensityMatrixSimulator(
|
|
293
293
|
dtype=dtype, noise=noise, seed=seed
|
|
294
294
|
).simulate(
|
|
295
|
-
program=
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
program=(
|
|
296
|
+
measurement_transformers.dephase_measurements(circuit_like)
|
|
297
|
+
if ignore_measurement_results
|
|
298
|
+
else circuit_like
|
|
299
|
+
),
|
|
298
300
|
initial_state=initial_state,
|
|
299
301
|
qubit_order=qubit_order,
|
|
300
302
|
param_resolver=param_resolver,
|
|
@@ -63,12 +63,19 @@ class SimulationProductState(
|
|
|
63
63
|
return self._split_untangled_states
|
|
64
64
|
|
|
65
65
|
def create_merged_state(self) -> TSimulationState:
|
|
66
|
+
merged_state = self.sim_states[None]
|
|
66
67
|
if not self.split_untangled_states:
|
|
67
|
-
return
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
return merged_state
|
|
69
|
+
extra_states = set([self.sim_states[k] for k in self.sim_states.keys() if k is not None])
|
|
70
|
+
if not extra_states:
|
|
71
|
+
return merged_state
|
|
72
|
+
|
|
73
|
+
# This comes from a member variable so we need to copy it if we're going to modify inplace
|
|
74
|
+
# before returning. We're not running a step currently, so no need to copy buffers.
|
|
75
|
+
merged_state = merged_state.copy(deep_copy_buffers=False)
|
|
76
|
+
for state in extra_states:
|
|
77
|
+
merged_state.kronecker_product(state, inplace=True)
|
|
78
|
+
return merged_state.transpose_to_qubit_order(self.qubits, inplace=True)
|
|
72
79
|
|
|
73
80
|
def _act_on_fallback_(
|
|
74
81
|
self, action: Any, qubits: Sequence['cirq.Qid'], allow_decompose: bool = True
|
|
@@ -76,9 +83,7 @@ class SimulationProductState(
|
|
|
76
83
|
gate_opt = (
|
|
77
84
|
action
|
|
78
85
|
if isinstance(action, ops.Gate)
|
|
79
|
-
else action.gate
|
|
80
|
-
if isinstance(action, ops.Operation)
|
|
81
|
-
else None
|
|
86
|
+
else action.gate if isinstance(action, ops.Operation) else None
|
|
82
87
|
)
|
|
83
88
|
|
|
84
89
|
if isinstance(gate_opt, ops.IdentityGate):
|
|
@@ -106,7 +111,7 @@ class SimulationProductState(
|
|
|
106
111
|
if op_args_opt is None:
|
|
107
112
|
op_args_opt = self.sim_states[q]
|
|
108
113
|
elif q not in op_args_opt.qubits:
|
|
109
|
-
op_args_opt
|
|
114
|
+
op_args_opt.kronecker_product(self.sim_states[q], inplace=True)
|
|
110
115
|
op_args = op_args_opt or self.sim_states[None]
|
|
111
116
|
|
|
112
117
|
# (Backfill the args map with the new value)
|
|
@@ -123,7 +128,7 @@ class SimulationProductState(
|
|
|
123
128
|
):
|
|
124
129
|
for q in qubits:
|
|
125
130
|
if op_args.allows_factoring and len(op_args.qubits) > 1:
|
|
126
|
-
q_args,
|
|
131
|
+
q_args, _ = op_args.factor((q,), validate=False, inplace=True)
|
|
127
132
|
self._sim_states[q] = q_args
|
|
128
133
|
|
|
129
134
|
# (Backfill the args map with the new value)
|
cirq/sim/simulation_state.py
CHANGED
|
@@ -111,7 +111,7 @@ class SimulationState(SimulationStateBase, Generic[TState], metaclass=abc.ABCMet
|
|
|
111
111
|
return [self.qubit_map[q] for q in qubits]
|
|
112
112
|
|
|
113
113
|
def _perform_measurement(self, qubits: Sequence['cirq.Qid']) -> List[int]:
|
|
114
|
-
"""Delegates the call to measure the
|
|
114
|
+
"""Delegates the call to measure the `QuantumStateRepresentation`."""
|
|
115
115
|
if self._state is not None:
|
|
116
116
|
return self._state.measure(self.get_axes(qubits), self.prng)
|
|
117
117
|
raise NotImplementedError()
|
|
@@ -43,8 +43,8 @@ class ExampleSimulationState(cirq.SimulationState):
|
|
|
43
43
|
return True
|
|
44
44
|
|
|
45
45
|
def add_qubits(self, qubits):
|
|
46
|
-
|
|
47
|
-
return self
|
|
46
|
+
super().add_qubits(qubits)
|
|
47
|
+
return self
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
class DelegatingAncillaZ(cirq.Gate):
|
cirq/sim/simulator_base.py
CHANGED
|
@@ -261,9 +261,9 @@ class SimulatorBase(
|
|
|
261
261
|
for i in range(repetitions):
|
|
262
262
|
for step_result in self._core_iterator(
|
|
263
263
|
general_suffix,
|
|
264
|
-
sim_state=
|
|
265
|
-
|
|
266
|
-
|
|
264
|
+
sim_state=(
|
|
265
|
+
sim_state.copy(deep_copy_buffers=False) if i < repetitions - 1 else sim_state
|
|
266
|
+
),
|
|
267
267
|
):
|
|
268
268
|
pass
|
|
269
269
|
for k, r in step_result._classical_data.records.items():
|
|
@@ -60,11 +60,11 @@ class _BufferedStateVector(qis.QuantumStateRepresentation):
|
|
|
60
60
|
This initializer creates the buffer if necessary.
|
|
61
61
|
|
|
62
62
|
Args:
|
|
63
|
-
initial_state: The
|
|
63
|
+
initial_state: The state vector, must be correctly formatted. The data is not
|
|
64
64
|
checked for validity here due to performance concerns.
|
|
65
|
-
qid_shape: The shape of the
|
|
66
|
-
dtype: The dtype of the
|
|
67
|
-
buffer: Optional, must be length 3 and same shape as the
|
|
65
|
+
qid_shape: The shape of the state vector, if the initial state is provided as an int.
|
|
66
|
+
dtype: The dtype of the state vector, if the initial state is provided as an int.
|
|
67
|
+
buffer: Optional, must be length 3 and same shape as the state vector. If not
|
|
68
68
|
provided, a buffer will be created automatically.
|
|
69
69
|
Raises:
|
|
70
70
|
ValueError: If initial state is provided as integer, but qid_shape is not provided.
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"""Abstract classes for simulations which keep track of state vector."""
|
|
15
15
|
|
|
16
16
|
import abc
|
|
17
|
+
from functools import cached_property
|
|
17
18
|
from typing import Any, Dict, Iterator, Sequence, Type, TYPE_CHECKING, Generic, TypeVar
|
|
19
|
+
import warnings
|
|
18
20
|
|
|
19
21
|
import numpy as np
|
|
20
22
|
|
|
@@ -121,9 +123,22 @@ class StateVectorTrialResult(
|
|
|
121
123
|
qubit_map=final_simulator_state.qubit_map,
|
|
122
124
|
)
|
|
123
125
|
|
|
124
|
-
@
|
|
126
|
+
@cached_property
|
|
125
127
|
def final_state_vector(self) -> np.ndarray:
|
|
126
|
-
|
|
128
|
+
ret = self._get_merged_sim_state().target_tensor.reshape(-1)
|
|
129
|
+
norm = np.linalg.norm(ret)
|
|
130
|
+
if abs(norm - 1) > np.sqrt(np.finfo(ret.dtype).eps):
|
|
131
|
+
warnings.warn(
|
|
132
|
+
f"final state vector's {norm=} is too far from 1,"
|
|
133
|
+
f" {abs(norm-1)} > {np.sqrt(np.finfo(ret.dtype).eps)}."
|
|
134
|
+
"skipping renormalization"
|
|
135
|
+
)
|
|
136
|
+
return ret
|
|
137
|
+
# normalize only if doing so improves the round-off on total probability
|
|
138
|
+
ret_norm = ret / norm
|
|
139
|
+
round_off_change = abs(np.vdot(ret_norm, ret_norm) - 1) - abs(np.vdot(ret, ret) - 1)
|
|
140
|
+
result = ret_norm if round_off_change < 0 else ret
|
|
141
|
+
return result
|
|
127
142
|
|
|
128
143
|
def state_vector(self, copy: bool = False) -> np.ndarray:
|
|
129
144
|
"""Return the state vector at the end of the computation.
|
cirq/study/__init__.py
CHANGED
cirq/study/result.py
CHANGED
|
@@ -74,6 +74,18 @@ def _keyed_repeated_bitstrings(vals: Mapping[str, np.ndarray]) -> str:
|
|
|
74
74
|
return '\n'.join(keyed_bitstrings)
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
def _keyed_repeated_records(vals: Mapping[str, np.ndarray]) -> str:
|
|
78
|
+
keyed_bitstrings = []
|
|
79
|
+
for key in sorted(vals.keys()):
|
|
80
|
+
reps = vals[key]
|
|
81
|
+
n = reps.shape[2]
|
|
82
|
+
num_records = reps.shape[1]
|
|
83
|
+
for j in range(num_records):
|
|
84
|
+
all_bits = ', '.join(_bitstring(reps[:, j, i]) for i in range(n))
|
|
85
|
+
keyed_bitstrings.append(f'{key}={all_bits}')
|
|
86
|
+
return '\n'.join(keyed_bitstrings)
|
|
87
|
+
|
|
88
|
+
|
|
77
89
|
def _key_to_str(key: TMeasurementKey) -> str:
|
|
78
90
|
if isinstance(key, str):
|
|
79
91
|
return key
|
|
@@ -388,6 +400,8 @@ class ResultDict(Result):
|
|
|
388
400
|
p.text(str(self))
|
|
389
401
|
|
|
390
402
|
def __str__(self) -> str:
|
|
403
|
+
if self._records:
|
|
404
|
+
return _keyed_repeated_records(self.records)
|
|
391
405
|
return _keyed_repeated_bitstrings(self.measurements)
|
|
392
406
|
|
|
393
407
|
def _json_dict_(self):
|
cirq/study/result_test.py
CHANGED
|
@@ -127,6 +127,12 @@ def test_str():
|
|
|
127
127
|
)
|
|
128
128
|
assert str(result) == 'ab=13579, 2 4 6 8 10\nc=01234'
|
|
129
129
|
|
|
130
|
+
result = cirq.ResultDict(records={'c': np.array([[[True], [True]]])})
|
|
131
|
+
assert str(result) == 'c=1\nc=1'
|
|
132
|
+
|
|
133
|
+
result = cirq.ResultDict(records={'c': np.array([[[True, False], [False, True]]])})
|
|
134
|
+
assert str(result) == 'c=1, 0\nc=0, 1'
|
|
135
|
+
|
|
130
136
|
|
|
131
137
|
def test_df():
|
|
132
138
|
result = cirq.ResultDict(
|
cirq/study/sweeps.py
CHANGED
|
@@ -205,6 +205,10 @@ class _Unit(Sweep):
|
|
|
205
205
|
UnitSweep = _Unit()
|
|
206
206
|
document(UnitSweep, """The singleton sweep with no parameters.""")
|
|
207
207
|
|
|
208
|
+
# Alternate name to designate as a constant.
|
|
209
|
+
UNIT_SWEEP = UnitSweep
|
|
210
|
+
document(UNIT_SWEEP, """The singleton sweep with no parameters.""")
|
|
211
|
+
|
|
208
212
|
|
|
209
213
|
class Product(Sweep):
|
|
210
214
|
"""Cartesian product of one or more sweeps.
|
|
@@ -232,8 +236,6 @@ class Product(Sweep):
|
|
|
232
236
|
return sum((factor.keys for factor in self.factors), [])
|
|
233
237
|
|
|
234
238
|
def __len__(self) -> int:
|
|
235
|
-
if not self.factors:
|
|
236
|
-
return 0
|
|
237
239
|
length = 1
|
|
238
240
|
for factor in self.factors:
|
|
239
241
|
length *= len(factor)
|
cirq/study/sweeps_test.py
CHANGED
|
@@ -142,6 +142,11 @@ def test_product():
|
|
|
142
142
|
assert _values(sweep, 'b') == [4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7]
|
|
143
143
|
|
|
144
144
|
|
|
145
|
+
def test_empty_product():
|
|
146
|
+
sweep = cirq.Product()
|
|
147
|
+
assert len(sweep) == len(list(sweep)) == 1
|
|
148
|
+
|
|
149
|
+
|
|
145
150
|
def test_slice_access_error():
|
|
146
151
|
sweep = cirq.Points('a', [1, 2, 3])
|
|
147
152
|
with pytest.raises(TypeError, match='<class \'str\'>'):
|
|
@@ -232,6 +237,9 @@ def test_equality():
|
|
|
232
237
|
|
|
233
238
|
et.add_equality_group(cirq.UnitSweep, cirq.UnitSweep)
|
|
234
239
|
|
|
240
|
+
# Test singleton
|
|
241
|
+
assert cirq.UNIT_SWEEP is cirq.UnitSweep
|
|
242
|
+
|
|
235
243
|
# Simple sweeps with the same key are equal to themselves, but different
|
|
236
244
|
# from each other even if they happen to contain the same points.
|
|
237
245
|
et.make_equality_group(lambda: cirq.Linspace('a', 0, 10, 11))
|
cirq/testing/__init__.py
CHANGED
|
@@ -69,7 +69,12 @@ from cirq.testing.equivalent_basis_map import assert_equivalent_computational_ba
|
|
|
69
69
|
|
|
70
70
|
from cirq.testing.equivalent_repr_eval import assert_equivalent_repr
|
|
71
71
|
|
|
72
|
-
from cirq.testing.gate_features import
|
|
72
|
+
from cirq.testing.gate_features import (
|
|
73
|
+
SingleQubitGate,
|
|
74
|
+
TwoQubitGate,
|
|
75
|
+
ThreeQubitGate,
|
|
76
|
+
DoesNotSupportSerializationGate,
|
|
77
|
+
)
|
|
73
78
|
|
|
74
79
|
from cirq.testing.json import assert_json_roundtrip_works
|
|
75
80
|
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
See cirq/_compat_test.py for the tests.
|
|
4
4
|
This module contains example deprecations for modules.
|
|
5
5
|
"""
|
|
6
|
-
import
|
|
7
|
-
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
8
|
from cirq import _compat
|
|
9
9
|
|
|
10
|
-
info("init:compat_test_data")
|
|
10
|
+
logging.info("init:compat_test_data")
|
|
11
11
|
|
|
12
12
|
# simulates a rename of a child module
|
|
13
13
|
# fake_a -> module_a
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# pylint: disable=wrong-or-nonexistent-copyright-notice
|
|
2
2
|
"""module_a for module deprecation tests"""
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import logging
|
|
5
5
|
|
|
6
6
|
from cirq.testing._compat_test_data.module_a import module_b
|
|
7
7
|
|
|
@@ -11,4 +11,4 @@ from cirq.testing._compat_test_data.module_a.types import SampleType
|
|
|
11
11
|
|
|
12
12
|
MODULE_A_ATTRIBUTE = "module_a"
|
|
13
13
|
|
|
14
|
-
info("init:module_a")
|
|
14
|
+
logging.info("init:module_a")
|
cirq/testing/circuit_compare.py
CHANGED
|
@@ -226,7 +226,7 @@ def assert_circuits_have_same_unitary_given_final_permutation(
|
|
|
226
226
|
expected: circuits.AbstractCircuit,
|
|
227
227
|
qubit_map: Dict[ops.Qid, ops.Qid],
|
|
228
228
|
) -> None:
|
|
229
|
-
"""Asserts two circuits have the same unitary up to a final
|
|
229
|
+
"""Asserts two circuits have the same unitary up to a final permutation of qubits.
|
|
230
230
|
|
|
231
231
|
Args:
|
|
232
232
|
actual: A circuit computed by some code under test.
|
cirq/testing/consistent_qasm.py
CHANGED
|
@@ -42,6 +42,7 @@ def assert_qasm_is_consistent_with_unitary(val: Any):
|
|
|
42
42
|
if isinstance(val, ops.Operation):
|
|
43
43
|
qubits: Sequence[ops.Qid] = val.qubits
|
|
44
44
|
op = val
|
|
45
|
+
gate = val.gate
|
|
45
46
|
elif isinstance(val, ops.Gate):
|
|
46
47
|
qid_shape = protocols.qid_shape(val)
|
|
47
48
|
remaining_shape = list(qid_shape)
|
|
@@ -52,9 +53,14 @@ def assert_qasm_is_consistent_with_unitary(val: Any):
|
|
|
52
53
|
remaining_shape.pop(i)
|
|
53
54
|
qubits = devices.LineQid.for_qid_shape(remaining_shape)
|
|
54
55
|
op = val.on(*qubits)
|
|
56
|
+
gate = val
|
|
55
57
|
else:
|
|
56
58
|
raise NotImplementedError(f"Don't know how to test {val!r}")
|
|
57
59
|
|
|
60
|
+
if isinstance(gate, ops.GlobalPhaseGate):
|
|
61
|
+
# OpenQASM 2.0 does not support global phase gates.
|
|
62
|
+
return
|
|
63
|
+
|
|
58
64
|
args = protocols.QasmArgs(qubit_id_map={q: f'q[{i}]' for i, q in enumerate(qubits)})
|
|
59
65
|
qasm = protocols.qasm(op, args=args, default=None)
|
|
60
66
|
if qasm is None:
|
cirq/testing/gate_features.py
CHANGED
|
@@ -36,3 +36,13 @@ class ThreeQubitGate(raw_types.Gate):
|
|
|
36
36
|
|
|
37
37
|
def _num_qubits_(self) -> int:
|
|
38
38
|
return 3
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class DoesNotSupportSerializationGate(raw_types.Gate):
|
|
42
|
+
"""A gate that can't be serialized."""
|
|
43
|
+
|
|
44
|
+
def __init__(self, n_qubits: int = 1):
|
|
45
|
+
self.n_qubits = n_qubits
|
|
46
|
+
|
|
47
|
+
def _num_qubits_(self) -> int:
|
|
48
|
+
return self.n_qubits
|
cirq/testing/lin_alg_utils.py
CHANGED
|
@@ -133,7 +133,8 @@ def random_special_unitary(
|
|
|
133
133
|
The sampled special unitary.
|
|
134
134
|
"""
|
|
135
135
|
r = random_unitary(dim, random_state=random_state)
|
|
136
|
-
|
|
136
|
+
with np.errstate(divide="ignore", invalid="ignore"):
|
|
137
|
+
r[0, :] /= np.linalg.det(r)
|
|
137
138
|
return r
|
|
138
139
|
|
|
139
140
|
|
|
@@ -152,8 +153,9 @@ def random_special_orthogonal(
|
|
|
152
153
|
The sampled special orthogonal matrix.
|
|
153
154
|
"""
|
|
154
155
|
m = random_orthogonal(dim, random_state=random_state)
|
|
155
|
-
|
|
156
|
-
m
|
|
156
|
+
with np.errstate(divide="ignore", invalid="ignore"):
|
|
157
|
+
if np.linalg.det(m) < 0:
|
|
158
|
+
m[0, :] *= -1
|
|
157
159
|
return m
|
|
158
160
|
|
|
159
161
|
|
cirq/transformers/__init__.py
CHANGED
|
@@ -78,6 +78,8 @@ from cirq.transformers.drop_empty_moments import drop_empty_moments
|
|
|
78
78
|
|
|
79
79
|
from cirq.transformers.drop_negligible_operations import drop_negligible_operations
|
|
80
80
|
|
|
81
|
+
from cirq.transformers.dynamical_decoupling import add_dynamical_decoupling
|
|
82
|
+
|
|
81
83
|
from cirq.transformers.eject_z import eject_z
|
|
82
84
|
|
|
83
85
|
from cirq.transformers.measurement_transformers import (
|
|
@@ -119,3 +121,16 @@ from cirq.transformers.transformer_primitives import (
|
|
|
119
121
|
unroll_circuit_op_greedy_earliest,
|
|
120
122
|
unroll_circuit_op_greedy_frontier,
|
|
121
123
|
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
from cirq.transformers.gauge_compiling import (
|
|
127
|
+
CZGaugeTransformer,
|
|
128
|
+
ConstantGauge,
|
|
129
|
+
Gauge,
|
|
130
|
+
GaugeSelector,
|
|
131
|
+
GaugeTransformer,
|
|
132
|
+
ISWAPGaugeTransformer,
|
|
133
|
+
SpinInversionGaugeTransformer,
|
|
134
|
+
SqrtCZGaugeTransformer,
|
|
135
|
+
SqrtISWAPGaugeTransformer,
|
|
136
|
+
)
|
|
@@ -47,7 +47,9 @@ def _decompose_abc(matrix: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarr
|
|
|
47
47
|
See [1], chapter 4.
|
|
48
48
|
"""
|
|
49
49
|
assert matrix.shape == (2, 2)
|
|
50
|
-
|
|
50
|
+
with np.errstate(divide="ignore", invalid="ignore"):
|
|
51
|
+
# On MacOS, np.linalg.det emits superflous warnings
|
|
52
|
+
delta = np.angle(np.linalg.det(matrix)) * 0.5
|
|
51
53
|
alpha = np.angle(matrix[0, 0]) + np.angle(matrix[0, 1]) - 2 * delta
|
|
52
54
|
beta = np.angle(matrix[0, 0]) - np.angle(matrix[0, 1])
|
|
53
55
|
|
|
@@ -31,6 +31,24 @@ if TYPE_CHECKING:
|
|
|
31
31
|
import cirq
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
def _remove_partial_czs_or_fail(
|
|
35
|
+
operations: Iterable['cirq.Operation'], atol: float
|
|
36
|
+
) -> List['cirq.Operation']:
|
|
37
|
+
result = []
|
|
38
|
+
for op in operations:
|
|
39
|
+
if isinstance(op.gate, ops.CZPowGate):
|
|
40
|
+
t = op.gate.exponent % 2 # CZ^t is periodic with period 2.
|
|
41
|
+
if t < atol:
|
|
42
|
+
continue # Identity.
|
|
43
|
+
elif abs(t - 1) < atol:
|
|
44
|
+
result.append(ops.CZ(*op.qubits)) # Was either CZ or CZ**-1.
|
|
45
|
+
else:
|
|
46
|
+
raise ValueError(f'CZ^t is not allowed for t={t}')
|
|
47
|
+
else:
|
|
48
|
+
result.append(op)
|
|
49
|
+
return result
|
|
50
|
+
|
|
51
|
+
|
|
34
52
|
def two_qubit_matrix_to_cz_operations(
|
|
35
53
|
q0: 'cirq.Qid',
|
|
36
54
|
q1: 'cirq.Qid',
|
|
@@ -53,10 +71,16 @@ def two_qubit_matrix_to_cz_operations(
|
|
|
53
71
|
|
|
54
72
|
Returns:
|
|
55
73
|
A list of operations implementing the matrix.
|
|
74
|
+
|
|
75
|
+
Raises:
|
|
76
|
+
ValueError: If allow_partial_czs=False and the matrix requires partial CZs.
|
|
56
77
|
"""
|
|
57
78
|
kak = linalg.kak_decomposition(mat, atol=atol)
|
|
58
79
|
operations = _kak_decomposition_to_operations(q0, q1, kak, allow_partial_czs, atol=atol)
|
|
59
80
|
if clean_operations:
|
|
81
|
+
if not allow_partial_czs:
|
|
82
|
+
# CZ^t is not allowed for any $t$ except $t=1$.
|
|
83
|
+
return _remove_partial_czs_or_fail(cleanup_operations(operations), atol=atol)
|
|
60
84
|
return cleanup_operations(operations)
|
|
61
85
|
return operations
|
|
62
86
|
|
|
@@ -257,3 +257,20 @@ def test_decompose_to_diagonal_and_circuit(v):
|
|
|
257
257
|
combined_circuit = cirq.Circuit(cirq.MatrixGate(diagonal)(b, c), ops)
|
|
258
258
|
circuit_unitary = combined_circuit.unitary(qubits_that_should_be_present=[b, c])
|
|
259
259
|
cirq.testing.assert_allclose_up_to_global_phase(circuit_unitary, v, atol=2e-6)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def test_remove_partial_czs_or_fail():
|
|
263
|
+
CZ = cirq.CZ(*cirq.LineQubit.range(2))
|
|
264
|
+
assert (
|
|
265
|
+
cirq.transformers.analytical_decompositions.two_qubit_to_cz._remove_partial_czs_or_fail(
|
|
266
|
+
[CZ**1e-15], atol=1e-9
|
|
267
|
+
)
|
|
268
|
+
== []
|
|
269
|
+
)
|
|
270
|
+
assert cirq.transformers.analytical_decompositions.two_qubit_to_cz._remove_partial_czs_or_fail(
|
|
271
|
+
[CZ**-1, CZ], atol=1e-9
|
|
272
|
+
) == [CZ, CZ]
|
|
273
|
+
with pytest.raises(ValueError):
|
|
274
|
+
_ = cirq.transformers.analytical_decompositions.two_qubit_to_cz._remove_partial_czs_or_fail(
|
|
275
|
+
[CZ**-0.5], atol=1e-9
|
|
276
|
+
)
|