LIFT — Language 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.
- General Architecture
- lift-core — IR Core
- lift-ast — Parsing the .lif Language
- lift-tensor — Tensor Operations (107 ops)
- lift-quantum — Quantum Gates and Noise (46+ gates)
- lift-hybrid — Classical-Quantum Hybrid Computation
- lift-opt — Optimisation Passes (11 passes)
- lift-sim — Simulation and Cost Analysis
- lift-predict — Performance Prediction
- lift-import — Model Import
- lift-export — Backend Export (LLVM, ONNX, QASM)
- lift-config — Configuration (.lith)
- lift-cli — Command-Line Interface
- lift-codegen — Programmatic Model Generation
- Combinations and Complete Pipelines
- Concrete Examples
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 │
└──────────┴──────────┴───────────────────┘
The standard workflow is:
Source (.lif) → Lexer → Parser → IR (SSA) → Verification → Optimisation → Simulation → Export
| Extension | Description |
|---|---|
.lif |
LIFT IR source code |
.lith |
Compilation configuration |
.ll |
LLVM IR export |
.onnx |
ONNX export (protobuf text) |
.qasm |
OpenQASM 3.0 export |
[dependencies]
lift-core = "0.3.0"
lift-ast = "0.3.0"
lift-tensor = "0.3.0"
lift-quantum = "0.3.0"
lift-hybrid = "0.3.0"
lift-opt = "0.3.0"
lift-sim = "0.3.0"
lift-predict = "0.3.0"
lift-import = "0.3.0"
lift-export = "0.3.0"
lift-config = "0.3.0"The heart of the framework. Provides the SSA (Static Single Assignment) intermediate representation.
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.
| Field | Description | Usage |
|---|---|---|
ctx.values |
All SSA values | Each operation result is a unique value |
ctx.ops |
All operations | Program instructions |
ctx.blocks |
Basic blocks | Contain sequences of operations |
ctx.regions |
Regions | Contain blocks (function bodies) |
ctx.modules |
Modules | Compilation units |
ctx.strings |
String interning | ctx.strings.intern("name") |
ctx.type_interner |
Type interning | Type deduplication |
Combine with: All other crates. The Context is the entry point for every pipeline.
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*4Available data types:
| Type | Size | Usage |
|---|---|---|
FP64 |
8 bytes | High-precision scientific computing |
FP32 |
4 bytes | Standard training |
FP16 |
2 bytes | Fast inference |
BF16 |
2 bytes | Mixed-precision training (Google Brain) |
INT8 |
1 byte | Post-training quantisation |
INT32 |
4 bytes | Indices, counters |
BOOL |
1 byte | Masks |
Memory layouts: Contiguous, Strided.
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).
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.
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.
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 11 passes), lift-config (pass selection via configuration).
use lift_core::dialect::{DialectRegistry, Dialect};
let registry = DialectRegistry::new();
// The tensor, quantum, hybrid dialects are registered automaticallyThe 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.)
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());use lift_ast::Parser;
let mut parser = Parser::new(tokens);
let program = parser.parse().expect("Parsing errors");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");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).
| # | Op | IR Name | Inputs | Description |
|---|---|---|---|---|
| 1 | Add |
tensor.add |
2 | Element-wise addition |
| 2 | Sub |
tensor.sub |
2 | Subtraction |
| 3 | Mul |
tensor.mul |
2 | Element-wise multiplication |
| 4 | Div |
tensor.div |
2 | Division |
| 5 | Neg |
tensor.neg |
1 | Negation |
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"| # | Op | Inputs | Description |
|---|---|---|---|
| 6 | MatMul |
2 | Matrix multiplication |
| 7 | Linear |
3 | Linear layer (matmul + bias) |
| 8 | Embedding |
2 | Embedding lookup table |
| 9 | SparseMatMul |
2 | Sparse MatMul |
| # | Op | Description | FLOPs Formula |
|---|---|---|---|
| 10 | ReLU |
max(0, x) | N |
| 11 | GeLU |
Gaussian Error Linear Unit | ~8N |
| 12 | SiLU |
x * sigmoid(x) (Swish) | ~8N |
| 13 | Sigmoid |
1/(1+exp(-x)) | N |
| 14 | Tanh |
Hyperbolic tangent | N |
| 15 | Softmax |
exp(x)/sum(exp(x)) | 5N |
| 16 | LeakyReLU |
max(αx, x) | N |
| 17 | ELU |
Exponential Linear Unit | N |
| 18 | Mish |
x * tanh(softplus(x)) | ~8N |
| 19 | HardSwish |
Swish approximation | ~8N |
| 20 | HardSigmoid |
Sigmoid approximation | N |
assert!(TensorOp::ReLU.is_activation());
assert!(!TensorOp::MatMul.is_activation());| # | Op | Inputs | Description |
|---|---|---|---|
| 21 | LayerNorm |
2-3 | Layer normalisation |
| 22 | RMSNorm |
2-3 | Root Mean Square Norm (LLaMA) |
| 23 | BatchNorm |
3-5 | Batch normalisation |
| 24 | GroupNorm |
2-3 | Group normalisation |
| 25 | InstanceNorm |
2-3 | Instance normalisation |
assert!(TensorOp::LayerNorm.is_normalisation());| # | Op | Inputs | Description |
|---|---|---|---|
| 26 | Attention |
3-4 | Standard attention (Q, K, V, [mask]) |
| 27 | MultiHeadAttention |
3-4 | Multi-head |
| 28 | MultiQueryAttention |
3-4 | Multi-query (Llama) |
| 29 | GroupedQueryAttention |
3-4 | Grouped query (GQA) |
| 30 | FlashAttention |
3-4 | FlashAttention V2 (O(N) memory) |
| 31 | SlidingWindowAttention |
3-4 | Sliding window (Mistral) |
| 32 | CrossAttention |
3-4 | Cross-attention (encoder-decoder) |
| 33 | PagedAttention |
3-5 | Paged attention (vLLM) |
assert!(TensorOp::FlashAttention.is_attention());| # | Op | Description |
|---|---|---|
| 34 | Conv2D |
Convolution 2D standard |
| 35 | Conv1D |
1D convolution (audio, sequences) |
| 36 | Conv3D |
3D convolution (video, volumetric) |
| 37 | ConvTranspose2D |
Transposed convolution (upsampling) |
| 38 | DepthwiseConv2D |
Depthwise convolution (MobileNet) |
| 39 | DilatedConv2D |
Dilated convolution (large receptive field) |
| # | Op | Description |
|---|---|---|
| 40 | MaxPool2D |
Max pooling 2D |
| 41 | AvgPool2D |
Average pooling 2D |
| 42 | AdaptiveAvgPool2D |
Adaptive average pooling |
| 43 | GlobalAvgPool |
Global average pooling |
| # | Op | Description | FLOPs |
|---|---|---|---|
| 44 | Reshape |
Change shape | 0 |
| 45 | Transpose |
Transpose | 0 |
| 46 | Concat |
Concatenate | 0 |
| 47 | Split |
Split | 0 |
| 48 | Gather |
Advanced indexing | 0 |
| 49 | Scatter |
Indexed write | 0 |
| 50 | Squeeze |
Remove dim=1 | 0 |
| 51 | Unsqueeze |
Add dim=1 | 0 |
| 52 | Permute |
Permute dimensions | 0 |
| 53 | Expand |
Broadcast expansion | 0 |
| 54 | Slice |
Slice | 0 |
| 55 | Pad |
Padding | 0 |
| 56 | Tile |
Repeat | 0 |
assert!(TensorOp::Reshape.is_zero_flop());| # | Op | Description |
|---|---|---|
| 57 | Constant |
Constant tensor |
| 58 | Zeros |
Zero tensor |
| 59 | Ones |
Ones tensor |
| 60 | Arange |
Sequence [0, 1, ..., n-1] |
| 61 | Full |
Tensor filled with a value |
| # | Op | Description |
|---|---|---|
| 62 | LSTMCell |
LSTM cell |
| 63 | GRUCell |
GRU cell |
| 64 | RNNCell |
Simple RNN cell |
| # | Op | Description |
|---|---|---|
| 65 | Einsum |
Einstein notation |
| 66 | FFT |
Fast Fourier Transform |
| 67 | IFFT |
Inverse FFT |
| 68 | SVD |
Singular Value Decomposition |
| 69 | Eig |
Eigendecomposition |
| 70 | Solve |
Linear system solver |
| 71 | TopK |
Top-K values |
| 72 | Sort |
Sort |
| 73 | Cumsum |
Cumulative sum |
| # | Op | Description |
|---|---|---|
| 74 | Quantize |
FP → INT8 |
| 75 | Dequantize |
INT8 → FP |
| 76 | QuantizeInt4 |
FP → INT4 |
| 77 | DequantizeInt4 |
INT4 → FP |
| 78 | QuantizeFp8 |
FP → FP8 |
| 79 | DequantizeFp8 |
FP8 → FP |
| # | Op | Description |
|---|---|---|
| 80 | UNetDownBlock |
U-Net down block |
| 81 | UNetUpBlock |
U-Net up block |
| 82 | TimestepEmbedding |
Timestep embedding (Stable Diffusion) |
| # | Op | Description |
|---|---|---|
| 83 | GNNMessagePassing |
GNN message passing |
| 84 | GNNGlobalPooling |
GNN global pooling |
| # | Op | Description |
|---|---|---|
| 85 | MoEDispatch |
Route to experts |
| 86 | MoECombine |
Combine expert outputs |
| # | Op | Description |
|---|---|---|
| 87 | Checkpoint |
Gradient checkpointing (memory saving) |
| 88 | Offload |
CPU offload (for large models) |
| 89 | GradAccumulate |
Gradient accumulation |
| 90 | GradMatMul |
MatMul gradient |
| 91 | GradReLU |
ReLU gradient |
| 92 | GradSoftmax |
Softmax gradient |
| 93 | GradLayerNorm |
LayerNorm gradient |
| 94 | GradAttention |
Attention gradient |
| 95 | GradConv2D |
Conv2D gradient |
| 96 | GradLinear |
Linear gradient |
| 97 | GradGeLU |
GeLU gradient |
| # | Op | Description |
|---|---|---|
| 98 | ParallelSplit |
Data parallel split |
| 99 | ParallelAllReduce |
All-reduce across GPUs |
| 100 | PipelineSend |
Pipeline parallel send |
| 101 | PipelineReceive |
Pipeline parallel receive |
| # | Op | Description | Gain |
|---|---|---|---|
| 102 | FusedMatMulBiasReLU |
MatMul + Bias + ReLU | 1 kernel instead of 3 |
| 103 | FusedMatMulBias |
MatMul + Bias | 1 kernel instead of 2 |
| 104 | FusedLinearGeLU |
Linear + GeLU | Bandwidth gain |
| 105 | FusedAttentionLayerNorm |
Attention + LayerNorm | Memory reduction |
| 106 | FusedLinearSiLU |
Linear + SiLU | Bandwidth gain |
| 107 | FusedConvBatchNormReLU |
Conv + BN + ReLU | Fast inference |
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).
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)"| # | Gate | IR Name | Type | Description |
|---|---|---|---|---|
| 1 | H |
quantum.h |
Clifford | Hadamard |
| 2 | X |
quantum.x |
Pauli | Quantum NOT (bit-flip) |
| 3 | Y |
quantum.y |
Pauli | Y rotation by π |
| 4 | Z |
quantum.z |
Pauli | Phase-flip |
| 5 | S |
quantum.s |
Clifford | Phase π/2 |
| 6 | Sdg |
quantum.sdg |
Clifford | S inverse |
| 7 | T |
quantum.t |
Non-Clifford | Phase π/4 (expensive for QEC) |
| 8 | Tdg |
quantum.tdg |
Non-Clifford | T inverse |
| 9 | SX |
quantum.sx |
Clifford | Square root of X |
| # | Gate | Parameters | Description |
|---|---|---|---|
| 10 | RX |
θ | Rotation around X |
| 11 | RY |
θ | Rotation around Y |
| 12 | RZ |
θ | Rotation around Z |
| 13 | P |
φ | Phase gate |
| 14 | U1 |
λ | U1 unitary gate |
| 15 | U2 |
φ, λ | U2 unitary gate |
| 16 | U3 |
θ, φ, λ | General unitary gate |
| 17 | Rx90 |
— | Fixed RX(π/2) |
| 18 | Rx180 |
— | Fixed RX(π) |
| # | Gate | Description | Native for |
|---|---|---|---|
| 19 | CX |
CNOT | IBM |
| 20 | CZ |
Controlled-Z | IBM, Rigetti |
| 21 | CY |
Controlled-Y | — |
| 22 | SWAP |
Qubit swap | — |
| 23 | ISWAP |
iSWAP | Rigetti |
| 24 | ECR |
Echoed Cross-Resonance | IBM Eagle |
| 25 | RZX |
ZX rotation | IBM |
| 26 | XX |
Ising XX | IonQ |
| 27 | YY |
Ising YY | IonQ |
| 28 | ZZ |
Ising ZZ | IonQ |
| 29 | CPhase |
Controlled Phase | Rigetti |
| 30 | XY |
XY interaction | Rigetti |
| 31 | CP |
Controlled Phase | — |
| 32 | MS |
Mølmer–Sørensen | IonQ |
| # | Gate | Description |
|---|---|---|
| 33 | CCX |
Toffoli (CCNOT) |
| 34 | CSWAP |
Fredkin |
| 35 | MCX |
Multi-controlled X |
| 36 | MCZ |
Multi-controlled Z |
| # | Gate | Description |
|---|---|---|
| 37 | GlobalPhase |
Global phase |
| 38 | Delay |
Delay (decoherence) |
| 39 | VirtualRZ |
Virtual RZ (no physical cost) |
| 40 | IfElse |
Classical conditional control |
| 41 | Measure |
Measure 1 qubit |
| 42 | MeasureAll |
Measure all qubits |
| 43 | Reset |
Reset |
| 44 | Barrier |
Barrier (prevents optimisation) |
| 45 | Init |
Initialisation |
| 46 | ParamGate |
Generic parametric gate |
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)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);| Provider | Native Gates |
|---|---|
IbmEagle |
CX, RZ, SX, X |
IbmKyoto |
ECR, RZ, SX, X |
Rigetti |
CZ, RX, RZ |
IonQ |
GPI, GPI2, MS |
Quantinuum |
RZ, RX, ZZ |
Simulator |
All gates |
Combine with: lift-opt::LayoutMapping (transpilation to target hardware).
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 4Combine with: lift-opt::LayoutMapping, lift-opt::NoiseAwareSchedule.
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);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.
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).
| # | Op | IR Name | Description |
|---|---|---|---|
| 1 | Encode |
hybrid.encode |
Encode classical data → qubits |
| 2 | Decode |
hybrid.decode |
Decode quantum measurements → classical |
| # | Op | IR Name | Evaluations | Exact? |
|---|---|---|---|---|
| 3 | ParameterShift |
hybrid.parameter_shift |
2N | Yes |
| 4 | FiniteDifference |
hybrid.finite_difference |
N+1 | No |
| 5 | SPSA |
hybrid.spsa |
2 | No |
| 6 | AdjointDifferentiation |
hybrid.adjoint_diff |
1 | Yes |
| 7 | StochasticParameterShift |
hybrid.stochastic_param_shift |
2 | No |
| 8 | JointGradient |
hybrid.joint_gradient |
Combined | — |
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| # | Op | Description |
|---|---|---|
| 9 | ClassicalPreprocess |
Classical preprocessing |
| 10 | QuantumPostprocess |
Quantum postprocessing |
| 11 | HybridForward |
Hybrid forward pass |
| 12 | HybridBackward |
Hybrid backward pass |
| # | Op | Description | Usage |
|---|---|---|---|
| 13 | VqcLayer |
Variational circuit layer | Quantum classification |
| 14 | VqeAnsatz |
VQE ansatz | Quantum chemistry |
| 15 | QaoaLayer |
QAOA layer | Combinatorial optimisation |
| 16 | QuantumKernel |
Quantum kernel | Quantum machine learning |
| # | Op | Description |
|---|---|---|
| 17 | GpuToQpu |
GPU → QPU transfer |
| 18 | QpuToGpu |
QPU → GPU transfer |
| # | Op | Description |
|---|---|---|
| 19 | CoExecute |
Simultaneous classical+quantum execution |
| 20 | MeasureExpectation |
Observable expectation value |
| 21 | MeasureSamples |
Measurement sampling |
use lift_hybrid::ops::HybridOp;
let op = HybridOp::VqcLayer;
assert!(op.is_variational());
assert!(!op.is_gradient());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| Strategy | Qubits | Depth | Best for |
|---|---|---|---|
| Angle | n | 1 | Few features |
| Amplitude | log₂(n) | n | Many features |
| Basis | n | 1 | Binary data |
| IQP | n | 2n | Quantum advantage |
| Hamiltonian | n | n | Physical simulation |
| Kernel | n | 3n | Quantum ML |
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) = 101use 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, AmplitudeEncodinguse lift_opt::Canonicalize;
use lift_core::pass::Pass;
let pass = Canonicalize;
// Reorders operations into canonical form
// Normalises IR patterns to facilitate subsequent optimisationsUsage: Always run first in the pipeline.
use lift_opt::ConstantFolding;
let pass = ConstantFolding;
// Evaluates operations whose operands are all compile-time constants
// Example: add(const(2), const(3)) → const(5)use lift_opt::DeadCodeElimination;
let pass = DeadCodeElimination;
// Removes operations whose results are never used
// Respects operations with side effects (measurements, etc.)use lift_opt::TensorFusion;
let pass = TensorFusion;
// Fuses consecutive operations into fused operations
// Example: MatMul + Bias + ReLU → FusedMatMulBiasReLU
// Reduces memory accesses and kernel launchesCombine with: Run after Canonicalize and ConstantFolding.
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 effectsuse lift_opt::GateCancellation;
let pass = GateCancellation;
// Removes gate pairs that cancel out
// Example: H H → identity, X X → identity
// Respects qubit linearity invariantsuse 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)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 dependenciesCombine with: lift-quantum::topology::DeviceTopology for the target topology.
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)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| Target | Size | Usage |
|---|---|---|
Int8 |
1 byte | Standard inference |
Int4 |
0.5 byte | Compressed LLMs (GPTQ, AWQ) |
Fp8E4M3 |
1 byte | H100 training |
Fp8E5M2 |
1 byte | H100 inference |
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 attributesCombine with: lift-quantum::topology::DeviceTopology.
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 4: Final cleanup
pm.add_pass(Box::new(lift_opt::DeadCodeElimination));
let results = pm.run_all(&mut ctx);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 neededuse 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);| Parameter | Superconducting | Trapped Ions | Neutral Atoms |
|---|---|---|---|
| 1Q time | 0.02 µs | 10 µs | 0.5 µs |
| 2Q time | 0.3 µs | 200 µs | 1.0 µs |
| 1Q fidelity | 99.9% | 99.99% | 99.9% |
| 2Q fidelity | 99% | 99.9% | 99.5% |
| T1 | 100 µs | 1 s | 5 ms |
| Qubits | 127 | 32 | 256 |
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(); // OKuse 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 qubitsuse 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).
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);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).
use lift_import::OnnxImporter;
let importer = OnnxImporter::new();
let ctx = importer.import("model.onnx").expect("ONNX import failed");use lift_import::PyTorchFxImporter;
let importer = PyTorchFxImporter::new();
let ctx = importer.import("model_fx.json").expect("FX import failed");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).
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).
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 Operation | ONNX Op | Domain |
|---|---|---|
tensor.matmul |
MatMul |
standard |
tensor.linear |
Gemm |
standard |
tensor.add / sub / mul / div |
Add / Sub / Mul / Div |
standard |
tensor.relu |
Relu |
standard |
tensor.gelu |
Gelu |
standard |
tensor.silu |
Sigmoid + Mul |
standard |
tensor.softmax |
Softmax |
standard |
tensor.layernorm |
LayerNormalization |
standard |
tensor.rmsnorm |
SimplifiedLayerNormalization |
com.microsoft |
tensor.batchnorm |
BatchNormalization |
standard |
tensor.conv2d |
Conv |
standard |
tensor.maxpool2d |
MaxPool |
standard |
tensor.avgpool2d |
AveragePool |
standard |
tensor.attention |
Attention |
com.microsoft |
tensor.grouped_query_attention |
GroupQueryAttention |
com.microsoft |
tensor.flash_attention |
MultiHeadAttention |
com.microsoft |
tensor.quantize |
QuantizeLinear |
standard |
tensor.dequantize |
DequantizeLinear |
standard |
tensor.moe_dispatch |
MoE |
com.microsoft |
tensor.reshape |
Reshape |
standard |
tensor.transpose |
Transpose |
standard |
tensor.concat |
Concat |
standard |
tensor.gather |
Gather |
standard |
tensor.squeeze / unsqueeze |
Squeeze / Unsqueeze |
standard |
tensor.clip / clamp |
Clip |
standard |
tensor.topk |
TopK |
standard |
tensor.where |
Where |
standard |
tensor.cumsum |
CumSum |
standard |
tensor.constant |
Constant |
standard |
tensor.zeros / ones |
ConstantOfShape |
standard |
tensor.einsum |
Einsum |
standard |
tensor.fft / ifft |
DFT / IDFT |
standard |
tensor.sparse_matmul |
MatMul (sparse) |
standard |
tensor.fused_matmul_bias_relu |
FusedMatMulBiasRelu |
com.microsoft |
tensor.fused_matmul_bias |
FusedMatMulBias |
com.microsoft |
tensor.fused_linear_gelu |
FusedGemm |
com.microsoft |
tensor.fused_linear_silu |
FusedGemm |
com.microsoft |
tensor.fused_conv_batchnorm_relu |
FusedConvBatchNormRelu |
com.microsoft |
tensor.fused_attention_layernorm |
FusedAttention |
com.microsoft |
Data type mapping:
| LIFT DataType | ONNX ElemType |
|---|---|
FP32 |
1 (FLOAT) |
FP64 |
11 (DOUBLE) |
FP16 |
10 (FLOAT16) |
BF16 |
16 (BFLOAT16) |
INT8 |
3 (INT8) |
INT32 |
6 (INT32) |
INT64 |
7 (INT64) |
BOOL |
9 (BOOL) |
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).
[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 = 4096use 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);| Level | Passes | Usage |
|---|---|---|
O0 |
None | Debug, verification |
O1 |
Canonicalize, DCE | Fast compilation |
O2 |
+ ConstantFolding, TensorFusion | Default — good trade-off |
O3 |
+ FlashAttention, Quantisation, CSE | Maximum performance |
lift verify model.lif
lift verify --verbose model.lifChecks SSA invariants, qubit linearity, and typing.
lift analyse model.lif
lift analyse model.lif --format jsonProduces a report: op count, FLOPs, memory, quantum analysis.
lift print model.lifDisplays the IR in human-readable format.
lift optimise model.lif
lift optimise model.lif --config config.lith --output optimised.lifApplies the configured optimisation passes.
lift predict model.lif --device a100
lift predict model.lif --device h100Predicts execution time using the roofline model.
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.qasmExports to LLVM IR, ONNX (opset 21), or OpenQASM 3.0.
The lift-codegen binary lets you define models directly from Rust code and automatically generate all export formats.
cargo run --bin lift-codegenThis generates into examples/:
- 4
.lifmodels — Phi-3-mini, MLP, ResNet block, VQE circuit - 4
.llfiles — LLVM IR exports - 4
.onnxfiles — ONNX exports - 1
.qasmfile — OpenQASM export (for quantum models only) - 1
.lithconfig — H100 optimization configuration
Each model is automatically verified, analysed, optimised, and exported.
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();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.
// 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)?;// 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)?;// 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);# 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.onnxFile 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
}
}
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
}
}
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
}
}
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| Task | Crates to combine |
|---|---|
| Train an LLM | lift-tensor + lift-opt (TensorFusion, FlashAttention) + lift-sim (CostModel) + lift-export (LLVM, ONNX) |
| Quantised inference | lift-tensor + lift-opt (QuantisationPass) + lift-predict + lift-export (LLVM, ONNX) |
| Quantum circuit | lift-quantum + lift-opt (GateCancellation, RotationMerge, LayoutMapping) + lift-export (QASM) |
| VQE / QAOA | lift-hybrid + lift-quantum + lift-opt (NoiseAwareSchedule) + lift-sim (QuantumCostModel) |
| Quantum ML | lift-hybrid (QuantumKernel, encoding) + lift-tensor + lift-quantum |
| Cost analysis | lift-sim (CostModel, EnergyModel) + lift-predict |
| QEC planning | lift-quantum (qec, topology) + lift-sim (QuantumCostModel) |
| Import/Optimise/Export | lift-import + lift-opt + lift-export (LLVM, ONNX, QASM) |
| Programmatic generation | lift-codegen + lift-core (ModelBuilder) + lift-export |
| Stable Diffusion | lift-tensor (UNet ops) + lift-opt (TensorFusion) + lift-export |
| GNN | lift-tensor (GNNMessagePassing, GNNGlobalPooling) + lift-opt + lift-export |