Generalized Dynamical Systems — typed compositional specifications for complex systems
Project description
gds-framework
Typed compositional specifications for complex systems, grounded in Generalized Dynamical Systems theory (Zargham & Shorish, 2022).
Table of Contents
- Quick Start
- What is this?
- Architecture
- Examples
- What's Included
- Glossary
- Intellectual Lineage
- Status
- Credits & Attribution
Quick Start
pip install gds-framework
from gds import (
BoundaryAction, Policy, ControlAction,
interface, Wiring,
compile_system, verify,
)
from gds.ir.models import FlowDirection
# Define blocks with GDS roles and typed interfaces
sensor = BoundaryAction(
name="Temperature Sensor",
interface=interface(forward_out=["Temperature"]),
)
controller = Policy(
name="PID Controller",
interface=interface(
forward_in=["Temperature", "Setpoint"],
forward_out=["Heater Command"],
backward_in=["Energy Cost"],
),
)
plant = ControlAction(
name="Room",
interface=interface(
forward_in=["Heater Command"],
forward_out=["Temperature"],
backward_out=["Energy Cost"],
),
)
# Compose with operators — types checked at construction time
system = (sensor >> controller >> plant).feedback([
Wiring(
source_block="Room", source_port="Energy Cost",
target_block="PID Controller", target_port="Energy Cost",
direction=FlowDirection.CONTRAVARIANT,
)
])
# Compile to flat IR and verify
ir = compile_system("Thermostat", system)
report = verify(ir)
print(f"{len(ir.blocks)} blocks, {len(ir.wirings)} wirings")
# 3 blocks, 3 wirings
print(f"{report.checks_passed}/{report.checks_total} checks passed")
# 13/14 checks passed (G-002 flags BoundaryAction for having no inputs — expected)
What is this?
gds-framework is a foundation layer for specifying dynamical systems as compositions of typed blocks. It provides the domain-neutral primitives — you bring the domain knowledge.
gds-framework Your domain package
───────────────── ──────────────────
Block, Interface, Port PredatorBlock, PreyBlock
>> | .feedback() .loop() predator >> prey >> environment
TypeDef, Space, Entity Population(int, ≥0), EcosystemState
GDSSpec, verify() check_conservation(), check_stability()
compile_system() → SystemIR visualize(), simulate()
A Generalized Dynamical System is a pair {h, X} where X is a state space (any data structure) and h: X → X is a state transition map. The GDS canonical form decomposes h into a pipeline of typed blocks — observations, decisions, and state updates — that compose via wiring:
| GDS concept | Paper notation | gds-framework |
|---|---|---|
| State Space | X | Entity with StateVariables |
| Exogenous observation | g(·) | BoundaryAction |
| Decision / policy | g: X → U_x | Policy |
| State update | f: X × U_x → X | Mechanism |
| Admissible input constraint | U: X → ℘(U) | ControlAction |
| Transition map | h = f|_x ∘ g | Composed wiring (>>) |
| Trajectory | x₀, x₁, ... | Temporal loop (.loop()) |
This decomposition is the same regardless of whether you're modeling a biological ecosystem, a control system, a financial market, or a game-theoretic interaction. gds-framework provides the decomposition machinery; domain packages provide the semantics.
Architecture: foundation + domain packages
gds-framework (pip install gds-framework)
│
│ Domain-neutral composition algebra, typed spaces,
│ state model, verification engine, flat IR compiler.
│ No domain-specific concepts. No simulation. No rendering.
│
├── Domain: Ecology
│ └── Predator-prey dynamics, population models, SIR epidemiology
│
├── Domain: Control Systems
│ └── Controllers, plants, sensors, stability/controllability checks
│
├── Domain: Financial Systems
│ └── Insurance contracts, market mechanisms, conservation of flows
│
├── Domain: Game Theory
│ └── Iterated games, strategy adaptation, equilibrium analysis
│
└── Domain: Multi-Agent Systems
└── Agent policies, environment dynamics, coordination protocols
Each domain package is a thin layer. The heavy lifting — composition, compilation, verification, querying — lives in gds-framework.
Example: what lives where
Consider modeling a Lotka-Volterra predator-prey system as a GDS. The state space is (prey_population, predator_population). Each evaluation: the environment is observed, growth/predation rates are computed, populations are updated.
gds-framework provides (domain-neutral):
TypeDef(name="Population", python_type=int, constraint=lambda x: x >= 0)— constrained typesEntity(name="Prey", variables={"population": ...})— state containersBoundaryAction,Policy,Mechanism— block roles with interface constraints>>composition with type checking,.loop()for temporal iterationverify()— are all state variables updated? any write conflicts? all blocks reachable?
A domain package would add (ecology-specific):
- Concrete block implementations with actual dynamics (Lotka-Volterra equations)
- Domain-specific verification (population conservation, extinction checks)
- Simulation execution (running trajectories from initial conditions)
- Visualization (phase plots, time series)
The same split applies to any domain. An iterated prisoner's dilemma model would use BoundaryAction for observing the opponent's last move, Policy for strategy selection (tit-for-tat, always-defect, etc.), Mechanism for payoff calculation and score update, and .loop() for repeated rounds — all composed from the same primitives.
A thermostat control system would use BoundaryAction for the temperature sensor, Policy for the PID controller, Mechanism for the room's thermal dynamics, and .feedback() for the energy cost signal flowing backward.
Examples
Five tutorial examples in gds-examples demonstrate every framework feature. Each model.py reads like a tutorial chapter with inline GDS theory commentary.
| # | Example | What It Teaches | Composition |
|---|---|---|---|
| 1 | SIR Epidemic | Fundamentals — TypeDef, Entity, Space, 3 block roles | >> | |
| 2 | Thermostat PID | .feedback(), CONTRAVARIANT, backward ports |
>> .feedback() |
| 3 | Lotka-Volterra | .loop(), COVARIANT temporal iteration |
>> | .loop() |
| 4 | Prisoner's Dilemma | Nested |, multi-entity state, complex trees |
| >> .loop() |
| 5 | Insurance Contract | ControlAction role, complete 4-role taxonomy | >> |
Start with SIR Epidemic and work down — each introduces one new concept.
Each model generates 6 views automatically via gds-viz. Here are sample views for the SIR Epidemic:
Structural view — compiled block graph with role-based shapes and typed wiring labels
%%{init:{"theme":"neutral"}}%%
flowchart TD
classDef boundary fill:#93c5fd,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef policy fill:#fcd34d,stroke:#d97706,stroke-width:2px,color:#78350f
classDef mechanism fill:#86efac,stroke:#16a34a,stroke-width:2px,color:#14532d
classDef control fill:#d8b4fe,stroke:#9333ea,stroke-width:2px,color:#3b0764
classDef generic fill:#cbd5e1,stroke:#64748b,stroke-width:1px,color:#1e293b
Contact_Process([Contact Process]):::boundary
Infection_Policy[Infection Policy]:::generic
Update_Susceptible[[Update Susceptible]]:::mechanism
Update_Infected[[Update Infected]]:::mechanism
Update_Recovered[[Update Recovered]]:::mechanism
Contact_Process --Contact Signal--> Infection_Policy
Infection_Policy --Susceptible Delta--> Update_Susceptible
Infection_Policy --Infected Delta--> Update_Infected
Infection_Policy --Recovered Delta--> Update_Recovered
Canonical GDS view — mathematical decomposition: X_t → U → g → f → X_{t+1}
%%{init:{"theme":"neutral"}}%%
flowchart LR
classDef boundary fill:#93c5fd,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef policy fill:#fcd34d,stroke:#d97706,stroke-width:2px,color:#78350f
classDef mechanism fill:#86efac,stroke:#16a34a,stroke-width:2px,color:#14532d
classDef control fill:#d8b4fe,stroke:#9333ea,stroke-width:2px,color:#3b0764
classDef generic fill:#cbd5e1,stroke:#64748b,stroke-width:1px,color:#1e293b
classDef entity fill:#e2e8f0,stroke:#475569,stroke-width:2px,color:#0f172a
classDef param fill:#fdba74,stroke:#ea580c,stroke-width:2px,color:#7c2d12
classDef state fill:#5eead4,stroke:#0d9488,stroke-width:2px,color:#134e4a
classDef target fill:#fca5a5,stroke:#dc2626,stroke-width:2px,color:#7f1d1d
classDef empty fill:#e2e8f0,stroke:#94a3b8,stroke-width:1px,color:#475569
X_t(["X_t<br/>Susceptible.count, Infected.count, Recovered.count"]):::state
X_next(["X_{t+1}<br/>Susceptible.count, Infected.count, Recovered.count"]):::state
Theta{{"Θ<br/>contact_rate, beta, gamma"}}:::param
subgraph U ["Boundary (U)"]
Contact_Process[Contact Process]:::boundary
end
subgraph g ["Policy (g)"]
Infection_Policy[Infection Policy]:::policy
end
subgraph f ["Mechanism (f)"]
Update_Susceptible[Update Susceptible]:::mechanism
Update_Infected[Update Infected]:::mechanism
Update_Recovered[Update Recovered]:::mechanism
end
X_t --> U
U --> g
g --> f
Update_Susceptible -.-> |Susceptible.count| X_next
Update_Infected -.-> |Infected.count| X_next
Update_Recovered -.-> |Recovered.count| X_next
Theta -.-> g
Theta -.-> f
style U fill:#dbeafe,stroke:#60a5fa,stroke-width:1px,color:#1e40af
style g fill:#fef3c7,stroke:#fbbf24,stroke-width:1px,color:#92400e
style f fill:#dcfce7,stroke:#4ade80,stroke-width:1px,color:#166534
Architecture by role — blocks grouped by GDS role with entity state cylinders
%%{init:{"theme":"neutral"}}%%
flowchart TD
classDef boundary fill:#93c5fd,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef policy fill:#fcd34d,stroke:#d97706,stroke-width:2px,color:#78350f
classDef mechanism fill:#86efac,stroke:#16a34a,stroke-width:2px,color:#14532d
classDef control fill:#d8b4fe,stroke:#9333ea,stroke-width:2px,color:#3b0764
classDef generic fill:#cbd5e1,stroke:#64748b,stroke-width:1px,color:#1e293b
classDef entity fill:#e2e8f0,stroke:#475569,stroke-width:2px,color:#0f172a
classDef param fill:#fdba74,stroke:#ea580c,stroke-width:2px,color:#7c2d12
classDef state fill:#5eead4,stroke:#0d9488,stroke-width:2px,color:#134e4a
classDef target fill:#fca5a5,stroke:#dc2626,stroke-width:2px,color:#7f1d1d
classDef empty fill:#e2e8f0,stroke:#94a3b8,stroke-width:1px,color:#475569
subgraph boundary ["Boundary (U)"]
Contact_Process([Contact Process]):::boundary
end
subgraph policy ["Policy (g)"]
Infection_Policy[Infection Policy]:::policy
end
subgraph mechanism ["Mechanism (f)"]
Update_Susceptible[[Update Susceptible]]:::mechanism
Update_Infected[[Update Infected]]:::mechanism
Update_Recovered[[Update Recovered]]:::mechanism
end
entity_Susceptible[("Susceptible<br/>count: S")]:::entity
entity_Infected[("Infected<br/>count: I")]:::entity
entity_Recovered[("Recovered<br/>count: R")]:::entity
Update_Susceptible -.-> entity_Susceptible
Update_Infected -.-> entity_Infected
Update_Recovered -.-> entity_Recovered
Contact_Process --ContactSignalSpace--> Infection_Policy
Infection_Policy --DeltaSpace--> Update_Infected
Infection_Policy --DeltaSpace--> Update_Recovered
Infection_Policy --DeltaSpace--> Update_Susceptible
style boundary fill:#dbeafe,stroke:#60a5fa,stroke-width:1px,color:#1e40af
style policy fill:#fef3c7,stroke:#fbbf24,stroke-width:1px,color:#92400e
style mechanism fill:#dcfce7,stroke:#4ade80,stroke-width:1px,color:#166534
Parameter influence — Θ → blocks → entities causal map (Thermostat PID example)
%%{init:{"theme":"neutral"}}%%
flowchart LR
classDef boundary fill:#93c5fd,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef policy fill:#fcd34d,stroke:#d97706,stroke-width:2px,color:#78350f
classDef mechanism fill:#86efac,stroke:#16a34a,stroke-width:2px,color:#14532d
classDef control fill:#d8b4fe,stroke:#9333ea,stroke-width:2px,color:#3b0764
classDef generic fill:#cbd5e1,stroke:#64748b,stroke-width:1px,color:#1e293b
classDef entity fill:#e2e8f0,stroke:#475569,stroke-width:2px,color:#0f172a
classDef param fill:#fdba74,stroke:#ea580c,stroke-width:2px,color:#7c2d12
classDef state fill:#5eead4,stroke:#0d9488,stroke-width:2px,color:#134e4a
classDef target fill:#fca5a5,stroke:#dc2626,stroke-width:2px,color:#7f1d1d
classDef empty fill:#e2e8f0,stroke:#94a3b8,stroke-width:1px,color:#475569
param_Kd{{"Kd"}}:::param
param_Ki{{"Ki"}}:::param
param_Kp{{"Kp"}}:::param
param_setpoint{{"setpoint"}}:::param
PID_Controller[PID Controller]
entity_Room[("Room<br/>T, E")]:::entity
param_Kd -.-> PID_Controller
param_Ki -.-> PID_Controller
param_Kp -.-> PID_Controller
param_setpoint -.-> PID_Controller
Update_Room -.-> entity_Room
PID_Controller --> Room_Plant
Room_Plant --> PID_Controller
Room_Plant --> Update_Room
The remaining 2 views (architecture by domain, traceability) are in each example's VIEWS.md. See gds-examples for the full guide.
What's Included
Layer 1 — Composition Algebra:
Blocks with bidirectional typed interfaces, composed via four operators (>>, |, .feedback(), .loop()). A 3-stage compiler flattens composition trees into flat IR. Six generic verification checks validate structural properties.
Layer 2 — Specification Layer:
TypeDef with runtime constraints, typed Spaces, Entity with StateVariables, block roles (BoundaryAction, Policy, Mechanism, ControlAction), GDSSpec registry, ParameterSchema for configuration space Θ, CanonicalGDS projection deriving the formal h = f ∘ g decomposition, Tagged mixin for inert semantic annotations, semantic verification (completeness, determinism, reachability, type safety, parameter references, canonical wellformedness), SpecQuery for dependency analysis, and JSON serialization.
Glossary
GDS terminology mapped to framework concepts
| Term | Definition | In the framework |
|---|---|---|
| State (x) | The current configuration of the system — a point in the state space | A value held by StateVariables inside an Entity |
| State Space (X) | All possible configurations; can be any data structure, not just ℝⁿ | Product of all Entity variables, each typed by TypeDef |
| Exogenous Signal (z) | An external signal entering the system from outside | BoundaryAction outputs flowing through Ports. Paper uses u for the selected action; codebase uses z for exogenous signals to avoid conflation. |
| Decision (d) | The output of the policy mapping d = g(x, z) | Policy forward_out ports. Corresponds to the paper's selected action u ∈ U_x. |
| Admissible Input Space (U_x) | The set of inputs available given the current state x (paper Def 2.5) | Structural skeleton via AdmissibleInputConstraint; behavioral constraint requires runtime |
| Input Map (g) | Maps state and exogenous signals to a decision: g(x, z) → d | Policy blocks (endogenous decision logic) |
| State Update Map (f) | Takes current state and decision, produces the next state: f(x, d) → x⁺ | Mechanism blocks — the only blocks that write to state |
| State Transition Map (h) | The composed pipeline h = f|_x ∘ g — one full step of the system | The wiring produced by >> composition |
| Trajectory (x₀, x₁, ...) | A sequence of states produced by repeatedly applying h | Temporal iteration via .loop() |
| Reachability | Can the system reach state y from state x through some sequence of inputs? | check_reachability() in the verification engine |
| Controllability | Can the system be steered to a target state from any nearby initial condition? | Formal property checked at the spec level |
| Configuration Space | The subset of X where every point is reachable from some initial condition | Characterized by transitive closure over the wiring graph |
Intellectual Lineage
- GDS formalism (Roxin 1960s; Zargham & Shorish 2022) — state transitions composed over arbitrary data structures, with formal notions of reachability, controllability, and admissibility
- MSML (BlockScience) — block roles, parameter tracking, typed transmission channels
- BDP-lib (Block Diagram Protocol) — abstract/concrete separation, structural validation
- Categorical cybernetics (Ghani, Hedges et al.) — bidirectional composition with contravariant feedback
See docs/gds_deepdive.md for the full analysis.
Status
v0.2.0 — Alpha. Both layers are implemented and tested (347 tests, 99% coverage). v0.2 adds parameter typing (Θ), canonical projection (h = f ∘ g derivation), tagged metadata, and 6 Mermaid visualization views via gds-viz. The composition algebra and specification layer are stable. Domain packages and simulation execution are not yet built — gds-framework is the foundation they will build on.
License
Apache-2.0
Built with Claude Code. All code is test-driven and human-reviewed.
Credits & Attribution
Author: Rohan Mehta — BlockScience
Theoretical foundation: Dr. Michael Zargham and Dr. Jamsheed Shorish — Generalized Dynamical Systems, Part I: Foundations (2021).
Architectural inspiration: Sean McOwen — MSML and bdp-lib.
Contributors:
- Michael Zargham — Project direction, GDS theory guidance, and technical review (BlockScience).
- Peter Hacker — Code auditing and review (BlockScience).
Lineage: Part of the cadCAD ecosystem for Complex Adaptive Dynamics.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gds_framework-0.3.0.tar.gz.
File metadata
- Download URL: gds_framework-0.3.0.tar.gz
- Upload date:
- Size: 83.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c4f3b83123c9ca77fb5260eb6534d51857648c082eaa0820a23d1e637aed2bb
|
|
| MD5 |
84544ed6d7243938f36fb428fc18963e
|
|
| BLAKE2b-256 |
50c15d5344d63e7f33f665c8e42b3a9cf3624b8ddff99c174132510298265981
|
File details
Details for the file gds_framework-0.3.0-py3-none-any.whl.
File metadata
- Download URL: gds_framework-0.3.0-py3-none-any.whl
- Upload date:
- Size: 57.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98c44320c35c3d694daec4f37c0cc67fd150b0796fa2f72f57034764ee1d0ccb
|
|
| MD5 |
508c232d0cf40ca0e649debb14d50ccc
|
|
| BLAKE2b-256 |
76dc6ef3dbbc14b625a5e5e8f481f72591e99088efbd228ed327cf7981df2d06
|