988 lines
34 KiB
Markdown
988 lines
34 KiB
Markdown
# SymClaw Expansion Plan
|
||
## Quantum Computing · Genomic Biology · Quantum Chemistry · Materials Science
|
||
|
||
**Rust edition:** `2024` (rust-version `1.94.0`)
|
||
**Methodology:** Strict TDD — tests written first, no `todo!()`, no `unimplemented!()`, no mock/stub types, every function fully implemented before it is committed.
|
||
**File limit:** 1 250 lines per `.rs` source file. Files that grow beyond this are split at the nearest logical boundary into a `mod/` directory.
|
||
**Date drafted:** 2026-03-19
|
||
|
||
---
|
||
|
||
## 0. Immediate Housekeeping (before any new work)
|
||
|
||
### 0.1 Bump workspace Rust version
|
||
|
||
In `Cargo.toml` (workspace root):
|
||
|
||
```toml
|
||
[workspace.package]
|
||
edition = "2024"
|
||
rust-version = "1.94.0" # was 1.93.0
|
||
```
|
||
|
||
Verify: `rustup install 1.94.0 && cargo +1.94.0 check`
|
||
|
||
### 0.2 Split files already over 1 250 lines
|
||
|
||
These files violate the 1 250-line rule and must be split **before** any new modules are added:
|
||
|
||
| File | Lines | Split plan |
|
||
|------|-------|------------|
|
||
| `crates/symclaw-core/src/integrate_advanced/mod.rs` | 1 844 | Split into `rational.rs`, `risch.rs`, `special.rs`, `mod.rs` (re-exports only) |
|
||
| `crates/symclaw-core/src/step_by_step.rs` | 1 267 | Split into `step_by_step/render.rs`, `step_by_step/trace.rs`, `step_by_step/mod.rs` |
|
||
|
||
Each split must preserve all existing tests, which move with the code they test.
|
||
|
||
### 0.3 Fix all existing `unused_*` warnings
|
||
|
||
Run `cargo fix --lib -p symclaw-core` and then manually resolve the remaining
|
||
warnings in `factor.rs`, `galois.rs`, `modular_gcd`, `packed_poly.rs`, and `streaming.rs`.
|
||
All warnings become errors in CI by adding to `Cargo.toml`:
|
||
|
||
```toml
|
||
[workspace.lints.rust]
|
||
unused = "deny"
|
||
```
|
||
|
||
---
|
||
|
||
## 1. Architecture Overview
|
||
|
||
```
|
||
symclaw/
|
||
├── crates/
|
||
│ ├── symclaw-core/ existing — extended heavily
|
||
│ ├── symclaw-quantum/ NEW — ZX-calculus, Clifford, Pauli, circuits
|
||
│ ├── symclaw-bio/ NEW — structural identifiability, reaction networks
|
||
│ ├── symclaw-qchem/ NEW — second quantization, molecular integrals
|
||
│ ├── symclaw-materials/ NEW — crystallography, space groups, band theory
|
||
│ ├── symclaw-gpu/ existing — add tensor-network + Clifford GPU modules
|
||
│ ├── symclaw-cli/ existing — add new REPL commands for each domain
|
||
│ ├── symclaw-python/ existing — add PyO3 bindings for new crates
|
||
│ ├── symclaw-wasm/ existing — add WASM exports for quantum + bio
|
||
│ ├── symclaw-skill/ existing — add skill actions for new domains
|
||
│ └── symclaw-collab/ existing — unchanged
|
||
└── PLAN.md
|
||
```
|
||
|
||
All new crates are **workspace members** and share `[workspace.dependencies]`.
|
||
|
||
---
|
||
|
||
## 2. Core Extensions (`symclaw-core`)
|
||
|
||
These extend the existing engine rather than being separate crates. They must be
|
||
done first because later crates depend on them.
|
||
|
||
### 2.1 Clifford / Geometric Algebra (`clifford.rs` → split at 1 250)
|
||
|
||
**Purpose:** `Cl(p,q)` multivector algebra — generalises complex numbers,
|
||
quaternions, spinors, and spacetime algebra. Required by both
|
||
`symclaw-quantum` (Clifford gate algebra) and `symclaw-qchem` (Dirac equation).
|
||
|
||
**Module layout:**
|
||
|
||
```
|
||
clifford/
|
||
├── mod.rs re-exports, top-level docs ≤ 100 lines
|
||
├── basis.rs BasisBlade, grade, dimension, metric signature ≤ 400 lines
|
||
├── multivector.rs Multivector<P,Q> type, add/sub/mul/neg ≤ 600 lines
|
||
├── products.rs geometric, inner, outer, left/right contraction ≤ 500 lines
|
||
├── involute.rs reverse, grade-involution, conjugate ≤ 250 lines
|
||
└── symbolic.rs Multivector<P,Q> over Expr (symbolic coefficients)≤ 400 lines
|
||
```
|
||
|
||
**TDD test requirements (all must pass before any commit):**
|
||
|
||
```rust
|
||
// clifford/basis.rs
|
||
#[test] fn grade_of_scalar_is_zero()
|
||
#[test] fn grade_of_vector_is_one()
|
||
#[test] fn basis_blade_count_for_dim_n() // 2^n blades
|
||
#[test] fn metric_signature_euclidean()
|
||
#[test] fn metric_signature_minkowski()
|
||
|
||
// clifford/multivector.rs
|
||
#[test] fn add_multivectors()
|
||
#[test] fn mul_two_vectors_gives_scalar_plus_bivector()
|
||
#[test] fn complex_numbers_as_cl_0_1() // i² = -1
|
||
#[test] fn quaternions_as_cl_0_2() // i²=j²=k²=ijk=-1
|
||
#[test] fn pauli_algebra_as_cl_3_0()
|
||
|
||
// clifford/products.rs
|
||
#[test] fn outer_product_grade_adds()
|
||
#[test] fn inner_product_grade_subtracts()
|
||
#[test] fn geometric_product_associative()
|
||
#[test] fn reversion_involution()
|
||
|
||
// clifford/symbolic.rs
|
||
#[test] fn symbolic_multivector_diff_wrt_scalar()
|
||
#[test] fn symbolic_multivector_latex_output()
|
||
```
|
||
|
||
### 2.2 Exterior / Grassmann Algebra (`exterior.rs`)
|
||
|
||
**Purpose:** Antisymmetric tensor algebra — fermionic operators in QChem,
|
||
differential forms in geometry, determinant computation.
|
||
|
||
```
|
||
exterior/
|
||
├── mod.rs
|
||
├── form.rs DifferentialForm, wedge product ≤ 500 lines
|
||
└── algebra.rs ExteriorAlgebra<N>, grade decomposition ≤ 500 lines
|
||
```
|
||
|
||
**TDD tests:**
|
||
|
||
```rust
|
||
#[test] fn wedge_anticommutes() // α∧β = -β∧α
|
||
#[test] fn wedge_with_self_is_zero() // α∧α = 0
|
||
#[test] fn wedge_associativity()
|
||
#[test] fn n_form_on_n_dim_space_is_scalar_multiple()
|
||
#[test] fn exterior_derivative_of_zero_form()
|
||
#[test] fn d_squared_is_zero() // d(dω) = 0
|
||
```
|
||
|
||
### 2.3 Permutation Group (`permutation.rs`)
|
||
|
||
**Purpose:** Symmetric group Sₙ — genome rearrangements, Young tableaux,
|
||
representation theory (needed for crystallography).
|
||
|
||
```
|
||
permutation/
|
||
├── mod.rs
|
||
├── perm.rs Permutation, cycle notation, order, sign ≤ 400 lines
|
||
├── group.rs SymmetricGroup, subgroups, cosets, conjugacy ≤ 500 lines
|
||
└── young.rs YoungTableau, hook length formula, RSK ≤ 400 lines
|
||
```
|
||
|
||
**TDD tests:**
|
||
|
||
```rust
|
||
#[test] fn identity_permutation()
|
||
#[test] fn cycle_decomposition()
|
||
#[test] fn permutation_order()
|
||
#[test] fn permutation_sign() // even/odd
|
||
#[test] fn composition_is_associative()
|
||
#[test] fn inverse_undoes_permutation()
|
||
#[test] fn young_tableau_hook_length()
|
||
#[test] fn rsk_correspondence_bijection()
|
||
```
|
||
|
||
### 2.4 Cyclotomic Fields (`cyclotomic.rs`)
|
||
|
||
**Purpose:** Exact arithmetic in `ℚ(ζₙ)` — quantum gate angles (π/4, π/8 etc.),
|
||
number fields for Kochen-Specker proofs, minimal polynomial computation.
|
||
|
||
```
|
||
cyclotomic/
|
||
├── mod.rs
|
||
├── field.rs CyclotomicField<N>, elements as Q-polynomials ≤ 600 lines
|
||
└── minimal.rs minimal polynomial, conjugate, norm, trace ≤ 400 lines
|
||
```
|
||
|
||
**TDD tests:**
|
||
|
||
```rust
|
||
#[test] fn cyclotomic_4_gives_gaussian_integers()
|
||
#[test] fn cyclotomic_element_add()
|
||
#[test] fn cyclotomic_element_mul()
|
||
#[test] fn cyclotomic_element_norm()
|
||
#[test] fn minimal_polynomial_degree()
|
||
#[test] fn sqrt2_in_cyclotomic_8()
|
||
#[test] fn euler_phi_degree()
|
||
```
|
||
|
||
### 2.5 New `FuncId` variants and `Expr` variants
|
||
|
||
Extend `crates/symclaw-core/src/ast/functions.rs`:
|
||
|
||
```rust
|
||
// Quantum / Clifford
|
||
FuncId::PauliX, FuncId::PauliY, FuncId::PauliZ,
|
||
FuncId::Hadamard, FuncId::CNOT,
|
||
FuncId::Dagger, // Hermitian conjugate †
|
||
|
||
// Chemistry
|
||
FuncId::Create, // a† fermionic creation
|
||
FuncId::Annihilate, // a fermionic annihilation
|
||
|
||
// Biology / special
|
||
FuncId::HeavisideTheta,
|
||
FuncId::DiracDelta,
|
||
FuncId::Commutator, // [A,B] = AB - BA
|
||
FuncId::AntiCommutator, // {A,B} = AB + BA
|
||
```
|
||
|
||
Extend `crates/symclaw-core/src/ast/expr.rs` — new variants:
|
||
|
||
```rust
|
||
/// Bra-ket: ⟨φ| (bra), |ψ⟩ (ket), or ⟨φ|ψ⟩ (inner product)
|
||
BraKet {
|
||
kind: BraKetKind, // Bra | Ket | InnerProduct | OuterProduct
|
||
label: Arc<Expr>, // state label
|
||
label2: Option<Arc<Expr>>, // second label for inner/outer products
|
||
},
|
||
|
||
/// Quantum operator acting on a state
|
||
OperatorApply {
|
||
op: Arc<Expr>,
|
||
state: Arc<Expr>,
|
||
},
|
||
```
|
||
|
||
Every new `Expr` variant requires:
|
||
- A `Display` arm in `ast/display.rs`
|
||
- A `LaTeX` arm in `latex.rs`
|
||
- A simplification arm in `simplify.rs`
|
||
- A differentiation arm (or explicit "not differentiable" error) in `differentiate.rs`
|
||
- A parse arm in `parser.rs` (or documented that parsing is via construction API)
|
||
- A full unit test in its own `#[cfg(test)]` block
|
||
|
||
### 2.6 Code generation targets — extend `codegen.rs`
|
||
|
||
Add new language targets:
|
||
|
||
```rust
|
||
pub enum Language {
|
||
// existing...
|
||
OpenQASM3, // quantum circuit export
|
||
Qiskit, // Python + Qiskit
|
||
PennyLane, // Python + PennyLane
|
||
Cirq, // Python + Cirq
|
||
SBML, // Systems Biology Markup Language (XML)
|
||
Julia, // already exists
|
||
}
|
||
```
|
||
|
||
**TDD tests per target:**
|
||
|
||
```rust
|
||
#[test] fn openqasm3_hadamard()
|
||
#[test] fn openqasm3_cnot()
|
||
#[test] fn qiskit_circuit_export()
|
||
#[test] fn sbml_reaction_network_export()
|
||
```
|
||
|
||
---
|
||
|
||
## 3. New Crate: `symclaw-quantum`
|
||
|
||
### Dependency on `symclaw-core`
|
||
|
||
```toml
|
||
[dependencies]
|
||
symclaw-core = { path = "../symclaw-core" }
|
||
```
|
||
|
||
### Module map
|
||
|
||
```
|
||
symclaw-quantum/src/
|
||
├── lib.rs
|
||
├── pauli/
|
||
│ ├── mod.rs
|
||
│ ├── group.rs Pauli group P_n, multiplication table ≤ 600 lines
|
||
│ ├── stabilizer.rs Stabilizer formalism, generator sets ≤ 700 lines
|
||
│ └── tableau.rs Binary symplectic tableau, Gaussian elim ≤ 600 lines
|
||
├── clifford_gates/
|
||
│ ├── mod.rs
|
||
│ ├── gates.rs Single-qubit Clifford gates as Cl(2,0) elements ≤ 500 lines
|
||
│ └── compose.rs Gate composition, adjoint, conjugation ≤ 400 lines
|
||
├── zx/
|
||
│ ├── mod.rs
|
||
│ ├── diagram.rs ZXDiagram: nodes (Z/X/H), edges (wires) ≤ 700 lines
|
||
│ ├── rewrite.rs ZX rewrite rules (spider, bialgebra, etc.) ≤ 800 lines
|
||
│ ├── simplify.rs Graph simplification via e-graph-style search ≤ 600 lines
|
||
│ ├── extract.rs Circuit extraction from simplified ZX diagram ≤ 500 lines
|
||
│ └── to_circuit.rs ZXDiagram → QuantumCircuit ≤ 400 lines
|
||
├── circuit/
|
||
│ ├── mod.rs
|
||
│ ├── gate.rs Gate enum: H, X, Y, Z, CNOT, T, S, Rz(θ)… ≤ 500 lines
|
||
│ ├── circuit.rs QuantumCircuit: DAG of gates + qubits ≤ 700 lines
|
||
│ ├── optimize.rs Gate cancellation, commutation, T-count red. ≤ 800 lines
|
||
│ └── simulate.rs State-vector simulation (up to ~20 qubits) ≤ 700 lines
|
||
└── codegen/
|
||
├── mod.rs
|
||
├── openqasm3.rs QuantumCircuit → OpenQASM 3 ≤ 400 lines
|
||
├── qiskit.rs QuantumCircuit → Qiskit Python ≤ 400 lines
|
||
├── pennylane.rs QuantumCircuit → PennyLane Python ≤ 300 lines
|
||
└── cirq.rs QuantumCircuit → Cirq Python ≤ 300 lines
|
||
```
|
||
|
||
### ZX-Calculus Design
|
||
|
||
The ZX-calculus is a complete graphical calculus for quantum computing.
|
||
SymClaw's e-graph is the ideal engine for it because ZX simplification is
|
||
graph rewriting to a normal form — exactly what equality saturation does.
|
||
|
||
**Key types:**
|
||
|
||
```rust
|
||
/// A node in a ZX diagram.
|
||
pub enum ZXNode {
|
||
Z { phase: Arc<Expr> }, // Z-spider (green), phase in [0, 2π)
|
||
X { phase: Arc<Expr> }, // X-spider (red), phase in [0, 2π)
|
||
H, // Hadamard box
|
||
Input(usize), // boundary input wire n
|
||
Output(usize), // boundary output wire n
|
||
}
|
||
|
||
/// A ZX diagram: hypergraph of nodes connected by wires.
|
||
pub struct ZXDiagram {
|
||
nodes: Vec<ZXNode>,
|
||
wires: Vec<(NodeId, NodeId)>, // undirected edges
|
||
inputs: Vec<NodeId>,
|
||
outputs: Vec<NodeId>,
|
||
}
|
||
```
|
||
|
||
**Rewrite rules (all 11 core rules plus derived):**
|
||
|
||
| Rule | Description |
|
||
|------|-------------|
|
||
| Spider fusion | Two same-colour spiders → one (phases add) |
|
||
| Identity | Zero-phase spider with ≤ 2 legs → wire |
|
||
| π-copy | X-spider copies Z-spider through Hadamard |
|
||
| Bialgebra | Green-red bialgebra law |
|
||
| Hopf | Hadamard self-inverse |
|
||
| Euler decomposition | Z-X-Z = Euler angle |
|
||
| Phase teleportation | Move phases through wires |
|
||
| Supplementarity | Phase π/2 spiders |
|
||
| Local complementation | Graph state rewrite |
|
||
| Pivot | Graph state pivot |
|
||
| GS rule | Gflow preservation |
|
||
|
||
Each rule implemented as a `fn(ZXDiagram) -> Option<ZXDiagram>` with a matching
|
||
unit test showing before and after.
|
||
|
||
### TDD test plan for `symclaw-quantum`
|
||
|
||
**pauli/**
|
||
```rust
|
||
#[test] fn pauli_multiplication_table()
|
||
#[test] fn pauli_group_order_is_16() // ±{I,X,Y,Z}
|
||
#[test] fn pauli_commutator()
|
||
#[test] fn stabilizer_from_generators()
|
||
#[test] fn stabilizer_measurement()
|
||
#[test] fn tableau_gaussian_elimination()
|
||
```
|
||
|
||
**zx/**
|
||
```rust
|
||
#[test] fn spider_fusion_z()
|
||
#[test] fn spider_fusion_x()
|
||
#[test] fn identity_removal()
|
||
#[test] fn hadamard_self_inverse()
|
||
#[test] fn pi_copy_rule()
|
||
#[test] fn bialgebra_rule()
|
||
#[test] fn euler_decomposition()
|
||
#[test] fn cnot_zx_representation()
|
||
#[test] fn hadamard_zx_representation()
|
||
#[test] fn t_gate_zx_representation()
|
||
#[test] fn circuit_roundtrip() // circuit → ZX → simplify → extract → circuit
|
||
#[test] fn t_count_reduction_example() // concrete circuit from literature
|
||
```
|
||
|
||
**circuit/**
|
||
```rust
|
||
#[test] fn bell_state_circuit()
|
||
#[test] fn quantum_fourier_transform_3q()
|
||
#[test] fn grover_2q()
|
||
#[test] fn circuit_depth()
|
||
#[test] fn gate_cancellation_hh() // H·H = I
|
||
#[test] fn gate_cancellation_cnot_cnot()
|
||
#[test] fn simulate_bell_state_statevector()
|
||
#[test] fn simulate_ghz_state()
|
||
#[test] fn openqasm3_roundtrip()
|
||
#[test] fn qiskit_output_compiles() // string contains valid Python keywords
|
||
```
|
||
|
||
---
|
||
|
||
## 4. New Crate: `symclaw-bio`
|
||
|
||
Builds on existing `symclaw-core` ODE, Gröbner, and polynomial modules.
|
||
The central algorithm is **SIAN-style structural identifiability analysis**,
|
||
which uses characteristic sets / Gröbner bases to determine whether ODE
|
||
model parameters are identifiable from input-output observations.
|
||
|
||
### Module map
|
||
|
||
```
|
||
symclaw-bio/src/
|
||
├── lib.rs
|
||
├── ode_model/
|
||
│ ├── mod.rs
|
||
│ ├── model.rs OdeModel: states, inputs, outputs, params ≤ 600 lines
|
||
│ ├── io_equations.rs Input-output equations via Lie derivatives ≤ 700 lines
|
||
│ └── validate.rs Dimension checks, variable name validation ≤ 300 lines
|
||
├── identifiability/
|
||
│ ├── mod.rs
|
||
│ ├── sian.rs SIAN algorithm (Gröbner basis approach) ≤ 900 lines
|
||
│ ├── differential.rs Differential algebra toolkit ≤ 700 lines
|
||
│ └── report.rs IdentifiabilityReport: globally/locally/not ≤ 300 lines
|
||
├── reactions/
|
||
│ ├── mod.rs
|
||
│ ├── network.rs ReactionNetwork: species, reactions, rates ≤ 600 lines
|
||
│ ├── kinetics.rs MassAction, MichaelisMenten, HillFunction ≤ 500 lines
|
||
│ ├── stoichiometry.rs Stoichiometry matrix, nullspace, deficiency ≤ 500 lines
|
||
│ └── sbml.rs SBML XML import/export ≤ 600 lines
|
||
├── population/
|
||
│ ├── mod.rs
|
||
│ ├── genetics.rs Hardy-Weinberg, drift ODEs, selection eqs ≤ 500 lines
|
||
│ └── phylo.rs Cavender-Farris-Neyman model, JC69, K80 ≤ 500 lines
|
||
└── genome/
|
||
├── mod.rs
|
||
├── rearrangement.rs Sorting by reversals/transpositions (symbolic)≤ 600 lines
|
||
└── codon.rs Genetic code algebra, degeneracy classes ≤ 400 lines
|
||
```
|
||
|
||
### SIAN Algorithm Detail
|
||
|
||
The structural identifiability analysis for an ODE system:
|
||
|
||
```
|
||
ẋ = f(x, p, u) x: states, p: parameters, u: inputs
|
||
y = g(x, p) y: observed outputs
|
||
```
|
||
|
||
is determined by:
|
||
|
||
1. Compute Lie derivatives `L_f^k g` for each output `y_i` up to order equal to
|
||
the number of states plus parameters.
|
||
2. Form the **input-output equations** by eliminating state variables from the
|
||
system using resultants / Gröbner bases.
|
||
3. Compute a Gröbner basis of the characteristic ideal with respect to a
|
||
block `lex` ordering (parameter block > state block).
|
||
4. For each parameter `p_j`, check if the colon ideal `I : (∂/∂p_j)^∞`
|
||
yields a unique solution → globally identifiable.
|
||
5. Collect results into `IdentifiabilityReport`.
|
||
|
||
The existing `poly`, `modular_gcd`, and `groebner` modules provide the
|
||
computational backend. The `ode` module provides Lie derivative computation.
|
||
|
||
The **monomial ordering trick** from arXiv:2202.xxxxx: using `grevlex` within
|
||
the parameter block and `lex` between blocks gives 3-10× speedup over pure
|
||
`lex` on biological models.
|
||
|
||
### TDD test plan for `symclaw-bio`
|
||
|
||
**ode_model/**
|
||
```rust
|
||
#[test] fn simple_sir_model_construction()
|
||
#[test] fn io_equations_for_linear_compartment()
|
||
#[test] fn lie_derivative_first_order()
|
||
#[test] fn lie_derivative_chain_rule()
|
||
```
|
||
|
||
**identifiability/**
|
||
```rust
|
||
#[test] fn globally_identifiable_linear_ode()
|
||
#[test] fn not_identifiable_symmetric_model()
|
||
#[test] fn locally_identifiable_example()
|
||
#[test] fn sir_parameter_identifiability()
|
||
#[test] fn lotka_volterra_identifiability()
|
||
#[test] fn grevlex_ordering_faster_than_lex() // property: same result, measured time
|
||
```
|
||
|
||
**reactions/**
|
||
```rust
|
||
#[test] fn mass_action_kinetics()
|
||
#[test] fn michaelis_menten_quasi_steady()
|
||
#[test] fn stoichiometry_matrix_construction()
|
||
#[test] fn network_deficiency_zero()
|
||
#[test] fn sbml_roundtrip_simple_network()
|
||
```
|
||
|
||
**population/**
|
||
```rust
|
||
#[test] fn hardy_weinberg_equilibrium()
|
||
#[test] fn allele_frequency_drift_ode()
|
||
#[test] fn jc69_substitution_matrix()
|
||
```
|
||
|
||
**genome/**
|
||
```rust
|
||
#[test] fn sorting_by_reversals_pancake()
|
||
#[test] fn transposition_distance_lower_bound()
|
||
#[test] fn codon_degeneracy_classes()
|
||
#[test] fn stop_codons_excluded()
|
||
```
|
||
|
||
---
|
||
|
||
## 5. New Crate: `symclaw-qchem`
|
||
|
||
Second quantization algebra + molecular integral symbolic framework.
|
||
No chemistry library dependencies — all symbolic, with numeric evaluation
|
||
delegated to `symclaw-core::eval` and `symclaw-gpu::eval`.
|
||
|
||
### Module map
|
||
|
||
```
|
||
symclaw-qchem/src/
|
||
├── lib.rs
|
||
├── second_quant/
|
||
│ ├── mod.rs
|
||
│ ├── operators.rs FermionOp, BosonOp, creation/annihilation ≤ 600 lines
|
||
│ ├── algebra.rs Anticommutation relations, normal ordering ≤ 700 lines
|
||
│ ├── wick.rs Wick's theorem: automated normal ordering ≤ 800 lines
|
||
│ └── hamiltonian.rs One/two-body Hamiltonian symbolic form ≤ 600 lines
|
||
├── integrals/
|
||
│ ├── mod.rs
|
||
│ ├── gaussian.rs Gaussian basis function symbolic forms ≤ 700 lines
|
||
│ ├── overlap.rs Overlap integrals (analytical formulae) ≤ 500 lines
|
||
│ ├── kinetic.rs Kinetic energy integrals ≤ 400 lines
|
||
│ ├── nuclear.rs Nuclear attraction integrals (Boys function) ≤ 500 lines
|
||
│ └── eri.rs Electron repulsion integrals (analytical) ≤ 700 lines
|
||
├── spin/
|
||
│ ├── mod.rs
|
||
│ ├── spinor.rs Two-component spinors, Pauli matrices ≤ 400 lines
|
||
│ └── coupling.rs Clebsch-Gordan coefficients, angular momentum ≤ 600 lines
|
||
└── vqe/
|
||
├── mod.rs
|
||
├── ansatz.rs UCC, UCCSD, HF reference state symbolic form ≤ 600 lines
|
||
└── gradient.rs Symbolic parameter-shift gradients ≤ 500 lines
|
||
```
|
||
|
||
### Second Quantization Design
|
||
|
||
Fermionic operators `â†ᵢ`, `âᵢ` satisfy the anticommutation relations:
|
||
|
||
```
|
||
{âᵢ, â†ⱼ} = δᵢⱼ
|
||
{âᵢ, âⱼ} = 0
|
||
{â†ᵢ, â†ⱼ} = 0
|
||
```
|
||
|
||
In SymClaw these are symbolic terms in an `Expr` tree using `FuncId::Create`
|
||
and `FuncId::Annihilate`. The `simplify` module is extended with a
|
||
fermionic normal-ordering pass that uses the anticommutation relations as
|
||
rewrite rules, implemented as pattern-matching over the `Expr` tree.
|
||
|
||
**Wick's theorem** is implemented as a recursive algorithm that expresses a
|
||
product of operators as a sum over all possible contractions. Each contraction
|
||
is represented as an `Expr` tree node. The algorithm terminates because each
|
||
step reduces the number of operators by 2 (one contraction at a time).
|
||
|
||
**Molecular integrals:** Gaussian basis functions have the form:
|
||
|
||
```
|
||
φ(r; α, l, m, n, A) = N · (x-Ax)^l (y-Ay)^m (z-Az)^n · exp(-α|r-A|²)
|
||
```
|
||
|
||
All one-electron integrals (overlap, kinetic, nuclear attraction) have closed
|
||
symbolic forms via the McMurchie-Davidson recurrence. SymClaw will implement
|
||
these recursions symbolically, yielding exact closed-form expressions as `Expr`
|
||
trees that can then be evaluated numerically via `symclaw-gpu::eval` for
|
||
batch computation.
|
||
|
||
### TDD test plan for `symclaw-qchem`
|
||
|
||
**second_quant/**
|
||
```rust
|
||
#[test] fn anticommutation_relation_same_index()
|
||
#[test] fn anticommutation_relation_diff_index()
|
||
#[test] fn normal_order_single_product()
|
||
#[test] fn normal_order_two_body()
|
||
#[test] fn wick_theorem_one_body()
|
||
#[test] fn wick_theorem_two_body_vacuum()
|
||
#[test] fn one_body_hamiltonian_form()
|
||
#[test] fn two_body_hamiltonian_hermitian()
|
||
```
|
||
|
||
**integrals/**
|
||
```rust
|
||
#[test] fn gaussian_s_orbital_normalization()
|
||
#[test] fn overlap_ss_same_center() // = 1 when normalized
|
||
#[test] fn overlap_ss_far_apart_is_zero() // limiting behaviour
|
||
#[test] fn kinetic_s_orbital()
|
||
#[test] fn nuclear_attraction_s_orbital()
|
||
#[test] fn eri_ssss() // (ss|ss) integral
|
||
#[test] fn mcmurchie_davidson_recursion_base_case()
|
||
```
|
||
|
||
**spin/**
|
||
```rust
|
||
#[test] fn pauli_matrices_from_spinors()
|
||
#[test] fn clebsch_gordan_half_half() // 1/2 ⊗ 1/2 = 0 ⊕ 1
|
||
#[test] fn angular_momentum_algebra() // [Jx,Jy] = iJz
|
||
```
|
||
|
||
**vqe/**
|
||
```rust
|
||
#[test] fn uccsd_ansatz_parameterised()
|
||
#[test] fn parameter_shift_gradient_rule()
|
||
#[test] fn hf_reference_state()
|
||
```
|
||
|
||
---
|
||
|
||
## 6. New Crate: `symclaw-materials`
|
||
|
||
Crystallographic group algebra and band structure symbolic tools.
|
||
|
||
### Module map
|
||
|
||
```
|
||
symclaw-materials/src/
|
||
├── lib.rs
|
||
├── groups/
|
||
│ ├── mod.rs
|
||
│ ├── point_group.rs 32 crystallographic point groups (Schoenflies)≤ 800 lines
|
||
│ ├── space_group.rs 230 space groups, Wyckoff positions ≤ 900 lines
|
||
│ └── character.rs Character tables, irreducible representations ≤ 700 lines
|
||
├── lattice/
|
||
│ ├── mod.rs
|
||
│ ├── bravais.rs 14 Bravais lattices, reciprocal vectors ≤ 500 lines
|
||
│ └── miller.rs Miller indices, plane spacing, diffraction ≤ 400 lines
|
||
├── structure/
|
||
│ ├── mod.rs
|
||
│ ├── crystal.rs Crystal structure: unit cell + basis atoms ≤ 500 lines
|
||
│ └── factor.rs Structure factor F(hkl), extinction rules ≤ 400 lines
|
||
└── bonding/
|
||
├── mod.rs
|
||
└── descriptor.rs ICOHP-style bonding descriptors (symbolic) ≤ 500 lines
|
||
```
|
||
|
||
### TDD test plan for `symclaw-materials`
|
||
|
||
```rust
|
||
// groups/
|
||
#[test] fn point_group_oh_order_48()
|
||
#[test] fn point_group_td_order_24()
|
||
#[test] fn space_group_225_fcc_structure()
|
||
#[test] fn wyckoff_positions_for_sg_229()
|
||
#[test] fn character_table_c2v()
|
||
#[test] fn great_orthogonality_theorem()
|
||
|
||
// lattice/
|
||
#[test] fn fcc_reciprocal_lattice()
|
||
#[test] fn bcc_miller_indices_110()
|
||
#[test] fn bragg_law()
|
||
|
||
// structure/
|
||
#[test] fn nacl_structure_factor()
|
||
#[test] fn diamond_systematic_absences()
|
||
```
|
||
|
||
---
|
||
|
||
## 7. GPU Extensions (`symclaw-gpu`)
|
||
|
||
Add two new GPU modules to the existing crate:
|
||
|
||
### 7.1 `tensor_network.rs` — Tensor Network Contraction (≤ 900 lines)
|
||
|
||
Contract arbitrary tensor networks on GPU — required for quantum circuit
|
||
simulation beyond ~20 qubits and for lattice QCD.
|
||
|
||
```rust
|
||
pub struct TensorNetwork {
|
||
tensors: Vec<GpuTensor>,
|
||
contractions: Vec<(usize, usize, Vec<(usize, usize)>)>, // (t1, t2, [(i1,i2)])
|
||
}
|
||
impl TensorNetwork {
|
||
pub fn contract_all(&self, runtime: &CubeclRuntime) -> GpuTensor;
|
||
pub fn optimal_order(&self) -> Vec<(usize, usize)>; // greedy min-cut ordering
|
||
}
|
||
```
|
||
|
||
**TDD tests:**
|
||
```rust
|
||
#[test] fn matrix_multiply_as_tensor_contraction()
|
||
#[test] fn trace_as_tensor_contraction()
|
||
#[test] fn bell_state_tensor_network()
|
||
#[test] fn ghz_tensor_network_3q()
|
||
#[test] fn optimal_contraction_order_star_graph()
|
||
```
|
||
|
||
### 7.2 `clifford_sim.rs` — GPU Clifford Circuit Simulation (≤ 600 lines)
|
||
|
||
Clifford circuits can be simulated in polynomial time via tableau methods.
|
||
GPU-parallelise the binary symplectic Gaussian elimination for large qubit counts.
|
||
|
||
**TDD tests:**
|
||
```rust
|
||
#[test] fn clifford_sim_100_qubits()
|
||
#[test] fn clifford_sim_bell_state()
|
||
#[test] fn tableau_gpu_matches_cpu()
|
||
```
|
||
|
||
---
|
||
|
||
## 8. CLI Extensions (`symclaw-cli`)
|
||
|
||
Add new REPL commands for each domain:
|
||
|
||
| Command | Description |
|
||
|---------|-------------|
|
||
| `:quantum circuit <OpenQASM>` | Parse and display circuit |
|
||
| `:zx simplify <circuit>` | ZX-calculus simplification |
|
||
| `:bio sian <model>` | Run structural identifiability |
|
||
| `:bio reaction <SBML>` | Load and analyse reaction network |
|
||
| `:qchem hamiltonian <molecule>` | Build second-quantized Hamiltonian |
|
||
| `:mat spacegroup <HM symbol>` | Look up space group info |
|
||
| `:clifford <Cl(p,q) expr>` | Evaluate Clifford algebra expression |
|
||
|
||
Each command must have:
|
||
- A `#[test]` that exercises the command with a concrete valid input
|
||
- A `#[test]` that returns a meaningful error on invalid input
|
||
|
||
---
|
||
|
||
## 9. Python Bindings (`symclaw-python`)
|
||
|
||
Add PyO3 bindings for each new crate:
|
||
|
||
```python
|
||
# quantum
|
||
from symclaw import QuantumCircuit, ZXDiagram, PauliGroup
|
||
circ = QuantumCircuit(3)
|
||
circ.h(0); circ.cnot(0, 1); circ.cnot(1, 2)
|
||
zx = ZXDiagram.from_circuit(circ)
|
||
simplified = zx.simplify()
|
||
print(simplified.to_circuit().to_openqasm3())
|
||
|
||
# bio
|
||
from symclaw.bio import OdeModel, sian
|
||
model = OdeModel(states=["S","I","R"], params=["β","γ"])
|
||
model.add_ode("S", "-β*S*I")
|
||
model.add_ode("I", "β*S*I - γ*I")
|
||
model.add_ode("R", "γ*I")
|
||
model.add_output("I")
|
||
report = sian(model)
|
||
print(report) # {"β": "globally_identifiable", "γ": "globally_identifiable"}
|
||
|
||
# qchem
|
||
from symclaw.qchem import FermionOp, wick_normal_order
|
||
a, adag = FermionOp.annihilate, FermionOp.create
|
||
expr = adag(0) * adag(1) * a(1) * a(0)
|
||
print(wick_normal_order(expr))
|
||
```
|
||
|
||
Each Python-facing function must have a Python-level docstring and a
|
||
corresponding `#[test]` in Rust that exercises the same logic.
|
||
|
||
---
|
||
|
||
## 10. WASM Extensions (`symclaw-wasm`)
|
||
|
||
Add browser-accessible exports for quantum and bio:
|
||
|
||
```typescript
|
||
// quantum
|
||
export function zx_simplify(circuit_json: string): string;
|
||
export function circuit_to_openqasm3(circuit_json: string): string;
|
||
export function simulate_statevector(circuit_json: string, n_qubits: number): Float64Array;
|
||
|
||
// bio
|
||
export function run_sian(model_json: string): string;
|
||
export function reaction_network_odes(sbml_xml: string): string;
|
||
```
|
||
|
||
---
|
||
|
||
## 11. Skill Actions (`symclaw-skill`)
|
||
|
||
Add 14 new JSON-RPC skill actions:
|
||
|
||
| Action | Input | Output |
|
||
|--------|-------|--------|
|
||
| `quantum_circuit` | `{"gates": [...]}` | Circuit diagram + metrics |
|
||
| `zx_simplify` | `{"circuit": {...}}` | Simplified diagram + T-count |
|
||
| `zx_extract` | `{"diagram": {...}}` | Extracted circuit |
|
||
| `pauli_product` | `{"ops": ["X","Y","Z"]}` | Product with phase |
|
||
| `sian` | `{"model": {...}}` | Identifiability report |
|
||
| `reaction_network` | `{"reactions": [...]}` | ODEs + stoichiometry |
|
||
| `normal_order` | `{"expr": "..."}` | Normal-ordered expression |
|
||
| `wick_contract` | `{"expr": "..."}` | Contracted expression |
|
||
| `molecular_integral` | `{"type": "overlap", "basis": [...]}` | Closed-form integral |
|
||
| `spacegroup` | `{"symbol": "Fm-3m"}` | Group info + Wyckoff |
|
||
| `point_group` | `{"symbol": "Oh"}` | Character table |
|
||
| `structure_factor` | `{"crystal": {...}, "hkl": [1,1,0]}` | F(hkl) |
|
||
| `clifford_eval` | `{"pq": [3,0], "expr": "..."}` | Multivector result |
|
||
| `cyclotomic` | `{"n": 8, "expr": "..."}` | Exact cyclotomic arithmetic |
|
||
|
||
---
|
||
|
||
## 12. Implementation Phases & Sequencing
|
||
|
||
### Phase 0 — Housekeeping (1–2 days)
|
||
1. Bump `rust-version = "1.94.0"` and `edition = "2024"` in workspace
|
||
2. Split `integrate_advanced/mod.rs` → `rational.rs` + `risch.rs` + `special.rs`
|
||
3. Split `step_by_step.rs` → `step_by_step/trace.rs` + `step_by_step/render.rs`
|
||
4. Fix all `unused_*` warnings → promote to `deny`
|
||
5. CI: add `--deny warnings` flag
|
||
|
||
### Phase 1 — Core extensions (1 week)
|
||
Order matters — later phases depend on these:
|
||
|
||
1. `clifford/` — multivector algebra
|
||
2. `exterior/` — Grassmann algebra
|
||
3. `permutation/` — symmetric group
|
||
4. `cyclotomic/` — exact field arithmetic
|
||
5. New `FuncId` variants + `Expr` variants (BraKet, OperatorApply)
|
||
6. `codegen.rs` — OpenQASM3, Qiskit, SBML targets
|
||
7. TDD: **all tests in §2 must pass before Phase 2 begins**
|
||
|
||
### Phase 2 — `symclaw-quantum` (2 weeks)
|
||
1. `pauli/` — Pauli group + stabilizer
|
||
2. `clifford_gates/` — gates as Clifford algebra elements
|
||
3. `circuit/` — gate DAG + state-vector simulator
|
||
4. `zx/` — diagram, rewrites, simplifier, extractor
|
||
5. `codegen/` — OpenQASM3 / Qiskit / PennyLane / Cirq emitters
|
||
6. GPU: `clifford_sim.rs`
|
||
7. TDD: **all tests in §3 must pass before Phase 3 begins**
|
||
|
||
### Phase 3 — `symclaw-bio` (1.5 weeks)
|
||
1. `ode_model/` — model builder + Lie derivative engine
|
||
2. `identifiability/sian.rs` — core SIAN algorithm
|
||
3. `reactions/` — reaction networks + SBML
|
||
4. `population/` + `genome/`
|
||
5. TDD: **all tests in §4 must pass before Phase 4 begins**
|
||
|
||
### Phase 4 — `symclaw-qchem` (2 weeks)
|
||
1. `second_quant/` — operators, algebra, Wick
|
||
2. `integrals/` — Gaussian basis, McMurchie-Davidson
|
||
3. `spin/` — spinors, Clebsch-Gordan
|
||
4. `vqe/` — UCCSD ansatz, parameter-shift gradient
|
||
5. TDD: **all tests in §5 must pass before Phase 5 begins**
|
||
|
||
### Phase 5 — `symclaw-materials` (1 week)
|
||
1. `groups/` — 32 point groups, 230 space groups (data-driven)
|
||
2. `lattice/` + `structure/` + `bonding/`
|
||
3. TDD: **all tests in §6 must pass before Phase 6 begins**
|
||
|
||
### Phase 6 — GPU extensions (1 week)
|
||
1. `tensor_network.rs`
|
||
2. `clifford_sim.rs`
|
||
3. Benchmark: compare CPU vs GPU for 10, 20, 50 qubit circuits
|
||
|
||
### Phase 7 — Surface layers (1 week)
|
||
1. CLI commands
|
||
2. Python bindings (PyO3)
|
||
3. WASM exports
|
||
4. Skill actions (22 → 36)
|
||
5. Update README, ARCHITECTURE.md, CHANGELOG.md
|
||
|
||
### Phase 8 — Integration & documentation (3 days)
|
||
1. End-to-end example notebooks (Jupyter via PyO3)
|
||
2. Web app: add quantum circuit visualizer, ZX diagram renderer
|
||
3. Update comparison table vs Mathematica/SymPy/PyZX
|
||
4. Tag release: `v0.2.0`
|
||
|
||
**Total estimated time: ~9 weeks solo, ~4–5 weeks with parallel workstreams.**
|
||
|
||
---
|
||
|
||
## 13. TDD Discipline Rules
|
||
|
||
These are non-negotiable for every commit:
|
||
|
||
1. **Test first:** Write the `#[test]` that calls the function before writing the function.
|
||
2. **No `todo!()`:** If a function can't be fully implemented, don't commit it. Draft on a branch.
|
||
3. **No `unimplemented!()`:** Same rule.
|
||
4. **No mock types:** Test against real implementations. If a dependency is heavy, use a small concrete example, not a stub.
|
||
5. **No `#[ignore]`:** If a test is slow, optimise it or gate it behind `#[cfg(feature = "slow_tests")]` — never ignore.
|
||
6. **Property tests:** Every algebraic law (associativity, commutativity, distributivity) must be covered by a `proptest!` macro test, not just hand-picked examples.
|
||
7. **No `unwrap()` / `expect()` in library code:** Use `?` and `thiserror`. The lint `clippy::unwrap_used = "deny"` is already in the workspace — enforce it.
|
||
8. **Error types:** Every new module gets its own `Error` enum via `thiserror`. No `anyhow` in library code (only in CLI/tests).
|
||
9. **File limit enforcement:** CI step runs `find crates -name '*.rs' | xargs wc -l | awk '$1 > 1250'` and fails if any file exceeds 1 250 lines.
|
||
|
||
---
|
||
|
||
## 14. CI Pipeline Additions
|
||
|
||
Add to `.github/workflows/ci.yml`:
|
||
|
||
```yaml
|
||
- name: Check file line counts
|
||
run: |
|
||
OVER=$(find crates -name '*.rs' | xargs wc -l 2>/dev/null \
|
||
| awk '$1 > 1250 && $2 != "total" {print $0}')
|
||
if [ -n "$OVER" ]; then
|
||
echo "Files exceed 1250 lines:"
|
||
echo "$OVER"
|
||
exit 1
|
||
fi
|
||
|
||
- name: Check no todo/unimplemented
|
||
run: |
|
||
if grep -rn 'todo!()\\|unimplemented!()' crates/; then
|
||
echo "Found todo!/unimplemented! macros"
|
||
exit 1
|
||
fi
|
||
|
||
- name: Clippy deny warnings
|
||
run: cargo clippy --all-targets --all-features -- -D warnings
|
||
|
||
- name: Test all workspace members
|
||
run: cargo test --workspace --all-features
|
||
```
|
||
|
||
---
|
||
|
||
## 15. Dependency Additions
|
||
|
||
Add to `[workspace.dependencies]` in root `Cargo.toml`:
|
||
|
||
```toml
|
||
# Quantum / ZX
|
||
petgraph = "0.6" # graph data structure for ZX diagrams, circuit DAGs
|
||
|
||
# Biology
|
||
quick-xml = "0.36" # SBML XML import/export
|
||
|
||
# Quantum chemistry / spin
|
||
half = "2" # f16 for GPU integral batches (already present)
|
||
|
||
# Proptest for algebraic law testing
|
||
proptest = { version = "1", features = ["std"] } # promote from dev-dep
|
||
```
|
||
|
||
No new dependencies beyond these. All math is implemented from scratch in Rust
|
||
to maintain the zero-dependency-on-commercial-CAS guarantee.
|
||
|
||
---
|
||
|
||
## 16. Versioning & Changelog
|
||
|
||
- Current: `v0.1.0`
|
||
- After Phase 2 (quantum): `v0.2.0`
|
||
- After Phase 4 (bio + qchem): `v0.3.0`
|
||
- After Phase 5+ (materials + GPU): `v0.4.0`
|
||
- After Phase 7 (all surfaces): `v0.5.0`
|
||
|
||
Each phase's completion is tagged in git. CHANGELOG.md is updated at each tag.
|
||
|
||
---
|
||
|
||
## 17. README / Documentation Updates
|
||
|
||
After each phase, update:
|
||
- `README.md`: module table, stats (line count, test count, crate count)
|
||
- `ARCHITECTURE.md`: new crate dependency graph
|
||
- `docs/quantum.md` (new)
|
||
- `docs/bio.md` (new)
|
||
- `docs/qchem.md` (new)
|
||
- `docs/materials.md` (new)
|
||
|
||
Comparison table additions:
|
||
|
||
| Feature | SymClaw v0.5 | PyZX | SIAN | OpenFermion | ASE |
|
||
|---------|-------------|------|------|-------------|-----|
|
||
| ZX-calculus | ✅ GPU | ✅ | ❌ | ❌ | ❌ |
|
||
| Structural identifiability | ✅ GPU Gröbner | ❌ | ✅ Maple | ❌ | ❌ |
|
||
| Second quantization | ✅ | ❌ | ❌ | ✅ | ❌ |
|
||
| Molecular integrals | ✅ symbolic | ❌ | ❌ | ❌ | ❌ |
|
||
| Space group algebra | ✅ | ❌ | ❌ | ❌ | ✅ partial |
|
||
| AI agent integration | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||
| GPU acceleration | ✅ 11 modules | ❌ | ❌ | ❌ | ❌ |
|
||
| Open source | ✅ MIT/Apache | ✅ MIT | ❌ Maple | ✅ Apache | ✅ LGPL |
|
||
|
||
---
|
||
|
||
*End of PLAN.md — Last updated 2026-03-19*
|