9.4 KiB
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.