arael 0.4.0

Nonlinear optimization framework with compile-time symbolic differentiation
Documentation
# Symbolic Math Library (arael-sym)

The symbolic math library provides expression trees with automatic differentiation, algebraic simplification, code generation, and common subexpression elimination.

## Basics

```rust
use arael::sym::*;

arael::sym! {
    let x = symbol("x");
    let y = symbol("y");

    println!("x + y = {}", x + y);             // x + y
    println!("x * y - 1 = {}", x * y - 1.0);   // x * y - 1
    println!("x^2 = {}", pow(x, c(2.0)));       // x^2
}
```

The `arael::sym!` macro auto-inserts `.clone()` on variable reuse, eliminating ownership boilerplate.

### Auto-simplification

All operations auto-simplify:

```rust
arael::sym! {
    let x = symbol("x");
    let y = symbol("y");
    println!("{}", (x + y) / (x + y)); // 1
    println!("{}", x + 0.0);          // x
    println!("{}", x * 1.0);          // x
    println!("{}", x * 0.0);          // 0
    println!("{}", -(-x));             // x
    println!("{}", x - x);            // 0
    println!("{}", 3.0 * x + 2.0 * x); // 5 * x
    println!("{}", x * x);            // x^2
}
```

## Derivatives

The library implements all standard calculus rules:

```rust
arael::sym! {
    let x = symbol("x");

    // Power rule
    println!("d/dx(x^4) = {}", pow(x, c(4.0)).diff("x"));
    // 4 * x^3

    // Product rule
    println!("d/dx(x*sin(x)) = {}", (x * sin(x)).diff("x"));
    // x * cos(x) + sin(x)

    // Quotient rule
    println!("d/dx(sin(x)/x) = {}", (sin(x) / x).diff("x"));
    // (x * cos(x) - sin(x)) / x^2

    // Chain rule
    println!("d/dx(exp(sin(x))) = {}", exp(sin(x)).diff("x"));
    // cos(x) * exp(sin(x))

    // Nested chain rule
    let e = ln(sqrt(pow(x, c(2.0)) + 1.0));
    println!("d/dx(ln(sqrt(x^2+1))) = {}", e.diff("x"));
    // x / sqrt(x^2 + 1)^2

    // General power
    println!("d/dx(x^x) = {}", pow(x, x).diff("x"));
    // x^x * (ln(x) + 1)
}
```

### Trigonometric derivatives

```rust
arael::sym! {
    let x = symbol("x");
    println!("d/dx(sin(x)) = {}", sin(x).diff("x"));  // cos(x)
    println!("d/dx(cos(x)) = {}", cos(x).diff("x"));  // -sin(x)
    println!("d/dx(tan(x)) = {}", tan(x).diff("x"));  // 1 / cos(x)^2
    println!("d/dx(asin(x)) = {}", asin(x).diff("x")); // 1 / sqrt(-x^2 + 1)
    println!("d/dx(acos(x)) = {}", acos(x).diff("x")); // -1 / sqrt(-x^2 + 1)
    println!("d/dx(atan(x)) = {}", atan(x).diff("x")); // 1 / (x^2 + 1)
}
```

## Expansion and Collection

```rust
arael::sym! {
    let a = symbol("a");
    let b = symbol("b");
    let x = symbol("x");
    let y = symbol("y");

    println!("{}", (x * (a + b)).expand());  // a * x + b * x
    println!("{}", pow(x + y, c(2.0)).expand());  // x^2 + 2 * x * y + y^2
    println!("{}", pow(x - y, c(3.0)).expand());  // x^3 - 3 * x^2 * y + 3 * x * y^2 - y^3
    println!("{}", (a * x + b * x).collect("x")); // x * (a + b)
}
```

## Evaluation and Substitution

```rust
arael::sym! {
    let x = symbol("x");
    let y = symbol("y");
    let f = pow(x, c(2.0)) + 3.0 * x + 1.0;

    let vars = HashMap::from([("x", 2.0)]);
    println!("f(2) = {}", f.eval(&vars).unwrap()); // 11

    println!("f(y+1) = {}", f.subs("x", &(y + 1.0)));
    // (y + 1)^2 + 3 * (y + 1) + 1
}
```

### Kinematics example

```rust
arael::sym! {
    let t = symbol("t");
    let v0 = symbol("v0");
    let a = symbol("a");

    let s = 0.5 * a * pow(t, c(2.0)) + v0 * t;
    let v = s.diff("t");   // a * t + v0
    let acc = v.diff("t"); // a

    println!("s(t) = {}", s);
    println!("v(t) = {}", v);
    println!("a(t) = {}", acc);
}
```

## Free Variables

```rust
arael::sym! {
    let e = symbol("x") * symbol("y") + sin(symbol("z"));
    println!("{:?}", e.free_vars()); // {"x", "y", "z"}
}
```

## Linear Algebra

```rust
arael::sym! {
    let v = SymVec(vec![symbol("x"), symbol("y")]);
    println!("v.v = {}", v.dot(&v));   // x^2 + y^2

    let m = SymMat::new(2, 2, vec![c(1.0), c(2.0), c(3.0), c(4.0)]);
    println!("M*v = {}", m * &v);      // [x + 2 * y, 3 * x + 4 * y]
    println!("M^T = {}", m.transpose()); // [1, 3; 2, 4]

    let exprs = vec![symbol("x") * symbol("y"), pow(symbol("x"), c(2.0)) + sin(symbol("y"))];
    let j = jacobian(&exprs, &["x", "y"]);
    println!("J = {}", j); // [y, x; 2 * x, cos(y)]
}
```

## Output Formats

```rust
arael::sym! {
    let e = sin(symbol("x")) / pow(symbol("y"), c(2.0));
    println!("Display: {}", e);               // sin(x) / y^2
    println!("LaTeX:   {}", e.to_latex());     // \frac{\sin\left(x\right)}{y^{2}}
    println!("Rust:    {}", e.to_rust("f64")); // x.sin() / y.powf(2.0_f64)
}
```

## Common Subexpression Elimination

```rust
arael::sym! {
    let x = symbol("x");
    let y = symbol("y");
    let common = sin(x * y);
    let e1 = common + 1.0;
    let e2 = common * 2.0;

    let (intermediates, simplified) = cse(&[e1, e2]);
    // intermediates: [("__x0", sin(x * y))]
    // simplified: [__x0 + 1, 2 * __x0]
}
```

CSE is applied automatically in the constraint code generation macro, reducing generated code size dramatically (e.g., 47000 ops down to ~400 for a SLAM constraint).

## Parsing

```rust
let e: E = "x^2 + 3*x + 1".parse().unwrap();
let f = parse("sqrt(atan2(y, x) + pi)").unwrap();
let g = parse("exp(sin(x)) * cos(x)").unwrap();
println!("d/dx = {}", g.diff("x")); // cos(x)^2 * exp(sin(x)) - exp(sin(x)) * sin(x)
```