Complete LIFT Framework Guide — All Features

LIFTLanguage for Intelligent Frameworks and Technologies Unified intermediate representation for AI and quantum computing.

This document describes every feature of the LIFT framework, numbered and organised by crate. For each feature: what it does, how to use it, and which other features to combine it with.


Table of Contents

  1. General Architecture
  2. lift-core — IR Core
  3. lift-ast — Parsing the .lif Language
  4. lift-tensor — Tensor Operations (110 ops)
  5. lift-quantum — Quantum Gates and Noise (48 gates)
  6. lift-hybrid — Classical-Quantum Hybrid Computation
  7. lift-opt — Optimisation Passes (13 passes)
  8. lift-sim — Simulation and Cost Analysis
  9. lift-predict — Performance Prediction
  10. lift-import — Model Import
  11. lift-export — Backend Export (LLVM, ONNX, QASM)
  12. lift-config — Configuration (.lith)
  13. lift-cli — Command-Line Interface
  14. lift-codegen — Programmatic Model Generation
  15. Combinations and Complete Pipelines
  16. Concrete Examples

1. General Architecture

LIFT is a modular compiler composed of 14 crates organised in layers:

                    ┌──────────┐
                    │ lift-cli │  ← User interface
                    └────┬─────┘
           ┌─────────────┼─────────────┐
           │             │             │
    ┌──────┴──────┐ ┌────┴────┐ ┌──────┴──────┐
    │ lift-import │ │lift-opt │ │ lift-export │
    └──────┬──────┘ └────┬────┘ └──────┬──────┘
           │             │             │
    ┌──────┴──────┐ ┌────┴────┐ ┌──────┴──────┐
    │  lift-ast   │ │lift-sim │ │lift-predict │
    └──────┬──────┘ └────┬────┘ └──────┬──────┘
           │             │             │
    ┌──────┴─────────────┴─────────────┴──────┐
    │              lift-core                    │
    ├──────────┬──────────┬───────────────────┤
    │lift-tensor│lift-quantum│  lift-hybrid    │
    └──────────┴──────────┴───────────────────┘

1.1 Compilation Pipeline

The standard workflow is:

Source (.lif) → Lexer → Parser → IR (SSA) → Verification → Optimisation → Simulation → Export

1.2 File Formats

ExtensionDescription
.lifLIFT IR source code
.lithCompilation configuration
.llLLVM IR export
.onnxONNX export (protobuf text)
.qasmOpenQASM 3.0 export

1.3 Adding LIFT as a Dependency

[dependencies]
lift-core     = "0.4.3"
lift-ast      = "0.4.3"
lift-tensor   = "0.4.3"
lift-quantum  = "0.4.3"
lift-hybrid   = "0.4.3"
lift-opt      = "0.4.3"
lift-sim      = "0.4.3"
lift-predict  = "0.4.3"
lift-import   = "0.4.3"
lift-export   = "0.4.3"
lift-config   = "0.4.3"

2. lift-core — IR Core

The heart of the framework. Provides the SSA (Static Single Assignment) intermediate representation.

2.1 Context — The Central Container

#![allow(unused)]
fn main() {
use lift_core::Context;

let mut ctx = Context::new();
}

The Context stores all IR data: values, operations, blocks, regions, functions, modules, interned strings, and types.

FieldDescriptionUsage
ctx.valuesAll SSA valuesEach operation result is a unique value
ctx.opsAll operationsProgram instructions
ctx.blocksBasic blocksContain sequences of operations
ctx.regionsRegionsContain blocks (function bodies)
ctx.modulesModulesCompilation units
ctx.stringsString interningctx.strings.intern("name")
ctx.type_internerType interningType deduplication

Combine with: All other crates. The Context is the entry point for every pipeline.

2.2 Types — Type System

#![allow(unused)]
fn main() {
use lift_core::types::*;

// Data types
let fp32 = DataType::FP32;
let fp16 = DataType::FP16;
let bf16 = DataType::BF16;
let int8 = DataType::INT8;
let fp64 = DataType::FP64;

// Dimensions (static or symbolic)
let batch = Dimension::Constant(32);
let seq = Dimension::Symbolic("seq_len".to_string());

// Tensor type info
let tensor_info = TensorTypeInfo {
    shape: vec![Dimension::Constant(1), Dimension::Constant(784)],
    dtype: DataType::FP32,
    layout: MemoryLayout::Contiguous,
};

// Size in bytes
let bytes = tensor_info.size_bytes(); // Some(3136) = 1*784*4
}

Available data types:

TypeSizeUsage
FP648 bytesHigh-precision scientific computing
FP324 bytesStandard training
FP162 bytesFast inference
BF162 bytesMixed-precision training (Google Brain)
INT81 bytePost-training quantisation
INT324 bytesIndices, counters
BOOL1 byteMasks

Memory layouts: Contiguous, Strided.

2.3 Attributes — Operation Metadata

#![allow(unused)]
fn main() {
use lift_core::attributes::{Attribute, Attributes};

let mut attrs = Attributes::new();

// Different attribute types
attrs.set("num_heads", Attribute::Integer(8));
attrs.set("dropout", Attribute::Float(0.1));
attrs.set("causal", Attribute::Bool(true));

// Reading
let heads = attrs.get_integer("num_heads"); // Some(8)
let drop = attrs.get_float("dropout");       // Some(0.1)
let causal = attrs.get_bool("causal");       // Some(true)

// Checking
assert!(attrs.contains("num_heads"));
assert_eq!(attrs.len(), 3);

// Iteration
for (key, val) in attrs.iter() {
    println!("{}: {:?}", key, val);
}
}

Combine with: lift-opt (passes read/write attributes), lift-export (exporters read attributes).

2.4 Verifier — Invariant Checking

#![allow(unused)]
fn main() {
use lift_core::verifier;

let ctx = Context::new();
match verifier::verify(&ctx) {
    Ok(()) => println!("IR valid"),
    Err(errors) => {
        for e in &errors {
            eprintln!("Error: {}", e);
        }
    }
}
}

Checks:

  • SSA: every value is defined exactly once
  • Qubit linearity: every qubit is used exactly once
  • Typing: type consistency between operations
  • Structure: blocks, regions, terminators are correct

Combine with: Always use after import and after each optimisation pass.

2.5 Printer — IR Display

#![allow(unused)]
fn main() {
use lift_core::printer::print_ir;

let ctx = Context::new();
let output = print_ir(&ctx);
println!("{}", output);
}

Produces a human-readable textual representation of the IR, useful for debugging.

2.6 Pass Manager

#![allow(unused)]
fn main() {
use lift_core::pass::{PassManager, Pass, PassResult, AnalysisCache};

let mut pm = PassManager::new();
pm.add_pass(Box::new(lift_opt::Canonicalize));
pm.add_pass(Box::new(lift_opt::DeadCodeElimination));
pm.add_pass(Box::new(lift_opt::TensorFusion));

let results = pm.run_all(&mut ctx);
for (name, result) in &results {
    match result {
        PassResult::Changed => println!("{}: changed", name),
        PassResult::Unchanged => println!("{}: unchanged", name),
        PassResult::Error(e) => println!("{}: error: {}", name, e),
        PassResult::RolledBack => println!("{}: rolled back", name),
    }
}
}

Combine with: lift-opt (all 13 passes), lift-config (pass selection via configuration).

2.7 Dialect — Dialect System

#![allow(unused)]
fn main() {
use lift_core::dialect::{DialectRegistry, Dialect};

let registry = DialectRegistry::new();
// The tensor, quantum, hybrid dialects are registered automatically
}

The three LIFT dialects:

  • tensor: tensor operations (tensor.matmul, tensor.relu, etc.)
  • quantum: quantum gates (quantum.h, quantum.cx, etc.)
  • hybrid: hybrid operations (hybrid.encode, hybrid.vqc_layer, etc.)

3. lift-ast — Parsing the .lif Language

3.1 Lexer — Tokenisation

#![allow(unused)]
fn main() {
use lift_ast::Lexer;

let source = r#"
dialect tensor
module @mlp {
    func @forward(%x: tensor<1x784xf32>) -> tensor<1x10xf32> {
        %out = "tensor.relu"(%x) : (tensor<1x784xf32>) -> tensor<1x784xf32>
        return %out
    }
}
"#;

let mut lexer = Lexer::new(source);
let tokens = lexer.tokenize().to_vec();
assert!(lexer.errors().is_empty(), "Lexing errors: {:?}", lexer.errors());
}

3.2 Parser — Syntactic Analysis

#![allow(unused)]
fn main() {
use lift_ast::Parser;

let mut parser = Parser::new(tokens);
let program = parser.parse().expect("Parsing errors");
}

3.3 IrBuilder — IR Construction

#![allow(unused)]
fn main() {
use lift_ast::IrBuilder;
use lift_core::Context;

let mut ctx = Context::new();
let mut builder = IrBuilder::new();
builder.build_program(&mut ctx, &program).expect("IR construction errors");
}

3.4 Complete Parsing Pipeline

#![allow(unused)]
fn main() {
fn load_lif_file(path: &str) -> Result<Context, String> {
    let source = std::fs::read_to_string(path)
        .map_err(|e| format!("Read failed: {}", e))?;

    let mut lexer = Lexer::new(&source);
    let tokens = lexer.tokenize().to_vec();
    if !lexer.errors().is_empty() {
        return Err(format!("Lexer errors: {:?}", lexer.errors()));
    }

    let mut parser = Parser::new(tokens);
    let program = parser.parse().map_err(|e| format!("Parser errors: {:?}", e))?;

    let mut ctx = Context::new();
    let mut builder = IrBuilder::new();
    builder.build_program(&mut ctx, &program)?;
    Ok(ctx)
}
}

Combine with: lift-core (Context), then lift-opt (optimisation), lift-sim (analysis), lift-export (compilation).


4. lift-tensor — Tensor Operations (110 ops)

4.1 Complete Operation List by Category

4.1.1 Basic Arithmetic (5 ops)

#OpIR NameInputsDescription
1Addtensor.add2Element-wise addition
2Subtensor.sub2Subtraction
3Multensor.mul2Element-wise multiplication
4Divtensor.div2Division
5Negtensor.neg1Negation
#![allow(unused)]
fn main() {
use lift_tensor::ops::TensorOp;

let op = TensorOp::MatMul;
println!("Nom: {}", op.name());           // "tensor.matmul"
println!("Inputs: {:?}", op.num_inputs()); // (2, 2)
println!("FLOPs: {}", op.flops_formula()); // "2*M*N*K"
}

4.1.2 Linear Algebra (4 ops)

#OpInputsDescription
6MatMul2Matrix multiplication
7Linear3Linear layer (matmul + bias)
8Embedding2Embedding lookup table
9SparseMatMul2Sparse MatMul

4.1.3 Activations (11 ops)

#OpDescriptionFLOPs Formula
10ReLUmax(0, x)N
11GeLUGaussian Error Linear Unit~8N
12SiLUx * sigmoid(x) (Swish)~8N
13Sigmoid1/(1+exp(-x))N
14TanhHyperbolic tangentN
15Softmaxexp(x)/sum(exp(x))5N
16LeakyReLUmax(αx, x)N
17ELUExponential Linear UnitN
18Mishx * tanh(softplus(x))~8N
19HardSwishSwish approximation~8N
20HardSigmoidSigmoid approximationN
#![allow(unused)]
fn main() {
assert!(TensorOp::ReLU.is_activation());
assert!(!TensorOp::MatMul.is_activation());
}

4.1.4 Normalisation (5 ops)

#OpInputsDescription
21LayerNorm2-3Layer normalisation
22RMSNorm2-3Root Mean Square Norm (LLaMA)
23BatchNorm3-5Batch normalisation
24GroupNorm2-3Group normalisation
25InstanceNorm2-3Instance normalisation
#![allow(unused)]
fn main() {
assert!(TensorOp::LayerNorm.is_normalisation());
}

4.1.5 Attention (8 ops)

#OpInputsDescription
26Attention3-4Standard attention (Q, K, V, [mask])
27MultiHeadAttention3-4Multi-head
28MultiQueryAttention3-4Multi-query (Llama)
29GroupedQueryAttention3-4Grouped query (GQA)
30FlashAttention3-4FlashAttention V2 (O(N) memory)
31SlidingWindowAttention3-4Sliding window (Mistral)
32CrossAttention3-4Cross-attention (encoder-decoder)
33PagedAttention3-5Paged attention (vLLM)
#![allow(unused)]
fn main() {
assert!(TensorOp::FlashAttention.is_attention());
}

4.1.6 Convolutions (6 ops)

#OpDescription
34Conv2DConvolution 2D standard
35Conv1D1D convolution (audio, sequences)
36Conv3D3D convolution (video, volumetric)
37ConvTranspose2DTransposed convolution (upsampling)
38DepthwiseConv2DDepthwise convolution (MobileNet)
39DilatedConv2DDilated convolution (large receptive field)

4.1.7 Pooling (4 ops)

#OpDescription
40MaxPool2DMax pooling 2D
41AvgPool2DAverage pooling 2D
42AdaptiveAvgPool2DAdaptive average pooling
43GlobalAvgPoolGlobal average pooling

4.1.8 Shape Operations (13 ops)

#OpDescriptionFLOPs
44ReshapeChange shape0
45TransposeTranspose0
46ConcatConcatenate0
47SplitSplit0
48GatherAdvanced indexing0
49ScatterIndexed write0
50SqueezeRemove dim=10
51UnsqueezeAdd dim=10
52PermutePermute dimensions0
53ExpandBroadcast expansion0
54SliceSlice0
55PadPadding0
56TileRepeat0
#![allow(unused)]
fn main() {
assert!(TensorOp::Reshape.is_zero_flop());
}

4.1.9 Constants (5 ops)

#OpDescription
57ConstantConstant tensor
58ZerosZero tensor
59OnesOnes tensor
60ArangeSequence [0, 1, ..., n-1]
61FullTensor filled with a value

4.1.10 Recurrent (3 ops)

#OpDescription
62LSTMCellLSTM cell
63GRUCellGRU cell
64RNNCellSimple RNN cell

4.1.11 Advanced Mathematics (9 ops)

#OpDescription
65EinsumEinstein notation
66FFTFast Fourier Transform
67IFFTInverse FFT
68SVDSingular Value Decomposition
69EigEigendecomposition
70SolveLinear system solver
71TopKTop-K values
72SortSort
73CumsumCumulative sum

4.1.12 Quantisation (6 ops)

#OpDescription
74QuantizeFP → INT8
75DequantizeINT8 → FP
76QuantizeInt4FP → INT4
77DequantizeInt4INT4 → FP
78QuantizeFp8FP → FP8
79DequantizeFp8FP8 → FP

4.1.13 Diffusion / Generative (3 ops)

#OpDescription
80UNetDownBlockU-Net down block
81UNetUpBlockU-Net up block
82TimestepEmbeddingTimestep embedding (Stable Diffusion)

4.1.14 GNN — Graph Neural Networks (2 ops)

#OpDescription
83GNNMessagePassingGNN message passing
84GNNGlobalPoolingGNN global pooling

4.1.15 MoE — Mixture of Experts (2 ops)

#OpDescription
85MoEDispatchRoute to experts
86MoECombineCombine expert outputs

4.1.16 Memory and Gradient (11 ops)

#OpDescription
87CheckpointGradient checkpointing (memory saving)
88OffloadCPU offload (for large models)
89GradAccumulateGradient accumulation
90GradMatMulMatMul gradient
91GradReLUReLU gradient
92GradSoftmaxSoftmax gradient
93GradLayerNormLayerNorm gradient
94GradAttentionAttention gradient
95GradConv2DConv2D gradient
96GradLinearLinear gradient
97GradGeLUGeLU gradient

4.1.17 Parallelism (4 ops)

#OpDescription
98ParallelSplitData parallel split
99ParallelAllReduceAll-reduce across GPUs
100PipelineSendPipeline parallel send
101PipelineReceivePipeline parallel receive

4.1.18 Fused Operations (6 ops)

#OpDescriptionGain
102FusedMatMulBiasReLUMatMul + Bias + ReLU1 kernel instead of 3
103FusedMatMulBiasMatMul + Bias1 kernel instead of 2
104FusedLinearGeLULinear + GeLUBandwidth gain
105FusedAttentionLayerNormAttention + LayerNormMemory reduction
106FusedLinearSiLULinear + SiLUBandwidth gain
110FusedConvBatchNormReLUConv + BN + ReLUFast inference

4.2 Shape Inference

#![allow(unused)]
fn main() {
use lift_core::types::*;
use lift_tensor::ops::TensorOp;
use lift_tensor::shape::ShapeInference;

fn mk(shape: Vec<usize>, dtype: DataType) -> TensorTypeInfo {
    TensorTypeInfo {
        shape: shape.into_iter().map(Dimension::Constant).collect(),
        dtype,
        layout: MemoryLayout::Contiguous,
    }
}

// Shape inference
let a = mk(vec![2, 3, 64], DataType::FP32);
let b = mk(vec![2, 64, 128], DataType::FP32);
let result = ShapeInference::infer_output_shape(&TensorOp::MatMul, &[&a, &b]).unwrap();
// result[0].shape = [2, 3, 128]

// FLOP computation
let flops = ShapeInference::compute_flops(&TensorOp::MatMul, &[&a, &b]);
println!("FLOPs: {:?}", flops); // Some(49152)

// Memory computation
let mem = ShapeInference::compute_memory_bytes(&TensorOp::MatMul, &[&a, &b]);
println!("Memory: {:?} bytes", mem);
}

Combine with: lift-sim (cost model uses FLOPs), lift-predict (roofline prediction).

4.3 Useful Predicates

#![allow(unused)]
fn main() {
let op = TensorOp::FlashAttention;

op.is_attention();      // true — attention variant?
op.is_convolution();    // false — convolution?
op.is_normalisation();  // false — normalisation?
op.is_activation();     // false — activation?
op.is_fused();          // false — fused operation?
op.is_gradient();       // false — gradient operation?
op.is_zero_flop();      // false — zero FLOPs (reshape, etc.)?
op.num_inputs();        // (3, 4) — min/max number of inputs
op.flops_formula();     // "2*B*H*(S^2*D + S*D^2)"
}

5. lift-quantum — Quantum Gates and Noise (48 gates)

5.1 Quantum Gates

5.1.1 Standard 1-Qubit Gates (9 gates)

#GateIR NameTypeDescription
1Hquantum.hCliffordHadamard
2Xquantum.xPauliQuantum NOT (bit-flip)
3Yquantum.yPauliY rotation by π
4Zquantum.zPauliPhase-flip
5Squantum.sCliffordPhase π/2
6Sdgquantum.sdgCliffordS inverse
7Tquantum.tNon-CliffordPhase π/4 (expensive for QEC)
8Tdgquantum.tdgNon-CliffordT inverse
9SXquantum.sxCliffordSquare root of X

5.1.2 Parametric 1-Qubit Gates (9 gates)

#GateParametersDescription
10RXθRotation around X
11RYθRotation around Y
12RZθRotation around Z
13PφPhase gate
14U1λU1 unitary gate
15U2φ, λU2 unitary gate
16U3θ, φ, λGeneral unitary gate
17Rx90Fixed RX(π/2)
18Rx180Fixed RX(π)

5.1.3 2-Qubit Gates (14 gates)

#GateDescriptionNative for
19CXCNOTIBM
20CZControlled-ZIBM, Rigetti
21CYControlled-Y
22SWAPQubit swap
23ISWAPiSWAPRigetti
24ECREchoed Cross-ResonanceIBM Eagle
25RZXZX rotationIBM
26XXIsing XXIonQ
27YYIsing YYIonQ
28ZZIsing ZZIonQ
29CPhaseControlled PhaseRigetti
30XYXY interactionRigetti
31CPControlled Phase
32MSMølmer–SørensenIonQ

5.1.4 3-Qubit and Multi-Control Gates (4 gates)

#GateDescription
33CCXToffoli (CCNOT)
34CSWAPFredkin
35MCXMulti-controlled X
36MCZMulti-controlled Z

5.1.5 Special and Control Gates (10 gates)

#GateDescription
37GlobalPhaseGlobal phase
38DelayDelay (decoherence)
39VirtualRZVirtual RZ (no physical cost)
40IfElseClassical conditional control
41MeasureMeasure 1 qubit
42MeasureAllMeasure all qubits
43ResetReset
44BarrierBarrier (prevents optimisation)
45InitInitialisation
46ParamGateGeneric parametric gate
#![allow(unused)]
fn main() {
use lift_quantum::gates::QuantumGate;

let gate = QuantumGate::H;
println!("Name: {}", gate.op_name());       // "quantum.h"
println!("Qubits: {}", gate.num_qubits());  // 1
println!("Clifford: {}", gate.is_clifford()); // true
println!("Parametric: {}", gate.is_parametric()); // false
println!("Self-inverse: {}", gate.is_self_inverse()); // true

// Look up a gate by its IR name
let gate = QuantumGate::from_name("quantum.cx"); // Some(CX)
}

5.2 Hardware Providers — Native Gate Sets

#![allow(unused)]
fn main() {
use lift_quantum::gates::{QuantumGate, Provider};

// Native gates per provider
let ibm_basis = QuantumGate::native_basis(Provider::IbmEagle);
let rigetti_basis = QuantumGate::native_basis(Provider::Rigetti);
let ionq_basis = QuantumGate::native_basis(Provider::IonQ);
let quant_basis = QuantumGate::native_basis(Provider::Quantinuum);
}
ProviderNative Gates
IbmEagleCX, RZ, SX, X
IbmKyotoECR, RZ, SX, X
RigettiCZ, RX, RZ
IonQGPI, GPI2, MS
QuantinuumRZ, RX, ZZ
SimulatorAll gates

Combine with: lift-opt::LayoutMapping (transpilation to target hardware).

5.3 Device Topology — Hardware Topology

#![allow(unused)]
fn main() {
use lift_quantum::topology::DeviceTopology;

// Predefined topologies
let linear = DeviceTopology::linear(10);         // Linear chain
let grid = DeviceTopology::grid(3, 3);           // 3x3 grid
let hex = DeviceTopology::heavy_hex(27);         // Heavy-hex IBM
let ion = DeviceTopology::all_to_all(32);        // All-to-all (trapped ions)
let tree = DeviceTopology::tree(15);             // Binary tree

// Custom topology
let custom = DeviceTopology::custom("my_chip",
    &[(0,1), (1,2), (2,3), (0,3)], 0.99);

// Querying
linear.are_connected(0, 1);           // true
linear.shortest_path(0, 4);           // Some([0, 1, 2, 3, 4])
linear.swap_distance(0, 4);           // Some(3)
linear.avg_connectivity();             // average connectivity
linear.diameter();                     // graph diameter
grid.neighbors(4);                     // neighbours of qubit 4
}

Combine with: lift-opt::LayoutMapping, lift-opt::NoiseAwareSchedule.

5.4 Noise Models

#![allow(unused)]
fn main() {
use lift_quantum::noise::{NoiseModel, GateNoise, CircuitNoise};

// Noise models
let ideal = NoiseModel::Ideal;
let depol = NoiseModel::Depolarizing { p: 0.01 };
let bitflip = NoiseModel::BitFlip { p: 0.001 };
let phaseflip = NoiseModel::PhaseFlip { p: 0.001 };

// Model fidelity
let fidelity = depol.fidelity(); // 0.99

// Per-gate noise
let gate_noise = GateNoise::with_depolarizing(0.999, 0.02);

// Full circuit analysis
let mut cn = CircuitNoise::new();
// ... noise accumulation
println!("Total fidelity: {}", cn.total_fidelity);
println!("2-qubit gates: {}", cn.two_qubit_count);
}

5.5 Kraus Channels — Quantum Noise Channels

#![allow(unused)]
fn main() {
use lift_quantum::kraus::{ComplexMatrix, KrausChannel};

// Predefined noise channels
let depol = KrausChannel::depolarizing(0.01, 1);     // 1-qubit depolarising
let amp = KrausChannel::amplitude_damping(0.02);      // Amplitude damping
let phase = KrausChannel::phase_damping(0.01);         // Phase damping

// Channel fidelity
let fidelity = depol.average_gate_fidelity();
println!("Fidelity: {:.6}", fidelity);

// Complex matrices
let mut m = ComplexMatrix::identity(2);
let dagger = m.dagger();    // Conjugate transpose
let product = m.mul(&dagger).unwrap();
let trace = m.trace().unwrap();
}

Combine with: lift-sim::QuantumCostModel (circuit fidelity estimation), lift-opt::NoiseAwareSchedule.

5.6 QEC — Quantum Error Correction

#![allow(unused)]
fn main() {
use lift_quantum::qec::{QecCode, QecAnalysis};

// Available QEC codes
let surface = QecCode::SurfaceCode { distance: 5 };   // 25 physical qubits/logical
let steane = QecCode::SteaneCode;                       // 7 physical qubits/logical
let shor = QecCode::ShorCode;                            // 9 physical qubits/logical
let rep = QecCode::RepetitionCode { distance: 7 };     // 7 physical qubits
let ldpc = QecCode::LdpcCode { n: 100, k: 10 };       // LDPC code

// Code properties
println!("Physical/logical: {}", surface.physical_per_logical()); // 25
println!("Distance: {}", surface.code_distance());                 // 5
println!("Syndrome depth: {}", surface.syndrome_circuit_depth()); // 5

// Full QEC analysis
let analysis = QecAnalysis::analyse(
    10,     // logical qubits
    100,    // circuit depth
    QecCode::SurfaceCode { distance: 5 },
    0.001,  // physical error rate
);
println!("Physical qubits: {}", analysis.physical_qubits);
println!("Logical error rate: {:.2e}", analysis.logical_error_rate);
println!("Overhead: {}", analysis.overhead_qubits);
}

Combine with: lift-sim::QuantumCostModel, lift-predict (fidelity budget).


6. lift-hybrid — Classical-Quantum Hybrid Computation

6.1 Hybrid Operations (21 ops)

6.1.1 Encoding/Decoding (2 ops)

#OpIR NameDescription
1Encodehybrid.encodeEncode classical data → qubits
2Decodehybrid.decodeDecode quantum measurements → classical

6.1.2 Gradient Methods (6 ops)

#OpIR NameEvaluationsExact?
3ParameterShifthybrid.parameter_shift2NYes
4FiniteDifferencehybrid.finite_differenceN+1No
5SPSAhybrid.spsa2No
6AdjointDifferentiationhybrid.adjoint_diff1Yes
7StochasticParameterShifthybrid.stochastic_param_shift2No
8JointGradienthybrid.joint_gradientCombined
#![allow(unused)]
fn main() {
use lift_hybrid::gradient::GradientMethod;

let method = GradientMethod::ParameterShift;
let evals = method.circuit_evaluations(100); // 200 evaluations for 100 params
assert!(method.is_exact()); // true
}

6.1.3 Processing (4 ops)

#OpDescription
9ClassicalPreprocessClassical preprocessing
10QuantumPostprocessQuantum postprocessing
11HybridForwardHybrid forward pass
12HybridBackwardHybrid backward pass

6.1.4 Variational Algorithms (4 ops)

#OpDescriptionUsage
13VqcLayerVariational circuit layerQuantum classification
14VqeAnsatzVQE ansatzQuantum chemistry
15QaoaLayerQAOA layerCombinatorial optimisation
16QuantumKernelQuantum kernelQuantum machine learning

6.1.5 Data Transfer (2 ops)

#OpDescription
17GpuToQpuGPU → QPU transfer
18QpuToGpuQPU → GPU transfer

6.1.6 Co-Execution and Measurement (3 ops)

#OpDescription
19CoExecuteSimultaneous classical+quantum execution
20MeasureExpectationObservable expectation value
21MeasureSamplesMeasurement sampling
#![allow(unused)]
fn main() {
use lift_hybrid::ops::HybridOp;

let op = HybridOp::VqcLayer;
assert!(op.is_variational());
assert!(!op.is_gradient());
}

6.2 Encoding Strategies

#![allow(unused)]
fn main() {
use lift_hybrid::encoding::{EncodingStrategy, EncodingConfig};

let strategies = [
    EncodingStrategy::AngleEncoding,       // 1 qubit/feature, depth 1
    EncodingStrategy::AmplitudeEncoding,    // log2(n) qubits, depth n
    EncodingStrategy::BasisEncoding,        // 1 qubit/feature, depth 1
    EncodingStrategy::IQPEncoding,          // 1 qubit/feature, depth 2n
    EncodingStrategy::HamiltonianEncoding,  // 1 qubit/feature, depth n
    EncodingStrategy::KernelEncoding,       // 1 qubit/feature, depth 3n
];

// Encoding configuration
let config = EncodingConfig::new(EncodingStrategy::AmplitudeEncoding, 256);
println!("Qubits required: {}", config.num_qubits); // 8 = log2(256)
println!("Classical dimension: {}", config.classical_dim); // 256
}
StrategyQubitsDepthBest for
Anglen1Few features
Amplitudelog₂(n)nMany features
Basisn1Binary data
IQPn2nQuantum advantage
HamiltoniannnPhysical simulation
Kerneln3nQuantum ML

6.3 Gradient Configuration — Joint Gradient Setup

#![allow(unused)]
fn main() {
use lift_hybrid::gradient::{GradientMethod, JointGradientConfig};

let config = JointGradientConfig {
    classical_method: GradientMethod::Backprop,
    quantum_method: GradientMethod::ParameterShift,
    num_classical_params: 1000,
    num_quantum_params: 50,
};
println!("Total evaluations: {}", config.total_evaluations());
// 1 (backprop) + 100 (2*50 parameter shift) = 101
}

6.4 Auxiliary Types

#![allow(unused)]
fn main() {
use lift_hybrid::ops::{AnsatzType, SyncPolicy, FeatureMap};

// Ansatz types for VQC
let ansatz = AnsatzType::HardwareEfficient; // HardwareEfficient, StronglyEntangling, TwoLocal, UCCSD, Custom

// Synchronisation policy
let sync = SyncPolicy::Blocking; // Blocking, Asynchronous, Pipeline

// Feature maps for quantum kernels
let fm = FeatureMap::ZZFeatureMap; // ZZFeatureMap, PauliFeatureMap, AngleEncoding, AmplitudeEncoding
}

7. lift-opt — Optimisation Passes (13 passes)

7.1 Classical Passes (5 passes)

7.1.1 Canonicalize — Canonical Form

#![allow(unused)]
fn main() {
use lift_opt::Canonicalize;
use lift_core::pass::Pass;

let pass = Canonicalize;
// Reorders operations into canonical form
// Normalises IR patterns to facilitate subsequent optimisations
}

Usage: Always run first in the pipeline.

7.1.2 ConstantFolding — Constant Folding

#![allow(unused)]
fn main() {
use lift_opt::ConstantFolding;

let pass = ConstantFolding;
// Evaluates operations whose operands are all compile-time constants
// Example: add(const(2), const(3)) → const(5)
}

7.1.3 DeadCodeElimination — Dead Code Elimination

#![allow(unused)]
fn main() {
use lift_opt::DeadCodeElimination;

let pass = DeadCodeElimination;
// Removes operations whose results are never used
// Respects operations with side effects (measurements, etc.)
}

7.1.4 TensorFusion — Tensor Fusion

#![allow(unused)]
fn main() {
use lift_opt::TensorFusion;

let pass = TensorFusion;
// Fuses consecutive operations into fused operations
// Example: MatMul + Bias + ReLU → FusedMatMulBiasReLU
// Reduces memory accesses and kernel launches
}

Combine with: Run after Canonicalize and ConstantFolding.

7.1.5 CommonSubexprElimination — Common Subexpression Elimination

#![allow(unused)]
fn main() {
use lift_opt::CommonSubexprElimination;

let pass = CommonSubexprElimination;
// Detects identical operations (same op, same operands)
// Replaces duplicates with references to the first occurrence
// Excludes operations with side effects
}

7.2 Quantum Passes (3 passes)

7.2.1 GateCancellation — Gate Cancellation

#![allow(unused)]
fn main() {
use lift_opt::GateCancellation;

let pass = GateCancellation;
// Removes gate pairs that cancel out
// Example: H H → identity, X X → identity
// Respects qubit linearity invariants
}

7.2.2 RotationMerge — Rotation Merging

#![allow(unused)]
fn main() {
use lift_opt::RotationMerge;

let pass = RotationMerge;
// Merges consecutive rotations on the same axis
// Example: RZ(0.3) RZ(0.5) → RZ(0.8)
// Removes identity rotations (angle ≈ 0)
}

7.2.3 NoiseAwareSchedule — Noise-Aware Scheduling

#![allow(unused)]
fn main() {
use lift_opt::NoiseAwareSchedule;

let pass = NoiseAwareSchedule;
// Reorders quantum gates to minimise decoherence
// Prioritises fast gates (1-qubit) before slow ones (2-qubit)
// Respects SSA dependencies
}

Combine with: lift-quantum::topology::DeviceTopology for the target topology.

7.3 Advanced AI Passes (3 passes)

7.3.1 FlashAttentionPass — FlashAttention Replacement

#![allow(unused)]
fn main() {
use lift_opt::FlashAttentionPass;

let pass = FlashAttentionPass::default(); // threshold = 512
let pass_custom = FlashAttentionPass { seq_len_threshold: 1024 };
// Replaces tensor.attention with tensor.flash_attention
// when sequence length exceeds the threshold
// Reduces memory complexity from O(N²) to O(N)
}

7.3.2 QuantisationPass — Quantisation Annotation

#![allow(unused)]
fn main() {
use lift_opt::QuantisationPass;
use lift_opt::quantisation_pass::{QuantTarget, QuantMode};

let pass = QuantisationPass::default(); // INT8, Dynamic
let pass_custom = QuantisationPass {
    target_dtype: QuantTarget::Fp8E4M3,
    mode: QuantMode::Static,
};
// Annotates heavy operations (MatMul, Conv, Linear, Attention)
// with quantisation metadata
// Inserts Quantize/Dequantize pairs around annotated ops
}
TargetSizeUsage
Int81 byteStandard inference
Int40.5 byteCompressed LLMs (GPTQ, AWQ)
Fp8E4M31 byteH100 training
Fp8E5M21 byteH100 inference

7.3.3 LayoutMapping — Qubit Mapping

#![allow(unused)]
fn main() {
use lift_opt::LayoutMapping;

let pass = LayoutMapping;
// Inserts SWAP gates to map logical qubits to physical qubits
// Based on the target device topology
// Marks operations requiring swaps via attributes
}

Combine with: lift-quantum::topology::DeviceTopology.

7.3.4 GateDecomposition — Hardware-Native Gate Sets

#![allow(unused)]
fn main() {
use lift_opt::gate_decompose::GateDecomposition;
use lift_quantum::dialect::Provider;

let pass = GateDecomposition::new(Some(Provider::Ibm));
// Lowers high-level gates to hardware-native gate sets:
//   H     → RZ(π/2) SX RZ(π/2)
//   T/Tdg → RZ(±π/4)
//   S/Sdg → RZ(±π/2)
//   Y     → RZ(π/2) X RZ(-π/2)
//   RX(θ) → RZ(-π/2) SX RZ(π+θ) SX RZ(π/2)
// Provider is read from QuantumConfig (provider = ibm|rigetti|ionq|quantinuum|simulator)
// Uses Context::insert_op_before to preserve SSA dominance
}

Combine with: lift-config [quantum] provider key.

7.3.5 RealRouting — SWAP-Based Qubit Routing

#![allow(unused)]
fn main() {
use lift_opt::real_routing::RealRouting;
use lift_quantum::topology::DeviceTopology;

let pass = RealRouting::new(DeviceTopology::linear(8));
// Inserts actual quantum.swap operations so every 2-qubit gate
// only acts on physically connected qubits.
// Strategy: identity initial placement, BFS shortest-path routing,
// logical↔physical placement maps updated after every swap.
}

Combine with: lift-config [quantum] topology / num_qubits keys.

7.4 Optimisation Levels (O0-O3)

lift-config provides preset pipelines so you don't have to enumerate passes by hand:

LevelPasses
O0none
O1canonicalize, constant-folding, dce
O2O1 + cse, tensor-fusion
O3all 13 passes (incl. gate-decomposition, real-routing)
[optimisation]
level = "O3"                  # preset pipeline
passes = []                   # (optional) explicit overrides the level
disabled_passes = ["cse"]     # (optional) remove specific passes
max_iterations = 5

Explicit passes take priority over level; unknown pass names are reported by OptimisationConfig::validate().

#![allow(unused)]
fn main() {
use lift_core::PassManager;

let mut pm = PassManager::new();

// Phase 1: Cleanup
pm.add_pass(Box::new(lift_opt::Canonicalize));
pm.add_pass(Box::new(lift_opt::ConstantFolding));
pm.add_pass(Box::new(lift_opt::DeadCodeElimination));
pm.add_pass(Box::new(lift_opt::CommonSubexprElimination));

// Phase 2: Fusion (AI)
pm.add_pass(Box::new(lift_opt::TensorFusion));
pm.add_pass(Box::new(lift_opt::FlashAttentionPass::default()));
pm.add_pass(Box::new(lift_opt::QuantisationPass::default()));

// Phase 3: Quantum
pm.add_pass(Box::new(lift_opt::GateCancellation));
pm.add_pass(Box::new(lift_opt::RotationMerge));
pm.add_pass(Box::new(lift_opt::NoiseAwareSchedule));
pm.add_pass(Box::new(lift_opt::LayoutMapping));

// Phase 3b: Hardware targeting
pm.add_pass(Box::new(lift_opt::gate_decompose::GateDecomposition::new(Some(Provider::Ibm))));
pm.add_pass(Box::new(lift_opt::real_routing::RealRouting::new(DeviceTopology::linear(8))));

// Phase 4: Final cleanup
pm.add_pass(Box::new(lift_opt::DeadCodeElimination));

let results = pm.run_all(&mut ctx);
}

8. lift-sim — Simulation and Cost Analysis

8.1 CostModel — Classical Cost Model

#![allow(unused)]
fn main() {
use lift_sim::cost::CostModel;

// Predefined GPU profiles
let a100 = CostModel::a100();  // 312 TFLOPS, 2039 GB/s
let h100 = CostModel::h100();  // 989 TFLOPS, 3350 GB/s

// Time estimation
let flops = 2 * 1024 * 1024 * 1024_u64;
let bytes = 4 * 1024 * 1024_u64;

let compute_ms = a100.compute_time_ms(flops);      // Compute time
let memory_ms = a100.memory_time_ms(bytes);         // Memory time
let roofline_ms = a100.roofline_time_ms(flops, bytes); // Roofline model

// Analysis
let ai = a100.arithmetic_intensity(flops, bytes);   // FLOPs/byte
let bound = a100.is_compute_bound(flops, bytes);    // true = compute-bound
let fits = a100.fits_in_memory(bytes);               // Fits in memory?
let gpus = a100.num_gpus_needed(bytes);              // GPUs needed
}

8.2 QuantumCostModel — Quantum Cost Model

#![allow(unused)]
fn main() {
use lift_sim::cost::QuantumCostModel;

// Quantum processor profiles
let sc = QuantumCostModel::superconducting_default(); // IBM-like: 127 qubits
let ion = QuantumCostModel::trapped_ion_default();     // IonQ-like: 32 qubits
let atom = QuantumCostModel::neutral_atom_default();   // Atom-like: 256 qubits

// Circuit fidelity estimation
let fidelity = sc.circuit_fidelity(50, 20); // 50 1Q gates, 20 2Q gates
println!("Fidelity: {:.6}", fidelity);

// Circuit time
let time_us = sc.circuit_time_us(50, 20, 5, 10); // 50 1Q, 20 2Q, 5 measurements, 10 depth
println!("Time: {:.2} µs", time_us);

// Decoherence fidelity
let decoherence = sc.decoherence_fidelity(time_us);
println!("Decoherence fidelity: {:.6}", decoherence);
}
ParameterSuperconductingTrapped IonsNeutral Atoms
1Q time0.02 µs10 µs0.5 µs
2Q time0.3 µs200 µs1.0 µs
1Q fidelity99.9%99.99%99.9%
2Q fidelity99%99.9%99.5%
T1100 µs1 s5 ms
Qubits12732256

8.3 Budget — Resource Constraints

#![allow(unused)]
fn main() {
use lift_sim::cost::Budget;

let budget = Budget {
    max_flops: Some(1_000_000_000_000), // 1 TFLOP max
    max_memory_bytes: Some(80_000_000_000), // 80 GB
    max_time_ms: Some(100.0),           // 100 ms
    min_fidelity: Some(0.99),           // 99% min fidelity
    max_circuit_depth: Some(1000),      // 1000 layers max
};

budget.check_flops(500_000_000_000).unwrap();   // OK
budget.check_memory(40_000_000_000).unwrap();   // OK
budget.check_fidelity(0.995).unwrap();           // OK
}

8.4 EnergyModel — Energy and Carbon Estimation

#![allow(unused)]
fn main() {
use lift_sim::cost::EnergyModel;

let model = EnergyModel::a100();

// Energy for 1 second of computation on 4 GPUs
let joules = model.energy_joules(1000.0, 4);     // Joules
let kwh = model.energy_kwh(1000.0, 4);           // kWh
let carbon = model.carbon_grams(1000.0, 4);       // grams CO₂

println!("Energy: {:.2} J", joules);
println!("Carbon: {:.4} g CO₂", carbon);

// Quantum energy (cryogenic refrigeration)
let q_joules = model.quantum_energy_joules(100.0, 127); // 100 µs, 127 qubits
}

8.5 ReactiveBudget — Dynamic Budget

#![allow(unused)]
fn main() {
use lift_sim::cost::{Budget, ReactiveBudget};

let budget = Budget {
    max_flops: Some(1_000_000),
    max_memory_bytes: Some(1_000_000),
    max_time_ms: Some(50.0),
    min_fidelity: Some(0.9),
    max_circuit_depth: None,
};
let mut rb = ReactiveBudget::new(budget);

// Consume resources incrementally
rb.consume(100_000, 50_000, 5.0, 0.99); // flops, mem, time, fidelity
rb.consume(200_000, 80_000, 10.0, 0.98);

// Check remaining budget
rb.check_remaining().unwrap(); // OK if within limits

// Utilisation report
let util = rb.utilisation();
println!("FLOPs used: {:.1}%", util.flop_ratio.unwrap() * 100.0);
println!("Time used: {:.1}%", util.time_ratio.unwrap() * 100.0);

// Remaining budget
println!("Remaining FLOPs: {:?}", rb.remaining_flops());
println!("Remaining time: {:?} ms", rb.remaining_time_ms());
}

Combine with: lift-opt (stop optimisation if budget exhausted), lift-predict (verify prediction respects budget).

8.6 Module Analysis

#![allow(unused)]
fn main() {
use lift_sim::{analyze_module, analyze_quantum_ops};

let ctx = load_and_parse("model.lif").unwrap();

// Classical analysis
let report = analyze_module(&ctx);
println!("Total ops: {}", report.num_ops);
println!("Tensor ops: {}", report.num_tensor_ops);
println!("Quantum ops: {}", report.num_quantum_ops);
println!("Hybrid ops: {}", report.num_hybrid_ops);
println!("Total FLOPs: {}", report.total_flops);
println!("Total memory: {} bytes", report.total_memory_bytes);
println!("Peak memory: {} bytes", report.peak_memory_bytes);

// Quantum analysis
let quantum = analyze_quantum_ops(&ctx);
println!("Qubits: {}", quantum.num_qubits_used);
println!("Gates: {}", quantum.gate_count);
println!("1Q gates: {}", quantum.one_qubit_gates);
println!("2Q gates: {}", quantum.two_qubit_gates);
println!("Measurements: {}", quantum.measurements);
println!("Estimated fidelity: {:.6}", quantum.estimated_fidelity);
}

9. lift-predict — Performance Prediction

#![allow(unused)]
fn main() {
use lift_predict::predict_performance;
use lift_sim::{analyze_module, cost::CostModel};

let report = analyze_module(&ctx);
let cost_model = CostModel::h100();
let prediction = predict_performance(&report, &cost_model);

println!("Compute time: {:.4} ms", prediction.compute_time_ms);
println!("Memory time: {:.4} ms", prediction.memory_time_ms);
println!("Predicted time: {:.4} ms", prediction.predicted_time_ms);
println!("Arithmetic intensity: {:.2} FLOP/byte", prediction.arithmetic_intensity);
println!("Bottleneck: {}", prediction.bottleneck); // "compute" or "memory"
}

Combine with: lift-sim (provides the analysis report and cost model).


10. lift-import — Model Import

10.1 ONNX Import

#![allow(unused)]
fn main() {
use lift_import::OnnxImporter;

let importer = OnnxImporter::new();
let ctx = importer.import("model.onnx").expect("ONNX import failed");
}

10.2 PyTorch FX Import

#![allow(unused)]
fn main() {
use lift_import::PyTorchFxImporter;

let importer = PyTorchFxImporter::new();
let ctx = importer.import("model_fx.json").expect("FX import failed");
}

10.3 OpenQASM 3.0 Import

#![allow(unused)]
fn main() {
use lift_import::OpenQasm3Importer;

let importer = OpenQasm3Importer::new();
let ctx = importer.import("circuit.qasm").expect("QASM import failed");
}

Combine with: lift-core::verifier (verify imported IR), then lift-opt (optimise).


11. lift-export — Backend Export (LLVM, ONNX, QASM)

11.1 Export LLVM IR

#![allow(unused)]
fn main() {
use lift_export::LlvmExporter;

let exporter = LlvmExporter::new();
let llvm_ir = exporter.export(&ctx).expect("LLVM export failed");
std::fs::write("output.ll", &llvm_ir).unwrap();
}

Produces LLVM IR with runtime function calls for tensor operations (cuBLAS/cuDNN backend).

11.2 Export ONNX

#![allow(unused)]
fn main() {
use lift_export::OnnxExporter;

let exporter = OnnxExporter::new();
let onnx_text = exporter.export(&ctx).expect("ONNX export failed");
std::fs::write("output.onnx", &onnx_text).unwrap();

// Also available: JSON format
let onnx_json = exporter.export_json(&ctx).expect("ONNX JSON export failed");
std::fs::write("output_onnx.json", &onnx_json).unwrap();
}

Produces ONNX protobuf text format at opset version 21, IR version 9. Compatible with:

  • PyTorch, TensorFlow, TensorRT, ONNX Runtime
  • Microsoft extension ops for attention and MoE

ONNX op mapping (70+ operations):

LIFT OperationONNX OpDomain
tensor.matmulMatMulstandard
tensor.linearGemmstandard
tensor.add / sub / mul / divAdd / Sub / Mul / Divstandard
tensor.reluRelustandard
tensor.geluGelustandard
tensor.siluSigmoid + Mulstandard
tensor.softmaxSoftmaxstandard
tensor.layernormLayerNormalizationstandard
tensor.rmsnormSimplifiedLayerNormalizationcom.microsoft
tensor.batchnormBatchNormalizationstandard
tensor.conv2dConvstandard
tensor.maxpool2dMaxPoolstandard
tensor.avgpool2dAveragePoolstandard
tensor.attentionAttentioncom.microsoft
tensor.grouped_query_attentionGroupQueryAttentioncom.microsoft
tensor.flash_attentionMultiHeadAttentioncom.microsoft
tensor.quantizeQuantizeLinearstandard
tensor.dequantizeDequantizeLinearstandard
tensor.moe_dispatchMoEcom.microsoft
tensor.reshapeReshapestandard
tensor.transposeTransposestandard
tensor.concatConcatstandard
tensor.gatherGatherstandard
tensor.squeeze / unsqueezeSqueeze / Unsqueezestandard
tensor.clip / clampClipstandard
tensor.topkTopKstandard
tensor.whereWherestandard
tensor.cumsumCumSumstandard
tensor.constantConstantstandard
tensor.zeros / onesConstantOfShapestandard
tensor.einsumEinsumstandard
tensor.fft / ifftDFT / IDFTstandard
tensor.sparse_matmulMatMul (sparse)standard
tensor.fused_matmul_bias_reluFusedMatMulBiasRelucom.microsoft
tensor.fused_matmul_biasFusedMatMulBiascom.microsoft
tensor.fused_linear_geluFusedGemmcom.microsoft
tensor.fused_linear_siluFusedGemmcom.microsoft
tensor.fused_conv_batchnorm_reluFusedConvBatchNormRelucom.microsoft
tensor.fused_attention_layernormFusedAttentioncom.microsoft

Data type mapping:

LIFT DataTypeONNX ElemType
FP321 (FLOAT)
FP6411 (DOUBLE)
FP1610 (FLOAT16)
BF1616 (BFLOAT16)
INT83 (INT8)
INT326 (INT32)
INT647 (INT64)
BOOL9 (BOOL)

11.3 Export OpenQASM 3.0

#![allow(unused)]
fn main() {
use lift_export::QasmExporter;

let exporter = QasmExporter::new();
let qasm = exporter.export(&ctx).expect("QASM export failed");
std::fs::write("output.qasm", &qasm).unwrap();
}

Produces OpenQASM 3.0 executable on IBM Quantum, Rigetti, IonQ, Quantinuum.

Combine with: lift-opt (optimise before export), lift-quantum::Provider (transpile to native gate set).


12. lift-config — Configuration (.lith)

12.1 .lith File Format

[target]
backend = "cuda"
device = "A100"
precision = "fp16"

[budget]
max_flops = 1000000000000
max_memory_bytes = 80000000000
max_time_ms = 100.0
min_fidelity = 0.99

[optimisation]
level = O2
max_iterations = 10

[simulation]
shape_propagation = true
flop_counting = true
memory_analysis = true
noise_simulation = true

[quantum]
topology = "heavy_hex"
num_qubits = 127
shots = 4096

12.2 Programmatic Loading

#![allow(unused)]
fn main() {
use lift_config::{ConfigParser, LithConfig};

// From a file
let source = std::fs::read_to_string("config.lith").unwrap();
let config = ConfigParser::new().parse(&source).unwrap();

// Default configuration
let default = LithConfig::default();
// Backend: llvm, Level: O2, Passes: canonicalize, constant-folding, dce, tensor-fusion

// With quantum
let hybrid = LithConfig::default().with_quantum("heavy_hex", 127);
}

12.3 Optimisation Levels

LevelPassesUsage
O0NoneDebug, verification
O1Canonicalize, DCEFast compilation
O2+ ConstantFolding, TensorFusionDefault — good trade-off
O3+ FlashAttention, Quantisation, CSEMaximum performance

13. lift-cli — Command-Line Interface

13.1 Available Commands

13.1.1 lift verify — Verify a .lif file

lift verify model.lif
lift verify --verbose model.lif

Checks SSA invariants, qubit linearity, and typing.

13.1.2 lift analyse — Analyse a program

lift analyse model.lif
lift analyse model.lif --format json

Produces a report: op count, FLOPs, memory, quantum analysis.

13.1.3 lift print — Display the IR

lift print model.lif

Displays the IR in human-readable format.

13.1.4 lift optimise — Optimise

lift optimise model.lif
lift optimise model.lif --config config.lith --output optimised.lif

Applies the configured optimisation passes.

13.1.5 lift predict — Predict performance

lift predict model.lif --device a100
lift predict model.lif --device h100

Predicts execution time using the roofline model.

13.1.6 lift export — Export

lift export model.lif --backend llvm --output model.ll
lift export model.lif --backend onnx --output model.onnx
lift export quantum.lif --backend qasm --output circuit.qasm

Exports to LLVM IR, ONNX (opset 21), or OpenQASM 3.0.


14. lift-codegen — Programmatic Model Generation

The lift-codegen binary lets you define models directly from Rust code and automatically generate all export formats.

14.1 Running the Code Generator

cargo run --bin lift-codegen

This generates into examples/:

  • 4 .lif models — Phi-3-mini, MLP, ResNet block, VQE circuit
  • 4 .ll files — LLVM IR exports
  • 4 .onnx files — ONNX exports
  • 1 .qasm file — OpenQASM export (for quantum models only)
  • 1 .lith config — H100 optimization configuration

Each model is automatically verified, analysed, optimised, and exported.

14.2 ModelBuilder API

#![allow(unused)]
fn main() {
use lift_core::model_builder::{ModelBuilder, tensor, tensor_2d, DataType};

let model = ModelBuilder::new("my_model")
    .function("forward")
        .param("x", tensor(&[1, 784], DataType::FP32))
        .param("w", tensor_2d(784, 256, DataType::FP32))
        .op("tensor.matmul", &["x", "w"], "h", tensor(&[1, 256], DataType::FP32))
        .op("tensor.relu", &["h"], "out", tensor(&[1, 256], DataType::FP32))
        .returns("out")
        .done();

// Write .lif source file
model.write_lif("my_model.lif").unwrap();

// Build IR context for verification/analysis/export
let ctx = model.build_context();
lift_core::verifier::verify(&ctx).unwrap();
}

14.3 Multi-Target Export from Code

#![allow(unused)]
fn main() {
let ctx = model.build_context();

// Optimise first
let mut pm = PassManager::new();
pm.add_pass(Box::new(lift_opt::Canonicalize));
pm.add_pass(Box::new(lift_opt::ConstantFolding));
pm.add_pass(Box::new(lift_opt::DeadCodeElimination));
pm.add_pass(Box::new(lift_opt::TensorFusion));
pm.run_all(&mut ctx);

// Export to all 3 backends
let llvm_ir = lift_export::LlvmExporter::new().export(&ctx).unwrap();
let onnx_ir = lift_export::OnnxExporter::new().export(&ctx).unwrap();
std::fs::write("my_model.ll", &llvm_ir).unwrap();
std::fs::write("my_model.onnx", &onnx_ir).unwrap();

// Export QASM only if quantum ops present
if ctx.ops.iter().any(|(_, op)| ctx.strings.resolve(op.name).starts_with("quantum.")) {
    let qasm_ir = lift_export::QasmExporter::new().export(&ctx).unwrap();
    std::fs::write("my_model.qasm", &qasm_ir).unwrap();
}
}

Combine with: All other crates. ModelBuilder is the programmatic entry point for defining models without .lif files.


15. Combinations and Complete Pipelines

15.1 Complete AI Pipeline (Transformer)

#![allow(unused)]
fn main() {
// 1. Import an ONNX model
let ctx = OnnxImporter::new().import("bert.onnx")?;

// 2. Verify
verifier::verify(&ctx)?;

// 3. Analyse
let report = analyze_module(&ctx);

// 4. Optimise
let mut pm = PassManager::new();
pm.add_pass(Box::new(Canonicalize));
pm.add_pass(Box::new(ConstantFolding));
pm.add_pass(Box::new(DeadCodeElimination));
pm.add_pass(Box::new(CommonSubexprElimination));
pm.add_pass(Box::new(TensorFusion));
pm.add_pass(Box::new(FlashAttentionPass { seq_len_threshold: 512 }));
pm.add_pass(Box::new(QuantisationPass {
    target_dtype: QuantTarget::Int8,
    mode: QuantMode::Dynamic,
}));
pm.add_pass(Box::new(DeadCodeElimination));
pm.run_all(&mut ctx);

// 5. Predict performance
let h100 = CostModel::h100();
let pred = predict_performance(&analyze_module(&ctx), &h100);

// 6. Export to LLVM and ONNX
let llvm = LlvmExporter::new().export(&ctx)?;
let onnx = OnnxExporter::new().export(&ctx)?;
std::fs::write("bert_optimised.ll", llvm)?;
std::fs::write("bert_optimised.onnx", onnx)?;
}

15.2 Complete Quantum Pipeline (Bell State)

#![allow(unused)]
fn main() {
// 1. Parse the circuit
let ctx = load_lif_file("quantum_bell.lif")?;

// 2. Analyse noise
let quantum = analyze_quantum_ops(&ctx);
let sc = QuantumCostModel::superconducting_default();
let fidelity = sc.circuit_fidelity(
    quantum.one_qubit_gates, quantum.two_qubit_gates
);

// 3. QEC if needed
if fidelity < 0.99 {
    let analysis = QecAnalysis::analyse(2, 5,
        QecCode::SurfaceCode { distance: 3 }, 0.001);
    println!("Physical qubits needed: {}", analysis.physical_qubits);
}

// 4. Optimise
let mut pm = PassManager::new();
pm.add_pass(Box::new(GateCancellation));
pm.add_pass(Box::new(RotationMerge));
pm.add_pass(Box::new(NoiseAwareSchedule));
pm.add_pass(Box::new(LayoutMapping));
pm.run_all(&mut ctx);

// 5. Export to QASM
let qasm = QasmExporter::new().export(&ctx)?;
std::fs::write("bell_optimised.qasm", qasm)?;
}

15.3 Complete Hybrid Pipeline (VQE)

#![allow(unused)]
fn main() {
// 1. Configure encoding
let encoding = EncodingConfig::new(EncodingStrategy::AngleEncoding, 4);

// 2. Configure gradient
let grad_config = JointGradientConfig {
    classical_method: GradientMethod::Backprop,
    quantum_method: GradientMethod::ParameterShift,
    num_classical_params: 100,
    num_quantum_params: 20,
};

// 3. Reactive budget to control resources
let budget = Budget {
    max_flops: Some(1_000_000_000),
    max_memory_bytes: Some(8_000_000_000),
    max_time_ms: Some(60_000.0),
    min_fidelity: Some(0.95),
    max_circuit_depth: Some(500),
};
let mut rb = ReactiveBudget::new(budget);

// 4. VQE optimisation loop
for iteration in 0..100 {
    // Execute the quantum circuit
    rb.consume(10_000, 1_000, 0.5, 0.999);
    
    if rb.check_remaining().is_err() {
        println!("Budget exhausted at iteration {}", iteration);
        break;
    }
    
    let util = rb.utilisation();
    println!("Iteration {}: FLOP {:.1}%, Time {:.1}%",
        iteration,
        util.flop_ratio.unwrap() * 100.0,
        util.time_ratio.unwrap() * 100.0
    );
}

// 5. Estimate carbon footprint
let energy = EnergyModel::a100();
let carbon = energy.carbon_grams(rb.elapsed_ms, 1);
println!("Carbon footprint: {:.4} g CO₂", carbon);
}

15.4 Complete CLI Pipeline

# Verify, analyse, optimise, predict and export in one sequence
lift verify model.lif
lift analyse model.lif --format json > analysis.json
lift optimise model.lif --config production.lith --output optimised.lif
lift predict optimised.lif --device h100
lift export optimised.lif --backend llvm --output model.ll
lift export optimised.lif --backend onnx --output model.onnx

16. Concrete Examples

16.1 MLP (Multi-Layer Perceptron)

File tensor_mlp.lif:

#dialect tensor

module @mlp {
    func @forward(%x: tensor<1x784xf32>, %w1: tensor<784x256xf32>,
                  %b1: tensor<256xf32>, %w2: tensor<256x10xf32>,
                  %b2: tensor<10xf32>) -> tensor<1x10xf32> {
        %h1 = "tensor.matmul"(%x, %w1) : (tensor<1x784xf32>, tensor<784x256xf32>) -> tensor<1x256xf32>
        %h2 = "tensor.add"(%h1, %b1) : (tensor<1x256xf32>, tensor<256xf32>) -> tensor<1x256xf32>
        %h3 = "tensor.relu"(%h2) : (tensor<1x256xf32>) -> tensor<1x256xf32>
        %h4 = "tensor.matmul"(%h3, %w2) : (tensor<1x256xf32>, tensor<256x10xf32>) -> tensor<1x10xf32>
        %h5 = "tensor.add"(%h4, %b2) : (tensor<1x10xf32>, tensor<10xf32>) -> tensor<1x10xf32>
        %out = "tensor.softmax"(%h5) : (tensor<1x10xf32>) -> tensor<1x10xf32>
        return %out
    }
}

16.2 Self-Attention (Transformer)

File attention.lif:

#dialect tensor

module @transformer {
    func @self_attention(%q: tensor<1x128x64xf32>, %k: tensor<1x128x64xf32>,
                         %v: tensor<1x128x64xf32>, %norm_w: tensor<64xf32>)
                         -> tensor<1x128x64xf32> {
        %attn = "tensor.attention"(%q, %k, %v) : (...) -> tensor<1x128x64xf32>
        %normed = "tensor.layernorm"(%attn, %norm_w) : (...) -> tensor<1x128x64xf32>
        return %normed
    }
}

16.3 Bell State (Quantum)

File quantum_bell.lif:

#dialect quantum

module @bell_state {
    func @bell(%q0: qubit, %q1: qubit) -> (qubit, qubit) {
        %q2 = "quantum.h"(%q0) : (qubit) -> qubit
        %q3, %q4 = "quantum.cx"(%q2, %q1) : (qubit, qubit) -> (qubit, qubit)
        return %q3, %q4
    }
}

16.4 Production Configuration

File production.lith:

[target]
backend = "cuda"
device = "H100"
precision = "fp16"

[budget]
max_flops = 1000000000000
max_memory_bytes = 80000000000
max_time_ms = 100.0

[optimisation]
level = O3
max_iterations = 20

[simulation]
shape_propagation = true
flop_counting = true
memory_analysis = true
noise_simulation = true

[quantum]
topology = "heavy_hex"
num_qubits = 127
shots = 4096

Summary of Combinations by Task

TaskCrates to combine
Train an LLMlift-tensor + lift-opt (TensorFusion, FlashAttention) + lift-sim (CostModel) + lift-export (LLVM, ONNX)
Quantised inferencelift-tensor + lift-opt (QuantisationPass) + lift-predict + lift-export (LLVM, ONNX)
Quantum circuitlift-quantum + lift-opt (GateCancellation, RotationMerge, LayoutMapping) + lift-export (QASM)
VQE / QAOAlift-hybrid + lift-quantum + lift-opt (NoiseAwareSchedule) + lift-sim (QuantumCostModel)
Quantum MLlift-hybrid (QuantumKernel, encoding) + lift-tensor + lift-quantum
Cost analysislift-sim (CostModel, EnergyModel) + lift-predict
QEC planninglift-quantum (qec, topology) + lift-sim (QuantumCostModel)
Import/Optimise/Exportlift-import + lift-opt + lift-export (LLVM, ONNX, QASM)
Programmatic generationlift-codegen + lift-core (ModelBuilder) + lift-export
Stable Diffusionlift-tensor (UNet ops) + lift-opt (TensorFusion) + lift-export
GNNlift-tensor (GNNMessagePassing, GNNGlobalPooling) + lift-opt + lift-export