View on QuantumAI | Run in Google Colab | View source on GitHub | Download notebook |
try:
import cirq
except ImportError:
print("installing cirq...")
!pip install --quiet cirq
print("installed cirq.")
import cirq
Running this notebook requires the pyQuil QVM and Compiler. If you are running on Google Colab or a Linux Debian machine, you can run the below cell to install them if necessary. If you are on a non-Linux Debian machine, see these instructions for installation.
! [ -z "$(which qvm)" ] &&\
apt update &&\
apt install jq &&\
export LATEST_FOREST_SDK_VERSION=$(curl -s https://downloads.rigetti.com/qcs-sdk/versions | jq -r '.versions[0].sdk') &&\
curl -f https://downloads.rigetti.com/qcs-sdk/forest-sdk-$LATEST_FOREST_SDK_VERSION-linux-deb.tar.bz2 -o $PWD/forest-sdk-$LATEST_FOREST_SDK_VERSION-linux-deb.tar.bz2 &&\
tar -xf forest-sdk-$LATEST_FOREST_SDK_VERSION-linux-deb.tar.bz2 &&\
./forest-sdk-$LATEST_FOREST_SDK_VERSION-linux-deb/forest-sdk-$LATEST_FOREST_SDK_VERSION-linux-deb.run &&\
quilc --version &&\
qvm --version
Hit:1 http://archive.ubuntu.com/ubuntu bionic InRelease Get:2 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB] Get:3 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB] Hit:4 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease Get:5 https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/ InRelease [3,626 B] Get:6 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB] Ign:7 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 InRelease Hit:8 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 Release Get:9 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic InRelease [15.9 kB] Hit:10 http://ppa.launchpad.net/cran/libgit2/ubuntu bionic InRelease Get:11 http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic InRelease [15.9 kB] Hit:12 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic InRelease Get:13 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [1,512 kB] Get:14 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [2,799 kB] Get:15 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [3,231 kB] Get:16 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [2,286 kB] Get:18 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic/main Sources [1,992 kB] Get:19 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic/main amd64 Packages [1,021 kB] Get:20 http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic/main amd64 Packages [45.3 kB] Fetched 13.2 MB in 5s (2,876 kB/s) Reading package lists... Done Building dependency tree Reading state information... Done 45 packages can be upgraded. Run 'apt list --upgradable' to see them. Reading package lists... Done Building dependency tree Reading state information... Done The following package was automatically installed and is no longer required: libnvidia-common-460 Use 'apt autoremove' to remove it. The following additional packages will be installed: libjq1 libonig4 The following NEW packages will be installed: jq libjq1 libonig4 0 upgraded, 3 newly installed, 0 to remove and 45 not upgraded. Need to get 276 kB of archives. After this operation, 930 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libonig4 amd64 6.7.0-1 [119 kB] Get:2 http://archive.ubuntu.com/ubuntu bionic/universe amd64 libjq1 amd64 1.5+dfsg-2 [111 kB] Get:3 http://archive.ubuntu.com/ubuntu bionic/universe amd64 jq amd64 1.5+dfsg-2 [45.6 kB] Fetched 276 kB in 0s (1,212 kB/s) Selecting previously unselected package libonig4:amd64. (Reading database ... 155632 files and directories currently installed.) Preparing to unpack .../libonig4_6.7.0-1_amd64.deb ... Unpacking libonig4:amd64 (6.7.0-1) ... Selecting previously unselected package libjq1:amd64. Preparing to unpack .../libjq1_1.5+dfsg-2_amd64.deb ... Unpacking libjq1:amd64 (1.5+dfsg-2) ... Selecting previously unselected package jq. Preparing to unpack .../jq_1.5+dfsg-2_amd64.deb ... Unpacking jq (1.5+dfsg-2) ... Setting up libonig4:amd64 (6.7.0-1) ... Setting up libjq1:amd64 (1.5+dfsg-2) ... Setting up jq (1.5+dfsg-2) ... Processing triggers for man-db (2.8.3-2ubuntu0.1) ... Processing triggers for libc-bin (2.27-3ubuntu1.3) ... /sbin/ldconfig.real: /usr/local/lib/python3.7/dist-packages/ideep4py/lib/libmkldnn.so.0 is not a symbolic link % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 54.1M 100 54.1M 0 0 25.5M 0 0:00:02 0:00:02 --:--:-- 25.5M Verifying archive integrity... 0% 7% 14% 22% 29% 37% 44% 51% 59% 66% 74% 81% 89% 96% 100% MD5 checksums are OK. All good. Uncompressing forest-sdk-deb 0% 7% 14% 22% 29% 37% 44% 51% 59% 66% 74% 81% 89% 96% 100% Reading package lists... Done Building dependency tree Reading state information... Done libblas-dev is already the newest version (3.7.1-4ubuntu1). libblas-dev set to manually installed. liblapack-dev is already the newest version (3.7.1-4ubuntu1). The following package was automatically installed and is no longer required: libnvidia-common-460 Use 'apt autoremove' to remove it. The following NEW packages will be installed: libffi-dev 0 upgraded, 1 newly installed, 0 to remove and 45 not upgraded. Need to get 156 kB of archives. After this operation, 362 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 libffi-dev amd64 3.2.1-8 [156 kB] Fetched 156 kB in 0s (728 kB/s) Selecting previously unselected package libffi-dev:amd64. (Reading database ... 155649 files and directories currently installed.) Preparing to unpack .../libffi-dev_3.2.1-8_amd64.deb ... Unpacking libffi-dev:amd64 (3.2.1-8) ... Setting up libffi-dev:amd64 (3.2.1-8) ... Processing triggers for man-db (2.8.3-2ubuntu0.1) ... Selecting previously unselected package forest-sdk. (Reading database ... 155684 files and directories currently installed.) Preparing to unpack forest-sdk_2.23.0.deb ... Unpacking forest-sdk (2.23.0) ... Setting up forest-sdk (2.23.0) ... Processing triggers for man-db (2.8.3-2ubuntu0.1) ... 1.23.0 [e6c0939] 1.17.1 [cf3f91f]
Next, run the pyQuil QVM and Compiler if they are not already running on their default ports.
import subprocess
subprocess.Popen(["qvm", "--quiet", "-S"])
subprocess.Popen(["quilc", "--quiet", "-R"])
<subprocess.Popen at 0x7fd6121add10>
Running a Bell state circuit
To demonstrate the basic functionality of the Cirq Rigetti integration, we begin constructing a basic Bell state circuit.
bell_circuit = cirq.Circuit()
qubits = cirq.LineQubit.range(2)
bell_circuit.append(cirq.H(qubits[0]))
bell_circuit.append(cirq.CNOT(qubits[0], qubits[1]))
bell_circuit.append(cirq.measure(qubits[0], qubits[1], key='m'))
print(bell_circuit)
0: ───H───@───M('m')─── │ │ 1: ───────X───M────────
Next, we'll import RigettiQCSService
and list available quantum processors.
from cirq_rigetti import RigettiQCSService
quantum_processors = RigettiQCSService.list_quantum_processors().quantum_processors
processors_list = [quantum_processor.id for quantum_processor in quantum_processors]
print(processors_list)
['Aspen-11', 'Aspen-M-1']
For now, we'll instantiate the RigettiQCSService
as a pyQuil Quantum Virtual Machine based on the topology of one of the available Rigetti quantum processors. At the time of this writing, Aspen-11
is available.
Note, in addition to the quantum processors listed above, you can also instantiate the RigettiQCSService
by naming an arbitrary virtual device the pyQuil QVM supports. See the documentation for pyquil get_qc for more information.
from cirq_rigetti import circuit_transformers, circuit_sweep_executors, get_rigetti_qcs_service
SERVICE_NAME = processors_list[0]
print(SERVICE_NAME)
service = get_rigetti_qcs_service(SERVICE_NAME, as_qvm=True, noisy=False)
result = service.run(bell_circuit, repetitions=1000)
print(result.histogram(key='m'))
Aspen-11 Counter({3: 529, 0: 471})
We'll use the built-in cirq.plot_state_histogram
to visually verify the results of our Bell state.
cirq.plot_state_histogram(result.histogram(key='m'))
<matplotlib.axes._subplots.AxesSubplot at 0x7fd610001b10>
As expected, we see states 0 (ie '00') and 3 (ie '11') as the dominant results.
You may initialize both the RigettiQCSService
and RigettiQCSSampler
with execution functions from the cirq_rigetti.circuit_sweep_executor
module and transformation functions from cirq_rigetti.circuit_transformations
.
You may invoke these functions with arguments for controlling your circuit execution at a more fine grained level. For instance, you may want add Pragma statements to set the initial rewiring strategy, invoke active qubit reset prior to execution, or explicitly address physical qubits on the quantum computer.
from pyquil.quilbase import Reset, Pragma
def hook(program, measurement_id_map):
program._instructions.insert(0, Reset())
program._instructions.insert(1, Pragma('INITIAL_REWIRING', freeform_string='GREEDY'))
print(program)
return program, measurement_id_map
# assign qubits explicitly to hardware or virtual machine qubits.
qubit_id_map = {
qubits[0]: 4,
qubits[1]: 5,
}
executor = circuit_sweep_executors.with_quilc_compilation_and_cirq_parameter_resolution
transformer = circuit_transformers.build(qubit_id_map=qubit_id_map, qubits=qubits, post_transformation_hooks=[hook])
service = get_rigetti_qcs_service(SERVICE_NAME, as_qvm=True, executor=executor, transformer=transformer)
result = service.run(bell_circuit, repetitions=1000)
cirq.plot_state_histogram(result.histogram(key='m'))
RESET PRAGMA INITIAL_REWIRING "GREEDY" DECLARE m0 BIT[2] H 4 CNOT 4 5 MEASURE 4 m0[0] MEASURE 5 m0[1] <matplotlib.axes._subplots.AxesSubplot at 0x7fd6110b2150>
Running a parameterized circuit
Of course, you may be running a parameterized circuit and would like to leverage the Quil compilers support for parametric compilation. This affords a speedup in execution times as the Cirq Rigetti integration will only compile the circuit once for a single parameter sweep.
We start by initializing the RigettiQCSSampler
and specifying a circuit sweep executor that supports parametric compilation. Note, that this class accepts the same executor
and transformer
types as RigettiQCSService
.
from cirq_rigetti import get_rigetti_qcs_sampler
executor = circuit_sweep_executors.with_quilc_parametric_compilation
sampler = get_rigetti_qcs_sampler(SERVICE_NAME, as_qvm=True, executor=executor)
Next, we will initialize a parameterized circuit in Cirq along with a set of parameter values.
import sympy
qubit = cirq.LineQubit.range(1)[0]
circuit = cirq.Circuit(
cirq.H(qubit)**sympy.Symbol('t'),
cirq.measure(qubit, key='m'))
params = cirq.Linspace('t', start=0, stop=4, length=5)
print(circuit)
0: ───H^t───M('m')───
In much the same way that we invoke, RigettiQCSSerivce.run
, we invoke RigettiQCSSampler.run_sweep
with our parameters here.
import pandas as pd
results = sampler.run_sweep(circuit, params, repetitions=10)
data = {f't={result.params["t"]}': [measurement[0] for measurement in result.measurements['m']] for result in results}
pd.DataFrame(data)