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

  • Bell's Theorem: CHSH inequality
  • Circuit Diagram
  • Exploring Fundamentals of Quantum Theory
  • Getting Started
  • An IBM Quantum Error Map
  • Connecting to QPU Services
  • Quantum Machine Learning in Phase Space
  • Quantum object abstraction
  • Quantum Object Composition
  • Quantum Optimization
  • Second Quantization Functions
  • Sending Queries to IBM QPUs
  • Tensor Network
  • Time Evolution
  • Fast Gates on a Transmon
  • Quantum Computation

Guides

  • Wolfram Quantum Computation Framework

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

Connecting to QPU Services

OpenQASM: the common language of QPUs
Amazon Braket
IBM Quantum
​
The Wolfram Quantum Framework lets you build, simulate and analyze quantum circuits symbolically and numerically. The same circuit object can also be sent to real quantum processing units (QPUs) hosted in the cloud. This tutorial covers the three pieces you need for that: OpenQASM, the portable text format that QPUs speak; the IBM Quantum platform; and Amazon Braket, which exposes several hardware vendors through a single service.
Everything in the OpenQASM section runs locally with no account. The hardware sections need credentials with the respective provider, and those cells are marked so you can read the tutorial without running them. For help, write to quantum@wolfram.com.
In[1]:=
<<Wolfram`QuantumFramework`

OpenQASM: the common language of QPUs

A quantum circuit built in the Wolfram Language is a symbolic object. To run it on hardware it has to be expressed in a format the device understands, and the de facto standard is OpenQASM. Both IBM and Amazon Braket accept OpenQASM, so it is the bridge between a
QuantumCircuitOperator
and the cloud.
Build a small reference circuit that we reuse throughout: a three-qubit GHZ state
|GHZ〉=
1
2
(|000〉+|111〉)
, followed by a quantum Fourier transform and a measurement of all three qubits.
In[2]:=
qc=
QuantumCircuitOperator
[{"GHZ","Fourier"[3],{1,2,3}}];​​qc["Diagram"]
QuantumQASM
is the single hub for OpenQASM. 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[3]:=
QuantumQASM[qc]
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[4]:=
QuantumCircuitOperator
[QuantumQASM[qc]]qc
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[5]:=
QuantumQASM[qc,"Version"2]

IBM Quantum

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:
In[6]:=
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[7]:=
ibm=ServiceConnect["IBMQuantumPlatform","New",Authentication{"apikey"api}]
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[8]:=
ibm["Backends"]

Inspecting a backend

Before committing a circuit to a device, you can see its live calibration as an error map: the qubit lattice with the
cz
gate error, the static
ZZ
crosstalk, the relaxation time
T
1
, and the readout error painted on at once. This reads only the free metadata endpoints, so it runs no circuit and spends no quantum time.
In[9]:=
ibm["ErrorMap","Backend""ibm_fez"]
The same calibration is available as data through
ibm["DeviceModel","Backend"->"ibm_fez"]
and its per-pair and per-qubit projections (
"CouplingMap"
,
"CZErrors"
,
"ZZ"
,
"ReadoutErrors"
,
"Coherence"
, and the rest), which is how you compare devices before choosing one for
IBMJobSubmit
. For the full picture see
the IBM error map tutorial
.

Building and checking a circuit

Using the circuit
qc
from the previous section, plot its exact output distribution: the noiseless ground truth a QPU run approximates, and the reference we overlay with the hardware counts:
In[10]:=
qc[]["ProbabilityPlot"]
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):
In[11]:=
qc["Qiskit"]["Shots"4096]["ProbabilityPlot"]

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[12]:=
job=IBMJobSubmit[qc,"ibm_fez"]
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[13]:=
job["Status"]
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 the Wolfram Language qubit order:
In[14]:=
qpu=job["Refresh"][]
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[15]:=
job["QuantumSeconds"]

Comparing exact and hardware results

Putting the exact distribution next to the hardware run shows the structure surviving the device noise: the dominant
000
,
001
and
111
outcomes and the near-zero
100
all come through, with the noise flattening the distribution. The hardware values below are
qpu["Probabilities"]
from a recorded
ibm_fez
run:
In[16]:=
exact=N[Values[KeySort[FullSimplify/@qc[]["Probabilities"]]]];​​hardware=Values@KeySort@​​{0,0,0}0.255,{0,0,1}0.197,{0,1,0}0.149,{0,1,1}0.054,​​{1,0,0}0.019,{1,0,1}0.035,{1,1,0}0.120,{1,1,1}0.171;​​BarChart[Transpose[{exact,hardware}],​​ChartLegends{"Exact WL","QPU ibm_fez"},​​ChartLabels{Tuples[{0,1},3],None},​​FrameTrue,AspectRatio1/2]
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.

Amazon Braket

Amazon Braket is a quantum computing service on
Amazon Web Services
(AWS). Unlike IBM, which exposes its own superconducting devices, Braket fronts several vendors (IonQ, Rigetti, QuEra and others) and on-demand simulators through one API, which makes it convenient for comparing technologies side by side. The Wolfram Language reaches it through the standard AWS service connection.

Connecting to AWS

Connect to AWS with your credentials (access key ID and secret access key); see the workflow
Authenticate with Amazon Web Services
for details on storing them:
In[17]:=
aws=ServiceConnect["AWS","New"]
Braket writes every task result to an S3 bucket, so you reach two AWS services through the connection: S3 for storage and Braket for the quantum tasks. If you do not have an S3 bucket yet,
create one
first:
In[18]:=
s3=ServiceExecute[aws,"GetService",{"Name""S3"}];​​braket=ServiceExecute[aws,"GetService",{"Name""Braket"}];

Finding devices

List the available devices, both simulators and QPUs:
In[19]:=
devices=braket["SearchDevices","Filters"{}]["Devices",All];​​devices[All,{"DeviceName","DeviceType","DeviceStatus"}]
Select one on-demand simulator (Amazon's state-vector simulator SV1) and one QPU by their Amazon Resource Names (ARNs), decoding each device's capabilities from JSON:
In[20]:=
sim=devices[​​SelectFirst[#DeviceArn"arn:aws:braket:::device/quantum-simulator/amazon/sv1"&],​​MapAt[ImportString[#,"RawJSON"]&,"DeviceCapabilities"]];​​qpu=devices[​​SelectFirst[StringContainsQ[#DeviceArn,"ionq"]&],​​MapAt[ImportString[#,"RawJSON"]&,"DeviceCapabilities"]];

Preparing the circuit as OpenQASM

Build the circuit, then express it as OpenQASM for submission. Braket accepts OpenQASM, so the native
QuantumQASM
output is a good way to inspect exactly what will be sent:
In[21]:=
qc=
QuantumCircuitOperator
[{"GHZ","Fourier"[3],{1,2,3}}];​​QuantumQASM[qc]
For submission to a specific Braket backend it is safest to render the device dialect of OpenQASM, which maps the circuit onto that vendor's supported gate set. Passing
"Provider"->"AWSBraket"
to the Qiskit interface does this conversion (it needs the Python Qiskit and Braket providers configured):
In[22]:=
qasm=qc["Qiskit"]["QASM","Provider""AWSBraket"];

Submitting a quantum task

A Braket job is a "quantum task". Submit the OpenQASM as the task action, naming the device ARN, the destination S3 bucket and the number of shots. Run it once on the simulator:
In[23]:=
taskSV1=braket["CreateQuantumTask",​​"DeviceArn"sim["DeviceArn"],​​"Shots"100,​​"Action"braketSchemaHeadername"braket.ir.openqasm.program",version"1",sourceqasm,​​"OutputS3Bucket""amazon-braket-my-bucket","OutputS3KeyPrefix""tasks",​​"RequestRegion""us-east-1"]
The same call against the QPU ARN queues a hardware run:
In[24]:=
taskIonQ=braket["CreateQuantumTask",​​"DeviceArn"qpu["DeviceArn"],​​"Shots"100,​​"Action"braketSchemaHeadername"braket.ir.openqasm.program",version"1",sourceqasm,​​"OutputS3Bucket""amazon-braket-my-bucket","OutputS3KeyPrefix""tasks",​​"RequestRegion""us-east-1"]

Checking status and fetching results

Query a task by its ARN. The simulator usually completes in seconds; a QPU task may sit
QUEUED
until the device is available:
In[25]:=
braket["GetQuantumTask","QuantumTaskArn"taskSV1["quantumTaskArn"],"RequestRegion""us-east-1"]["status"]
The result is written to S3. Locate its directory, then read
results.json
from the bucket:
In[26]:=
outputPath=braket["GetQuantumTask",​​"QuantumTaskArn"taskSV1["quantumTaskArn"],"RequestRegion""us-east-1"]["outputS3Directory"];​​results=ImportByteArray[​​s3["GetObject","Bucket""amazon-braket-my-bucket",​​"Key"FileNameJoin[{outputPath,"results.json"}],"RequestRegion""us-east-1"]["Body"],​​"RawJSON"];

Comparing exact and simulator results

© 2026 Wolfram. All rights reserved.

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