Metadata-Version: 2.4
Name: gds-symbolic
Version: 0.1.0
Summary: Symbolic math bridge for the GDS ecosystem — SymPy to ODE compilation
Project-URL: Homepage, https://github.com/BlockScience/gds-core
Project-URL: Repository, https://github.com/BlockScience/gds-core
Project-URL: Documentation, https://blockscience.github.io/gds-core
Author-email: Rohan Mehta <rohan@block.science>
License-Expression: Apache-2.0
Keywords: control-systems,gds-framework,generalized-dynamical-systems,symbolic-math,sympy
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: gds-control>=0.1.0
Requires-Dist: gds-framework>=0.2.3
Requires-Dist: pydantic>=2.10
Provides-Extra: continuous
Requires-Dist: gds-continuous>=0.1.0; extra == 'continuous'
Provides-Extra: sympy
Requires-Dist: numpy>=1.26; extra == 'sympy'
Requires-Dist: sympy>=1.13; extra == 'sympy'
Description-Content-Type: text/markdown

# gds-symbolic

Symbolic math bridge for the GDS ecosystem — compiles SymPy expressions
into plain Python callables for use with `gds-continuous`.

## Installation

```bash
uv add gds-symbolic[sympy]
```

## Quick Start

```python
from gds_control.dsl.elements import State, Input, Sensor, Controller
from gds_symbolic import SymbolicControlModel, StateEquation

model = SymbolicControlModel(
    name="damped_oscillator",
    states=[State(name="x"), State(name="v")],
    inputs=[Input(name="force")],
    sensors=[Sensor(name="position", observes=["x"])],
    controllers=[Controller(name="actuator", reads=["position", "force"], drives=["x", "v"])],
    state_equations=[
        StateEquation(state_name="x", expr_str="v"),
        StateEquation(state_name="v", expr_str="-k*x - c*v + force"),
    ],
    symbolic_params=["k", "c"],
)

# Compile to plain callable (no SymPy at runtime)
ode_fn, state_order = model.to_ode_function()

# Linearize at origin
lin = model.linearize(x0=[0.0, 0.0], u0=[0.0])
print(lin.A)  # [[0, 1], [-k, -c]] evaluated at operating point
```
