Tutorial examples for gds-framework — six complete domain models demonstrating every framework feature
Project description
GDS Framework Examples
Six complete domain models demonstrating every gds-framework feature. Each model.py is written as a tutorial chapter with inline GDS theory commentary — read them in order.
Table of Contents
- Learning Path
- Quick Start
- Examples
- Visualization Views
- Feature Coverage Matrix
- Building New Examples
- Credits & Attribution
Learning Path
Start with SIR Epidemic and work down. Each example introduces one new concept.
| # | Example | New Concept | Composition | Roles |
|---|---|---|---|---|
| 1 | SIR Epidemic | Fundamentals — TypeDef, Entity, Space, blocks | >> | |
BA, P, M |
| 2 | Thermostat PID | .feedback(), CONTRAVARIANT backward flow |
>> .feedback() |
BA, P, CA, M |
| 3 | Lotka-Volterra | .loop(), COVARIANT temporal iteration |
>> | .loop() |
BA, P, M |
| 4 | Prisoner's Dilemma | Nested |, multi-entity X, complex trees |
| >> .loop() |
BA, P, M |
| 5 | Insurance Contract | ControlAction role, complete 4-role taxonomy | >> |
BA, P, CA, M |
| 6 | Crosswalk Problem | Mechanism design, discrete Markov transitions | >> |
BA, P, CA, M |
Roles: BA = BoundaryAction, P = Policy, CA = ControlAction, M = Mechanism
Quick Start
# Run all example tests (168 tests)
uv run pytest examples/ -v
# Run a specific example
uv run pytest examples/sir_epidemic/ -v
# Generate all structural diagrams
uv run python examples/visualize_examples.py
# Generate all 6 views for one example
uv run python examples/sir_epidemic/generate_views.py # print to stdout
uv run python examples/sir_epidemic/generate_views.py --save # write VIEWS.md
File Structure
Each example follows the same layout:
examples/sir_epidemic/
├── __init__.py # empty
├── model.py # types, entities, spaces, blocks, build_spec(), build_system()
├── test_model.py # comprehensive tests for every layer
├── generate_views.py # generates all 6 visualization views with commentary
└── VIEWS.md # generated output — 6 Mermaid diagrams with explanations
Examples
SIR Epidemic
Start here. 3 compartments (Susceptible, Infected, Recovered) with contact-driven infection dynamics.
X = (S, I, R) U = contact_rate g = infection_policy f = (update_s, update_i, update_r) Θ = {beta, gamma, contact_rate}
contact >> infection_policy >> (update_s | update_i | update_r)
What you'll learn
- TypeDef with runtime constraints (non-negative counts, positive rates)
- Entity and StateVariable for defining state space X
- Space for typed inter-block communication channels
- BoundaryAction (exogenous input), Policy (decision logic), Mechanism (state update)
>>sequential composition with token-based auto-wiring|parallel composition for independent mechanisms- GDSSpec registration and SpecWiring
- compile_system() to produce SystemIR
Files: model.py · tests · views
Thermostat PID
Adds feedback — backward information flow within a single timestep.
X = (T, E) U = measured_temp g = pid_controller f = update_room Θ = {setpoint, Kp, Ki, Kd}
(sensor >> controller >> plant >> update).feedback([Energy Cost: plant -> controller CONTRAVARIANT])
What you'll learn
.feedback()composition for within-timestep backward flow- CONTRAVARIANT flow direction (backward_out → backward_in)
- ControlAction role — reads state and emits control signals (vs Mechanism which writes state)
- backward_in / backward_out ports on block interfaces
- Multi-variable Entity (Room has both temperature and energy_consumed)
Key distinction: Room Plant is ControlAction (not Mechanism) because it has backward_out. Mechanisms cannot have backward ports.
Files: model.py · tests · views
Lotka-Volterra
Adds temporal loops — forward iteration across timesteps.
X = (x, y) U = population_signal g = compute_rates f = (update_prey, update_predator) Θ = {prey_birth_rate, ...}
(observe >> compute >> (update_prey | update_pred)).loop([Population Signal -> Compute Rates COVARIANT])
What you'll learn
.loop()composition for cross-timestep temporal feedback- COVARIANT flow direction — mandatory for
.loop()(CONTRAVARIANT raises GDSTypeError) - Mechanism with forward_out — emitting signals after state update
- exit_condition parameter for loop termination
- Contrast with
.feedback(): within-timestep (thermostat) vs across-timestep (here)
Key distinction: Temporal wirings must be COVARIANT — .loop() enforces this at construction time.
Files: model.py · tests · views
Prisoner's Dilemma
Most complex composition — nested parallel + sequential + temporal loop.
X = (s_A, U_A, s_B, U_B, t) U = game_config g = (alice, bob) f = (payoff, world_models) Θ = {}
pipeline = (payoff_setting | (alice | bob)) >> payoff_realization >> (alice_world | bob_world)
system = pipeline.loop([world models -> decisions])
What you'll learn
- Nested parallel composition:
(A | B) | Cfor logical grouping - Multi-entity state space X with 3 entities (5 state variables total)
- Mechanism with forward_out for temporal feedback
- Complex composition tree combining all operators except
.feedback() - Design choice: parameter vs exogenous input (payoff matrix is U, not Θ)
Files: model.py · tests · views · architecture viz
Insurance Contract
Completes the role taxonomy — the only example using all 4 block roles.
X = (R, P, C, H) U = claim_event g = risk_assessment d = premium_calculation f = (claim_payout, reserve_update) Θ = {base_premium_rate, deductible, coverage_limit}
claim >> risk >> premium >> payout >> reserve_update
What you'll learn
- ControlAction role — the 4th block role, for admissibility/control decisions
- Complete 4-role taxonomy: BoundaryAction → Policy → ControlAction → Mechanism
- ControlAction vs Policy: Policy is core decision logic (g), ControlAction constrains the action space (d)
- params_used on ControlAction — parameterized admissibility rules
Key distinction: Premium Calculation is ControlAction because it enforces admissibility constraints — it decides what's allowed, not what to do.
Files: model.py · tests · views
Crosswalk Problem
Mechanism design — the canonical GDS example from BlockScience. A pedestrian decides whether to cross a one-way street while traffic evolves as a discrete Markov chain. A governance body chooses crosswalk placement to minimize accident probability.
X = traffic_state ∈ {-1, 0, +1} U = (luck, crossing_position) g = pedestrian_decision d = safety_check f = traffic_transition Θ = {crosswalk_location}
observe >> decide >> check >> transition
What you'll learn
- Discrete Markov state transitions as GDS
- Mechanism design: governance parameter (crosswalk location) constraining agent behavior
- ControlAction for admissibility enforcement (safety check)
- Complete 4-role taxonomy in a minimal model
- Design parameter Θ as a governance lever
Files: model.py · tests · views · README
Visualization Views
Each example includes a generate_views.py script that produces 6 complementary views via gds-viz:
| View | Input | What It Shows |
|---|---|---|
| 1. Structural | SystemIR | Compiled block graph — role shapes, wiring arrows |
| 2. Canonical GDS | CanonicalGDS | Mathematical decomposition: X_t → U → g → f → X_{t+1} |
| 3. Architecture by Role | GDSSpec | Blocks grouped by GDS role |
| 4. Architecture by Domain | GDSSpec | Blocks grouped by domain tag |
| 5. Parameter Influence | GDSSpec | Θ → blocks → entities causal map |
| 6. Traceability | GDSSpec | Backwards trace from one state variable to all influencing blocks |
Sample diagrams
Architecture by domain (Thermostat PID) — blocks grouped by physical subsystem:
%%{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 Sensor ["Sensor"]
Temperature_Sensor([Temperature Sensor]):::boundary
end
subgraph Controller ["Controller"]
PID_Controller[PID Controller]:::policy
end
subgraph Plant ["Plant"]
Room_Plant[Room Plant]:::control
Update_Room[[Update Room]]:::mechanism
end
entity_Room[("Room<br/>temperature: T, energy_consumed: E")]:::entity
Update_Room -.-> entity_Room
Temperature_Sensor --TemperatureSpace--> PID_Controller
PID_Controller --CommandSpace--> Room_Plant
Room_Plant --EnergyCostSpace--> PID_Controller
Room_Plant --RoomStateSpace--> Update_Room
Structural view (Thermostat PID) — thick feedback arrow (==>) shows CONTRAVARIANT flow:
%%{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
Temperature_Sensor([Temperature Sensor]):::boundary
PID_Controller[PID Controller]:::generic
Room_Plant[Room Plant]:::generic
Update_Room[[Update Room]]:::mechanism
Temperature_Sensor --Measured Temperature--> PID_Controller
PID_Controller --Heater Command--> Room_Plant
Room_Plant --Room State--> Update_Room
Room_Plant ==Energy Cost==> PID_Controller
Parameter influence (SIR Epidemic) — Θ → blocks → entities causal map:
%%{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_beta{{"beta"}}:::param
param_contact_rate{{"contact_rate"}}:::param
param_gamma{{"gamma"}}:::param
Contact_Process[Contact Process]
Infection_Policy[Infection Policy]
entity_Infected[("Infected<br/>I")]:::entity
entity_Recovered[("Recovered<br/>R")]:::entity
entity_Susceptible[("Susceptible<br/>S")]:::entity
param_beta -.-> Infection_Policy
param_contact_rate -.-> Contact_Process
param_gamma -.-> Infection_Policy
Update_Recovered -.-> entity_Recovered
Update_Susceptible -.-> entity_Susceptible
Update_Infected -.-> entity_Infected
Contact_Process --> Infection_Policy
Infection_Policy --> Update_Infected
Infection_Policy --> Update_Recovered
Infection_Policy --> Update_Susceptible
Each example's VIEWS.md contains all 6 views with commentary. Output is Mermaid markdown — renders in GitHub, GitLab, VS Code, Obsidian, and mermaid.live.
# Generate views for one example
uv run python examples/sir_epidemic/generate_views.py --save
# Generate views for all examples
for d in sir_epidemic thermostat lotka_volterra prisoners_dilemma insurance crosswalk; do
uv run python examples/$d/generate_views.py --save
done
Feature Coverage Matrix
| Feature | SIR | Thermostat | Lotka-V | Prisoner's D | Insurance | Crosswalk |
|---|---|---|---|---|---|---|
| BoundaryAction | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Policy | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Mechanism | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| ControlAction | ✓ | ✓ | ✓ | |||
>> (sequential) |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| (parallel) |
✓ | ✓ | ✓ | |||
.feedback() |
✓ | |||||
.loop() |
✓ | ✓ | ||||
| CONTRAVARIANT wiring | ✓ | |||||
| Temporal wiring | ✓ | ✓ | ||||
| Multi-variable Entity | ✓ | ✓ | ✓ | |||
| Multiple entities | ✓ | ✓ | ✓ | ✓ | ||
| Parameters (Θ) | ✓ | ✓ | ✓ | ✓ | ✓ |
Building New Examples
See CLAUDE.md for a detailed guide covering:
- Step-by-step model creation (types → entities → spaces → blocks → spec → system)
- Role constraint rules (what each role enforces on its interface)
- Composition operator reference with pitfalls
- Common mistakes at construction, registration, and validation time
- Test patterns to follow
- Design decisions (state vs signal, parameter vs exogenous input, ControlAction vs Policy)
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
Release history Release notifications | RSS feed
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_examples-0.1.2.tar.gz.
File metadata
- Download URL: gds_examples-0.1.2.tar.gz
- Upload date:
- Size: 61.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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 |
ebf15615751d2cb92f3611ec8a4ce39645fedda2b139bb20e8ccab630c788a1f
|
|
| MD5 |
41e914011cfd23ca9574773a4e14aea5
|
|
| BLAKE2b-256 |
e94ee0cb10ddcf5d43272bd394cbbf21f12bae003c364663901a3557fab57d05
|
File details
Details for the file gds_examples-0.1.2-py3-none-any.whl.
File metadata
- Download URL: gds_examples-0.1.2-py3-none-any.whl
- Upload date:
- Size: 74.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","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 |
c863a62bc277e3735ff8827db361a06216d9c79e8baa687b4728480700bc8345
|
|
| MD5 |
adc4a5e490a7357a2c29438aa62339f6
|
|
| BLAKE2b-256 |
1cf9f9b042e714d0048d819aba326030628a6287aa2418ec1c41eb64da757798
|