diff --git a/cirq-core/cirq/experiments/__init__.py b/cirq-core/cirq/experiments/__init__.py
index 5f9183272c4..70732a51977 100644
--- a/cirq-core/cirq/experiments/__init__.py
+++ b/cirq-core/cirq/experiments/__init__.py
@@ -20,8 +20,6 @@
)
from cirq.experiments.qubit_characterizations import (
- rabi_oscillations,
- RabiResult,
RandomizedBenchMarkResult,
single_qubit_randomized_benchmarking,
single_qubit_state_tomography,
diff --git a/cirq-core/cirq/experiments/qubit_characterizations.py b/cirq-core/cirq/experiments/qubit_characterizations.py
index 917e4277152..e884638b78d 100644
--- a/cirq-core/cirq/experiments/qubit_characterizations.py
+++ b/cirq-core/cirq/experiments/qubit_characterizations.py
@@ -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
@@ -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."""
@@ -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',
diff --git a/cirq-core/cirq/experiments/qubit_characterizations_test.py b/cirq-core/cirq/experiments/qubit_characterizations_test.py
index d565f11d0a3..baa82c02ffc 100644
--- a/cirq-core/cirq/experiments/qubit_characterizations_test.py
+++ b/cirq-core/cirq/experiments/qubit_characterizations_test.py
@@ -22,7 +22,6 @@
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,
@@ -30,20 +29,6 @@
)
-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]])
diff --git a/docs/tutorials/_index.yaml b/docs/tutorials/_index.yaml
index 9e3dd8bc3ff..d48bb79d084 100644
--- a/docs/tutorials/_index.yaml
+++ b/docs/tutorials/_index.yaml
@@ -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
diff --git a/docs/tutorials/educators/intro.ipynb b/docs/tutorials/educators/intro.ipynb
index 12634b3a2d0..93341230d46 100644
--- a/docs/tutorials/educators/intro.ipynb
+++ b/docs/tutorials/educators/intro.ipynb
@@ -2,14 +2,14 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "906e07f6e562"
},
"outputs": [],
"source": [
- "#@title Copyright 2022 The Cirq Developers\n",
+ "# @title Copyright 2022 The Cirq Developers\n",
"# 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",
@@ -90,7 +90,7 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": null,
"metadata": {
"id": "RlJBDvNgC00H"
},
@@ -122,49 +122,15 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
"metadata": {
"id": "FTrmLyq4C2gf"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " (0, 5)───(0, 6)\n",
- " │ │\n",
- " │ │\n",
- " (1, 4)───(1, 5)───(1, 6)───(1, 7)\n",
- " │ │ │ │\n",
- " │ │ │ │\n",
- " (2, 3)───(2, 4)───(2, 5)───(2, 6)───(2, 7)───(2, 8)\n",
- " │ │ │ │ │ │\n",
- " │ │ │ │ │ │\n",
- " (3, 2)───(3, 3)───(3, 4)───(3, 5)───(3, 6)───(3, 7)───(3, 8)───(3, 9)\n",
- " │ │ │ │ │ │ │ │\n",
- " │ │ │ │ │ │ │ │\n",
- " (4, 1)───(4, 2)───(4, 3)───(4, 4)───(4, 5)───(4, 6)───(4, 7)───(4, 8)───(4, 9)\n",
- " │ │ │ │ │ │ │ │\n",
- " │ │ │ │ │ │ │ │\n",
- "(5, 0)───(5, 1)───(5, 2)───(5, 3)───(5, 4)───(5, 5)───(5, 6)───(5, 7)───(5, 8)\n",
- " │ │ │ │ │ │ │\n",
- " │ │ │ │ │ │ │\n",
- " (6, 1)───(6, 2)───(6, 3)───(6, 4)───(6, 5)───(6, 6)───(6, 7)\n",
- " │ │ │ │ │\n",
- " │ │ │ │ │\n",
- " (7, 2)───(7, 3)───(7, 4)───(7, 5)───(7, 6)\n",
- " │ │ │\n",
- " │ │ │\n",
- " (8, 3)───(8, 4)───(8, 5)\n",
- " │\n",
- " │\n",
- " (9, 4)\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Test successful installation by printing out the Sycamore device.\"\"\"\n",
"import cirq_google\n",
+ "\n",
"print(cirq_google.Sycamore)"
]
},
@@ -242,25 +208,11 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": null,
"metadata": {
"id": "pE88WsFeDGfs"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit:\n",
- "\n",
- "a: ───H───────────\n",
- "\n",
- "b: ───H───@───H───\n",
- " │\n",
- "c: ───────X───────\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Creating a circuit.\"\"\"\n",
"# Define three qubits.\n",
@@ -304,14 +256,14 @@
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "6a5TEN5bKAPz"
},
"outputs": [],
"source": [
- "#@title Attempt the solution here\n",
+ "# @title Attempt the solution here\n",
"\n",
"# Define 4 qubits.\n",
"\n",
@@ -322,32 +274,14 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "Q52e1pX_JIdi"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit:\n",
- "\n",
- " ┌──┐\n",
- "0: ───H─────@────────\n",
- " │\n",
- "1: ───H────@┼────H───\n",
- " ││\n",
- "2: ────────X┼────────\n",
- " │\n",
- "3: ─────────X────────\n",
- " └──┘\n"
- ]
- }
- ],
- "source": [
- "#@title Expand to view the solution\n",
+ "outputs": [],
+ "source": [
+ "# @title Expand to view the solution\n",
"\"\"\"Creating a circuit.\"\"\"\n",
"# Define four line qubits. NamedQubits would also work, however this demonstrates a more succint syntax.\n",
"q = cirq.LineQubit.range(4)\n",
@@ -382,23 +316,11 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": null,
"metadata": {
"id": "YKfg575v1DQB"
},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.70710678+0.j, 0.70710678+0.j],\n",
- " [ 0.70710678+0.j, -0.70710678+0.j]])"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Get the unitary of a gate, here the Hadamard gate.\"\"\"\n",
"cirq.unitary(cirq.H)"
@@ -432,47 +354,11 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": null,
"metadata": {
"id": "hH-y4JiEMv25"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit:\n",
- "\n",
- "a: ───H───────────\n",
- "\n",
- "b: ───H───@───H───\n",
- " │\n",
- "c: ───────X───────\n",
- "\n",
- "Moments in the circuit:\n",
- "\n",
- "Moment 0: \n",
- " ╷ None\n",
- "╶─┼──────\n",
- "a │ H\n",
- " │\n",
- "b │ H\n",
- " │\n",
- "Moment 1: \n",
- " ╷ None\n",
- "╶─┼──────\n",
- "b │ @\n",
- " │ │\n",
- "c │ X\n",
- " │\n",
- "Moment 2: \n",
- " ╷ None\n",
- "╶─┼──────\n",
- "b │ H\n",
- " │\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Print out the moments in a circuit.\"\"\"\n",
"print(\"Circuit:\\n\")\n",
@@ -481,7 +367,7 @@
"# Inspecting individual moments.\n",
"print(\"\\nMoments in the circuit:\\n\")\n",
"for i, moment in enumerate(circuit):\n",
- " print('Moment {}: \\n{}'.format(i, moment))"
+ " print(f'Moment {i}: \\n{moment}')"
]
},
{
@@ -495,30 +381,11 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": null,
"metadata": {
"id": "2Y6zG_peQG1y"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "cirq.Circuit([\n",
- " cirq.Moment(\n",
- " cirq.H(cirq.NamedQubit('a')),\n",
- " cirq.H(cirq.NamedQubit('b')),\n",
- " ),\n",
- " cirq.Moment(\n",
- " cirq.CNOT(cirq.NamedQubit('b'), cirq.NamedQubit('c')),\n",
- " ),\n",
- " cirq.Moment(\n",
- " cirq.H(cirq.NamedQubit('b')),\n",
- " ),\n",
- "])\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Print the repr of a circuit.\"\"\"\n",
"print(repr(circuit))"
@@ -576,36 +443,21 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": null,
"metadata": {
"id": "QFoV-eOE1tGN"
},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
a: ───@───X───@───\n",
- " │ │ │\n",
- "b: ───X───@───X─── "
- ],
- "text/plain": [
- "a: ───@───X───@───\n",
- " │ │ │\n",
- "b: ───X───@───X───"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Creating a circuit from generator functions.\"\"\"\n",
+ "\n",
+ "\n",
"def xor_swap(a, b):\n",
" \"\"\"Swaps two qubits with three CNOTs.\"\"\"\n",
- " yield cirq.CNOT(a, b) # |a> |b> --> |a> |a ^ b>\n",
- " yield cirq.CNOT(b, a) # |a> |a ^ b> --> |a ^ a ^ b> | a ^ b> = |b>|a^b>\n",
- " yield cirq.CNOT(a, b) # |b> |a ^ b> --> |b>|a ^ b ^ b> = |b> |a>\n",
+ " yield cirq.CNOT(a, b) # |a> |b> --> |a> |a ^ b>\n",
+ " yield cirq.CNOT(b, a) # |a> |a ^ b> --> |a ^ a ^ b> | a ^ b> = |b>|a^b>\n",
+ " yield cirq.CNOT(a, b) # |b> |a ^ b> --> |b>|a ^ b ^ b> = |b> |a>\n",
+ "\n",
"\n",
"cirq.Circuit(xor_swap(a, b))"
]
@@ -630,30 +482,30 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "LbIZIMINEzD9"
},
"outputs": [],
"source": [
- "#@title Attempt the solution here"
+ "# @title Attempt the solution here"
]
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "5oqmyccsE1kK"
},
"outputs": [],
"source": [
- "#@title Expand to view the solution\n",
+ "# @title Expand to view the solution\n",
"def left_rotate(qubits):\n",
" \"\"\"Rotates qubits to the left.\"\"\"\n",
" for i in range(len(qubits) - 1):\n",
- " a, b = qubits[i: i + 2]\n",
+ " a, b = qubits[i : i + 2]\n",
" yield xor_swap(a, b)\n",
"\n",
"\n",
@@ -718,25 +570,11 @@
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": null,
"metadata": {
"id": "wNek1WjpX4MR"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit:\n",
- "\n",
- "a: ───@───H───\n",
- " │\n",
- "b: ───@───H───\n",
- "\n",
- "c: ───H───────\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Appending operations with InsertStrategy.EARLIEST.\"\"\"\n",
"# Create an empty circuit.\n",
@@ -786,25 +624,11 @@
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": null,
"metadata": {
"id": "qWVDhLxFYuRp"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit:\n",
- "\n",
- "a: ───@───H───\n",
- " │\n",
- "b: ───@───H───\n",
- "\n",
- "c: ───────H───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Appending operations with InsertStrategy.NEW_THEN_INLINE.\"\"\"\n",
"# Create an empty circuit.\n",
@@ -855,40 +679,26 @@
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "-HXXD801OFGF"
},
"outputs": [],
"source": [
- "#@title Attempt the solution here"
+ "# @title Attempt the solution here"
]
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "jP4VkPeHcjJT"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit:\n",
- "\n",
- "a: ───@───H───────────H───H───\n",
- " │\n",
- "b: ───@───────H───@───H───────\n",
- " │\n",
- "c: ───H───────────@───────────\n"
- ]
- }
- ],
- "source": [
- "#@title Expand to view the solution\n",
+ "outputs": [],
+ "source": [
+ "# @title Expand to view the solution\n",
"# Define three qubits.\n",
"a = cirq.NamedQubit('a')\n",
"b = cirq.NamedQubit('b')\n",
@@ -903,7 +713,7 @@
"# Append these gates using cirq.InsertStrategy.NEW_THEN_INLINE.\n",
"circuit.append(\n",
" [cirq.H(b), cirq.CZ(b, c), cirq.H(b), cirq.H(a), cirq.H(a)],\n",
- " strategy=cirq.InsertStrategy.NEW_THEN_INLINE\n",
+ " strategy=cirq.InsertStrategy.NEW_THEN_INLINE,\n",
")\n",
"\n",
"# Display the circuit.\n",
@@ -924,23 +734,15 @@
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": null,
"metadata": {
"id": "V6tZk3qGqBoH"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a: ───X^0.5───@───X^0.5───M───\n",
- " │ │\n",
- "b: ───X^0.5───@───X^0.5───M───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Get a circuit to simulate.\"\"\"\n",
+ "\n",
+ "\n",
"def basic_circuit(measure=True):\n",
" \"\"\"Returns a simple circuit with some one- and two-qubit gates,\n",
" as well as (optionally) measurements.\n",
@@ -948,13 +750,14 @@
" # Gates we will use in the circuit.\n",
" sqrt_x = cirq.X**0.5\n",
" cz = cirq.CZ\n",
- " \n",
+ "\n",
" # Yield the operations.\n",
" yield sqrt_x(a), sqrt_x(b)\n",
" yield cz(a, b)\n",
" yield sqrt_x(a), sqrt_x(b)\n",
" if measure:\n",
- " yield cirq.measure(a,b)\n",
+ " yield cirq.measure(a, b)\n",
+ "\n",
"\n",
"# Create a circuit including measurements.\n",
"circuit = cirq.Circuit(basic_circuit())\n",
@@ -972,20 +775,11 @@
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": null,
"metadata": {
"id": "KmGuMjvGw_Ef"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Measurement results:\n",
- "a,b=1, 0\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Example of simulating a circuit in Cirq.\"\"\"\n",
"# Get a simulator.\n",
@@ -1021,23 +815,11 @@
},
{
"cell_type": "code",
- "execution_count": 19,
+ "execution_count": null,
"metadata": {
"id": "Apj7WiFZ0WFm"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "State vector:\n",
- "[0.5+0.j 0. +0.5j 0. +0.5j 0.5+0.j ]\n",
- "\n",
- "Dirac notation:\n",
- "0.5|00⟩ + 0.5j|01⟩ + 0.5j|10⟩ + 0.5|11⟩\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Simulating a circuit with the `simulate` method.\"\"\"\n",
"# Get a circuit without measurements.\n",
@@ -1108,41 +890,11 @@
},
{
"cell_type": "code",
- "execution_count": 20,
+ "execution_count": null,
"metadata": {
"id": "QxkmBlo21lrQ"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Counter({0: 255, 1: 253, 2: 251, 3: 241})\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 20,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Simulate a circuit using 1000 repetitions.\"\"\"\n",
"# Get a circuit with terminal measurements to simulate.\n",
@@ -1172,21 +924,17 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": null,
"metadata": {
"id": "rPqVUsD9snYf"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Counter({'disagree': 504, 'agree': 496})\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
- "print(result.histogram(key=\"a,b\", fold_func=lambda bits: \"agree\" if bits[0] == bits[1] else \"disagree\"))"
+ "print(\n",
+ " result.histogram(\n",
+ " key=\"a,b\", fold_func=lambda bits: \"agree\" if bits[0] == bits[1] else \"disagree\"\n",
+ " )\n",
+ ")"
]
},
{
@@ -1286,7 +1034,7 @@
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": null,
"metadata": {
"id": "YtWiBHonly69"
},
@@ -1302,8 +1050,8 @@
" '0': [],\n",
" '1': [cirq.X(q1)],\n",
" 'x': [cirq.CNOT(q0, q1)],\n",
- " 'notx': [cirq.CNOT(q0, q1), cirq.X(q1)]\n",
- "} "
+ " 'notx': [cirq.CNOT(q0, q1), cirq.X(q1)],\n",
+ "}"
]
},
{
@@ -1348,40 +1096,15 @@
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": null,
"metadata": {
"id": "aMHzLxztj-gq"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit for f_0:\n",
- "0: ───H───H───M───\n",
- "\n",
- "1: ───X───H───────\n",
- "\n",
- "Circuit for f_1:\n",
- "0: ───H───H───M───\n",
- "\n",
- "1: ───X───H───X───\n",
- "\n",
- "Circuit for f_x:\n",
- "0: ───H───────@───H───M───\n",
- " │\n",
- "1: ───X───H───X───────────\n",
- "\n",
- "Circuit for f_notx:\n",
- "0: ───H───────@───H───M───\n",
- " │\n",
- "1: ───X───H───X───X───────\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Creating the circuit used in Deutsch's algorithm.\"\"\"\n",
+ "\n",
+ "\n",
"def deutsch_algorithm(oracle):\n",
" \"\"\"Returns the circuit for Deutsch's algorithm given an input\n",
" oracle, i.e., a sequence of operations to query a particular function.\n",
@@ -1392,6 +1115,7 @@
" yield cirq.H(q0)\n",
" yield cirq.measure(q0)\n",
"\n",
+ "\n",
"for key, oracle in oracles.items():\n",
" print(f\"Circuit for f_{key}:\")\n",
" print(cirq.Circuit(deutsch_algorithm(oracle)), end=\"\\n\\n\")"
@@ -1408,29 +1132,17 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": null,
"metadata": {
"id": "ImffrBgJvLme"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "oracle: f_0 results: 0=0000000000\n",
- "oracle: f_1 results: 0=0000000000\n",
- "oracle: f_x results: 0=1111111111\n",
- "oracle: f_notx results: 0=1111111111\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Simulate each of the circuits.\"\"\"\n",
"simulator = cirq.Simulator()\n",
"for key, oracle in oracles.items():\n",
- " result = simulator.run(cirq.Circuit(deutsch_algorithm(oracle)), \n",
- " repetitions=10)\n",
- " print('oracle: f_{:<4} results: {}'.format(key, result))"
+ " result = simulator.run(cirq.Circuit(deutsch_algorithm(oracle)), repetitions=10)\n",
+ " print(f'oracle: f_{key:<4} results: {result}')"
]
},
{
@@ -1465,7 +1177,7 @@
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": null,
"metadata": {
"id": "V5ZCXGCrxl4k"
},
@@ -1478,19 +1190,16 @@
"q0, q1, q2 = cirq.LineQubit.range(3)\n",
"\n",
"# Define the operations to query each of the two constant functions.\n",
- "constant = (\n",
- " [], \n",
- " [cirq.X(q2)]\n",
- ")\n",
+ "constant = ([], [cirq.X(q2)])\n",
"\n",
"# Define the operations to query each of the six balanced functions.\n",
"balanced = (\n",
- " [cirq.CNOT(q0, q2)], \n",
- " [cirq.CNOT(q1, q2)], \n",
+ " [cirq.CNOT(q0, q2)],\n",
+ " [cirq.CNOT(q1, q2)],\n",
" [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2)],\n",
- " [cirq.CNOT(q0, q2), cirq.X(q2)], \n",
- " [cirq.CNOT(q1, q2), cirq.X(q2)], \n",
- " [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2), cirq.X(q2)]\n",
+ " [cirq.CNOT(q0, q2), cirq.X(q2)],\n",
+ " [cirq.CNOT(q1, q2), cirq.X(q2)],\n",
+ " [cirq.CNOT(q0, q2), cirq.CNOT(q1, q2), cirq.X(q2)],\n",
")"
]
},
@@ -1505,17 +1214,19 @@
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "qJP_e68e1JBs"
},
"outputs": [],
"source": [
- "#@title Attempt the solution here\n",
+ "# @title Attempt the solution here\n",
"\"\"\"Exercise: Write a quantum circuit that can distinguish \n",
"constant from balanced functions on two bits.\n",
"\"\"\"\n",
+ "\n",
+ "\n",
"def your_circuit(oracle):\n",
" # Your code here!\n",
" yield oracle\n",
@@ -1534,39 +1245,20 @@
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": null,
"metadata": {
"id": "81da6ec6fc5a"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "Your result on constant functions:\n",
- "2=0000000000\n",
- "2=1111111111\n",
- "\n",
- "Your result on balanced functions:\n",
- "2=0000000000\n",
- "2=0000000000\n",
- "2=0000000000\n",
- "2=1111111111\n",
- "2=1111111111\n",
- "2=1111111111\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Check your answer by running this cell.\"\"\"\n",
"simulator = cirq.Simulator()\n",
- " \n",
+ "\n",
"print(\"\\nYour result on constant functions:\")\n",
"for oracle in constant:\n",
" result = simulator.run(cirq.Circuit(your_circuit(oracle)), repetitions=10)\n",
" print(result)\n",
- " \n",
+ "\n",
"print(\"\\nYour result on balanced functions:\")\n",
"for oracle in balanced:\n",
" result = simulator.run(cirq.Circuit(your_circuit(oracle)), repetitions=10)\n",
@@ -1575,27 +1267,27 @@
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "mUvm9rmRFb4p"
},
"outputs": [],
"source": [
- "#@title Expand to view the solution\n",
+ "# @title Expand to view the solution\n",
"def dj_circuit(oracle):\n",
" # Phase kickback trick.\n",
" yield cirq.X(q2), cirq.H(q2)\n",
- " \n",
+ "\n",
" # Get an equal superposition over input bits.\n",
" yield cirq.H(q0), cirq.H(q1)\n",
- " \n",
+ "\n",
" # Query the function.\n",
" yield oracle\n",
- " \n",
+ "\n",
" # Use interference to get result, put last qubit into |1>.\n",
" yield cirq.H(q0), cirq.H(q1), cirq.H(q2)\n",
- " \n",
+ "\n",
" # Use a final OR gate to put result in final qubit.\n",
" yield cirq.X(q0), cirq.X(q1), cirq.CCX(q0, q1, q2)\n",
" yield cirq.measure(q2)"
@@ -1612,36 +1304,18 @@
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": null,
"metadata": {
"id": "c1b1e989dab2"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Result on constant functions:\n",
- "2=0000000000\n",
- "2=0000000000\n",
- "\n",
- "Result on balanced functions:\n",
- "2=1111111111\n",
- "2=1111111111\n",
- "2=1111111111\n",
- "2=1111111111\n",
- "2=1111111111\n",
- "2=1111111111\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Simulate the Deutsch-Jozsa circuit and check the results.\"\"\"\n",
"print(\"Result on constant functions:\")\n",
"for oracle in constant:\n",
" result = simulator.run(cirq.Circuit(dj_circuit(oracle)), repetitions=10)\n",
" print(result)\n",
- " \n",
+ "\n",
"print(\"\\nResult on balanced functions:\")\n",
"for oracle in balanced:\n",
" result = simulator.run(cirq.Circuit(dj_circuit(oracle)), repetitions=10)\n",
@@ -1677,23 +1351,11 @@
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": null,
"metadata": {
"id": "iIpoDaqK4yjV"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0: ───X───@───H───────@───×───@───@───iSwap──────Rx(0.5π)───X^0.5───\n",
- " │ │ │ │ │ │\n",
- "1: ───Y───@───@───T───@───×───×───@───iSwap──────Ry(0.5π)───────────\n",
- " │ │ │ │\n",
- "2: ───Z───────X───S───@───────×───X───Rz(0.5π)──────────────────────\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Examples of common gates defined in Cirq.\"\"\"\n",
"# Get some qubits.\n",
@@ -1701,23 +1363,23 @@
"\n",
"# Get a bunch of common gates defined in Cirq.\n",
"ops = [\n",
- " cirq.X(q0), # Pauli-X.\n",
- " cirq.Y(q1), # Pauli-Y.\n",
- " cirq.Z(q2), # Pauli-Z.\n",
- " cirq.CZ(q0,q1), # Controlled-Z gate.\n",
- " cirq.CNOT(q1,q2), # Controlled-X gate.\n",
- " cirq.H(q0), # Hadamard gate.\n",
- " cirq.T(q1), # T gate.\n",
- " cirq.S(q2), # S gate.\n",
- " cirq.CCZ(q0, q1, q2), # Controlled CZ gate.\n",
- " cirq.SWAP(q0, q1), # Swap gate.\n",
- " cirq.CSWAP(q0, q1, q2), # Controlled swap gate.\n",
- " cirq.CCX(q0, q1, q2), # Toffoli (CCNOT) gate.\n",
- " cirq.ISWAP(q0, q1), # ISWAP gate.\n",
+ " cirq.X(q0), # Pauli-X.\n",
+ " cirq.Y(q1), # Pauli-Y.\n",
+ " cirq.Z(q2), # Pauli-Z.\n",
+ " cirq.CZ(q0, q1), # Controlled-Z gate.\n",
+ " cirq.CNOT(q1, q2), # Controlled-X gate.\n",
+ " cirq.H(q0), # Hadamard gate.\n",
+ " cirq.T(q1), # T gate.\n",
+ " cirq.S(q2), # S gate.\n",
+ " cirq.CCZ(q0, q1, q2), # Controlled CZ gate.\n",
+ " cirq.SWAP(q0, q1), # Swap gate.\n",
+ " cirq.CSWAP(q0, q1, q2), # Controlled swap gate.\n",
+ " cirq.CCX(q0, q1, q2), # Toffoli (CCNOT) gate.\n",
+ " cirq.ISWAP(q0, q1), # ISWAP gate.\n",
" cirq.Rx(rads=0.5 * np.pi)(q0), # Rotation about X.\n",
" cirq.Ry(rads=0.5 * np.pi)(q1), # Rotation about Y.\n",
" cirq.Rz(rads=0.5 * np.pi)(q2), # Rotation about Z.\n",
- " cirq.X(q0) ** 0.5, # Sqrt of NOT gate.\n",
+ " cirq.X(q0) ** 0.5, # Sqrt of NOT gate.\n",
"]\n",
"\n",
"# Display a circuit with all of these operations.\n",
@@ -1735,22 +1397,11 @@
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": null,
"metadata": {
"id": "7SUAT5F17afR"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n",
- " [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n",
- " [0.+0.j 0.+0.j 0.+0.j 1.+0.j]\n",
- " [0.+0.j 0.+0.j 1.+0.j 0.+0.j]]\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Get the unitary of CNOT.\"\"\"\n",
"print(cirq.unitary(cirq.CNOT))"
@@ -1781,22 +1432,11 @@
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": null,
"metadata": {
"id": "UgoNBN1H8B6h"
},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Plot the probability of measuring a qubit in the ground state.\"\"\"\n",
"# Get a qubit.\n",
@@ -1832,22 +1472,11 @@
},
{
"cell_type": "code",
- "execution_count": 33,
+ "execution_count": null,
"metadata": {
"id": "iynhJEvoCIro"
},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Plot the probability of measuring a qubit in the ground state by sampling.\"\"\"\n",
"# Number of times to sample.\n",
@@ -1860,7 +1489,7 @@
" samples = step.sample([a], repetitions=repetitions)\n",
" prob = np.sum(samples, axis=0)[0] / repetitions\n",
" sampled_probs.append(prob)\n",
- " \n",
+ "\n",
"\n",
"# Plot the probability of the ground state at each simulation step.\n",
"plt.style.use('seaborn-whitegrid')\n",
@@ -1901,18 +1530,19 @@
},
{
"cell_type": "code",
- "execution_count": 34,
+ "execution_count": null,
"metadata": {
"id": "Y2a7t2qmLDTb"
},
"outputs": [],
"source": [
"\"\"\"Example of defining a custom gate in Cirq.\"\"\"\n",
+ "\n",
+ "\n",
"class RationalGate(cirq.SingleQubitGate):\n",
- " \n",
" def _unitary_(self):\n",
" return np.array([[3 / 5, 4 / 5], [-4 / 5, 3 / 5]])\n",
- " \n",
+ "\n",
" def __str__(self):\n",
" return 'ζ'"
]
@@ -1928,19 +1558,11 @@
},
{
"cell_type": "code",
- "execution_count": 35,
+ "execution_count": null,
"metadata": {
"id": "28f06d1baf9b"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a: ───ζ───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Using the custom gate in a circuit.\"\"\"\n",
"a = cirq.NamedQubit('a')\n",
@@ -1959,20 +1581,11 @@
},
{
"cell_type": "code",
- "execution_count": 36,
+ "execution_count": null,
"metadata": {
"id": "x9dHKNfgMoyz"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[ 0.6 0.8]\n",
- " [-0.8 0.6]]\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"print(cirq.unitary(rg))"
]
@@ -1988,19 +1601,11 @@
},
{
"cell_type": "code",
- "execution_count": 37,
+ "execution_count": null,
"metadata": {
"id": "_RXBrSQ8PWnu"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[ 0.6+0.j -0.8+0.j]\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Simulate a circuit with a custom gate.\"\"\"\n",
"circuit = cirq.Circuit(rg(a))\n",
@@ -2047,23 +1652,17 @@
},
{
"cell_type": "code",
- "execution_count": 38,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "9htgTzqAYHsA"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[]\n"
- ]
- }
- ],
- "source": [
- "#@title Attempt the solution here\n",
+ "outputs": [],
+ "source": [
+ "# @title Attempt the solution here\n",
"\"\"\"Define a custom controlled cirq.rx gate here.\"\"\"\n",
+ "\n",
+ "\n",
"class CRx(cirq.Gate):\n",
" def __init__(self, theta):\n",
" self.theta = theta\n",
@@ -2072,37 +1671,30 @@
" return 2\n",
"\n",
" def _unitary_(self):\n",
- " return np.array([\n",
- " # Your code here!\n",
- " ])\n",
+ " return np.array(\n",
+ " [\n",
+ " # Your code here!\n",
+ " ]\n",
+ " )\n",
"\n",
"\n",
"# Print out its unitary.\n",
- "print(np.around(cirq.unitary(CRx(0.5 * np.pi)), 3)) "
+ "print(np.around(cirq.unitary(CRx(0.5 * np.pi)), 3))"
]
},
{
"cell_type": "code",
- "execution_count": 39,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "XaG8n5bdGgf2"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[1. +0.j 0. +0.j 0. +0.j 0. +0.j ]\n",
- " [0. +0.j 1. +0.j 0. +0.j 0. +0.j ]\n",
- " [0. +0.j 0. +0.j 0.707+0.j 0. -0.707j]\n",
- " [0. +0.j 0. +0.j 0. -0.707j 0.707+0.j ]]\n"
- ]
- }
- ],
- "source": [
- "#@title Expand to view the solution\n",
+ "outputs": [],
+ "source": [
+ "# @title Expand to view the solution\n",
"\"\"\"Defining a custom controlled cirq.Rx gate.\"\"\"\n",
+ "\n",
+ "\n",
"class CRx(cirq.Gate):\n",
" def __init__(self, theta):\n",
" self.theta = theta\n",
@@ -2111,19 +1703,21 @@
" return 2\n",
"\n",
" def _unitary_(self):\n",
- " return np.array([\n",
- " [1, 0, 0, 0],\n",
- " [0, 1, 0, 0],\n",
- " [0, 0, np.cos(self.theta/2), -1j * np.sin(self.theta/2)],\n",
- " [0, 0, -1j * np.sin(self.theta/2), np.cos(self.theta/2)]\n",
- " ])\n",
- " \n",
+ " return np.array(\n",
+ " [\n",
+ " [1, 0, 0, 0],\n",
+ " [0, 1, 0, 0],\n",
+ " [0, 0, np.cos(self.theta / 2), -1j * np.sin(self.theta / 2)],\n",
+ " [0, 0, -1j * np.sin(self.theta / 2), np.cos(self.theta / 2)],\n",
+ " ]\n",
+ " )\n",
+ "\n",
" def _circuit_diagram_info_(self, args):\n",
- " return '@', 'Rx({}π)'.format(self.theta / np.pi)\n",
+ " return '@', f'Rx({self.theta / np.pi}π)'\n",
"\n",
"\n",
"# Print out its unitary.\n",
- "print(np.around(cirq.unitary(CRx(0.5 * np.pi)), 3)) "
+ "print(np.around(cirq.unitary(CRx(0.5 * np.pi)), 3))"
]
},
{
@@ -2137,22 +1731,11 @@
},
{
"cell_type": "code",
- "execution_count": 40,
+ "execution_count": null,
"metadata": {
"id": "a1cd089df7ba"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit diagram:\n",
- "a: ───@───────────\n",
- " │\n",
- "b: ───Rx(0.25π)───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Display a circuit with the custom gate.\"\"\"\n",
"# Get qubits.\n",
@@ -2188,18 +1771,19 @@
},
{
"cell_type": "code",
- "execution_count": 41,
+ "execution_count": null,
"metadata": {
"id": "9G-9_29h09Mx"
},
"outputs": [],
"source": [
"\"\"\"Example of a custom gate which supports the decompose protocol.\"\"\"\n",
+ "\n",
+ "\n",
"class HXGate(cirq.SingleQubitGate):\n",
- " \n",
" def _decompose_(self, qubits):\n",
" return cirq.H(*qubits), cirq.X(*qubits)\n",
- " \n",
+ "\n",
" def __str__(self):\n",
" return 'HX'"
]
@@ -2215,22 +1799,11 @@
},
{
"cell_type": "code",
- "execution_count": 42,
+ "execution_count": null,
"metadata": {
"id": "370e8528c762"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a: ───HX───\n",
- "\n",
- "[[ 0.70710678+0.j -0.70710678+0.j]\n",
- " [ 0.70710678+0.j 0.70710678+0.j]]\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Use the gate in a circuit.\"\"\"\n",
"HX = HXGate()\n",
@@ -2252,19 +1825,11 @@
},
{
"cell_type": "code",
- "execution_count": 43,
+ "execution_count": null,
"metadata": {
"id": "47ec94cdecf3"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a: ───Y^0.5───X───X───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Decompose the gate.\"\"\"\n",
"print(cirq.Circuit(cirq.decompose(circuit)))"
@@ -2281,19 +1846,11 @@
},
{
"cell_type": "code",
- "execution_count": 44,
+ "execution_count": null,
"metadata": {
"id": "AS-YMmAv6zUg"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a: ───H───X───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Decompose the gate once.\"\"\"\n",
"print(cirq.Circuit(cirq.decompose_once(HX(a))))"
@@ -2327,7 +1884,7 @@
},
{
"cell_type": "code",
- "execution_count": 45,
+ "execution_count": null,
"metadata": {
"id": "YnaqZI6dRNxX"
},
@@ -2339,10 +1896,10 @@
"\n",
"# Valid gates and operations are accepted by the gateset.\n",
"assert cirq.CNOT(*cirq.LineQubit.range(2)) in gateset\n",
- "assert cirq.X ** 0.5 in gateset\n",
+ "assert cirq.X**0.5 in gateset\n",
"\n",
"# Arbitrary powers of cirq.CXPowGate are not part of the gateset.\n",
- "assert cirq.CNOT ** 0.5 not in gateset"
+ "assert cirq.CNOT**0.5 not in gateset"
]
},
{
@@ -2360,23 +1917,11 @@
},
{
"cell_type": "code",
- "execution_count": 46,
+ "execution_count": null,
"metadata": {
"id": "0afe36a32636"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit with parameterized gates:\n",
- "\n",
- "a: ───X^s───\n",
- "\n",
- "b: ───X^s───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Define a circuit with parameterized gates.\"\"\"\n",
"# Import sympy for parameterized values.\n",
@@ -2408,28 +1953,11 @@
},
{
"cell_type": "code",
- "execution_count": 47,
+ "execution_count": null,
"metadata": {
"id": "TIaVRzCD4deU"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "s=0: [1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n",
- "\n",
- "s=1: [ 0.6 +0.6j 0.25-0.25j 0.25-0.25j -0.1 -0.1j ]\n",
- "\n",
- "s=2: [0. +0.5j 0.5+0.j 0.5+0.j 0. -0.5j]\n",
- "\n",
- "s=3: [-0.1 +0.1j 0.25+0.25j 0.25+0.25j 0.6 -0.6j ]\n",
- "\n",
- "s=4: [0.+0.j 0.+0.j 0.+0.j 1.+0.j]\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Simulate the circuit at multiple parameter values.\"\"\"\n",
"simulator = cirq.Simulator()\n",
@@ -2438,7 +1966,7 @@
"num_params = 5\n",
"for y in range(num_params):\n",
" result = simulator.simulate(circuit, param_resolver={\"s\": y / 4.0})\n",
- " print(\"s={}: {}\\n\".format(y, np.around(result.final_state_vector, 2)))"
+ " print(f\"s={y}: {np.around(result.final_state_vector, 2)}\\n\")"
]
},
{
@@ -2454,38 +1982,11 @@
},
{
"cell_type": "code",
- "execution_count": 48,
+ "execution_count": null,
"metadata": {
"id": "Gj_Y3Lrh49o9"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "params: OrderedDict([('s', 0.0)])\n",
- "a=0000000000\n",
- "b=0000000000\n",
- "\n",
- "params: OrderedDict([('s', 0.125)])\n",
- "a=0000000000\n",
- "b=0000000000\n",
- "\n",
- "params: OrderedDict([('s', 0.25)])\n",
- "a=0001000000\n",
- "b=0010000000\n",
- "\n",
- "params: OrderedDict([('s', 0.375)])\n",
- "a=0000010000\n",
- "b=0001000100\n",
- "\n",
- "params: OrderedDict([('s', 0.5)])\n",
- "a=0010110110\n",
- "b=0101100011\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Simulate the circuit at multiple parameter values.\"\"\"\n",
"# Get a list of param resolvers.\n",
@@ -2496,14 +1997,10 @@
"circuit.append([cirq.measure(a), cirq.measure(b)])\n",
"\n",
"# Simulate the circuit using run_sweep.\n",
- "results = simulator.run_sweep(\n",
- " program=circuit,\n",
- " params=resolvers,\n",
- " repetitions=10\n",
- ")\n",
+ "results = simulator.run_sweep(program=circuit, params=resolvers, repetitions=10)\n",
"\n",
"for i, result in enumerate(results):\n",
- " print('params: {}\\n{}\\n'.format(result.params.param_dict, result))"
+ " print(f'params: {result.params.param_dict}\\n{result}\\n')"
]
},
{
@@ -2517,192 +2014,13 @@
},
{
"cell_type": "code",
- "execution_count": 49,
+ "execution_count": null,
"metadata": {
"id": "074f9fd5cdcd"
},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- " \n",
- "
\n",
- "
\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " s \n",
- " a \n",
- " b \n",
- " \n",
- " \n",
- " \n",
- " \n",
- " count \n",
- " 50.000000 \n",
- " 50.000000 \n",
- " 50.00000 \n",
- " \n",
- " \n",
- " mean \n",
- " 0.250000 \n",
- " 0.260000 \n",
- " 0.30000 \n",
- " \n",
- " \n",
- " std \n",
- " 0.178571 \n",
- " 0.443087 \n",
- " 0.46291 \n",
- " \n",
- " \n",
- " min \n",
- " 0.000000 \n",
- " 0.000000 \n",
- " 0.00000 \n",
- " \n",
- " \n",
- " 25% \n",
- " 0.125000 \n",
- " 0.000000 \n",
- " 0.00000 \n",
- " \n",
- " \n",
- " 50% \n",
- " 0.250000 \n",
- " 0.000000 \n",
- " 0.00000 \n",
- " \n",
- " \n",
- " 75% \n",
- " 0.375000 \n",
- " 0.750000 \n",
- " 1.00000 \n",
- " \n",
- " \n",
- " max \n",
- " 0.500000 \n",
- " 1.000000 \n",
- " 1.00000 \n",
- " \n",
- " \n",
- "
\n",
- "
\n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " \n",
- " \n",
- " \n",
- " \n",
- " \n",
- "\n",
- " \n",
- "
\n",
- "
\n",
- " "
- ],
- "text/plain": [
- " s a b\n",
- "count 50.000000 50.000000 50.00000\n",
- "mean 0.250000 0.260000 0.30000\n",
- "std 0.178571 0.443087 0.46291\n",
- "min 0.000000 0.000000 0.00000\n",
- "25% 0.125000 0.000000 0.00000\n",
- "50% 0.250000 0.000000 0.00000\n",
- "75% 0.375000 0.750000 1.00000\n",
- "max 0.500000 1.000000 1.00000"
- ]
- },
- "execution_count": 49,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "results = simulator.sample(\n",
- " program=circuit,\n",
- " params=resolvers,\n",
- " repetitions=10\n",
- ")\n",
+ "outputs": [],
+ "source": [
+ "results = simulator.sample(program=circuit, params=resolvers, repetitions=10)\n",
"\n",
"results.describe()"
]
@@ -2718,29 +2036,11 @@
},
{
"cell_type": "code",
- "execution_count": 50,
+ "execution_count": null,
"metadata": {
"id": "zOymGxlb72Fk"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "cirq.ParamResolver({'x': 0.0})\n",
- "cirq.ParamResolver({'x': 0.1})\n",
- "cirq.ParamResolver({'x': 0.2})\n",
- "cirq.ParamResolver({'x': 0.3})\n",
- "cirq.ParamResolver({'x': 0.4})\n",
- "cirq.ParamResolver({'x': 0.5})\n",
- "cirq.ParamResolver({'x': 0.6})\n",
- "cirq.ParamResolver({'x': 0.7})\n",
- "cirq.ParamResolver({'x': 0.8})\n",
- "cirq.ParamResolver({'x': 0.9})\n",
- "cirq.ParamResolver({'x': 1.0})\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Alternative method of getting a sequence of param resolvers.\"\"\"\n",
"linspace = cirq.Linspace(start=0, stop=1.0, length=11, key='x')\n",
@@ -2761,15 +2061,16 @@
},
{
"cell_type": "code",
- "execution_count": 51,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "8yW2e3sq9JM8"
},
"outputs": [],
"source": [
- "#@title Attempt the solution here\n",
+ "# @title Attempt the solution here\n",
"import pandas\n",
+ "\n",
"q = cirq.NamedQubit(\"q\")\n",
"theta = sp.Symbol(\"theta\")\n",
"parameterized_circuit = cirq.Circuit(\n",
@@ -2780,9 +2081,7 @@
"param_resolvers = None\n",
"repetitions = 100\n",
"results = cirq.Simulator().sample(\n",
- " program=parameterized_circuit,\n",
- " params=param_resolvers,\n",
- " repetitions=repetitions\n",
+ " program=parameterized_circuit, params=param_resolvers, repetitions=repetitions\n",
")\n",
"\n",
"# You can test with the following plot\n",
@@ -2791,43 +2090,21 @@
},
{
"cell_type": "code",
- "execution_count": 52,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "sl1UGhThC6rn"
},
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 52,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "#@title Expand to view the solution\n",
+ "outputs": [],
+ "source": [
+ "# @title Expand to view the solution\n",
"import pandas\n",
+ "\n",
"q = cirq.NamedQubit(\"q\")\n",
"parameterized_circuit = cirq.Circuit([cirq.Rx(rads=sp.Symbol(\"theta\"))(q), cirq.measure(q)])\n",
"param_resolvers = cirq.Linspace(start=0, stop=np.pi, length=100, key='theta')\n",
"results = cirq.Simulator().sample(\n",
- " program=parameterized_circuit,\n",
- " params=param_resolvers,\n",
- " repetitions=repetitions\n",
+ " program=parameterized_circuit, params=param_resolvers, repetitions=repetitions\n",
")\n",
"pandas.crosstab(results.theta, results.q).plot()"
]
@@ -2872,19 +2149,11 @@
},
{
"cell_type": "code",
- "execution_count": 53,
+ "execution_count": null,
"metadata": {
"id": "YclVFbKZ0aD4"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a: ───D(0.2)───M───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Create a circuit with a depolarizing channel.\"\"\"\n",
"circuit = cirq.Circuit(cirq.depolarize(0.2)(a), cirq.measure(a))\n",
@@ -2902,34 +2171,11 @@
},
{
"cell_type": "code",
- "execution_count": 54,
+ "execution_count": null,
"metadata": {
"id": "0ig_NSrS12PE"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Kraus operator 0 is:\n",
- "[[0.89442719 0. ]\n",
- " [0. 0.89442719]]\n",
- "\n",
- "Kraus operator 1 is:\n",
- "[[0. +0.j 0.25819889+0.j]\n",
- " [0.25819889+0.j 0. +0.j]]\n",
- "\n",
- "Kraus operator 2 is:\n",
- "[[0.+0.j 0.-0.25819889j]\n",
- " [0.+0.25819889j 0.+0.j ]]\n",
- "\n",
- "Kraus operator 3 is:\n",
- "[[ 0.25819889+0.j 0. +0.j]\n",
- " [ 0. +0.j -0.25819889+0.j]]\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"for i, kraus in enumerate(cirq.kraus(cirq.depolarize(0.2))):\n",
" print(f\"Kraus operator {i} is:\", kraus, sep=\"\\n\", end=\"\\n\\n\")"
@@ -2946,30 +2192,11 @@
},
{
"cell_type": "code",
- "execution_count": 55,
+ "execution_count": null,
"metadata": {
"id": "a2e5258ae33d"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Kraus operator 0 is:\n",
- "0.894*I\n",
- "\n",
- "Kraus operator 1 is:\n",
- "0.258*X\n",
- "\n",
- "Kraus operator 2 is:\n",
- "0.258*Y\n",
- "\n",
- "Kraus operator 3 is:\n",
- "0.258*Z\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"for i, kraus in enumerate(cirq.kraus(cirq.depolarize(0.2))):\n",
" pauli_ex = cirq.expand_matrix_in_orthogonal_basis(kraus, cirq.PAULI_BASIS)\n",
@@ -2987,36 +2214,23 @@
},
{
"cell_type": "code",
- "execution_count": 56,
+ "execution_count": null,
"metadata": {
"id": "skLIvXYq4yvX"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit:\n",
- "a: ───D(0.2)───\n",
- "\n",
- "Final density matrix:\n",
- "[[0.8666666 +0.j 0. +0.j]\n",
- " [0. +0.j 0.13333333+0.j]]\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Example of simulating a noisy circuit with the density matrix simulator.\"\"\"\n",
"# Circuit to simulate.\n",
"circuit = cirq.Circuit(cirq.depolarize(0.2)(a))\n",
- "print('Circuit:\\n{}\\n'.format(circuit))\n",
+ "print(f'Circuit:\\n{circuit}\\n')\n",
"\n",
"# Get the density matrix simulator.\n",
"simulator = cirq.DensityMatrixSimulator()\n",
"\n",
"# Simulate the circuit and get the final density matrix.\n",
"matrix = simulator.simulate(circuit).final_density_matrix\n",
- "print('Final density matrix:\\n{}'.format(matrix))"
+ "print(f'Final density matrix:\\n{matrix}')"
]
},
{
@@ -3030,19 +2244,11 @@
},
{
"cell_type": "code",
- "execution_count": 57,
+ "execution_count": null,
"metadata": {
"id": "_SjPRrIX5F4O"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Simulating a circuit with measurements using the DensityMatrixSimulator.\"\"\"\n",
"# Get a circuit with measurements.\n",
@@ -3084,42 +2290,15 @@
},
{
"cell_type": "code",
- "execution_count": 58,
+ "execution_count": null,
"metadata": {
"id": "9Pt7o-Tq2SNz"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "prob = 0.8\n",
- "unitary: \n",
- "[[1. 0.]\n",
- " [0. 1.]]\n",
- "\n",
- "prob = 0.06666666666666667\n",
- "unitary: \n",
- "[[0.+0.j 1.+0.j]\n",
- " [1.+0.j 0.+0.j]]\n",
- "\n",
- "prob = 0.06666666666666667\n",
- "unitary: \n",
- "[[0.+0.j 0.-1.j]\n",
- " [0.+1.j 0.+0.j]]\n",
- "\n",
- "prob = 0.06666666666666667\n",
- "unitary: \n",
- "[[ 1.+0.j 0.+0.j]\n",
- " [ 0.+0.j -1.+0.j]]\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Use the cirq.mixture protocol on the cirq.depolarize channel.\"\"\"\n",
"for p, u in cirq.mixture(cirq.depolarize(0.2)):\n",
- " print(\"prob = {}\\nunitary: \\n{}\\n\".format(p, u))"
+ " print(f\"prob = {p}\\nunitary: \\n{u}\\n\")"
]
},
{
@@ -3133,30 +2312,23 @@
},
{
"cell_type": "code",
- "execution_count": 59,
+ "execution_count": null,
"metadata": {
"id": "HvhpBD334o1v"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "does cirq.depolarize(0.2) have _kraus_? no\n",
- "does cirq.depolarize(0.2) have _mixture_? yes\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Check if cirq.depolarize has _kraus_ and _mixture_ methods.\"\"\"\n",
"# Get a depolarizing channel.\n",
"d = cirq.depolarize(0.2)\n",
"\n",
"# Check if it has _kraus_ implemented.\n",
- "print('does cirq.depolarize(0.2) have _kraus_? {}'.format('yes' if getattr(d, '_kraus_', None) else 'no'))\n",
+ "print(f\"does cirq.depolarize(0.2) have _kraus_? {'yes' if getattr(d, '_kraus_', None) else 'no'}\")\n",
"\n",
"# Check if it has _mixture_ implemented.\n",
- "print('does cirq.depolarize(0.2) have _mixture_? {}'.format('yes' if getattr(d, '_mixture_', None) else 'no'))"
+ "print(\n",
+ " f\"does cirq.depolarize(0.2) have _mixture_? {'yes' if getattr(d, '_mixture_', None) else 'no'}\"\n",
+ ")"
]
},
{
@@ -3170,19 +2342,11 @@
},
{
"cell_type": "code",
- "execution_count": 60,
+ "execution_count": null,
"metadata": {
"id": "vDEhGG0v-UJy"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a=1001010101\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Use the wavefunction simulator on a channel that implements the mixture protocol.\"\"\"\n",
"circuit = cirq.Circuit(cirq.depolarize(0.5).on(a), cirq.measure(a))\n",
@@ -3222,40 +2386,24 @@
},
{
"cell_type": "code",
- "execution_count": 61,
+ "execution_count": null,
"metadata": {
"id": "PfRP7K598wNQ"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Circuit with no noise:\n",
- "a: ───H───@───M───\n",
- " │ │\n",
- "b: ───────X───M───\n",
- "\n",
- "Circuit with noise:\n",
- "a: ───H───D(0.2)[cirq.VirtualTag()]───@───D(0.2)[cirq.VirtualTag()]───M───D(0.2)[cirq.VirtualTag()]───\n",
- " │ │\n",
- "b: ───────D(0.2)[cirq.VirtualTag()]───X───D(0.2)[cirq.VirtualTag()]───M───D(0.2)[cirq.VirtualTag()]───\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Adding noise to a circuit.\"\"\"\n",
"# Get a noiseless circuit.\n",
"noise = cirq.ConstantQubitNoiseModel(cirq.depolarize(0.2))\n",
"circuit = cirq.Circuit(cirq.H(a), cirq.CNOT(a, b), cirq.measure(a, b))\n",
- "print('Circuit with no noise:\\n{}\\n'.format(circuit))\n",
+ "print(f'Circuit with no noise:\\n{circuit}\\n')\n",
"\n",
"# Add noise to the circuit.\n",
"system_qubits = sorted(circuit.all_qubits())\n",
"noisy_circuit = cirq.Circuit()\n",
"for moment in circuit:\n",
" noisy_circuit.append(noise.noisy_moment(moment, system_qubits))\n",
- "print('Circuit with noise:\\n{}'.format(noisy_circuit))"
+ "print(f'Circuit with noise:\\n{noisy_circuit}')"
]
},
{
@@ -3269,36 +2417,11 @@
},
{
"cell_type": "code",
- "execution_count": 62,
+ "execution_count": null,
"metadata": {
"id": "uzxaFCGIz2aQ"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "After step 0 state was\n",
- "[[0.43333328+0.j 0. +0.j 0.31777775+0.j 0. +0.j]\n",
- " [0. +0.j 0.06666666+0.j 0. +0.j 0.04888888+0.j]\n",
- " [0.31777775+0.j 0. +0.j 0.43333328+0.j 0. +0.j]\n",
- " [0. +0.j 0.04888888+0.j 0. +0.j 0.06666666+0.j]]\n",
- "\n",
- "After step 1 state was\n",
- "[[0.34859255+0.j 0. +0.j 0. +0.j 0.17089382+0.j]\n",
- " [0. +0.j 0.15140739+0.j 0.02629136+0.j 0. +0.j]\n",
- " [0. +0.j 0.02629136+0.j 0.15140739+0.j 0. +0.j]\n",
- " [0.17089382+0.j 0. +0.j 0. +0.j 0.34859255+0.j]]\n",
- "\n",
- "After step 2 state was\n",
- "[[0.11555552+0.j 0. +0.j 0. +0.j 0. +0.j]\n",
- " [0. +0.j 0.7511109 +0.j 0. +0.j 0. +0.j]\n",
- " [0. +0.j 0. +0.j 0.01777777+0.j 0. +0.j]\n",
- " [0. +0.j 0. +0.j 0. +0.j 0.11555552+0.j]]\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Perform noisy simulation by defining a density matrix simulator with a noise model.\"\"\"\n",
"# Define a noise model.\n",
@@ -3312,7 +2435,7 @@
"\n",
"# Simulate the circuit in steps.\n",
"for i, step in enumerate(simulator.simulate_moment_steps(circuit)):\n",
- " print('After step {} state was\\n{}\\n'.format(i, step.density_matrix()))"
+ " print(f'After step {i} state was\\n{step.density_matrix()}\\n')"
]
},
{
@@ -3337,46 +2460,11 @@
},
{
"cell_type": "code",
- "execution_count": 63,
+ "execution_count": null,
"metadata": {
"id": "BmzxGpDB9jJ4"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " (0, 5)───(0, 6)\n",
- " │ │\n",
- " │ │\n",
- " (1, 4)───(1, 5)───(1, 6)───(1, 7)\n",
- " │ │ │ │\n",
- " │ │ │ │\n",
- " (2, 3)───(2, 4)───(2, 5)───(2, 6)───(2, 7)───(2, 8)\n",
- " │ │ │ │ │ │\n",
- " │ │ │ │ │ │\n",
- " (3, 2)───(3, 3)───(3, 4)───(3, 5)───(3, 6)───(3, 7)───(3, 8)───(3, 9)\n",
- " │ │ │ │ │ │ │ │\n",
- " │ │ │ │ │ │ │ │\n",
- " (4, 1)───(4, 2)───(4, 3)───(4, 4)───(4, 5)───(4, 6)───(4, 7)───(4, 8)───(4, 9)\n",
- " │ │ │ │ │ │ │ │\n",
- " │ │ │ │ │ │ │ │\n",
- "(5, 0)───(5, 1)───(5, 2)───(5, 3)───(5, 4)───(5, 5)───(5, 6)───(5, 7)───(5, 8)\n",
- " │ │ │ │ │ │ │\n",
- " │ │ │ │ │ │ │\n",
- " (6, 1)───(6, 2)───(6, 3)───(6, 4)───(6, 5)───(6, 6)───(6, 7)\n",
- " │ │ │ │ │\n",
- " │ │ │ │ │\n",
- " (7, 2)───(7, 3)───(7, 4)───(7, 5)───(7, 6)\n",
- " │ │ │\n",
- " │ │ │\n",
- " (8, 3)───(8, 4)───(8, 5)\n",
- " │\n",
- " │\n",
- " (9, 4)\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"print(cirq_google.Sycamore)"
]
@@ -3394,19 +2482,11 @@
},
{
"cell_type": "code",
- "execution_count": 64,
+ "execution_count": null,
"metadata": {
"id": "HAwdWkprAPXN"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "25 ns\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Get the duration of an operation.\"\"\"\n",
"op = cirq.X.on(cirq.GridQubit(5, 5))\n",
@@ -3424,23 +2504,11 @@
},
{
"cell_type": "code",
- "execution_count": 65,
+ "execution_count": null,
"metadata": {
"id": "r5F4FUtmA5kW"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(5, 5): ───iSwap───────\n",
- " │\n",
- "(6, 6): ───iSwap^0.5───\n",
- "error, as expected: \n",
- "Operation does not use valid qubit target: ISWAP**0.5((5, 5), (6, 6)).\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Validate operations on a device.\"\"\"\n",
"# Get non-adjacent qubits on the Sycamore device.\n",
@@ -3452,15 +2520,15 @@
"cirq_google.Sycamore.validate_operation(cirq.SQRT_ISWAP(q55, q56))\n",
"cirq_google.Sycamore.validate_operation(cirq.SQRT_ISWAP(q56, q66))\n",
"\n",
- "# Operation on non-adjacent qubits will raise an error. \n",
+ "# Operation on non-adjacent qubits will raise an error.\n",
"ops = [cirq.SQRT_ISWAP(q55, q66)]\n",
"circuit = cirq.Circuit(ops)\n",
"print(circuit)\n",
"\n",
- "try: \n",
- " cirq_google.Sycamore.validate_circuit(circuit)\n",
+ "try:\n",
+ " cirq_google.Sycamore.validate_circuit(circuit)\n",
"except ValueError as ex:\n",
- " print(f\"error, as expected: \\n{ex}\")"
+ " print(f\"error, as expected: \\n{ex}\")"
]
},
{
@@ -3476,33 +2544,34 @@
},
{
"cell_type": "code",
- "execution_count": 66,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "zDE-19I_a3on"
},
"outputs": [],
"source": [
- "#@title Attempt the solution here"
+ "# @title Attempt the solution here"
]
},
{
"cell_type": "code",
- "execution_count": 67,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "DuOcTG3XZfmb"
},
"outputs": [],
"source": [
- "#@title Expand to view the solution\n",
+ "# @title Expand to view the solution\n",
"class SquareDevice(cirq.Device):\n",
" \"\"\"A Square Grid Device.\n",
- " \n",
- " The device that only allows \n",
+ "\n",
+ " The device that only allows\n",
" 1) Grid Qubits from (0, 0) to (grid_size - 1, grid_size - 1)\n",
" 2) H, CZ and MeasurementGate gates.\n",
" \"\"\"\n",
+ "\n",
" def __init__(self, grid_size):\n",
" self.qubits = []\n",
" for i in range(grid_size):\n",
@@ -3512,7 +2581,9 @@
" def validate_operation(self, operation: 'cirq.Operation') -> None:\n",
" if not isinstance(operation, cirq.GateOperation):\n",
" raise ValueError(f\"Unsupported operation {operation}\")\n",
- " if not (operation.gate in [cirq.H, cirq.CZ] or isinstance(operation.gate, cirq.MeasurementGate)):\n",
+ " if not (\n",
+ " operation.gate in [cirq.H, cirq.CZ] or isinstance(operation.gate, cirq.MeasurementGate)\n",
+ " ):\n",
" raise ValueError(f\"Unsupported gate {operation.gate}\")\n",
" for qubit in operation.qubits:\n",
" if qubit not in self.qubits:\n",
@@ -3546,40 +2617,29 @@
},
{
"cell_type": "code",
- "execution_count": 68,
+ "execution_count": null,
"metadata": {
"id": "l7eFMVe1GEe2"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Before optimizing:\n",
- "a: ───X───Z───@───X───\n",
- " │\n",
- "b: ───────────@───────\n",
- "\n",
- "After optimizing:\n",
- "a: ───Y───────@───X───\n",
- " │\n",
- "b: ───────────@───────\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Example of writing a custom cirq transformer.\"\"\"\n",
+ "\n",
+ "\n",
"@cirq.transformer\n",
- "def xz_optimizer(circuit, *, context = None):\n",
- " \"\"\"Replaces an X followed by a Z with a Y.\"\"\"\n",
- " def merge_func(op1, op2):\n",
- " return cirq.Y(*op1.qubits) if op1.gate == cirq.X and op2.gate == cirq.Z else None\n",
- " return cirq.merge_operations(circuit, merge_func)\n",
+ "def xz_optimizer(circuit, *, context=None):\n",
+ " \"\"\"Replaces an X followed by a Z with a Y.\"\"\"\n",
+ "\n",
+ " def merge_func(op1, op2):\n",
+ " return cirq.Y(*op1.qubits) if op1.gate == cirq.X and op2.gate == cirq.Z else None\n",
+ "\n",
+ " return cirq.merge_operations(circuit, merge_func)\n",
+ "\n",
"\n",
"circuit = cirq.Circuit(cirq.X(a), cirq.Z(a), cirq.CZ(a, b), cirq.X(a))\n",
- "print(\"Before optimizing:\\n{}\\n\". format(circuit))\n",
+ "print(f\"Before optimizing:\\n{circuit}\\n\")\n",
"circuit = xz_optimizer(circuit)\n",
- "print(\"After optimizing:\\n{}\".format(circuit))"
+ "print(f\"After optimizing:\\n{circuit}\")"
]
},
{
@@ -3609,93 +2669,68 @@
},
{
"cell_type": "code",
- "execution_count": 69,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "S0PThmctKFxl"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "None\n"
- ]
- }
- ],
- "source": [
- "#@title Attempt the solution here\n",
+ "outputs": [],
+ "source": [
+ "# @title Attempt the solution here\n",
"@cirq.transformer\n",
- "def simplify_flipped_cnots(circuit, *, context = None):\n",
- " # Use transformer primitives to simplify your circuit. \n",
- " pass\n",
+ "def simplify_flipped_cnots(circuit, *, context=None):\n",
+ " # Use transformer primitives to simplify your circuit.\n",
+ " pass\n",
+ "\n",
"\n",
"\"\"\"Test your optimizer on this circuit.\"\"\"\n",
"circuit = cirq.Circuit(\n",
- " cirq.H.on_each(a, b, c), \n",
- " cirq.CNOT(a, b), \n",
- " cirq.H.on_each(a, b), \n",
- " cirq.CZ(a, b)\n",
+ " cirq.H.on_each(a, b, c), cirq.CNOT(a, b), cirq.H.on_each(a, b), cirq.CZ(a, b)\n",
")\n",
"print(simplify_flipped_cnots(circuit))"
]
},
{
"cell_type": "code",
- "execution_count": 70,
+ "execution_count": null,
"metadata": {
"cellView": "form",
"id": "O8pnDlAngS80"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Before optimizing:\n",
- "a: ───H───@───H───@───\n",
- " │ │\n",
- "b: ───H───X───H───@───\n",
- "\n",
- "c: ───H───────────────\n",
- "\n",
- "After optimizing:\n",
- "a: ───────X───────@───\n",
- " │ │\n",
- "b: ───────@───────@───\n",
- "\n",
- "c: ───H───────────────\n"
- ]
- }
- ],
- "source": [
- "#@title Expand to view the solution\n",
- "def simplify_flipped_cnots(circuit, *, context = None):\n",
+ "outputs": [],
+ "source": [
+ "# @title Expand to view the solution\n",
+ "def simplify_flipped_cnots(circuit, *, context=None):\n",
" \"\"\"Replaces a CX surrounded by Hadamards\"\"\"\n",
+ "\n",
" def can_merge(ops1, ops2):\n",
- " merged = cirq.Circuit(ops1, ops2)\n",
- " return (\n",
- " len(merged) <= 3 and \n",
- " all(o.gate == cirq.H for o in merged[0].operations)\n",
- " and merged[1].operations[0].gate == cirq.CNOT\n",
- " and (len(merged) < 3 or all(o.gate == cirq.H for o in merged[2].operations))\n",
- " )\n",
+ " merged = cirq.Circuit(ops1, ops2)\n",
+ " return (\n",
+ " len(merged) <= 3\n",
+ " and all(o.gate == cirq.H for o in merged[0].operations)\n",
+ " and merged[1].operations[0].gate == cirq.CNOT\n",
+ " and (len(merged) < 3 or all(o.gate == cirq.H for o in merged[2].operations))\n",
+ " )\n",
+ "\n",
" merged_tag = \"h_cx_h\"\n",
- " circuit = cirq.merge_operations_to_circuit_op(circuit, can_merge, merged_circuit_op_tag=merged_tag)\n",
+ " circuit = cirq.merge_operations_to_circuit_op(\n",
+ " circuit, can_merge, merged_circuit_op_tag=merged_tag\n",
+ " )\n",
+ "\n",
" def map_func(op, _):\n",
- " if merged_tag not in op.tags:\n",
- " return op\n",
- " cops = [*op.untagged.mapped_circuit().all_operations()]\n",
- " return cirq.CNOT(*cops[2].qubits[::-1]) if len(cops) == 5 else cops\n",
+ " if merged_tag not in op.tags:\n",
+ " return op\n",
+ " cops = [*op.untagged.mapped_circuit().all_operations()]\n",
+ " return cirq.CNOT(*cops[2].qubits[::-1]) if len(cops) == 5 else cops\n",
+ "\n",
" return cirq.map_operations(circuit, map_func)\n",
+ "\n",
+ "\n",
"circuit = cirq.Circuit(\n",
- " cirq.H.on_each(a, b, c), \n",
- " cirq.CNOT(a, b), \n",
- " cirq.H.on_each(a, b), \n",
- " cirq.CZ(a, b)\n",
+ " cirq.H.on_each(a, b, c), cirq.CNOT(a, b), cirq.H.on_each(a, b), cirq.CZ(a, b)\n",
")\n",
- "print(\"Before optimizing:\\n{}\\n\". format(circuit))\n",
- "print(\"After optimizing:\\n{}\".format(simplify_flipped_cnots(circuit)))"
+ "print(f\"Before optimizing:\\n{circuit}\\n\")\n",
+ "print(f\"After optimizing:\\n{simplify_flipped_cnots(circuit)}\")"
]
},
{
@@ -3716,54 +2751,29 @@
},
{
"cell_type": "code",
- "execution_count": 71,
+ "execution_count": null,
"metadata": {
"id": "ydDrxmlL18F1"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Original Circuit (depth 6): ┌──┐ ┌──┐\n",
- "0: ───iSwap──────────────iSwap───iSwap────@─────\n",
- " │ │ │ │\n",
- "1: ───┼─────────×────T───iSwap───iSwap────┼×────\n",
- " │ │ ││\n",
- "2: ───┼────────T┼────────X────────────────@┼────\n",
- " │ │ │\n",
- "3: ───iSwap─────×──────────────────────────×────\n",
- " └──┘ └──┘\n",
- "Compiled circuit for CZ Target (depth 17): ┌──┐ ┌──────────────┐\n",
- "0: ───PhX(-0.75)^0.5───@───PhX(0.25)^0.5────@───PhXZ(a=-0.75,x=0.5,z=0.5)──────────────────────────────────────────────PhXZ(a=-0.5,x=0,z=-1)─────────────────────────────────@────────────────────────────────────────\n",
- " │ │ │\n",
- "1: ────────────────────┼────────────────────┼───────────────────────────────@───PhX(0.5)^0.5───@───PhX(-0.5)^0.5───@───PhXZ(a=-1.11e-16,x=0.25,z=0.5)────@──────PhX(1)^0.5───┼────@───PhX(-2.22e-16)^0.5───@───S^-1───\n",
- " │ │ │ │ │ │ │ │ │\n",
- "2: ────────────────────┼────────────────────┼───────────────────────────────┼──────────────────┼───────────────────┼───PhXZ(a=0.25,x=0,z=0.25)───────────┼X──────────────────@────┼────────────────────────┼──────────\n",
- " │ │ │ │ │ │ │ │\n",
- "3: ───PhX(0.25)^0.5────@───PhX(-0.75)^0.5───@───PhXZ(a=0.25,x=0.5,z=0.5)────@───PhX(0.5)^0.5───@───PhX(-0.5)^0.5───@───PhXZ(a=-0.5,x=0,z=-1)─────────────@──────PhX(-0.5)^0.5─────@───PhX(0.5)^0.5─────────@───S──────\n",
- " └──┘ └──────────────┘\n",
- "Compiled circuit for Sqrt-Iswap Target (depth 16): ┌──────────────────┐ ┌──────────────────┐\n",
- "0: ───PhXZ(a=-4.44e-16,x=0,z=0.5)───iSwap───────iSwap──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────PhXZ(a=-1.0,x=0.5,z=-0.5)─────────────iSwap────────PhXZ(a=-5.55e-17,x=1,z=0)──────────────iSwap────────PhXZ(a=-0.5,x=0.5,z=2.05e-08)───────────────────────────────────────────\n",
- " │ │ │ │\n",
- "1: ─────────────────────────────────┼───────────┼─────────────────────────────────────iSwap───────PhXZ(a=-0.83,x=0.5,z=0.83)───iSwap───────PhXZ(a=0.5,x=0.5,z=0)───iSwap───────PhXZ(a=-0.5,x=0.92,z=0.5)────iSwap────┼────────────PhXZ(a=0.17,x=0.5,z=-0.17)────iSwap────┼────────────PhXZ(a=0.5,x=0.5,z=0)───────────iSwap───────PhXZ(a=0.5,x=0.83,z=-0.5)───\n",
- " │ │ │ │ │ │ │ │ │ │\n",
- "2: ─────────────────────────────────┼───────────┼─────────────────────────────────────┼────────────────────────────────────────┼───────────────────────────────────┼───────────PhXZ(a=0.5,x=0.5,z=0)────────┼────────iSwap^0.5──────────────────────────────────┼────────iSwap^0.5────PhXZ(a=0.5,x=0.5,z=0.25)────────┼───────────────────────────────────────\n",
- " │ │ │ │ │ │ │ │\n",
- "3: ─────────────────────────────────iSwap^0.5───iSwap^0.5───PhXZ(a=-1.0,x=0,z=-0.5)───iSwap^0.5───PhXZ(a=-0.83,x=0.5,z=0.83)───iSwap^0.5───PhXZ(a=0.5,x=0.5,z=0)───iSwap^0.5───PhXZ(a=0.5,x=0.83,z=0.5)─────iSwap^0.5─────────────PhXZ(a=0.17,x=0.5,z=-0.17)────iSwap^0.5─────────────PhXZ(a=0.5,x=0.5,z=0)───────────iSwap^0.5───PhXZ(a=0.5,x=0.83,z=-1.0)───\n",
- " └──────────────────┘ └──────────────────┘\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"circuit = cirq.testing.random_circuit(qubits=4, n_moments=6, op_density=0.8, random_state=1234)\n",
"print(f\"Original Circuit (depth {len(circuit)}):\", circuit)\n",
- "cz_compiled_circuit = cirq.optimize_for_target_gateset(circuit, gateset = cirq.CZTargetGateset())\n",
- "cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(circuit, cz_compiled_circuit, atol=1e-7)\n",
+ "cz_compiled_circuit = cirq.optimize_for_target_gateset(circuit, gateset=cirq.CZTargetGateset())\n",
+ "cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(\n",
+ " circuit, cz_compiled_circuit, atol=1e-7\n",
+ ")\n",
"print(f\"Compiled circuit for CZ Target (depth {len(cz_compiled_circuit)}):\", cz_compiled_circuit)\n",
- "sqrt_iswap_compiled_circuit = cirq.optimize_for_target_gateset(circuit, gateset = cirq.SqrtIswapTargetGateset())\n",
- "cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(circuit, sqrt_iswap_compiled_circuit, atol=1e-7)\n",
- "print(f\"Compiled circuit for Sqrt-Iswap Target (depth {len(sqrt_iswap_compiled_circuit)}):\", sqrt_iswap_compiled_circuit)"
+ "sqrt_iswap_compiled_circuit = cirq.optimize_for_target_gateset(\n",
+ " circuit, gateset=cirq.SqrtIswapTargetGateset()\n",
+ ")\n",
+ "cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(\n",
+ " circuit, sqrt_iswap_compiled_circuit, atol=1e-7\n",
+ ")\n",
+ "print(\n",
+ " f\"Compiled circuit for Sqrt-Iswap Target (depth {len(sqrt_iswap_compiled_circuit)}):\",\n",
+ " sqrt_iswap_compiled_circuit,\n",
+ ")"
]
},
{
@@ -3786,27 +2796,17 @@
},
{
"cell_type": "code",
- "execution_count": 72,
+ "execution_count": null,
"metadata": {
"id": "Ih8YgwX19h2-"
},
- "outputs": [
- {
- "data": {
- "image/png": "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wYBNpIJBgwbB4XAAEAFv27ZtOHnyJMaPH4/f//73AMSSmMuXL8eRI0ewcOFCdOjQAffeey/WrFnT4LW++uorDBgwAP3798dHH32Ee++9FwAwcuRIjBgxAj/++CPi4+Px8ssvo7i4GPfddx9iYmJwwQUXIC8vr8GNxJ49ezBv3jxYLBacccYZWLRoERISEtznT548iXXr1mHGjBk+39e5557rfl/ffvstnnvuOcTExCAhIQF//etfYbVaMX36dBw6dAjnnHOO++cmTJiARx55BAkJCZg5cyYAoK6uDosXL0ZaWprP95KcnIxevXph06ZNpstYRubEJnGiCKutrcWGDRuQmZmJkydPIjU1FW+//TbeeustPPfccw2e+8Ybb+CBBx7Aiy++qPh6a9euxfXXX4/Ro0fjo48+ch8vKCjADTfcgFWrVuHYsWPYtWsX3njjDYwaNQorV67EqVOnmrzW/PnzMW/ePCxfvhxDhw6F3W5vcH7btm3o27ev4kpnn3zyCQYMGAAAqKiowFNPPYWVK1ciLi4OX3/9Nb755hvU1dVh1apV+M1vfoOjR482+Pni4mJMmzYNK1aswM0334y33npL8b0AYtnU7777TvGzITIS1rCJIuDXX3/FhAkTAAC7du3C5MmT3Wu0V1RUIDs7GzExMSgvL3f/zMUXXwxA1Maffvppn69bVVWFb775BvPmzUNcXBxiY2ORn5+PzMxMxMXFoV+/fgCAlJQUHD9+HHv37nUv/nDVVVdh+/btDV5v27ZteOSRRwAAp06dalALBkRATUlJaXDs4YcfRvv27VFcXIwePXpg4cKFAMQytn/5y19QX1+PgoICXHzxxSgvL8f5558PQNTGGy/52qVLFzz++ONYunQpjh07hszMTADw+V7kx3l5eX4+eSLjYMAmigDvPux7770XvXv3BgBs2bIFmzdvxooVKxATE+MOZo0p9dGuX78e9fX1kCQJAFBeXo6PPvoImZmZTWrBLpcLLpfL/Vq+XrNdu3Z48803/fYJNz4n92Fv3LgR//jHP5CcnAwAmD17Nl5++WVkZGS4+95dLleD3M1Op7PBay1ZsgTDhg3D+PHj8cknn+CLL74AAJ/vhchs2CROFGEzZ87EU089herqapSXlyMlJQUxMTHYsGED6uvr3U3Vcs3xv//9L/r06ePztdauXYsnnngC77//Pt5//3288847+OSTTxQDWlpaGnbs2AEA+PLLL5uc79evn/v4Rx99hE2bNjU4n5ycjEOHDvl87SuvvBKnTp1yB9nKykp069YNx44dw3fffYfa2lr07t3b/ft//PHHJs3y5eXlSEtLg8vlci9Q4c/hw4eb1PiJjIoBmyjCevbsiWuvvRZ///vfcemll8LhcCAnJwcFBQW44oor8Oijj7qfe/fdd2PJkiWYOnVqk9cpLy/Hrl27cPnll7uP9ejRAz179sSPP/7o83dPnDgRq1atwm233QYATVYqys3NxUsvvYScnBysWbMG/fv3b3B+0KBB2LVrl+KUtIcffhgLFy7EyZMnceutt2L8+PF45JFHMHnyZLz00ksYMGAAampqkJOTg48//rjJ0o7jxo3D/PnzMXnyZIwePRpbtmzB119/rfhZfv/9982akkakZ1yti8hEdu/ejWPHjmHw4MFYu3atexpWcyxcuBDnnnuuuy9cLaWlpbjrrruwevVqTusiU2DAJjKRoqIiTJ8+HRaLBVarFQsXLkTPnj2b9RqVlZWYNm0alixZ4p6LrYbp06dj4sSJOPfcc1UrA1EkMWATERHpAPuwiYiIdIABm4iISAcYsImIiHSAAZuIiEgHGLCJiIh04P8B4SZnNn/nC90AAAAASUVORK5CYII=\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "result = cirq.experiments.rabi_oscillations(\n",
+ "outputs": [],
+ "source": [
+ "qubit = cirq.LineQubit(0)\n",
+ "result = cirq.experiments.single_qubit_state_tomography(\n",
" sampler=cirq.Simulator(), # In case of Google QCS or other hardware providers, sampler could point at real hardware.\n",
- " qubit=cirq.LineQubit(0),\n",
- " num_points=200,\n",
+ " qubit=qubit,\n",
+ " circuit=cirq.Circuit(cirq.Z(qubit), cirq.X(qubit)),\n",
" repetitions=1000,\n",
")\n",
"result.plot();"
@@ -3823,14 +2823,13 @@
},
{
"cell_type": "code",
- "execution_count": 73,
+ "execution_count": null,
"metadata": {
"id": "j7FoZGKv90qe"
},
"outputs": [],
"source": [
"class InconsistentXGate(cirq.SingleQubitGate):\n",
- "\n",
" def _decompose_(self, qubits):\n",
" yield cirq.H(qubits[0])\n",
" yield cirq.Z(qubits[0])\n",
@@ -3839,6 +2838,7 @@
" def _unitary_(self):\n",
" return np.array([[0, -1j], [1j, 0]]) # Oops! Y instead of X!\n",
"\n",
+ "\n",
"# cirq.testing.assert_decompose_is_consistent_with_unitary(InconsistentXGate())"
]
},
@@ -3853,37 +2853,11 @@
},
{
"cell_type": "code",
- "execution_count": 74,
+ "execution_count": null,
"metadata": {
"id": "qH7xB-vZ-Jsn"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "// Generated from Cirq v0.15.0.dev20220329072625\n",
- "\n",
- "OPENQASM 2.0;\n",
- "include \"qelib1.inc\";\n",
- "\n",
- "\n",
- "// Qubits: [0, 1, 2]\n",
- "qreg q[3];\n",
- "\n",
- "\n",
- "h q[0];\n",
- "h q[2];\n",
- "cx q[0],q[1];\n",
- "\n",
- "// Gate: CCZ\n",
- "h q[2];\n",
- "ccx q[0],q[1],q[2];\n",
- "h q[2];\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Export a circuit to Qasm.\"\"\"\n",
"a, b, c = cirq.LineQubit.range(3)\n",
@@ -3902,27 +2876,11 @@
},
{
"cell_type": "code",
- "execution_count": 75,
+ "execution_count": null,
"metadata": {
"id": "951a57e8e0fd"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "# Created using Cirq.\n",
- "\n",
- "H 0\n",
- "H 2\n",
- "CNOT 0 1\n",
- "H 2\n",
- "CCNOT 0 1 2\n",
- "H 2\n",
- "\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Export a circuit to QUIL.\"\"\"\n",
"print(circuit.to_quil())"
@@ -3939,22 +2897,15 @@
},
{
"cell_type": "code",
- "execution_count": 76,
+ "execution_count": null,
"metadata": {
"id": "Ydst5b0S9IGE"
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "http://algassert.com/quirk#circuit=%7B%22cols%22%3A%5B%5B%22H%22%2C1%2C%22H%22%5D%2C%5B%22%E2%80%A2%22%2C%22X%22%5D%2C%5B%22%E2%80%A2%22%2C%22%E2%80%A2%22%2C%22Z%22%5D%5D%7D\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"\"\"\"Export a circuit to a Quirk URL.\"\"\"\n",
"from cirq.contrib.quirk.export_to_quirk import circuit_to_quirk_url\n",
+ "\n",
"print(circuit_to_quirk_url(circuit))"
]
}
diff --git a/docs/tutorials/educators/intro.tst b/docs/tutorials/educators/intro.tst
index d4be25c899f..3e8f710a0b0 100644
--- a/docs/tutorials/educators/intro.tst
+++ b/docs/tutorials/educators/intro.tst
@@ -15,7 +15,6 @@
# Replacements to apply during testing. See devtools/notebook_test.py for syntax.
num_angles = 200->num_angles = 2
-num_points=200->num_points=2
repetitions=1000->repetitions=2
repetitions = 100->repetitions=2
repetitions=10->repetitions=2
diff --git a/docs/tutorials/rabi_oscillations.ipynb b/docs/tutorials/rabi_oscillations.ipynb
deleted file mode 100644
index 6686a3a37a3..00000000000
--- a/docs/tutorials/rabi_oscillations.ipynb
+++ /dev/null
@@ -1,499 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "zJAHLtnyQah6"
- },
- "source": [
- "##### Copyright 2020 The Cirq Developers"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "cellView": "form",
- "id": "zuEmbgh8QaG1"
- },
- "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": "W31l4SmqQSrM"
- },
- "source": [
- "# Rabi oscillation experiment"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "2eDV4QFhQhlO"
- },
- "source": [
- ""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "bd9529db1c0b"
- },
- "outputs": [],
- "source": [
- "try:\n",
- " import cirq\n",
- " import cirq_google\n",
- "except ImportError:\n",
- " print(\"installing cirq...\")\n",
- " !pip install --quiet cirq-google\n",
- " print(\"installed cirq.\")\n",
- " import cirq\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "kL2C06ln6h48"
- },
- "source": [
- "In this experiment, you are going to use Cirq to check that rotating a qubit by an increasing angle, and then measuring the qubit, produces Rabi oscillations. This requires you to do the following things:\n",
- "\n",
- "1. Prepare the $|0\\rangle$ state.\n",
- "2. Rotate by an angle $\\theta$ around the $X$ axis.\n",
- "3. Measure to see if the result is a 1 or a 0.\n",
- "4. Repeat steps 1-3 $k$ times.\n",
- "5. Report the fraction of $\\frac{\\text{Number of 1's}}{k}$\n",
- "found in step 3."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "ACqqV6tJ7xXp"
- },
- "source": [
- "## 1. Getting to know Cirq\n",
- "\n",
- "Cirq emphasizes the details of implementing quantum algorithms on near term devices.\n",
- "For example, when you work on a qubit in Cirq you don't operate on an unspecified qubit that will later be mapped onto a device by a hidden step.\n",
- "Instead, you are always operating on specific qubits at specific locations that you specify.\n",
- "\n",
- "Suppose you are working with a 54 qubit Sycamore chip.\n",
- "This device is included in Cirq by default.\n",
- "It is called `cirq_google.Sycamore`, and you can see its layout by printing it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "rKoMKEw46XY7"
- },
- "outputs": [],
- "source": [
- "import cirq\n",
- "import cirq_google\n",
- "working_device = cirq_google.Sycamore\n",
- "print(working_device)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "FJJEbuk-98Gj"
- },
- "source": [
- "For this experiment you only need one qubit and you can just pick whichever one you like."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "XoXekxuQ8bI0"
- },
- "outputs": [],
- "source": [
- "my_qubit = cirq.GridQubit(5, 6)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "8Tucm7os-uET"
- },
- "source": [
- "Once you've chosen your qubit you can build circuits that use it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "niH8sty--Hu0"
- },
- "outputs": [],
- "source": [
- "from cirq.contrib.svg import SVGCircuit\n",
- "\n",
- "# Create a circuit with X, Ry(pi/2) and H.\n",
- "my_circuit = cirq.Circuit(\n",
- " # Rotate the qubit pi/2 radians around the X axis.\n",
- " cirq.rx(3.141 / 2).on(my_qubit),\n",
- " # Measure the qubit.\n",
- " cirq.measure(my_qubit, key='out')\n",
- ")\n",
- "SVGCircuit(my_circuit)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "-zbI-2KUMU66"
- },
- "source": [
- "Now you can simulate sampling from your circuit using `cirq.Simulator`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "IqUn4uv9_IVo"
- },
- "outputs": [],
- "source": [
- "sim = cirq.Simulator()\n",
- "samples = sim.sample(my_circuit, repetitions=10)\n",
- "samples"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "k-uAT6sHdGib"
- },
- "source": [
- "You can also get properties of the circuit, such as the density matrix of the circuit's output or the state vector just before the terminal measurement."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "83OqpReyHyUK"
- },
- "outputs": [],
- "source": [
- "state_vector_before_measurement = sim.simulate(my_circuit[:-1])\n",
- "sampled_state_vector_after_measurement = sim.simulate(my_circuit)\n",
- "\n",
- "print(f'State before measurement:')\n",
- "print(state_vector_before_measurement)\n",
- "print()\n",
- "print(f'State after measurement:')\n",
- "print(sampled_state_vector_after_measurement)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "1raIf8dsWHLJ"
- },
- "source": [
- "You can also examine the outputs from a noisy environment.\n",
- "For example, an environment where 10% depolarization is applied to each qubit after each operation in the circuit:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "P7VW97ugWE_h"
- },
- "outputs": [],
- "source": [
- "noisy_sim = cirq.DensityMatrixSimulator(noise=cirq.depolarize(0.1))\n",
- "noisy_post_measurement_state = noisy_sim.simulate(my_circuit)\n",
- "noisy_pre_measurement_state = noisy_sim.simulate(my_circuit[:-1])\n",
- "\n",
- "print('Noisy state after measurement:' + str(noisy_post_measurement_state))\n",
- "print('Noisy state before measurement:' + str(noisy_pre_measurement_state))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "2h6yoOl4Rmwt"
- },
- "source": [
- "## 2. Parameterized Circuits and Sweeps\n",
- "\n",
- "Now that you have some of the basics end to end, you can create a parameterized circuit that rotates by an angle $\\theta$:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "n6h6yuyGM58s"
- },
- "outputs": [],
- "source": [
- "import sympy\n",
- "theta = sympy.Symbol('theta')\n",
- "\n",
- "parameterized_circuit = cirq.Circuit(\n",
- " cirq.rx(theta).on(my_qubit),\n",
- " cirq.measure(my_qubit, key='out')\n",
- ")\n",
- "SVGCircuit(parameterized_circuit)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "rU3BBOp0S4sM"
- },
- "source": [
- "In the above block you saw that there is a `sympy.Symbol` that you placed in the circuit. Cirq supports symbolic computation involving circuits. What this means is that when you construct `cirq.Circuit` objects you can put placeholders in many of the classical control parameters of the circuit which you can fill with values later on.\n",
- "\n",
- "Now if you wanted to use `cirq.simulate` or `cirq.sample` with the parameterized circuit you would also need to specify a value for `theta`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "SMdz-yAZSwrU"
- },
- "outputs": [],
- "source": [
- "samples_at_theta_equals_2 = sim.sample(\n",
- " parameterized_circuit, \n",
- " params={theta: 2}, \n",
- " repetitions=10)\n",
- "samples_at_theta_equals_2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "H_H13Hc8g873"
- },
- "source": [
- "You can also specify *multiple* values of `theta`, and get samples back for each value."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "0zjZxGY6hIsu"
- },
- "outputs": [],
- "source": [
- "samples_at_multiple_theta = sim.sample(\n",
- " parameterized_circuit, \n",
- " params=[{theta: 0.5}, {theta: 3.141}], \n",
- " repetitions=10)\n",
- "samples_at_multiple_theta"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "juuWvOEphaaE"
- },
- "source": [
- "Cirq has shorthand notation you can use to sweep `theta` over a range of values."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "8lCb3049hqXn"
- },
- "outputs": [],
- "source": [
- "samples_at_swept_theta = sim.sample(\n",
- " parameterized_circuit, \n",
- " params=cirq.Linspace(theta, start=0, stop=3.14159, length=5), \n",
- " repetitions=5)\n",
- "samples_at_swept_theta"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "wqaORMoKiAIW"
- },
- "source": [
- "The result value being returned by `sim.sample` is a `pandas.DataFrame` object.\n",
- "Pandas is a common library for working with table data in Python.\n",
- "You can use standard pandas methods to analyze and summarize your results."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "bLzGV8nFiS9o"
- },
- "outputs": [],
- "source": [
- "import pandas\n",
- "\n",
- "big_results = sim.sample(\n",
- " parameterized_circuit, \n",
- " params=cirq.Linspace(theta, start=0, stop=3.14159, length=20), \n",
- " repetitions=10_000)\n",
- "\n",
- "# big_results is too big to look at. Plot cross tabulated data instead.\n",
- "pandas.crosstab(big_results.theta, big_results.out).plot()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "b2TkL28AmBSQ"
- },
- "source": [
- "## 3. The built-in experiment\n",
- "\n",
- "Cirq comes with a pre-written Rabi oscillation experiment `cirq.experiments.rabi_oscillations`.\n",
- "This method takes a `cirq.Sampler`, which could be a simulator or a network connection to real hardware.\n",
- "The method takes a few more experimental parameters, and returns a result object\n",
- "that can be plotted."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "ma0pVZwSThQx"
- },
- "outputs": [],
- "source": [
- "import datetime\n",
- "\n",
- "result = cirq.experiments.rabi_oscillations(\n",
- " sampler=noisy_sim,\n",
- " qubit=my_qubit,\n",
- " num_points=50,\n",
- " repetitions=10000)\n",
- "result.plot()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "U-oezaJAnzJ8"
- },
- "source": [
- "Notice that you can tell from the plot that you used the noisy simulator you defined earlier.\n",
- "You can also tell that the amount of depolarization is roughly 10%."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "V6uE-yFxoT-3"
- },
- "source": [
- "## 4. Exercise: Find the best qubit\n",
- "\n",
- "As you have seen, you can use Cirq to perform a Rabi oscillation experiment.\n",
- "You can either make the experiment yourself out of the basic pieces made available by Cirq, or use the prebuilt experiment method.\n",
- "\n",
- "Now you're going to put this knowledge to the test.\n",
- "\n",
- "There is some amount of depolarizing noise on each qubit.\n",
- "Your goal is to characterize every qubit from the Sycamore chip using a Rabi oscillation experiment, and find the qubit with the lowest noise according to the secret noise model."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "-eISq1eqXYWx"
- },
- "outputs": [],
- "source": [
- "import hashlib\n",
- "\n",
- "class SecretNoiseModel(cirq.NoiseModel):\n",
- " def noisy_operation(self, op):\n",
- " # Hey! No peeking!\n",
- " q = op.qubits[0]\n",
- " v = hashlib.sha256(str(q).encode()).digest()[0] / 256\n",
- " yield cirq.depolarize(v).on(q)\n",
- " yield op\n",
- "\n",
- "secret_noise_sampler = cirq.DensityMatrixSimulator(noise=SecretNoiseModel())"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "id": "Rvf87Wqrp-lu"
- },
- "outputs": [],
- "source": [
- "q = cirq_google.Sycamore.qubits[3]\n",
- "print('qubit', repr(q))\n",
- "cirq.experiments.rabi_oscillations(\n",
- " sampler=secret_noise_sampler,\n",
- " qubit=q\n",
- ").plot()"
- ]
- }
- ],
- "metadata": {
- "colab": {
- "collapsed_sections": [
- "V6uE-yFxoT-3"
- ],
- "name": "rabi_oscillations.ipynb",
- "toc_visible": true
- },
- "kernelspec": {
- "display_name": "Python 3",
- "name": "python3"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
diff --git a/examples/qubit_characterizations_example.py b/examples/qubit_characterizations_example.py
index 88cd2aa9304..e18b5fa6334 100644
--- a/examples/qubit_characterizations_example.py
+++ b/examples/qubit_characterizations_example.py
@@ -1,14 +1,12 @@
# pylint: disable=wrong-or-nonexistent-copyright-notice
-import numpy as np
import cirq
def main(minimum_cliffords=5, maximum_cliffords=20, cliffords_step=5):
"""Examples of how to run various qubit characterizations.
- This example shows various methods on how to characterize a qubit, including a Rabi
- oscillation experiments, Clifford-based randomized benchmarking, and
- state tomography.
+ This example shows various methods on how to characterize a qubit, including
+ Clifford-based randomized benchmarking and state tomography.
The number of cliffords to use in a randomized benchmarking experiment
can be varied. For instance, setting minimum_cliffords=10,
@@ -30,10 +28,6 @@ def main(minimum_cliffords=5, maximum_cliffords=20, cliffords_step=5):
q_0 = cirq.GridQubit(0, 0)
q_1 = cirq.GridQubit(0, 1)
- # Measure Rabi oscillation of q_0.
- rabi_results = cirq.experiments.rabi_oscillations(simulator, q_0, 4 * np.pi)
- rabi_results.plot()
-
clifford_range = range(minimum_cliffords, maximum_cliffords, cliffords_step)
# Clifford-based randomized benchmarking of single-qubit gates on q_0.