<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Calibration
Step1:  Note
Step3:  Overview
Floquet and XEB calibration are tools to characterize a family of gates including $\sqrt{\text{iSWAP}}$ gates on a particular processor and compensate for errors. The family of gates is represented by the cirq.PhasedFSimGate, a two-qubit gate with five angles $\theta$, $\zeta$, $\chi$, $\gamma$, $\phi$ given by the following unitary matrix
Step4:  Note
Step5:  Next, use these options to get characterization requests - i.e., cirq.Moments to characterize on the Quantum Engine - then characterize them.
Step6:  Note
Step7:  Note the addition of cirq.Rz gates to compensate for characterized errors. This calibrated circuit can now be run on the processor.
XEB calibration
XEB calibration works by executing a library of random circuits both on a noiseless simulator and on a noisy processor, then comparing results. In principle it can characterize any two-qubit gate, but compensation is currently only for $\zeta$, $\chi$, and $\gamma$. For more details about how XEB calibration works, see the Parallel XEB tutorial.
Like Floquet calibration, the first step to using XEB calibration is defining options. Unlike Floquet calibration, XEB calibration requires significant classical processing to characterize angles. In addition to the angles to characterize, we also need to define the cycle_depths of the random circuits. The number of processes n_processes is a parallelization option for the classical processing.
Step8:  The remaining steps are identical to Floquet calibration
Step9:  Making compensations is also identical to the Floquet calibration example.
<ASSISTANT_TASK:>
Python Code:
try:
    import cirq
except ImportError:
    print("installing cirq...")
    !pip install --quiet cirq --pre
    print("installed cirq.")
import numpy as np
import cirq
import cirq_google as cg
Explanation: Calibration: Overview and API
<table class="tfo-notebook-buttons" align="left">
  <td>
    <a target="_blank" href="https://quantumai.google/cirq/tutorials/google/calibration_api"><img src="https://quantumai.google/site-assets/images/buttons/quantumai_logo_1x.png" />View on QuantumAI</a>
  </td>
  <td>
    <a target="_blank" href="https://colab.research.google.com/github/quantumlib/Cirq/blob/master/docs/tutorials/google/calibration_api.ipynb"><img src="https://quantumai.google/site-assets/images/buttons/colab_logo_1x.png" />Run in Google Colab</a>
  </td>
  <td>
    <a target="_blank" href="https://github.com/quantumlib/Cirq/blob/master/docs/tutorials/google/calibration_api.ipynb"><img src="https://quantumai.google/site-assets/images/buttons/github_logo_1x.png" />View source on GitHub</a>
  </td>
  <td>
    <a href="https://storage.googleapis.com/tensorflow_docs/Cirq/docs/tutorials/google/calibration_api.ipynb"><img src="https://quantumai.google/site-assets/images/buttons/download_icon_1x.png" />Download notebook</a>
  </td>
</table>
This tutorial provides an introductory overview of calibration. By the end, you will understand the high-level calibration process, how to run calibrations through the API, and how to choose which calibration technique to use.
Setup
Note: this notebook relies on unreleased Cirq features. If you want to try these features, make sure you install cirq via pip install cirq --pre.
End of explanation
import os
# The Google Cloud Project id to use.
project_id = '' #@param {type:"string"}
processor_id = "" #@param {type:"string"}
from cirq_google.engine.qcs_notebook import get_qcs_objects_for_notebook
device_sampler = get_qcs_objects_for_notebook(project_id, processor_id)
Explanation: Note: Leave the project_id and/or processor_id blank to use a noisy simulator.
End of explanation
Define your circuit(s) here.
qubits = cg.line_on_device(device_sampler.device, length=2)
circuit = cirq.Circuit(cirq.ISWAP.on(*qubits) ** 0.5)
print("Example circuit:", circuit, sep="\n\n")
Explanation: Overview
Floquet and XEB calibration are tools to characterize a family of gates including $\sqrt{\text{iSWAP}}$ gates on a particular processor and compensate for errors. The family of gates is represented by the cirq.PhasedFSimGate, a two-qubit gate with five angles $\theta$, $\zeta$, $\chi$, $\gamma$, $\phi$ given by the following unitary matrix:
$$
U(\theta, \zeta, \chi, \gamma, \phi) := \left[ \begin{matrix}
1 & 0                                          & 0                                         & 0      \
0 &    \exp(-i \gamma - i \zeta) \cos( \theta ) & -i \exp(-i \gamma + i \chi) \sin( \theta ) & 0 \
0 & -i \exp(-i \gamma - i \chi) \sin( \theta )  &    \exp(-i \gamma + i \zeta) \cos( \theta) & 0    \
0 & 0                                          & 0                               & \exp(-2 i \gamma -i \phi )
\end{matrix} \right]
$$
The $\sqrt{\text{iSWAP}}$ gate corresponds to angles $\theta=-\pi / 4$ and $\zeta = \chi = \gamma = \phi = 0$. 
Characterization is done by the Quantum Engine and compensation (currently the insertion of $Z$ gates around $\sqrt{\text{iSWAP}}$ gates) is completely client-side with the help of Cirq utilities. At the highest level, each calibration tool inputs one or more quantum circuits of interest as well as a processor to run on, and outputs the calibrated circuit(s) for this processor.
Both calibrations are primarily focused on decreasing the effects of two sources of coherent errors: calibration drifts and cross-talk errors. These errors are not uniform across the chip and vary in magnitude between qubits and device calibrations. The circuit-specific calibrations should be used in situations when achieving the best performance is more important than using extra time on the device for the characterizations.
Calibration techniques and API
To run calibration, define your circuit or circuits below. For sake of example we use a simple circuit with a single $\sqrt{\text{iSWAP}}$ gate.
End of explanation
# Define calibration options.
floquet_options = cg.FloquetPhasedFSimCalibrationOptions(
    characterize_theta=True,
    characterize_zeta=True,
    characterize_chi=False,
    characterize_gamma=True,
    characterize_phi=True,
)
Explanation: Note: Above we picked any qubits, but in an actual experiment you want to pick a good set of qubits to run on. To do so, use the latest maintanence report as in this XEB calibration example or use a Loschmidt echo as in this Loschmidt echo tutorial.
Floquet calibration
Floquet calibration returns fast, accurate estimates for every angle of the cirq.PhasedFSimGate except $\chi$ (chi).
The first step to Floquet calibration is defining the angles to characterize.
End of explanation
# Get characterization requests.
floquet_characterization_requests = cg.prepare_characterization_for_operations(
    circuit, options=floquet_options
)
# Characterize the requests on the engine.
floquet_characterizations = cg.run_calibrations(
    floquet_characterization_requests, device_sampler.sampler
)
Explanation: Next, use these options to get characterization requests - i.e., cirq.Moments to characterize on the Quantum Engine - then characterize them.
End of explanation
# Compensate your circuit based on the characterizations.
floquet_calibrated_circuit = cg.make_zeta_chi_gamma_compensation_for_moments(
    circuit, floquet_characterizations
).circuit
print("Floquet calibrated circuit:", floquet_calibrated_circuit, sep="\n\n")
Explanation: Note: The first argument to cirq_google.prepare_characterization_for_operations can also be a sequence of circuits.
The last step is to compensate for offsets using the cirq_google.make_zeta_chi_gamma_compensation_for_moments function.
End of explanation
# Define calibration options.
cycle_depths=(5, 25, 50, 100)
xeb_options = cg.LocalXEBPhasedFSimCalibrationOptions(
    cycle_depths=cycle_depths,
    n_processes=1,
    # Note that all angles below are set to True by default.
    fsim_options=cirq.experiments.XEBPhasedFSimCharacterizationOptions(
        characterize_theta=False,
        characterize_zeta=True,
        characterize_chi=True,
        characterize_gamma=True,
        characterize_phi=False,
    ),
)
Explanation: Note the addition of cirq.Rz gates to compensate for characterized errors. This calibrated circuit can now be run on the processor.
XEB calibration
XEB calibration works by executing a library of random circuits both on a noiseless simulator and on a noisy processor, then comparing results. In principle it can characterize any two-qubit gate, but compensation is currently only for $\zeta$, $\chi$, and $\gamma$. For more details about how XEB calibration works, see the Parallel XEB tutorial.
Like Floquet calibration, the first step to using XEB calibration is defining options. Unlike Floquet calibration, XEB calibration requires significant classical processing to characterize angles. In addition to the angles to characterize, we also need to define the cycle_depths of the random circuits. The number of processes n_processes is a parallelization option for the classical processing.
End of explanation
# Get characterization requests.
xeb_characterization_requests = cg.prepare_characterization_for_operations(
    circuit, options=xeb_options
)
# Characterize the requests on the engine.
xeb_characterizations = cg.run_calibrations(
    xeb_characterization_requests, device_sampler.sampler
)
Explanation: The remaining steps are identical to Floquet calibration: first getting characterization requests then characterizing them on the engine.
End of explanation
xeb_calibrated_circuit = cg.make_zeta_chi_gamma_compensation_for_moments(
    circuit, xeb_characterizations,
).circuit
print("XEB calibrated circuit:", xeb_calibrated_circuit, sep="\n\n")
Explanation: Making compensations is also identical to the Floquet calibration example.
End of explanation
<END_TASK>