Skip to main content

rqm-circuits

Canonical external circuit IR for the RQM Technologies quantum software stack.

PyPI Python 3.11+ License: Apache 2.0 CI


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 use rqm-circuits as 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-circuits is lightweight and backend-neutral: no dependency on Qiskit, Braket, or rqm-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-core handles that)
  • Not the compiler's internal IR (rqm-compiler has 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 via controls=[{"index": ctrl}] and the target qubit via targets=[{"index": tgt}]. The legacy encoding (both qubits in targets, 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.

Metadata

Release files for rqm-circuits 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rqm-circuits 0.2.1
File Size Uploaded
rqm_circuits-0.2.1.tar.gz 49.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rqm-circuits 0.2.1
File Interpreter ABI Platform
rqm_circuits-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 90.6 kB

Release files / rqm_circuits-0.2.1.tar.gz

Download URL rqm_circuits-0.2.1.tar.gz
Size 49.9 kB
Tags Source
SHA-256 checksum
How to use checksums
ce01532219153607aa37502c720ac2df8014ba865cd8d6d873be5cfe15bc359b
BLAKE2b-256 checksum
How to use checksums
0c58cab611448b6c3aa7f38c19d08a89d0b9268b56f5330c2c6d48db70af8cf7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release files / rqm_circuits-0.2.1-py3-none-any.whl

Download URL rqm_circuits-0.2.1-py3-none-any.whl
Size 40.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0e8c367cc5f2374435631ab10a8837b100ac89bccb0a39801d2912cf14aadd3b
BLAKE2b-256 checksum
How to use checksums
452922aca051119b62b74e2edb6950a63edec1ff7302c968e422b9148bc4d717
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page