Wolfram Language Paclet Repository

Community-contributed installable additions to the Wolfram Language

Primary Navigation

    • Cloud & Deployment
    • Core Language & Structure
    • Data Manipulation & Analysis
    • Engineering Data & Computation
    • External Interfaces & Connections
    • Financial Data & Computation
    • Geographic Data & Computation
    • Geometry
    • Graphs & Networks
    • Higher Mathematical Computation
    • Images
    • Knowledge Representation & Natural Language
    • Machine Learning
    • Notebook Documents & Presentation
    • Scientific and Medical Data & Computation
    • Social, Cultural & Linguistic Data
    • Strings & Text
    • Symbolic & Numeric Computation
    • System Operation & Setup
    • Time-Related Computation
    • User Interface Construction
    • Visualization & Graphics
    • Random Paclet
    • Alphabetical List
  • Using Paclets
    • Get Started
    • Download Definition Notebook
  • Learn More about Wolfram Language

QuantumFramework

Tutorials

  • Getting Started
  • Quantum Object Composition

Guides

  • Wolfram Quantum Computation Framework

Tech Notes

  • Bell's Theorem: CHSH inequality
  • Circuit Diagram
  • Exploring Fundamentals of Quantum Theory
  • An IBM Quantum Error Map
  • QPU Service Connection
  • Quantum object abstraction
  • Quantum Optimization
  • Second Quantization Functions
  • Sending Queries to IBM QPUs
  • Tensor Network
  • Quantum Computation

Symbols

  • CliffordChannel
  • EinsteinSummation
  • GraphState
  • IBMJob
  • IBMJobSubmit
  • LocalComplement
  • PauliStabilizer
  • QiskitCircuit
  • QiskitTarget
  • QuantumBasis
  • QuantumChannel
  • QuantumCircuitMultiwayGraph [EXPERIMENTAL]
  • QuantumCircuitOperator
  • QuantumDistance
  • QuantumEntangledQ
  • QuantumEntanglementMonotone
  • QuantumEvolve
  • QuantumMeasurement
  • QuantumMeasurementOperator
  • QuantumMeasurementSimulation
  • QuantumMPS [EXPERIMENTAL]
  • QuantumOperator
  • QuantumPartialTrace
  • QuantumPhaseSpaceTransform
  • QuantumQASM
  • QuantumShortcut [EXPERIMENTAL]
  • QuantumSimilarity
  • QuantumStateEstimate [EXPERIMENTAL]
  • QuantumState
  • QuantumTensorProduct
  • QuantumWignerMICTransform [EXPERIMENTAL]
  • QuantumWignerTransform [EXPERIMENTAL]
  • QuditBasis
  • QuditName
  • StabilizerFrame
  • StabilizerStateQ
Sending Queries to IBM QPUs
In the Wolfram Quantum Framework a quantum circuit is a single symbolic object: you can simulate it exactly and send that same object to a real IBM Quantum processing unit (QPU). This tutorial walks the full path: connect to the IBM Quantum Platform, build and check a circuit, inspect it as OpenQASM (the portable text format QPUs read), submit it to hardware with
IBMJobSubmit
, and hold the hardware counts up against the exact result.
Building and checking run locally with no account. The hardware cells need an IBM Quantum account and are marked so you can read the tutorial without running them. For help, write to quantum@wolfram.com.
In[1]:=
<<Wolfram`QuantumFramework`
Connecting to the IBM Quantum Platform
Create an account at
quantum.cloud.ibm.com
. From the dashboard you need two things: an IAM API key (the long secret string shown once when you create the key, not the key's display name) and the instance CRN (a
crn:v1:…
string identifying your instance).
The API key is a secret and is stored in your encrypted system credential store. The CRN is read from a local symbol that the connection consults when it builds the request headers, so set both before connecting:
api="XXX";​​LocalSymbol["ibm_crn"]="XXX";
Loading the Wolfram Quantum Framework registers the IBM Quantum Platform service automatically, so
ServiceConnect
recognizes the
"IBMQuantumPlatform"
name directly:
In[43]:=
ibm=ServiceConnect["IBMQuantumPlatform","New",Authentication{"apikey"api}]
Out[43]=
ServiceObject
Connection: IBMQuantumPlatform
ID: 180528cf-c780-4…

A connected service object lists the QPUs your account can reach through
"Backends"
. Submitting and retrieving jobs is handled for you by
IBMJobSubmit
and the
IBMJob
handle, shown below. List the available backends:
In[18]:=
ibm["Backends"]
Out[18]=
{ibm_fez,ibm_marrakesh,ibm_kingston}
Building and checking a circuit
Build the circuit in the Wolfram Language first, so you have an exact reference to compare the hardware against. This example prepares a three-qubit GHZ state
|GHZ〉=
1
2
(|000〉+|111〉)
, applies a quantum Fourier transform and measures all three qubits. The transform turns the GHZ entanglement into a definite interference pattern across the eight outcomes, and that structure is exactly what device noise erodes, which makes the circuit a sensitive benchmark:
In[25]:=
qc=
QuantumCircuitOperator
[{"GHZ","Fourier"[3],{1,2,3}}];​​qc["Diagram"]
Out[26]=
Because the circuit is small, plot its exact output distribution: the noiseless ground truth a QPU run approximates, and the reference we overlay with the hardware counts:
In[3]:=
qc[]["ProbabilityPlot"]
Out[3]=
Before spending QPU time, you can sample the circuit on a local noiseless simulator.
QuantumCircuitOperator
's
"Qiskit"
interface runs through a local Qiskit Aer simulator when no provider is given, returning a
QuantumMeasurement
whose statistics converge to the exact distribution as the shot count grows (this needs the Python Qiskit stack):
qc["Qiskit"]["Shots"4096]["ProbabilityPlot"]
Inspecting the circuit as OpenQASM
A QPU does not read a Wolfram Language expression: the circuit is sent as OpenQASM.
QuantumQASM
is the single hub for it. Called on a circuit with no extra arguments it emits OpenQASM 3.0 natively, in pure Wolfram Language with no external dependency, serializing the circuit exactly as built. Measurements become classical-bit assignments:
In[4]:=
QuantumQASM[qc]
Out[4]=
OPENQASM 3.0;qubit[3] q;bit[3] c;U(1.5707963267948966, 0., 3.141592653589793) q[0];ctrl(1) @ negctrl(0) @ U(3.141592653589793, 0., 3.141592653589793) q[0] q[1];ctrl(1) @ negctrl(0) @ U(3.141592653589793, 0., 3.141592653589793) q[1] q[2];U(1.5707963267948966, 0., 3.141592653589793) q[0];ctrl(1) @ negctrl(0) @ U(0., 0., 1.5707963267948966) q[1] q[0];ctrl(1) @ negctrl(0) @ U(0., 0., 0.7853981633974483) q[2] q[0];U(1.5707963267948966, 0., 3.141592653589793) q[1];ctrl(1) @ negctrl(0) @ U(0., 0., 1.5707963267948966) q[2] q[1];U(1.5707963267948966, 0., 3.141592653589793) q[2];swap q[0] q[2];c[0] = measure q[0];c[1] = measure q[1];c[2] = measure q[2];
The hub is also an importer: handing OpenQASM source (or a
.qasm
file) back to
QuantumCircuitOperator
reconstructs the circuit, again with no external dependency. The round trip recovers a circuit equal to the original:
In[5]:=
QuantumCircuitOperator
[QuantumQASM[qc]]qc
Out[5]=
True
OpenQASM 3.0 is the native and recommended target. For older toolchains that still require the legacy
qelib1.inc
gate set, pass
"Version"->2
to emit OpenQASM 2.0. This path renders through Qiskit, so it needs the Python Qiskit stack configured:
In[29]:=
QuantumQASM[qc,"Version"2]
Out[29]=
OPENQASM 2.0;include "qelib1.inc";qreg q[3];creg c[3];h q[0];cx q[0],q[1];cx q[1],q[2];h q[0];cp(pi/2) q[1],q[0];cp(pi/4) q[2],q[0];h q[1];cp(pi/2) q[2],q[1];h q[2];swap q[0],q[2];measure q[0] -> c[0];measure q[1] -> c[1];measure q[2] -> c[2];
Running on hardware
With an active connection,
IBMJobSubmit
is the one call that runs a circuit on a QPU. It transpiles the circuit against the backend's own error-aware
Target
(per-instruction error and duration), submits it through the
SamplerV2
primitive, and returns immediately with an asynchronous
IBMJob
handle while the job sits in the queue. There is no manual OpenQASM, no raw request and no hex decoding of the classical register: the handle carries the per-bit to qubit map captured at transpile time, so results come back already in the Wolfram Language qubit order.
In[27]:=
job=IBMJobSubmit[qc,"ibm_kingston"]
Out[27]=
IBMJob
Status: ● Queued
Backend: ibm_kingston
Job ID: d8q8timgbcrc73f31ut0
Results not available yet.

The handle reports the job's status. Poll it while the job is queued, or pass
"Wait"->True
to
IBMJobSubmit
to block until the job reaches a terminal status:
In[31]:=
job["Status"]
Out[31]=
Queued
Refresh the handle to pull a fresh snapshot from the service. Once the status is
"Completed"
, applying the handle returns the measurement reconstructed from the hardware counts:
In[32]:=
qpu=job["Refresh"][]
Out[32]=
QuantumMeasurement
Target: {1,2,3}
Measurement Outcomes: 8

The same handle keeps every response IBM returns under
"Raw"
and exposes curated accessors on top, so the run's metadata is one query away. For example, the billed quantum runtime:
In[33]:=
job["Refresh"]["QuantumSeconds"]
Out[33]=
3
s
Comparing exact and hardware results
qpu
is the hardware measurement returned by the handle; the circuit
qc
gives the exact, noiseless reference. Take the corresponding Wolfram Language measurement:
In[34]:=
wl=qc[]
Out[34]=
QuantumMeasurement
Target: {1,2,3}
Measurement Outcomes: 8

Putting the two distributions side by side shows how much of the interference pattern survives the hardware. Each
QuantumMeasurement
exposes its outcome distribution through
"Probabilities"
; sorting both by outcome and overlaying them, the dominant
000
,
001
and
111
peaks and the all-but-forbidden
100
still come through, while decoherence erodes the contrast and pulls the rest toward a uniform distribution:
The differences are not in the queries but in device noise: each shot passes through a deep transpiled circuit on superconducting hardware, and the noise varies from job to job.

© 2026 Wolfram. All rights reserved.

  • Legal & Privacy Policy
  • Contact Us
  • WolframAlpha.com
  • WolframCloud.com