cirq-core 1.6.0.dev20250416035400__py3-none-any.whl → 1.6.0.dev20250417204649__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/study/resolver.py +1 -1
- {cirq_core-1.6.0.dev20250416035400.dist-info → cirq_core-1.6.0.dev20250417204649.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250416035400.dist-info → cirq_core-1.6.0.dev20250417204649.dist-info}/RECORD +58 -58
- {cirq_core-1.6.0.dev20250416035400.dist-info → cirq_core-1.6.0.dev20250417204649.dist-info}/WHEEL +0 -0
- {cirq_core-1.6.0.dev20250416035400.dist-info → cirq_core-1.6.0.dev20250417204649.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250416035400.dist-info → cirq_core-1.6.0.dev20250417204649.dist-info}/top_level.txt +0 -0
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Code for generating random quantum circuits."""
|
|
15
15
|
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
16
18
|
import dataclasses
|
|
17
19
|
import itertools
|
|
18
20
|
from typing import (
|
|
@@ -179,20 +181,20 @@ document(
|
|
|
179
181
|
|
|
180
182
|
|
|
181
183
|
def random_rotations_between_two_qubit_circuit(
|
|
182
|
-
q0:
|
|
183
|
-
q1:
|
|
184
|
+
q0: cirq.Qid,
|
|
185
|
+
q1: cirq.Qid,
|
|
184
186
|
depth: int,
|
|
185
187
|
two_qubit_op_factory: Callable[
|
|
186
|
-
[
|
|
188
|
+
[cirq.Qid, cirq.Qid, np.random.RandomState], cirq.OP_TREE
|
|
187
189
|
] = lambda a, b, _: ops.CZPowGate()(a, b),
|
|
188
|
-
single_qubit_gates: Sequence[
|
|
190
|
+
single_qubit_gates: Sequence[cirq.Gate] = (
|
|
189
191
|
ops.X**0.5,
|
|
190
192
|
ops.Y**0.5,
|
|
191
193
|
ops.PhasedXPowGate(phase_exponent=0.25, exponent=0.5),
|
|
192
194
|
),
|
|
193
195
|
add_final_single_qubit_layer: bool = True,
|
|
194
|
-
seed:
|
|
195
|
-
) ->
|
|
196
|
+
seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
197
|
+
) -> cirq.Circuit:
|
|
196
198
|
"""Generate a random two-qubit quantum circuit.
|
|
197
199
|
|
|
198
200
|
This construction uses a similar structure to those in the paper
|
|
@@ -243,14 +245,14 @@ def random_rotations_between_two_qubit_circuit(
|
|
|
243
245
|
|
|
244
246
|
def generate_library_of_2q_circuits(
|
|
245
247
|
n_library_circuits: int,
|
|
246
|
-
two_qubit_gate:
|
|
248
|
+
two_qubit_gate: cirq.Gate,
|
|
247
249
|
*,
|
|
248
250
|
max_cycle_depth: int = 100,
|
|
249
|
-
q0:
|
|
250
|
-
q1:
|
|
251
|
-
random_state:
|
|
251
|
+
q0: cirq.Qid = devices.LineQubit(0),
|
|
252
|
+
q1: cirq.Qid = devices.LineQubit(1),
|
|
253
|
+
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
252
254
|
tags: Sequence[Any] = (),
|
|
253
|
-
) -> List[
|
|
255
|
+
) -> List[cirq.Circuit]:
|
|
254
256
|
"""Generate a library of two-qubit Circuits.
|
|
255
257
|
|
|
256
258
|
For single-qubit gates, this uses PhasedXZGates where the axis-in-XY-plane is one
|
|
@@ -316,7 +318,7 @@ def _get_random_combinations(
|
|
|
316
318
|
n_combinations: int,
|
|
317
319
|
*,
|
|
318
320
|
pair_gen: Iterator[Tuple[List[QidPairT], Any]],
|
|
319
|
-
random_state:
|
|
321
|
+
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
320
322
|
) -> List[CircuitLibraryCombination]:
|
|
321
323
|
"""For qubit pairs, prepare a set of combinations to efficiently sample
|
|
322
324
|
parallel two-qubit XEB circuits.
|
|
@@ -366,7 +368,7 @@ def get_random_combinations_for_device(
|
|
|
366
368
|
device_graph: nx.Graph,
|
|
367
369
|
*,
|
|
368
370
|
pattern: Sequence[GridInteractionLayer] = HALF_GRID_STAGGERED_PATTERN,
|
|
369
|
-
random_state:
|
|
371
|
+
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
370
372
|
) -> List[CircuitLibraryCombination]:
|
|
371
373
|
"""For a given device, prepare a set of combinations to efficiently sample
|
|
372
374
|
parallel two-qubit XEB circuits.
|
|
@@ -420,7 +422,7 @@ def get_random_combinations_for_pairs(
|
|
|
420
422
|
n_library_circuits: int,
|
|
421
423
|
n_combinations: int,
|
|
422
424
|
all_pairs: List[List[QidPairT]],
|
|
423
|
-
random_state:
|
|
425
|
+
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
424
426
|
) -> List[CircuitLibraryCombination]:
|
|
425
427
|
"""For an explicit nested list of pairs, prepare a set of combinations to efficiently sample
|
|
426
428
|
parallel two-qubit XEB circuits.
|
|
@@ -460,7 +462,7 @@ def get_random_combinations_for_pairs(
|
|
|
460
462
|
)
|
|
461
463
|
|
|
462
464
|
|
|
463
|
-
def _pairs_from_moment(moment:
|
|
465
|
+
def _pairs_from_moment(moment: cirq.Moment) -> List[QidPairT]:
|
|
464
466
|
"""Helper function in `get_random_combinations_for_layer_circuit` pair generator.
|
|
465
467
|
|
|
466
468
|
The moment should contain only two qubit operations, which define a list of qubit pairs.
|
|
@@ -477,8 +479,8 @@ def _pairs_from_moment(moment: 'cirq.Moment') -> List[QidPairT]:
|
|
|
477
479
|
def get_random_combinations_for_layer_circuit(
|
|
478
480
|
n_library_circuits: int,
|
|
479
481
|
n_combinations: int,
|
|
480
|
-
layer_circuit:
|
|
481
|
-
random_state:
|
|
482
|
+
layer_circuit: cirq.Circuit,
|
|
483
|
+
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
482
484
|
) -> List[CircuitLibraryCombination]:
|
|
483
485
|
"""For a layer circuit, prepare a set of combinations to efficiently sample
|
|
484
486
|
parallel two-qubit XEB circuits.
|
|
@@ -523,7 +525,7 @@ def get_grid_interaction_layer_circuit(
|
|
|
523
525
|
device_graph: nx.Graph,
|
|
524
526
|
pattern: Sequence[GridInteractionLayer] = HALF_GRID_STAGGERED_PATTERN,
|
|
525
527
|
two_qubit_gate=ops.ISWAP**0.5,
|
|
526
|
-
) ->
|
|
528
|
+
) -> cirq.Circuit:
|
|
527
529
|
"""Create a circuit representation of a grid interaction pattern on a given device topology.
|
|
528
530
|
|
|
529
531
|
The resulting circuit is deterministic, of depth len(pattern), and consists of `two_qubit_gate`
|
|
@@ -547,21 +549,21 @@ def get_grid_interaction_layer_circuit(
|
|
|
547
549
|
|
|
548
550
|
|
|
549
551
|
def random_rotations_between_grid_interaction_layers_circuit(
|
|
550
|
-
qubits: Iterable[
|
|
552
|
+
qubits: Iterable[cirq.GridQubit],
|
|
551
553
|
depth: int,
|
|
552
554
|
*, # forces keyword arguments
|
|
553
555
|
two_qubit_op_factory: Callable[
|
|
554
|
-
[
|
|
556
|
+
[cirq.GridQubit, cirq.GridQubit, np.random.RandomState], cirq.OP_TREE
|
|
555
557
|
] = lambda a, b, _: ops.CZPowGate()(a, b),
|
|
556
558
|
pattern: Sequence[GridInteractionLayer] = GRID_STAGGERED_PATTERN,
|
|
557
|
-
single_qubit_gates: Sequence[
|
|
559
|
+
single_qubit_gates: Sequence[cirq.Gate] = (
|
|
558
560
|
ops.X**0.5,
|
|
559
561
|
ops.Y**0.5,
|
|
560
562
|
ops.PhasedXPowGate(phase_exponent=0.25, exponent=0.5),
|
|
561
563
|
),
|
|
562
564
|
add_final_single_qubit_layer: bool = True,
|
|
563
|
-
seed:
|
|
564
|
-
) ->
|
|
565
|
+
seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
566
|
+
) -> cirq.Circuit:
|
|
565
567
|
"""Generate a random quantum circuit of a particular form.
|
|
566
568
|
|
|
567
569
|
This construction is based on the circuits used in the paper
|
|
@@ -619,12 +621,12 @@ def random_rotations_between_grid_interaction_layers_circuit(
|
|
|
619
621
|
return circuit
|
|
620
622
|
|
|
621
623
|
|
|
622
|
-
def _coupled_qubit_pairs(qubits: List[
|
|
624
|
+
def _coupled_qubit_pairs(qubits: List[cirq.GridQubit]) -> List[GridQubitPairT]:
|
|
623
625
|
pairs = []
|
|
624
626
|
qubit_set = set(qubits)
|
|
625
627
|
for qubit in qubits:
|
|
626
628
|
|
|
627
|
-
def add_pair(neighbor:
|
|
629
|
+
def add_pair(neighbor: cirq.GridQubit):
|
|
628
630
|
if neighbor in qubit_set:
|
|
629
631
|
pairs.append((qubit, neighbor))
|
|
630
632
|
|
|
@@ -637,16 +639,16 @@ def _coupled_qubit_pairs(qubits: List['cirq.GridQubit']) -> List[GridQubitPairT]
|
|
|
637
639
|
class _RandomSingleQubitLayerFactory:
|
|
638
640
|
def __init__(
|
|
639
641
|
self,
|
|
640
|
-
qubits: Sequence[
|
|
641
|
-
single_qubit_gates: Sequence[
|
|
642
|
-
prng:
|
|
642
|
+
qubits: Sequence[cirq.Qid],
|
|
643
|
+
single_qubit_gates: Sequence[cirq.Gate],
|
|
644
|
+
prng: np.random.RandomState,
|
|
643
645
|
) -> None:
|
|
644
646
|
self.qubits = qubits
|
|
645
647
|
self.single_qubit_gates = single_qubit_gates
|
|
646
648
|
self.prng = prng
|
|
647
649
|
|
|
648
|
-
def new_layer(self, previous_single_qubit_layer:
|
|
649
|
-
def random_gate(qubit:
|
|
650
|
+
def new_layer(self, previous_single_qubit_layer: cirq.Moment) -> cirq.Moment:
|
|
651
|
+
def random_gate(qubit: cirq.Qid) -> cirq.Gate:
|
|
650
652
|
excluded_op = previous_single_qubit_layer.operation_at(qubit)
|
|
651
653
|
excluded_gate = excluded_op.gate if excluded_op is not None else None
|
|
652
654
|
g = self.single_qubit_gates[self.prng.randint(0, len(self.single_qubit_gates))]
|
|
@@ -658,10 +660,10 @@ class _RandomSingleQubitLayerFactory:
|
|
|
658
660
|
|
|
659
661
|
|
|
660
662
|
class _FixedSingleQubitLayerFactory:
|
|
661
|
-
def __init__(self, fixed_single_qubit_layer: Dict[
|
|
663
|
+
def __init__(self, fixed_single_qubit_layer: Dict[cirq.Qid, cirq.Gate]) -> None:
|
|
662
664
|
self.fixed_single_qubit_layer = fixed_single_qubit_layer
|
|
663
665
|
|
|
664
|
-
def new_layer(self, previous_single_qubit_layer:
|
|
666
|
+
def new_layer(self, previous_single_qubit_layer: cirq.Moment) -> cirq.Moment:
|
|
665
667
|
return circuits.Moment(v.on(q) for q, v in self.fixed_single_qubit_layer.items())
|
|
666
668
|
|
|
667
669
|
|
|
@@ -669,9 +671,7 @@ _SingleQubitLayerFactory = Union[_FixedSingleQubitLayerFactory, _RandomSingleQub
|
|
|
669
671
|
|
|
670
672
|
|
|
671
673
|
def _single_qubit_gates_arg_to_factory(
|
|
672
|
-
single_qubit_gates: Sequence[
|
|
673
|
-
qubits: Sequence['cirq.Qid'],
|
|
674
|
-
prng: 'np.random.RandomState',
|
|
674
|
+
single_qubit_gates: Sequence[cirq.Gate], qubits: Sequence[cirq.Qid], prng: np.random.RandomState
|
|
675
675
|
) -> _SingleQubitLayerFactory:
|
|
676
676
|
"""Parse the `single_qubit_gates` argument for circuit generation functions.
|
|
677
677
|
|
|
@@ -688,11 +688,11 @@ def _single_qubit_gates_arg_to_factory(
|
|
|
688
688
|
def _two_qubit_layer(
|
|
689
689
|
coupled_qubit_pairs: List[GridQubitPairT],
|
|
690
690
|
two_qubit_op_factory: Callable[
|
|
691
|
-
[
|
|
691
|
+
[cirq.GridQubit, cirq.GridQubit, np.random.RandomState], cirq.OP_TREE
|
|
692
692
|
],
|
|
693
693
|
layer: GridInteractionLayer,
|
|
694
|
-
prng:
|
|
695
|
-
) -> Iterator[
|
|
694
|
+
prng: np.random.RandomState,
|
|
695
|
+
) -> Iterator[cirq.OP_TREE]:
|
|
696
696
|
for a, b in coupled_qubit_pairs:
|
|
697
697
|
if (a, b) in layer or (b, a) in layer:
|
|
698
698
|
yield two_qubit_op_factory(a, b, prng)
|
|
@@ -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 itertools
|
|
15
18
|
from typing import Callable, cast, Dict, Iterable, List, Optional, Sequence, Set, Tuple
|
|
16
19
|
|
|
@@ -366,7 +369,7 @@ def test_random_rotations_between_grid_interaction_layers(
|
|
|
366
369
|
pattern: Sequence[GridInteractionLayer],
|
|
367
370
|
single_qubit_gates: Sequence[cirq.Gate],
|
|
368
371
|
add_final_single_qubit_layer: bool,
|
|
369
|
-
seed:
|
|
372
|
+
seed: cirq.RANDOM_STATE_OR_SEED_LIKE,
|
|
370
373
|
expected_circuit_length: int,
|
|
371
374
|
single_qubit_layers_slice: slice,
|
|
372
375
|
two_qubit_layers_slice: slice,
|
|
@@ -444,12 +447,12 @@ def _validate_two_qubit_layers(
|
|
|
444
447
|
|
|
445
448
|
|
|
446
449
|
def _coupled_qubit_pairs(
|
|
447
|
-
qubits: Set[
|
|
448
|
-
) -> List[Tuple[
|
|
450
|
+
qubits: Set[cirq.GridQubit],
|
|
451
|
+
) -> List[Tuple[cirq.GridQubit, cirq.GridQubit]]:
|
|
449
452
|
pairs = []
|
|
450
453
|
for qubit in qubits:
|
|
451
454
|
|
|
452
|
-
def add_pair(neighbor:
|
|
455
|
+
def add_pair(neighbor: cirq.GridQubit):
|
|
453
456
|
if neighbor in qubits:
|
|
454
457
|
pairs.append((qubit, neighbor))
|
|
455
458
|
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Utilities to compute readout confusion matrix and use it for readout error mitigation."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
import time
|
|
18
20
|
from typing import Any, cast, Dict, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
|
|
19
21
|
|
|
@@ -60,7 +62,7 @@ class TensoredConfusionMatrices:
|
|
|
60
62
|
def __init__(
|
|
61
63
|
self,
|
|
62
64
|
confusion_matrices: Union[np.ndarray, Sequence[np.ndarray]],
|
|
63
|
-
measure_qubits: Union[Sequence[
|
|
65
|
+
measure_qubits: Union[Sequence[cirq.Qid], Sequence[Sequence[cirq.Qid]]],
|
|
64
66
|
*,
|
|
65
67
|
repetitions: int,
|
|
66
68
|
timestamp: float,
|
|
@@ -112,14 +114,14 @@ class TensoredConfusionMatrices:
|
|
|
112
114
|
self._measure_qubits = tuple(tuple(q) for q in measure_qubits)
|
|
113
115
|
self._qubits = tuple(sorted(set(q for ql in measure_qubits for q in ql)))
|
|
114
116
|
self._qubits_to_idx = {q: i for i, q in enumerate(self._qubits)}
|
|
115
|
-
self._cache: Dict[Tuple[
|
|
117
|
+
self._cache: Dict[Tuple[cirq.Qid, ...], np.ndarray] = {}
|
|
116
118
|
if sum(len(q) for q in self._measure_qubits) != len(self._qubits):
|
|
117
119
|
raise ValueError(f"Repeated qubits not allowed in measure_qubits: {measure_qubits}.")
|
|
118
120
|
|
|
119
121
|
@classmethod
|
|
120
122
|
def from_measurement(
|
|
121
|
-
cls, gate: ops.MeasurementGate, qubits: Sequence[
|
|
122
|
-
) ->
|
|
123
|
+
cls, gate: ops.MeasurementGate, qubits: Sequence[cirq.Qid]
|
|
124
|
+
) -> TensoredConfusionMatrices:
|
|
123
125
|
"""Generates TCM for the confusion map in a MeasurementGate.
|
|
124
126
|
|
|
125
127
|
This ignores any invert_mask defined for the gate - it only replicates the confusion map.
|
|
@@ -160,21 +162,21 @@ class TensoredConfusionMatrices:
|
|
|
160
162
|
return self._confusion_matrices
|
|
161
163
|
|
|
162
164
|
@property
|
|
163
|
-
def measure_qubits(self) -> Tuple[Tuple[
|
|
165
|
+
def measure_qubits(self) -> Tuple[Tuple[cirq.Qid, ...], ...]:
|
|
164
166
|
"""Calibrated qubit pattern for which individual confusion matrices were computed."""
|
|
165
167
|
return self._measure_qubits
|
|
166
168
|
|
|
167
169
|
@property
|
|
168
|
-
def qubits(self) -> Tuple[
|
|
170
|
+
def qubits(self) -> Tuple[cirq.Qid, ...]:
|
|
169
171
|
"""Sorted list of all calibrated qubits."""
|
|
170
172
|
return self._qubits
|
|
171
173
|
|
|
172
|
-
def _get_vars(self, qubit_pattern: Sequence[
|
|
174
|
+
def _get_vars(self, qubit_pattern: Sequence[cirq.Qid]) -> List[int]:
|
|
173
175
|
in_vars = [2 * self._qubits_to_idx[q] for q in qubit_pattern]
|
|
174
176
|
out_vars = [2 * self._qubits_to_idx[q] + 1 for q in qubit_pattern]
|
|
175
177
|
return in_vars + out_vars
|
|
176
178
|
|
|
177
|
-
def _confusion_matrix(self, qubits: Sequence[
|
|
179
|
+
def _confusion_matrix(self, qubits: Sequence[cirq.Qid]) -> np.ndarray:
|
|
178
180
|
ein_input: List[np.ndarray | List[int]] = []
|
|
179
181
|
for qs, cm in zip(self.measure_qubits, self.confusion_matrices):
|
|
180
182
|
ein_input.extend([cm.reshape((2, 2) * len(qs)), self._get_vars(qs)])
|
|
@@ -183,7 +185,7 @@ class TensoredConfusionMatrices:
|
|
|
183
185
|
ret = np.einsum(*ein_input, ein_out).reshape((2 ** len(qubits),) * 2)
|
|
184
186
|
return ret / ret.sum(axis=1)
|
|
185
187
|
|
|
186
|
-
def confusion_matrix(self, qubits: Optional[Sequence[
|
|
188
|
+
def confusion_matrix(self, qubits: Optional[Sequence[cirq.Qid]] = None) -> np.ndarray:
|
|
187
189
|
"""Returns a single confusion matrix constructed for the given set of qubits.
|
|
188
190
|
|
|
189
191
|
The single `2 ** len(qubits) x 2 ** len(qubits)` confusion matrix is constructed
|
|
@@ -211,7 +213,7 @@ class TensoredConfusionMatrices:
|
|
|
211
213
|
self._cache[key] = self._confusion_matrix(qubits)
|
|
212
214
|
return self._cache[key]
|
|
213
215
|
|
|
214
|
-
def correction_matrix(self, qubits: Optional[Sequence[
|
|
216
|
+
def correction_matrix(self, qubits: Optional[Sequence[cirq.Qid]] = None) -> np.ndarray:
|
|
215
217
|
"""Returns a single correction matrix constructed for the given set of qubits.
|
|
216
218
|
|
|
217
219
|
A correction matrix is the inverse of confusion matrix and can be used to apply corrections
|
|
@@ -240,7 +242,7 @@ class TensoredConfusionMatrices:
|
|
|
240
242
|
def apply(
|
|
241
243
|
self,
|
|
242
244
|
result: np.ndarray,
|
|
243
|
-
qubits: Optional[Sequence[
|
|
245
|
+
qubits: Optional[Sequence[cirq.Qid]] = None,
|
|
244
246
|
*,
|
|
245
247
|
method='least_squares',
|
|
246
248
|
) -> np.ndarray:
|
|
@@ -300,7 +302,7 @@ class TensoredConfusionMatrices:
|
|
|
300
302
|
return res.x
|
|
301
303
|
|
|
302
304
|
def readout_mitigation_pauli_uncorrelated(
|
|
303
|
-
self, qubits: Sequence[
|
|
305
|
+
self, qubits: Sequence[cirq.Qid], measured_bitstrings: np.ndarray
|
|
304
306
|
) -> tuple[float, float]:
|
|
305
307
|
r"""Uncorrelated readout error mitigation for a multi-qubit Pauli operator.
|
|
306
308
|
|
|
@@ -384,7 +386,7 @@ class TensoredConfusionMatrices:
|
|
|
384
386
|
@classmethod
|
|
385
387
|
def _from_json_dict_(
|
|
386
388
|
cls, confusion_matrices, measure_qubits, repetitions, timestamp, **kwargs
|
|
387
|
-
) ->
|
|
389
|
+
) -> TensoredConfusionMatrices:
|
|
388
390
|
return cls(
|
|
389
391
|
[np.asarray(cm) for cm in confusion_matrices],
|
|
390
392
|
measure_qubits,
|
|
@@ -423,8 +425,8 @@ class TensoredConfusionMatrices:
|
|
|
423
425
|
|
|
424
426
|
|
|
425
427
|
def measure_confusion_matrix(
|
|
426
|
-
sampler:
|
|
427
|
-
qubits: Union[Sequence[
|
|
428
|
+
sampler: cirq.Sampler,
|
|
429
|
+
qubits: Union[Sequence[cirq.Qid], Sequence[Sequence[cirq.Qid]]],
|
|
428
430
|
repetitions: int = 1000,
|
|
429
431
|
) -> TensoredConfusionMatrices:
|
|
430
432
|
"""Prepares `TensoredConfusionMatrices` for the n qubits in the input.
|
|
@@ -11,7 +11,11 @@
|
|
|
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
|
+
|
|
14
15
|
"""Single qubit readout experiments using parallel or isolated statistics."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
15
19
|
import dataclasses
|
|
16
20
|
import time
|
|
17
21
|
from typing import Any, cast, Dict, Iterable, List, Optional, TYPE_CHECKING
|
|
@@ -43,8 +47,8 @@ class SingleQubitReadoutCalibrationResult:
|
|
|
43
47
|
timestamp: The time the data was taken, in seconds since the epoch.
|
|
44
48
|
"""
|
|
45
49
|
|
|
46
|
-
zero_state_errors: Dict[
|
|
47
|
-
one_state_errors: Dict[
|
|
50
|
+
zero_state_errors: Dict[cirq.Qid, float]
|
|
51
|
+
one_state_errors: Dict[cirq.Qid, float]
|
|
48
52
|
repetitions: int
|
|
49
53
|
timestamp: float
|
|
50
54
|
|
|
@@ -197,7 +201,7 @@ class SingleQubitReadoutCalibrationResult:
|
|
|
197
201
|
|
|
198
202
|
|
|
199
203
|
def estimate_single_qubit_readout_errors(
|
|
200
|
-
sampler:
|
|
204
|
+
sampler: cirq.Sampler, *, qubits: Iterable[cirq.Qid], repetitions: int = 1000
|
|
201
205
|
) -> SingleQubitReadoutCalibrationResult:
|
|
202
206
|
"""Estimate single-qubit readout error.
|
|
203
207
|
|
|
@@ -229,9 +233,9 @@ def estimate_single_qubit_readout_errors(
|
|
|
229
233
|
|
|
230
234
|
|
|
231
235
|
def estimate_parallel_single_qubit_readout_errors(
|
|
232
|
-
sampler:
|
|
236
|
+
sampler: cirq.Sampler,
|
|
233
237
|
*,
|
|
234
|
-
qubits: Iterable[
|
|
238
|
+
qubits: Iterable[cirq.Qid],
|
|
235
239
|
trials: int = 20,
|
|
236
240
|
repetitions: int = 1000,
|
|
237
241
|
trials_per_batch: Optional[int] = None,
|
|
@@ -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 Sequence
|
|
15
18
|
|
|
16
19
|
import numpy as np
|
|
@@ -30,7 +33,7 @@ def test_single_qubit_readout_result_repr():
|
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
class NoisySingleQubitReadoutSampler(cirq.Sampler):
|
|
33
|
-
def __init__(self, p0: float, p1: float, seed:
|
|
36
|
+
def __init__(self, p0: float, p1: float, seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None):
|
|
34
37
|
"""Sampler that flips some bits upon readout.
|
|
35
38
|
|
|
36
39
|
Args:
|
|
@@ -44,7 +47,7 @@ class NoisySingleQubitReadoutSampler(cirq.Sampler):
|
|
|
44
47
|
self.simulator = cirq.Simulator(seed=self.prng, split_untangled_states=False)
|
|
45
48
|
|
|
46
49
|
def run_sweep(
|
|
47
|
-
self, program:
|
|
50
|
+
self, program: cirq.AbstractCircuit, params: cirq.Sweepable, repetitions: int = 1
|
|
48
51
|
) -> Sequence[cirq.Result]:
|
|
49
52
|
results = self.simulator.run_sweep(program, params, repetitions)
|
|
50
53
|
for result in results:
|
|
@@ -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
|
import warnings
|
|
16
18
|
from typing import Any, cast, Optional, Sequence, TYPE_CHECKING
|
|
17
19
|
|
|
@@ -31,14 +33,14 @@ optimize = _import.LazyLoader("optimize", globals(), "scipy.optimize")
|
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
def t1_decay(
|
|
34
|
-
sampler:
|
|
36
|
+
sampler: cirq.Sampler,
|
|
35
37
|
*,
|
|
36
|
-
qubit:
|
|
38
|
+
qubit: cirq.Qid,
|
|
37
39
|
num_points: int,
|
|
38
|
-
max_delay:
|
|
39
|
-
min_delay:
|
|
40
|
+
max_delay: cirq.DURATION_LIKE,
|
|
41
|
+
min_delay: cirq.DURATION_LIKE = None,
|
|
40
42
|
repetitions: int = 1000,
|
|
41
|
-
) ->
|
|
43
|
+
) -> cirq.experiments.T1DecayResult:
|
|
42
44
|
"""Runs a t1 decay experiment.
|
|
43
45
|
|
|
44
46
|
Initializes a qubit into the |1⟩ state, waits for a variable amount of time,
|
|
@@ -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 enum
|
|
15
18
|
from typing import Any, List, Optional, TYPE_CHECKING, Union
|
|
16
19
|
|
|
@@ -35,17 +38,17 @@ _T2_COLUMNS = ['delay_ns', 0, 1]
|
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
def t2_decay(
|
|
38
|
-
sampler:
|
|
41
|
+
sampler: cirq.Sampler,
|
|
39
42
|
*,
|
|
40
|
-
qubit:
|
|
41
|
-
experiment_type:
|
|
43
|
+
qubit: cirq.Qid,
|
|
44
|
+
experiment_type: ExperimentType = ExperimentType.RAMSEY,
|
|
42
45
|
num_points: int,
|
|
43
|
-
max_delay:
|
|
44
|
-
min_delay:
|
|
46
|
+
max_delay: cirq.DURATION_LIKE,
|
|
47
|
+
min_delay: cirq.DURATION_LIKE = None,
|
|
45
48
|
repetitions: int = 1000,
|
|
46
49
|
delay_sweep: Optional[study.Sweep] = None,
|
|
47
50
|
num_pulses: Optional[List[int]] = None,
|
|
48
|
-
) -> Union[
|
|
51
|
+
) -> Union[cirq.experiments.T2DecayResult, List[cirq.experiments.T2DecayResult]]:
|
|
49
52
|
"""Runs a t2 transverse relaxation experiment.
|
|
50
53
|
|
|
51
54
|
Initializes a qubit into a superposition state, evolves the system using
|
|
@@ -234,7 +237,7 @@ def _create_tabulation(measurements: pd.DataFrame) -> pd.DataFrame:
|
|
|
234
237
|
return tabulation
|
|
235
238
|
|
|
236
239
|
|
|
237
|
-
def _cpmg_circuit(qubit:
|
|
240
|
+
def _cpmg_circuit(qubit: cirq.Qid, delay_var: sympy.Symbol, max_pulses: int) -> cirq.Circuit:
|
|
238
241
|
"""Creates a CPMG circuit for a given qubit.
|
|
239
242
|
|
|
240
243
|
The circuit will look like:
|