Skip to content

Commit 21bc62b

Browse files
committed
Work on dsl.
Signed-off-by: James Goppert <james.goppert@gmail.com>
1 parent 916516c commit 21bc62b

File tree

15 files changed

+11478
-64
lines changed

15 files changed

+11478
-64
lines changed

cyecca/dsl/ROADMAP.md

Lines changed: 915 additions & 0 deletions
Large diffs are not rendered by default.

cyecca/dsl/__init__.py

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
"""
2+
Cyecca DSL - A Modelica-inspired Domain Specific Language for Python.
3+
4+
This module provides a high-level, declarative API for defining dynamic systems
5+
that closely mirrors Modelica syntax while remaining fully Pythonic.
6+
7+
================================================================================
8+
PROTOTYPE MODE - API IS IN FLUX
9+
================================================================================
10+
11+
This DSL is in active prototype development. The API may change significantly
12+
between versions. Do NOT maintain backward compatibility - iterate rapidly.
13+
14+
================================================================================
15+
DESIGN PRINCIPLES - DO NOT REMOVE OR IGNORE
16+
================================================================================
17+
18+
1. MODELICA CONFORMANCE: This DSL conforms as closely as possible to the
19+
Modelica Language Specification v3.7-dev.
20+
Reference: https://specification.modelica.org/master/
21+
22+
- Variable flags (parameter, input, output, constant) follow Modelica semantics
23+
- Attributes (start, fixed, min, max, nominal, unit) match Modelica definitions
24+
- Equation-based modeling with der() operator
25+
- Automatic state/algebraic classification based on der() usage
26+
- Connector/connection semantics (future) will follow Modelica Chapter 9
27+
28+
2. TYPE SAFETY: All functions MUST use beartype for runtime type checking.
29+
- All public functions decorated with @beartype
30+
- All classes use proper type hints for full IDE autocomplete
31+
- Do NOT use Any where a more specific type is possible
32+
- Do NOT remove beartype decorators
33+
- WHEN ADDING NEW FUNCTIONS: Always add @beartype decorator
34+
- Import and use type aliases (Shape, Indices) from types.py
35+
36+
3. SELF-CONTAINED: This DSL module uses NO external compute libraries except:
37+
- Python standard library
38+
- beartype (for runtime type checking)
39+
- numpy (for NumericValue type hints only)
40+
41+
The DSL builds an abstract model representation (expression trees, equation
42+
graphs) that can be compiled by separate backends (CasADi, JAX, etc.).
43+
44+
DO NOT import CasADi, JAX, or other compute backends in the core DSL modules.
45+
46+
4. IMMUTABILITY: Prefer immutable data structures where possible.
47+
48+
5. EXPLICIT > IMPLICIT: All behavior should be explicit and documented.
49+
50+
================================================================================
51+
52+
Example
53+
-------
54+
>>> import matplotlib.pyplot as plt
55+
>>> from cyecca.dsl import model, var, sin, cos, der
56+
>>> from cyecca.dsl.backends import CasadiBackend
57+
>>>
58+
>>> @model
59+
... class Pendulum:
60+
... '''Simple pendulum model.'''
61+
... # Parameters (constant during simulation)
62+
... g = var(9.81, parameter=True)
63+
... l = var(1.0, parameter=True)
64+
...
65+
... # States (automatically detected via der() usage)
66+
... theta = var(start=0.5)
67+
... omega = var()
68+
...
69+
... # Outputs (explicitly flagged)
70+
... x = var(output=True)
71+
... y = var(output=True)
72+
...
73+
... def equations(m): # Use 'm' for model namespace (cleaner than 'self')
74+
... yield der(m.theta) == m.omega
75+
... yield der(m.omega) == -m.g / m.l * sin(m.theta)
76+
... yield m.x == m.l * sin(m.theta)
77+
... yield m.y == -m.l * cos(m.theta)
78+
>>>
79+
>>> # Create, compile, and simulate
80+
>>> pend = Pendulum()
81+
>>> compiled = CasadiBackend.compile(pend.flatten())
82+
>>> result = compiled.simulate(tf=10.0)
83+
>>>
84+
>>> # Plot using model variables (autocomplete works on pend.theta)
85+
>>> _ = plt.figure() # doctest: +SKIP
86+
>>> _ = plt.plot(result.t, result(pend.theta), label='theta') # doctest: +SKIP
87+
>>> _ = plt.plot(result.t, result(pend.omega), label='omega') # doctest: +SKIP
88+
>>> _ = plt.legend() # doctest: +SKIP
89+
>>> plt.show() # doctest: +SKIP
90+
91+
Variable Classification
92+
-----------------------
93+
Variables are classified automatically based on flags and equation analysis:
94+
95+
1. var(parameter=True) → parameter (constant during simulation)
96+
2. var(constant=True) → constant (compile-time constant)
97+
3. var(input=True) → input (externally controlled)
98+
4. var(output=True) → output (computed, exposed)
99+
5. If der(var) appears in equations → state
100+
6. Otherwise → algebraic variable
101+
102+
Architecture
103+
------------
104+
The DSL is structured in two layers:
105+
106+
1. DSL Layer (no external compute libraries):
107+
- model.py: @model decorator, var(), expression trees
108+
- simulation.py: SimulationResult with plotting utilities
109+
- operators.py: Math functions that return Expr nodes
110+
111+
2. Backend Layer:
112+
- backends/casadi.py: Compiles FlatModel to CasADi functions
113+
- (future) backends/jax.py: Compiles FlatModel to JAX functions
114+
"""
115+
116+
from cyecca.dsl.model import (
117+
model,
118+
block,
119+
function,
120+
var,
121+
submodel,
122+
der,
123+
pre,
124+
edge,
125+
change,
126+
and_,
127+
or_,
128+
not_,
129+
if_then_else,
130+
local,
131+
assign,
132+
Model,
133+
FlatModel,
134+
Expr,
135+
ExprKind,
136+
Equation,
137+
Assignment,
138+
FunctionMetadata,
139+
)
140+
from cyecca.dsl.types import Var, VarKind, DType, Shape, Indices
141+
from cyecca.dsl.operators import sin, cos, tan, asin, acos, atan, atan2, sqrt, exp, log, abs
142+
from cyecca.dsl.simulation import SimulationResult, Simulator
143+
144+
__all__ = [
145+
# Decorators
146+
"model",
147+
"block",
148+
"function",
149+
# Variable declaration
150+
"var",
151+
"Var",
152+
"VarKind",
153+
"DType",
154+
"Shape",
155+
"Indices",
156+
"submodel",
157+
# Free functions (continuous)
158+
"der",
159+
# Free functions (discrete/event)
160+
"pre",
161+
"edge",
162+
"change",
163+
# Boolean operators
164+
"and_",
165+
"or_",
166+
"not_",
167+
# Conditional expression
168+
"if_then_else",
169+
# Algorithm section
170+
"local",
171+
"assign",
172+
"Assignment",
173+
# Function support
174+
"FunctionMetadata",
175+
# Base class
176+
"Model",
177+
# Model representation
178+
"FlatModel",
179+
"Expr",
180+
"ExprKind",
181+
"Equation",
182+
# Simulation
183+
"SimulationResult",
184+
"Simulator",
185+
# Math functions
186+
"sin",
187+
"cos",
188+
"tan",
189+
"asin",
190+
"acos",
191+
"atan",
192+
"atan2",
193+
"sqrt",
194+
"exp",
195+
"log",
196+
"abs",
197+
]

cyecca/dsl/backends/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Compute backends for the Cyecca DSL.
3+
4+
Backends compile FlatModel representations into executable functions
5+
for simulation, optimization, and analysis.
6+
7+
Available backends:
8+
- casadi: CasADi-based backend for symbolic computation and simulation
9+
- SX (default): Scalar symbolic expressions - expands arrays
10+
- MX: Matrix symbolic expressions - keeps array structure for efficiency
11+
"""
12+
13+
from cyecca.dsl.backends.casadi import CasadiBackend, CompiledModel, SymbolicType
14+
from cyecca.dsl.simulation import SimulationResult, Simulator
15+
16+
__all__ = ["CasadiBackend", "CompiledModel", "SymbolicType", "SimulationResult", "Simulator"]

0 commit comments

Comments
 (0)