Files
symclaw/benchmarks/benches/engine_bench.rs
T

300 lines
8.4 KiB
Rust

use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main};
use std::sync::Arc;
use symclaw_core::ast::Expr;
use symclaw_core::differentiate::{differentiate, nth_derivative};
use symclaw_core::egraph::egraph_simplify;
use symclaw_core::integrate::integrate;
use symclaw_core::interner::Symbol;
use symclaw_core::latex::to_latex;
use symclaw_core::parser::parse;
use symclaw_core::series::{maclaurin, taylor};
use symclaw_core::simplify::simplify;
use symclaw_core::solve::solve;
// ── Helpers ──────────────────────────────────────────────────────
fn p(input: &str) -> Arc<Expr> {
parse(input).unwrap_or_else(|e| panic!("parse failed for {input:?}: {e}"))
}
fn sym(name: &str) -> Symbol {
Symbol::new(name)
}
// ── Parsing ──────────────────────────────────────────────────────
fn bench_parsing(c: &mut Criterion) {
let mut group = c.benchmark_group("parsing");
let cases = [
("simple", "x + 1"),
("medium", "x^3 * sin(x) + 2*x^2 - cos(x/2)"),
("complex", "(x^4 + 3*x^3 - 2*x^2 + x - 1) / (x^2 + 1)"),
];
for (name, input) in &cases {
group.bench_with_input(BenchmarkId::new("parse", name), input, |b, input| {
b.iter(|| parse(black_box(input)).unwrap());
});
}
group.finish();
}
// ── Simplification ──────────────────────────────────────────────
fn bench_simplification(c: &mut Criterion) {
let mut group = c.benchmark_group("simplification");
// Identity removal
let identity_cases = [
("add_zero", "x + 0"),
("mul_one", "x * 1"),
("pow_one", "x^1"),
];
for (name, input) in &identity_cases {
let expr = p(input);
group.bench_with_input(BenchmarkId::new("identity", name), &expr, |b, expr| {
b.iter(|| simplify(black_box(expr)));
});
}
// Constant folding
{
let expr = p("2 + 3 + 4 + 5");
group.bench_function("constant_folding", |b| {
b.iter(|| simplify(black_box(&expr)));
});
}
// Like-term combination
{
let expr = p("3*x + 5*x + 2*x");
group.bench_function("like_terms", |b| {
b.iter(|| simplify(black_box(&expr)));
});
}
// Complex via e-graph
{
let expr = p("(x^2 - 1) / (x - 1)");
group.bench_function("egraph_complex", |b| {
b.iter(|| egraph_simplify(black_box(&expr)));
});
}
group.finish();
}
// ── Differentiation ─────────────────────────────────────────────
fn bench_differentiation(c: &mut Criterion) {
let mut group = c.benchmark_group("differentiation");
let x = sym("x");
// Polynomial
{
let expr = p("x^5 + 3*x^3 - x");
group.bench_function("polynomial", |b| {
b.iter(|| differentiate(black_box(&expr), x));
});
}
// Trigonometric
{
let expr = p("sin(x^2) * cos(x)");
group.bench_function("trigonometric", |b| {
b.iter(|| differentiate(black_box(&expr), x));
});
}
// Chain rule depth
{
let expr = p("sin(cos(exp(x)))");
group.bench_function("chain_rule_deep", |b| {
b.iter(|| differentiate(black_box(&expr), x));
});
}
// Higher-order: d^5/dx^5(x^6)
{
let expr = p("x^6");
group.bench_function("higher_order_5th", |b| {
b.iter(|| nth_derivative(black_box(&expr), x, 5));
});
}
group.finish();
}
// ── Integration ─────────────────────────────────────────────────
fn bench_integration(c: &mut Criterion) {
let mut group = c.benchmark_group("integration");
let x = sym("x");
// Power rule
{
let expr = p("x^4");
group.bench_function("power_rule", |b| {
b.iter(|| integrate(black_box(&expr), x));
});
}
// Trig
{
let expr = p("sin(x) * cos(x)");
group.bench_function("trig", |b| {
b.iter(|| integrate(black_box(&expr), x));
});
}
// By parts
{
let expr = p("x * exp(x)");
group.bench_function("by_parts", |b| {
b.iter(|| integrate(black_box(&expr), x));
});
}
group.finish();
}
// ── Solving ─────────────────────────────────────────────────────
fn bench_solving(c: &mut Criterion) {
let mut group = c.benchmark_group("solving");
let x = sym("x");
// Linear: 2*x + 6 = 0
{
let expr = p("2*x + 6");
group.bench_function("linear", |b| {
b.iter(|| solve(black_box(&expr), x));
});
}
// Quadratic: x^2 - 5*x + 6 = 0
{
let expr = p("x^2 - 5*x + 6");
group.bench_function("quadratic", |b| {
b.iter(|| solve(black_box(&expr), x));
});
}
// Cubic: x^3 - 6*x^2 + 11*x - 6 = 0
{
let expr = p("x^3 - 6*x^2 + 11*x - 6");
group.bench_function("cubic", |b| {
b.iter(|| solve(black_box(&expr), x));
});
}
group.finish();
}
// ── Series ──────────────────────────────────────────────────────
fn bench_series(c: &mut Criterion) {
let mut group = c.benchmark_group("series");
let x = sym("x");
// Maclaurin sin(x) order 10
{
let expr = p("sin(x)");
group.bench_function("maclaurin_sin_10", |b| {
b.iter(|| maclaurin(black_box(&expr), x, 10));
});
}
// Taylor exp(x) about 1, order 8
{
let expr = p("exp(x)");
let point = Expr::from(1i64);
group.bench_function("taylor_exp_about1_8", |b| {
b.iter(|| taylor(black_box(&expr), x, black_box(&point), 8));
});
}
// Maclaurin x * sin(x) order 6
{
let expr = p("x * sin(x)");
group.bench_function("maclaurin_xsinx_6", |b| {
b.iter(|| maclaurin(black_box(&expr), x, 6));
});
}
group.finish();
}
// ── E-graph ─────────────────────────────────────────────────────
fn bench_egraph(c: &mut Criterion) {
let mut group = c.benchmark_group("egraph");
// Simple
{
let expr = p("x * 1 + 0");
group.bench_function("simple_identity", |b| {
b.iter(|| egraph_simplify(black_box(&expr)));
});
}
// Trig identity
{
let expr = p("sin(x)^2 + cos(x)^2");
group.bench_function("trig_identity", |b| {
b.iter(|| egraph_simplify(black_box(&expr)));
});
}
// Distribution
{
let expr = p("x * (y + z)");
group.bench_function("distribution", |b| {
b.iter(|| egraph_simplify(black_box(&expr)));
});
}
group.finish();
}
// ── LaTeX Rendering ─────────────────────────────────────────────
fn bench_latex(c: &mut Criterion) {
let mut group = c.benchmark_group("latex");
// Simple
{
let expr = p("x^2 + 3*x - 7");
group.bench_function("simple", |b| {
b.iter(|| to_latex(black_box(&expr)));
});
}
// Complex fraction
{
let expr = p("(x^4 + 3*x^3 - 2*x^2 + x - 1) / (x^2 + 1)");
group.bench_function("complex_fraction", |b| {
b.iter(|| to_latex(black_box(&expr)));
});
}
group.finish();
}
// ── Criterion Harness ───────────────────────────────────────────
criterion_group!(
benches,
bench_parsing,
bench_simplification,
bench_differentiation,
bench_integration,
bench_solving,
bench_series,
bench_egraph,
bench_latex,
);
criterion_main!(benches);