terminal
Docs

Get started with Cirq on IonQ Hardware

Last updated: January 30, 2024
IonQ Staff

Cirq is an open source Python framework for writing, modifying, and running programs for quantum computers. As of v0.12.0, Cirq-Ionq provides support for IonQ’s trapped-ion systems. This means that you can write quantum circuits and run them on IonQ’s trapped-ion quantum computers, all from within the Cirq framework.

In this guide we will walk you through the process of writing and running a quantum program on an IonQ trapped-ion quantum computer via Cirq. We’ll see that this process allows you to swap out Cirq’s simulators for the IonQ device with only a few lines of code.

About Cirq

Cirq is an open-source Python framework which focuses on noisy intermediate scale quantum (NISQ) processors. It was developed by the quantum software team at Google, and is now supported by a vibrant open source community beyond Google. If you’re new to the framework, this tutorial gives a great introduction to the basics of Cirq and its philosophy.

Installing Cirq and the Cirq-IonQ Integration

For a simple install, you can install Cirq from PyPI, the Python Package Index, using pip:

pip install cirq-ionq==v0.14.1

However, to get the best experience from the framework, install recommended add-on packages, or for instructions specific to your OS, we recommend following the complete Cirq installation guide.

The IonQ Cloud API

IonQ’s quantum computers run behind the IonQ Quantum Cloud and are exposed via an API. That is to say, there are quantum computers in IonQ’s quantum data center, and you can remotely run quantum programs by sending them over the internet to the IonQ Cloud API. The IonQ Quantum Cloud will then take care of optimizing these programs for IonQ hardware and running them on the quantum computers themselves.

More specifically, quantum programs are sent to the API as jobsJobs are then put into a queue, where they are run in a fair, throughput-optimized way. Jobs are generally run and returned in a few minutes, but may take up to several hours depending on demand, maintenance windows, calibration, and the like. After a job has run, it is possible to query the IonQ Cloud API for the results.

So, the basic flow of running a job is:

  1. Write the quantum program

  2. Send program to the IonQ Cloud API, which creates a job

  3. Await the results of the job running to completion (or, use the job ID that is passed back to check back later for the results)

  4. Process the results

But, you don’t have to worry too much about this — the Cirq-IonQ integration takes care of most of the things that you would normally need to handle in a remote processing environment like this (for example, retrying results when the API is temporarily unavailable). All you have to do is create a program, specify IonQ as your backend, and wait for the results.

Running a Program on IonQ Hardware

Let’s walk through running a simple quantum program via the API.

Create a quantum program

First, let’s create a very simple quantum circuit for a trapped-ion quantum computer. IonQ’s 11-qubit trapped-ion system allows for two qubit gates between any of these qubits (so called all-to-all connectivity). In Cirq we represent these 11 qubits with a LineQubit object. Let’s create a quantum circuit to create an entangled pair of qubits as an example, in the process demonstrating that the gate can be between any two qubits.

# import cirq
import cirq_ionq as ionq

# In cirq_ionq <= 0.15, this helper will transpile the circuit.
qc = cirq_ionq.decompose_to_device(qc)

# In cirq_ionq >= 0.15, you can use the IonQTargetGateset and compile
# more complex custom gates!
# qc = cirq.optimize_for_target_gateset(qc, gateset=ionq_gateset.IonQTargetGateset(), 

q0, q1 = cirq.LineQubit(0), cirq.LineQubit(5)
circuit = cirq.Circuit()
circuit.append([cirq.H(q0), cirq.CNOT(q0, q1), cirq.measure(q0, q1, key='x')])
print(circuit)
0: ───H───@───M('x')───
          │   │
5: ───────X───M────────

Using print, we can see a visualization our little circuit that creates the entangled state (00+11)(∣00⟩+∣11⟩) and then measures it.

Set up the IonQ Cloud API Service

Once you have the API token, the basic object you will need to create to run a program is the ionq.Service object. Here we create such an object by directly feeding in the API key

API_KEY = “put the API key here”
service = ionq.Service(api_key=API_KEY)

However, we recommend storing your API key in an environment variable, rather than in your code itself. This is a more secure practice, because it means that you don’t have code with your sensitive API key in your code, which you might accidentally send to someone or check into source control.

Adding your API key to your environment variables in bash would look like this:

export IONQ_API_KEY=”put your API key here”

And if you use the name IONQ_API_KEY for this env var, you can instantiate the service just by calling

service = ionq.Service()

Run the job on the IonQ hardware

Now let’s run our quantum program via the IonQ Cloud API. There are two targets you can run your quantum program against. One is the IonQ cloud simulator and the other is IonQ’s 11-qubit trapped-ion system. The simulator target is called simulator, and the quantum computer is called qpu, for quantum processing unit. As new hardware gets added to the IonQ Quantum Cloud, more targets with different names will be added.

To submit the program and await the results, simply run

result = service.run(circuit=circuit, repetitions=100, target=`qpu`)

Note that this method will block waiting for the result to return. Because you have to wait for your program to get to the front of the queue to run, running a program this way can result in you waiting for a long time for the queue to clear. Below we explain a better pattern than this.

But, once the above does execute successfully, you get back a cirq.Result object, which is the basic container for results in Cirq.

# print out a histogram of the results
print(result.histogram(key=’x’))
Count({3: 55, 0: 42, 1: 2, 4: 1})

Here we see that mostly the results are 0 and 3 or, in binary, 00 and 11, which is what we expect from our quantum circuit.

The asynchronous pattern for running programs

An alternative way to execute the program is to run it asynchronously.

First, create a job:

job = service.create_job(circuit=circuit, repetitions=100, target='qpu')

From this job, you could just ask for the results, like so:

results = job.results()

but again, this would block until the results are done.

An alternative is to get the job ID and then periodically ask for its status.

print(job.job_id())

prints out a unique string id for the job. Once you have this ID, you can then recreate a job object at any time in the future:

same_job = service.get_job(job.job_id())

To check if the job is done running, you can query the job for its status, which is not a blocking action

print(same_job.status())

If the job is completed, this will return complete, and then you can get retrieve its results:

results = same_job.results()

Additional resources

A Jupyter notebook for getting started on IonQ hardware is available here.

Full documentation for the IonQ-Cirq integration can be found on the Cirq documentation site. This site also includes numerous tutorials and documentation about writing and running quantum circuits in Cirq, many of which you'll be able to be run on IonQ hardware with minimal modification.

One particularly useful read is the page on the IonQAPIDevice, which is a way to make sure your circuit runs with gates that are supported by the IonQ API.

Additional SDKs

Beyond Cirq, IonQ supports integration with most major quantum SDKs. These include Microsoft’s Q#Amazon’s BraketIBM’s QiskitXanadu’s PennyLaneCambridge Quantum Computing’s pytketOak Ridge National Laboratory’s XACC, and more.

Licensing for Cirq is Apache 2.0. API keys and access to IonQ services must be obtained under separate terms from IonQ.

The IonQ logo and Q mark are trademarks of IonQ, Inc. Copyright IonQ © 2021. All rights reserved.