How to run circuits on Fire Opal

Learning the basics of running circuits with Fire Opal

If you want to run a circuit or a list of circuits, Fire Opal's execute function is designed for straightforward job submission to quantum hardware. As your workload scales, and you need to run several hundred circuits at once or multiple consecutive circuits, you can use the iterate function, which is optimized for handling several jobs or executing multiple consecutive circuits, such as variational or batch workflows. The iterate function minimizes preprocessing and queuing delays when jobs are submitted in immediate succession.

In this user guide, you will learn how to run circuits using both the execute and iterate functions.

1. Imports and initialization

To run these examples, you'll first need to set up your account information for Fire Opal and your hardware provider.

1.1 Fire Opal import and initialization

import fireopal as fo
# Replace "YOUR_QCTRL_API_KEY" with your API key, which you can find at https://accounts.q-ctrl.com/security
api_key = "YOUR_QCTRL_API_KEY"
fo.authenticate_qctrl_account(api_key=api_key)

1.2 IBM Quantum import and initialization

If you are using an IBM Quantum device, first you will need to setup your IBM account, then import the required libraries for this user guide.

from qiskit import QuantumCircuit, qasm3
from qiskit.circuit import Parameter

You can access devices on IBM Quantum via Fire Opal by signing up for an IBM Quantum account and using your token and credentials to authenticate.

# Insert your token and instance information
ibm_token = "YOUR_IBMQ_TOKEN"
hub = "ibm-q"
group = "open"
project = "main"

# Create your credentials dictionary hardware platform authentication
credentials = fo.credentials.make_credentials_for_ibmq(
    token=ibm_token, hub=hub, group=group, project=project
)

1.3 IonQ through Amazon Braket import and initialization

If you are using an IonQ device, first you will need to setup your AWS Braket environment, then import the required libraries for this user guide.

from braket.circuits.serialization import IRType
from braket.circuits import Circuit
from braket.aws import AwsDevice

On Amazon Braket, you can use the function make_credentials_for_braket to generate the credentials dictionary needed to execute jobs.

arn = "your_role_arn"
credentials = fo.credentials.make_credentials_for_braket(arn=arn)

2. Running a single job in Fire Opal

The following entanglement circuit demonstrates a basic example of how to code and run a job using the execute function, this function is limited to 300 circuits per batch.

2.1 Submitting a circuit with execute on IBM Quantum

# Create a basic circuit with a Hadamard and a CNOT gate
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
qc.draw("mpl")

Be sure to choose a backend and replace "desired_backend" with the target name.

# Define shots and desired backend (replace "desired_backend" with your backend)
shot_count = 1024
backend_name = "desired_backend"
# Run the circuit with the execute function
fire_opal_job = fo.execute(
    circuits=[qasm3.dumps(qc)],
    shot_count=shot_count,
    credentials=credentials,
    backend_name=backend_name,
)
fire_opal_job.result()

2.2 Submitting a circuit with execute on IonQ

# Create a basic circuit with a Hadamard and a CNOT gate
qc = """
OPENQASM 3.0;
include "stdgates.inc";
bit[2] b;
qubit[2] q;
h q[0];
cx q[0], q[1];
b[0] = measure q[0];
b[1] = measure q[1];
"""
circuit = Circuit.from_ir(qc)
print(circuit)

Use the function show_supported_devices to list the devices that are supported by Fire Opal and accessible to you, and choose a backend device.

supported_devices = fo.show_supported_devices(credentials=credentials)[
    "supported_devices"
]
for name in supported_devices:
    print(name)
# Enter your desired IonQ backend here or select one with a small queue
shot_count = 1024
backend_name = "desired_backend"
print(f"Will run on backend: {backend_name}")
fire_opal_job = fo.execute(
    circuits=[qc],
    shot_count=shot_count,
    credentials=credentials,
    backend_name=backend_name,
)
fire_opal_result = fire_opal_job.result()

3. Running multiple jobs in Fire Opal

The following code demonstrates a basic example of using iterate to submit multiple jobs on IBM Quantum. You can also refer to more in-depth guides on using iterate to run batch workloads and variational algorithms.

# Creating a parameterized circuit
from qiskit.circuit import Parameter

angle = Parameter("alpha")
param_qc = QuantumCircuit(1)
param_qc.rx(angle, 0)
param_qc.measure_all()
param_qc.draw("mpl")
# Generate sets of random values for the parameters
random_values = np.random.rand(500, 2)
parameter_dicts = [
    {param.name: val for param, val in zip(param_qc.parameters, values)}
    for values in random_values
]

# Split the dictionary of parameters to account for the max job size.
max_size = 300
result_arrays = np.array_split(
    parameter_dicts, np.ceil(len(parameter_dicts) / max_size)
)
# Define the backend (replace "desired_backend" with your backend)
backend_name = "desired_backend"
# Submit jobs for each list of parameters
jobs = []
for param_array in result_arrays:
    fire_opal_job = fo.iterate(
        circuits=[qasm3.dumps(param_qc)],
        shot_count=1024,
        credentials=credentials,
        backend_name=backend_name,
        parameters=param_array.tolist(),
    )
    jobs.append(fire_opal_job)
results = []
for job in jobs:
    results.append(job.result())

You can use the iterate function to bypass the limit of 300 circuits from the execute function, however, this will initiate a session on IBM Quantum, which may incur in additional costs. If your workflow does not involve dependent iterations, an alternative is to split your circuits into batches of 300.

Was this useful?

cta background

New to Fire Opal?

Get access to everything you need to automate and optimize quantum hardware performance at scale.