Skip to content

Release: merge dev to main#145

Closed
rororowyourboat wants to merge 16 commits intomainfrom
dev
Closed

Release: merge dev to main#145
rororowyourboat wants to merge 16 commits intomainfrom
dev

Conversation

@rororowyourboat
Copy link
Copy Markdown
Collaborator

Summary

Merges all work from dev since last release to main. Major additions:

  • gds-continuous: ODE integration engine (scipy.solve_ivp wrapper, 49 tests)
  • gds-symbolic: SymPy bridge for control models (29 tests)
  • gds-analysis: GDSSpec-to-gds-sim bridge with reachability (44 tests)
  • gds-viz phase module: Phase portraits, vector fields, nullclines (10 tests)
  • Homicidal Chauffeur example: Isaacs 1951 differential game (9 tests + marimo notebook)
  • Modular package extras: Root metapackage restructured to optional deps
  • StateMetric structural annotation: Paper Assumption 3.2
  • Verification audit fixes: PBT, SHACL gate, formal proof corrections

~2,460 tests across 14 packages, all passing. Lint clean.

rohan and others added 16 commits March 28, 2026 17:34
New package connecting structural annotations from gds-framework to
gds-sim execution, completing the spec-to-simulation pipeline.

adapter.py: spec_to_model() maps GDSSpec blocks to gds_sim.Model
  - BoundaryAction + Policy → policies
  - Mechanism.updates → state update functions (keyed by state var)
  - Default initial state from entities
  - Optional constraint enforcement via AdmissibleInputConstraint

constraints.py: guarded_policy() wraps policies with admissibility
  checks at runtime (warn/raise/zero on violation)

metrics.py: trajectory_distances() computes StateMetric distances
  between successive trajectory states

21 tests covering adapter, constraints, metrics, and end-to-end
simulation with constraint enforcement and distance computation.
…s 4-5)

reachability.py implements Paper Definitions 4.1 and 4.2:

- reachable_set(): compute R(x) by running one timestep per input sample,
  deduplicating reached states by fingerprint
- reachable_graph(): BFS expansion from initial states, building an
  adjacency dict of state transitions
- configuration_space(): Tarjan's SCC algorithm on the reachability graph,
  returning mutually reachable state sets sorted by size

11 new tests: single/multiple/duplicate inputs, empty inputs, depth-1
and depth-2 graph expansion, SCC cases (self-loop, cycle, DAG,
disconnected), and end-to-end thermostat integration.
Add gds-continuous package — continuous-time ODE integration engine
mirroring gds-sim's architecture but wrapping scipy.integrate.solve_ivp.
Standalone (pydantic-only), scipy is an optional dependency.

Restructure root metapackage from hard dependencies to optional extras
so users pick adapters: `uv add gds-core[control,continuous]`.

43 tests, 90% coverage. Covers exponential decay (exact solution),
harmonic oscillator (energy conservation), parameter sweeps, 6 solver
methods, and terminal event detection.
Extends ControlModel with symbolic ODEs (StateEquation, OutputEquation)
that compile to plain Python callables via sympy.lambdify. Includes
Jacobian linearization at arbitrary operating points.

Pipeline: SymbolicControlModel → to_ode_function() → ODEFunction
callable that feeds directly into gds-continuous. SymPy is optional.

29 tests, 95% coverage. Covers decay, oscillator, Van der Pol models
with exact RHS verification, linearization Jacobians, and end-to-end
integration through gds-continuous.
Full pipeline demonstration: structural spec → adapter → simulate →
metrics + reachability. Tests population conservation, epidemic
progression, trajectory distances, reachable set, reachability graph,
configuration space (SCCs), and constraint enforcement.

8 tests using float-valued SIR dynamics (beta=0.3, gamma=0.1, N=1000).
Recreates key numerical results from mzargham/hc-marimo using
gds-continuous, proving the ODE engine handles a real differential
game (Isaacs 1951).

5 tests verify: Hamiltonian conservation (H* ~ 0), costate norm
conservation (||p||^2 invariant), forward/backward capture round-trip,
stationary evader straight-line capture, and parameter sweep over
evader speed ratios.
Full differential game example demonstrating the gds-symbolic +
gds-continuous pipeline against mzargham/hc-marimo reference:

- Symbolic derivation of Hamiltonian and optimal controls (SymPy)
- Hand-coded numpy RHS as independent cross-check
- Backward reachable set (isochrone) computation
- Conservation law verification (H*, ||p||^2)
- Forward/backward capture round-trip
- Usable part boundary conditions

9 tests tracing to hc-marimo verification IDs (T1-T7, ISO).
…operties

End-to-end test of the crosswalk mechanism design problem using
gds-analysis. Behavioral functions implement discrete Markov transitions
from the Zargham & Shorish crosswalk lectures.

Tests grounded in NotebookLM analysis of 6 source documents:
- Crosswalk safety guarantee: p=k → Stopped, never Accident
- Accident reachable via jaywalking with bad luck
- Flowing unreachable from Accident in one step
- Not crossing preserves Flowing
- All three states reachable from Flowing
- Configuration space via SCC analysis
Interactive notebook with parameter sliders (v_E, omega_max, ell),
backward trajectory computation via gds-continuous, isochrone
visualization, and conservation law verification table.

16 cells: symbolic derivation (SymPy), lambdification, ODEModel
integration, matplotlib trajectory/isochrone plots.
Crosswalk analysis: reachable set from each traffic state, reachability
graph, configuration space (SCCs), trajectory metrics, and verification
that Flowing is unreachable from Accident — grounded in Zargham & Shorish
crosswalk lectures.

SIR analysis: epidemic simulation with population conservation check,
Euclidean state distance metrics, and reachable set from initial (S=999,
I=1, R=0) under varied infection rates.

Both scripts use the full gds-analysis pipeline: structural spec →
adapter → simulate → metrics + reachability.
Critical:
1. _step_once strips metadata keys (timestep, substep, run, subset)
   from returned state dicts. BFS at depth > 1 no longer passes
   corrupted state to nested calls.
2. Adapter now warns when constraints are registered for non-
   BoundaryAction blocks (Policy/ControlAction).

Important:
3. guarded_policy projects state to depends_on fields before calling
   constraint — enforces R1 structural skeleton at runtime.
4. ControlAction blocks now handled by adapter (raises ValueError if
   missing policy function, same as BoundaryAction/Policy).
5. Docstring corrected: "All blocks packed into a single
   StateUpdateBlock" (was falsely claiming per-wiring groups).
6. Tarjan SCC rewritten as iterative (no recursion limit for large
   reachability graphs).
7. assert replaced with ValueError in trajectory_distances (safe
   under python -O).

Minor:
8. TYPE_CHECKING guards used for type-only imports.
9. Documentation claims left for separate update.
C-1: Wire output_fn into engine — now called per-timepoint with test
C-2: Replace sympify with parse_expr (no eval, restricted local_dict)
I-4: Move gds-continuous from hard dep to optional extra in gds-symbolic
I-5: Remove runs field from ODESimulation (no purpose for deterministic ODEs)
M-2: SymbolicError now inherits from CSError (exception hierarchy)
M-3: Remove dead require_numpy() from _compat.py
M-4: Replace relative imports with absolute in HC example tests
I-2/I-3: Add CLAUDE.md documenting bridge gap and time-varying input limitation
Also: add gds-analysis to root modular extras
feat: continuous-time ODE engine, SymPy bridge, and modular package extras
New gds_viz.phase module with vector fields, trajectories, nullclines,
and full phase_portrait() combining all three. Supports >2D systems
via fixed_states projection.

Behind [phase] optional extra (matplotlib + numpy + gds-continuous) —
existing Mermaid functionality has no new dependencies.

10 tests: vector field computation, trajectory integration, nullclines,
Lorenz 3D projection. 97% package coverage.

Closes #126.
@rororowyourboat
Copy link
Copy Markdown
Collaborator Author

Merged directly — dev fast-forwarded to main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant