# Get Backends
get /backends
Retrieve a list of all available backends.
# Get a Characterization
get /characterizations/{UUID}
This endpoint retrieves a characterization.
# Get All Backend Characterizations
get /characterizations/backends/{backend}
This endpoint retrieves an array of all available backend characterizations, with pagination.
# Get the Most Recent Backend Characterization
get /characterizations/backends/{backend}/current
This endpoint retrieves the most recent backend characterization data available.
# API Core Concepts
This page details some concepts specific to how the API works. There is also a more-general [platform glossary](/glossary) as well as a [quantum-focused glossary on ionq.com](https://ionq.com/resources/glossary).
## Jobs
A **job** is the basic unit of work on the IonQ cloud.
Whether you're simulating a simple circuit, or submitting a program to run on our world-class hardware, you'll send it along as a job.
***
## Quantum Programs
Quantum programs are collections of circuits to be run on a QPU. They are submitted to a job in the `input` parameter. Examples can be found on the [Writing Quantum Programs](/api-reference/v0.3/writing-quantum-programs)
***
## Metadata
Updatable resources (such as a [Job](/api-reference/v0.3/jobs)) can store arbitrary metadata for your convenience — we store but ignore it. For example, you could tag different algorithms or projects for later analysis, or if you're building an app, tag jobs submitted by customers with a unique customer ID.
You can specify up to 10 keys, with names up to 40 characters long and values up to 40000 characters long.
```json
{
"metadata": {
"custom_key": "a string, maximum 400 chars"
},
"input": { ... }
}
```
***
## Authorization
API keys are associated with a user and can be created on the
[IonQ Quantum Cloud](https://cloud.ionq.com) application. To authenticate, prefix your API Key with `apiKey ` and place it in the `Authorization` request header. For example:
```
Authorization: apiKey {your-api-key}
```
If you're new to managing API keys, [learn more in our guide](/guides/managing-api-keys).
***
## Pagination
You can bulk fetch any resource (for example, [list all jobs](#operation/getJobs) you have access to).
In addition to any specific query parameters those endpoints may support for filtering, all endpoints returning multiple resources take two parameters for pagination: next and limit.
limit tells us how many objects to return; next identifies the next chunk of the iteration.
When loading a paginated resource, you'll receive a next key with each page. Pass it to subsequent queries with a `next` querystring to fetch the next batch.
```bash
curl -H "Authorization: apiKey ..." "https://api.ionq.co/v0.3/jobs?limit=100&next=dce01d5c-987e-48e8-b2b7-41c24d69d711"
{
"jobs": [ ... ],
"next": "38f525e4-f865-48f6-a996-dab85ba1f7b0"
}
```
***
## HTTP Responses
IonQ uses standard HTTP response status codes to indicate the result of a request.
### Success
A successful response will have a status code in the `2XX` range. Successful responses are documented above on a per-endpoint basis.
### Bad Request
A request that contained invalid input data will have a `400` response status code and response data indicating the invalid items:
```json
{
"statusCode": 400,
"error": "Bad Request",
"message": "\"some-parameter\" was invalid.",
"validation": {
"keys": [
"some-parameter"
],
"source": "params"
}
}
```
### Unauthorized
A request that fails API Authentication will receive a `401`.
See API Key for more details.
```json
{
"statusCode": 401,
"error": "Unauthorized Error",
"message": "Invalid key provided. See https://docs.ionq.com/#authentication for details, or email support@ionq.co for help."
}
```
### Not Found
A request whose resource does not exist will have a `404` response status code and some detail about the missing resource:
```json
{
"statusCode": 404,
"error": "Not Found Error",
"message": "Resource not found. See https://docs.ionq.com/ for details, or email support@ionq.co for help."
}
```
### Internal Server Error
Any unexpected errors are indicated by the `500` response status code.
Internal service outage. Visit [https://status.ionq.co/](https://status.ionq.co/) to track this incident.
```json
{
"statusCode": 500,
"error": "Internal Server Error",
"message": "Internal service outage. Visit https://status.ionq.co/ to track this incident."
}
```
# v0.3 Error Codes
When a request fails, the API will respond with an appropriate 400 or 500 error in the following format in the body of the response:
```javascript
{
'error': 'Error Name',
'message': 'A description of the specific error conditions.',
'statusCode': 400
}
```
| Error | Description |
| --------------------- | -------------------------------------------------------------------------------------------- |
| Bad Request | Generic request error. The message should indicate the specific parameter which was invalid. |
| Forbidden | The request failed to authenticate the supplied API key |
| Unauthorized | The supplied API key failed authorization for the requested resource |
| Not Found | The specified resource does not exist or could not be found. |
| Internal Server Error | A service was unexpectedly offline, unavailable, or failed in an unknown manner. |
***
## Job Errors
The following errors are specific to the `/job` ([API reference](/api-reference/v0.3/jobs/)) resource:
| Error | Description |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| BillingError | Generic error inside of the billing service |
| CircuitTooLarge | The circuit has too many unique gates on a single qubit which created an error when converting to pulse waveforms on-system |
| CompilationError | Generic failure in our compilation service |
| ContractExpiredError | The billing service shows that the contract governing the key being used has expired |
| DebiasingError | Unknown execution error when using debiasing (an IonQ-provided error mitigation technique) |
| InternalError | An unattributable internal error |
| NotEnoughQubits | The backend you are submitting to has fewer qubits than this job requires |
| OptimizationError | Generic error in our optimization service |
| PreflightError | Generic error during preflight checks. This most often occurs when the input circuit is syntax checked and includes malformed gates, commands, formats, or similar |
| QuantumComputerError | Generic failure that occured while the job was being processed on-QPU |
| QuotaExhaustedError | The billing system shows that your user, project, or organization has an inadequate credit balance to run this job |
| SimulationError | Generic failure in our simulation service |
| SimulationTimeout | Timeout error in our compilation service. This is most commonly caused by simulations that are too large for the service to simulate before hitting our runaway process timeout |
| SystemCancel | A member of IonQ staff has manually cancelled your job. This most often occurs as a result of a customer request, but can sometimes represent manual resolution of an unknown failure mode |
| TooLongPredictedExecutionTime | preflight error of a specific type: the predicted execution time for the circuit was longer than the single-job timeout duration for a given backend |
| TooManyControls | The job submitted includes a multi-control gate with more control qubits (7 or more) than the target backend allows |
| TooManyGates | Preflight error of a specific type: the job submitted includes more gates per circuit than the target backend allows |
| TooManyShots | Preflight error of a specific type: the job submitted requested more shots than the target backend allows |
| UnknownBillingError | Unknown error related to but not originating from our billing service. This most often means the service is briefly unavailable for some reason. |
| UnsupportedGate | Preflight error of a specific type: the job submitted uses a gate that the target backend does not allow |
***
# Introduction
Our API uses the [REST](https://en.wikipedia.org/wiki/Representational_State_Transfer) architectural style, which means we provide unsurprising, resource-oriented URLs and take advantage of built-in HTTP response codes, authentication, verbs, and other features.
We allow cross-site requests from any domain, and return JSON responses.
***
## Working with APIs
While you can work [directly](/guides/direct-api-submission) with our APIs if you'd like, most users will find it more convenient to work through one of the available SDKs. For new users, we tend to recommend [Qiskit](https://github.com/Qiskit/qiskit), and have provided a [getting started guide](/guides/qiskit) for it.
***
## System status
We continuously report the status of our APIs and our QPU fleet at [https://status.ionq.co/](https://status.ionq.co/). On that page, you can subscribe for automated updates when we perform maintenance or experience an outage.
System status is also displayed within the IonQ Quantum Cloud application on the [Backends](https://cloud.ionq.com/backends) page.
# Cancel a Job
put /jobs/{UUID}/status/cancel
Cancel the execution of a single job by ID.
# Cancel many Jobs
put /jobs/status/cancel
Cancel the execution of many jobs at once by passing a list of jobs.
# Create a Job
post /jobs
To submit a program to be simulated or executed on our quantum hardware, `POST` it to the `jobs` endpoint.
# Delete a Job
delete /jobs/{UUID}
Permanently delete a job from our service. This cannot be undone.
# Delete many Jobs
delete /jobs
Permanently remove many jobs from our platform. This cannot be undone.
# Get a specific Job
get /jobs/{UUID}
Retrieve a specific job by UUID.
# Get a Job's output
get /jobs/{UUID}/results
Retrieve a specific job's results by UUID.
# Get Jobs
get /jobs
**NOTE**: If request filters are provided, this endpoint will limit responses to 1 or more specific jobs based on those filters.
This endpoint retrieves all jobs this API key is authorized to view.
# Migrating from old versions
### Breaking changes
* Body has been renamed to `input`, and is always a JSON payload. The `format` field in input replaces lang as a means of controlling what kind of input is being run.
* Results are no longer served alongside the job body when fetching jobs; now use the results\_url field to fetch.
* *(v0.1 only)* **Calibrations** endpoints has been deprecated in favor of [Characterizations](/api-reference/v0.3/characterizations).
### New features
* Error mitigation is now controllable via API. Debiasing can improve performance via randomized qubit mappings and intelligent post-processing of noise.
* Ability to specify target hardware generation on Job creation. (e.g. `qpu.aria-1`)
## Non-breaking changes
* Histogram example expanded to include scientific notation for a JSON numeric value.
# Multicircuit Jobs
This guide covers everything from setting up a multicircuit job, submitting it to IonQ's backend, and retrieving the results.
Jobs contain a circuit to be executed on a QPU, and in the case of *multicircuit* jobs, multiple circuits are being submitted in a single job payload. The advantage of this approach is that it simplifies the submission process, allowing for example, all of the circuits of a gradient calculation to be submitted in a single HTTP request, instead of over hundreds.
When submitting work from a local environment with a poor internet connection, this can also help overcome job submissions failing intermittently from network issues.
To ensure smooth processing, please format your quantum programs in
`ionq.circuit.v0` as demonstrated below.
## Creating a Multicircuit Job
Below is a JSON object that describes a multicircuit job for IonQ's simulator. This job includes two distinct circuits:
```json
{
"target": "simulator",
"shots": 1024,
"name": "Multicircuit Job Example",
"input": {
"format": "ionq.circuit.v0",
"gateset": "qis",
"qubits": 3,
"circuits": [
{
"name": "Circuit 1",
"circuit": [
{
"gate": "rz",
"targets": [0],
"rotation": -0.7853981633974474
},
{
"gate": "ry",
"targets": [0],
"rotation": 3.141592653589793
}
]
},
{
"name": "Circuit 2",
"circuit": [
{
"gate": "h",
"targets": [1]
},
{
"gate": "x",
"targets": [2],
"controls": [1]
}
]
}
]
}
}
```
## Submitting the Job
To submit this multicircuit job to IonQ, use the following `curl` command. Make sure to replace `your-api-key` with your actual API key:
```bash
curl -X POST "https://api.ionq.co/v0.3/jobs" \
-H "Authorization: apiKey your-api-key" \
-H "Content-Type: application/json" \
-d '{...}' # JSON data from the creation step
```
### Expected Response
You should receive a JSON response containing the job ID and status, similar to this:
```json
{
"id": "unique-job-id",
"status": "ready",
"request": 1234567890
}
```
## Retrieving Job Results
Once the job is complete, fetch the results using the job's UUID provided in the job submission response:
```bash
curl "https://api.ionq.co/v0.3/jobs/unique-job-id/results" \
-H "Authorization: apiKey your-api-key"
```
### Result Example
```json
{
"circuit1-uuid": {
"0": 0.5,
"6": 0.5
},
"circuit2-uuid": {
"1": 1.0
}
}
```
Each UUID represents a circuit within your job, and the results show the probability distribution of the qubit measurements.
If you are interested in implementing these steps using the Qiskit SDK, check
out this detailed [multicircuit guide with Qiskit and
IonQ](https://docs.ionq.com/guides/sdks/qiskit#submitting-multiple-circuits-in-a-single-job).
# Using native gates with the IonQ API
Learn how to use our hardware-native gateset to run a circuit with the IonQ API
This guide covers how to use IonQ's native gates via our API. To learn more about what the native gates are and when to use them, refer to our guide on [getting started with native gates](/guides/getting-started-with-native-gates).
Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control and transparency than the default abstract gateset (though often at the cost of performance and convenience).
Before working with native gates, we recommend reviewing our guides on [Getting Started with Native Gates](/guides/getting-started-with-native-gates) and [Writing Quantum Programs](/api-reference/v0.3/writing-quantum-programs). Native gates are also supported in [Qiskit](/sdks/qiskit/native-gates-qiskit), [Cirq](/sdks/cirq/native-gates-cirq), and [PennyLane](/sdks/pennylane/native-gates-pennylane).
This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.
***
## Native gate JSON specification
If you have used our abstract gate specification, the native gate specification should feel quite familiar. Its parameters are slightly different though, and we'll walk through them here.
To specify a circuit using native gates, you must do two things:
1. Set the parameter `gateset` to `"native"` inside the circuit body. This is an optional parameter that defaults to `"qis"`, which signifies our abstract gateset based on the general-purpose gates of quantum information science (QIS).
2. Your `circuit` array must only use native gates. These are formatted similar to [QIS gates](/api-reference/v0.3/writing-quantum-programs#supported-gates). The only gates allowed in a native gate circuit are `gpi`, `gpi2`, and either `ms` or `zz` depending on the backend. You cannot mix and match native and abstract gates in the same circuit.
Much more detailed information about the native gate definitions can be found in our [native gates guide](/guides/getting-started-with-native-gates#introducing-the-native-gates)
### Parameters
Available parameters (depending on gate type) are:
* `gate`: a string representation of the gate name. This works just like the abstract gate interface, but you can only use the available native gates: `gpi`, `gpi2`, `ms`, and `zz`. If you submit any other gates in the array, you'll receive an error.
* `phase` or `phases`: a number representation of the phase parameter or parameters in the gate. It is represented in *turns*, where one turn is 2π radians. We accept floating point values between -1 and 1 for this parameter.
* `angle`: an optional number representation of the angle parameter, available for the MS gate only. This value is also represented in turns and can range from 0 to 0.25 (fully entangling), with 0.25 being the default.
* `target` or `targets`: the number index (starting from zero) of the qubit to apply the gate to. For two-qubit gates, use an array of qubit indices labeled `targets` instead.
The parameters in the IonQ native gate specification are always defined in *turns*, not in radians. One turn is 2π radians.
### Gates
| Gate | Description | Parameters |
| ------ | ----------------------------------------------------------------------------------------------------- | --------------------------------------- |
| `gpi` | [GPI gate](/guides/getting-started-with-native-gates#gpi) | `phase`, `target` |
| `gpi2` | [GPI2 gate](/guides/getting-started-with-native-gates#gpi2) | `phase`, `target` |
| `ms` | [Mølmer–Sørensen gate](\(/guides/getting-started-with-native-gates#ms-gates\)) (only on Aria systems) | `phases`, `angle` (optional), `targets` |
| `zz` | [ZZ gate](\(/guides/getting-started-with-native-gates#zz-gates\)) (only on Forte systems) | `angle`, `targets` |
***
## Basic example
Here's a simple example circuit using native gates with the IonQ API.
```json
{
"name": "Hello native gates!",
"shots": 1024,
"target": "simulator",
"input": {
"gateset": "native",
"qubits": 2,
"circuit": [
{
"gate": "ms",
"targets": [0, 1],
"phases": [0, 0]
},
{
"gate": "gpi",
"phase": 0,
"target": 0
},
{
"gate": "gpi2",
"phase": 0,
"target": 1
}
]
}
}
```
Like any other [API job](/guides/direct-api-submission), you can save this to a file, like `native_gates_circuit.json`, and submit it:
```bash
curl -X POST "https://api.ionq.co/v0.3/jobs" \
-H "Authorization: apiKey $IONQ_API_KEY" \
-H "Content-Type: application/json" \
-d @native_gates_circuit.json
```
***
## Additional resources
* [Direct API submission](/guides/direct-api-submission)
* [API reference for POST /jobs](/api-reference/v0.3/jobs/create-a-job)
* [Writing quantum programs](/api-reference/v0.3/writing-quantum-programs)
* [Getting started with native gates](/guides/getting-started-with-native-gates)
* Using native gates with [Qiskit](/sdks/qiskit/native-gates-qiskit), [Cirq](/sdks/cirq/native-gates-cirq), and [PennyLane](/sdks/pennylane/native-gates-pennylane)
# Get an Organization’s Report
get /report/organizations/{org_id}
Get a usage report for the given organization from the start_date and end_date, detailing how much usage went to each QPU during that period. If no start_date or end_date are provided, period defaults to last 30 days until current time.
# Writing Quantum Programs
For the best results, please submit quantum programs in the `ionq.circuit.v0` format, as demonstrated below.
In the compilation and optimization process, your submitted circuit will be converted to an equivalent, optimized circuit expressed in terms of IonQ's native gates, which may involve combining or canceling out some operations. If you wish to guarantee that the quantum computer executes the exact series of operations that you define, please bypass our compiler and submit directly to our native gate interface.
For more examples and the full API specification for defining circuits, refer to [the API reference](/api-reference/v0.3/jobs/create-a-job).
To write a quantum program using [Qiskit](/guides/sdks/qiskit) or another SDK, refer to our SDK guides.
***
## Bell State
We can create a maximally entangled [Bell state](https://en.wikipedia.org/wiki/Bell_state) by applying a Hadamard gate to a single qubit, and applying a controlled-not gate to a second qubit.
Half of the time the second qubit will be measured as $|0⟩$, the other half will be measured as $|1⟩$.
```json
{
"format": "ionq.circuit.v0",
"gateset": "qis",
// The fields above are optional, as they are the default.
"qubits": 2,
"circuit": [
{
"gate": "h",
"target": 0
},
{
"gate": "cnot",
"target": 1,
"control": 0
}
]
}
```
***
## GHZ State
We can create a three qubit [GHZ state](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state) by first applying a Hadamard gate to a single qubit, and then using it as the control qubit for a series of controlled-not gates.
```json
{
"qubits": 4,
"circuit": [
{
"gate": "h",
"target": 0
},
{
"gate": "cnot",
"control": 0,
"target": 1
},
{
"gate": "cnot",
"control": 0,
"target": 2
},
{
"gate": "cnot",
"control": 0,
"target": 3
}
]
}
```
***
## Toffoli gate
The [Toffoli gate](https://en.wikipedia.org/wiki/Toffoli_gate), or controlled-controlled-not gate, is a universal reversible logic gate. We can simply apply a cnot to our target qubit, with two control qubits provided via array.
```json
{
"qubits": 3,
"circuit": [
{
"gate": "cnot",
"target": 0,
"controls": [1, 2]
}
]
}
```
***
## Supported Gates
For actual execution, gates will be compiled into optimal operations for our trapped ion hardware. For convenience, we provide a more expressive gateset for programming.
| Gate | Description |
| ------ | ---------------------------------------------- |
| `x` | Pauli X gate |
| `y` | Pauli Y gate |
| `z` | Pauli Z gate |
| `rx` | X-axis rotation |
| `ry` | Y-axis rotation |
| `rz` | Z-axis rotation |
| `h` | Hadamard gate |
| `not` | Convenient alias for Pauli-X gate |
| `cnot` | Convenient alias for controlled-not gate |
| `s` | S gate |
| `si` | Conjugate transpose of S gate |
| `t` | T gate |
| `ti` | Conjugate transpose of T gate |
| `v` | Square root of not gate |
| `vi` | Conjugate transpose of square-root-of-not gate |
| `swap` | Swaps two qubits |
Each operation in a circuit specifies a `gate` and a `target` qubit index (or a list of multiple `targets`). Rotation gates also specify a `rotation` in radians.
In addition, any gate can be expressed as a controlled gate by specifying a `control` qubit, or as its multi-controlled variant by specifying a list of up to seven `controls` (for any gate except `swap`). This can often be used to simplify the circuit's description. In general, circuits expressed in fewer QIS gates will be further optimized for runtime, so using multi-controlled variants of gates is recommended.
Examples:
* Hadamard gate: `{"gate": "h", "target": 0}`
* Controlled-not gate: `{"gate": "cnot", "target": 1, "control": 0}`
* Toffoli gate (multi-controlled not gate): `{"gate": "cnot", "target": 0, "controls": [1, 2]}`
* Rx gate with $\pi/2$ rotation: `{"gate": "rx", "target": 0, "rotation": 1.5708}`
* Swap gate: `{"gate": "swap", "targets": [0,1]}`
For more examples and the full API specification for defining circuits, refer to [the API reference](/api-reference/v0.3/jobs/create-a-job).
## Native Specification
For information about writing quantum programs using IonQ's hardware-native gate set, refer to our guides on [getting started with native gates](/guides/getting-started-with-native-gates) and [using native gates with the IonQ API](/api-reference/v0.3/native-gates-api).
***
## Other Formats (experimental)
Support for submitting programs in [QASM/OpenQASM](https://github.com/Qiskit/openqasm/) and [Quipper](https://www.mathstat.dal.ca/~selinger/quipper/) is currently experimental. If you use these languages, we will compile your code to a logically-equivalent representation using our Supported Gates. (For billing purposes, we'll calculate your program's resource requirements **after** it's been compiled this way.)
### OpenQASM
```json
{
"format": "openqasm",
"data": "string"
}
```
### QASM
```json
{
"format": "qasm",
"data": "string"
}
```
### Quipper
```json
{
"format": "quipper",
"data": "string"
}
```
***
Is there a language format you'd like to see supported? Drop us a line and let us know.
# null
# Connecting a SAML Identity Provider
Enhance security and simplify user management by authenticating with your SAML-based SSO provider
IonQ Quantum Cloud can be integrated with any [SAML 2.0](https://en.wikipedia.org/wiki/SAML_2.0) compatible Single sign-on (SSO) provider, such as Azure Active Directory, Okta, or JumpCloud. By federating IonQ with your Provider, you can easily provide access to anyone in your organization and manage that access centrally.
***
## Before you begin
To successfully complete this integration, you'll need:
* The ability to create or register a new Application in your Identity system
* Your Identity provider's Entity ID, SAML SSO URL, and Public Key certificate.
***
## Configuring Your Identity Provider
Your Identity Provider must be configured to recognize IonQ Quantum Cloud as a new application. How this works varies by provider, but typically you'll find an Applications section within your Admin control panel.
When you create the new application, you'll set the following:
1. Assertion Consumer Service (ACS) URL: `https://ionq.firebaseapp.com/__/auth/handler`
2. Application Entity ID: `app.ionq.com`
Once the App has been added to your system, you'll be able to create access rules for your users. Again, how this is configured varies by provider, but
typically App access is set for either specific roles or specific users.
***
## IonQ Configuration
Once the App has been added on the Identity Provider side, email the following information to [support@ionq.co](mailto:support@ionq.co):
> 1. Identity provider's Entity ID: A URI that identifies the identity provider.
> 2. Identity provider's SAML SSO URL: The URL of the identity provider's sign-in page.
> 3. Identity provider's public key certificate: The certificate used to validate tokens signed by the identity provider.
Once received, our team will configure the provider in our production environment within 2 business days.
***
## Testing and Support
Once we've registered your provider with IonQ Quantum Cloud, the IonQ team will get in touch to work with you so you can debug and test the configuration before enabling it on your organization.
If you need further assistance, or have any questions about this process, please reach out at [support@ionq.co](mailto:support@ionq.co) or contact the Customer Success manager for your Organization.
# Direct API Submissions
Learn how to submit jobs directly to the IonQ API
Most users will submit jobs and interact with IonQ through an SDK like [Qiskit](/guides/qiskit), but in some instances direct API submission is needed. This guide walks you through the basics of using the IonQ Quantum Cloud to write and run quantum programs: using the Quantum Cloud API to specify a quantum circuit, submitting it as a job, and then accessing the results.
## Before you begin
You'll need an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and you'll need to create an API key. We also have a guide about [setting up and managing your API keys](/guides/managing-api-keys) if you need some help.
This guide assumes that you have followed these instructions and have saved your API key as a local environment variable named `IONQ_API_KEY`.
***
## Writing a quantum circuit
We'll need to create a quantum circuit to submit as your first job. Let's use a simple [GHZ state](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state) using three qubits, first applying a Hadamard gate to a single qubit, and then using it as the control qubit for a series of controlled-not gates on the other two.
Diagrammed, a three-qubit GHZ circuit looks like this:
![A visualization of a Greenberger-Horne-Zeilinger (GHZ) state.](https://mintlify.s3-us-west-1.amazonaws.com/ionq/guides/_media/direct-api-submission-ghz-circuit.png)
In IonQ's language-agnostic JSON circuit representation, the circuit looks like this:
```json
{
"input": {
"qubits": 3,
"circuit": [
{
"gate": "h",
"target": 0
},
{
"gate": "cnot",
"control": 0,
"target": 1
},
{
"gate": "cnot",
"control": 0,
"target": 2
}
]
}
}
```
***
## Submit your quantum circuit as a Job
For the purposes of this guide we'll use `curl` on the command line, but in the real world example, you'd likely want to use a [SDK](/guides/qiskit). Alternately you may be using an HTTP request library in Python, Javascript.
Now we're ready to submit this circuit as a job. To submit the job, we need to add a few additional parameters to our circuit: the language, the number of shots, where we want the job to run (ex: `simulator` or `qpu.aria-1`) and, optionally, a name for your own reference.
For a full list of options that can be passed to this resource check out the API reference for [POST /jobs](/api-reference/v0.3/jobs/create-a-job).
In this case, we'll submit a job to the simulator so that we get our results quickly, and we'll use the Aria [noise model](/guides/simulation-with-noise-models):
```json
{
"name": "Hello many worlds!",
"shots": 1024,
"target": "simulator",
"noise": {
"model": "aria-1"
},
"input": {
"qubits": 3,
"circuit": [
{
"gate": "h",
"target": 0
},
{
"gate": "cnot",
"control": 0,
"target": 1
},
{
"gate": "cnot",
"control": 0,
"target": 2
}
]
}
}
```
Paste this in your text editor of choice and then save it using a memorable name—something like `ghz-job.json`.
Now, we're ready to submit our job to the IonQ Cloud API. To do that, we'll `POST` our JSON job body to the job creation route, with two headers: one for authorization with the API key we created earlier, and one to tell the API that our job body is JSON formatted. Since we want to see something quickly, we'll submit to `"target": "simulator"` for now.
```bash
curl -X POST "https://api.ionq.co/v0.3/jobs" \
-H "Authorization: apiKey $IONQ_API_KEY" \
-H "Content-Type: application/json" \
-d @ghz-job.json
```
Which will return something like:
```json
{
"id": "7135ca98-176f-48c9-8616-8f53ec505028",
"status": "ready",
"request": 1718302151
}
```
And there it goes! The `id` can now be used to [cancel it](/api-reference/v0.3/jobs/cancel-a-job), [get the status](api-reference/jobs/get-a-specific-job), or [retrieve results](api-reference/jobs/get-a-specific-jobs-output).
***
## Retrieve the job results
To retrieve the job, we can now `GET` it at its own resource URL, determined by the job id:
```bash
curl "https://api.ionq.co/v0.3/jobs/{your-job-id}" \
-H "Authorization: apiKey $IONQ_API_KEY"
```
Remember to replace `{your-job-id}` with the ID you just got back.
This request will return the current status. Since we submitted to the simulator, our job is already `completed`! (Note: If you decided to submit to a QPU, you'll have to wait for your job to work its way through the queue):
```json
{
"id": "7135ca98-176f-48c9-8616-8f53ec505028",
"submitted_by": "65e8b97c521dcf001299126b",
"name": "Hello many worlds!",
"status": "completed",
"target": "simulator",
"qubits": 3,
"circuits": 1,
"results_url": "/v0.3/jobs/7135ca98-176f-48c9-8616-8f53ec505028/results",
"gate_counts": {
"1q": 1,
"2q": 2
},
"cost_usd": 0,
"project_id": "428499cb-c392-4ab1-ad8e-c954a1a99ff5",
"request": 1718302151,
"start": 1718302154,
"response": 1718302154,
"execution_time": 78,
"predicted_execution_time": 8,
"shots": 1024,
"noise": {
"seed": 917721158,
"model": "aria-1"
},
"error_mitigation": {
"debias": false
},
"children": []
}
```
## Retrieving the results
Now that the job has completed, we can retrieve the results using the URL provided in the output:
```bash
curl "https://api.ionq.co/v0.3/jobs/{your-job-id}/results" \
-H "Authorization: apiKey $IONQ_API_KEY"
```
Which will return a dictionary with the results of the job:
```json
{
"0": 0.4619140625,
"1": 0.017578125,
"2": 0.0185546875,
"3": 0.0244140625,
"4": 0.0185546875,
"5": 0.025390625,
"6": 0.0107421875,
"7": 0.4228515625
}
```
The results request contains the histogram output of the probabilities of each measured state across all 1024 shots. Two things to note here: the output is sparse, that is, it only shows data for outcomes that were actually measured, and the output keys are formatted as big-endian integers, i.e. 0 is 000, 2 is 010, 3 is 011, and so-on, where the leftmost bit is the qubit with index zero from our submitted program.
***
## Additional Resources
If you're working on your own tools to interact with the API, the full [API Reference](/api-reference) has details on HTTP verbs and endpoints, expected response formats, and other features not covered in this guide.
Additionally, our [best practices page](https://ionq.com/best-practices) provides detailed instructions for getting the most out of our trapped-ion systems, and our support center is always available to help you solve any problems you might run into.
# IonQ API Key Management with dotenv Integration
Discover how to effortlessly manage IonQ API keys across various projects by leveraging dotenv's automatic loading feature, enhancing security and codebase cleanliness.
## Leveraging dotenv for IonQ API Key Management
Storing and managing API keys securely is paramount in software development, especially when dealing with sensitive services like IonQ's quantum computing API. There are a couple of methods for securely storing your IonQ API key where integrations like `qiskit_ionq` can automatically find it: you can [store it locally in an environment variable on your system](/guides/managing-api-keys#storing-keys) as described in our main API key guide, or use dotenv as shown here.
This guide introduces a streamlined approach to handle IonQ API keys using dotenv, which automatically loads `.env` files, thus simplifying the management process across different projects. Using dotenv may be easier than using your system's environment variables, depending on your particular setup and preferences.
## Prerequisites
Before diving in, ensure you have:
* Registered on the [IonQ Quantum Cloud](https://cloud.ionq.com) and generated your API keys. Visit IonQ's [API key management guide](/guides/managing-api-keys) for detailed instructions.
* Python 3.11 installed on your computer. Confirm your Python version with `python --version` via command line.
To prevent dependency conflicts, consider utilizing an environment manager
like [virtualenv](https://virtualenv.pypa.io/en/latest/) or
[conda](https://docs.conda.io/en/latest/).
## Step 1: Creating a .env File
Navigate to the root directory of your project and create a `.env` file. This file will host your project-specific settings, including the IonQ API key, keeping them secure and easily accessible.
## Step 2: Adding the IonQ API Key to the .env File
Open the `.env` file in a text editor and insert your IonQ API key as shown below:
```plaintext
IONQ_API_KEY=your_api_key_here
```
Replace `your_api_key_here` with your actual IonQ API key. After saving the file, your key is securely stored and ready for use.
Don't forget that sharing the `.env` file that contains your API key would mean sharing access to your IonQ account and resources. If you unintentionally share the file, you can always revoke an API key from the IonQ Cloud Console.
## Step 3: Ensure dotenv Package Installation
The IonQ Provider for Qiskit has been designed to check for and automatically load `.env` files. If you haven't already, ensure the `python-dotenv` package is installed in your environment:
```bash
pip install python-dotenv
```
## Step 4: Using the IonQ API Key in Your Project
With the `python-dotenv` package installed and your `.env` file configured, the `IonQProvider` is now set to automatically load and use the API key from the `.env` file without any additional code for dotenv loading in your script.
With this automatic loading feature, accessing the IonQ API key in your project code is straightforward. Here's an example with the IonQ Provider for Qiskit:
```python
from qiskit_ionq import IonQProvider
# The IonQProvider automatically looks for the IONQ_API_KEY in your environment
provider = IonQProvider()
```
This setup ensures your IonQ API key is automatically detected and utilized, streamlining the development process.
## Conclusion
You've successfully learned how to manage IonQ API keys more efficiently using dotenv's automatic loading functionality. This approach not only secures your API keys by keeping them out of your codebase but also simplifies configuration management across multiple projects.
For additional information on quantum computing and project management with IonQ, explore the comprehensive [IonQ documentation](https://ionq.com/docs).
# Native Gates
Getting started with IonQ's hardware-native gateset
This is a general guide covering what the native gates are and why you might want to use them. To learn *how* to use these native gates, refer to our native gate guides for the [IonQ API](/api-reference/v0.3/native-gates-api), [Qiskit](/sdks/qiskit/native-gates-qiskit), [Cirq](/sdks/cirq/native-gates-cirq), and [PennyLane](/sdks/pennylane/native-gates-pennylane).
The IonQ Quantum Cloud has one of the best—-maybe *the* best—-optimizing compilers in quantum computing. This allows users to focus on the details of their algorithms instead of the details of our quantum system. You can submit quantum circuits using a large, diverse set of quantum gates that allows for maximum flexibility in how to define your problem, and our compilation and optimization stack ensures that your circuit runs on our QPUs in the most compact, streamlined, hardware-optimized form possible.
This flexibility in circuit definition also allows for high portability of algorithm code. We don't restrict you to hardware-native basis gates, so you're free to define in any gateset you want—-even the basis gates of a different hardware provider—-and then simply submit to IonQ hardware as-is. No changes necessary!
While this is ideal for many applications, the hardware-native basis gateset allows for more customizability, flexibility, and what-you-submit-is-what-you-get control. Being as “close to the metal” as possible allows for control over each individual gate and qubit, unlocking avenues of exploration that are impossible with a compiler between you and the qubits. Currently, submitting circuits defined in native gates is the only way to bypass the compiler and optimizer.
Read on to get started with our hardware-native gate specification, learn how it works, and run an example circuit using this powerful new ability.
This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.
***
## When to use native gates
Native gates are not the right solution for every problem. As the warning above states, the native gate specification is an advanced-level feature. If your goal is simply to run a quantum circuit for evaluation or algorithm investigation purposes, using native gates will *often* result in lower-quality output than simply using the abstract gate interface.
The native gate interface is the simplest, most direct way to run a circuit on IonQ hardware: we run exactly the gates you submitted, as submitted, and we return the results. That's it.
![Comparison of submitting via the native gate interface (blue) and the abstract interface (black)](https://mintlify.s3-us-west-1.amazonaws.com/ionq/guides/_media/native-gate-flow.png)
This means that our proprietary compilation and optimization toolchain is **fully turned off** when we execute a "native" circuit. (Error mitigation is also turned off by default, though you can choose to override this setting and turn on debiasing.) To take full advantage of our compilation, optimization, and error mitigation, you must submit your circuit using our default abstract gate interface, and if you are looking for maximum algorithmic performance from our systems, it is likely that you'll find it by doing just that.
But, this toolchain performs a number of transformations on submitted circuits that we consider proprietary, and we therefore do not disclose the full details of how it works. By the time a circuit you submit through the abstract gate interface actually runs on hardware, it has been changed, sometimes considerably. Extraneous gates are optimized away or commuted into different places, they are transpiled into native gates using special heuristics and optimized again, and so on.
So, we recommend only using native gates when you cannot use the abstract interface to accomplish your goals - when you need to know exactly what circuit was run, or when you specifically want to run circuits that are not optimized. This might involve investigation and characterization of noise, designing noise-aware circuits, or exploring new error mitigation techniques, as well as the development and testing of circuit optimization and compilation methods.
***
## Introducing the native gates
The native gateset is the set of quantum gates that are physically executed on IonQ hardware by addressing ions with resonant lasers via stimulated Raman transitions.
We currently expose two single-qubit gates and one two-qubit entangling gate for each QPU. Other native gates may be provided in the future.
All gate parameters are measured in *turns* rather than in radians: a value of 1 turn corresponds to 2π radians. We track the phase at the pulse level as units of turns--or, more accurately, as units of how long a turn takes--so, we expose the controls in the same way to you. This reduces floating point conversion error between what you submit and what runs.
### Single-qubit gates
The "textbook" way to think about single-qubit gates is as rotations along different axes on the Bloch sphere, but another way to think about them is as rotations along a *fixed* axis while rotating the Bloch sphere itself.
Because, in physical reality, the Bloch sphere itself *is* rotating--that is, the phase is advancing in time--changing the orientation of the Bloch sphere is virtually noiseless on hardware. As such, we manipulate qubit states in this "noiseless" phase space whenever possible.
#### GPi
The GPi gate can be considered a π or bit-flip rotation with an embedded phase. It always *rotates* π radians--hence the name--but can rotate on any longitudinal axis of the Bloch sphere. At a ϕ of 0 turns this is equivalent to an X gate, and at a ϕ of 0.25 turns (π/2 radians) it is equivalent to a Y gate, but it can also be mapped to any other azimuthal angle.
$GPI(\phi) = \begin{bmatrix} 0 & e^{-i\phi} \\ e^{i\phi} & 0 \end{bmatrix}$
A single-qubit gate is physically implemented as a Rabi oscillation made with a two-photon Raman transition, i.e. driving the qubits on resonance using a pair of lasers in a Raman configuration. For more details on the physical gate implementation, we recommend [this paper](https://www.nature.com/articles/s41467-019-13534-2) from the IonQ staff.
#### GPi2
The GPi2 gate could be considered an RX(π/2)--or RY(π/2)--rotation with an embedded phase. It always *rotates* π/2 radians but can rotate on any longitudinal axis of the Bloch sphere. At a ϕ of 0.5 turns (π radians) this is equivalent to RX(π/2), at a ϕ of 0.25 turns (π/2 radians) it is equivalent to RY(π/2), but it can also be mapped to any other azimuthal angle.
$GPI2(\phi)= \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & -ie^{-i\phi} \\ -ie^{i\phi} & 1 \end{bmatrix}$
Like the GPi gate, the GPi2 gate is physically implemented as a Rabi oscillation made with a two-photon Raman transition.
#### Virtual Z
We do not expose or implement a "true" Z gate (sometimes also called a P or Phase Gate), where we wait for the phase to advance in time, but a Virtual RZ can be performed by simply advancing or retarding the phase of the following operation in the circuit. This does not physically change the internal state of the trapped ion at the time of its implementation; it adjusts the phases of the future operations such that it is equivalent to an actual Z-rotation around the Bloch sphere. In effect, virtual RZ operations are implied by the phase inputs to later gates.
$Virtual Z(\theta)= \begin{bmatrix} e^{-i\theta/2} & 0 \\ 0 & e^{i\theta/2} \end{bmatrix}$
For example, to add RZ(θ)--an RZ with an arbitrary rotation θ--to a qubit where the subsequent operation is GPi(0.5), we can just add that rotation to the phases of the following gates:
> \--RZ(θ)--GPI(0.5)--GPI2(0) = --GPI(θ + 0.5)--GPI2(θ + 0)
### Entangling gates
For entangling gates, we offer different options for each QPU: the [Mølmer-Sørenson gate](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.82.1835) on Aria-class systems, and the ZZ gate on our Forte-class systems.
#### MS gates
Invented in 1999 by [several groups simultaneously](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.59.R2539), the Mølmer-Sørenson gate along with single-qubit gates constitutes a universal gate set. By irradiating any two ions in the chain with a predesigned set of pulses, we can couple the ions' internal states with the chain's normal modes of motion to create entanglement.
While it is *possible* to entangle many qubits simultaneously with the Mølmer-Sørenson interaction via global MS, or GMS, we only offer two-qubit MS gates at this time.
**Fully entangling MS**
The fully entangling MS gate is an XX gate--a simultaneous, entangling π/2 rotation on both qubits. Like our single-qubit gates, they nominally follow the X axis as they occur, but take two phase parameters that make e.g. YY or XY also possible. The first phase parameter ϕ0 refers to the first qubit's phase (measured in turns) as it acts on the second one, the second parameter ϕ1 refers to the second qubit's phase (measured in turns) as it acts on the first one.
If both are set to zero, there is no advancing phase between the two qubits because the transition is driven on both qubits simultaneously, in-phase. That is, the *relative* phase between the two qubits remains the same during the operation unless a phase offset is provided.
$MS(\phi_0, \phi_1) = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 & 0 & 0 & -ie^{-i(\phi_0 + \phi_1)} \\ 0 & 1 & -ie^{-i(\phi_0 - \phi_1)} & 0 \\ 0 & -ie^{i(\phi_0 - \phi_1)} & 1 & 0 \\ -ie^{i(\phi_0 + \phi_1)} & 0 & 0 & 1 \end{bmatrix}$
Note that while two distinct ϕ parameters are provided here (one for each qubit, effectively), they always act on the unitary together. This means that there are multiple ways to get to the same relative phase relationship between the two qubits for this gate; two parameters just makes the recommended approach of "Virtual Z" phase accounting on each qubit across the entire circuit a little neater.
**Partially entangling MS**
In addition to the fully entangling MS gate described above, we also support partially entangling MS gates, which are useful in some cases. To implement these gates, we add a third (optional) arbitrary angle θ:
$\text{MS}(\phi_0,\phi_1,\theta) = \begin{bmatrix} \cos \frac{\theta}{2} & 0 & 0 & -i e^{-i(\phi_0+\phi_1)} \sin \frac{\theta}{2} \\ 0 & \cos \frac{\theta}{2} & -i e^{-i(\phi_0-\phi_1)} \sin \frac{\theta}{2} & 0 \\ 0 & -i e^{i(\phi_0-\phi_1)} \sin \frac{\theta}{2} & \cos \frac{\theta}{2} & 0 \\ -i e^{i(\phi_0+\phi_1)} \sin \frac{\theta}{2} & 0 & 0 & \cos \frac{\theta}{2} \end{bmatrix}$
This parameter is also measured in turns, and can be any floating-point value between 0 (identity) and 0.25 (fully-entangling); in practice, the physical hardware is limited to around three decimal places of precision. Requesting an MS gate without this parameter will always run the fully entangling version.
Partially entangling MS gates yield more compact circuits: to produce the same effect as one arbitrary-angle MS gate would require up to two fully-entangling MS gates plus four single-qubit rotations. This offers a potential reduction in gate depth that can indirectly improve performance by removing unnecessary gates in certain circuits.
Additionally, small-angle MS gates are generally more performant: for smaller angles, these gates are implemented by lower-power laser pulses, and therefore experience lower light shift and other power-dependent errors. We do not currently have a detailed characterization of how much more performant these gates are on our current-generation systems, but in our (now-decommissioned) system described in [this paper](https://www.nature.com/articles/s41467-019-13534-2), we saw an improvement from \~97.5% to \~99.6% two qubit fidelity when comparing angles of π/2 and π/100, which is described [in more detail here](https://www.nature.com/articles/s41534-020-0259-3).
#### ZZ gates
Our Forte systems use the ZZ gate, which is another option for creating entanglement between two qubits. Unlike the Mølmer-Sørenson gate, the ZZ gate only requires a single parameter, θ, to set the phase of the entanglement.
$ZZ(\theta) = \exp\left(-i \frac{\theta}{2} Z{\otimes}Z\right) = \begin{pmatrix} e^{-i \frac{\theta}{2}} & 0 & 0 & 0 \\ 0 & e^{i \frac{\theta}{2}} & 0 & 0 \\ 0 & 0 & e^{i \frac{\theta}{2}} & 0 \\ 0 & 0 & 0 & e^{-i \frac{\theta}{2}} \end{pmatrix}$
***
## Converting to native gates
You can write a quantum circuit using native gates directly, but you can also convert an abstract-gate circuit into native gates. To do this automatically, we [support Qiskit's transpiler](/sdks/qiskit/native-gates-qiskit#transpiling-a-circuit-to-native-gates). Here, we'll walk through the general approach for manually translating circuits into native gates.
Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset throughout--you cannot mix and match native gates and abstract gates in the same circuit.
### General algorithm
To translate anything into native gates, the following general approach works well:
1. Decompose the gates used in the circuit so that each gate involves at most two qubits.
2. Convert all easy-to-convert gates into RX, RY, RZ, and CNOT gates.
3. Convert CNOT gates into XX gates using the decomposition described [here](https://arxiv.org/abs/1603.07678) and at the bottom of this section.
4. For hard-to-convert gates, first calculate the matrix representation of the unitary, then use either [KAK decomposition](https://arxiv.org/abs/quant-ph/0507171) or the method introduced in [this paper](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.77.066301) to implement the unitary using RX, RY, RZ and XX. Note that Cirq and Qiskit also have subroutines that can do this automatically, although potentially not optimally. See [cirq.linag.kak\_decomposition](https://quantumai.google/reference/python/cirq/kak_decomposition) and [qiskit.synthesis.TwoQubitBasisDecomposer](https://docs.quantum.ibm.com/api/qiskit/qiskit.synthesis.TwoQubitBasisDecomposer).
5. Write RX, RY, RZ and XX into GPi, GPi2 and MS gates as documented above (making sure to convert all angles and phases from radians to turns).
#### CNOT to XX decomposition
A CNOT gate can be expressed in XX, RX, and RY gates which can be directly converted to IonQ's native gates.
```python
----@----- ----| RY(π/2) |----| |----| RX(-π/2) |----| RY(-π/2) |-----
| = | XX(π/4) |
----X----- -------------------| |----| RX(-π/2) |---------------------
```
Many more advanced approaches, decompositions, and optimizations for trapped-ion native gates, including a parameterizable version of this decomposition can be found in [Basic circuit compilation techniques for an ion-trap quantum machine](https://arxiv.org/abs/1603.07678), where this decomposition is described.
***
## Additional resources
To learn how to use native gates via the IonQ API and supported SDKs:
* [Native gates in the IonQ API](/api-reference/v0.3/native-gates-api)
* [Native gates in Qiskit](/sdks/qiskit/native-gates-qiskit)
* [Native gates in Cirq](/sdks/cirq/native-gates-cirq)
* [Native gates in PennyLane](/sdks/pennylane/native-gates-pennylane)
For those interested in learning more about trapped-ion quantum computers as a physical apparatus, the implementation of gates, etc, we recommend [the PhD theses from our cofounder Chris Monroe's lab](https://iontrap.umd.edu/publications/theses/) as a starting point, especially those of Debnath, Egan, Figgat, Landsman, and Wright. The hardware they describe is in many ways the "first iteration" of IonQ's hardware, and much of the fundamental physics of the trapped-ion approach carries over.
# Hosted Hybrid Service
Run hybrid execution loops using functions managed by IonQ's Cloud.
The Hosted Hybrid service is currently in a limited preview and only available
to customers with an active contract. Please contact
[support@ionq.co](mailto:support@ionq.co) for more information.
IonQ's Hosted Hybrid Service allows users to run hybrid quantum-classical workloads without needing to write or host the classical optimization logic. This means that you can run a hybrid algorithm like a VQE, optimize the inputs with a method like SPSA, and do it all without having to write-or-run any of the code yourself.
This service introduces a two new things to our platform:
A ***Quantum Function*** is an abstraction that represents a composition of classical and quantum logic to perform simple computations. We currently expose two types of Quantum Functions:
* **Hamiltonian Energy**, which takes an ansatz and a hamiltonian to perform hamiltonian energy evaluation.
* **Quadratically Constrained Quadratic Program** that models the objective of a (constrained) quadratic program. This `QuantumFunction` can be used to solve constrained quadratic programs.
An ***Optimization*** looks for the optimal parameters for a Quantum Function using a supported optimization function. Once completed, the solution returned is the minimum energy value and the optimal parameters used to achieve it.
These new tools allow you take a problem that you want to solve, represent it in the form of a function, and run it through an optimization routine—without having to run any of the classical code yourself in a local notebook, or manage a remote execution environment.
***
## Setup
To run hybrid workloads with this tool, you'll need:
We recommend using a version manager such as [pyenv](https://github.com/pyenv/pyenv) or [asdf](https://asdf-vm.com/guide/introduction.html) to simplify management and upgrades.
```bash
pip install 'ionq[all]'
```
We'll start by setting up our our `Client` which will allow us to connect to IonQ's platform, then select a backend to use with it.
```python
# Initialize backend
from ionq.client import Client
from ionq import Backend
# Initialize a client for connecting to the IonQ API
client = Client()
# Note: Assuming it's stored as $IONQ_API_KEY in your environment,
# the SDK (and any other quantum SDK) will find it automatically.
# However, if you wanted to specify it directly, you could with:
# client = Client(api_key="aaa-bbb-ccc")
# Select a backend to use. We'll stick with the simulator for now, but you can
backend = Backend(name="simulator", client=client)
```
***
## Creating a demo workload
In practice, you'd be using our hamiltonian energy evaluations to evaluate *your own* hamiltonians and ansatze, but for this guide we'll build a couple of functions for creating random inputs -- but if you can provide your own, more the better.
So first, we'll build an example hamiltonian:
```python
import random
import math
from itertools import product
from qiskit.quantum_info import SparsePauliOp
# Create our example hamiltonian
num_qubits = 2 # or more, but it scales rapidly!
pauli_list = [
(ps, random.uniform(-1, 1))
for ps in [
"".join(p) for p in list(product(["I", "X", "Y", "Z"], repeat=num_qubits))
]
]
# Create and display an example hamiltonian
hamiltonian = SparsePauliOp.from_list(pauli_list)
```
Which, if we `print`ed it, would look something like:
> ```python
> print(hamiltonian.to_matrix())
>
> [[-0.66819263+0.j -1.36722223-1.22394246j 1.61219673+1.45550222j
> 0.1523982 -1.25363417j]
> [-1.36722223+1.22394246j 1.40731579+0.j -1.42421166+0.51092863j
> -0.16465104-0.43298482j]
> [ 1.61219673-1.45550222j -1.42421166-0.51092863j 0.86269394+0.j
> -0.388201 -0.74335051j]
> [ 0.1523982 +1.25363417j -0.16465104+0.43298482j -0.388201 +0.74335051j
> 2.28670504+0.j ]]
> ```
Now we'll do the same for an example ansatz and some initial parameters:
```python
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
params = [Parameter(f"θ{i}") for i in range(2 * num_qubits)]
ansatz = QuantumCircuit(num_qubits)
# Add a layer of single-qubit parameterized rotations (Ry and Rz)
for i in range(num_qubits):
ansatz.ry(params[i], i)
ansatz.rz(params[i + num_qubits], i)
ansatz.barrier()
# Add CNOT gates to entangle the qubits
for i in range(num_qubits - 1):
ansatz.cx(i, i + 1)
# Set up some initial parameters
initial_params = {
params[i]: random.uniform(0, 2 * math.pi) for i in range(2 * num_qubits)
}
```
Which will produce an ansatz that looks something like:
> ```python
> ansatz.draw(output="mpl")
> ```
>
> ![Image](https://mintlify.s3-us-west-1.amazonaws.com/ionq/guides/_media/hosted_hybrid-example_ansatz.png)
***
## Example 1: Running a simple circuit
As a simple demonstration of functionality, let's take our backend and submit a basic circuit job to it using our example ansatz. This is *not* a hybrid workflow, but a normal circuit job.
Note: We're using `ionq.ionq_qiskit`, which is a helper library we are providing for translating Qiskit circuits into IonQ-native QIS.
```python
from ionq.utils import ionq_qiskit
# Create a circuit using a helper that translates Qiskit circuits to QIS
circuit = ionq_qiskit.to_circuit(
[ansatz.assign_parameters(initial_params, inplace=False)]
)
# And submit it to our backend
circuit_job = backend.run(
circuit,
name="Example 1: Circuit Workload"
)
```
And plotting this circuit we'll see something like:
> ```python
> circuit_results = circuit_job.results()
> for results in circuit_results:
> results.plot_results()
> ```
>
> ![Circuit Workload Histogram](https://mintlify.s3-us-west-1.amazonaws.com/ionq/guides/_media/hosted_hybrid-circuit_workload_histogram.png)
***
## Example 2: Running a Quantum Function
Now we're build on this by submitting a *`QuantumFunction`* instead of just a simple circuit.
A quantum function is a workload that has some predefined logic built in to it. In this case, we'll pass it an ansatz and a hamiltonian, and when we send it to the backend along with a set of parameters, it will submit circuits and do an Hamiltonian Energy evaluation.
```python
from ionq.jobs import HamiltonianEnergy
from ionq.utils import ionq_qiskit
# Build a QuantumFunction
qfunc = HamiltonianEnergy(
ansatz=ionq_qiskit.to_ansatz(ansatz),
hamiltonian=ionq_qiskit.to_hamiltonian(hamiltonian),
)
# Submit it to the backend
qfunc_job = backend.run(
qfunc,
params=list(initial_params.values()),
name="Example 2: Quantum Function Workload",
)
```
***
## Example 3: Quadratically Constrained Quadratic Program Objective
We can also prepare the model for a constrained quadratic program, by creating a Quantum Function that takes an ansatz, a QUBO matrix, and a list of constraints. This can then be used to solve constrained quadratic programs with classical optimization methods. Let's first model it, with some simple linear constraints and confirm it runs with a random set of parameters.
```python
import numpy as np
from ionq.problems.quadratic import LinearConstraint
from ionq.problems import QCQPObjective
from ionq.utils import ionq_qiskit
Q = np.array([[4, -6], [-6, 10]])
constraints = [
LinearConstraint(
coeffs=[1, 2],
rhs=5,
),
LinearConstraint(
coeffs=[3, 4],
rhs=6,
)
]
print(f"{Q=}", "\n\n", f"{constraints=}")
# Build our QuantumFunction
qfunc = QCQPObjective(
ansatz=ionq_qiskit.to_ansatz(ansatz),
qp_objective=Q,
linear_constraints=constraints,
penalty=random.uniform(-1, 1),
)
# Submit it to the backend
qfunc_job = backend.run(
qfunc,
params=list(initial_params.values()),
name="Example 3: Quantum Function (with constraints and a penalty)",
)
```
***
## Example 4: Optimizations
We can also run a (IonQ hosted!) classical loop to optimize our parameters. Here we'll take the same quantum function we ran in Example 3, but we'll add a 5-iteration optimization using SPSA.
It doesn't add that much complexity here, only requiring some simple additions:
1. What `method` to use for optimization
2. The maximum desired number of iterations
3. The learning rate, and perturbation for each iteration
These values will define how each iteration in the series will change based on the results of the previous job.
```python
from ionq.jobs import Optimization
from ionq.jobs import OptimizationMethod
opt = Optimization(
quantum_function=qfunc,
method=OptimizationMethod.SPSA,
initial_params=list(initial_params.values()),
log_interval=1,
options={"maxiter": 5, "learning_rate": 0.1, "perturbation": 0.5},
maxiter=5,
)
# Run the optimization job
opt_job = backend.run(
opt,
name="Example 4: Optimization"
)
```
As before, we've provided some useful helpers for visualization. running `plot_results()` gives us:
> ```python
> opt_results = opt_job.results()
> opt_results.plot_results()
> ```
>
> ![A graph of the results of an optimization job.](https://mintlify.s3-us-west-1.amazonaws.com/ionq/guides/_media/hosted_hybrid-opt_job_results.png)
And retrieving the "results" of this job will identify the `minimum_value` and `optimal_parameters` for the problem:
> ```python
> "solution": {
> "minimum_value": -0.6128005853629444,
> "optimal_parameters": [
> 4.915170460439439,
> 3.228145593574783,
> 5.550801246532398,
> -0.012326729967622713
> ]
> }
> ```
***
## Learn more
This service is still in a private alpha at this time, but reach out to [sales@ionq.co](mailto:sales@ionq.co) for more information, or contact your account manager.
# Managing API keys
Learn how to create and manage your IonQ API keys for secure access through SDKs and APIs.
An **API key** is similar to a password—it's a string of text used to authenticate (identify yourself) with to our systems and allow the system to authorize that you have access to the action you're attempting to take. When using our APIs
IonQ uses API keys to manage access to our systems. Users must provide a valid key when using APIs both directly or through an SDK.
## Creating API keys
API keys are created in the [IonQ Quantum Cloud](https://cloud.ionq.com/settings/keys) application under the API Keys page found in the top menu (pictured above.) On that page, you can also see a list of currently active keys, see when they were last used, and revoke (delete) any that are no longer needed.
Manage your keys from the IonQ Quantum Cloud application
***
## Storing Keys
The *value* of the key is only visible at the time of creation, so we highly recommend storing it securely. One approach is to use a password manager (e.g. [LastPass](https://www.lastpass.com/), [1Password](https://1password.com/), or similar) which can be useful if you find yourself moving from machine to machine often, as these tools can sync between devices.
You can also store your key locally as an *environment variable*, making it easy to access from software you're running locally.
### On Windows
Press `Windows + R` to open the Run prompt, type in `sysdm.cpl` and click `OK`.
Open the `Advanced` tab and click on the `Environment Variables` button in the System Properties window.
Click on the `New...` button to open the `New User Variable` box, where you can add your variable.
Give your variable a suitable and paste in the value provided by the IonQ application.
Once added, variables are accessible from the Windows Command Line by referencing `%IONQ_API_KEY%`. In your Python code, you can use `os.getenv('IONQ_API_KEY')` function to retrieve the stored value.
Alternately, variables can be set from the command line with the `setx` command, like so:
```bash
setx [IONQ_API_KEY] ""
```
Note: You'll need to restart the Command Prompt for the changes to take effect, as it reads the local environment variables into memory when opened.
### On Mac or Linux
In both Mac and Linux environments, environment variables are added using the `export` command in the command line, like so:
```bash
export IONQ_API_KEY=""
```
To add this variable to your environment permanently, add it to the "profile" configuration file of your shell. If you're on a (modern) Mac, that file will be called `.zshrc` (for zsh), while most Linux distributions use `.bashrc` (for bash). Once added, all new shell sessions (i.e. terminal windows) will have access to these variables.
You'll find your profile in your user directory, which can be referenced with the `~` keyword. For example, to open a `zsh` profile in the editor nano, you could run `nano ~/.zshrc`.
Once added, variables are accessible from the command line by referencing `$IONQ_API_KEY`. In your Python code, you can use `os.getenv('IONQ_API_KEY')` function to retrieve the stored value.
***
## Best Practices
* Keys are a type of password. Keep them as safe and secure them as you would any other password.
* When presenting on a video call, be aware of what's in your code. If you're hardcoding your key in to a script, it will be visible. Use an environment variable instead.
* Keys are still active even if you're no longer using them. If a key is no longer needed, delete it.
* Keys are free! If you need to delete one and replace it with a new one because you're concerned that it was compromised, go for it.
***
## Need help?
Having trouble? Seeing something you don't expect? Have other questions? Reach out to [support@ionq.co](mailto:support@ionq.co) or submit a ticket on support.ionq.com.
# QPU Submission Checklist
Things to do before submitting to IonQ's hardware systems.
Once you've gotten access to IonQ's systems and set up a quantum circuit using the IonQ API, Qiskit, or any other method, you can submit a job to one of our QPUs. However, before you start running on quantum hardware, we have a few recommendations to ensure that your circuits run successfully.
The following are not *required* to use our QPUs, but we recommend taking these steps to ensure the best experience (and that you're using your budget effectively!)
#### Run your job on the cloud simulator
The ideal simulator is a great starting point for making sure that your code runs successfully, you can submit jobs to the IonQ Quantum Cloud, and your circuits compile without errors.
#### Run your job on the cloud simulator with noise model
Once you've run a job on the ideal simulator, try running with the noisy simulator, using the noise model based on your target QPU. While our noise models don't capture all sources of noise for the QPUs, they can give you a general idea of how noise will affect your results. This can also help you determine how many shots to use. You can learn more about noise models and submitting noisy simulation jobs [here](/guides/simulation-with-noise-models).
#### Check that you have access to the QPU
On the ["Backends" tab](https://cloud.ionq.com/backends) of the IonQ Cloud Console, you can see our current QPUs. If a QPU is marked with "Out of Plan", you won't be able to submit to it. You can request access [with this form](https://ionq.com/get-access?intent=direct-access) or ask your IonQ point of contact.
#### Check the QPU status
The ["Backends" tab](https://cloud.ionq.com/backends) of the IonQ Cloud Console and the [IonQ Status page](https://status.ionq.co/) provide information about system availability and maintenance. If you submit a job to a system that is not currently available, it will still go into the queue and will show as "ready" on the ["My Jobs" tab](https://cloud.ionq.com/jobs), but jobs in the queue won't run until the system is available again.
#### Check the queue status
The ["Backends" tab](https://cloud.ionq.com/backends) of the IonQ Cloud Console shows the average time in queue for jobs that are currently waiting, and the [IonQ Status page](https://status.ionq.co/) shows this average over time. This information doesn't tell you exactly when your job will run, but it can give you a general idea of how crowded the systems are when you submit.
#### Check your project budget
On the ["Projects" tab](https://cloud.ionq.com/projects) of the IonQ Cloud Console, you can see your spend so far and the total budget for each of your projects. If your spend is approaching your total available budget, you may not be able to run a job. Your organization owner can adjust project budgets.
#### Double-check your API key and project
Each API key is tied to a specific project. If you have multiple projects, we suggest verifying that your code is using the API key for the right project. You can view the jobs submitted to a project by clicking on it from the ["Projects" tab](https://cloud.ionq.com/projects). This list includes simulator jobs, so if you've tested your code on the simulator and those jobs are showing up in the intended project, switching to a QPU backend with the same API key will keep those jobs in the same project.
#### Make a reservation
If you're running a hybrid or variational job, you may want to make a reservation to ensure that multiple circuits submitted (i.e., multiple iterations of your variational optimization) will run consecutively rather than via the queue. You can request a reservation by emailing [support@ionq.co](mailto:support@ionq.co) with information about the target system, reservation length, and scheduling preferences.
***
Once you've confirmed that you're ready to run on the QPU, you should be good to go! Please reach out to [support@ionq.co](mailto:support@ionq.co) or submit a ticket on [support.ionq.com](https://support.ionq.com) if you run into any problems or you have any additional questions.
# Simulation with Noise Models
Getting started with hardware noise model simulation
Simulating circuits is a critical part of every quantum developer's toolchain--whether you're exploring new ideas or just making sure that all of your code is ready to run on a remote QPU. Simulation provides quantum developers efficient, fast feedback, making iteration and testing much faster.
**"Ideal" simulators provide *perfect outcomes*, but real quantum hardware is noisy**. Understanding these noise characteristics when designing an application helps you set expectations for your results and develop strategies to address noise, like error mitigation, noise-adaptive compilation, or noise-resilient circuit design.
IonQ Quantum Cloud supports both `ideal` and `noisy` simulations, allowing you to choose to see both the complete range of outcomes in the ideal case, or an example of how a circuit would run on physical hardware with a limited number of shots.
Noise models are provided for IonQ's currently available QPUs (Aria 1, Aria 2, and Forte 1), as well as our retired Harmony QPU. Like our ideal cloud-based simulators, they are free for all users with direct IonQ access, including through Google Cloud Marketplace or simulator-only accounts. Noise model simulations can be submitted through our API, Qiskit, and Cirq.
Noise model simulation uses an approximation of system performance, and is meant to help users understand the impact of noise on quantum algorithms. IonQ offers to specific guarantees of accuracy, and these models should not be used to predict if a specific IonQ system will or won't be able to successfully execute a specific circuit.
***
## Our noise model
We perform a detailed gate-level characterization of the noise sources on our systems, and then approximate the noise model with a depolarization error channel where the noise strength is determined from the gate-level characterization of the noises. The Kraus operators for one-qubit depolarization error channels are given by:
$K_0 = \sqrt{1 - \frac{3r_{1q}}{4}}\sigma_0$
$K_i = \sqrt{\frac{r_{1q}}{4}}\sigma_i$, where $\sigma_{k\{k=1,2,3\}}$ are Pauli matrices and $\sigma_0$ is an identity.
Similarly, two-qubit Kraus operators are:
$K_{00} = \sqrt{1 - \frac{15r_{2q}}{16}}\sigma_0 \otimes \sigma_0$
$K_{ij} = \sqrt{\frac{r_{2q}}{16}}\sigma_i \otimes \sigma_j$, where $\sigma_{k\{k=1,2,3\}}$ are Pauli matrices and $\sigma_0$ is an identity.
The one- and two-qubit depolarization channels are applied after each corresponding ideal one- and two-qubit gate in the circuit. For our currently available Aria and Forte systems, the error rate parameters used for one- and two-qubit gates in this model are:
| System | $r_{1q}$ | $r_{2q}$ |
| ------- | ----------------------- | ---------------------- |
| Aria 1 | `0.0005` | `0.0133` |
| Aria 2 | `0.0006573333333333332` | `0.01856` |
| Forte 1 | `0.0002666666666666667` | `0.004949333333333333` |
Harmony (retired in September 2024) has a noise model available in our cloud simulator, but it uses a different formula and parameters than those described above.
Since this model is a simplified approximation, these static parameters should not be directly compared to experimentally obtained error rates. The latest characterization data for our systems is available [in the IonQ Cloud Console](https://cloud.ionq.com/backends) and previous characterization results are also available [via the IonQ API](/api-reference/v0.3/characterizations).
This model aggregates various sources of noise into one error channel, while in reality these types of noise may affect different circuits in different ways. This means that noisy simulation has a limited ability to predict application-level performance on real QPUs.
We continually improve our understanding of noise sources in our systems and develop new strategies for error suppression and mitigation, which may be reflected in changes or updates to our noise models over time.
***
## Example results
Here's an example of ideal simulation, noisy simulation, and QPU execution for a nine-qubit GHZ state.
This circuit creates the maximally-entangled state that is the equal superposition of $\ket{000000000}$ and $\ket{111111111}$.
```python
q_0 ----| H |----@--------------------------------------------| M |
|
q_1 -------------X----@---------------------------------------| M |
|
q_2-------------------X----@----------------------------------| M |
|
q_3 -----------------------X----@-----------------------------| M |
|
q_4 ----------------------------X----@------------------------| M |
|
q_5 ---------------------------------X----@-------------------| M |
|
q_6 --------------------------------------X----@--------------| M |
|
q_7 -------------------------------------------X----@---------| M |
|
q_8 ------------------------------------------------X----@----| M |
|
q_9 -----------------------------------------------------X----| M |
```
We ran this circuit on the ideal simulator, noisy simulator with `harmony` noise model and 1000 shots, and our Harmony QPU (which has since been retired) with 1000 shots. Here's the output probabilities graphed together for comparison:
![Results for ideal simulation, noise model simulation, and QPU](https://mintlify.s3-us-west-1.amazonaws.com/ionq/guides/_media/noisysim.png)
For the ideal simulation (in gray), we obtained exactly 50% probability for each of the two target states and zero probability in all other states. For the noisy simulation (in blue) and QPU (in orange), we recorded less than 50% probability in those states and nonzero probability in several other states.
Here's a version that's zoomed in on the y-axis, so we can see the noise a little better:
![Zoomed-in results for ideal simulation, noise model simulation, and QPU](https://mintlify.s3-us-west-1.amazonaws.com/ionq/guides/_media/noisysim-zoom.png)
As you can see, the IonQ Harmony noise model simulation not only has more noise than the ideal simulation, that noise has a pattern and volume that roughly mimics the noise introduced by the real QPU. That said, please note that it is only *broadly* similar — the IonQ Harmony simulation and hardware runs are not similar in a statistical sense, only a general one.
***
## Using the noisy simulator
In general, submitting noisy simulation jobs is almost the same process as submitting ideal simulation jobs, with one extra keyword to specify the noise model (which can be `aria-1`, `aria-2`, `forte-1`, or `harmony`).
You can also specify `"ideal"` whenever you are setting the noise model. This will use the ideal simulator, which is also the default if no noise model is specified.
For our smaller systems, each noise model simulation can use as many qubits as its corresponding QPU has (25 qubits for Aria 1 or Aria 2, 11 qubits for Harmony). For our Forte 1 system (which has 36 qubits) as well as our ideal simulator, each simulation can currently use up to 29 qubits. Simulation capabilities for larger circuits will be available in the future.
Unlike ideal simulation, which runs a single calculation to generate probabilities, noise model simulation is shot-aware: it will run one simulation for each shot you request. This means that the number of counts in your output histogram will match the number of shots you submitted. Another implication of this: the more shots you use, the longer your simulation will take to finish - though this generally isn't very noticeable unless you are simulating circuits with many qubits and a very large number of shots.
The noise model takes an optional parameter called `seed`. This allows you to specify a specific seed for the pseudo-random noise generation and shot sampling that occurs during noise model simulation, allowing for reproducible “noisy” results. If you don't provide a seed, one will be chosen at random and then provided as part of the simulation output (viewable in an API job result or the job detail page in the IonQ Cloud Console). The seed can be any integer between 1 and $2^31$.
Jobs submitted to a noisy simulator follow the same compilation and optimization process as jobs submitted to a QPU. If the circuit is written in abstract gates, it will be compiled to IonQ's native gates and optimized before simulation. If the circuit is written in our [native gates](/guides/getting-started-with-native-gates), it will not be optimized or modified before simulation.
Noisy simulation currently doesn't include [debiasing](https://ionq.com/resources/debiasing-and-sharpening), our default error mitigation strategy. Future versions of our simulator may implement this feature.
### API example
When [submitting a job via the API](/guides/direct-api-submission), use `"target": "simulator"` and add `"noise": {"model": "aria-1"}` (or specify a different QPU noise model) to the job body.
To specify a random seed, use `"noise": {"model": "aria-1", "seed": 481516}`.
```
{
"name": "Hello many worlds!",
"shots": 1000,
"target": "simulator",
"noise": {
"model": "aria-1",
},
"input": {
"qubits": 2,
"circuit": [
{
"gate": "h",
"target": 0
},
{
"gate": "cnot",
"control": 0,
"target": 1
}
]
}
}
```
### Qiskit examples
When [using an IonQ backend with Qiskit](/sdks/qiskit/index), the noise model can be specified either when setting up a backend or when submitting a job.
#### For a backend
To set the noise model for a simulator backend, which will be the default noise model for all jobs run on that backend, use `backend.set_options(noise_model="aria-1")`.
To also specify the simulation's random seed, use `backend.set_options(noise_model="aria-1", sampler_seed=8151623)`.
```python
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider
provider = IonQProvider()
noisy_backend = provider.get_backend("ionq_simulator")
noisy_backend.set_options(noise_model="aria-1")
# Create a basic Bell State circuit
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Run the circuit on the IonQ simulator with aria-1 noise model
job = noisy_backend.run(qc, shots=1000)
# Print the counts
print(job.get_counts())
```
#### For a job
To set the noise model for an individual job run on a simulator backend, use the `noise_model` keyword argument when calling `backend.run()`.
```python
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider
provider = IonQProvider()
simulator_backend = provider.get_backend("ionq_simulator")
# Create a basic Bell State circuit
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Run the circuit on the IonQ simulator with aria-1 noise model
job = simulator_backend.run(qc, shots=1000, noise_model="aria-1")
# Print the counts
print(job.get_counts())
```
### Cirq example
When using an IonQ service with Cirq, use `extra_query_params={"noise": {"model": "aria-1"}}` (or specify another noise model) when running a job. You can also use `extra_query_params` to add other parameters, using the same format as an API job.
To specify the simulation's random seed, use `extra_query_params={"noise": {"model": "aria-1", "seed": 15162342}}`.
```python
import cirq
import cirq_ionq
service = cirq_ionq.Service()
# Create a basic Bell state circuit
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
cirq.H(q0),
cirq.CNOT(q0, q1),
cirq.measure(q0, q1, key='x')
)
# Run the circuit on the IonQ simulator with aria-1 noise model
job = service.run(
circuit,
repetitions=1000,
target="simulator",
extra_query_params={"noise": {"model": "aria-1"}}
)
# Print the result
print(job.histogram(key='x'))
```
***
## Noise model do's and don't's
**Do:**
* Run noisy simulations before submitting jobs to a QPU. This is a great way to test your code and workflows!
* Explore the directional effect of noise while varying circuit depth, complexity, and number of shots, as well as testing noise models for different QPUs. For example, comparing an ideal and noisy simulation can help you isolate and understand the effects of noise from statistical sampling vs errors from running the circuit.
* Reconsider your approach if you get completely unusable results from a noisy simulation. If your circuit is clearly well beyond the limits of the noisy simulator performance, it's unlikely to perform better on today's QPUs. You may need to consider shallower circuits, additional optimization, or other approaches.
**Don't:**
* Expect QPU results to quantitatively match noisy simulation results. These noise models are *simplified approximations* of what would happen on actual hardware, provided for developer convenience and efficiency, and should not be considered a replacement for running circuits on real hardware.
* Use noise model results to precisely predict what a given IonQ system will or won't be able to execute. If you need help in understanding if your algorithm will successfully run on a specific generation of IonQ hardware, please reach out to [support@ionq.com](mailto:support@ionq.com) for guidance.
* Rely on noise model results when investigating specific error channels or benchmarking methods. For these specialized circuits that are sensitive to particular sources of noise, this general model likely won't work well.
That's all you need to know to begin simulating jobs using hardware noise models on the IonQ Quantum Cloud. Contact us at [support@ionq.com](mailto:support@ionq.com) or [join our Slack community](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w) if you have questions about our noise models, feedback on our simulation tools, or ideas for additional noisy simulation capabilities you'd like to see in the future!
# IonQ Documentation
Welcome to IonQ's developer documentation! Get started, learn advanced techniques, and browse through our reference materials.
Check out our guides on how use IonQ's Quantum Cloud platform through Qiskit, Cirq, and TensorFlow.
Learn how to use different tools and techniques on the IonQ platform.
Explore our available API endpoints, view detailed specifications, and run test queries.
Learn about the IonQ Quantum Cloud Console and all of the features find in it.
Looking to use IonQ in conjunction with a cloud vendor? Check out our integrations with [Amazon Braket](/partners/amazon).
Explore our quantum computing resources, curated to help you take your skills to the next level.
Browse example notebooks for different SDKs and advanced examples for implementing complex algorithms and workflows.
***
# Quickstart
Ready to submit some quantum circuits? Here's everything you need to get started:
With a free IonQ Quantum Cloud account you can create and manage API keys, track and retrieve job results, invite and manage organization users and allocate and manage quotas. You'll also get access to IonQ's ideal state simulators—supporting up to 29 qubits—and IonQ Aria noise model simulators.
[**» Sign up for free**](https://cloud.ionq.com)
Once you have an account, you'll be able to create an API key that can be used with SDKs or directly with our API to submit quantum programs, check on their job status, and retrieve the results once they've completed.
[**» Learn how to create keys**](/guides/managing-api-keys)
If you are new to quantum computing, we recommend you start by submitting your first job via Qiskit—it’s easy to use, has a strong user community, and supports the majority of functionality that IonQ’s systems offer. We've written a guide that takes you step by step on installing it and submitting your first quantum circuit to our simulator.
[**» Learn how to use Qiskit**](/guides/sdks/qiskit)
Running your first circuit is only the first step. Explore our other learning resources to learn about the state of the art in quantum computing, dive in to understand complex quantum techniques, and read case studies to see how other industry leaders are leveraging these new tools.
[**» Explore our Resource Center**](https://ionq.com/resources/)
If you have any questions, want to share your feedback, or otherwise get in touch with us, the best way to do so is in our IonQ Community Slack. Join today!
[**» Join our IonQ Community Slack**](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w)
***
# Get in touch
Join our community Slack to ask questions, give feedback, and connect directly with us.
Not a fan of Slack? Send us your thoughts via email at [support@ionq.co](mailto:support@ionq.co)
Having trouble, or not finding the information you need? Reach out to [support@ionq.co](mailto:support@ionq.co) or submit a ticket on support.ionq.com.
# Amazon Braket
Learn how to connect to IonQ products and services through AWS Braket
![aws-braket-console](https://mintlify.s3-us-west-1.amazonaws.com/ionq/media/content/aws-braket-console.png)
Amazon Braket is a managed AWS service that allows AWS customers to buy time on quantum computers from a variety of vendors such as IonQ. This is particularly useful for customers who are invested in the AWS Marketplace ecosystem, and may find it advantageous to purchase IonQ credit directly through that channel.
***
## Get started
Simply log to AWS and navigate to the [Braket console](https://console.aws.amazon.com/braket/). From there you'll be able to view devices, create and view notebook instances, run hybrid jobs from a file, and browse their algorithm library.
Additionally, through Amazon Braket Direct you can also set up device reservations for customers who need periods of exclusive access time.
***
## Learn more
* Check out the [Braket SDK for Python](https://github.com/aws/amazon-braket-sdk-python)
* Browse their [example notebooks on GitHub](https://github.com/amazon-braket/amazon-braket-examples)
* See [IonQ's page in the Braket Docs](https://docs.aws.amazon.com/braket/latest/developerguide/braket-qpu-partner-ionq.html)
* For Qiskit users, check out the [Qiskit provider for Braket](https://aws.amazon.com/blogs/quantum-computing/introducing-the-qiskit-provider-for-amazon-braket/)
* View the [Braket Training Plan](https://explore.skillbuilder.aws/learn/public/learning_plan/view/1986/amazon-braket-badge-knowledge-badge-readiness-path) in AWS Skillbuilder
# Azure Quantum
aaa
# Google Cloud
aaa
# Getting started with Cirq
Learn how to use the Cirq SDK to submit quantum circuits to IonQ's simulators and quantum computers.
## What is Cirq?
[Cirq](https://quantumai.google/cirq) is an open source Python framework for writing, modifying, and running programs for quantum computers. 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](https://quantumai.google/cirq/tutorials/basics) gives a great introduction to the basics of Cirq and its philosophy.
[The `cirq-ionq` module](https://github.com/quantumlib/Cirq/tree/main/cirq-ionq) provides support for IonQ's trapped-ion systems. This means that you can write quantum circuits and run them on IonQ's simulators and trapped-ion quantum computers, all from within the Cirq framework.
## Before you begin
You'll need an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and you'll need to create an API key. We also have a guide about [setting up and managing your API keys](/guides/managing-api-keys) if you need some help.
You'll also need Python 3.11 or higher running locally on your machine.
Run `python --version` from your command line if you aren't sure which version
you have running.
***
## Set up Cirq
For a simple install, you can install `cirq-ionq` from the Python Package Index (PyPI) using `pip`:
```bash
pip install cirq-ionq
```
This will also install the core functionality of `cirq`. For more details and advanced features, we recommend following the complete [Cirq installation guide](https://quantumai.google/cirq/install).
**Note:** We encourage doing this inside an environment management system like
[virtualenv](https://virtualenv.pypa.io/en/latest/) or
[conda](https://docs.conda.io/en/latest/) so as to avoid [this
fate](https://xkcd.com/1987/), but do what makes the most sense for you.
***
## Set up the IonQ Service
We'll walk through each step of the code examples for different job submissions here, but full, copy-paste-friendly code examples are provided [below](#full-code-examples).
Open a file up in whatever IDE or notebook you prefer, and add the following:
```python
import cirq_ionq
service = cirq_ionq.Service()
```
Cirq will automatically look for your API key in the environment variable `IONQ_API_KEY` when setting up the `cirq_ionq.Service()`. If you need to pass in your API key directly, you can instead use:
```python
service = cirq_ionq.Service(api_key="YOUR API KEY HERE")
```
## Build a circuit
Next, construct a circuit. Each qubit is represented by a `cirq.LineQubit` with a unique integer identifier. While we use `LineQubit` objects to represent the chain of trapped-ion qubits in an IonQ system, the qubit identifier does not indicate the position of a particular qubit in the chain. Also note that all IonQ systems have all-to-all connectivity, so two-qubit gates can be performed directly on any pair of qubits, whether or not their `LineQubit` identifiers are adjacent.
```python
import cirq
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
cirq.H(q0),
cirq.CNOT(q0, q1),
cirq.measure(q0, q1, key='x')
)
print(circuit)
```
Here's a basic Bell state circuit:
```
0: ---H---@---M('x')---
| |
1: -------X---M--------
```
## Submit a circuit to the ideal simulator
After we've built a quantum circuit, we can submit it to IonQ's ideal simulator. Here, we'll use `repetitions` to request 1000 shots and `extra_query_params` to give the circuit a name that will show up in the [IonQ Cloud Console](https://cloud.ionq.com/jobs).
```python
result = service.run(
circuit=circuit,
target="simulator",
repetitions=1000,
extra_query_params={"name": "Hello simulator, Cirq"}
)
print(result.histogram(key='x'))
```
This returns:
```python
Counter({0: 502, 3: 498})
```
The `cirq.Result` object shows 502 counts for the 0 state (`00`) and 498 for the 3 state (`11`).
## Submit a circuit to the noisy simulator
This process is almost the same as the ideal simulator example above, except when calling `service.run()`, we'll use the `extra_query_params` to add `{"noise": {"model": "aria-1"}}` for the Aria 1 noise model.
The available noise models are `harmony` (legacy), `aria-1`, `aria-2`, and `forte-1`. You can read more about these noise models [here](/guides/simulation-with-noise-models).
```python
result = service.run(
circuit=circuit,
target="simulator",
repetitions=1000,
extra_query_params={"noise": {"model": "aria-1"}}
)
```
Or, to supply both a circuit name and a noise model:
```python
result = service.run(
circuit=circuit,
target="simulator",
repetitions=1000,
extra_query_params={
"noise": {"model": "aria-1"}
"name": "Hello noisy simulator, Cirq"
}
)
```
## Submit a circuit to a QPU
For the QPU, we'll use `service.create_job()` instead of `service.run()`. This will submit the job, but won't wait for it to finish, so our code won't be blocked waiting for the result to return. In most cases, a QPU job will wait in the queue for some time before running.
The available QPU targets may include `qpu.aria-1`, `qpu.aria-2`, and `qpu.forte-1`. You can view your access to these systems on the ["Backends" tab](https://cloud.ionq.com/backends) of the IonQ Cloud Console.
Before submitting to any QPU, we recommend testing your code on a simulator (including with noise model) and following the other steps on [this list](/guides/qpu-submission-checklist) to confirm your access and the QPU availability.
```python
job = service.create_job(
circuit=circuit,
target="qpu.aria-1",
repetitions=1000,
extra_query_params={"name": "Hello QPU, Cirq"}
)
```
You can check the status of your job:
```python
print(job.status())
```
If the job is waiting in the queue, this will print `'ready'`. If the job is finished, this will print `'completed'`.
You can also print and record the job's unique ID, which can be used to retrieve the job (including its status and results) at a later time.
```python
print(job.job_id())
```
Once the job is completed, you can retrieve its results:
```python
result = job.results().to_cirq_result()
print(result.histogram(key='x'))
```
You can cancel a job while it's waiting in the queue:
```python
job.cancel()
```
## Retrieve a job
You can retrieve results for a previously run job using its job ID. You can save the job ID after submitting a job (as in the QPU example above) or copy it from the "ID" column in the ["My Jobs" tab on the IonQ Cloud Console](https://cloud.ionq.com/jobs).
```python
job_id = "..."
job = service.get_job(job_id)
result = job.results().to_cirq_result()
print(result.histogram(key='x'))
```
## Supported gates
Note that some gates supported by Cirq aren't accepted by IonQ backends. The [supported gates](https://quantumai.google/cirq/hardware/ionq/circuits#api_gates) include:
* `cirq.XPowGate`, `cirq.YPowGate`, `cirq.ZPowGate`
* This includes `cirq.rx`, `cirq.ry`, and `cirq.rz` and Pauli gates `cirq.X`, `cirq.Y`, and `cirq.Z`.
* `cirq.H`
* `cirq.XXPowGate`, `cirq.YYPowGate`, `cirq.ZZPowGate`
* `cirq.CNOT`, `cirq.SWAP`
* `cirq.MeasurementGate`: usually via `cirq.measure`
Other [gates available in Cirq](https://quantumai.google/cirq/build/gates), such as the Toffoli gate, are not directly supported by IonQ systems. However, you can decompose a circuit to IonQ-supported gates.
Construct a circuit containing an unsupported gate:
```python
q0, q1, q2 = cirq.LineQubit.range(3)
circuit = cirq.Circuit(
cirq.TOFFOLI(q0, q1, q2),
cirq.measure(q0, q1, q2, key='x')
)
print(circuit)
```
This circuit looks like:
```python
0: ---H---@---@---M('x')---
| | |
1: -------X---@---M--------
| |
2: -----------X---M--------
```
Get the IonQ target gateset and decompose the unsupported gates in the circuit:
```python
target_gateset = cirq_ionq.ionq_gateset.IonQTargetGateset()
circuit2 = cirq.optimize_for_target_gateset(
circuit,
gateset=target_gateset
)
print(circuit2)
```
The resulting circuit has more gates, but all of these gates can be submitted to an IonQ backend:
```python
0: ---H---@------------------@------------------@---@---T------@---M('x')---
| | | | | |
1: -------X-------@----------+-------@---T------+---X---T^-1---X---M--------
| | | | |
2: -----------H---X---T^-1---X---T---X---T^-1---X---T---H----------M--------
```
From here, we can run `circuit2` using `service.run()` or `service.create_job()` as shown in the previous examples.
Note that prior to `cirq-ionq` v0.15, this step was performed using `cirq_ionq.decompose_to_device(qc)` instead.
IonQ's native gates (GPi, GPi2, and MS) are also supported in Cirq. See our [native gates introduction](/guides/getting-started-with-native-gates) and [guide to using native gates in Cirq](/sdks/cirq/native-gates-cirq) for more details and examples.
***
## Full code examples
Here's full, copy-paste-friendly code examples for building a circuit and submitting it to the simulator, noisy simulator, or QPU.
```python Run on the ideal simulator
import cirq
import cirq_ionq
# Set up the IonQ service
service = cirq_ionq.Service()
# Build a circuit
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
cirq.H(q0),
cirq.CNOT(q0, q1),
cirq.measure(q0, q1, key='x')
)
# Run on the simulator
result = service.run(
circuit=circuit,
target="simulator",
repetitions=1000,
extra_query_params={"name": "Hello simulator, Cirq"}
)
# Print results
print(result.histogram(key='x'))
```
```python Run on the noisy simulator
import cirq
import cirq_ionq
# Set up the IonQ service
service = cirq_ionq.Service()
# Build a circuit
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
cirq.H(q0),
cirq.CNOT(q0, q1),
cirq.measure(q0, q1, key='x')
)
# Run on the simulator with noise model
result = service.run(
circuit=circuit,
target="simulator",
repetitions=1000,
extra_query_params={
"name": "Hello simulator, Cirq",
"noise": {"model": "aria-1"}}
)
# Print results
print(result.histogram(key='x'))
```
```python Submit to a QPU
import cirq
import cirq_ionq
# Set up the IonQ service
service = cirq_ionq.Service()
# Build a circuit
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
cirq.H(q0),
cirq.CNOT(q0, q1),
cirq.measure(q0, q1, key='x')
)
# Submit a job to the Aria 1 QPU
job = service.create_job(
circuit=circuit,
target="qpu.aria-1",
repetitions=1000,
extra_query_params={"name": "Hello QPU, Cirq"}
)
# Print the job status
print(job.status())
```
```python Retrieve results later
import cirq
import cirq_ionq
# Set up the IonQ service
service = cirq_ionq.Service()
# Retrieve a job
job_id = "..."
job = service.get_job(job_id)
# Get the job results
result = job.results().to_cirq_result()
print(result.histogram(key='x'))
```
***
## Additional resources
A Jupyter notebook for getting started with Cirq on IonQ hardware [is available here](https://quantumai.google/cirq/tutorials/ionq/getting_started).
Full documentation for the Cirq-IonQ integration can be found on the [Cirq documentation site](https://quantumai.google/cirq/start). 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.
The [IonQ hardware](https://quantumai.google/cirq/hardware#ionq-hardware) section of Cirq's documentation includes additional topics and resources specific to Cirq-IonQ.
You can find the [source code for the cirq-ionq package](https://github.com/quantumlib/Cirq/tree/main/cirq-ionq) on GitHub.
Licensing for Cirq is Apache 2.0.
# Using native gates with Cirq
Learn how to use our hardware-native gateset to run a circuit with Cirq
## Introduction
This guide covers how to use IonQ's native gates in Cirq. To learn more about what the native gates are and when to use them, refer to our guide on [getting started with native gates](/guides/getting-started-with-native-gates).
Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control and transparency than the default abstract gateset (though often at the cost of performance and convenience).
Before working with native gates in Cirq, we recommend reviewing our guides on [Getting Started with Native Gates](/guides/getting-started-with-native-gates) and [Getting Started with Cirq](/sdks/cirq/index). Native gates are also supported in the [IonQ API](/api-reference/v0.3/native-gates-api), [Qiskit](/sdks/qiskit/native-gates-qiskit), and [PennyLane](/sdks/pennylane/native-gates-pennylane).
This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.
***
## Building a circuit with native gates
IonQ's native gates are provided as part of the `cirq-ionq` package, including:
* `GPIGate(phi)`
* `GPI2Gate(phi)`
* `MSGate(phi0, phi1, theta=0.25)` for Aria systems
The ZZ two-qubit gate used on our Forte systems is currently not available in `cirq-ionq`. To use this type of native gate, build and submit circuits via [the IonQ API](/api-reference/v0.3/native-gates-api) or [Qiskit](/sdks/qiskit/native-gates-qiskit).
The native gates can be imported from `cirq_ionq.ionq_native_gates`:
```python Import circuit and gate definitions
import cirq
import cirq_ionq
from cirq_ionq.ionq_native_gates import GPIGate, GPI2Gate, MSGate
```
For more details about these gate definitions and parameters, refer to the [native gates guide](/guides/getting-started-with-native-gates#introducing-the-native-gates).
The parameters in the IonQ native gate specification are always defined in *turns*, not in radians. One turn is 2π radians.
Native gates are used like other gates when building a circuit:
```python Build a circuit using native gates
# Initialize the quantum circuit
q0, q1, q2 = cirq.LineQubit.range(3)
# Define gates (with parameter values in turns) and build the circuit
gpi = GPIGate(phi=0.5).on(q0)
gpi2 = GPI2Gate(phi=0.5).on(q1)
ms = MSGate(phi0=0, phi1=0.5).on(q1, q2)
meas = cirq.measure(q0, q1, q2, key='output')
circuit = cirq.Circuit([gpi, gpi2, ms, meas])
print(circuit)
```
```python
0: ---GPI(0.5)--------------M('output')---
│
1: ---GPI2(0.5)---MS(0)-----M-------------
│ │
2: ---------------MS(0.5)---M-------------
```
Note that Cirq also defines an MS gate in `cirq.MSGate`, but this gate is *not* equivalent to the IonQ native gates. To build a circuit in IonQ native gates, make sure you're using the MS gate imported from `cirq_ionq`.
## Submitting a circuit with native gates
No changes or special arguments are needed to submit a native gate circuit to a `cirq_ionq.Service`--the gateset will be detected automatically.
```python Submit a circuit
service = cirq_ionq.Service(api_key=YOUR_API_KEY)
result = service.run(circuit=circuit, repetitions=1024, target="simulator", name="Native gates in Cirq")
```
Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset throughout--you cannot mix and match native gates and abstract gates in the same circuit.
***
## Transpiling a circuit to native gates
The `cirq-ionq` integration currently does not support automatic transpilation to native gates via Cirq's compiler, but we plan to add this capability in the future. If you'd like to help, feel free to open an issue or a pull request on [the cirq-ionq module](https://github.com/quantumlib/Cirq/tree/main/cirq-ionq).
For now, we recommend following this general procedure (also described in our main [native gates guide](/guides/getting-started-with-native-gates#converting-to-native-gates)).
1. Decompose the gates used in the circuit so that each gate involves at most two qubits.
2. Convert all easy-to-convert gates into RX, RY, RZ, and CNOT gates.
3. Convert CNOT gates into XX gates using the decomposition described [here](https://arxiv.org/abs/1603.07678) and at the bottom of this section.
4. For hard-to-convert gates, first calculate the matrix representation of the unitary, then use either [KAK decomposition](https://arxiv.org/abs/quant-ph/0507171) or the method introduced in [this paper](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.77.066301) to implement the unitary using RX, RY, RZ and XX. Note that Cirq and Qiskit also have subroutines that can do this automatically, although potentially not optimally. See [cirq.linag.kak\_decomposition](https://quantumai.google/reference/python/cirq/kak_decomposition) and [qiskit.synthesis.TwoQubitBasisDecomposer](https://docs.quantum.ibm.com/api/qiskit/qiskit.synthesis.TwoQubitBasisDecomposer).
5. Write RX, RY, RZ and XX into GPi, GPi2 and MS gates as documented above (making sure to convert all angles and phases from radians to turns).
**CNOT to XX decomposition**
A CNOT gate can be expressed in XX, RX, and RY gates which can be directly converted to IonQ's native gates.
```python
----@----- ----| RY(π/2) |----| |----| RX(-π/2) |----| RY(-π/2) |-----
| = | XX(π/4) |
----X----- -------------------| |----| RX(-π/2) |---------------------
```
### Final transpilation step in code
Once you've completed steps 1-4 and expressed your circuit in terms of RX, RY, RZ, and XX gates, this example code snippet can perform the final transpilation step. The key here is to use a `qubit_phase` list to track and adjust the orientation of the Bloch sphere of each qubit as the circuit progresses.
```python
from cirq_ionq.ionq_native_gates import GPIGate, GPI2Gate, MSGate
import numpy as np
def compile_to_native_json(circuit):
qubit_phase=[0]*32
op_list=[]
for op in circuit.all_operations():
if type(op.gate)==cirq.ops.common_gates.Rz:
qubit_phase[op.qubits[0].x]=(qubit_phase[op.qubits[0].x]-op.gate._rads/(2*np.pi))%1
elif type(op.gate)==cirq.ops.common_gates.Ry:
if abs(op.gate._rads-0.5*np.pi)<1e-6:
op_list.append(
GPI2Gate(phi=(qubit_phase[op.qubits[0].x]+0.25)%1).on(op.qubits[0])
)
elif abs(op.gate._rads+0.5*np.pi)<1e-6:
op_list.append(
GPI2Gate(phi=(qubit_phase[op.qubits[0].x]+0.75)%1).on(op.qubits[0])
)
elif abs(op.gate._rads-np.pi)<1e-6:
op_list.append(
GPIGate(phi=(qubit_phase[op.qubits[0].x]+0.25)%1).on(op.qubits[0])
)
elif abs(op.gate._rads+np.pi)<1e-6:
op_list.append(
GPIGate(phi=(qubit_phase[op.qubits[0].x]+0.75)%1).on(op.qubits[0])
)
else:
op_list.append(
GPI2Gate(phi=(qubit_phase[op.qubits[0].x]+0)%1).on(op.qubits[0])
)
qubit_phase[op.qubits[0].x]=(qubit_phase[op.qubits[0].x]-op.gate._rads/(2*np.pi))%1
op_list.append(
GPI2Gate(phi=(qubit_phase[op.qubits[0].x]+0.5)%1).on(op.qubits[0])
)
elif type(op.gate)==cirq.ops.common_gates.Rx:
if abs(op.gate._rads-0.5*np.pi)<1e-6:
op_list.append(
GPI2Gate(phi=(qubit_phase[op.qubits[0].x]+0)%1).on(op.qubits[0])
)
elif abs(op.gate._rads+0.5*np.pi)<1e-6:
op_list.append(
GPI2Gate(phi=(qubit_phase[op.qubits[0].x]+0.5)%1).on(op.qubits[0])
)
elif abs(op.gate._rads-np.pi)<1e-6:
op_list.append(
GPIGate(phi=(qubit_phase[op.qubits[0].x]+0)%1).on(op.qubits[0])
)
elif abs(op.gate._rads+np.pi)<1e-6:
op_list.append(
GPIGate(phi=(qubit_phase[op.qubits[0].x]+0.5)%1).on(op.qubits[0])
)
else:
op_list.append(
GPI2Gate(phi=(qubit_phase[op.qubits[0].x]+0.75)%1).on(op.qubits[0])
)
qubit_phase[op.qubits[0].x]=(qubit_phase[op.qubits[0].x]-op.gate._rads/(2*np.pi))%1
op_list.append(
GPI2Gate(phi=(qubit_phase[op.qubits[0].x]+0.25)%1).on(op.qubits[0])
)
elif type(op.gate)==cirq.ops.parity_gates.XXPowGate:
if op.gate.exponent>0:
op_list.append(
MSGate(
phi0=qubit_phase[op.qubits[0].x],
phi1=qubit_phase[op.qubits[1].x]
).on(op.qubits[0],op.qubits[1])
)
else:
op_list.append(
MSGate(
phi0=qubit_phase[op.qubits[0].x],
phi1=(qubit_phase[op.qubits[1].x]+0.5)%1
).on(op.qubits[0],op.qubits[1])
)
else:
raise ValueError(f"Gate type unrecognized: must be Rx, Ry, Rz, XXPowGate")
return op_list
```
Once the circuit is fully expressed in IonQ native gates, it can be submitted to an IonQ backend as shown above.
***
## Additional resources
* [Getting Started with Native Gates](/guides/getting-started-with-native-gates)
* [Getting Started with Cirq](/sdks/cirq/index)
# Quantum SDKs
SDKs allow access to IonQ resources directly from within your code environment
{/* Use snippets to simplify maintenance! */}
While you can access IonQs resources directly via API, the majority of users use an SDK that simplifies usage and helps improve the stability of your code. As we make changes to our APIs, we also update our SDKs with the appropriate change to make sure they keep working as intended. If you were using our APIs directly, you *may* need to implement this yourself--but with an SDK you just need to update the package.
IonQ maintains compatibility with these SDKs, but *bugs happen*. If you come across a problem (or you just need some help), reach out to [support@ionq.co](mailto:support@ionq.co).
***
## Qiskit
[Qiskit](https://github.com/Qiskit/qiskit) is an open-source Python SDK for working with quantum computers at a variety of levels—from the “metal” itself, to pulses, gates, circuits and higher-order application areas like quantum machine learning and quantum chemistry. It has “Providers” that enable support for different vendors and the various “backends” (read: quantum computers or simulators) that they offer.
**Install Qiskit and the IonQ provider with:**
```bash
pip install qiskit qiskit-ionq
```
**Learn more:**
Quickly get up to speed and learn the fundamentals of working with this SDK
Explore the official reference materials for complete information on every feature this SDK supports
* [Additional tutorials](https://learning.quantum.ibm.com/catalog/tutorials) are available including implementations of VQE and QAOA
* [Report issues](https://github.com/qiskit-community/qiskit-ionq) with the `qiskit-ionq` provider in the GitHub project
***
## Cirq
[Cirq](https://quantumai.google/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.
* [Read our Cirq guide](/sdks/cirq) to get started
* [Google's example notebook](https://quantumai.google/cirq/start/start) is also a great way to get going
* A [complete reference](https://quantumai.google/reference/python/cirq/all_symbols) to all of the features in the SDK is available
***
## Pennylane
[PennyLane](https://pennylane.ai/) is an open-source Python library designed for quantum machine learning (QML). It facilitates the creation, simulation, and optimization of quantum circuits, enabling seamless integration with classical machine learning frameworks such as TensorFlow and PyTorch. One of PennyLane's key features is its ability to compute gradients of quantum circuits, a critical component for quantum machine learning models. PennyLane supports various quantum computing platforms, including IonQ, through its plugin system.
**Install Qiskit and the IonQ provider with:**
```bash
pip install pennylane pennylane-ionq
```
Quickly get up to speed and learn the fundamentals of working with this SDK
Explore the official reference materials for complete information on every feature this SDK supports
# PennyLane
Learn how to use PennyLane to submit quantum circuits to IonQ's simulators and quantum computers.
## What is PennyLane?
[PennyLane](https://pennylane.ai/) is an open-source Python library designed for quantum machine learning (QML). It facilitates the creation, simulation, and optimization of quantum circuits, enabling seamless integration with classical machine learning frameworks such as TensorFlow and PyTorch. One of PennyLane's key features is its ability to compute gradients of quantum circuits, a critical component for quantum machine learning models. PennyLane supports various quantum computing platforms, including IonQ, through its plugin system.
IonQ's [PennyLane plugin](https://pennylane-ionq.readthedocs.io) allows users to leverage IonQ's powerful trapped-ion quantum systems and high-performance cloud simulator directly within PennyLane, making it simpler to integrate quantum computing into your machine learning projects.
## Before you begin
Ensure you have an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and generate an API key for authentication. If you need assistance with this, there's a helpful guide on [setting up and managing your API keys](/guides/managing-api-keys).
You should also have Python 3.11 installed on your computer.
To check your Python version, run `python --version` in your terminal.
***
## Setting up PennyLane and the IonQ plugin
Install PennyLane and the IonQ plugin using pip:
```bash
pip install pennylane pennylane-ionq
```
**Note:** It's recommended to perform this installation within a virtual
environment using tools like
[virtualenv](https://virtualenv.pypa.io/en/latest/) or
[conda](https://docs.conda.io/en/latest/) to manage your Python packages
cleanly.
## Configuring your environment
PennyLane will use the `IONQ_API_KEY` environment variable by default. Visit the [IonQ Cloud](https://cloud.ionq.com/settings/keys) to obtain an API key. Then set this variable in your shell or terminal:
```bash
export IONQ_API_KEY="your_api_key_here"
```
Alternatively, you can specify your API key programmatically when creating a device in PennyLane.
## Writing a quantum circuit
Create a Python script or a Jupyter notebook and import PennyLane. Define a quantum device that targets IonQ's simulator (or a quantum processing unit, QPU, if you have access):
```python
import pennylane as qml
# Setup the device
dev = qml.device(
'ionq.simulator',
api_key="your_api_key_here",
wires=2
)
```
Define a simple quantum circuit as a function decorated with `@qml.qnode` that targets your device:
```python
@qml.qnode(dev)
def bell_state():
qml.Hadamard(wires=0)
qml.CNOT(wires=[0, 1])
return qml.probs(wires=[0, 1])
```
Execute the circuit and print the results:
```python
print(bell_state())
```
This code snippet creates a Bell state and measures the probabilities of the quantum state being in each basis state.
***
## Running your circuit
Execute your script or Jupyter notebook cell. You should receive an output similar to:
```python
[0.5 0. 0. 0.5]
```
This output represents the probabilities of measuring the quantum state in the `00`, `01`, `10`, and `11` states, showing that our Bell state preparation was successful.
***
## Viewing job results
You can view the results and status of your quantum jobs on the IonQ Quantum Cloud dashboard, under the "My Jobs" section.
***
## Expanding your knowledge
Congratulations on running your first quantum circuit with PennyLane and IonQ! To deepen your understanding:
* Explore [PennyLane's documentation](https://pennylane.readthedocs.io) for comprehensive guides and tutorials on quantum machine learning.
* Visit IonQ's [documentation](https://docs.ionq.com/) for more details on using their quantum systems.
* Check out advanced examples and use cases in the [PennyLane tutorials](https://pennylane.ai/qml/) and [IonQ's GitHub examples](https://github.com/ionq-samples).
# Using native gates with PennyLane
Learn how to use our hardware-native gateset to run a circuit with PennyLane
This guide covers how to use IonQ's native gates in PennyLane. To learn more about what the native gates are and when to use them, refer to our guide on [getting started with native gates](/guides/getting-started-with-native-gates).
## Introduction
Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control and transparency than the default abstract gateset (though often at the cost of performance and convenience).
Before working with native gates in PennyLane, we recommend reviewing our guides on [Getting Started with Native Gates](/guides/getting-started-with-native-gates) and [Getting Started with PennyLane](/sdks/pennylane/index). Native gates are also supported in the [IonQ API](/api-reference/v0.3/native-gates-api), [Qiskit](/sdks/qiskit/native-gates-qiskit), and [Cirq](/sdks/cirq/native-gates-cirq).
This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.
***
## Using native gates
Native gates are supported as of `v0.28.0` of the [PennyLane IonQ plugin](https://github.com/PennyLaneAI/PennyLane-IonQ).
Gates are provided as part of the `pennylane-ionq` package, including:
* `GPI(phi)`
* `GPI2(phi)`
* `MS(phi0, phi1, theta=0.25)` for Aria systems
For more details about these gate definitions and parameters, refer to the [native gates guide](/guides/getting-started-with-native-gates#introducing-the-native-gates).
The native gates can be imported from `pennylane_ionq.ops`:
```python
# Import circuit and gate definitions
import pennylane as qml
from pennylane_ionq.ops import GPI, GPI2, MS
```
The parameters in the IonQ native gate specification are always defined in *turns*, not in radians. One turn is 2π radians.
To use native gates, set up an IonQ device with `gateset="native"`:
```python
dev = qml.device('ionq.simulator', wires=3, gateset="native")
```
Native gate circuits can then be built and executed using this device:
```python QNode example
@qml.qnode(dev)
def native_gate_circuit():
GPI(0.5, wires=[0])
GPI2(0, wires=[1])
MS(0, 0.5, wires=[1, 2])
return qml.probs(wires=[0, 1, 2])
print(native_gate_circuit())
```
```python Tape example
with qml.tape.QuantumTape() as tape:
GPI(0.5, wires=[0])
GPI2(0, wires=[1])
MS(0, 0.5, wires=[1, 2])
qml.probs(wires=[0,1,2])
dev.execute(tape)
```
Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset throughout--you cannot mix and match native gates and abstract gates in the same circuit.
The `pennylane-ionq` plugin currently does not support automatic transpilation from abstract to native gates, but we may add this capability in the future. For now, we recommend following this general procedure (also described in our main [native gates guide](/guides/getting-started-with-native-gates#converting-to-native-gates)) or using a different SDK.
***
## Additional resources
* [Getting Started with Native Gates](/guides/getting-started-with-native-gates)
* [Getting Started with PennyLane](/sdks/pennylane/index)
# Using debiasing with Qiskit
Learn how to use IonQ's error mitigation techniques with Qiskit
## Introduction
IonQ's default error mitigation strategy is debiasing, a compiler-level error mitigation strategy that works by creating and running many symmetric variations of a given circuit. Results from the different circuit executions are aggregated to minimize the impact of some types of noise. Aggregation is performed via averaging and via sharpening (plurality voting) and the aggregated results from either strategy can be retrieved, depending on the specific application. This technique is very general and doesn't require additional shot or qubit overhead.
This guide covers when debiasing is applied, how to enable or disable debiasing when submitting a job via Qiskit, and how to retrieve results with averaging or sharpening via Qiskit. For more details about this technique and how it works, refer to our [debiasing and sharpening guide](https://ionq.com/resources/debiasing-and-sharpening).
***
## Error mitigation defaults
For jobs submitted to IonQ QPUs via the IonQ cloud, debiasing is enabled by default for jobs with 500 or more shots, but it can be disabled (as shown below). It is not used for jobs with fewer than 500 shots, and cannot be enabled - at least 500 shots are required in order to obtain a significant number of results for each circuit execution variant.
These default settings and shot cutoffs apply for jobs submitted directly to the IonQ cloud platform, and they may be different for jobs submitted via our cloud partners.
Debiasing is not currently available for jobs run via IonQ's simulators, including our [noisy simulators](/guides/simulation-with-noise-models).
In most cases, there is a minimum cost for jobs run on IonQ's QPUs, and this minimum cost is increased by debiasing. For small circuits, splitting a job into multiple executions can add a significant amount of time relative to the actual circuit duration, so debiasing makes the job more expensive. If you are running particularly shallow circuits that yield high-quality results without error mitigation, you may prefer to disable debiasing. For more specifics on pricing, please contact your IonQ representative directly.
## Specifying the debiasing settings
To explicitly specify the debiasing setting for a job, we need to:
1. Import `ErrorMitigation` from `qiskit_ionq`
2. Pass either `error_mitigation=ErrorMitigation.DEBIASING` or `error_mitigation=ErrorMitigation.NO_DEBIASING` when calling `backend.run()`
In this example, we'll disable debiasing for a job with 1000 shots (where it would be enabled by default).
```python
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider, ErrorMitigation
provider = IonQProvider()
qpu_backend = provider.get_backend("ionq_qpu.aria-1")
# Create a basic Bell State circuit:
qc = QuantumCircuit(2, 2, name="Debiasing Off")
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Run the circuit on IonQ's platform:
job = qpu_backend.run(
qc,
shots=1000,
error_mitigation=ErrorMitigation.NO_DEBIASING
)
```
## Retrieving and aggregating results
After a job is run with debiasing, there are two options for aggregating the results over the different symmetric variants. You can read more about component-wise averaging, sharpening via plurality voting, and which one to choose in our [debiasing guide](https://ionq.com/resources/debiasing-and-sharpening#average-aggregation).
Component-wise **averaging** computes the mean probabilities over all circuit variants, which preserves the measured probability distribution. This is the default aggregation method used when retrieving the results of a job. Once you have a job (either one that you just submitted, or one retrieved using the job ID and `backend.retrieve_job(job_id)`), just get the counts.
```python
print(job.get_counts())
```
The above example might give something like:
```python
{'11': 505, '00': 483, '10': 9, '01': 3}
```
Note that `job.result().get_counts()` and `job.result(sharpen=False).get_counts()` are equivalent.
**Sharpening** via plurality voting is a different aggregation strategy which takes the highest-probability result from each variant. For circuits where you're trying to identify one or a few high-probability states, debiasing and sharpening can greatly improve the result quality.
```python
print(job.result(sharpen=True).get_counts())
```
For this example, the sharpened result looks like:
```python
{'00': 530, '11': 470}
```
The QPU result included a few measurements of the `10` and `01` states, which can only occur due to error. These were included when the results were aggregated by averaging. However, when sharpening was used, we counted only the highest-probability state from each circuit variant that was run, and these states were always either `00` or `11`.
***
## Additional resources
* [Full guide to debiasing and sharpening](https://ionq.com/resources/debiasing-and-sharpening)
* [Enhancing quantum computer performance via symmetrization](https://arxiv.org/abs/2301.07233) on arXiv (symmetrization is another term for debiasing)
# Getting started with Qiskit
Learn how to use the Qiskit SDK to submit quantum circuits to IonQ's simulators and quantum computers.
## What is Qiskit?
[Qiskit](https://github.com/Qiskit/qiskit) is an open-source Python SDK for working with quantum computers at a variety of levels—from the “metal” itself, to pulses, gates, circuits and higher-order application areas like quantum machine learning and quantum chemistry. It has “Providers” that enable support for different vendors and the various “backends” (read: quantum computers or simulators) that they offer.
IonQ maintains an [IonQ Provider for Qiskit](https://github.com/qiskit-community/qiskit-ionq) that allows you to work with our trapped-ion systems and our high-performance cloud simulator, which we'll install and use here.
## Before you begin
You'll need an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and you'll need to create an API key. We also have a guide about [setting up and managing your API keys](/guides/managing-api-keys) if you need some help.
You'll also need Python 3.11 running locally on your machine.
Run `python --version` from your command line if you aren't sure which version
you have running.
***
## Set up Qiskit
First, we'll install Qiskit and the IonQ Provider from [PyPI](https://pypi.org/) using pip:
```bash
pip install qiskit qiskit-ionq
```
**Note:** We encourage doing this inside an environment management system like
[virtualenv](https://virtualenv.pypa.io/en/latest/) or
[conda](https://docs.conda.io/en/latest/) so as to avoid [this
fate](https://xkcd.com/1987/), but do what makes the most sense for you.
## Set up your environment
By default, Qiskit will look in your local environment for a variable named `IONQ_API_KEY`, so if you've already followed our guide on [setting up and managing your API keys](/guides/managing-api-keys), Qiskit will automatically find it.
Alternatively, you can set an environment variable temporarily from your command line, by running:
```bash
export IONQ_API_KEY="your_api_key_here"
```
While we recommend setting an environment variable so that Qiskit can find your API key, you can also pass in your API key explicitly within your Python code, when creating the IonQ Provider object that authenticates your connection to the IonQ Cloud Platform. This might be necessary if you've named your environment variable something other than `IONQ_API_KEY`, or if you are working from a Python environment where accessing environment variables is not straightforward. You can import your key explicitly or load it from a file, and pass it into the `IonQProvider()` object directly:
```python
import os
from qiskit_ionq import IonQProvider
# Load your API key from an environment variable named MY_IONQ_API_KEY
my_api_key = os.getenv("MY_IONQ_API_KEY")
provider = IonQProvider(my_api_key)
```
In the examples below, we show `IonQProvider()` initialized with no arguments and assume that Qiskit will automatically find your API key, but you can always use this approach instead.
## Start a script
For this exercise, we'll create a Python file and run it as a script. If you're comfortable and familiar with Python, you can approach this any number of ways—our [getting-started](https://github.com/ionq-samples/getting-started/tree/main) repository includes Jupyter notebooks that can be downloaded or run in Google Colab.
Open a file up in whatever IDE you prefer, and add the following:
```python
from qiskit_ionq import IonQProvider
provider = IonQProvider()
print(provider.backends())
```
Running this script should print the results below—something like this:
```bash
[, ]
```
If this works correctly then your Qiskit installation works, your API key is valid, and you have access to the IonQ simulator! If you have access to a QPU, you'll see it in this list, as well.
***
## Submit a circuit to the simulator
### Running a simple Bell state circuit
First, let's try running a simple Bell state circuit on the ideal quantum simulator. Try running this script:
```python
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider
provider = IonQProvider()
simulator_backend = provider.get_backend("ionq_simulator")
# Create a basic Bell State circuit:
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Run the circuit on IonQ's platform:
job = simulator_backend.run(qc, shots=10000)
# Print the counts
print(job.get_counts())
```
When you run it, you should see something like:
```python
{'00': 4984, '11': 5016}
```
The simulator is simulating the circuit we defined, running it 10,000 times, and counting the number of times each state was measured. In this case, the circuit evaluated to a “00” state 5,016 times, and a “11” state 4,984 times.
While the ideal simulator creates a quantum state with a 50-50 probability of being measured as "00" or "11", the `.get_counts()` method samples from this probability distribution, so we didn't end up with exactly 5,000 counts for each state. You can use `job.get_probabilities()` to see the calculated probabilities for a circuit that was run on the simulator.
### Submitting multiple circuits in a single job
To submit multiple circuits in a single job submission, pass all of the circuits to the `run()` function in a list instead:
```python
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider
provider = IonQProvider()
simulator_backend = provider.get_backend("ionq_simulator")
# Define two quantum circuits
qc1 = QuantumCircuit(2, name="bell state")
qc1.h(0)
qc1.cx(0, 1)
qc1.measure_all()
qc2 = QuantumCircuit(3, name="ghz state")
qc2.h(0)
qc2.cx(0, 1)
qc2.cx(0, 2)
qc2.measure_all()
# Submit both circuits as a single job
job = simulator_backend.run([qc1, qc2])
# Print the results
print(job.get_counts())
# Or a specific job
print(job.get_counts(qc1))
```
This script submits two quantum circuits in a single job: a Bell state circuit and a GHZ state circuit. When the job completes, it prints the counts for each circuit:
```python
[{'00': 519, '11': 505}, {'000': 505, '111': 519}]
{'00': 519, '11': 505}
```
***
## Submit a circuit to the noisy simulator
To run the same circuit (or circuits) using the simulator with a noise model, we just need to modify one line of code in the above script: here, we'll add the argument `noise_model="aria-1"` when calling `simulator_backend.run()`. The available noise models are `harmony` (legacy), `aria-1`, `aria-2`, and `forte-1`. You can read more about these noise models [here](/guides/simulation-with-noise-models).
```python
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider
provider = IonQProvider()
simulator_backend = provider.get_backend("ionq_simulator")
# Create a basic Bell State circuit:
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Run the circuit on IonQ's platform:
job = simulator_backend.run(qc, shots=10000, noise_model="aria-1")
# Print the counts
print(job.get_counts())
```
When this simulation includes the effects of noise, we would expect to see results that are similar to the ideal simulation shown above, but with a few instances of measuring the "01" and "10" states. For example:
```python
{'00': 4919, '01': 37, '10': 33, '11': 5011}
```
***
## Submit a circuit to a QPU
To run the same circuit on IonQ's quantum hardware (QPU), we need to define a different backend at the beginning of the script and submit the circuit to that backend. Available QPU backend options may include `ionq_qpu.aria-1`, `ionq_qpu.aria-2`, or `ionq_qpu.forte-1`. You can view your access to these systems on the ["Backends" tab](https://cloud.ionq.com/backends) of the IonQ Cloud Console.
Before submitting to any QPU, we recommend testing your code on a simulator (including with noise model) and following the other steps on [this list](/guides/qpu-submission-checklist.mdx) to confirm your access and the QPU availability.
```python
# Set up the Aria-1 QPU backend:
qpu_backend = provider.get_backend("ionq_qpu.aria-1")
# Create a basic Bell State circuit:
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Run the circuit on IonQ's platform:
job = qpu_backend.run(qc, shots=10000)
# Print the job ID
print(job.job_id())
```
When submitting jobs to a QPU, your job may need to wait in the queue, so you probably won't get the results right away. Next, we'll show how to check a previously submitted job's status and retrieve its results.
***
## Viewing job status and results
On the [“My Jobs” tab](https://cloud.ionq.com/jobs) in the IonQ Quantum Cloud application, you can always view the status of all of your jobs, and you can view and download their results.
!["My Jobs" in the IonQ Cloud Console](https://mintlify.s3-us-west-1.amazonaws.com/ionq/guides/_media/run-your-first-job-my-jobs.png)
You can also get the job status and results within Qiskit. You'll need the job ID, which you can save after submitting a job (as in the QPU example above) or copy from the "ID" column in the "My Jobs" tab.
```python
from qiskit_ionq import IonQProvider
# Set up the IonQ provider and backend
provider = IonQProvider()
simulator_backend = provider.get_backend("ionq_simulator")
# Specify a job ID
job_id = "..."
# Retrieve the job
job = backend.retrieve_job(job_id)
# Print the job status
print(job.status())
```
Once you've retrieved a job, you can use the same methods as in the above examples to print counts, probabilities, and other information.
***
## Learning more
*Great work!* You successfully ran your first quantum circuits—*now what?*
**For additional resources on using Qiskit,** we recommend their [getting started page](https://qiskit.org/documentation/getting_started.html) and [learning resources](https://qiskit.org/learn). For more detailed information on Qiskit, we recommend the [Qiskit documentation](https://qiskit.org/documentation/).
**For advanced features** on IonQ systems with Qiskit, refer to our guides on [using native gates](/sdks/qiskit/native-gates-qiskit) and [error mitigation with debiasing and sharpening](/sdks/qiskit/error-mitigation-qiskit).
**For examples using different SDKs,** more complex circuits, and in other languages, check out our [IonQ Samples library on GitHub](https://github.com/ionq-samples/getting-started).
Finally (and maybe most importantly,) you can also [**request access to IonQ Quantum Computers here.**](https://ionq.com/get-access?intent=direct-access)
# Using native gates with Qiskit
Learn how to use our hardware-native gateset to run a circuit with Qiskit
This guide covers how to use IonQ's native gates in Qiskit. To learn more about what the native gates are and when to use them, refer to our guide on [getting started with native gates](/guides/getting-started-with-native-gates).
## Introduction
Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control and transparency than the default abstract gateset (though often at the cost of performance and convenience).
Before working with native gates in Qiskit, we recommend reviewing our guides on [Getting Started with Native Gates](/guides/getting-started-with-native-gates) and [Getting Started with Qiskit](/sdks/qiskit/index). Native gates are also supported in the [IonQ API](/api-reference/v0.3/native-gates-api), [Cirq](/sdks/cirq/native-gates-cirq), and [PennyLane](/sdks/pennylane/native-gates-pennylane).
Note that the first few code examples in this section highlight specific components of native gate workflows. For end-to-end code snippets that you can copy-paste and run directly, skip to the [full code examples](/sdks/qiskit/native-gates-qiskit#full-code-examples) section below.
This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.
***
## Building circuits with native gates
Native gate circuit construction is supported as of `v0.3.1` of the [Qiskit IonQ Provider](https://github.com/qiskit-community/qiskit-ionq).
Gates are provided as part of the `qiskit-ionq` package, including:
* `GPIGate(phi)`
* `GPI2Gate(phi)`
* `MSGate(phi0, phi1, theta=0.25)` for Aria systems
* `ZZGate(theta)` for Forte systems
```python
# Import circuit and gate definitions
from qiskit import QuantumCircuit
from qiskit_ionq import GPIGate, GPI2Gate, MSGate, ZZGate
```
For more details about these gate definitions and parameters, refer to the [native gates guide](/guides/getting-started-with-native-gates#introducing-the-native-gates).
The parameters in the IonQ native gate specification are always defined in *turns*, not in radians. One turn is 2π radians.
To add these gates to a circuit, use Qiskit's `circuit.append()` method:
```python
# Initialize the quantum circuit
circuit = QuantumCircuit(2, 2)
# Add gates (remembering that parameters are in turns, not radians)
circuit.append(MSGate(0, 0), [0, 1])
circuit.append(GPIGate(0), [0])
circuit.append(GPI2Gate(1), [1])
circuit.measure([0, 1], [0, 1])
circuit.draw()
```
![Circuit built using native gates](https://mintlify.s3-us-west-1.amazonaws.com/ionq/sdks/qiskit/_media/qiskit-native-gates-circuit1-light.png)
Note that Qiskit also defines MS and ZZ gates in `qiskit.circuit.library`, but these gates are *not* equivalent to the IonQ native gates. To build a circuit in IonQ native gates, make sure you're using the gates imported from `qiskit_ionq`.
For a complete code example including circuit submission, skip to the [full code examples](/sdks/qiskit/native-gates-qiskit#full-code-examples) below.
***
## Transpiling a circuit to native gates
Converting a circuit to native gates with Qiskit's transpilation is supported as of `v0.5.1` of the [Qiskit IonQ Provider](https://github.com/qiskit-community/qiskit-ionq).
Start with the usual imports, plus Qiskit's `transpile()` method:
```python
from qiskit import QuantumCircuit, transpile
from qiskit_ionq import IonQProvider
```
Build a quantum circuit using the abstract (QIS) gateset:
```python
qc_abstract = QuantumCircuit(2, 2, name="hello world, native gates")
qc_abstract.h(0)
qc_abstract.cx(0, 1)
qc_abstract.measure([0, 1], [0, 1])
qc_abstract.draw()
```
![Circuit built using abstract gates](https://mintlify.s3-us-west-1.amazonaws.com/ionq/sdks/qiskit/_media/qiskit-native-gates-circuit2-light.png)
Next, set up an `IonQProvider` and backend, using `gateset="native"`. Qiskit's transpiler can use the target gateset defined by this backend.
```python
provider = IonQProvider()
backend_native = provider.get_backend("simulator", gateset="native")
```
Finally, use Qiskit's `transpile()` method and the native-gates backend to convert the circuit to IonQ's native gateset:
```python
qc_native = transpile(qc_abstract, backend=backend_native)
qc.draw()
```
![Circuit transpiled to native gates](https://mintlify.s3-us-west-1.amazonaws.com/ionq/sdks/qiskit/_media/qiskit-native-gates-circuit3-light.png)
Here, we can see that the Hadamard and CNOT gates in the original circuit were converted into a series of GPI2 gates and one MS gate.
For a complete code example including circuit submission, skip to the [full code examples](/sdks/qiskit/native-gates-qiskit#full-code-examples) below.
***
## Submitting a circuit that uses native gates
Whether you built a circuit in native gates originally, or you built a circuit in abstract gates and transpiled it with Qiskit, you'll need to submit it to an IonQ backend that was set up with the native gateset. Circuits submitted this way will bypass IonQ's compiler and optimizer.
Set up an IonQ backend and specify the native gateset: here, we'll use the ideal simulator, but you can also use the noisy simulator or an IonQ QPU.
This tells the backend to expect circuits defined in native gates, and to bypass IonQ's compiler and optimizer. With the default setting, `gateset="qis"`, the backend will expect circuits defined in abstract gates.
```python
provider = IonQProvider()
backend_native = provider.get_backend("simulator", gateset="native")
```
After you define a quantum circuit `qc_native`, either by building it in native gates directly or building it in abstract gates and then transpiling it, you can submit it to the native gate backend:
```python
job_native = backend_native.run(qc_native, shots=1000)
```
Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset throughout--you cannot mix and match native gates and abstract gates in the same circuit.
For a complete code example including circuit construction, continue to the [full code examples](/sdks/qiskit/native-gates-qiskit#full-code-examples) below.
***
## Full code examples
These examples put together the pieces from the above sections to show two different complete workflows: one for building a circuit in native gates and submitting it to IonQ's simulator; one for building a different circuit in abstract gates, transpiling it via Qiskit, and submitting it to IonQ's simulator.
```python Build in native gates and run
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider
from qiskit_ionq import GPIGate, GPI2Gate, MSGate, ZZGate
# Set up an IonQ backend to use native gates
provider = IonQProvider()
backend_native = provider.get_backend("simulator", gateset="native")
# Initialize a quantum circuit
circuit = QuantumCircuit(2, 2, name="build in native gates")
# Add gates (remember that parameters are in turns, not radians)
circuit.append(MSGate(0, 0), [0, 1])
circuit.append(GPIGate(0), [0])
circuit.append(GPI2Gate(1), [1])
circuit.measure([0, 1], [0, 1])
# Run the circuit on the native gates backend
job = backend_native.run(circuit, shots=1000)
# Print results
print(job.get_counts())
```
```python Build in abstract gates, transpile, and run
from qiskit import QuantumCircuit, transpile
from qiskit_ionq import IonQProvider
# Set up an IonQ backend to use native gates
provider = IonQProvider()
backend_native = provider.get_backend("simulator", gateset="native")
# Build a circuit using abstract gates
qc_abstract = QuantumCircuit(2, 2, name="transpile native gates")
qc_abstract.h(0)
qc_abstract.cx(0, 1)
qc_abstract.measure([0, 1], [0, 1])
# Transpile the circuit to native gates
qc_native = transpile(qc_abstract, backend_native)
# Run the circuit on the native gates backend
job = backend_native.run(qc_native, shots=1000)
# Print results
print(job.get_counts())
```
***
## Additional resources
* [Getting Started with Native Gates](/guides/getting-started-with-native-gates)
* [Getting Started with Qiskit](/sdks/qiskit/index)
# TensorFlow Quantum
Learn how to use TensorFlow Quantum to connect your ML workflows to IonQ's simulators and quantum computers.
**Time:** 1-2 Hours
**Expected knowledge:** Basic familiarity with Google Cloud is strongly encouraged. Some knowledge of machine learning and quantum circuits and algorithms is helpful
**System requirements:** Internet access, Python 3.6 or later
One of the most exciting applications of quantum computing today is its application to machine learning algorithms. Equivalently-sized [quantum kernels](https://blog.tensorflow.org/2020/11/characterizing-quantum-advantage-in.html) have been proved to provide measurable improvements in learning on the identical training data.
With the latest major release of TensorFlow Quantum (`>= 0.6.0`), it's now possible to use the [quantum machine learning](https://www.tensorflow.org/quantum/concepts) spinoff of one of the world's most well-known machine learning libraries with IonQ's devices. Whether you're [struggling with barren plateaus](https://www.tensorflow.org/quantum/tutorials/barren_plateaus), or doing [full-fledged reinforcement learning](https://www.tensorflow.org/quantum/tutorials/quantum_reinforcement_learning), this guide can help you take the first step on the path of becoming a quantum machine learning (QML) expert.
***
## Before you begin
You'll need an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and you'll need to create an API key. We also have a guide about [setting up and managing your API keys](/guides/managing-api-keys) if you need some help.
This guide assumes that you have followed these instructions and have saved your API key as a local environment variable named `IONQ_API_KEY`.
***
## About Tensorflow Quantum
TensorFlow Quantum (TFQ) is part of [TensorFlow](https://www.tensorflow.org/), a popular library for prototyping, training and deploying machine learning models. TFQ's [quantum machine learning](https://www.tensorflow.org/quantum/concepts) tools help users of a variety of skill levels prototype and build machine learning models that use a hybrid quantum-classical approach by combining the quantum computing tools and logic designed in [Cirq](/guides/cirq), with TensorFlow APIs, and inbuilt quantum circuit simulators.
The [TensorFlow Quantum whitepaper](https://arxiv.org/abs/2003.02989) and [TensorFlow Quantum website](https://www.tensorflow.org/quantum/) provide more details on the motivation and philosophy behind the project, as well as full API documentation and example code for a variety of common ML application.
***
## Installing and Setting up TensorFlow Quantum
You can install TensorFlow Quantum from PyPI, the Python Package Index, using `pip`.
We recommend creating a requirements.txt file and then installing from that:
```bash
echo "cirq-google>=0.13.1
cirq-ionq>=0.13.1
pydot==1.4.2
tensorflow>=2.7.0
tensorflow-quantum>=0.6.0" > requirements.txt
```
**Note about Windows:** Tensorflow Quantum must be built from source for Windows support. Alternatively, you can try running these inside WSL or a docker container.
**Note about Python:** We encourage doing this inside an environment management system like [virtualenv](https://virtualenv.pypa.io/en/latest/) or [conda](https://docs.conda.io/en/latest/) so as to avoid [this fate](https://xkcd.com/1987/), but do what makes the most sense for you.
To set up a virtual environment with `venv` and install our above requirements in to it, run the following:
```bash
python3 -m venv tfq-ionq
source tfq-ionq/bin/activate
pip install -r requirements
```
That's it! Because TensorFlow quantum uses Cirq under the hood and IonQ [works with Cirq](/guides/cirq), you're now ready to use TensorFlow Quantum with IonQ hardware.
***
## Running your first TensorFlow Quantum program
Here is an adaptation of TFQ's [Hello, many worlds](https://www.tensorflow.org/quantum/tutorials/hello_many_worlds) tutorial, which uses the IonQ simulator backend to train a simple parameterized circuit.
Run the following as a Python script or in a Jupyter notebook, and you're off to the races:
```python
import tensorflow as tf
import tensorflow_quantum as tfq
import cirq
import sympy
import numpy as np
a, b = sympy.symbols('a b')
import cirq_ionq as ionq
# API key is assumed to be stored as an env var named IONQ_API_KEY
service = ionq.Service()
# Parameters that the classical NN will feed values into.
control_params = sympy.symbols('theta_1 theta_2 theta_3')
# Create the parameterized circuit.
qubit = cirq.LineQubit.range(1)[0]
model_circuit = cirq.Circuit(
cirq.rz(control_params[0])(qubit),
cirq.ry(control_params[1])(qubit),
cirq.rx(control_params[2])(qubit))
controller = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation='elu'),
tf.keras.layers.Dense(3)
])
# This input is the simulated mis-calibration that the model will learn to correct.
circuits_input = tf.keras.Input(shape=(),
# The circuit-tensor has dtype `tf.string`
dtype=tf.string,
name='circuits_input')
# Commands will be either `0` or `1`, specifying the state to set the qubit to.
commands_input = tf.keras.Input(shape=(1,),
dtype=tf.dtypes.float32,
name='commands_input')
dense_2 = controller(commands_input)
# TFQ layer for classically controlled circuits.
expectation_layer = tfq.layers.ControlledPQC(model_circuit,
backend=service.sampler('simulator'),
repetitions=3000,
# Observe Z
operators = cirq.Z(qubit))
expectation = expectation_layer([circuits_input, dense_2])
model = tf.keras.Model(inputs=[circuits_input, commands_input],
outputs=expectation)
tf.keras.utils.plot_model(model, show_shapes=True, dpi=70)
commands = np.array([[0], [1]], dtype=np.float32)
expected_outputs = np.array([[1], [-1]], dtype=np.float32)
random_rotations = np.random.uniform(0, 2 * np.pi, 3)
noisy_preparation = cirq.Circuit(
cirq.rx(random_rotations[0])(qubit),
cirq.ry(random_rotations[1])(qubit),
cirq.rz(random_rotations[2])(qubit)
)
datapoint_circuits = tfq.convert_to_tensor([
noisy_preparation
] * 2) # Make two copies of this circuit
print("Fitting with tfq... this may take some time...")
optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)
loss = tf.keras.losses.MeanSquaredError()
model.compile(optimizer=optimizer, loss=loss)
history = model.fit(x=[datapoint_circuits, commands],
y=expected_outputs,
epochs=30,
verbose=0)
print ("Plotting now")
import matplotlib.pyplot as plt
plt.plot(history.history['loss'])
plt.title("Learning to Control a Qubit")
plt.xlabel("Iterations")
plt.ylabel("Error in Control")
plt.show()
```
Once you've seen what it can do, simply switch the backend to service.sampler('qpu') to run the above code on actual IonQ Hardware.
We're very excited to see what our users do with this new functionality. Are you blazing a trail into the QML future? Have you used IonQ hardware for something interesting in the quantum machine learning space? Let us know at [@IonQ\_Inc](https://twitter.com/IonQ_Inc).
***
Licensing for TensorFlow Quantum and all code samples in this document are Apache 2.0.
# Your Account
Accounts are freely available, and can be created by [signing up here](https://cloud.ionq.com). All accounts have access to IonQ's cloud simulators up to 29 qubits (including [noise models](/guides/simulation-with-noise-models) for our current QPUs) and our [our APIs](/api-reference), which can also be used through a third-party SDK such as [Qiskit](/guides/qiskit).
To join an existing organization, an Organization Owner will need to [send you an invitation](/user-manual/organizations#inviting-members) first.
***
## API Keys
IonQ uses API keys to manage access to our systems. Each key must be assigned to a [Project](/user-manual/projects), and all jobs submitted with that key be automatically assigned to that project.
**Keys are a type of password, and should be treated as such.** To learn how to store your keys safely, check out our guide on [managing API keys](/guides/managing-api-keys).
### Creating a new key
API keys are created on the [API Keys](https://cloud.ionq.com/settings/keys) page found in the top menu.
### Viewing Current Keys
Your currently active keys are available under the menu, under the API Keys item. The key itself is not visible after creation, however, from this page you can view the name, assigned project, and time each was last used.
Manage your keys from the IonQ Quantum Cloud application
### Revoking a key
If a key is no longer needed, it can be revoked from the [API Keys page](https://cloud.ionq.com/settings/keys). Revoked keys immediately stop working, meaning they will no longer be recognized by our APIs.
Jobs submitted with a key will stay in queue even if the key is revoked.
***
## Deleting your account
Accounts can be deleted upon request. Please contact your IonQ representative, or reach out to [support@ionq.co](mailto:support@ionq.co).
# Glossary
An glossary of IonQ Platform terminology
This is a glossary of terms relating to the [IonQ Quantum Cloud Platform](https://cloud.ionq.com) and the APIs and SDKs that integrate with it. To learn *quantum computing* terminology, visit the ["Quantum Glossary"](https://ionq.com/resources/glossary) on our Resource Center.
## Platform Concepts
#### API
An *application programming interface*, or API, allows an external user to interact with a specific system or service. In the case of the [IonQ Quantum Platform's API](/api-reference), it takes the format of a "RESTful" HTTP interface. Users can interact directly with the API via command-line tools like `curl` or Python libraries like `requests`, or they can interact with the IonQ Quantum Platform via an [SDK](#sdk) like Qiskit.
***
#### API Key
To access an API you need to *authenticate* yourself using an API key. This is a special type of password used to access our systems via API. Keys are attached to [Projects](#project), and are created on [cloud.ionq.com](https://cloud.ionq.com/settings/keys).
To learn more, read our guide on [Managing API Keys](/guides/managing-api-keys).
***
#### Backend
A backend is a system that [jobs](#job) can be submitted to. A backend can either be a [QPU](#qpu) (a quantum computer) or a [simulator](#simulator).
The status of our systems can be found on [status.ionq.co](https://status.ionq.co/). The possible statuses are:
* **Operational:** The system is meeting spec both in terms of job quality and throughput.
* **Degraded:** The system is underperforming spec. The specific way it is underperforming will be noted on the status page.
* **Partial Outage:** The system is down while a component is remotely reconfigured.
* **Major Outage:** The system is down while *two or more* components are remotely reconfigured.
* **Under Maintenance:** The system is down while one or more components are under physical maintenance.
***
#### Characterizations
A characterization is a snapshot of an IonQ QPU's performance at a moment in time. While our quantum computers are continuously calibrated moment to moment, we periodically take measurements of gate fidelities and other statistics.
This data is listed [in the UI](https://cloud.ionq.com/backends) *(Click on "Show Details" on a backend)* as well as made available [via the API](/api-reference/v0.3/characterizations/get-a-characterization).
***
#### Circuit
A representation of a quantum computation, made up of a series of qubit initializations, gates, and measurements. They can be submitted to a QPU as a part of a [job](#job).
***
#### Execution
Executions are created by a [job](#job) to run a specific circuit on a QPU. The number of times it will be repeated and measured is expressed as [shots](#shots).
***
#### Hybrid
"Hybrid" is a general term used to refer to when a QPU co-processes with a classical computing system. Commonly, this is used to run an [optimization algorithm](https://en.wikipedia.org/wiki/Mathematical_optimization) for optimizing a variational quantum circuit. A hybrid workflow will contain many [jobs](#job) as the algorithm optimizes the circuit.
***
#### Job
A task to be completed by our system. This can be one more more [circuits](#circuit) in a variety of formats, or instructions for the IonQ platform for a specific type of workload task. A job may also be a *parent job* (created during a multicircuit job submission), which triggers the creation of additional *child jobs* for individual circuits.
***
#### Job Status
As jobs progress through the platform, they move through different states. Job status can be viewed on the [My Jobs](https://cloud.ionq.com/jobs) page of the IonQ Cloud Console or on a specific [project's](#project) page for jobs submitted to that project, as well as accessed via the API or an SDK. The possible statuses are listed in the [user manual's Jobs page](/user-manual/jobs).
***
#### Job Queue
Once submitted, jobs are decomposed into executions which are then added to a queue. The queue is served in a prioritized model based on a [fair-sharing](https://en.wikipedia.org/wiki/Fair-share_scheduling) schedule.
***
#### Reservation
A reservation is a pre-scheduled block of time where a single user or organization is given access to a specific QPU. To make a reservation, reach out to your IonQ point of contact or email [support@ionq.co](mailto:support@ionq.co) with information about the workload, target system, and scheduling considerations.
***
#### SDK
A set of libraries or tools that ease the integration or interaction with another computing system. For example, common "quantum SDKs" are [Qiskit](https://qiskit.org/), [Cirq](https://quantumai.google/cirq), or [Pennylane](https://pennylane.ai/). IonQ offers plug-ins and integrations for many SDKs, which enable easier interaction with the IonQ API.
***
#### Shot
A single measurement of a given [circuit](#circuit) on a QPU. Given the nature of quantum circuits, many shots are required for an accurate representation of the circuit's output.
***
#### Simulator
A *simulation* of a quantum computer, made available as a backend in our system. Simulators mimic the behavior of quantum computers by following the rules of quantum mechanics--giving users the ability to test circuits without running them directly on a QPU.
***
#### Solver
A packaged tool that takes in an input, creates a circuit, runs it on a QPU, evaluates the results, and optimizes the circuit until a goal is hit.
***
#### QPU
A quantum computer, made available as a backend in our system. In IonQ's case, one that [employs individual atoms an ion trap](https://ionq.com/technology) as qubits.
***
## Administrative Concepts
#### Organization
An group consisting of many users and projects that can be granted QPU access through a contract. [Learn more](/user-manual/organizations).
***
#### Project
Projects allow multiple users to submit jobs to a single, shared place. Users can be added to a project by an organization owner, and when jobs are submitted, they must be submitted to a specific project. Organization owners can set a [budget](#budget) on each project. [Learn more](/user-manual/projects).
***
#### User
An individual user's account in an organization which is assigned a specific role that defines what permissions they have. [Learn more](/user-manual/accounts).
***
#### User Role
A set of permissions assigned to a given user. Currently the roles can be:
* **Users:** A normal user.
* **Organization owner:** Can manage projects and users in the organization.
***
## Billing Concepts
#### Allocation
An amount of access time to a QPU (or other system) granted through a contract from which [job usage](#usage) is deducted. Allocations are also evaluated as part of [job queueing](#job-queue) process, and are one determinant of how priority is set.
***
#### Budget
Budgets are spending limits that can be added by an organization owner to a project that, when hit, will prevent further jobs from being submitted. [Learn more](/user-manual/projects#adding-or-changing-a-project-budget).
***
#### Contract
A legal agreement setting the rate, [allocation](#allocation), and other terms for access to IonQ's backends and other systems. Note that a contract is required for access to a QPU; contact [sales@ionq.co](mailto:sales@ionq.co) for more information.
***
#### Cost
Cost represents how much your organization will pay for something. In the case of jobs, this is the amount of [usage](#usage) multiplied by the rate specified in your contract for the backend it was run on.
***
#### Usage
The time it took to run a given job on a backend. Usage is aggregated contextually--for example, how much a [project](#project) "used" would refer to the aggregate usage of all jobs submitted to that project in the given period.
# Introduction
Welcome to the IonQ Quantum Cloud
**The IonQ Quantum Cloud is a platform for optimizing, running and simulating quantum programs.** It combines access to our trapped-ion systems via the Quantum Cloud API with web-based tools for inspecting and understanding your quantum jobs, as well as a powerful, proprietary optimization and compilation pipeline that ensures you're always getting the best out of our hardware.
It also supports the most languages, SDKs and quantum cloud integrations of any quantum hardware provider. Whatever tools or cloud you use for quantum computing, the IonQ Quantum Cloud will allow you to use them with IonQ's high-performance hardware.
***
## The Quantum Cloud Console
The Quantum Cloud Console, available at [cloud.ionq.com](https://cloud.ionq.com), provides a web-based interface for managing your API credentials and interactively exploring the programs you’ve submitted, including their status and results. In this guide, we’ll use it to create an API key and then look at the results of our job once it’s complete.
# Jobs
Jobs are tasks running on IonQ systems, usually containing a circuit to run on a QPU.
Jobs are submitted by users of a [Project](/user-manual/projects) and contain an `input` that tells the backend what to do--such as running a circuit.
***
## Submitting Jobs
Jobs are submitted to our platform [directly via API](/guides/direct-api-submission) or through one of the available [SDKs](/sdks). Typically it's as simple as picking a backend, building a circuit, and submitting that circuit to the backend, such as:
```python
backend = provider.get_backend("aria-1") # Pick a backend...
circuit = QuantumCircuit(2, 2).h(0) # build your circuit...
job = backend.run(circuit, shots=500) # and run it on the backend!
```
For a complete reference to the available options, see our [API reference](/api-reference/v0.3/jobs/create-a-job), or review one of our [SDK guides](/sdks/qiskit/index) for more information and examples.
***
## Job Status
As jobs move through our system, they go through a series of states. This `status` is represented in both the UI and in the API, and will be one of the following values:
| State | Description |
| ----------- | --------------------------------------------------------------------------------------------------------- |
| `ready` | The job has been processed by the platform and is in [queue](/user-manual/platform-systems#queue-manager) |
| `running` | The job is currently running on a backend |
| `completed` | The job has finished running and results are available |
| `canceled` | The job was canceled by the user before it was run |
| `failed` | The job failed due to an error detailed in the response body |
***
## Multi-circuit Jobs
To pass *multiple* circuits within a single job, simply pass the circuits in a list as the `input`, for example:
```bash
{
"input": [
{
"format": "ionq.circuit.v0",
"qubits": 1,
"circuit": [{ "gate": "h", "target": 0 }]
},
{
"format": "ionq.circuit.v0",
"qubits": 1,
"circuit": [{ "gate": "h", "target": 0 }]
},
{
"format": "ionq.circuit.v0",
"qubits": 1,
"circuit": [{ "gate": "h", "target": 0 }]
}
]
}
```
Not all SDKs support multi-circuit job submission. Please see their individual documentation for more details.
# Organizations
A new organization is created when you sign up at [cloud.ionq.com](https://cloud.ionq.com). To join an existing account, you must be invited by an Organization Owner.
Organizations can contain many users, have many [projects](/user-manual/projects), and can be assigned QPU access.
***
## Managing Members
Members of an organization can be either an **Owner** or a **User**.
* **Organization Owners can...**
* Add or remove users from the organization and manage user's roles
* View the aggregate spend of the organization
* View the individual spend of all users in the organization
* Create, archive, and manage the membership and budgets of projects
* View all projects and job data of any project in the organization
* **Organization Users can...**
* View and submit jobs to projects they are a member of
* View the details of jobs inside the project
* View the cost of the project, both in aggregate and per-member spend
The creator of the Organization starts as the first `owner`, and they can add additional organization owners or users as needed.
### Inviting members
On the Organization Settings page, click `Invite member` from the top of the page. Invitations expire after 30 days, and can be re-sent on this page if needed.
When an invite is still pending, it can be revoked or resent as needed from the member list.
Currently, users can only be part of a single organization. To join multiple organizations, you'll need to sign up with a "+" address. For example, `casey@domain.com` could use `casey+org2@domain.com`.
### Changing a member's role
To change a member's role, click on the role dropdown in the member list. Changes are saved as soon as they're made.
### Viewing a member's projects
You can view all the projects an organization member belongs to by selecting the number of the projects in the “projects” column in the organization members list.
### Remove organization member
You can remove an organization member from the organization by selecting a multi action button at the end of the member row in the organization members list. Select the “remove from organization” button.
***
## Spend and Budgets
### View spend
If your organization has paid QPU access, you can view your total organization spend from your organization spend.
![Screenshot of the Organization Settings page, showing the total aggregate spend of the organization and the available budget.](https://mintlify.s3-us-west-1.amazonaws.com/ionq/user-manual/media/organizations-view_spend.png)
### Change cost display
By default, job cost is shown in the cloud console to all users. If you would like to hide this value, you can choose to only display time to users instead. You can do that from the organization settings page. You can always reverse this change.
Note: Making this change will be applied to both the API as well as the cloud console.
\[Include a screenshot of this setting]
### Change budget
At this time, budgets must be managed by IonQ staff. If you would like to increase your budget, please contact your IonQ representative, or reach out to [support@ionq.co](mailto:support@ionq.co).
***
## Settings
### Change organization name
To edit your organization name insert a new organization name and select the “Update organization information” button under the organization name input to save changes.
***
## QPU Access
QPU access is available at the organization level through a contract. To learn more, please contact your IonQ account representative, or reach out to [sales@ionq.co](mailto:sales@ionq.co) to get in touch.
# Platform Systems
An overview of some of the systems that make up the IonQ Quantum Cloud Platform
## Queue Manager
Jobs are managed through a *[fair-share](https://en.wikipedia.org/wiki/Fair-share_scheduling) style*, weighted scheduling system. When a job is submitted, queue manager places it in the appropriate *allocation group* based on its parent organization. As jobs are pulled from the queue to be sent to the QPU, the queue manager cycles through each of those groups over a set duration for each.
![Fair share](https://mintlify.s3-us-west-1.amazonaws.com/ionq/user-manual/media/fair-share-trans.png)
***
## Reservations
Reservations are a period of *exclusive access* to the QPU during a pre-scheduled block of time. These are offered to support large runs of jobs or for timing-sensitive hybrid runs. During this period, the [Queue Manager](#queue-manager) modifies its allocation groups so that it will only retrieve jobs from the organization specified in the reservation configuration.
Reservations are typically scheduled for blocks no-shorter than 1 hour, only available to customers with an existing contract, and can be scheduled by contactin [support@ionq.co](mailto:support@ionq.co).
Braket customers can also make reservations directly through the Braket console. [Learn more](https://docs.aws.amazon.com/braket/latest/developerguide/braket-reservations.html)
***
## **Learning More**
*This list is not exhaustive and our systems evolve constantly. If you have additional questions about our software stack or Platform systems, do not hesitate to reach out [in Slack](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w) or via [support@ionq.co](mailto:support@ionq.co) .*
# Projects
Projects are collaborative workspaces created in an organization to manage teams and resources.
Projects is a new feature and we'd love your feedback! If you questions or suggestions, [please let us know](mailto:support@ionq.co).
## What are projects?
**All jobs are submitted to a project** since all API keys must be attached to one. Anything submitted with that API key will automatically be associated with that project.
**Projects can have many members** added to them by an organization owner. Jobs in a project are visible by all members of that project, meaning its easy to share results and see how much budget is left for the team.
**Only members of a project can see it exists or access the jobs in it.** Only the members that are currently assigned to a project are able to see any data related to it.
**Projects can have a budget** set by an organization owner, allowing them to manage split their larger overall budget out to specific teams or initiatives.
View your available projects on the IonQ Quantum Cloud.
***
## Creating projects
Projects can only be created or managed by [Organization Owners](/user-manual/organizations#roles).
To create a new project, click “Create project” on the [Projects page](https://cloud.ionq.com/projects). When creating a project, you'll be prompted to enter a project `name`, `budget` and `description`.
Project budgets can be set to:
* **Unlimited:** No set budget limit for the project. Users can submit QPU jobs as long as the organization has a remaining budget.
* **Limited:** Constrained by the given dollar amount. Project members can run jobs until the limit is hit for the project.
Budgets, while always configurable, are only applicable to Organizations with QPU access (since Simulator access is free.)
### Personal Projects
When a new account is created, a project named `Personal Project (email@domain.com)` is created as a workspace for the new user. By default, the budget for this project is set to \$0, but like any other project, that budget can be changed and additional users added to it by an organization owner.
If a user is removed from an organization, they lose access to any projects they were a member of, but the jobs they submitted to the projects remain there.
***
## Members
Project members are users that have been added to a project by an organization owner. Members can submit jobs to the project, view the project's current available budget, see other members of the project, and view the results of any jobs that have been submitted.
While org owners can view and manage projects and a project's jobs, they must *add themselves as a member* of a project before they'll be able to create an API key and submit a job to it.
### Adding project members
To add project members navigate to the “members” tab in a project workspace. Select the “Add members” button on the right side of the workspace. When adding a member, you’ll be prompted to select organization members.
Project members need to be added to the organization first. You can learn how to add organization members by heading to invite organization members.
### Tracking total member spend and usage
The Members list on a project shows the aggregated spend (cost) and usage (time) of each member. These values represent the **total** of jobs submitted to this project by this user at any point in time.
![Screenshot of the Projects Members Page tab, showing the spend aggregated per member.](https://mintlify.s3-us-west-1.amazonaws.com/ionq/user-manual/media/projects-view_member_spend.png)
***
## Jobs
### Submitting jobs to a project
When [creating an API key,](/user-manual/accounts#generating-api-keys) you must assign it to a project. Any job that is submitted using that API key will be submitted to that project. Only members of a project can assign an API key to a project, and thus submit jobs to it.
!["yes"](https://mintlify.s3-us-west-1.amazonaws.com/ionq/user-manual/media/projects-create_key.png)
### Viewing jobs in a project
Inside a project, the jobs page shows all of the jobs that have been submitted to the project. All members of a project are able to view any job submitted by any other member of the project.
Job results, including their histogram, can be viewed by clicking on them and selecting `view job details`.
The main [Jobs page](https://cloud.ionq.com/jobs) displays all of your jobs across all of your projects.
### Total cost
At the top of the jobs page, the total project cost or usage is displayed for *all* jobs submitted to the project. This is an aggregation of this value across all org members' jobs submitted at any time.
![Screenshot of the Projects Overview tab, showing the total aggregate job cost.](https://mintlify.s3-us-west-1.amazonaws.com/ionq/user-manual/media/projects-view_cost.png)
If displaying cost is disabled for your organization you should see project usage in % and your jobs usage will be expressed in time.
\[Include a screenshot of the project space, jobs tab with the usage in %]
***
## Settings
To change the project settings navigate to the “settings tab”. You can update project name and project description.
!["tktktk"](https://mintlify.s3-us-west-1.amazonaws.com/ionq/user-manual/media/projects-settings.png)
### Adding or changing a project budget
To set up or change a project budget navigate to the “jobs” tab in a project workspace. Select the “change budget” button next to the project cost tracker. You can choose between limited and unlimited budget options.
### Archiving a project
Archiving a project prevents project members from submitting additional jobs to it, and also cancels any jobs that were currently in queue.
To archive a project navigate to the “settings” tab. Select the “archive this project” button. You can unarchive it at any time from the same location.