rqm-circuits
Canonical external circuit IR for the RQM Technologies quantum software stack.
What is rqm-circuits?
rqm-circuits is the single source-of-truth wire format for API and Studio
traffic in the RQM Technologies quantum software stack. It defines the canonical
circuit object model that sits between the quaternion math layer and the internal
optimization engine.
Architecture
rqm-core – quaternion/math foundation
rqm-circuits – canonical external circuit IR ← you are here
rqm-compiler – internal optimization / canonicalization engine
rqm-qiskit – Qiskit translation/execution bridge
rqm-braket – Amazon Braket translation/execution bridge
rqm-api – hosted API (accepts rqm-circuits JSON payloads)
Studio – visual circuit editor (emits rqm-circuits JSON payloads)
Key roles:
rqm-circuits= canonical external circuit IR. API payloads and Studio traffic userqm-circuitsas the wire format. The JSON representation is versioned and stable.rqm-compiler= internal engine. Compiler descriptors are internal; they are not the public API payload.rqm-circuitsis lightweight and backend-neutral: no dependency on Qiskit, Braket, orrqm-compiler.
What it is NOT
- Not a backend adapter
- Not a transpiler to Qiskit / Braket / PennyLane
- Not a simulator
- Not a quaternion math library (
rqm-corehandles that) - Not the compiler's internal IR (
rqm-compilerhas its own descriptor types)
Quaternion connection
Every single-qubit SU(2) gate can be represented exactly as a unit quaternion
q = cos(θ/2) + u·sin(θ/2)
where u is the unit pure-imaginary quaternion (rotation axis) and θ is the
physical Bloch-sphere rotation angle. rqm-circuits annotates each standard
gate with its quaternion form (gate.quaternion_form) as an informational field.
The mathematical evaluation of those forms lives in rqm-core.
Rx(angle) → q = cos(angle/2) + i·sin(angle/2)
Ry(angle) → q = cos(angle/2) + j·sin(angle/2)
Rz(angle) → q = cos(angle/2) + k·sin(angle/2)
H → q = (i+k)/√2 (π-rotation about (x̂+ẑ)/√2)
X → q = i (π-rotation about x̂)
Y → q = j (π-rotation about ŷ)
Z → q = k (π-rotation about ẑ)
phaseshift(angle) has matrix diag(1, exp(i·angle)); its quaternion metadata
uses the determinant-one Rz(angle) representative, which is equivalent up to
global phase.
The universal single-qubit gate u1q is parameterised directly by the unit
quaternion components (w, x, y, z):
u1q(w, x, y, z) → q = w + xi + yj + zk (|q| = 1)
Standard two-qubit interaction rotations use the same half-angle convention:
c = Circuit(num_qubits=2)
c.rxx(0.25, 0, 1)
c.ryy(0.50, 0, 1)
c.rzz(0.75, 0, 1)
Their matrices are exp[-i·angle·P/2] for P = X⊗X, Y⊗Y, or Z⊗Z.
These families are entangling-capable, but a nonzero angle—especially for
rzz—does not imply that every input state becomes entangled.
Standard-Compatible Quaternion Coordinates
A complete quaternion and a complete conventional complex/SU(2) or matrix representation carry the same transformation information. RQM uses quaternions because they make ordered rotation composition, inverses, normalization, sign handling, residuals, canonicalization, and lowering explicit in one structured coordinate system.
Any claimed benefit must come from a measured implementation or workflow—not from additional physics or information in the representation. This package does not claim unique measurement, tomography, hardware-error, compression, or universal compiler advantages.
Install
pip install rqm-circuits
Or for development:
git clone https://github.com/RQM-Technologies-dev/rqm-circuits.git
cd rqm-circuits
pip install -e ".[dev]"
Quick start
Bell circuit
from rqm_circuits import Circuit, make_instruction
# Create a 2-qubit Bell circuit
c = Circuit(num_qubits=2, name="bell")
c.add(make_instruction("h", targets=[0]))
# cx: supply the control qubit via controls=, the target via targets=
c.add(make_instruction("cx", targets=[1], controls=[0]))
print(c.summary())
# Circuit 'bell': 2 qubit(s), 0 clbit(s), 2 instruction(s)
# [ 0] h q[0]
# [ 1] cx ctrl:q[0] q[1]
GHZ circuit
from rqm_circuits import Circuit, make_instruction
n = 3
c = Circuit(num_qubits=n, name="ghz")
c.add(make_instruction("h", [0]))
for i in range(1, n):
c.add(make_instruction("cx", targets=[i], controls=[0]))
Rotation gate with a parameter
import math
from rqm_circuits import Circuit, make_instruction, Parameter
c = Circuit(num_qubits=1, name="rotation")
# Canonical parameter name for all rotation gates is "angle"
c.add(make_instruction("rx", targets=[0], params=[Parameter("angle", value=math.pi / 2)]))
Phase-shift gate
from rqm_circuits import Circuit, make_instruction, Parameter
c = Circuit(num_qubits=1)
c.add(make_instruction("phaseshift", targets=[0], params=[Parameter("angle", value=0.5)]))
Universal single-qubit gate (u1q)
import math
from rqm_circuits import Circuit, make_instruction, Parameter
# Hadamard expressed as a unit quaternion
norm = 1.0 / math.sqrt(2)
c = Circuit(num_qubits=1)
c.add(make_instruction(
"u1q", targets=[0],
params=[
Parameter("w", value=0.0),
Parameter("x", value=norm),
Parameter("y", value=0.0),
Parameter("z", value=norm),
],
))
Symbolic (unbound) parameter
c = Circuit(num_qubits=1)
c.add(make_instruction("rz", targets=[0], params=[Parameter("angle")]))
from rqm_circuits import is_parametric
print(is_parametric(c)) # True
Measurement
c = Circuit(num_qubits=1, num_clbits=1)
c.add(make_instruction("x", targets=[0]))
c.add(make_instruction("measure", targets=[0], clbits=[0]))
JSON serialization
rqm-circuits is designed as an API-ready IR layer. Every circuit serializes
to a clean, deterministic JSON payload (schema version "0.2").
from rqm_circuits import Circuit, make_instruction
c = Circuit(num_qubits=2, name="bell")
c.add(make_instruction("h", [0]))
c.add(make_instruction("cx", targets=[1], controls=[0]))
# Serialize
json_str = c.to_json()
print(json_str)
# Deserialize
c2 = Circuit.from_json(json_str)
assert c == c2
Example JSON output:
{
"instructions": [
{
"gate": {
"arity": 1,
"categories": ["clifford", "single_qubit"],
"description": "Hadamard gate. π-rotation about the (x+z)/√2 axis.",
"name": "h",
"num_params": 0,
"quaternion_form": "q = (i+k)/√2 (axis = (x̂+ẑ)/√2, angle = π)"
},
"targets": [{"index": 0, "type": "qubit"}]
},
{
"controls": [{"index": 0, "type": "qubit"}],
"gate": {
"arity": 1,
"categories": ["clifford", "two_qubit"],
"description": "Controlled-X (CNOT) gate. One control qubit, one target qubit.",
"name": "cx",
"num_controls": 1,
"num_params": 0
},
"targets": [{"index": 1, "type": "qubit"}]
}
],
"name": "bell",
"num_qubits": 2,
"schema_version": "0.2"
}
Schema versioning
| Version | Description |
|---|---|
"0.1" |
Legacy. Controlled gates encoded as arity-2 with both qubits in targets. |
"0.2" |
Current. Controlled gates use arity=1, num_controls=1, explicit controls list. Gates include phaseshift, u1q, rxx, ryy, rzz. Canonical rotation param name "angle". |
Schema "0.1" payloads are accepted on ingestion and transparently normalized.
Adding the Pauli-pair rotations is backward-compatible, so no existing payload
shape or accepted schema version changes.
IR analysis helpers
from rqm_circuits import (
circuit_depth,
gate_counts,
has_measurements,
is_parametric,
qubit_usage,
filter_by_category,
GateCategory,
)
print(circuit_depth(c)) # 2
print(gate_counts(c)) # {'cx': 1, 'h': 1}
print(has_measurements(c)) # False
print(is_parametric(c)) # False
print(qubit_usage(c)) # {0: [0, 1], 1: [1]}
Standard gate set
| Gate | Arity | Controls | Params | Param names | Category | Quaternion form |
|---|---|---|---|---|---|---|
i |
1 | 0 | 0 | — | Clifford | q = 1 |
x |
1 | 0 | 0 | — | Clifford | q = i |
y |
1 | 0 | 0 | — | Clifford | q = j |
z |
1 | 0 | 0 | — | Clifford | q = k |
h |
1 | 0 | 0 | — | Clifford | q = (i+k)/√2 |
s |
1 | 0 | 0 | — | Clifford | q = cos(π/4) + k·sin(π/4) |
t |
1 | 0 | 0 | — | Non-Clifford | q = cos(π/8) + k·sin(π/8) |
rx |
1 | 0 | 1 | angle |
Rotation | q = cos(angle/2) + i·sin(angle/2) |
ry |
1 | 0 | 1 | angle |
Rotation | q = cos(angle/2) + j·sin(angle/2) |
rz |
1 | 0 | 1 | angle |
Rotation | q = cos(angle/2) + k·sin(angle/2) |
rxx |
2 | 0 | 1 | angle |
Rotation, two-qubit, entangling-capable | exp[-i angle XX/2] |
ryy |
2 | 0 | 1 | angle |
Rotation, two-qubit, entangling-capable | exp[-i angle YY/2] |
rzz |
2 | 0 | 1 | angle |
Rotation, two-qubit, entangling-capable | exp[-i angle ZZ/2] |
phaseshift |
1 | 0 | 1 | angle |
Rotation | q = cos(angle/2) + k·sin(angle/2) (up to global phase) |
u1q |
1 | 0 | 4 | w,x,y,z |
— | q = w + xi + yj + zk |
cx |
1 | 1 | 0 | — | Clifford | — |
cy |
1 | 1 | 0 | — | Clifford | — |
cz |
1 | 1 | 0 | — | Clifford | — |
swap |
2 | 0 | 0 | — | Clifford | — |
iswap |
2 | 0 | 0 | — | — | — |
measure |
1 | 0 | 0 | — | Measurement | — |
barrier |
* | 0 | 0 | — | Directive | — |
Controlled gates (
cx,cy,cz): supply the control qubit viacontrols=[{"index": ctrl}]and the target qubit viatargets=[{"index": tgt}]. The legacy encoding (both qubits intargets, arity=2) is still accepted on ingestion for schema"0.1"backward compatibility.
Rotation gates (
rx,ry,rz,phaseshift,rxx,ryy,rzz): the canonical parameter name is"angle". Legacy names"theta"and"phi"are silently normalized to"angle"on ingestion.
Package layout
src/rqm_circuits/
__init__.py Public API surface
circuit.py Circuit class
gates.py Gate definitions + standard registry
instructions.py Instruction model + make_instruction()
registers.py QubitRef / ClassicalBitRef
params.py Parameter (concrete + symbolic)
validators.py Validation rules
serialization.py JSON helpers + schema versioning
ir.py IR analysis utilities
errors.py Custom exceptions
types.py Type aliases and enumerations
schema.py JSON Schema + TypedDict definitions
tests/
test_circuit.py
test_gates.py
test_serialization.py
test_validation.py
test_schema.py
test_new_features.py
Error handling
All errors are structured and human-readable:
| Exception | When raised |
|---|---|
CircuitValidationError |
Invalid qubit indices, circuit structure, wrong clbit usage |
InstructionError |
Wrong arity, parameter count/name, duplicate targets, missing controls |
GateDefinitionError |
Unknown gate, invalid gate definition |
SerializationError |
Missing fields, wrong schema version, bad JSON |
Breaking changes (schema 0.1 → 0.2)
| Change | Schema 0.1 | Schema 0.2 |
|---|---|---|
cx/cy/cz arity |
2 (both qubits in targets) |
1 (target in targets, control in controls) |
| Rotation param name | "theta" or "phi" |
"angle" (legacy normalized on ingestion) |
| New gates | — | phaseshift, u1q |
Gate fields |
name, arity, num_params |
+ num_controls, param_names |
Schema "0.1" payloads remain accepted on ingestion; they are transparently
normalized to the "0.2" internal representation.
Development
pip install -e ".[dev]"
pytest
License
Apache License 2.0 — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rqm_circuits-0.2.1.tar.gz.
File metadata
- Download URL: rqm_circuits-0.2.1.tar.gz
- Upload date:
- Size: 49.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce01532219153607aa37502c720ac2df8014ba865cd8d6d873be5cfe15bc359b
|
|
| MD5 |
fde7bbc08d56873d4d3364d9b0fe0238
|
|
| BLAKE2b-256 |
0c58cab611448b6c3aa7f38c19d08a89d0b9268b56f5330c2c6d48db70af8cf7
|
Provenance
The following attestation bundles were made for rqm_circuits-0.2.1.tar.gz:
Publisher:
publish.yml on RQM-Technologies-dev/rqm-circuits
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rqm_circuits-0.2.1.tar.gz -
Subject digest:
ce01532219153607aa37502c720ac2df8014ba865cd8d6d873be5cfe15bc359b - Sigstore transparency entry: 2278989258
- Sigstore integration time:
-
Permalink:
RQM-Technologies-dev/rqm-circuits@4032265fd0c6672cfb188b600d583b8be98eebfc -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/RQM-Technologies-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4032265fd0c6672cfb188b600d583b8be98eebfc -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file rqm_circuits-0.2.1-py3-none-any.whl.
File metadata
- Download URL: rqm_circuits-0.2.1-py3-none-any.whl
- Upload date:
- Size: 40.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e8c367cc5f2374435631ab10a8837b100ac89bccb0a39801d2912cf14aadd3b
|
|
| MD5 |
df862f2d3fc3ae70bc1bf148d103f736
|
|
| BLAKE2b-256 |
452922aca051119b62b74e2edb6950a63edec1ff7302c968e422b9148bc4d717
|
Provenance
The following attestation bundles were made for rqm_circuits-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on RQM-Technologies-dev/rqm-circuits
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rqm_circuits-0.2.1-py3-none-any.whl -
Subject digest:
0e8c367cc5f2374435631ab10a8837b100ac89bccb0a39801d2912cf14aadd3b - Sigstore transparency entry: 2278989295
- Sigstore integration time:
-
Permalink:
RQM-Technologies-dev/rqm-circuits@4032265fd0c6672cfb188b600d583b8be98eebfc -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/RQM-Technologies-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4032265fd0c6672cfb188b600d583b8be98eebfc -
Trigger Event:
workflow_dispatch
-
Statement type: