Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create workflow for Z-phase calibration #6728

Merged
merged 27 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ade51ee
checkpoint
NoureldinYosri Aug 2, 2024
145880e
checkpoint
NoureldinYosri Aug 2, 2024
9a9d06f
Create workflow for Z-phase calibration
NoureldinYosri Sep 13, 2024
d37ea60
update deps
NoureldinYosri Sep 13, 2024
717155c
increase error
NoureldinYosri Sep 13, 2024
b053a93
nit
NoureldinYosri Sep 13, 2024
eadda56
nit
NoureldinYosri Sep 13, 2024
07ba30a
Add test
NoureldinYosri Sep 13, 2024
8c244e7
Merge branch 'main' into z_cal2
NoureldinYosri Sep 19, 2024
552b7df
checkpoint
NoureldinYosri Sep 19, 2024
6f71abf
coverage
NoureldinYosri Sep 19, 2024
39b1537
Add plotting method and calculate the variance of estimated fidelity
NoureldinYosri Oct 2, 2024
e2cac7d
Merge branch 'main' into z_cal2
NoureldinYosri Oct 2, 2024
9f42000
docstring
NoureldinYosri Oct 2, 2024
26593a1
coverage
NoureldinYosri Oct 2, 2024
39e0a6d
change qubit names
NoureldinYosri Oct 2, 2024
d0a9583
Merge branch 'main' into z_cal2
NoureldinYosri Oct 24, 2024
530dc2d
checkpoint
NoureldinYosri Oct 30, 2024
55c47a5
address comments
NoureldinYosri Oct 31, 2024
0cb890d
Merge branch 'main' into z_cal2
NoureldinYosri Oct 31, 2024
5d668e2
address comments
NoureldinYosri Nov 7, 2024
a372c8e
nit
NoureldinYosri Nov 7, 2024
fcb2d2a
Merge branch 'main' into z_cal2
NoureldinYosri Nov 7, 2024
d9a8282
Update cirq-core/cirq/experiments/z_phase_calibration.py
NoureldinYosri Nov 7, 2024
b19cee9
Update cirq-core/cirq/experiments/z_phase_calibration.py
NoureldinYosri Nov 7, 2024
360aee1
Update cirq-core/cirq/experiments/z_phase_calibration.py
NoureldinYosri Nov 7, 2024
296922d
Update cirq-core/cirq/experiments/z_phase_calibration.py
NoureldinYosri Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cirq-core/cirq/experiments/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,6 @@
parallel_two_qubit_xeb as parallel_two_qubit_xeb,
run_rb_and_xeb as run_rb_and_xeb,
)


from cirq.experiments.z_phase_calibration import z_phase_calibration_workflow, calibrate_z_phases
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a little redundant to have both calibrate_z_phases and z_phase_calibration_workflow. Can we just have one thing with the functionality of z_phase_calibration_workflow?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On an unrelated note, please use the from somewhere import foo as foo so that the new names can be imported from cirq.experiments without raising mypy error. (Ref: #6717)

5 changes: 4 additions & 1 deletion cirq-core/cirq/experiments/two_qubit_xeb.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from cirq._compat import cached_method

if TYPE_CHECKING:
import multiprocessing

Check warning on line 41 in cirq-core/cirq/experiments/two_qubit_xeb.py

View check run for this annotation

Codecov / codecov/patch

cirq-core/cirq/experiments/two_qubit_xeb.py#L41

Added line #L41 was not covered by tests
import cirq


Expand Down Expand Up @@ -358,6 +359,7 @@
cycle_depths: Sequence[int] = (5, 25, 50, 100, 200, 300),
random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
ax: Optional[plt.Axes] = None,
pool: Optional['multiprocessing.pool.Pool'] = None,
**plot_kwargs,
) -> Tuple[pd.DataFrame, Sequence['cirq.Circuit'], pd.DataFrame]:
"""A utility method that runs the full XEB workflow.
Expand All @@ -373,6 +375,7 @@
random_state: The random state to use.
ax: the plt.Axes to plot the device layout on. If not given,
no plot is created.
NoureldinYosri marked this conversation as resolved.
Show resolved Hide resolved
pool: An optional multiprocessing pool.
NoureldinYosri marked this conversation as resolved.
Show resolved Hide resolved
**plot_kwargs: Arguments to be passed to 'plt.Axes.plot'.

Returns:
Expand Down Expand Up @@ -426,7 +429,7 @@
)

fids = benchmark_2q_xeb_fidelities(
sampled_df=sampled_df, circuits=circuit_library, cycle_depths=cycle_depths
sampled_df=sampled_df, circuits=circuit_library, cycle_depths=cycle_depths, pool=pool
)

return fids, circuit_library, sampled_df
Expand Down
11 changes: 8 additions & 3 deletions cirq-core/cirq/experiments/xeb_fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,16 +385,21 @@ def SqrtISwapXEBOptions(*args, **kwargs):


def parameterize_circuit(
circuit: 'cirq.Circuit', options: XEBCharacterizationOptions
circuit: 'cirq.Circuit',
options: XEBCharacterizationOptions,
target_gatefamily: Optional[ops.GateFamily] = None,
) -> 'cirq.Circuit':
"""Parameterize PhasedFSim-like gates in a given circuit according to
`phased_fsim_options`.
"""
if isinstance(target_gatefamily, ops.GateFamily):
should_parameterize = lambda op: op in target_gatefamily or options.should_parameterize(op)
else:
should_parameterize = options.should_parameterize
gate = options.get_parameterized_gate()
return circuits.Circuit(
circuits.Moment(
gate.on(*op.qubits) if options.should_parameterize(op) else op
for op in moment.operations
gate.on(*op.qubits) if should_parameterize(op) else op for op in moment.operations
)
for moment in circuit.moments
)
Expand Down
193 changes: 193 additions & 0 deletions cirq-core/cirq/experiments/z_phase_calibration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# Copyright 2024 The Cirq Developers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Provides a method to do z-phase calibration for excitation-preserving gates."""
from typing import Optional, Sequence, Tuple, Dict, TYPE_CHECKING

import numpy as np

from cirq.experiments import xeb_fitting
from cirq.experiments.two_qubit_xeb import parallel_xeb_workflow
from cirq import ops

if TYPE_CHECKING:
import cirq
import pandas as pd
import multiprocessing

Check warning on line 27 in cirq-core/cirq/experiments/z_phase_calibration.py

View check run for this annotation

Codecov / codecov/patch

cirq-core/cirq/experiments/z_phase_calibration.py#L25-L27

Added lines #L25 - L27 were not covered by tests


def z_phase_calibration_workflow(
sampler: 'cirq.Sampler',
qubits: Optional[Sequence['cirq.GridQubit']] = None,
two_qubit_gate: 'cirq.Gate' = ops.CZ,
options: Optional[xeb_fitting.XEBPhasedFSimCharacterizationOptions] = None,
n_repetitions: int = 10**4,
n_combinations: int = 10,
n_circuits: int = 20,
cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
atol: float = 1e-3,
pool: Optional['multiprocessing.pool.Pool'] = None,
) -> Tuple[xeb_fitting.XEBCharacterizationResult, 'pd.DataFrame']:
"""Perform z-phase calibration for excitation-preserving gates.

For a given excitation-preserving two-qubit gate we assume an error model that can be described
using Z-rotations:
0: ───Rz(a)───two_qubit_gate───Rz(c)───
1: ───Rz(b)───two_qubit_gate───Rz(d)───
for some angles a, b, c, and d.

Since the two-qubit gate is a excitation-preserving-gate, it can be represented by an FSimGate
and the effect of rotations turns it into a PhasedFSimGate. Using XEB-data we find the
PhasedFSimGate parameters that minimize the infidelity of the gate.

References:
- https://arxiv.org/abs/2001.08343
- https://arxiv.org/abs/2010.07965
- https://arxiv.org/abs/1910.11333

Args:
sampler: The quantum engine or simulator to run the circuits.
qubits: Qubits to use. If none, use all qubits on the sampler's device.
two_qubit_gate: The entangling gate to use.
options: The XEB-fitting options. If None, calibrate all 5 PhasedFSimGate parameters,
using the representation of a two-qubit gate as an FSimGate for the initial guess.
n_repetitions: The number of repetitions to use.
n_combinations: The number of combinations to generate.
n_circuits: The number of circuits to generate.
cycle_depths: The cycle depths to use.
random_state: The random state to use.
atol: Absolute tolerance to be used by the minimizer.
pool: Optional multi-threading or multi-processing pool.

Returns:
- An `XEBCharacterizationResult` object that contains the calibration result.
- A `pd.DataFrame` comparing the before and after fidilities.
NoureldinYosri marked this conversation as resolved.
Show resolved Hide resolved
"""

fids_df_0, circuits, sampled_df = parallel_xeb_workflow(
sampler=sampler,
qubits=qubits,
entangling_gate=two_qubit_gate,
n_repetitions=n_repetitions,
cycle_depths=cycle_depths,
n_circuits=n_circuits,
n_combinations=n_combinations,
random_state=random_state,
pool=pool,
)

if options is None:
options = xeb_fitting.XEBPhasedFSimCharacterizationOptions(
characterize_chi=False, characterize_gamma=False, characterize_zeta=False
).with_defaults_from_gate(two_qubit_gate)
NoureldinYosri marked this conversation as resolved.
Show resolved Hide resolved

p_circuits = [
xeb_fitting.parameterize_circuit(circuit, options, ops.GateFamily(two_qubit_gate))
for circuit in circuits
]

result = xeb_fitting.characterize_phased_fsim_parameters_with_xeb_by_pair(
sampled_df=sampled_df,
parameterized_circuits=p_circuits,
cycle_depths=cycle_depths,
options=options,
fatol=atol,
xatol=atol,
pool=pool,
)

return result, xeb_fitting.before_and_after_characterization(
fids_df_0, characterization_result=result
)


def calibrate_z_phases(
sampler: 'cirq.Sampler',
qubits: Optional[Sequence['cirq.GridQubit']] = None,
two_qubit_gate: 'cirq.Gate' = ops.CZ,
options: Optional[xeb_fitting.XEBPhasedFSimCharacterizationOptions] = None,
n_repetitions: int = 10**4,
n_combinations: int = 10,
n_circuits: int = 20,
cycle_depths: Sequence[int] = tuple(np.arange(3, 100, 20)),
random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
atol: float = 1e-3,
pool: Optional['multiprocessing.pool.Pool'] = None,
) -> Dict[Tuple['cirq.Qid', 'cirq.Qid'], 'cirq.PhasedFSimGate']:
"""Perform z-phase calibration for excitation-preserving gates.

For a given excitation-preserving two-qubit gate we assume an error model that can be described
using Z-rotations:
0: ───Rz(a)───two_qubit_gate───Rz(c)───
1: ───Rz(b)───two_qubit_gate───Rz(d)───
for some angles a, b, c, and d.

Since the two-qubit gate is a excitation-preserving gate, it can be represented by an FSimGate
and the effect of rotations turns it into a PhasedFSimGate. Using XEB-data we find the
PhasedFSimGate parameters that minimize the infidelity of the gate.

References:
- https://arxiv.org/abs/2001.08343
- https://arxiv.org/abs/2010.07965
- https://arxiv.org/abs/1910.11333

Args:
sampler: The quantum engine or simulator to run the circuits.
qubits: Qubits to use. If none, use all qubits on the sampler's device.
two_qubit_gate: The entangling gate to use.
options: The XEB-fitting options. If None, calibrate all 5 PhasedFSimGate parameters,
using the representation of a two-qubit gate as an FSimGate for the initial guess.
n_repetitions: The number of repetitions to use.
n_combinations: The number of combinations to generate.
n_circuits: The number of circuits to generate.
cycle_depths: The cycle depths to use.
random_state: The random state to use.
atol: Absolute tolerance to be used by the minimizer.
pool: Optional multi-threading or multi-processing pool.

Returns:
- A dictionary mapping qubit pairs to the calibrated PhasedFSimGates.
"""

if options is None:
options = xeb_fitting.XEBPhasedFSimCharacterizationOptions(
characterize_chi=False, characterize_gamma=False, characterize_zeta=False
).with_defaults_from_gate(two_qubit_gate)
NoureldinYosri marked this conversation as resolved.
Show resolved Hide resolved

result, _ = z_phase_calibration_workflow(
sampler=sampler,
qubits=qubits,
two_qubit_gate=two_qubit_gate,
options=options,
n_repetitions=n_repetitions,
n_combinations=n_combinations,
n_circuits=n_circuits,
cycle_depths=cycle_depths,
random_state=random_state,
atol=atol,
pool=pool,
)

gates = {}
for pair, params in result.final_params.items():
params['theta'] = params.get('theta', options.theta_default or 0)
params['phi'] = params.get('phi', options.phi_default or 0)
params['zeta'] = params.get('zeta', options.zeta_default or 0)
params['chi'] = params.get('chi', options.chi_default or 0)
params['gamma'] = params.get('gamma', options.gamma_default or 0)
gates[pair] = ops.PhasedFSimGate(**params)
return gates
Loading