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

Qb spec fix #175

Merged
merged 9 commits into from
Jul 8, 2019
Merged
4 changes: 2 additions & 2 deletions docs/fit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ Fits

base_param_decay
fit_base_param_decay
decay_constant_param_decay
fit_decay_constant_param_decay
decay_time_param_decay
fit_decay_time_param_decay
decaying_cosine
fit_decaying_cosine
shifted_cosine
Expand Down
2 changes: 1 addition & 1 deletion docs/qubit_spec.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ CZ phase Ramsey
:toctree: autogen
:template: autosumm.rst

generate_cz_phase_ramsey_experiment
generate_cz_phase_ramsey_experiments
fit_cz_phase_ramsey_results
35 changes: 21 additions & 14 deletions examples/qubit_spectroscopy_cz_ramsey.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
" RZ(theta) 0\n",
" RX(pi/2) 0\n",
" MEASURE 0 ro[0]\n",
" \n",
"Since we can natively parameterize `RZ` rotations continuously on our hardware, we are able to make use of [Quil 2.0's parametric program compilation](https://pyquil.readthedocs.io/en/stable/migration3-declare.html?highlight=parametric%20program%20compilation#Parametric-compilation) using `DECLARE theta REAL[1]` and `RZ(theta) 0`. "
" "
]
},
{
Expand Down Expand Up @@ -48,9 +47,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## measurement, analysis, and plotting\n",
"\n",
"This method takes in a `pandas.DataFrame` object with all the CZ Ramsey data, including the phases and qubits measured, and plots the CZ Ramsey fringes of each qubit with respect to increasing applied contrast phase. It fits to a sinusoid, evaluates the phases at which excited state visibility is maximized for each qubit, $\\theta_0$ and $\\theta_1$, and plots a vertical line at these maximum excited state visibility points over the experimental data. "
"## measurement, analysis, and plotting"
]
},
{
Expand All @@ -72,7 +69,8 @@
"metadata": {},
"outputs": [],
"source": [
"#qc.device.specs"
"# if you are on the QPU you can look at `qc.device.specs`\n",
"# qc.device.specs"
]
},
{
Expand All @@ -92,7 +90,9 @@
"import numpy as np\n",
"from numpy import pi\n",
"angles = np.linspace(0, 2*pi, 15)\n",
"expts = [generate_cz_phase_ramsey_experiment(edge, measure_q, angles) for edge in edges for measure_q in edge]"
"edge = (0, 1)\n",
"# genereate a set of len(angles) experiments for each measurement qubit on edge (0, 1).\n",
"edge_0_1_expts = [generate_cz_phase_ramsey_experiments(edge, measure_q, angles) for measure_q in edge]"
]
},
{
Expand All @@ -101,7 +101,7 @@
"source": [
"**Acquire data**\n",
"\n",
"Collect our Ramsey raw data using `acquire_cz_phase_ramsey_data`."
"Collect our Ramsey raw data using `estimate_observables`."
]
},
{
Expand All @@ -110,15 +110,23 @@
"metadata": {},
"outputs": [],
"source": [
"# acquire results for a particular experiment\n",
"results = acquire_cz_phase_ramsey_data(qc, expts[0], num_shots=500)"
"from forest.benchmarking.observable_estimation import estimate_observables\n",
"# acquire results for each measurement qubit on each edge.\n",
"results = []\n",
"for angle_expts in zip(*edge_0_1_expts):\n",
" angle_results = []\n",
" for meas_q_expt in angle_expts:\n",
" angle_results += estimate_observables(qc, meas_q_expt, num_shots=500)\n",
" results.append(angle_results)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Use the results to produce estimates of Ramsey-acquired compensatory RZ phases**"
"**Use the results to produce estimates of Ramsey-acquired compensatory RZ phases for this edge**\n",
"\n",
"In the cell below we first extract the expectation and std_err for each meausurement and store these results in lists separately for each qubit measured. For each qubit measured we then fit a sinusoid to the data from which we can determine the `offset` of the maximum excited state visibility, which tells us the effective imparted phase. Finally we plot the CZ Ramsey fringes for each qubit with respect to increasing applied contrast phase."
]
},
{
Expand All @@ -131,9 +139,8 @@
"\n",
"stats_by_qubit = get_stats_by_qubit(results)\n",
"for q, stats in stats_by_qubit.items():\n",
" fit = fit_cz_phase_ramsey_results(angles, stats_by_qubit[q]['expectation'],\n",
" stats_by_qubit[q]['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit',xlabel=\"RX angle [rad]\",\n",
" fit = fit_cz_phase_ramsey_results(angles, stats['expectation'], stats['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit', xlabel=\"RX angle [rad]\",\n",
" ylabel=r\"Pr($|1\\rangle$)\")\n",
" frequency = fit.params['frequency'].value # ratio of actual angle over intended control angle\n",
" amplitude = fit.params['amplitude'].value # (P(1 given 1) - P(1 given 0)) / 2\n",
Expand Down
29 changes: 12 additions & 17 deletions examples/qubit_spectroscopy_rabi.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
"This notebook demonstrates how to perform a Rabi experiment on a simulated or real quantum device. This experiment tests the calibration of the `RX` pulse by rotating through a full $2\\pi$ radians and evaluating the excited state visibility as a function of the angle of rotation, $\\theta$. The QUIL program for one data point for qubit 0 at, for example $\\theta=\\pi/2$, is\n",
"\n",
" DECLARE ro BIT[1]\n",
" X 0\n",
" RX(pi/2) 0\n",
" MEASURE 0 ro[0]\n",
" \n",
"We expect to see a characteristic \"Rabi flop\" by sweeping $\\theta$ over $[0, 2\\pi)$, thereby completing a full rotation around the Bloch sphere. It should look like $\\dfrac{1-\\cos(\\theta)}{2}$"
"The X 0 is simply to initialize the state to $|1\\rangle$. We expect to see a characteristic \"Rabi flop\" by sweeping $\\theta$ over $[0, 2\\pi)$, thereby completing a full rotation around the Bloch sphere. It should look like $\\dfrac{1-\\cos(\\theta)}{2}$"
]
},
{
Expand Down Expand Up @@ -40,13 +41,6 @@
"## measurement, analysis, and plotting"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This method takes a `pandas.DataFrame` object with all the Rabi data and plots the Rabi flop. It fits to a sinusoid and evaluates the period for each qubit (which should be $2\\pi$). "
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -63,7 +57,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Generate simultaneous Rabi experiments**\n"
"**Generate simultaneous Rabi experiments on all qubits**\n"
]
},
{
Expand All @@ -84,7 +78,7 @@
"source": [
"**Acquire data**\n",
"\n",
"Collect our Rabi raw data using `acquire_rabi_data`. "
"Collect our Rabi raw data using `acquire_qubit_spectroscopy_data`. "
]
},
{
Expand All @@ -93,14 +87,16 @@
"metadata": {},
"outputs": [],
"source": [
"results = acquire_rabi_data(qc, rabi_expts, num_shots=500)"
"results = acquire_qubit_spectroscopy_data(qc, rabi_expts, num_shots=500)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Use the results to fit a Rabi curve and estimate parameters**"
"**Use the results to fit a Rabi curve and estimate parameters**\n",
"\n",
"In the cell below we first extract lists of expectations and std_errs from the results and store them separately by qubit. For each qubit we then fit to a sinusoid and evaluate the period (which should be $2\\pi$). Finally we plot the Rabi flop."
]
},
{
Expand All @@ -113,13 +109,12 @@
"\n",
"stats_by_qubit = get_stats_by_qubit(results)\n",
"for q, stats in stats_by_qubit.items():\n",
" fit = fit_rabi_results(angles, stats_by_qubit[q]['expectation'],\n",
" stats_by_qubit[q]['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit',xlabel=\"RX angle [rad]\",\n",
" fit = fit_rabi_results(angles, stats['expectation'], stats['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit', xlabel=\"RX angle [rad]\",\n",
" ylabel=r\"Pr($|1\\rangle$)\")\n",
" frequency = fit.params['frequency'].value # ratio of actual angle over intended control angle\n",
" amplitude = fit.params['amplitude'].value # (P(1 given 1) - P(1 given 0)) / 2\n",
" baseline = fit.params['baseline'].value # amplitude + p(1 given 0)\n"
" baseline = fit.params['baseline'].value # amplitude + p(1 given 0)"
]
},
{
Expand All @@ -137,5 +132,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}
29 changes: 17 additions & 12 deletions examples/qubit_spectroscopy_t1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
"source": [
"# Qubit spectroscopy: $T_1$ measurement example\n",
"\n",
"This notebook demonstrates how to assess the decoherence time, $T_1$, of one or more qubits on a real quantum device using pyQuil. A $T_1$ experiment consists of an X pulse, bringing the qubit from $|0\\rangle$ to $|1\\rangle$ (the excited state of the artifical atom), followed by a delay of variable duration. \n",
"This notebook demonstrates how to use the module `qubit_spectroscopy` to assess the \"energy relaxation\" time, $T_1$, of one or more qubits on a real quantum device using pyQuil. This one of the major sources of error on a quantum computer.\n",
"\n",
"The physics of the devices is such that We expect the state to decay exponentially with increasing time because of [\"energy relaxation\"](https://en.wikipedia.org/wiki/Relaxation_(NMR)). We characterize this decay by the time decay constant, which we call $\\Gamma =1/T_1$. The parameter $T_1$ is refered to as the qubit's \"relaxation\" or \"decoherence\" time. A sample QUIL program at one data point (specified by the duration of the DELAY pragma) for qubit 0 with a 10us wait would look like \n",
"\n",
"A $T_1$ experiment consists of an X pulse, bringing the qubit from $|0\\rangle$ to $|1\\rangle$ (the excited state of the artifical atom), followed by a delay of variable duration. \n",
"\n",
"The physics of the devices is such that we expect the state to decay exponentially with increasing time because of [\"energy relaxation\"](https://en.wikipedia.org/wiki/Relaxation_(NMR)). We characterize this decay by the `decay_time` constant, typically denoted $T_1 =1/\\Gamma$ where $\\Gamma$ is the decay rate. The parameter $T_1$ is refered to as the qubit's \"relaxation\" or \"decoherence\" time. A sample QUIL program at one data point (specified by the duration of the DELAY pragma) for qubit 0 with a 10us wait would look like \n",
"\n",
" DECLARE ro BIT[1]\n",
" RX(pi) 0\n",
Expand All @@ -22,7 +25,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## setup - imports and relevant units"
"### setup - imports and relevant units"
]
},
{
Expand All @@ -36,7 +39,7 @@
"\n",
"from forest.benchmarking.qubit_spectroscopy import (\n",
" generate_t1_experiments,\n",
" acquire_t1_data,\n",
" acquire_qubit_spectroscopy_data,\n",
" fit_t1_results, get_stats_by_qubit)"
]
},
Expand Down Expand Up @@ -76,7 +79,9 @@
"metadata": {},
"outputs": [],
"source": [
"# use this command to get the real QPU\n",
"#qc = get_qc('Aspen-1-15Q-A')\n",
"\n",
"qc = get_qc('2q-noisy-qvm') # will run on a QVM, but not meaningfully \n",
"qubits = qc.qubits()\n",
"qubits"
Expand Down Expand Up @@ -111,7 +116,7 @@
"source": [
"**Acquire data**\n",
"\n",
"Collect our $T_1$ raw data using `acquire_t1_data`. "
"Collect our $T_1$ raw data using `acquire_qubit_spectroscopy_data`. "
]
},
{
Expand All @@ -121,7 +126,7 @@
"outputs": [],
"source": [
"num_shots = 1000\n",
"results = acquire_t1_data(qc, expt, num_shots)"
"results = acquire_qubit_spectroscopy_data(qc, expt, num_shots)"
]
},
{
Expand All @@ -135,7 +140,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"This method takes a StratifiedExperiment object with all the $T_1$ data, including the times and qubit measured and the resulting decay at each data point, and fits to an exponential decay curve. "
"In the cell below we first extract lists of expectations and std_errs from the results and store them separately by qubit. For each qubit we then fit to an exponential decay curve and evaluate the `decay_time` constant, i.e. the T1. Finally we plot the decay curve fit over the data for each qubit."
]
},
{
Expand All @@ -148,11 +153,11 @@
"\n",
"stats_by_qubit = get_stats_by_qubit(results)\n",
"for q, stats in stats_by_qubit.items():\n",
" fit = fit_t1_results(np.asarray(times) / MICROSECOND, stats_by_qubit[q]['expectation'],\n",
" stats_by_qubit[q]['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit',xlabel=r\"Time [$\\mu s$]\",\n",
" fit = fit_t1_results(np.asarray(times) / MICROSECOND, stats['expectation'],\n",
" stats['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit', xlabel=r\"Time [$\\mu s$]\",\n",
" ylabel=r\"Pr($|1\\rangle$)\")\n",
" t1 = fit.params['decay_constant'].value # in us"
" t1 = fit.params['decay_time'].value # in us"
]
},
{
Expand All @@ -170,5 +175,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}
42 changes: 20 additions & 22 deletions examples/qubit_spectroscopy_t2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"source": [
"# Qubit spectroscopy: $T_2^*$ (Ramsey) and $T_2$-echo (Hahn echo) measurement example\n",
"\n",
"This notebook demonstrates how to assess the dephasing time, $T_2^*$, and detuning of one or more qubits on a real quantum device using pyQuil. \n",
"This notebook demonstrates how to assess the dephasing time or [spin–spin relaxation\n",
"](https://en.wikipedia.org/wiki/Spin%E2%80%93spin_relaxation), $T_2^*$, and detuning of one or more qubits on a real quantum device using pyQuil. \n",
"\n",
"A $T_2^*$ Ramsey experiment measures the dephasing time, $T_2^*$, of a qubit and the qubit's detuning, which is a measure of the difference between the qubit's resonant frequency and the frequency of the rotation pulses being used to perform the $T_2^*$ Ramsey experiment. Ideally, this detuning would be 0, meaning our pulses are perfectly tailored to address each qubit without enacting any unintended interactions with neighboring qubits. Practically, however, qubits drift, and the pulse parameters need to be updated. We retune our qubits and pulses regularly, but if you want to assess how well tuned the pulses are to the qubits' frequencies for yourself, you can run a $T_2^*$ Ramsey experiment and see how big the qubit detuning is. \n",
"\n",
Expand All @@ -30,7 +31,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## setup - imports and relevant units"
"### setup - imports and relevant units"
]
},
{
Expand All @@ -45,7 +46,7 @@
"from forest.benchmarking.qubit_spectroscopy import (\n",
" generate_t2_star_experiments,\n",
" generate_t2_echo_experiments,\n",
" acquire_t2_data,\n",
" acquire_qubit_spectroscopy_data,\n",
" fit_t2_results, get_stats_by_qubit)\n",
"from forest.benchmarking.plotting import plot_figure_for_fit\n"
]
Expand Down Expand Up @@ -74,13 +75,6 @@
"## measurement, analysis, and plotting"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This method takes in our simulated detuning frequency and a `pandas.DataFrame` object with all the $T_2^*$ data, including the times and qubits measured and the resulting decay at each data point, and plots the Ramsey fringes of each qubit with respect to increasing delay duration. It also fits to an exponentially-decay sinusoid, evaluates the fitted time decay constant, $T_2^*$, and fitted detuning for each qubit, and plots the fitted curve on top of the experimental data so that a user can assess the fit if so desired. "
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -145,14 +139,16 @@
"metadata": {},
"outputs": [],
"source": [
"results = acquire_t2_data(qc, t2_star_expt, num_shots=500)"
"results = acquire_qubit_spectroscopy_data(qc, t2_star_expt, num_shots=500)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Use the results to fit a curve and produce estimates of $T_2^*$**"
"**Use the results to fit a curve and produce estimates of $T_2^*$**\n",
"\n",
"In the cell below we first extract lists of expectations and std_errs from the results and store them separately by qubit. For each qubit we then fit to an exponentially decaying sinusoid and evaluate the fitted `decay_time` constant, i.e. the $T_2^*$, as well as the fitted detuning. Finally we plot the curve fit over the data for each qubit. These are the Ramsey fringes for each qubit with respect to increasing delay duration."
]
},
{
Expand All @@ -172,10 +168,12 @@
"\n",
"stats_by_qubit = get_stats_by_qubit(results)\n",
"for q, stats in stats_by_qubit.items():\n",
" fit = fit_t2_results(np.asarray(times) / MICROSECOND, stats_by_qubit[q]['expectation'],\n",
" stats_by_qubit[q]['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit',xlabel=r\"Time [$\\mu s$]\",\n",
" ylabel=r\"Pr($|1\\rangle$)\")"
" fit = fit_t2_results(np.asarray(times) / MICROSECOND, stats['expectation'],\n",
" stats['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit', xlabel=r\"Time [$\\mu s$]\",\n",
" ylabel=r\"Pr($|1\\rangle$)\")\n",
" t2_star = fit.params['decay_time'].value # in us\n",
" freq = fit.params['frequency'].value # in MHZ"
]
},
{
Expand Down Expand Up @@ -210,7 +208,7 @@
"metadata": {},
"outputs": [],
"source": [
"echo_results = acquire_t2_data(qc, t2_echo_expt)"
"echo_results = acquire_qubit_spectroscopy_data(qc, t2_echo_expt)"
]
},
{
Expand All @@ -230,11 +228,11 @@
"\n",
"stats_by_qubit = get_stats_by_qubit(echo_results)\n",
"for q, stats in stats_by_qubit.items():\n",
" fit = fit_t2_results(np.asarray(times) / MICROSECOND, stats_by_qubit[q]['expectation'],\n",
" stats_by_qubit[q]['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit',xlabel=r\"Time [$\\mu s$]\",\n",
" fit = fit_t2_results(np.asarray(times) / MICROSECOND, stats['expectation'],\n",
" stats['std_err'])\n",
" fig, axs = plot_figure_for_fit(fit, title=f'Q{q} Data and Fit', xlabel=r\"Time [$\\mu s$]\",\n",
" ylabel=r\"Pr($|1\\rangle$)\")\n",
" t2 = fit.params['decay_constant'].value # in us\n",
" t2_echo = fit.params['decay_time'].value # in us\n",
" freq = fit.params['frequency'].value # in MHZ"
]
},
Expand All @@ -253,5 +251,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}
Loading