Architecture

This advanced reference is for contributors and for users who inspect dialects, passes, or intermediate representations. For the Python interface, start with Getting started and the use cases.

CUDA-Q Logical has one user surface over four semantic stages, orthogonal analysis facets, and one primary MLIR dialect family per stage. This page walks you through the whole machine: the dialect stack, the artifact model, the ownership contract, the compile pipeline, and the verification layers that hold it together.

The dialect stack

Each semantic stage owns one primary representation family, and the passes that convert between families are the canonical compiler lowerings. Analysis facets are ops and results inside the owning representation, not extra semantic stages.

The four stage dialects with their responsibilities, lowerings, estimators, and emission boundaries.

One primary representation family per stage. The named passes on the arrows are the canonical lowerings; the green strip summarizes estimation and emission products.

The division of labor is strict. qlx (P0) may not mention a machine or a code. lvm (P1) binds values to machine spaces and slots but does not choose codes. fabric (P2) is the QEC semantic hub: codes, encodings, verified gadgets, protocols, and the static resource evidence derived from them. phys (P3) binds those realizations to physical resources, native events, routes, and schedules.

The semantic spine and its facets

Stages describe semantic commitment: a later stage must discharge the intent its earlier stages left open, and each transition produces immutable evidence instead of silently filling in missing physics.

The P0, P1, P2, and P3 stage boxes with their facets and consumers attached orthogonally.

The semantic spine. Facets (pink) attach to immutable stage roots; consumers (green) sit orthogonal to the spine and read the verified stage they need.

Facets attach independently verified facts to stage roots (cudaq.logical.stages.Facet). P2 facets include QEC_SPEC, QEC_REALIZATION, PROTOCOL_NETWORK, and PATCH_GRAPH; physical lowering and scheduling attach their own. A build reports the ones it carries, so cudaq.logical.stages.PROTOCOL_NETWORK in p2.facets is the way to ask. Estimate results attach the same way: typed records naming their producer, source, and evidence.

Definitions versus builds

Decorators create reusable definitions:

  • @cudaq.logical.program defines an executable application kernel;

  • @cudaq.logical.objective defines reusable ideal behavior to claim against;

  • @cudaq.logical.machine defines logical spaces, capabilities, and capacity;

  • @cudaq.logical.code defines a QEC code as validated data;

  • @cudaq.logical.gadget defines one encoded realization of an objective; and

  • @cudaq.logical.protocol composes resources, rotations, and postselection into a reusable protocol.

(cql above is the shipped alias: import cudaq.logical as cql.)

cudaq.logical.compile traces a definition into an immutable Build; cudaq.logical.compiler.place continues a P0 build into a placed P1 build without retracing Python. Every build serializes and replays exactly: Build.replay(build.serialize()) reproduces it, witness included.

The artifact model

Three clusters of artifacts carry the system’s semantics.

The QEC algebra. You author a @cudaq.logical.code as data — block shape, stabilizer checks, logical operators, distance. CUDA-Q Logical validates it at construction and materializes it into the fabric dialect on demand. Reusable families live in cudaq.logical.codes (Steane, rotated surface, repetition, Reed–Muller 15, bare qubit); cudaq.logical.codes.BareQubit is the honest no-protection boundary used by protocol factories.

The gadget stack. A gadget claims an objective through implements=; an ordinary authored body over typed patches realizes it. Matching compares the body’s derived Clifford action against the claimed objective — a typed contract, not a naming convention. Compilation materializes typed gadget records (fabric-materialize-record-schemas) before verification.

Machines, placement, and builds. A @cudaq.logical.machine declares logical regions with capabilities and capacity; a layered device binds those regions to QEC architectures and physical resources. Placement constraints such as cudaq.logical.architecture.colocate(...) guide the P1 solver. QEC selection produces P2, and physical projection, routing, native legalization, and scheduling produce P3. Builds are immutable: continuing one never mutates it, and every estimate or emission reads a private view.

Data ownership

Logical qubits, encoded patches, and protocol resources are linear owners. Operations consume the incoming owner and return its successor; measurement or an explicit cudaq.logical.discard ends ownership. The IR verifiers reject duplication, stale reuse, and mismatched branch carries — there is no in-place mutation anywhere in the IR.

State machine of a patch's linear ownership from allocation through active execution to terminal readout.

The linear life of a patch: every arrow consumes the incoming owner and produces a successor.

The compile pipeline

cudaq.logical.compiler.pipelines.* presets name the canonical pass sequences. Passes declare the facets they require and provide, so an out-of-order pipeline fails verification instead of guessing:

Preset

Passes

Output

logical()

qlx-normalize-actions, qlx-infer-requirements, qlx-verify-p0

verified P0

placed()

qlx-verify-p0, qlx-place, qlx-to-lvm, lvm-verify-p1

verified P1 + placement witness

qec()

lvm-select, lvm-apply-qec-lowerings, lvm-to-fabric, fabric-materialize-default-encodings, fabric-verify-generated-protocols

verified P2 (realization + protocol network)

physical()

fabric-derive-patch-graph, fabric-map-patches, fabric-to-phys, phys-route, phys-legalize-native-actions, phys-verify-p3

verified P3 physical event graph

clifford_t(precision=…)

qlx-synthesize-rotations, qlx-verify-clifford-t

P0 legalized to positive H/S/T/CX

pbc()

qlx-to-pbc, qlx-verify-pbc, qlx-verify-p0

P0 in Pauli-based-computation form

Definition-level recipes verify the other facets: qec_definitions() (fabric-verify-p2s, provides QEC_SPEC), gadgets() (fabric-verify-p2a, requires QEC_SPEC, provides QEC_REALIZATION), and protocols() (fabric-link-calls, fabric-verify-p2n, provides PROTOCOL_NETWORK). device_stack(profile) verifies an immutable device prefix against its p1, p2, or p3 profile.

Four estimation tiers read verified artifacts without changing their semantic stage. Tier.LOGICAL profiles P0; Tier.STATIC counts a selected P2 network; Tier.ANALYTICAL combines P2 counts with an explicit physical model; and Tier.SCHEDULE authenticates resources and timing from a scheduled P3 graph. Presets are ordinary Pipeline values: insert_after, configure, replace, append, and remove compose them without string surgery.

The P2 patch graph

Topology survives as inspectable evidence before physical lowering. A selected P2 build exposes build.patch_graph: a typed, read-only view (PatchGraphView) of the patch instances and logical interactions the realization implies, derived from canonical fabric IR facts. You can convert the view to NetworkX or render it to PNG when the optional packages are installed. Placement stays code-agnostic at P1, and the interaction structure that a placement implies becomes checkable at P2. P3 then maps those patches to physical resources, routes their interactions, legalizes native events, and records the schedule as separate verified facets.

Verification layers

Three independent layers enforce correctness:

  • Construction: CUDA-Q Logical validates a code definition as you author it — stabilizer shape, logical operators, and distance evidence must agree before a @cudaq.logical.code exists at all.

  • IR verifiers (C++): every stage boundary has a verify pass — qlx-verify-p0, lvm-verify-p1, fabric-verify-p2s / -p2a / -p2n, fabric-verify-machine, and phys-verify-p3, plus the gate-set verifiers qlx-verify-clifford-t and qlx-verify-pbc. Missing or inconsistent evidence fails closed. A Python linear-use analysis (compiler/linearity.py) and strict link completeness (compiler/link_check.py) back them on the authoring side.

  • Semantic verification: the analysis derives a gadget’s Clifford action from its body and compares it against the claimed objective (cudaq.logical.gadgets.analysis.clifford_action); names never select semantics.

Typed inspection

You inspect builds through typed APIs, not text scraping: build.stage, build.placement, build.definitions, build.calls(symbol), build.protocol_for(objective), build.status, build.synthesis, build.patch_graph, build.to_mlir(), build.content_sha256, and build.serialize() / Build.replay(...). Estimate results are typed the same way: LogicalEstimate, FabricCounts, FabricEstimate, and ScheduleEstimate expose structured results from the four estimation tiers.

Package map

cudaq/logical/
  programs/      programs, objectives, selection intents, typed references
  ops/           canonical executable authoring operations
  types/         canonical values, references, annotations, traced proxies
  algebra/       exact angles, Pauli algebra, Clifford actions, GF(2) values
  codes/         code definitions, encodings, profiles, blocks, families
  gadgets/       gadget definitions, typed records, verification, factories
  protocols/     protocol definitions, builders, resource protocols
  architecture/  logical, QEC, and physical architecture
  devices/       layered devices, resources, regions, reusable local recipes
  compiler/      pipelines, immutable builds, placement, synthesis, topology
  estimate/      logical, static, analytical, and schedule estimation
  experiments/   immutable, reproducible compilation experiments
  algorithms/    algorithm libraries (the Gidney–Ekerå study)
  analysis/      resource-estimation and evidence APIs
  lower/         target lowering and Stim emission
  targets/       built-in CUDA-Q targets (estimator, clifford_t, surface)
  std/           standard resource kinds and objectives (T_STATE, ...)
  qec/           QEC implementation-lowering contracts
  dialects/      generated MLIR Python bindings (qlx, lvm, fabric, phys)
  stages.py      stage and facet enums

Extensibility

You can write the same typed values the decorator surface produces through the lower-level builders. Pipelines are composable values, gate sets are data (GateSet: actions plus legalization passes), and new CUDA-Q targets wrap a backend with Target.from_backend(...). Device- and code-specific libraries are ordinary Python modules, not global registries.

Where to go next

  • The core concepts explain the stage, ownership, and evidence model this architecture implements.

  • The use cases apply the Python interface to codes, placement, synthesis, estimation, and emission.