{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "S97D7gQHMdG_"
},
"outputs": [],
"source": [
"##### Copyright 2021 The Cirq Developers"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"id": "Y6Wh1qtGMghL"
},
"outputs": [],
"source": [
"#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gNBCrapEMgxB"
},
"source": [
"# Calibration: Overview and API"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "tlnEweYsMgzj"
},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "PnYvZgIoMg2O"
},
"source": [
"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."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "BRfLi9YSMg4v"
},
"source": [
"## Setup\n",
"Note: this notebook relies on unreleased Cirq features. If you want to try these features, make sure you install cirq via `pip install cirq~=1.0.dev`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "JolZGos2MhDM"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.15.0.dev\n"
]
}
],
"source": [
"try:\n",
" import cirq\n",
"except ImportError:\n",
" print(\"installing cirq...\")\n",
" !pip install --quiet cirq~=1.0.dev\n",
" print(\"installed cirq.\")\n",
" import cirq\n",
"print(\"Using cirq version\", cirq.__version__)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "lFI7APiqMhFy"
},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"import cirq\n",
"import cirq_google as cg"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fh6P5258GXQX"
},
"source": [
"Note: Leave the `project_id` and/or `processor_id` blank to use a noisy simulator."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"id": "UaBOLd1ZNZwC"
},
"outputs": [],
"source": [
"import os\n",
"\n",
"# The Google Cloud Project id to use.\n",
"project_id = '' #@param {type:\"string\"}\n",
"processor_id = \"\" #@param {type:\"string\"}\n",
"\n",
"from cirq_google.engine.qcs_notebook import get_qcs_objects_for_notebook\n",
"device_sampler = get_qcs_objects_for_notebook(project_id, processor_id)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fHj9lpEeNMI2"
},
"source": [
"## Overview"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "grmpD_A1SyVx"
},
"source": [
"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:\n",
"\n",
"$$\n",
"U(\\theta, \\zeta, \\chi, \\gamma, \\phi) := \\left[ \\begin{matrix}\n",
"1 & 0 & 0 & 0 \\\\\n",
"0 & \\exp(-i \\gamma - i \\zeta) \\cos( \\theta ) & -i \\exp(-i \\gamma + i \\chi) \\sin( \\theta ) & 0 \\\\\n",
"0 & -i \\exp(-i \\gamma - i \\chi) \\sin( \\theta ) & \\exp(-i \\gamma + i \\zeta) \\cos( \\theta) & 0 \\\\\n",
"0 & 0 & 0 & \\exp(-2 i \\gamma -i \\phi ) \n",
"\\end{matrix} \\right]\n",
"$$\n",
"\n",
"The $\\sqrt{\\text{iSWAP}}$ gate corresponds to angles $\\theta=-\\pi / 4$ and $\\zeta = \\chi = \\gamma = \\phi = 0$. \n",
"\n",
"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.\n",
"\n",
"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."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ww1Mdjm0NPeo"
},
"source": [
"## Calibration techniques and API"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "qOOw5G0IWvUd"
},
"source": [
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "rVnp2Y1pOAAp"
},
"outputs": [],
"source": [
"\"\"\"Define your circuit(s) here.\"\"\"\n",
"qubits = cg.line_on_device(device_sampler.device, length=2)\n",
"circuit = cirq.Circuit(cirq.ISWAP.on(*qubits) ** 0.5)\n",
"\n",
"print(\"Example circuit:\", circuit, sep=\"\\n\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c9ZjppgcbVQz"
},
"source": [
"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](./qcvv/xeb_calibration_example.ipynb) or use a Loschmidt echo as in [this Loschmidt echo tutorial](../tutorials/google/echoes.ipynb)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "O8PvBodGNfHn"
},
"source": [
"### Floquet calibration"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZCbXAVZINN33"
},
"source": [
"Floquet calibration returns fast, accurate estimates for every angle of the `cirq.PhasedFSimGate` except $\\chi$ (chi).\n",
"\n",
"The first step to Floquet calibration is defining the angles to characterize."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "utut_505Nds3"
},
"outputs": [],
"source": [
"# Define calibration options.\n",
"floquet_options = cg.FloquetPhasedFSimCalibrationOptions(\n",
" characterize_theta=True,\n",
" characterize_zeta=True,\n",
" characterize_chi=False,\n",
" characterize_gamma=True,\n",
" characterize_phi=True,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c5bcRE2SWxzc"
},
"source": [
"Next, use these options to get characterization requests - i.e., `cirq.Moment`s to characterize on the Quantum Engine - then characterize them."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Bt7qDv-YW7Qv"
},
"outputs": [],
"source": [
"# Get characterization requests.\n",
"floquet_characterization_requests = cg.prepare_characterization_for_operations(\n",
" circuit, options=floquet_options\n",
")\n",
"\n",
"# Characterize the requests on the engine.\n",
"floquet_characterizations = cg.run_calibrations(\n",
" floquet_characterization_requests, device_sampler.sampler\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9Dhfr0xNm-m-"
},
"source": [
"Note: The first argument to `cirq_google.prepare_characterization_for_operations` can also be a sequence of circuits."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "HhwNWy0dW7--"
},
"source": [
"The last step is to compensate for offsets using the `cirq_google.make_zeta_chi_gamma_compensation_for_moments` function."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bNQddsaJXfym"
},
"outputs": [],
"source": [
"# Compensate your circuit based on the characterizations.\n",
"floquet_calibrated_circuit = cg.make_zeta_chi_gamma_compensation_for_moments(\n",
" circuit, floquet_characterizations\n",
").circuit\n",
"\n",
"print(\"Floquet calibrated circuit:\", floquet_calibrated_circuit, sep=\"\\n\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JoQNOxdLN8YB"
},
"source": [
"Note the addition of `cirq.Rz` gates to compensate for characterized errors. This calibrated circuit can now be run on the processor."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "j0ZBw4zWNg-y"
},
"source": [
"### XEB calibration"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "io2YyhxaN6xt"
},
"source": [
"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](./qcvv/parallel_xeb.ipynb).\n",
"\n",
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "KA9QJ87sMhPI"
},
"outputs": [],
"source": [
"# Define calibration options.\n",
"cycle_depths=(5, 25, 50, 100)\n",
"\n",
"xeb_options = cg.LocalXEBPhasedFSimCalibrationOptions(\n",
" cycle_depths=cycle_depths,\n",
" n_processes=1,\n",
" # Note that all angles below are set to True by default.\n",
" fsim_options=cirq.experiments.XEBPhasedFSimCharacterizationOptions(\n",
" characterize_theta=False,\n",
" characterize_zeta=True,\n",
" characterize_chi=True,\n",
" characterize_gamma=True,\n",
" characterize_phi=False,\n",
" ),\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WsFn5OKdY2p0"
},
"source": [
"The remaining steps are identical to Floquet calibration: first getting characterization requests then characterizing them on the engine."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "SVuqkj6gYE-V"
},
"outputs": [],
"source": [
"# Get characterization requests.\n",
"xeb_characterization_requests = cg.prepare_characterization_for_operations(\n",
" circuit, options=xeb_options\n",
")\n",
"\n",
"# Characterize the requests on the engine.\n",
"xeb_characterizations = cg.run_calibrations(\n",
" xeb_characterization_requests, device_sampler.sampler\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lkNc2hEgl9Ql"
},
"source": [
"Making compensations is also identical to the Floquet calibration example."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "aKy2mdpsZzmP"
},
"outputs": [],
"source": [
"xeb_calibrated_circuit = cg.make_zeta_chi_gamma_compensation_for_moments(\n",
" circuit, xeb_characterizations,\n",
").circuit\n",
"\n",
"print(\"XEB calibrated circuit:\", xeb_calibrated_circuit, sep=\"\\n\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "HlnmFNFnN9nz"
},
"source": [
"Again note the addition of `cirq.Rz` gates to compensate for errors. This calibrated circuit can now be run on the processor."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bBZ8MRdNN9qi"
},
"source": [
"## Which calibration should I use?"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8iyr366iN9v8"
},
"source": [
"This question is very dependent on the particular type of circuit, but some guidelines exist. XEB calibration is generally more applicable to circuits that alternate single-qubit and two-qubit layers due to the similarity between the random XEB circuits and executed circuits. Floquet calibration may be more applicable to circuits with two-qubit gates and $Z$ gates only."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2Yw4ykeBlRgU"
},
"source": [
"## Summary and notes"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "g5jECqZ5N9tB"
},
"source": [
"\n",
"\n",
"\n",
" \n",
" | \n",
" Floquet calibration | \n",
" XEB calibration | \n",
"
\n",
"\n",
"\n",
" \n",
" FSim angles characterized | \n",
" 4 / 5 (all but χ) | \n",
" 5 / 5 | \n",
"
\n",
" \n",
" FSim angles compensated | \n",
" 2 / 5 (ζ and γ) | \n",
" 3 / 5 (ζ, χ, and γ)
| \n",
"
\n",
" \n",
" Relative runtime | \n",
" 1 | \n",
" ~10x Floquet calibration runtime | \n",
"
\n",
" \n",
" Robust to SPAM errors? | \n",
" Yes | \n",
" Yes | \n",
"
\n",
" \n",
" Experiments used in | \n",
" Fermi-Hubbard | \n",
" OTOC | \n",
"
\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "xYFhw2mWSLDx"
},
"source": [
"- The ζ, χ and γ parameters of the `cirq.PhasedFSimGate` are subject to drifts that range in frequency from seconds to hours.\n",
"- Neither calibration technique attempts to correct the misaligned iSWAP rotation or the additional two-qubit phase. This is a non-trivial task and we do currently have simple tools to achieve this. It is up to the user to correct for these in experiments as best as possible.\n",
"- Floquet calibration does not yet support microwave gates."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "p-J9h3YWSQkE"
},
"source": [
"## Next steps"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8tLka4CaSS9Z"
},
"source": [
"Try running Floquet and/or XEB calibration on your circuit(s). See the following tutorials for detailed examples and benchmarks.\n",
"\n",
"- [Floquet calibration: Example and benchmark](./floquet_calibration_example.ipynb)\n",
"- [XEB calibration: Example and benchmark](./qcvv/xeb_calibration_example.ipynb)\n",
"\n",
"See also the [Calibration FAQ](./calibration_faq.md) for additional information on calibration."
]
}
],
"metadata": {
"colab": {
"name": "calibration_api.ipynb",
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 0
}