Skip to content
2 changes: 0 additions & 2 deletions cirq-core/cirq/experiments/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
)

from cirq.experiments.qubit_characterizations import (
rabi_oscillations,
RabiResult,
RandomizedBenchMarkResult,
single_qubit_randomized_benchmarking,
single_qubit_state_tomography,
Expand Down
88 changes: 1 addition & 87 deletions cirq-core/cirq/experiments/qubit_characterizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@

from typing import Any, Iterator, List, Optional, Sequence, Tuple, TYPE_CHECKING
import numpy as np
import sympy

from matplotlib import pyplot as plt

# this is for older systems with matplotlib <3.2 otherwise 3d projections fail
from mpl_toolkits import mplot3d # pylint: disable=unused-import
from cirq import circuits, ops, protocols, study
from cirq import circuits, ops, protocols

if TYPE_CHECKING:
import cirq
Expand Down Expand Up @@ -54,52 +53,6 @@ class Cliffords:
s1_y: List[List[ops.Gate]]


class RabiResult:
"""Results from a Rabi oscillation experiment."""

def __init__(self, rabi_angles: Sequence[float], excited_state_probabilities: Sequence[float]):
"""Inits RabiResult.

Args:
rabi_angles: The rotation angles of the qubit around the x-axis
of the Bloch sphere.
excited_state_probabilities: The corresponding probabilities that
the qubit is in the excited state.
"""
self._rabi_angles = rabi_angles
self._excited_state_probs = excited_state_probabilities

@property
def data(self) -> Sequence[Tuple[float, float]]:
"""Returns a sequence of tuple pairs with the first item being a Rabi
angle and the second item being the corresponding excited state
probability.
"""
return [(angle, prob) for angle, prob in zip(self._rabi_angles, self._excited_state_probs)]

def plot(self, ax: Optional[plt.Axes] = None, **plot_kwargs: Any) -> plt.Axes:
"""Plots excited state probability vs the Rabi angle (angle of rotation
around the x-axis).

Args:
ax: the plt.Axes to plot on. If not given, a new figure is created,
plotted on, and shown.
**plot_kwargs: Arguments to be passed to 'plt.Axes.plot'.
Returns:
The plt.Axes containing the plot.
"""
show_plot = not ax
if not ax:
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
ax.set_ylim([0, 1])
ax.plot(self._rabi_angles, self._excited_state_probs, 'ro-', **plot_kwargs)
ax.set_xlabel(r"Rabi Angle (Radian)")
ax.set_ylabel('Excited State Probability')
if show_plot:
fig.show()
return ax


class RandomizedBenchMarkResult:
"""Results from a randomized benchmarking experiment."""

Expand Down Expand Up @@ -216,45 +169,6 @@ def plot(self, axes: Optional[List[plt.Axes]] = None, **plot_kwargs: Any) -> Lis
return axes


def rabi_oscillations(
sampler: 'cirq.Sampler',
qubit: 'cirq.Qid',
max_angle: float = 2 * np.pi,
*,
repetitions: int = 1000,
num_points: int = 200,
) -> RabiResult:
"""Runs a Rabi oscillation experiment.

Rotates a qubit around the x-axis of the Bloch sphere by a sequence of Rabi
angles evenly spaced between 0 and max_angle. For each rotation, repeat
the circuit a number of times and measure the average probability of the
qubit being in the |1> state.

Args:
sampler: The quantum engine or simulator to run the circuits.
qubit: The qubit under test.
max_angle: The final Rabi angle in radians.
repetitions: The number of repetitions of the circuit for each Rabi
angle.
num_points: The number of Rabi angles.

Returns:
A RabiResult object that stores and plots the result.
"""
theta = sympy.Symbol('theta')
circuit = circuits.Circuit(ops.X(qubit) ** theta)
circuit.append(ops.measure(qubit, key='z'))
sweep = study.Linspace(key='theta', start=0.0, stop=max_angle / np.pi, length=num_points)
results = sampler.run_sweep(circuit, params=sweep, repetitions=repetitions)
angles = np.linspace(0.0, max_angle, num_points)
excited_state_probs = np.zeros(num_points)
for i in range(num_points):
excited_state_probs[i] = np.mean(results[i].measurements['z'])

return RabiResult(angles, excited_state_probs)


def single_qubit_randomized_benchmarking(
sampler: 'cirq.Sampler',
qubit: 'cirq.Qid',
Expand Down
15 changes: 0 additions & 15 deletions cirq-core/cirq/experiments/qubit_characterizations_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,13 @@
from cirq import GridQubit
from cirq import circuits, ops, sim
from cirq.experiments import (
rabi_oscillations,
single_qubit_randomized_benchmarking,
two_qubit_randomized_benchmarking,
single_qubit_state_tomography,
two_qubit_state_tomography,
)


def test_rabi_oscillations():
# Check that the excited state population matches the ideal case within a
# small statistical error.
simulator = sim.Simulator()
qubit = GridQubit(0, 0)
results = rabi_oscillations(simulator, qubit, np.pi, repetitions=1000)
data = np.asarray(results.data)
angles = data[:, 0]
actual_pops = data[:, 1]
target_pops = 0.5 - 0.5 * np.cos(angles)
rms_err = np.sqrt(np.mean((target_pops - actual_pops) ** 2))
assert rms_err < 0.1


def test_single_qubit_cliffords():
I = np.eye(2)
X = np.array([[0, 1], [1, 0]])
Expand Down
5 changes: 0 additions & 5 deletions docs/tutorials/_index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ landing_page:
path: /cirq/tutorials/hidden_linear_function
icon:
name: menu_book
- heading: Rabi oscillation experiment
description: Example of using sweeps and symbols to show rotation of a qubit by different angles.
path: /cirq/tutorials/rabi_oscillations
icon:
name: menu_book
- heading: Shor's algorithm
description: Factor numbers using a quantum computer.
path: /cirq/tutorials/shor
Expand Down
Loading