alkahest

A high-performance computer algebra system for Python and Rust

pip install alkahest

Python 3.9–3.13 · PyPI

Default wheels include egraph and groebner; LLVM JIT and parallel are opt-in. On Linux x86_64, optional +jit / +full wheels are on GitHub Releases. See Getting started for URLs, LD_LIBRARY_PATH, and building from source.

Simplification you can audit

Every rewrite records the rule applied — not just the final expression.

from alkahest import ExprPool, simplify

pool = ExprPool()
x = pool.symbol("x")
r = simplify(x + pool.integer(0))
print(r.value)   # x
print(r.steps)   # e.g. [RewriteStep(rule='add_zero', ...)]

Dense univariate polynomials (FLINT)

GCD and exact division stay in a FLINT-backed representation for heavy polynomial work.

from alkahest import ExprPool, UniPoly

pool = ExprPool()
x = pool.symbol("x")
p = UniPoly.from_symbolic(x**3 + pool.integer(-1), x)
q = UniPoly.from_symbolic(x + pool.integer(-1), x)
print(p.gcd(q))   # x - 1
print(p // q)     # x^2 + x + 1

Plotting — no bundled dependency

alkahest detects what you have installed (Matplotlib or Plotly) and calls into it. A dependency-free SVG renderer is built into the Rust kernel for zero-install use.

import alkahest as ak

pool = ak.ExprPool()
x = pool.symbol("x")

# Curve — uses matplotlib by default, or plotly if specified
ak.plot(ak.sin(x), x, (-6.28, 6.28))
ak.plot(ak.sin(x), x, (-6.28, 6.28), backend="plotly")

# 2-D surface
y = pool.symbol("y")
ak.plot3d(ak.sin(x) * ak.cos(y), x, y, (-5, 5), (-5, 5))

# Standalone SVG — no plotting library needed
svg = ak.plot_svg(ak.sin(x), x, (-6, 6))

Use the Rust kernel directly

alkahest-cas is a native Rust crate — embed the CAS in your own library or CLI without a Python runtime.

// Cargo.toml: alkahest-cas = "2"
use alkahest_cas::{ExprPool, diff, simplify, render_latex, parse};
use alkahest_cas::kernel::Domain;
use std::collections::HashMap;

fn main() {
    let pool = ExprPool::new();
    let x = pool.symbol("x", Domain::Real);
    let mut syms = HashMap::from([("x".to_owned(), x)]);

    // parse from a string
    let expr = parse("sin(x)^2 + cos(x)^2", &pool, &mut syms).unwrap();

    // differentiate
    let d = diff(expr, x, &pool).unwrap();
    println!("{}", render_latex(d.value, &pool));
}