LawSynthGitHub

Capabilities

LawSynth is a Rust-first toolkit with Python and TypeScript SDKs. Every capability below is a real command in the lawsynth CLI, and most are mirrored by a function in the Python SDK. They all read and write the same .lsworld bundle.

The work falls into four pillars: Discover, Analyze, Control, and Share.

Discover

Recover governing equations from observations by sparse symbolic regression over a configurable feature library.

  • Sparse regression — fit a compact law system with a choice of solver (stlsq, sr3, frols, ssr, or trapping), polynomial degree, and optional trigonometric or bounded-rational features.
$ lawsynth discover obs.csv --time t --state x,y --output world.lsworld --solver stlsq --pareto
  • Regimes, Pareto, refinement, causality — add --regimes to detect mode switches, --pareto for the accuracy/complexity frontier, --refine to jointly fit parameters, and --causal for dependency hypotheses.
  • Controlled discovery (SINDYc) — learn dynamics that include exogenous control inputs.
$ lawsynth control obs.csv --time t --state x,v --control u
  • Network coupling — recover which variables drive which across a multivariate system.
$ lawsynth network obs.csv --state x1,x2,x3 --edge-threshold 0.1
  • Cross-validated model selection — sweep degrees and thresholds under time-series cross-validation to choose a model that generalizes.
$ lawsynth select obs.csv --state x,y --degrees 2,3 --folds 5 --scheme rolling

Alternative discovery engines

When the strong (derivative) form struggles, switch engines — each recovers a different class of law:

  • Weak / integral form — noise-robust discovery that never differentiates the data. Same command, one flag:
$ lawsynth discover obs.csv --time t --state x,y --method weak-form --output world.lsworld
  • Koopman / DMD — a linear operator on the (lifted) state; reports discrete and continuous eigenvalues and their stability. Returns an operator, not a symbolic world.
$ lawsynth koopman obs.csv --time t --state x,y
  • Stochastic (SDE) — recover drift a(x) and diffusion b²(x) from a single noisy path via Kramers–Moyal moments (a statistical estimator: accuracy grows with path length).
$ lawsynth sde obs.csv --time t --state x --bins 40
  • Partial differential equations (PDE-FIND) — recover an evolution law u_t = F(u, u_x, u_xx, …) from a space–time field grid (finite-difference, so it wants a resolved grid).
$ lawsynth pde field.csv --dx 0.1 --dt 0.01

The same discovery flow from Python, through the Study façade:

import lawsynth

study = lawsynth.Study.from_csv("obs.csv", time="t", state=["x", "y"])
result = study.discover()
result.save("world.lsworld")

Analyze

Interrogate a discovered world — its structure, its long-run behavior, and how far to trust it.

  • Stability — locate and classify fixed points over a bounded region: lawsynth stability world.lsworld --box 0:5,0:5.
  • Bifurcation — sweep a parameter and track how fixed points appear, merge, or lose stability: lawsynth bifurcation world.lsworld --parameter mu --range 0:2 --box -3:3,-3:3.
  • Sensitivity — measure how the trajectory responds to each parameter: lawsynth sensitivity world.lsworld --parameters a,b.
  • Lyapunov exponents — a chaos diagnostic; a positive leading exponent signals sensitive dependence: lawsynth lyapunov world.lsworld --initial x=1,y=1,z=1.
  • Invariants — search a bounded basis for conserved quantities: lawsynth invariants world.lsworld --degree 2.
  • Basins of attraction — map which initial conditions flow to which attractor: lawsynth basins world.lsworld --box -2:2,-2:2.
  • Uncertainty — bootstrap coefficient bounds at discovery time (discover --bootstrap) and propagate them into forecast bands (forecast --confidence).

The analysis surface is mirrored in the SDK:

import lawsynth

fixed_points = lawsynth.stability("world.lsworld", box="0:5,0:5")
spectrum = lawsynth.lyapunov("world.lsworld", initial={"x": 1.0, "y": 1.0, "z": 1.0})

Control

Turn a world into something you can estimate, reduce, or steer.

  • State estimation — design an observer by pole placement, or a Kalman filter: lawsynth estimate world.lsworld --box -2:2,-2:2 --measure x --kalman.
  • Balanced model reduction — approximate a higher-order world with a lower-order one: lawsynth reduce world.lsworld --box -2:2,-2:2 --order 2.
  • Model-predictive control — compute a control sequence that drives states to a setpoint: lawsynth mpc world.lsworld --control u --setpoint x=1 --initial x=0.
  • Discrete-time simulation — step a discrete-time world forward: lawsynth simulate-discrete world.lsworld --initial x=1 --steps 100.
import lawsynth

plan = lawsynth.mpc("world.lsworld", control=["u"], setpoint={"x": 1.0}, initial={"x": 0.0})

Share

Explain, package, and hand off a world — no server, no external assets.

  • Explain — a plain-language, structured account of each law, its dominant terms, and its assumptions: lawsynth explain world.lsworld.
  • Report — a self-contained HTML report with rendered equations, fit, and inline trajectory charts: lawsynth report world.lsworld --output report.html.
  • Forecast — run the world forward, with interventions and optional confidence bands: lawsynth forecast world.lsworld --horizon 40.
  • Export — emit runnable code and interchange formats: lawsynth export world.lsworld --format python (also c, onnx, matlab, latex, json).
  • Simplify — algebraically reduce a law system with an e-graph: lawsynth simplify world.lsworld.
  • Compare — diff two worlds or two scenarios: lawsynth compare a.lsworld b.lsworld.
  • Domain presets — inspect and self-validate curated textbook systems: lawsynth domains run damped-oscillator.

Honest boundaries

LawSynth is built to be trusted, which means being explicit about what it does not claim:

  • Discovery is a sparse fit to your data — a compact hypothesis, not proof of causality. --causal produces dependency *hypotheses*.
  • Network coupling is correlational; an edge is not proof of mechanism.
  • Lyapunov exponents are a time-averaged numerical estimate, not an analytic result.
  • Invariants are found within a bounded basis, so the absence of a result is not proof none exist.
  • Determinism is the guarantee: identical inputs, config, version, and binary produce a bit-identical world. See Why determinism.