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:

K0=13r1q4σ0K_0 = \sqrt{1 - \frac{3r_{1q}}{4}}\sigma_0

Ki=r1q4σiK_i = \sqrt{\frac{r_{1q}}{4}}\sigma_i, where σk{k=1,2,3}\sigma_{k\{k=1,2,3\}} are Pauli matrices and σ0\sigma_0 is an identity.

Similarly, two-qubit Kraus operators are:

K00=115r2q16σ0σ0K_{00} = \sqrt{1 - \frac{15r_{2q}}{16}}\sigma_0 \otimes \sigma_0

Kij=r2q16σiσjK_{ij} = \sqrt{\frac{r_{2q}}{16}}\sigma_i \otimes \sigma_j, where σk{k=1,2,3}\sigma_{k\{k=1,2,3\}} are Pauli matrices and σ0\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:

Systemr1qr_{1q}r2qr_{2q}
Aria 10.00050.0133
Aria 20.00065733333333333320.01856
Forte 10.00026666666666666670.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 and previous characterization results are also available via the IonQ API.

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 000000000\ket{000000000} and 111111111\ket{111111111}.

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

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

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 2312^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, it will not be optimized or modified before simulation.

Noisy simulation currently doesn’t include debiasing, our default error mitigation strategy. Future versions of our simulator may implement this feature.

API example

When submitting a job via the API, 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, 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).

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().

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}}.

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 [email protected] 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 [email protected] or join our Slack community 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!