diff --git a/README.md b/README.md new file mode 100644 index 0000000..2b839b0 --- /dev/null +++ b/README.md @@ -0,0 +1,134 @@ +# circuit-cas + +A computer algebra system in Rust for algebraic circuit verification over polynomial rings with integer coefficients. + +## Overview + +`circuit-cas` provides two main layers: + +- **`poly`** — multivariate polynomials over ℤ, Gröbner bases, and ideals +- **`circuit`** — arithmetic circuits (DAGs of add/mul nodes) quotiented by an ideal + +The intended use case is verifying arithmetic circuits modulo an ideal: two circuits computing the same polynomial in the quotient ring are equivalent. + +## Modules + +### `poly` + +#### Variables — `poly::var` + +Variables are any type implementing the `Var` trait. The built-in `StaticVar` carries a static string name and optional integer indices, with a `var!` macro for construction: + +```rust +use circuit_cas::var; + +let x = var!("x"); // x +let x0 = var!("x", 0); // x₀ +let x01 = var!("x", 0, 1); // x₀,₁ +``` + +#### Polynomials — `poly::flat` + +`Poly` is a multivariate polynomial over ℤ backed by a `HashMap, i32>`. Arithmetic operators (`+`, `-`, `*`) and scalar multiplication are provided. Monomial ordering uses pure lexicographic order (lex) with variable names sorted alphabetically. + +```rust +// x² - 2xy (using array-of-pairs syntax) +let f: Poly = [ + (1i32, Mono::from([("x", 2u32)])), + (-2i32, Mono::from([("x", 1u32), ("y", 1u32)])), +].into_iter().collect(); +``` + +Key operations: + +| Method | Description | +|--------|-------------| +| `Poly::is_zero` | whether the polynomial is the zero polynomial | +| `Poly::leading_term_lex` | leading `(monomial, coefficient)` under lex | +| `Poly::s_poly(&other)` | S-polynomial of two polynomials | +| `Poly::div_rem(divisor)` | pseudo-division: returns `(d, q, r)` with `lc(g)^d·f = q·g + r` | + +#### Ideals — `poly::ideal` + +`Ideal` uses the typestate pattern to track at the type level whether its generators form a Gröbner basis: + +```rust +use circuit_cas::poly::ideal::{Ideal, Generators, GroebnerBasis}; + +// Arbitrary generators +let ideal: Ideal = Ideal::new(vec![f1, f2]); + +// Compute the reduced Gröbner basis — consumes the original ideal +let gb: Ideal = ideal.groebner_basis(); + +// Ideal membership test (only available on GroebnerBasis state) +assert!(gb.contains(&some_poly)); +``` + +`Ideal` implements `Display` as `` and `FromIterator>` for construction from an iterator. + +#### Buchberger's algorithm — `poly::buchberger` + +```rust +use circuit_cas::poly::buchberger::{groebner_basis, is_groebner_basis}; + +let basis = groebner_basis(vec![f1, f2]); +assert!(is_groebner_basis(&basis)); +``` + +`groebner_basis` returns the **reduced** Gröbner basis: after running Buchberger's algorithm it minimizes (removes redundant generators) and interreduces (fully reduces each generator modulo the others). + +### `circuit` + +#### DAG — `circuit::dag` + +`Circuit` is a DAG of `Node` values, with structural sharing via interning. Nodes are `Leaf(V)`, `Scale(id, i32)`, `Sum(id, id)`, or `Prod(id, id)`. + +#### Quotient ring — `circuit::quotient` + +`Quotient` pairs an arithmetic circuit with a `Ideal`, representing a circuit in the quotient ring `ℤ[vars] / I`. + +```rust +use circuit_cas::circuit::quotient::Quotient; + +// Build from a list of generators — Gröbner basis is computed automatically +let quotient: Quotient = vec![f1, f2, f3].into_iter().collect(); + +// Or from a pre-computed Gröbner basis +let quotient = Quotient::from(gb); + +println!("{quotient}"); // C/ +``` + +## Example + +```rust +use circuit_cas::{var, circuit::quotient::Quotient, poly::var::StaticVar}; + +fn main() { + let x = var!("x"); + let xb = var!("x\u{0304}"); // x̄ + + // Idempotency relations: x² = x, x̄² = x̄, x·x̄ = x + let idem = vec![ + 1 * (&x ^ 2) - 1 * (&x ^ 1), + 1 * (&xb ^ 2) - 1 * (&xb ^ 1), + 1 * ((&x ^ 1) * (&xb ^ 1)) - 1 * (&x ^ 1), + ]; + + let quotient: Quotient = idem.into_iter().collect(); + println!("{quotient}"); +} +``` + +Run with: + +``` +cargo run --example quotient +``` + +## Development + +``` +cargo test # run all tests +```