cirq-core 1.5.0.dev20241105235147__py3-none-any.whl → 1.5.0.dev20241108000946__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cirq-core might be problematic. Click here for more details.

cirq/_version.py CHANGED
@@ -28,4 +28,4 @@ if sys.version_info < (3, 10, 0): # pragma: no cover
28
28
  'of cirq (e.g. "python -m pip install cirq==1.1.*")'
29
29
  )
30
30
 
31
- __version__ = "1.5.0.dev20241105235147"
31
+ __version__ = "1.5.0.dev20241108000946"
cirq/_version_test.py CHANGED
@@ -3,4 +3,4 @@ import cirq
3
3
 
4
4
 
5
5
  def test_version():
6
- assert cirq.__version__ == "1.5.0.dev20241105235147"
6
+ assert cirq.__version__ == "1.5.0.dev20241108000946"
@@ -82,3 +82,9 @@ from cirq.experiments.two_qubit_xeb import (
82
82
  parallel_two_qubit_xeb as parallel_two_qubit_xeb,
83
83
  run_rb_and_xeb as run_rb_and_xeb,
84
84
  )
85
+
86
+
87
+ from cirq.experiments.z_phase_calibration import (
88
+ z_phase_calibration_workflow as z_phase_calibration_workflow,
89
+ calibrate_z_phases as calibrate_z_phases,
90
+ )
@@ -38,6 +38,7 @@ from cirq.qis import noise_utils
38
38
  from cirq._compat import cached_method
39
39
 
40
40
  if TYPE_CHECKING:
41
+ import multiprocessing
41
42
  import cirq
42
43
 
43
44
 
@@ -358,6 +359,7 @@ def parallel_xeb_workflow(
358
359
  cycle_depths: Sequence[int] = (5, 25, 50, 100, 200, 300),
359
360
  random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
360
361
  ax: Optional[plt.Axes] = None,
362
+ pool: Optional['multiprocessing.pool.Pool'] = None,
361
363
  **plot_kwargs,
362
364
  ) -> Tuple[pd.DataFrame, Sequence['cirq.Circuit'], pd.DataFrame]:
363
365
  """A utility method that runs the full XEB workflow.
@@ -373,6 +375,7 @@ def parallel_xeb_workflow(
373
375
  random_state: The random state to use.
374
376
  ax: the plt.Axes to plot the device layout on. If not given,
375
377
  no plot is created.
378
+ pool: An optional multiprocessing pool.
376
379
  **plot_kwargs: Arguments to be passed to 'plt.Axes.plot'.
377
380
 
378
381
  Returns:
@@ -426,7 +429,7 @@ def parallel_xeb_workflow(
426
429
  )
427
430
 
428
431
  fids = benchmark_2q_xeb_fidelities(
429
- sampled_df=sampled_df, circuits=circuit_library, cycle_depths=cycle_depths
432
+ sampled_df=sampled_df, circuits=circuit_library, cycle_depths=cycle_depths, pool=pool
430
433
  )
431
434
 
432
435
  return fids, circuit_library, sampled_df
@@ -95,6 +95,11 @@ def benchmark_2q_xeb_fidelities(
95
95
  df['e_u'] = np.sum(pure_probs**2, axis=1)
96
96
  df['u_u'] = np.sum(pure_probs, axis=1) / D
97
97
  df['m_u'] = np.sum(pure_probs * sampled_probs, axis=1)
98
+ # Var[m_u] = Var[sum p(x) * p_sampled(x)]
99
+ # = sum p(x)^2 Var[p_sampled(x)]
100
+ # = sum p(x)^2 p(x) (1 - p(x))
101
+ # = sum p(x)^3 (1 - p(x))
102
+ df['var_m_u'] = np.sum(pure_probs**3 * (1 - pure_probs), axis=1)
98
103
  df['y'] = df['m_u'] - df['u_u']
99
104
  df['x'] = df['e_u'] - df['u_u']
100
105
  df['numerator'] = df['x'] * df['y']
@@ -103,7 +108,11 @@ def benchmark_2q_xeb_fidelities(
103
108
  def per_cycle_depth(df):
104
109
  """This function is applied per cycle_depth in the following groupby aggregation."""
105
110
  fid_lsq = df['numerator'].sum() / df['denominator'].sum()
106
- ret = {'fidelity': fid_lsq}
111
+ # Note: both df['denominator'] and df['x'] are constants.
112
+ # Var[f] = Var[df['numerator']] / (sum df['denominator'])^2
113
+ # = sum (df['x']^2 * df['var_m_u']) / (sum df['denominator'])^2
114
+ var_fid = (df['var_m_u'] * df['x'] ** 2).sum() / df['denominator'].sum() ** 2
115
+ ret = {'fidelity': fid_lsq, 'fidelity_variance': var_fid}
107
116
 
108
117
  def _try_keep(k):
109
118
  """If all the values for a key `k` are the same in this group, we can keep it."""
@@ -385,16 +394,21 @@ def SqrtISwapXEBOptions(*args, **kwargs):
385
394
 
386
395
 
387
396
  def parameterize_circuit(
388
- circuit: 'cirq.Circuit', options: XEBCharacterizationOptions
397
+ circuit: 'cirq.Circuit',
398
+ options: XEBCharacterizationOptions,
399
+ target_gatefamily: Optional[ops.GateFamily] = None,
389
400
  ) -> 'cirq.Circuit':
390
401
  """Parameterize PhasedFSim-like gates in a given circuit according to
391
402
  `phased_fsim_options`.
392
403
  """
404
+ if isinstance(target_gatefamily, ops.GateFamily):
405
+ should_parameterize = lambda op: op in target_gatefamily or options.should_parameterize(op)
406
+ else:
407
+ should_parameterize = options.should_parameterize
393
408
  gate = options.get_parameterized_gate()
394
409
  return circuits.Circuit(
395
410
  circuits.Moment(
396
- gate.on(*op.qubits) if options.should_parameterize(op) else op
397
- for op in moment.operations
411
+ gate.on(*op.qubits) if should_parameterize(op) else op for op in moment.operations
398
412
  )
399
413
  for moment in circuit.moments
400
414
  )
@@ -667,13 +681,16 @@ def fit_exponential_decays(fidelities_df: pd.DataFrame) -> pd.DataFrame:
667
681
  a, layer_fid, a_std, layer_fid_std = _fit_exponential_decay(
668
682
  f1['cycle_depth'], f1['fidelity']
669
683
  )
684
+ fidelity_variance = 0
685
+ if 'fidelity_variance' in f1:
686
+ fidelity_variance = f1['fidelity_variance'].values
670
687
  record = {
671
688
  'a': a,
672
689
  'layer_fid': layer_fid,
673
690
  'cycle_depths': f1['cycle_depth'].values,
674
691
  'fidelities': f1['fidelity'].values,
675
692
  'a_std': a_std,
676
- 'layer_fid_std': layer_fid_std,
693
+ 'layer_fid_std': np.sqrt(layer_fid_std**2 + fidelity_variance),
677
694
  }
678
695
  return pd.Series(record)
679
696
 
@@ -0,0 +1,273 @@
1
+ # Copyright 2024 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Provides a method to do z-phase calibration for excitation-preserving gates."""
16
+ from typing import Union, Optional, Sequence, Tuple, Dict, TYPE_CHECKING
17
+ import multiprocessing
18
+ import multiprocessing.pool
19
+
20
+ import matplotlib.pyplot as plt
21
+ import numpy as np
22
+
23
+ from cirq.experiments import xeb_fitting
24
+ from cirq.experiments.two_qubit_xeb import parallel_xeb_workflow
25
+ from cirq import ops
26
+
27
+ if TYPE_CHECKING:
28
+ import cirq
29
+ import pandas as pd
30
+
31
+
32
+ def z_phase_calibration_workflow(
33
+ sampler: 'cirq.Sampler',
34
+ qubits: Optional[Sequence['cirq.GridQubit']] = None,
35
+ two_qubit_gate: 'cirq.Gate' = ops.CZ,
36
+ options: Optional[xeb_fitting.XEBPhasedFSimCharacterizationOptions] = None,
37
+ n_repetitions: int = 10**4,
38
+ n_combinations: int = 10,
39
+ n_circuits: int = 20,
40
+ cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
41
+ random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
42
+ atol: float = 1e-3,
43
+ num_workers_or_pool: Union[int, 'multiprocessing.pool.Pool'] = -1,
44
+ ) -> Tuple[xeb_fitting.XEBCharacterizationResult, 'pd.DataFrame']:
45
+ """Perform z-phase calibration for excitation-preserving gates.
46
+
47
+ For a given excitation-preserving two-qubit gate we assume an error model that can be described
48
+ using Z-rotations:
49
+ 0: ───Rz(a)───two_qubit_gate───Rz(c)───
50
+
51
+ 1: ───Rz(b)───two_qubit_gate───Rz(d)───
52
+ for some angles a, b, c, and d.
53
+
54
+ Since the two-qubit gate is a excitation-preserving-gate, it can be represented by an FSimGate
55
+ and the effect of rotations turns it into a PhasedFSimGate. Using XEB-data we find the
56
+ PhasedFSimGate parameters that minimize the infidelity of the gate.
57
+
58
+ References:
59
+ - https://arxiv.org/abs/2001.08343
60
+ - https://arxiv.org/abs/2010.07965
61
+ - https://arxiv.org/abs/1910.11333
62
+
63
+ Args:
64
+ sampler: The quantum engine or simulator to run the circuits.
65
+ qubits: Qubits to use. If none, use all qubits on the sampler's device.
66
+ two_qubit_gate: The entangling gate to use.
67
+ options: The XEB-fitting options. If None, calibrate only the three phase angles
68
+ (chi, gamma, zeta) using the representation of a two-qubit gate as an FSimGate
69
+ for the initial guess.
70
+ n_repetitions: The number of repetitions to use.
71
+ n_combinations: The number of combinations to generate.
72
+ n_circuits: The number of circuits to generate.
73
+ cycle_depths: The cycle depths to use.
74
+ random_state: The random state to use.
75
+ atol: Absolute tolerance to be used by the minimizer.
76
+ num_workers_or_pool: An optional multi-processing pool or number of workers.
77
+ A zero value means no multiprocessing.
78
+ A positive integer value will create a pool with the given number of workers.
79
+ A negative value will create pool with maximum number of workers.
80
+ Returns:
81
+ - An `XEBCharacterizationResult` object that contains the calibration result.
82
+ - A `pd.DataFrame` comparing the before and after fidelities.
83
+ """
84
+
85
+ pool: Optional['multiprocessing.pool.Pool'] = None
86
+ local_pool = False
87
+ if isinstance(num_workers_or_pool, multiprocessing.pool.Pool):
88
+ pool = num_workers_or_pool # pragma: no cover
89
+ elif num_workers_or_pool != 0:
90
+ pool = multiprocessing.Pool(num_workers_or_pool if num_workers_or_pool > 0 else None)
91
+ local_pool = True
92
+
93
+ fids_df_0, circuits, sampled_df = parallel_xeb_workflow(
94
+ sampler=sampler,
95
+ qubits=qubits,
96
+ entangling_gate=two_qubit_gate,
97
+ n_repetitions=n_repetitions,
98
+ cycle_depths=cycle_depths,
99
+ n_circuits=n_circuits,
100
+ n_combinations=n_combinations,
101
+ random_state=random_state,
102
+ pool=pool,
103
+ )
104
+
105
+ if options is None:
106
+ options = xeb_fitting.XEBPhasedFSimCharacterizationOptions(
107
+ characterize_chi=True,
108
+ characterize_gamma=True,
109
+ characterize_zeta=True,
110
+ characterize_theta=False,
111
+ characterize_phi=False,
112
+ ).with_defaults_from_gate(two_qubit_gate)
113
+
114
+ p_circuits = [
115
+ xeb_fitting.parameterize_circuit(circuit, options, ops.GateFamily(two_qubit_gate))
116
+ for circuit in circuits
117
+ ]
118
+
119
+ result = xeb_fitting.characterize_phased_fsim_parameters_with_xeb_by_pair(
120
+ sampled_df=sampled_df,
121
+ parameterized_circuits=p_circuits,
122
+ cycle_depths=cycle_depths,
123
+ options=options,
124
+ fatol=atol,
125
+ xatol=atol,
126
+ pool=pool,
127
+ )
128
+
129
+ before_after = xeb_fitting.before_and_after_characterization(
130
+ fids_df_0, characterization_result=result
131
+ )
132
+
133
+ if local_pool:
134
+ assert isinstance(pool, multiprocessing.pool.Pool)
135
+ pool.close()
136
+ return result, before_after
137
+
138
+
139
+ def calibrate_z_phases(
140
+ sampler: 'cirq.Sampler',
141
+ qubits: Optional[Sequence['cirq.GridQubit']] = None,
142
+ two_qubit_gate: 'cirq.Gate' = ops.CZ,
143
+ options: Optional[xeb_fitting.XEBPhasedFSimCharacterizationOptions] = None,
144
+ n_repetitions: int = 10**4,
145
+ n_combinations: int = 10,
146
+ n_circuits: int = 20,
147
+ cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
148
+ random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
149
+ atol: float = 1e-3,
150
+ num_workers_or_pool: Union[int, 'multiprocessing.pool.Pool'] = -1,
151
+ ) -> Dict[Tuple['cirq.Qid', 'cirq.Qid'], 'cirq.PhasedFSimGate']:
152
+ """Perform z-phase calibration for excitation-preserving gates.
153
+
154
+ For a given excitation-preserving two-qubit gate we assume an error model that can be described
155
+ using Z-rotations:
156
+ 0: ───Rz(a)───two_qubit_gate───Rz(c)───
157
+
158
+ 1: ───Rz(b)───two_qubit_gate───Rz(d)───
159
+ for some angles a, b, c, and d.
160
+
161
+ Since the two-qubit gate is a excitation-preserving gate, it can be represented by an FSimGate
162
+ and the effect of rotations turns it into a PhasedFSimGate. Using XEB-data we find the
163
+ PhasedFSimGate parameters that minimize the infidelity of the gate.
164
+
165
+ References:
166
+ - https://arxiv.org/abs/2001.08343
167
+ - https://arxiv.org/abs/2010.07965
168
+ - https://arxiv.org/abs/1910.11333
169
+
170
+ Args:
171
+ sampler: The quantum engine or simulator to run the circuits.
172
+ qubits: Qubits to use. If none, use all qubits on the sampler's device.
173
+ two_qubit_gate: The entangling gate to use.
174
+ options: The XEB-fitting options. If None, calibrate only the three phase angles
175
+ (chi, gamma, zeta) using the representation of a two-qubit gate as an FSimGate
176
+ for the initial guess.
177
+ n_repetitions: The number of repetitions to use.
178
+ n_combinations: The number of combinations to generate.
179
+ n_circuits: The number of circuits to generate.
180
+ cycle_depths: The cycle depths to use.
181
+ random_state: The random state to use.
182
+ atol: Absolute tolerance to be used by the minimizer.
183
+ num_workers_or_pool: An optional multi-processing pool or number of workers.
184
+ A zero value means no multiprocessing.
185
+ A positive integer value will create a pool with the given number of workers.
186
+ A negative value will create pool with maximum number of workers.
187
+
188
+ Returns:
189
+ - A dictionary mapping qubit pairs to the calibrated PhasedFSimGates.
190
+ """
191
+
192
+ if options is None:
193
+ options = xeb_fitting.XEBPhasedFSimCharacterizationOptions(
194
+ characterize_chi=True,
195
+ characterize_gamma=True,
196
+ characterize_zeta=True,
197
+ characterize_theta=False,
198
+ characterize_phi=False,
199
+ ).with_defaults_from_gate(two_qubit_gate)
200
+
201
+ result, _ = z_phase_calibration_workflow(
202
+ sampler=sampler,
203
+ qubits=qubits,
204
+ two_qubit_gate=two_qubit_gate,
205
+ options=options,
206
+ n_repetitions=n_repetitions,
207
+ n_combinations=n_combinations,
208
+ n_circuits=n_circuits,
209
+ cycle_depths=cycle_depths,
210
+ random_state=random_state,
211
+ atol=atol,
212
+ num_workers_or_pool=num_workers_or_pool,
213
+ )
214
+
215
+ gates = {}
216
+ for pair, params in result.final_params.items():
217
+ params['theta'] = params.get('theta', options.theta_default or 0)
218
+ params['phi'] = params.get('phi', options.phi_default or 0)
219
+ params['zeta'] = params.get('zeta', options.zeta_default or 0)
220
+ params['chi'] = params.get('chi', options.chi_default or 0)
221
+ params['gamma'] = params.get('gamma', options.gamma_default or 0)
222
+ gates[pair] = ops.PhasedFSimGate(**params)
223
+ return gates
224
+
225
+
226
+ def plot_z_phase_calibration_result(
227
+ before_after_df: 'pd.DataFrame',
228
+ axes: Optional[np.ndarray[Sequence[Sequence['plt.Axes']], np.dtype[np.object_]]] = None,
229
+ pairs: Optional[Sequence[Tuple['cirq.Qid', 'cirq.Qid']]] = None,
230
+ *,
231
+ with_error_bars: bool = False,
232
+ ) -> np.ndarray[Sequence[Sequence['plt.Axes']], np.dtype[np.object_]]:
233
+ """A helper method to plot the result of running z-phase calibration.
234
+
235
+ Note that the plotted fidelity is a statistical estimate of the true fidelity and as a result
236
+ may be outside the [0, 1] range.
237
+
238
+ Args:
239
+ before_after_df: The second return object of running `z_phase_calibration_workflow`.
240
+ axes: And ndarray of the axes to plot on.
241
+ The number of axes is expected to be >= number of qubit pairs.
242
+ pairs: If provided, only the given pairs are plotted.
243
+ with_error_bars: Whether to add error bars or not.
244
+ The width of the bar is an upper bound on standard variation of the estimated fidelity.
245
+ """
246
+ if pairs is None:
247
+ pairs = before_after_df.index
248
+ if axes is None:
249
+ # Create a 16x9 rectangle.
250
+ ncols = int(np.ceil(np.sqrt(9 / 16 * len(pairs))))
251
+ nrows = (len(pairs) + ncols - 1) // ncols
252
+ _, axes = plt.subplots(nrows=nrows, ncols=ncols)
253
+ axes = axes if isinstance(axes, np.ndarray) else np.array(axes)
254
+ for pair, ax in zip(pairs, axes.flatten()):
255
+ row = before_after_df.loc[[pair]].iloc[0]
256
+ ax.errorbar(
257
+ row.cycle_depths_0,
258
+ row.fidelities_0,
259
+ yerr=row.layer_fid_std_0 * with_error_bars,
260
+ label='original',
261
+ )
262
+ ax.errorbar(
263
+ row.cycle_depths_0,
264
+ row.fidelities_c,
265
+ yerr=row.layer_fid_std_c * with_error_bars,
266
+ label='calibrated',
267
+ )
268
+ ax.axhline(1, linestyle='--')
269
+ ax.set_xlabel('cycle depth')
270
+ ax.set_ylabel('fidelity estimate')
271
+ ax.set_title('-'.join(str(q) for q in pair))
272
+ ax.legend()
273
+ return axes
@@ -0,0 +1,207 @@
1
+ # Copyright 2024 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import pytest
16
+ import numpy as np
17
+ import pandas as pd
18
+
19
+ import cirq
20
+
21
+ from cirq.experiments.z_phase_calibration import (
22
+ calibrate_z_phases,
23
+ z_phase_calibration_workflow,
24
+ plot_z_phase_calibration_result,
25
+ )
26
+ from cirq.experiments.xeb_fitting import XEBPhasedFSimCharacterizationOptions
27
+
28
+ _ANGLES = ['theta', 'phi', 'chi', 'zeta', 'gamma']
29
+
30
+
31
+ def _create_tests(n, seed, with_options: bool = False):
32
+ rng = np.random.default_rng(seed)
33
+ angles = (rng.random((n, 5)) * 2 - 1) * np.pi
34
+ # Add errors to the last 3 angles (chi, zeta, gamma).
35
+ # The errors are in the union (-2, -1) U (1, 2).
36
+ # This is because we run the tests with few repetitions so a small error might not get fixed.
37
+ error = np.concatenate(
38
+ [np.zeros((n, 2)), (rng.random((n, 3)) + 1) * rng.choice([-1, 1], (n, 3))], axis=-1
39
+ )
40
+ if with_options:
41
+ options = []
42
+ for _ in range(n):
43
+ v = [False, False, False]
44
+ # Calibrate only one to keep the run time down.
45
+ v[rng.integers(0, 3)] = True
46
+ options.append(
47
+ {
48
+ 'characterize_chi': v[0],
49
+ 'characterize_gamma': v[1],
50
+ 'characterize_zeta': v[2],
51
+ 'characterize_phi': False,
52
+ 'characterize_theta': False,
53
+ }
54
+ )
55
+
56
+ return zip(angles, error, options)
57
+ return zip(angles, error)
58
+
59
+
60
+ def _trace_distance(A, B):
61
+ return 0.5 * np.abs(np.linalg.eigvals(A - B)).sum()
62
+
63
+
64
+ class _TestSimulator(cirq.Simulator):
65
+ """A simulator that replaces a specific gate by another."""
66
+
67
+ def __init__(self, gate: cirq.Gate, replacement: cirq.Gate, **kwargs):
68
+ super().__init__(**kwargs)
69
+ self.gate = gate
70
+ self.replacement = replacement
71
+
72
+ def _core_iterator(
73
+ self,
74
+ circuit: 'cirq.AbstractCircuit',
75
+ sim_state,
76
+ all_measurements_are_terminal: bool = False,
77
+ ):
78
+ new_circuit = cirq.Circuit(
79
+ [
80
+ [op if op.gate != self.gate else self.replacement(*op.qubits) for op in m]
81
+ for m in circuit
82
+ ]
83
+ )
84
+ yield from super()._core_iterator(new_circuit, sim_state, all_measurements_are_terminal)
85
+
86
+
87
+ @pytest.mark.parametrize(
88
+ ['angles', 'error', 'characterization_flags'],
89
+ _create_tests(n=10, seed=32432432, with_options=True),
90
+ )
91
+ def test_calibrate_z_phases(angles, error, characterization_flags):
92
+
93
+ original_gate = cirq.PhasedFSimGate(**{k: v for k, v in zip(_ANGLES, angles)})
94
+ actual_gate = cirq.PhasedFSimGate(**{k: v + e for k, v, e in zip(_ANGLES, angles, error)})
95
+
96
+ options = XEBPhasedFSimCharacterizationOptions(
97
+ **{f'{n}_default': t for n, t in zip(_ANGLES, angles)}, **characterization_flags
98
+ )
99
+
100
+ sampler = _TestSimulator(original_gate, actual_gate, seed=0)
101
+ qubits = cirq.q(0, 0), cirq.q(0, 1)
102
+ calibrated_gate = calibrate_z_phases(
103
+ sampler,
104
+ qubits,
105
+ original_gate,
106
+ options,
107
+ n_repetitions=10,
108
+ n_combinations=10,
109
+ n_circuits=10,
110
+ cycle_depths=range(3, 10),
111
+ )[qubits]
112
+
113
+ initial_unitary = cirq.unitary(original_gate)
114
+ final_unitary = cirq.unitary(calibrated_gate)
115
+ target_unitary = cirq.unitary(actual_gate)
116
+ maximally_mixed_state = np.eye(4) / 2
117
+ dm_initial = initial_unitary @ maximally_mixed_state @ initial_unitary.T.conj()
118
+ dm_final = final_unitary @ maximally_mixed_state @ final_unitary.T.conj()
119
+ dm_target = target_unitary @ maximally_mixed_state @ target_unitary.T.conj()
120
+
121
+ original_dist = _trace_distance(dm_initial, dm_target)
122
+ new_dist = _trace_distance(dm_final, dm_target)
123
+
124
+ # Either we reduced the error or the error is small enough.
125
+ assert new_dist < original_dist or new_dist < 1e-6
126
+
127
+
128
+ @pytest.mark.parametrize(['angles', 'error'], _create_tests(n=3, seed=32432432))
129
+ def test_calibrate_z_phases_no_options(angles, error):
130
+
131
+ original_gate = cirq.PhasedFSimGate(**{k: v for k, v in zip(_ANGLES, angles)})
132
+ actual_gate = cirq.PhasedFSimGate(**{k: v + e for k, v, e in zip(_ANGLES, angles, error)})
133
+
134
+ sampler = _TestSimulator(original_gate, actual_gate, seed=0)
135
+ qubits = cirq.q(0, 0), cirq.q(0, 1)
136
+ calibrated_gate = calibrate_z_phases(
137
+ sampler,
138
+ qubits,
139
+ original_gate,
140
+ options=None,
141
+ n_repetitions=10,
142
+ n_combinations=10,
143
+ n_circuits=10,
144
+ cycle_depths=range(3, 10),
145
+ )[qubits]
146
+
147
+ initial_unitary = cirq.unitary(original_gate)
148
+ final_unitary = cirq.unitary(calibrated_gate)
149
+ target_unitary = cirq.unitary(actual_gate)
150
+ maximally_mixed_state = np.eye(4) / 2
151
+ dm_initial = initial_unitary @ maximally_mixed_state @ initial_unitary.T.conj()
152
+ dm_final = final_unitary @ maximally_mixed_state @ final_unitary.T.conj()
153
+ dm_target = target_unitary @ maximally_mixed_state @ target_unitary.T.conj()
154
+
155
+ original_dist = _trace_distance(dm_initial, dm_target)
156
+ new_dist = _trace_distance(dm_final, dm_target)
157
+
158
+ # Either we reduced the error or the error is small enough.
159
+ assert new_dist < original_dist or new_dist < 1e-6
160
+
161
+
162
+ @pytest.mark.parametrize(['angles', 'error'], _create_tests(n=3, seed=32432432))
163
+ def test_calibrate_z_phases_workflow_no_options(angles, error):
164
+
165
+ original_gate = cirq.PhasedFSimGate(**{k: v for k, v in zip(_ANGLES, angles)})
166
+ actual_gate = cirq.PhasedFSimGate(**{k: v + e for k, v, e in zip(_ANGLES, angles, error)})
167
+
168
+ sampler = _TestSimulator(original_gate, actual_gate, seed=0)
169
+ qubits = cirq.q(0, 0), cirq.q(0, 1)
170
+ result, _ = z_phase_calibration_workflow(
171
+ sampler,
172
+ qubits,
173
+ original_gate,
174
+ options=None,
175
+ n_repetitions=1,
176
+ n_combinations=1,
177
+ n_circuits=1,
178
+ cycle_depths=(1, 2),
179
+ )
180
+
181
+ for params in result.final_params.values():
182
+ assert 'zeta' in params
183
+ assert 'chi' in params
184
+ assert 'gamma' in params
185
+ assert 'phi' not in params
186
+ assert 'theta' not in params
187
+
188
+
189
+ def test_plot_z_phase_calibration_result():
190
+ df = pd.DataFrame()
191
+ qs = cirq.q(0, 0), cirq.q(0, 1), cirq.q(0, 2)
192
+ df.index = [qs[:2], qs[-2:]]
193
+ df['cycle_depths_0'] = [[1, 2, 3]] * 2
194
+ df['fidelities_0'] = [[0.9, 0.8, 0.7], [0.6, 0.4, 0.1]]
195
+ df['layer_fid_std_0'] = [0.1, 0.2]
196
+ df['fidelities_c'] = [[0.9, 0.92, 0.93], [0.7, 0.77, 0.8]]
197
+ df['layer_fid_std_c'] = [0.2, 0.3]
198
+
199
+ axes = plot_z_phase_calibration_result(before_after_df=df)
200
+
201
+ np.testing.assert_allclose(axes[0].lines[0].get_xdata().astype(float), [1, 2, 3])
202
+ np.testing.assert_allclose(axes[0].lines[0].get_ydata().astype(float), [0.9, 0.8, 0.7])
203
+ np.testing.assert_allclose(axes[0].lines[1].get_ydata().astype(float), [0.9, 0.92, 0.93])
204
+
205
+ np.testing.assert_allclose(axes[1].lines[0].get_xdata().astype(float), [1, 2, 3])
206
+ np.testing.assert_allclose(axes[1].lines[0].get_ydata().astype(float), [0.6, 0.4, 0.1])
207
+ np.testing.assert_allclose(axes[1].lines[1].get_ydata().astype(float), [0.7, 0.77, 0.8])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cirq-core
3
- Version: 1.5.0.dev20241105235147
3
+ Version: 1.5.0.dev20241108000946
4
4
  Summary: A framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
5
5
  Home-page: http://github.com/quantumlib/cirq
6
6
  Author: The Cirq Developers
@@ -4,8 +4,8 @@ cirq/_compat_test.py,sha256=Qq3ZcfgD-Nb81cEppQdJqhAyrVqXKtfXZYGXT0p-Wh0,34718
4
4
  cirq/_doc.py,sha256=yDyWUD_2JDS0gShfGRb-rdqRt9-WeL7DhkqX7np0Nko,2879
5
5
  cirq/_import.py,sha256=p9gMHJscbtDDkfHOaulvd3Aer0pwUF5AXpL89XR8dNw,8402
6
6
  cirq/_import_test.py,sha256=6K_v0riZJXOXUphHNkGA8MY-JcmGlezFaGmvrNhm3OQ,1015
7
- cirq/_version.py,sha256=Ey0ynXkiFaW1nBxhycPXoXoc89NAUMEyK-HXRacOgIk,1206
8
- cirq/_version_test.py,sha256=4W3uKdYhz6bv2jm6sEvcRfMrIGSsgznYr_IajXVGPUg,147
7
+ cirq/_version.py,sha256=nLBLggkBN0DieQBaZbvaR3lLwkBovuzp-fGSnDMTHWg,1206
8
+ cirq/_version_test.py,sha256=pb1073s50b2-w67rs2zQmSYC-Gu6JxTNT-JALyhxxLM,147
9
9
  cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
10
10
  cirq/json_resolver_cache.py,sha256=ytePZtNZgKjOF2NiVpUTuotB-JKZmQNOFIFdvXqsxHw,13271
11
11
  cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
@@ -175,7 +175,7 @@ cirq/devices/thermal_noise_model.py,sha256=qdWrN7Kqw5dq1rwVUBLY1DDw1nCPADSaxoLtG
175
175
  cirq/devices/thermal_noise_model_test.py,sha256=ox9b0BoHH6d73CjWWI1fIAGd_o3r-4qy8v2ggUwc-pw,12246
176
176
  cirq/devices/unconstrained_device.py,sha256=cnwn1caPDj7GnBf9_GYX6jMCTCWi4q5g3RkLaVKnDLY,1525
177
177
  cirq/devices/unconstrained_device_test.py,sha256=OF9E2m1HPpq6hyrNAwFGWaNOpQ3H2efAEj6V8Y-hRW4,832
178
- cirq/experiments/__init__.py,sha256=T3wQh27SyxSS1op4XYCoaSriI2qc9zw0jzBcfkQ-k8g,3500
178
+ cirq/experiments/__init__.py,sha256=Sx2sW3Uj0p7W-E_HkZ21YpHVUvKlp_zc5WWtago4rlo,3667
179
179
  cirq/experiments/fidelity_estimation.py,sha256=JK9yUoD4TL3nkf2yiEJ5f_RR-rhkAHSKpeLlYCRvZU4,9214
180
180
  cirq/experiments/fidelity_estimation_test.py,sha256=SX5hwQjyzWm1yr1q0C_LCgbFfUF_Ye36g6HuQbtinGI,4918
181
181
  cirq/experiments/grid_parallel_two_qubit_xeb.py,sha256=ROJZiXLaeF5IYo06DxeIvDHpwNJTIiqEAfKxs6v0vHM,2216
@@ -196,14 +196,16 @@ cirq/experiments/t1_decay_experiment.py,sha256=ealdmc_RTE__z1YUcaDEncDzQOaiT0K6I
196
196
  cirq/experiments/t1_decay_experiment_test.py,sha256=Pgbm-37JiCdw9iQg2OaXVvs72xGWV2629CgsTQlLQnw,9139
197
197
  cirq/experiments/t2_decay_experiment.py,sha256=lTgZ9yJ7Fk9_ozUCHysQn1qKrMQwTpsgEv-QnvsEif0,19158
198
198
  cirq/experiments/t2_decay_experiment_test.py,sha256=DFR0BGn0Id4qNPfqIExj70TEAqf7Vrc8eK91Wj0YKTc,15031
199
- cirq/experiments/two_qubit_xeb.py,sha256=N2X9N1A6hRS2Xe4zcmLJTyZ80DKDB0Pmv2fN4-UOU_s,19943
199
+ cirq/experiments/two_qubit_xeb.py,sha256=GFTB6yBvvda5hQvbjhjduXeNSQNJwbcOMPeDb0n_Wa0,20085
200
200
  cirq/experiments/two_qubit_xeb_test.py,sha256=ZeZvClUAB8ir42Bd3PWr-s0_-QKWbFdYqfvvOMawsm0,10204
201
- cirq/experiments/xeb_fitting.py,sha256=tD678gTY495cDA6b55YIPdwq22VQFbB2AlnkeX_X9P0,29332
201
+ cirq/experiments/xeb_fitting.py,sha256=Tzo2kg62udpRp654XArSDVcyVNhlhkNmpx9UVyxZiiw,30337
202
202
  cirq/experiments/xeb_fitting_test.py,sha256=0GQ6ifSWdvEJ6-ICIcSR-R9lFLRwBykgf6toLElmg0o,15483
203
203
  cirq/experiments/xeb_sampling.py,sha256=6ZOidGi7Kt6p4cMQCjK7qQuIUXVHCYl47B2GnL8M-Bw,14987
204
204
  cirq/experiments/xeb_sampling_test.py,sha256=0XkQGvcURsug3IblE_wZrHVDoOQV3WuQilrqCJbDHjI,6784
205
205
  cirq/experiments/xeb_simulation.py,sha256=yML2NAnYTRFG1wsQHvxtNEGEMXuExbWjrE2JYuCqnrk,5076
206
206
  cirq/experiments/xeb_simulation_test.py,sha256=YWFKXPdtBFuZNhQoG06W1EetVhXighc3zyXwhKfGAeo,5652
207
+ cirq/experiments/z_phase_calibration.py,sha256=zKfxMg9X8u_wuBfABttOu83ZDa0eF6pJscFHtA4plPM,11303
208
+ cirq/experiments/z_phase_calibration_test.py,sha256=Hk6FR-mvlkwol1WQvc75gw6oC_adRW-0_JF5y0X598E,7592
207
209
  cirq/interop/__init__.py,sha256=Xt1xU9UegP_jBNa9xaeOFSgtC0lYb_HNHq4hQQ0J20k,784
208
210
  cirq/interop/quirk/__init__.py,sha256=W11jqaExSgvoUkjM_d0Kik4R8bqETF9Ezo27CDEB3iw,1237
209
211
  cirq/interop/quirk/url_to_circuit.py,sha256=1ToWnFJdJIhCko9q62BEvOoCGxCpOUl8891IdCa52MM,14211
@@ -1186,8 +1188,8 @@ cirq/work/sampler.py,sha256=BDd1HrUOOcHBOvXNJqVX0vRcvmm8btZmZa5yYC5y8n0,19856
1186
1188
  cirq/work/sampler_test.py,sha256=hL2UWx3dz2ukZVNxWftiKVvJcQoLplLZdQm-k1QcA40,13282
1187
1189
  cirq/work/zeros_sampler.py,sha256=x1C7cup66a43n-3tm8QjhiqJa07qcJW10FxNp9jJ59Q,2356
1188
1190
  cirq/work/zeros_sampler_test.py,sha256=JIkpBBFPJe5Ba4142vzogyWyboG1Q1ZAm0UVGgOoZn8,3279
1189
- cirq_core-1.5.0.dev20241105235147.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1190
- cirq_core-1.5.0.dev20241105235147.dist-info/METADATA,sha256=NGfDEt4BBBQBP6UV-QJxn3J-3Rn5d0diLKJ5vDrJyXo,1992
1191
- cirq_core-1.5.0.dev20241105235147.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
1192
- cirq_core-1.5.0.dev20241105235147.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1193
- cirq_core-1.5.0.dev20241105235147.dist-info/RECORD,,
1191
+ cirq_core-1.5.0.dev20241108000946.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1192
+ cirq_core-1.5.0.dev20241108000946.dist-info/METADATA,sha256=6X_nrqT_Q3cxXDC8_UOdP1Eas1a4Hn5zTvaFG7pGB9g,1992
1193
+ cirq_core-1.5.0.dev20241108000946.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
1194
+ cirq_core-1.5.0.dev20241108000946.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1195
+ cirq_core-1.5.0.dev20241108000946.dist-info/RECORD,,