Files
symclaw/docs/API.md
T

9.4 KiB
Raw Blame History

SymClaw API Reference

Rust API (symclaw-core)

symclaw_core::parser::parse

Parse a mathematical expression string into an AST.

pub fn parse(input: &str) -> Result<Arc<Expr>, ParseError>

Supported syntax:

  • Arithmetic: +, -, *, /, ^ (with standard precedence)
  • Implicit multiplication: 2x, 3(x+1), xy
  • Functions: sin, cos, tan, exp, ln, log, sqrt, abs, sinh, cosh, tanh, asin, acos, atan
  • Constants: pi, e
  • Parentheses: (, )
use symclaw_core::parser::parse;

let expr = parse("2*x^2 + 3*x - 5").unwrap();
let expr = parse("sin(x^2) * exp(-x)").unwrap();
let expr = parse("(x + 1)/(x - 1)").unwrap();

Errors: Returns ParseError with byte offset and description for malformed input.


symclaw_core::simplify::simplify

Simplify an expression to canonical form using the algebraic pipeline.

pub fn simplify(expr: &Expr) -> Arc<Expr>

Applies: constant folding, identity elimination, like-term collection, canonical ordering. Does not invoke e-graph saturation (use simplify_egraph for that).

use symclaw_core::{parser::parse, simplify::simplify};

let expr = parse("x + 0 + 2*x + 3").unwrap();
let result = simplify(&expr);
// → 3*x + 3

symclaw_core::egraph::simplify_egraph

Deep simplification via equality saturation.

pub fn simplify_egraph(expr: &Expr) -> Arc<Expr>

Inserts the expression into an e-graph, applies 30+ rewrite rules until saturation, then extracts the smallest equivalent expression. More powerful than simplify() but slower (~10-100× depending on expression complexity).

use symclaw_core::{parser::parse, egraph::simplify_egraph};

let expr = parse("sin(x)^2 + cos(x)^2").unwrap();
let result = simplify_egraph(&expr);
// → 1

symclaw_core::egraph::explain_equivalence

Prove that two expressions are equivalent by returning the chain of rewrite rules.

pub fn explain_equivalence(a: &Expr, b: &Expr) -> Option<Vec<String>>

Returns None if the expressions are not equivalent within the saturation budget.

use symclaw_core::{parser::parse, egraph::explain_equivalence};

let a = parse("(x+1)^2").unwrap();
let b = parse("x^2 + 2*x + 1").unwrap();
let steps = explain_equivalence(&a, &b).unwrap();
for step in &steps {
    println!("{step}");
}

symclaw_core::differentiate::differentiate

Compute the symbolic derivative of an expression.

pub fn differentiate(expr: &Expr, var: Symbol) -> Arc<Expr>

Supports all elementary functions with chain rule. Result is automatically simplified.

use symclaw_core::{parser::parse, differentiate::differentiate};

let expr = parse("sin(x^2)").unwrap();
let deriv = differentiate(&expr, "x".into());
// → 2*x*cos(x^2)

// Higher-order
let second = differentiate(&deriv, "x".into());

// Partial derivatives
let expr = parse("x^2 * y + y^3").unwrap();
let dx = differentiate(&expr, "x".into());  // → 2*x*y
let dy = differentiate(&expr, "y".into());  // → x^2 + 3*y^2

symclaw_core::integrate::integrate

Compute the symbolic indefinite integral.

pub fn integrate(expr: &Expr, var: Symbol) -> Option<Arc<Expr>>

Returns None when no closed-form antiderivative is found. Does not include the constant of integration.

use symclaw_core::{parser::parse, integrate::integrate};

let expr = parse("x^2").unwrap();
let result = integrate(&expr, "x".into());
// → Some(x^3/3)

let expr = parse("sin(x) * cos(x)").unwrap();
let result = integrate(&expr, "x".into());
// → Some(sin(x)^2/2)

Strategies applied: linearity, power rule, known antiderivatives, u-substitution, integration by parts.


symclaw_core::solve::solve

Solve the equation expr = 0 for the given variable.

pub fn solve(expr: &Expr, var: Symbol) -> Vec<Arc<Expr>>

Returns all found solutions as simplified expressions. Empty vector if no solutions are found.

use symclaw_core::{parser::parse, solve::solve};

// Quadratic
let expr = parse("x^2 - 5*x + 6").unwrap();
let solutions = solve(&expr, "x".into());
// → [2, 3]

// Linear
let expr = parse("3*x + 7").unwrap();
let solutions = solve(&expr, "x".into());
// → [-7/3]

// Transcendental
let expr = parse("exp(x) - 1").unwrap();
let solutions = solve(&expr, "x".into());
// → [0]

symclaw_core::series::taylor

Compute the Taylor series expansion of an expression.

pub fn taylor(expr: &Expr, var: Symbol, point: &Expr, order: u32) -> Arc<Expr>

Expands expr around point to the given order. Uses fast-path for known functions, falls back to repeated differentiation.

use symclaw_core::{parser::parse, series::taylor};

let expr = parse("sin(x)").unwrap();
let zero = parse("0").unwrap();
let series = taylor(&expr, "x".into(), &zero, 5);
// → x - x^3/6 + x^5/120

let expr = parse("exp(x)").unwrap();
let series = taylor(&expr, "x".into(), &zero, 4);
// → 1 + x + x^2/2 + x^3/6 + x^4/24

symclaw_core::eval::eval

Numerically evaluate an expression with variable substitution.

pub fn eval(expr: &Expr, vars: &HashMap<Symbol, f64>) -> Result<f64, EvalError>
use std::collections::HashMap;
use symclaw_core::{parser::parse, eval::eval};

let expr = parse("x^2 + y").unwrap();
let mut vars = HashMap::new();
vars.insert("x".into(), 3.0);
vars.insert("y".into(), 1.0);
let result = eval(&expr, &vars).unwrap();
// → 10.0

Errors: EvalError::UndefinedVariable if a variable has no binding, EvalError::DomainError for operations like ln(-1).


symclaw_core::latex::to_latex

Render an expression as a LaTeX string.

pub fn to_latex(expr: &Expr) -> String
use symclaw_core::{parser::parse, latex::to_latex};

let expr = parse("x^2/(2*y) + sqrt(z)").unwrap();
let latex = to_latex(&expr);
// → "\\frac{x^{2}}{2 y} + \\sqrt{z}"

Handles fractions (\frac), square roots (\sqrt), Greek letters, subscripts, and proper spacing.


WASM API (symclaw-wasm)

All WASM functions accept and return strings. Import via:

import init, * as symclaw from 'symclaw-wasm';
await init();
Function Signature Description
parse(input) string → string Parse and echo canonical form
simplify(input) string → string Simplify expression
differentiate(expr, var) (string, string) → string Symbolic derivative
integrate(expr, var) (string, string) → string | null Symbolic integral
solve(expr, var) (string, string) → string JSON array of solutions
taylor(expr, var, point, order) (string, string, string, number) → string Taylor expansion
eval_expr(expr, vars_json) (string, string) → number Numeric evaluation
to_latex(expr) string → string LaTeX rendering
simplify_egraph(expr) string → string E-graph simplification
explain(a, b) (string, string) → string | null Equivalence proof (JSON)
plot_data(expr, var, start, end, steps) (...) → string JSON array of [x, y] points
version() () → string Engine version

Skill Protocol (JSON-RPC)

The symclaw-skill binary reads JSON objects from stdin (one per line) and writes responses to stdout.

simplify

// Request
{"action": "simplify", "expr": "x^2 + 2*x + 1"}

// Response
{"success": true, "result": "(x + 1)^2", "latex": "(x + 1)^{2}"}

differentiate

// Request
{"action": "differentiate", "expr": "sin(x^2)", "var": "x"}
// "var" defaults to "x" if omitted

// Response
{"success": true, "result": "2*x*cos(x^2)", "latex": "2 x \\cos(x^{2})"}

integrate

// Indefinite
{"action": "integrate", "expr": "x^2", "var": "x"}
 {"success": true, "result": "x^3/3", "latex": "\\frac{x^{3}}{3}"}

// Definite
{"action": "integrate", "expr": "x^2", "var": "x", "lower": "0", "upper": "1"}
 {"success": true, "result": "1/3", "latex": "\\frac{1}{3}"}

solve

{"action": "solve", "expr": "x^2 - 5*x + 6", "var": "x"}
 {"success": true, "solutions": ["2", "3"], "latex_solutions": ["2", "3"]}

taylor

{"action": "taylor", "expr": "sin(x)", "var": "x", "point": "0", "order": 5}
 {"success": true, "result": "x - x^3/6 + x^5/120", "latex": "x - \\frac{x^{3}}{6} + \\frac{x^{5}}{120}"}

eval

{"action": "eval", "expr": "x^2 + y", "vars": {"x": 3.0, "y": 1.0}}
 {"success": true, "value": 10.0}

latex

{"action": "latex", "expr": "x^2/(2*y) + sqrt(z)"}
 {"success": true, "latex": "\\frac{x^{2}}{2 y} + \\sqrt{z}"}

plot_data

{"action": "plot_data", "expr": "sin(x)", "var": "x", "start": -6.283, "end": 6.283, "steps": 200}
 {"success": true, "points": [[-6.283, 0.0016], ..., [6.283, -0.0016]]}

Error Response

All actions return this format on failure:

{"success": false, "error": "Parse error at byte 5: unexpected token ')'"}

Canvas Actions

The skill also supports canvas rendering via the skill.json manifest:

  • canvas/manipulate.html — Interactive plot with parameter sliders. The gateway loads this in an iframe and passes expression + parameter ranges. WASM evaluates client-side.
  • canvas/result.html — Formatted result display with LaTeX rendering via KaTeX.

These are triggered by the OpenClaw gateway when the skill returns canvas-compatible data, not by direct JSON-RPC calls.