cirq-core 1.6.0.dev20250416221104__py3-none-any.whl → 1.6.0.dev20250418235304__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 +1 -1
- cirq/_version_test.py +1 -1
- cirq/devices/noise_model_test.py +3 -1
- cirq/devices/noise_properties.py +6 -4
- cirq/devices/noise_utils.py +8 -6
- cirq/devices/superconducting_qubits_noise_properties.py +10 -9
- cirq/devices/thermal_noise_model.py +12 -12
- cirq/devices/unconstrained_device.py +3 -1
- cirq/experiments/n_qubit_tomography.py +15 -12
- cirq/experiments/qubit_characterizations.py +34 -39
- cirq/experiments/random_quantum_circuit_generation.py +38 -38
- cirq/experiments/random_quantum_circuit_generation_test.py +7 -4
- cirq/experiments/readout_confusion_matrix.py +17 -15
- cirq/experiments/single_qubit_readout_calibration.py +9 -5
- cirq/experiments/single_qubit_readout_calibration_test.py +5 -2
- cirq/experiments/t1_decay_experiment.py +7 -5
- cirq/experiments/t2_decay_experiment.py +10 -7
- cirq/experiments/two_qubit_xeb.py +42 -43
- cirq/experiments/two_qubit_xeb_test.py +1 -1
- cirq/experiments/xeb_fitting.py +25 -21
- cirq/experiments/xeb_sampling.py +18 -14
- cirq/experiments/xeb_simulation.py +11 -7
- cirq/experiments/xeb_simulation_test.py +3 -3
- cirq/experiments/z_phase_calibration.py +27 -24
- cirq/experiments/z_phase_calibration_test.py +1 -4
- cirq/interop/quirk/cells/arithmetic_cells.py +11 -10
- cirq/interop/quirk/cells/cell.py +18 -15
- cirq/interop/quirk/cells/composite_cell.py +8 -8
- cirq/interop/quirk/cells/control_cells.py +14 -14
- cirq/interop/quirk/cells/frequency_space_cells.py +4 -3
- cirq/interop/quirk/cells/input_cells.py +6 -4
- cirq/interop/quirk/cells/input_rotation_cells.py +14 -12
- cirq/interop/quirk/cells/measurement_cells.py +4 -1
- cirq/interop/quirk/cells/qubit_permutation_cells.py +3 -1
- cirq/interop/quirk/cells/scalar_cells.py +4 -1
- cirq/interop/quirk/cells/single_qubit_rotation_cells.py +5 -2
- cirq/interop/quirk/cells/swap_cell.py +7 -5
- cirq/interop/quirk/cells/testing.py +1 -1
- cirq/interop/quirk/url_to_circuit.py +11 -8
- cirq/json_resolver_cache.py +5 -3
- cirq/linalg/decompositions.py +5 -4
- cirq/linalg/decompositions_test.py +1 -1
- cirq/linalg/operator_spaces.py +8 -8
- cirq/ops/arithmetic_operation.py +4 -2
- cirq/ops/boolean_hamiltonian.py +7 -6
- cirq/ops/classically_controlled_operation.py +23 -20
- cirq/ops/clifford_gate.py +43 -47
- cirq/ops/common_channels.py +16 -14
- cirq/ops/common_gates.py +49 -67
- cirq/ops/control_values.py +12 -15
- cirq/ops/controlled_gate.py +15 -17
- cirq/ops/controlled_operation.py +17 -15
- {cirq_core-1.6.0.dev20250416221104.dist-info → cirq_core-1.6.0.dev20250418235304.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250416221104.dist-info → cirq_core-1.6.0.dev20250418235304.dist-info}/RECORD +57 -57
- {cirq_core-1.6.0.dev20250416221104.dist-info → cirq_core-1.6.0.dev20250418235304.dist-info}/WHEEL +0 -0
- {cirq_core-1.6.0.dev20250416221104.dist-info → cirq_core-1.6.0.dev20250418235304.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250416221104.dist-info → cirq_core-1.6.0.dev20250418235304.dist-info}/top_level.txt +0 -0
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""Provides a method to do z-phase calibration for excitation-preserving gates."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
16
19
|
import multiprocessing
|
|
17
20
|
import multiprocessing.pool
|
|
18
21
|
from typing import Any, Dict, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
|
|
@@ -32,20 +35,20 @@ if TYPE_CHECKING:
|
|
|
32
35
|
|
|
33
36
|
|
|
34
37
|
def z_phase_calibration_workflow(
|
|
35
|
-
sampler:
|
|
36
|
-
qubits: Optional[Sequence[
|
|
37
|
-
two_qubit_gate:
|
|
38
|
+
sampler: cirq.Sampler,
|
|
39
|
+
qubits: Optional[Sequence[cirq.GridQubit]] = None,
|
|
40
|
+
two_qubit_gate: cirq.Gate = ops.CZ,
|
|
38
41
|
options: Optional[xeb_fitting.XEBPhasedFSimCharacterizationOptions] = None,
|
|
39
42
|
n_repetitions: int = 10**4,
|
|
40
43
|
n_combinations: int = 10,
|
|
41
44
|
n_circuits: int = 20,
|
|
42
45
|
cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
|
|
43
|
-
random_state:
|
|
46
|
+
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
44
47
|
atol: float = 1e-3,
|
|
45
|
-
num_workers_or_pool: Union[int,
|
|
46
|
-
pairs: Optional[Sequence[Tuple[
|
|
48
|
+
num_workers_or_pool: Union[int, multiprocessing.pool.Pool] = -1,
|
|
49
|
+
pairs: Optional[Sequence[Tuple[cirq.GridQubit, cirq.GridQubit]]] = None,
|
|
47
50
|
tags: Sequence[Any] = (),
|
|
48
|
-
) -> Tuple[xeb_fitting.XEBCharacterizationResult,
|
|
51
|
+
) -> Tuple[xeb_fitting.XEBCharacterizationResult, pd.DataFrame]:
|
|
49
52
|
"""Perform z-phase calibration for excitation-preserving gates.
|
|
50
53
|
|
|
51
54
|
For a given excitation-preserving two-qubit gate we assume an error model that can be described
|
|
@@ -88,7 +91,7 @@ def z_phase_calibration_workflow(
|
|
|
88
91
|
- A `pd.DataFrame` comparing the before and after fidelities.
|
|
89
92
|
"""
|
|
90
93
|
|
|
91
|
-
pool: Optional[
|
|
94
|
+
pool: Optional[multiprocessing.pool.Pool] = None
|
|
92
95
|
local_pool = False
|
|
93
96
|
if isinstance(num_workers_or_pool, multiprocessing.pool.Pool):
|
|
94
97
|
pool = num_workers_or_pool # pragma: no cover
|
|
@@ -145,20 +148,20 @@ def z_phase_calibration_workflow(
|
|
|
145
148
|
|
|
146
149
|
|
|
147
150
|
def calibrate_z_phases(
|
|
148
|
-
sampler:
|
|
149
|
-
qubits: Optional[Sequence[
|
|
150
|
-
two_qubit_gate:
|
|
151
|
+
sampler: cirq.Sampler,
|
|
152
|
+
qubits: Optional[Sequence[cirq.GridQubit]] = None,
|
|
153
|
+
two_qubit_gate: cirq.Gate = ops.CZ,
|
|
151
154
|
options: Optional[xeb_fitting.XEBPhasedFSimCharacterizationOptions] = None,
|
|
152
155
|
n_repetitions: int = 10**4,
|
|
153
156
|
n_combinations: int = 10,
|
|
154
157
|
n_circuits: int = 20,
|
|
155
158
|
cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
|
|
156
|
-
random_state:
|
|
159
|
+
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
157
160
|
atol: float = 1e-3,
|
|
158
|
-
num_workers_or_pool: Union[int,
|
|
159
|
-
pairs: Optional[Sequence[Tuple[
|
|
161
|
+
num_workers_or_pool: Union[int, multiprocessing.pool.Pool] = -1,
|
|
162
|
+
pairs: Optional[Sequence[Tuple[cirq.GridQubit, cirq.GridQubit]]] = None,
|
|
160
163
|
tags: Sequence[Any] = (),
|
|
161
|
-
) -> Dict[Tuple[
|
|
164
|
+
) -> Dict[Tuple[cirq.Qid, cirq.Qid], cirq.PhasedFSimGate]:
|
|
162
165
|
"""Perform z-phase calibration for excitation-preserving gates.
|
|
163
166
|
|
|
164
167
|
For a given excitation-preserving two-qubit gate we assume an error model that can be described
|
|
@@ -238,12 +241,12 @@ def calibrate_z_phases(
|
|
|
238
241
|
|
|
239
242
|
|
|
240
243
|
def plot_z_phase_calibration_result(
|
|
241
|
-
before_after_df:
|
|
242
|
-
axes: Optional[np.ndarray[Sequence[Sequence[
|
|
243
|
-
pairs: Optional[Sequence[Tuple[
|
|
244
|
+
before_after_df: pd.DataFrame,
|
|
245
|
+
axes: Optional[np.ndarray[Sequence[Sequence[plt.Axes]], np.dtype[np.object_]]] = None,
|
|
246
|
+
pairs: Optional[Sequence[Tuple[cirq.Qid, cirq.Qid]]] = None,
|
|
244
247
|
*,
|
|
245
248
|
with_error_bars: bool = False,
|
|
246
|
-
) -> np.ndarray[Sequence[Sequence[
|
|
249
|
+
) -> np.ndarray[Sequence[Sequence[plt.Axes]], np.dtype[np.object_]]:
|
|
247
250
|
"""A helper method to plot the result of running z-phase calibration.
|
|
248
251
|
|
|
249
252
|
Note that the plotted fidelity is a statistical estimate of the true fidelity and as a result
|
|
@@ -301,8 +304,8 @@ class CalibrationTransformer:
|
|
|
301
304
|
|
|
302
305
|
def __init__(
|
|
303
306
|
self,
|
|
304
|
-
target:
|
|
305
|
-
calibration_map: Dict[Tuple[
|
|
307
|
+
target: cirq.Gate,
|
|
308
|
+
calibration_map: Dict[Tuple[cirq.Qid, cirq.Qid], cirq.PhasedFSimGate],
|
|
306
309
|
):
|
|
307
310
|
"""Create a CalibrationTransformer.
|
|
308
311
|
|
|
@@ -327,10 +330,10 @@ class CalibrationTransformer:
|
|
|
327
330
|
|
|
328
331
|
def __call__(
|
|
329
332
|
self,
|
|
330
|
-
circuit:
|
|
333
|
+
circuit: cirq.AbstractCircuit,
|
|
331
334
|
*,
|
|
332
335
|
context: Optional[transformer_api.TransformerContext] = None,
|
|
333
|
-
) ->
|
|
336
|
+
) -> cirq.Circuit:
|
|
334
337
|
"""Adds 3 ZPowGates around each calibrated gate to cancel the effect of Z phases.
|
|
335
338
|
|
|
336
339
|
Args:
|
|
@@ -340,7 +343,7 @@ class CalibrationTransformer:
|
|
|
340
343
|
Returns:
|
|
341
344
|
New circuit with the extra ZPowGates.
|
|
342
345
|
"""
|
|
343
|
-
new_moments: List[Union[List[cirq.Operation],
|
|
346
|
+
new_moments: List[Union[List[cirq.Operation], cirq.Moment]] = []
|
|
344
347
|
for moment in circuit:
|
|
345
348
|
before = []
|
|
346
349
|
after = []
|
|
@@ -72,10 +72,7 @@ class _TestSimulator(cirq.Simulator):
|
|
|
72
72
|
self.replacement = replacement
|
|
73
73
|
|
|
74
74
|
def _core_iterator(
|
|
75
|
-
self,
|
|
76
|
-
circuit: 'cirq.AbstractCircuit',
|
|
77
|
-
sim_state,
|
|
78
|
-
all_measurements_are_terminal: bool = False,
|
|
75
|
+
self, circuit: cirq.AbstractCircuit, sim_state, all_measurements_are_terminal: bool = False
|
|
79
76
|
):
|
|
80
77
|
new_circuit = cirq.Circuit(
|
|
81
78
|
[
|
|
@@ -11,6 +11,9 @@
|
|
|
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 __future__ import annotations
|
|
16
|
+
|
|
14
17
|
import inspect
|
|
15
18
|
from typing import (
|
|
16
19
|
Any,
|
|
@@ -80,7 +83,7 @@ class QuirkArithmeticGate(ops.ArithmeticGate):
|
|
|
80
83
|
raise ValueError(f'Target too small for modulus.\nTarget: {target}\nModulus: {r}')
|
|
81
84
|
|
|
82
85
|
@property
|
|
83
|
-
def operation(self) ->
|
|
86
|
+
def operation(self) -> _QuirkArithmeticCallable:
|
|
84
87
|
return ARITHMETIC_OP_TABLE[self.identifier]
|
|
85
88
|
|
|
86
89
|
def _value_equality_values_(self) -> Any:
|
|
@@ -89,7 +92,7 @@ class QuirkArithmeticGate(ops.ArithmeticGate):
|
|
|
89
92
|
def registers(self) -> Sequence[Union[int, Sequence[int]]]:
|
|
90
93
|
return [self.target, *self.inputs]
|
|
91
94
|
|
|
92
|
-
def with_registers(self, *new_registers: Union[int, Sequence[int]]) ->
|
|
95
|
+
def with_registers(self, *new_registers: Union[int, Sequence[int]]) -> QuirkArithmeticGate:
|
|
93
96
|
if len(new_registers) != len(self.inputs) + 1:
|
|
94
97
|
raise ValueError(
|
|
95
98
|
'Wrong number of registers.\n'
|
|
@@ -109,7 +112,7 @@ class QuirkArithmeticGate(ops.ArithmeticGate):
|
|
|
109
112
|
def apply(self, *registers: int) -> Union[int, Iterable[int]]:
|
|
110
113
|
return self.operation(*registers)
|
|
111
114
|
|
|
112
|
-
def _circuit_diagram_info_(self, args:
|
|
115
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> List[str]:
|
|
113
116
|
lettered_args = list(zip(self.operation.letters, self.inputs))
|
|
114
117
|
|
|
115
118
|
result: List[str] = []
|
|
@@ -183,8 +186,8 @@ class ArithmeticCell(Cell):
|
|
|
183
186
|
def __init__(
|
|
184
187
|
self,
|
|
185
188
|
identifier: str,
|
|
186
|
-
target: Sequence[
|
|
187
|
-
inputs: Sequence[Union[None, Sequence[
|
|
189
|
+
target: Sequence[cirq.Qid],
|
|
190
|
+
inputs: Sequence[Union[None, Sequence[cirq.Qid], int]],
|
|
188
191
|
):
|
|
189
192
|
self.identifier = identifier
|
|
190
193
|
self.target = tuple(target)
|
|
@@ -204,7 +207,7 @@ class ArithmeticCell(Cell):
|
|
|
204
207
|
f'\n {self.inputs!r})'
|
|
205
208
|
)
|
|
206
209
|
|
|
207
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
210
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
208
211
|
return ArithmeticCell(
|
|
209
212
|
identifier=self.identifier,
|
|
210
213
|
target=Cell._replace_qubits(self.target, qubits),
|
|
@@ -218,16 +221,14 @@ class ArithmeticCell(Cell):
|
|
|
218
221
|
def operation(self):
|
|
219
222
|
return ARITHMETIC_OP_TABLE[self.identifier]
|
|
220
223
|
|
|
221
|
-
def with_input(
|
|
222
|
-
self, letter: str, register: Union[Sequence['cirq.Qid'], int]
|
|
223
|
-
) -> 'ArithmeticCell':
|
|
224
|
+
def with_input(self, letter: str, register: Union[Sequence[cirq.Qid], int]) -> ArithmeticCell:
|
|
224
225
|
new_inputs = [
|
|
225
226
|
reg if letter != reg_letter else register
|
|
226
227
|
for reg, reg_letter in zip(self.inputs, self.operation.letters)
|
|
227
228
|
]
|
|
228
229
|
return ArithmeticCell(self.identifier, self.target, new_inputs)
|
|
229
230
|
|
|
230
|
-
def operations(self) ->
|
|
231
|
+
def operations(self) -> cirq.OP_TREE:
|
|
231
232
|
missing_inputs = [
|
|
232
233
|
letter for reg, letter in zip(self.inputs, self.operation.letters) if reg is None
|
|
233
234
|
]
|
cirq/interop/quirk/cells/cell.py
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
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 __future__ import annotations
|
|
16
|
+
|
|
14
17
|
import abc
|
|
15
18
|
from typing import (
|
|
16
19
|
Any,
|
|
@@ -41,7 +44,7 @@ class Cell(metaclass=abc.ABCMeta):
|
|
|
41
44
|
"""
|
|
42
45
|
|
|
43
46
|
@classmethod
|
|
44
|
-
def _replace_qubit(cls, old_qubit:
|
|
47
|
+
def _replace_qubit(cls, old_qubit: cirq.Qid, qubits: List[cirq.Qid]) -> cirq.Qid:
|
|
45
48
|
if not isinstance(old_qubit, devices.LineQubit):
|
|
46
49
|
raise ValueError(f'Can only map from line qubits, but got {old_qubit!r}.')
|
|
47
50
|
if not 0 <= old_qubit.x < len(qubits):
|
|
@@ -50,12 +53,12 @@ class Cell(metaclass=abc.ABCMeta):
|
|
|
50
53
|
|
|
51
54
|
@classmethod
|
|
52
55
|
def _replace_qubits(
|
|
53
|
-
cls, old_qubits: Iterable[
|
|
54
|
-
) -> Tuple[
|
|
56
|
+
cls, old_qubits: Iterable[cirq.Qid], qubits: List[cirq.Qid]
|
|
57
|
+
) -> Tuple[cirq.Qid, ...]:
|
|
55
58
|
return tuple(Cell._replace_qubit(e, qubits) for e in old_qubits)
|
|
56
59
|
|
|
57
60
|
@abc.abstractmethod
|
|
58
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
61
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
59
62
|
"""Returns the same cell, but targeting different qubits.
|
|
60
63
|
|
|
61
64
|
It is assumed that the cell is currently targeting `LineQubit`
|
|
@@ -84,7 +87,7 @@ class Cell(metaclass=abc.ABCMeta):
|
|
|
84
87
|
extremely adversarial conditions.
|
|
85
88
|
"""
|
|
86
89
|
|
|
87
|
-
def with_input(self, letter: str, register: Union[Sequence[
|
|
90
|
+
def with_input(self, letter: str, register: Union[Sequence[cirq.Qid], int]) -> Cell:
|
|
88
91
|
"""The same cell, but linked to an explicit input register or constant.
|
|
89
92
|
|
|
90
93
|
If the cell doesn't need the input, it is returned unchanged.
|
|
@@ -99,7 +102,7 @@ class Cell(metaclass=abc.ABCMeta):
|
|
|
99
102
|
"""
|
|
100
103
|
return self
|
|
101
104
|
|
|
102
|
-
def controlled_by(self, qubit:
|
|
105
|
+
def controlled_by(self, qubit: cirq.Qid) -> Cell:
|
|
103
106
|
"""The same cell, but with an explicit control on its main operations.
|
|
104
107
|
|
|
105
108
|
Cells with effects that do not need to be controlled are permitted to
|
|
@@ -113,7 +116,7 @@ class Cell(metaclass=abc.ABCMeta):
|
|
|
113
116
|
"""
|
|
114
117
|
return self
|
|
115
118
|
|
|
116
|
-
def operations(self) ->
|
|
119
|
+
def operations(self) -> cirq.OP_TREE:
|
|
117
120
|
"""Returns operations that implement the cell's main action.
|
|
118
121
|
|
|
119
122
|
Returns:
|
|
@@ -126,7 +129,7 @@ class Cell(metaclass=abc.ABCMeta):
|
|
|
126
129
|
"""
|
|
127
130
|
return ()
|
|
128
131
|
|
|
129
|
-
def basis_change(self) ->
|
|
132
|
+
def basis_change(self) -> cirq.OP_TREE:
|
|
130
133
|
"""Operations to conjugate a column with.
|
|
131
134
|
|
|
132
135
|
The main distinctions between operations performed during the body of a
|
|
@@ -143,7 +146,7 @@ class Cell(metaclass=abc.ABCMeta):
|
|
|
143
146
|
"""
|
|
144
147
|
return ()
|
|
145
148
|
|
|
146
|
-
def modify_column(self, column: List[Optional[
|
|
149
|
+
def modify_column(self, column: List[Optional[Cell]]) -> None:
|
|
147
150
|
"""Applies this cell's modification to its column.
|
|
148
151
|
|
|
149
152
|
For example, a control cell will add a control qubit to other operations
|
|
@@ -159,7 +162,7 @@ class Cell(metaclass=abc.ABCMeta):
|
|
|
159
162
|
Nothing. The `column` argument is mutated in place.
|
|
160
163
|
"""
|
|
161
164
|
|
|
162
|
-
def persistent_modifiers(self) -> Dict[str, Callable[[
|
|
165
|
+
def persistent_modifiers(self) -> Dict[str, Callable[[Cell], Cell]]:
|
|
163
166
|
"""Overridable modifications to apply to the rest of the circuit.
|
|
164
167
|
|
|
165
168
|
Persistent modifiers apply to all cells in the same column and also to
|
|
@@ -186,7 +189,7 @@ class ExplicitOperationsCell(Cell):
|
|
|
186
189
|
def gate_count(self) -> int:
|
|
187
190
|
return len(self._operations) + 2 * len(self._basis_change)
|
|
188
191
|
|
|
189
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
192
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
190
193
|
return ExplicitOperationsCell(
|
|
191
194
|
operations=tuple(
|
|
192
195
|
op.with_qubits(*Cell._replace_qubits(op.qubits, qubits)) for op in self._operations
|
|
@@ -200,13 +203,13 @@ class ExplicitOperationsCell(Cell):
|
|
|
200
203
|
def _value_equality_values_(self):
|
|
201
204
|
return self._operations, self._basis_change
|
|
202
205
|
|
|
203
|
-
def basis_change(self) ->
|
|
206
|
+
def basis_change(self) -> cirq.OP_TREE:
|
|
204
207
|
return self._basis_change
|
|
205
208
|
|
|
206
|
-
def operations(self) ->
|
|
209
|
+
def operations(self) -> cirq.OP_TREE:
|
|
207
210
|
return self._operations
|
|
208
211
|
|
|
209
|
-
def controlled_by(self, qubit:
|
|
212
|
+
def controlled_by(self, qubit: cirq.Qid) -> ExplicitOperationsCell:
|
|
210
213
|
return ExplicitOperationsCell(
|
|
211
214
|
[op.controlled_by(qubit) for op in self._operations], self._basis_change
|
|
212
215
|
)
|
|
@@ -223,7 +226,7 @@ CellMaker = NamedTuple(
|
|
|
223
226
|
[
|
|
224
227
|
('identifier', str),
|
|
225
228
|
('size', int),
|
|
226
|
-
('maker', Callable[[CellMakerArgs], Union[None,
|
|
229
|
+
('maker', Callable[[CellMakerArgs], Union[None, Cell, 'cirq.Operation']]),
|
|
227
230
|
],
|
|
228
231
|
)
|
|
229
232
|
CellMaker.__doc__ = """Turns Quirk identifiers into Cirq operations.
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from typing import (
|
|
16
18
|
Callable,
|
|
17
19
|
cast,
|
|
@@ -79,7 +81,7 @@ class CompositeCell(Cell):
|
|
|
79
81
|
def gate_count(self) -> int:
|
|
80
82
|
return self._gate_count
|
|
81
83
|
|
|
82
|
-
def _transform_cells(self, func: Callable[[Cell], Cell]) ->
|
|
84
|
+
def _transform_cells(self, func: Callable[[Cell], Cell]) -> CompositeCell:
|
|
83
85
|
return CompositeCell(
|
|
84
86
|
height=self.height,
|
|
85
87
|
# It is important that this is a generator instead of a list!
|
|
@@ -96,18 +98,16 @@ class CompositeCell(Cell):
|
|
|
96
98
|
self._sub_cell_cols_generator = list(self._sub_cell_cols_generator)
|
|
97
99
|
return cast(List[List[Optional[Cell]]], self._sub_cell_cols_generator)
|
|
98
100
|
|
|
99
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
101
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
100
102
|
return self._transform_cells(lambda cell: cell.with_line_qubits_mapped_to(qubits))
|
|
101
103
|
|
|
102
|
-
def with_input(
|
|
103
|
-
self, letter: str, register: Union[Sequence['cirq.Qid'], int]
|
|
104
|
-
) -> 'CompositeCell':
|
|
104
|
+
def with_input(self, letter: str, register: Union[Sequence[cirq.Qid], int]) -> CompositeCell:
|
|
105
105
|
return self._transform_cells(lambda cell: cell.with_input(letter, register))
|
|
106
106
|
|
|
107
|
-
def controlled_by(self, qubit:
|
|
107
|
+
def controlled_by(self, qubit: cirq.Qid) -> CompositeCell:
|
|
108
108
|
return self._transform_cells(lambda cell: cell.controlled_by(qubit))
|
|
109
109
|
|
|
110
|
-
def circuit(self) ->
|
|
110
|
+
def circuit(self) -> cirq.Circuit:
|
|
111
111
|
result = circuits.Circuit()
|
|
112
112
|
for col in self._sub_cell_cols_sealed():
|
|
113
113
|
body = circuits.Circuit(cell.operations() for cell in col if cell is not None)
|
|
@@ -120,7 +120,7 @@ class CompositeCell(Cell):
|
|
|
120
120
|
result += basis_change**-1
|
|
121
121
|
return result
|
|
122
122
|
|
|
123
|
-
def operations(self) ->
|
|
123
|
+
def operations(self) -> cirq.OP_TREE:
|
|
124
124
|
return self.circuit()
|
|
125
125
|
|
|
126
126
|
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from typing import Any, Iterable, Iterator, List, Optional, TYPE_CHECKING, Union
|
|
16
18
|
|
|
17
19
|
from cirq import ops, value
|
|
@@ -25,7 +27,7 @@ if TYPE_CHECKING:
|
|
|
25
27
|
class ControlCell(Cell):
|
|
26
28
|
"""A modifier that adds controls to other cells in the column."""
|
|
27
29
|
|
|
28
|
-
def __init__(self, qubit:
|
|
30
|
+
def __init__(self, qubit: cirq.Qid, basis_change: Iterable[cirq.Operation]):
|
|
29
31
|
self.qubit = qubit
|
|
30
32
|
self._basis_change = tuple(basis_change)
|
|
31
33
|
|
|
@@ -42,7 +44,7 @@ class ControlCell(Cell):
|
|
|
42
44
|
def gate_count(self) -> int:
|
|
43
45
|
return 0
|
|
44
46
|
|
|
45
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
47
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
46
48
|
return ControlCell(
|
|
47
49
|
qubit=Cell._replace_qubit(self.qubit, qubits),
|
|
48
50
|
basis_change=tuple(
|
|
@@ -51,13 +53,13 @@ class ControlCell(Cell):
|
|
|
51
53
|
),
|
|
52
54
|
)
|
|
53
55
|
|
|
54
|
-
def modify_column(self, column: List[Optional[
|
|
56
|
+
def modify_column(self, column: List[Optional[Cell]]):
|
|
55
57
|
for i in range(len(column)):
|
|
56
58
|
gate = column[i]
|
|
57
59
|
if gate is not None:
|
|
58
60
|
column[i] = gate.controlled_by(self.qubit)
|
|
59
61
|
|
|
60
|
-
def basis_change(self) ->
|
|
62
|
+
def basis_change(self) -> cirq.OP_TREE:
|
|
61
63
|
return self._basis_change
|
|
62
64
|
|
|
63
65
|
|
|
@@ -69,7 +71,7 @@ class ParityControlCell(Cell):
|
|
|
69
71
|
of them are individually satisfied.
|
|
70
72
|
"""
|
|
71
73
|
|
|
72
|
-
def __init__(self, qubits: Iterable[
|
|
74
|
+
def __init__(self, qubits: Iterable[cirq.Qid], basis_change: Iterable[cirq.Operation]):
|
|
73
75
|
self.qubits = list(qubits)
|
|
74
76
|
self._basis_change = list(basis_change)
|
|
75
77
|
|
|
@@ -86,7 +88,7 @@ class ParityControlCell(Cell):
|
|
|
86
88
|
def gate_count(self) -> int:
|
|
87
89
|
return 0
|
|
88
90
|
|
|
89
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
91
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
90
92
|
return ParityControlCell(
|
|
91
93
|
qubits=Cell._replace_qubits(self.qubits, qubits),
|
|
92
94
|
basis_change=tuple(
|
|
@@ -95,7 +97,7 @@ class ParityControlCell(Cell):
|
|
|
95
97
|
),
|
|
96
98
|
)
|
|
97
99
|
|
|
98
|
-
def modify_column(self, column: List[Optional[
|
|
100
|
+
def modify_column(self, column: List[Optional[Cell]]):
|
|
99
101
|
for i in range(len(column)):
|
|
100
102
|
gate = column[i]
|
|
101
103
|
if gate is self:
|
|
@@ -109,7 +111,7 @@ class ParityControlCell(Cell):
|
|
|
109
111
|
elif gate is not None:
|
|
110
112
|
column[i] = gate.controlled_by(self.qubits[0])
|
|
111
113
|
|
|
112
|
-
def basis_change(self) -> Iterator[
|
|
114
|
+
def basis_change(self) -> Iterator[cirq.OP_TREE]:
|
|
113
115
|
yield from self._basis_change
|
|
114
116
|
|
|
115
117
|
# Temporarily move the ZZZ..Z parity observable onto a single qubit.
|
|
@@ -132,7 +134,7 @@ def generate_all_control_cell_makers() -> Iterator[CellMaker]:
|
|
|
132
134
|
yield _reg_parity_control("zpar", basis_change=None)
|
|
133
135
|
|
|
134
136
|
|
|
135
|
-
def _reg_control(identifier: str, *, basis_change: Optional[
|
|
137
|
+
def _reg_control(identifier: str, *, basis_change: Optional[cirq.Gate]) -> CellMaker:
|
|
136
138
|
return CellMaker(
|
|
137
139
|
identifier=identifier,
|
|
138
140
|
size=1,
|
|
@@ -142,9 +144,7 @@ def _reg_control(identifier: str, *, basis_change: Optional['cirq.Gate']) -> Cel
|
|
|
142
144
|
)
|
|
143
145
|
|
|
144
146
|
|
|
145
|
-
def _reg_parity_control(
|
|
146
|
-
identifier: str, *, basis_change: Optional['cirq.Gate'] = None
|
|
147
|
-
) -> CellMaker:
|
|
147
|
+
def _reg_parity_control(identifier: str, *, basis_change: Optional[cirq.Gate] = None) -> CellMaker:
|
|
148
148
|
return CellMaker(
|
|
149
149
|
identifier=identifier,
|
|
150
150
|
size=1,
|
|
@@ -155,8 +155,8 @@ def _reg_parity_control(
|
|
|
155
155
|
|
|
156
156
|
|
|
157
157
|
def _basis_else_empty(
|
|
158
|
-
basis_change: Optional[
|
|
159
|
-
) -> Iterable[
|
|
158
|
+
basis_change: Optional[cirq.Gate], qureg: Union[cirq.Qid, Iterable[cirq.Qid]]
|
|
159
|
+
) -> Iterable[cirq.Operation]:
|
|
160
160
|
if basis_change is None:
|
|
161
161
|
return ()
|
|
162
162
|
return basis_change.on_each(qureg)
|
|
@@ -11,6 +11,9 @@
|
|
|
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 __future__ import annotations
|
|
16
|
+
|
|
14
17
|
from typing import Callable, Iterator
|
|
15
18
|
|
|
16
19
|
import sympy
|
|
@@ -41,9 +44,7 @@ def generate_all_frequency_space_cell_makers() -> Iterator[CellMaker]:
|
|
|
41
44
|
)
|
|
42
45
|
|
|
43
46
|
|
|
44
|
-
def _family(
|
|
45
|
-
identifier_prefix: str, gate_maker: Callable[[int], 'cirq.Gate']
|
|
46
|
-
) -> Iterator[CellMaker]:
|
|
47
|
+
def _family(identifier_prefix: str, gate_maker: Callable[[int], cirq.Gate]) -> Iterator[CellMaker]:
|
|
47
48
|
f = lambda args: ExplicitOperationsCell([gate_maker(len(args.qubits)).on(*args.qubits)])
|
|
48
49
|
yield CellMaker(identifier_prefix, 1, f)
|
|
49
50
|
for i in CELL_SIZES:
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from typing import Iterable, Iterator, List, Optional, TYPE_CHECKING
|
|
16
18
|
|
|
17
19
|
from cirq.interop.quirk.cells.cell import Cell, CELL_SIZES, CellMaker
|
|
@@ -23,17 +25,17 @@ if TYPE_CHECKING:
|
|
|
23
25
|
class InputCell(Cell):
|
|
24
26
|
"""A modifier that provides a quantum input to gates in the same column."""
|
|
25
27
|
|
|
26
|
-
def __init__(self, qubits: Iterable[
|
|
28
|
+
def __init__(self, qubits: Iterable[cirq.Qid], letter: str):
|
|
27
29
|
self.qubits = tuple(qubits)
|
|
28
30
|
self.letter = letter
|
|
29
31
|
|
|
30
32
|
def gate_count(self) -> int:
|
|
31
33
|
return 0
|
|
32
34
|
|
|
33
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
35
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
34
36
|
return InputCell(qubits=Cell._replace_qubits(self.qubits, qubits), letter=self.letter)
|
|
35
37
|
|
|
36
|
-
def modify_column(self, column: List[Optional[
|
|
38
|
+
def modify_column(self, column: List[Optional[Cell]]):
|
|
37
39
|
for i in range(len(column)):
|
|
38
40
|
cell = column[i]
|
|
39
41
|
if cell is not None:
|
|
@@ -50,7 +52,7 @@ class SetDefaultInputCell(Cell):
|
|
|
50
52
|
def gate_count(self) -> int:
|
|
51
53
|
return 0
|
|
52
54
|
|
|
53
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
55
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
54
56
|
return self
|
|
55
57
|
|
|
56
58
|
def persistent_modifiers(self):
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from typing import Any, Iterable, Iterator, List, Optional, Sequence, Tuple, Union
|
|
16
18
|
|
|
17
19
|
import numpy as np
|
|
@@ -28,8 +30,8 @@ class InputRotationCell(Cell):
|
|
|
28
30
|
def __init__(
|
|
29
31
|
self,
|
|
30
32
|
identifier: str,
|
|
31
|
-
register: Optional[Sequence[
|
|
32
|
-
base_operation:
|
|
33
|
+
register: Optional[Sequence[cirq.Qid]],
|
|
34
|
+
base_operation: cirq.Operation,
|
|
33
35
|
exponent_sign: int,
|
|
34
36
|
):
|
|
35
37
|
self.identifier = identifier
|
|
@@ -52,7 +54,7 @@ class InputRotationCell(Cell):
|
|
|
52
54
|
def gate_count(self) -> int:
|
|
53
55
|
return 1
|
|
54
56
|
|
|
55
|
-
def with_line_qubits_mapped_to(self, qubits: List[
|
|
57
|
+
def with_line_qubits_mapped_to(self, qubits: List[cirq.Qid]) -> Cell:
|
|
56
58
|
return InputRotationCell(
|
|
57
59
|
self.identifier,
|
|
58
60
|
None if self.register is None else Cell._replace_qubits(self.register, qubits),
|
|
@@ -62,7 +64,7 @@ class InputRotationCell(Cell):
|
|
|
62
64
|
exponent_sign=self.exponent_sign,
|
|
63
65
|
)
|
|
64
66
|
|
|
65
|
-
def with_input(self, letter: str, register: Union[Sequence[
|
|
67
|
+
def with_input(self, letter: str, register: Union[Sequence[cirq.Qid], int]) -> Cell:
|
|
66
68
|
# Parameterized rotations use input A as their parameter.
|
|
67
69
|
if self.register is None and letter == 'a':
|
|
68
70
|
if isinstance(register, int):
|
|
@@ -75,7 +77,7 @@ class InputRotationCell(Cell):
|
|
|
75
77
|
)
|
|
76
78
|
return self
|
|
77
79
|
|
|
78
|
-
def controlled_by(self, qubit:
|
|
80
|
+
def controlled_by(self, qubit: cirq.Qid):
|
|
79
81
|
return InputRotationCell(
|
|
80
82
|
self.identifier,
|
|
81
83
|
self.register,
|
|
@@ -83,7 +85,7 @@ class InputRotationCell(Cell):
|
|
|
83
85
|
self.exponent_sign,
|
|
84
86
|
)
|
|
85
87
|
|
|
86
|
-
def operations(self) ->
|
|
88
|
+
def operations(self) -> cirq.OP_TREE:
|
|
87
89
|
if self.register is None:
|
|
88
90
|
raise ValueError("Missing input 'a'")
|
|
89
91
|
return QuirkInputRotationOperation(
|
|
@@ -98,8 +100,8 @@ class QuirkInputRotationOperation(ops.Operation):
|
|
|
98
100
|
def __init__(
|
|
99
101
|
self,
|
|
100
102
|
identifier: str,
|
|
101
|
-
register: Iterable[
|
|
102
|
-
base_operation:
|
|
103
|
+
register: Iterable[cirq.Qid],
|
|
104
|
+
base_operation: cirq.Operation,
|
|
103
105
|
exponent_sign: int,
|
|
104
106
|
):
|
|
105
107
|
if exponent_sign not in [-1, +1]:
|
|
@@ -113,7 +115,7 @@ class QuirkInputRotationOperation(ops.Operation):
|
|
|
113
115
|
return (self.identifier, self.register, self.base_operation, self.exponent_sign)
|
|
114
116
|
|
|
115
117
|
@property
|
|
116
|
-
def qubits(self) -> Tuple[
|
|
118
|
+
def qubits(self) -> Tuple[cirq.Qid, ...]:
|
|
117
119
|
return tuple(self.base_operation.qubits) + self.register
|
|
118
120
|
|
|
119
121
|
def with_qubits(self, *new_qubits):
|
|
@@ -127,7 +129,7 @@ class QuirkInputRotationOperation(ops.Operation):
|
|
|
127
129
|
self.exponent_sign,
|
|
128
130
|
)
|
|
129
131
|
|
|
130
|
-
def _circuit_diagram_info_(self, args:
|
|
132
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs):
|
|
131
133
|
sub_result = cirq.circuit_diagram_info(self.base_operation)
|
|
132
134
|
sign_char = '-' if self.exponent_sign == -1 else ''
|
|
133
135
|
symbols = list(sub_result.wire_symbols)
|
|
@@ -142,7 +144,7 @@ class QuirkInputRotationOperation(ops.Operation):
|
|
|
142
144
|
def _has_unitary_(self) -> bool:
|
|
143
145
|
return True
|
|
144
146
|
|
|
145
|
-
def _apply_unitary_(self, args:
|
|
147
|
+
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs):
|
|
146
148
|
transposed_args = args.with_axes_transposed_to_start()
|
|
147
149
|
|
|
148
150
|
target_axes = transposed_args.axes[: len(self.base_operation.qubits)]
|
|
@@ -184,7 +186,7 @@ def generate_all_input_rotation_cell_makers() -> Iterator[CellMaker]:
|
|
|
184
186
|
yield _input_rotation_gate("Z^(-A/2^n)", ops.Z, -1)
|
|
185
187
|
|
|
186
188
|
|
|
187
|
-
def _input_rotation_gate(identifier: str, gate:
|
|
189
|
+
def _input_rotation_gate(identifier: str, gate: cirq.Gate, exponent_sign: int) -> CellMaker:
|
|
188
190
|
return CellMaker(
|
|
189
191
|
identifier,
|
|
190
192
|
gate.num_qubits(),
|
|
@@ -11,6 +11,9 @@
|
|
|
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 __future__ import annotations
|
|
16
|
+
|
|
14
17
|
from typing import cast, Iterable, Iterator, Optional, TYPE_CHECKING
|
|
15
18
|
|
|
16
19
|
from cirq import ops
|
|
@@ -27,7 +30,7 @@ def generate_all_measurement_cell_makers() -> Iterator[CellMaker]:
|
|
|
27
30
|
yield _measurement("XDetector", basis_change=ops.Y**0.5)
|
|
28
31
|
|
|
29
32
|
|
|
30
|
-
def _measurement(identifier: str, basis_change: Optional[
|
|
33
|
+
def _measurement(identifier: str, basis_change: Optional[cirq.Gate] = None) -> CellMaker:
|
|
31
34
|
return CellMaker(
|
|
32
35
|
identifier=identifier,
|
|
33
36
|
size=1,
|