Cloud Simulation
Cloud Execution via QoroService
QoroService connects Divi to Qoro’s cloud simulation platform, where jobs are routed to high-performance Maestro simulator backends — including MPS, state vector, and stabilizer simulators.
This is ideal for:
- Large circuits that are too slow for local simulation
- Running on high-performance cloud simulators
- Parallelizing workloads across cloud instances
- Scaling variational algorithms to larger problem sizes
Getting Started
1. Create an Account & Get Your API Token
Visit dash.qoroquantum.net to create an account and manage your API tokens. From the dashboard you can:
- Generate your API token — head to the Token page to activate your token
- Purchase simulation credits — browse available credit packages on the Credits page
- Monitor your jobs — track submitted jobs, credit usage, and execution history
2. Install Divi
pip install qoro-divi3. Configure Your Token
Store your API token in a .env file at the root of your project:
# .env
QORO_API_KEY="your-api-token"⚠️ Important: Make sure
.envis listed in your.gitignoreso you don’t accidentally commit your API key to version control.
Then use it in your code:
from divi.backends import QoroService, JobConfig
# Option 1: Pass the token directly
q_service = QoroService(auth_token="your-api-token", config=JobConfig(shots=5000, qpu_system="qoro_maestro"))
# Option 2: Reads from QORO_API_KEY environment variable automatically
q_service = QoroService(config=JobConfig(shots=5000, qpu_system="qoro_maestro"))4. Use It as a Backend
Any Divi quantum program accepts QoroService as a backend — just swap it in:
# Local simulation
from divi.backends import ParallelSimulator
backend = ParallelSimulator()
# Cloud simulation — same interface, more power
from divi.backends import QoroService, JobConfig
backend = QoroService(config=JobConfig(shots=5000, qpu_system="qoro_maestro"))Examples
Cloud VQE
Run a Variational Quantum Eigensolver for molecular ground-state energy estimation:
import pennylane as qml
from divi.qprog import VQE, HartreeFockAnsatz
from divi.qprog.optimizers import ScipyOptimizer, ScipyMethod
from divi.backends import QoroService, JobConfig
q_service = QoroService(config=JobConfig(shots=5000, qpu_system="qoro_maestro"))
# Define a hydrogen molecule
molecule = qml.qchem.Molecule(
symbols=["H", "H"],
coordinates=[[0.0, 0.0, 0.0], [0.0, 0.0, 0.735]],
)
vqe = VQE(
molecule=molecule,
ansatz=HartreeFockAnsatz(),
optimizer=ScipyOptimizer(ScipyMethod.COBYLA),
max_iterations=10,
backend=q_service,
)
vqe.run()
print(f"Energy: {vqe.best_loss:.4f}")Cloud QAOA
Solve combinatorial optimization problems like MaxCut using QAOA:
from divi.qprog import QAOA, GraphProblem
from divi.qprog.optimizers import MonteCarloOptimizer
from divi.backends import QoroService, JobConfig
import networkx as nx
q_service = QoroService(config=JobConfig(shots=10000, qpu_system="qoro_maestro"))
G = nx.random_regular_graph(3, 20, seed=42)
qaoa = QAOA(
problem=G,
graph_problem=GraphProblem.MAXCUT,
n_layers=2,
optimizer=MonteCarloOptimizer(),
max_iterations=10,
backend=q_service,
)
qaoa.run()
print(f"Solution: {qaoa.solution}")Cloud VQE Sweep
Sweep across molecular bond lengths to map out a potential energy surface:
import pennylane as qml
from divi.qprog import VQEHyperparameterSweep, MoleculeTransformer, HartreeFockAnsatz
from divi.qprog.optimizers import ScipyOptimizer, ScipyMethod
from divi.backends import QoroService, JobConfig
q_service = QoroService(config=JobConfig(shots=5000, qpu_system="qoro_maestro"))
# Define a base hydrogen molecule
base_molecule = qml.qchem.Molecule(
symbols=["H", "H"],
coordinates=[[0.0, 0.0, 0.0], [0.0, 0.0, 0.735]],
)
# Create a transformer that scales the bond length
transformer = MoleculeTransformer(
base_molecule=base_molecule,
bond_modifiers=[0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.5, 1.8, 2.0],
)
sweep = VQEHyperparameterSweep(
ansatze=[HartreeFockAnsatz()],
molecule_transformer=transformer,
optimizer=ScipyOptimizer(ScipyMethod.COBYLA),
max_iterations=20,
backend=q_service,
)
sweep.create_programs()
sweep.run(blocking=True)
(best_ansatz, best_modifier), best_energy = sweep.aggregate_results()
print(f"Best energy: {best_energy:.4f} Ha (ansatz={best_ansatz}, modifier={best_modifier})")Cloud Custom VQA
Run a custom variational quantum algorithm with your own parameterized circuit:
import pennylane as qml
from divi.qprog import CustomVQA
from divi.qprog.optimizers import ScipyOptimizer, ScipyMethod
from divi.backends import QoroService, JobConfig
q_service = QoroService(config=JobConfig(shots=5000, qpu_system="qoro_maestro"))
# Define a parameterized quantum circuit as a QuantumScript
H = qml.Hamiltonian([1.0, 0.5], [qml.PauliZ(0), qml.PauliX(0) @ qml.PauliX(1)])
with qml.queuing.AnnotatedQueue() as q:
qml.RY(0.1, wires=0)
qml.RY(0.2, wires=1)
qml.CNOT(wires=[0, 1])
qml.expval(H)
qscript = qml.tape.QuantumScript.from_queue(q, trainable_params=[0, 1])
custom = CustomVQA(
qscript=qscript,
optimizer=ScipyOptimizer(ScipyMethod.L_BFGS_B),
max_iterations=50,
backend=q_service,
)
custom.run()
print(f"Best energy: {custom.best_loss:.4f}")Features
Expectation Value Support
When using QoroService with the qoro_maestro system, expectation values of your cost Hamiltonian are computed directly on the cloud backend. Instead of sampling bitstrings locally and reconstructing expectation values, Divi sends the Hamiltonian as Pauli operator strings to the cloud, where they are evaluated efficiently. This avoids the overhead of observable grouping and state tomography.
This is enabled automatically for all variational algorithms (VQE, QAOA, CustomVQA, etc.) when the backend supports it. You can also use it directly via submit_circuits by providing your QASM circuit and observables as semicolon-separated Pauli strings:
from divi.backends import QoroService, JobConfig
q_service = QoroService(config=JobConfig(shots=5000, qpu_system="qoro_maestro"))
# A simple 2-qubit QASM circuit
qasm_circuit = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
ry(0.5) q[0];
ry(1.2) q[1];
cx q[0], q[1];
"""
# Submit with Pauli observables — each term is a string of I, X, Y, Z
# e.g. "ZI" measures Z on qubit 0, I on qubit 1
result = q_service.submit_circuits(
circuits={"my_circuit": qasm_circuit},
ham_ops="ZI;IX;XX", # Semicolon-separated Pauli operator strings
)
# Poll until the job completes
q_service.poll_job_status(result, loop_until_complete=True)
# Retrieve the expectation values
result = q_service.get_job_results(result)
print(result.results)If you need to force sampling-based measurement instead, set force_sampling=True in your JobConfig:
q_service = QoroService(config=JobConfig(shots=5000, qpu_system="qoro_maestro", force_sampling=True))Checkpointing
Save and resume long-running cloud jobs. If a cloud execution is interrupted, checkpointing lets you pick up exactly where you left off:
from divi.qprog.checkpointing import CheckpointConfig
qaoa = QAOA(
problem=G,
graph_problem=GraphProblem.MAXCUT,
n_layers=2,
optimizer=ScipyOptimizer(ScipyMethod.COBYLA),
max_iterations=100,
backend=q_service,
)
qaoa.run(checkpoint_config=CheckpointConfig(checkpoint_dir="./checkpoints"))