Metadata-Version: 2.4
Name: gds-examples
Version: 0.1.0
Summary: Tutorial examples for gds-framework — five complete domain models demonstrating every framework feature
Project-URL: Homepage, https://github.com/BlockScience/gds-examples
Project-URL: Repository, https://github.com/BlockScience/gds-examples
Author-email: Rohan Mehta <rohan@block.science>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: compositional-systems,examples,gds-framework,generalized-dynamical-systems,system-specification,tutorial
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: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Requires-Dist: gds-framework>=0.2.0
Requires-Dist: gds-viz>=0.1.0
Description-Content-Type: text/markdown

# GDS Framework Examples

Five complete domain models demonstrating every framework feature. Each `model.py` is written as a tutorial chapter with inline GDS theory commentary — read them in order.

## Learning Path

Start with SIR Epidemic and work down. Each example introduces one new concept.

| # | Example | New Concept | Composition | Roles |
|:-:|---------|-------------|-------------|-------|
| 1 | [SIR Epidemic](#sir-epidemic) | Fundamentals — TypeDef, Entity, Space, blocks | `>>` `\|` | BA, P, M |
| 2 | [Thermostat PID](#thermostat-pid) | `.feedback()`, CONTRAVARIANT backward flow | `>>` `.feedback()` | BA, P, CA, M |
| 3 | [Lotka-Volterra](#lotka-volterra) | `.loop()`, COVARIANT temporal iteration | `>>` `\|` `.loop()` | BA, P, M |
| 4 | [Prisoner's Dilemma](#prisoners-dilemma) | Nested `\|`, multi-entity X, complex trees | `\|` `>>` `.loop()` | BA, P, M |
| 5 | [Insurance Contract](#insurance-contract) | ControlAction role, complete 4-role taxonomy | `>>` | BA, P, CA, M |

**Roles:** BA = BoundaryAction, P = Policy, CA = ControlAction, M = Mechanism

## Quick Start

```bash
# Run all example tests (140 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
```

Additional files:
- `examples/visualize_examples.py` — generates structural diagrams for all examples
- `examples/prisoners_dilemma/visualize.py` — custom architecture-aware diagram
- `examples/CLAUDE.md` — detailed guide for building new models from scratch

---

## SIR Epidemic

**Start here.** The most thoroughly documented example — every definition has inline commentary explaining the GDS concept it represents.

**Model:** 3 compartments (Susceptible, Infected, Recovered) with contact-driven infection dynamics.

**GDS Decomposition:**
```
X = (S, I, R)          — state: population counts
U = contact_rate        — exogenous input
g = infection_policy    — policy: computes deltas
f = (update_s, update_i, update_r)  — mechanisms: apply deltas
Θ = {beta, gamma, contact_rate}
```

**Composition:**
```python
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](sir_epidemic/model.py) · [tests](sir_epidemic/test_model.py) · [views](sir_epidemic/VIEWS.md)

---

## Thermostat PID

**Adds feedback** — backward information flow within a single timestep.

**Model:** PID controller maintaining room temperature with energy cost feedback from the plant.

**GDS Decomposition:**
```
X = (T, E)             — state: temperature, cumulative energy
U = measured_temp       — exogenous sensor reading
g = pid_controller      — policy with backward_in for cost feedback
f = update_room         — mechanism: applies changes to X
Θ = {setpoint, Kp, Ki, Kd}
```

**Composition:**
```python
(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 — that constraint is enforced at construction time.

**Files:** [model.py](thermostat/model.py) · [tests](thermostat/test_model.py) · [views](thermostat/VIEWS.md)

---

## Lotka-Volterra

**Adds temporal loops** — forward iteration across timesteps.

**Model:** Predator-prey population dynamics where updated populations feed back into rate computation at the next timestep.

**GDS Decomposition:**
```
X = (x, y)             — state: prey and predator populations
U = population_signal   — exogenous seed observation
g = compute_rates       — policy: Lotka-Volterra rate equations
f = (update_prey, update_predator)  — mechanisms with forward_out
Θ = {prey_birth_rate, predation_rate, predator_death_rate, predator_efficiency}
```

**Composition:**
```python
(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. The mechanisms here have `forward_out` ports, unlike SIR's terminal mechanisms.

**Files:** [model.py](lotka_volterra/model.py) · [tests](lotka_volterra/test_model.py) · [views](lotka_volterra/VIEWS.md)

---

## Prisoner's Dilemma

**Most complex composition** — nested parallel + sequential + temporal loop.

**Model:** Iterated game with two adaptive agents (Alice, Bob) learning from payoff outcomes.

**GDS Decomposition:**
```
X = (s_A, U_A, s_B, U_B, t)  — state: strategies, scores, round
U = game_config                — exogenous payoff matrix (R, T, S, P)
g = (alice_decision, bob_decision)  — independent policies
f = (payoff_realization, alice_world_model, bob_world_model)
Θ = {}  (payoff matrix is exogenous, not a parameter)
```

**Composition:**
```python
input_phase = payoff_setting | (alice_decision | bob_decision)
world_updates = alice_world_model | bob_world_model
pipeline = input_phase >> payoff_realization >> world_updates
system = pipeline.loop([world models -> decisions])
```

**What you'll learn:**
- Nested parallel composition: `(A | B) | C` for logical grouping
- Multi-entity state space X with 3 entities (5 state variables total)
- Mechanism with forward_out for temporal feedback (same pattern as lotka_volterra)
- Complex composition tree combining all operators except `.feedback()`
- Design choice: parameter vs exogenous input (payoff matrix is U, not Θ)

**Files:** [model.py](prisoners_dilemma/model.py) · [tests](prisoners_dilemma/test_model.py) · [views](prisoners_dilemma/VIEWS.md) · [architecture viz](prisoners_dilemma/visualize.py)

---

## Insurance Contract

**Completes the role taxonomy** — the only example using all 4 block roles.

**Model:** Claim processing pipeline with risk-based premium calculation and reserve management.

**GDS Decomposition:**
```
X = (R, P, C, H)      — state: reserve, premium pool, coverage, claims history
U = claim_event        — exogenous claim arrival
g = risk_assessment    — policy: scores risk from claim data
d = premium_calculation — control action: admissibility decision
f = (claim_payout, reserve_update)  — mechanisms: state transitions
Θ = {base_premium_rate, deductible, coverage_limit}
```

**Composition:**
```python
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
- Mechanism with forward_out for chaining within a timestep (Claim Payout → Reserve Update)

**Key distinction:** Premium Calculation is ControlAction because it enforces admissibility constraints (deductible, coverage limit) — it decides what's allowed, not what to do.

**Files:** [model.py](insurance/model.py) · [tests](insurance/test_model.py) · [views](insurance/VIEWS.md)

---

## Visualization Views

Each example includes a `generate_views.py` script that produces 6 complementary views:

| 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 (boundary/policy/mechanism/control) |
| 4. Architecture by Domain | GDSSpec | Blocks grouped by domain tag (organizational view) |
| 5. Parameter Influence | GDSSpec | Θ → blocks → entities causal map |
| 6. Traceability | GDSSpec | Backwards trace from one state variable to all influencing blocks |

Here's the **architecture by domain view** for the Thermostat PID — blocks grouped by domain tag (Sensor, Controller, Plant), revealing the physical subsystem decomposition:

```mermaid
%%{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
```

And the **structural view** for the Thermostat PID — note the thick feedback arrow (`==>`) from Room Plant back to PID Controller, showing CONTRAVARIANT within-timestep flow:

```mermaid
%%{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
```

Here's the **parameter influence view** for the SIR Epidemic — Θ → blocks → entities causal map showing which parameters affect which state variables:

```mermaid
%%{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](sir_epidemic/VIEWS.md) contains all 6 views with commentary explaining what each reveals for that specific model.

```bash
# 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; do
    uv run python examples/$d/generate_views.py --save
done
```

Output is Mermaid markdown — renders in GitHub, GitLab, VS Code, Obsidian, and [mermaid.live](https://mermaid.live).

---

## Test Coverage

All examples include tests covering every layer:

- **Types** — TypeDef.check_value() for valid/invalid/boundary values
- **Entities** — Entity.validate_state() with good/bad/missing data
- **Blocks** — Role isinstance checks, interface port counts, Mechanism.updates
- **Composition** — Operators build without error, flatten() yields expected block count
- **GDSSpec** — validate_spec() returns no errors, entity/block/parameter counts
- **SystemIR** — compile_system() succeeds, block/wiring counts correct
- **Verification** — Generic checks (G-001/003/004/005/006), semantic checks (completeness, determinism, type safety, reachability)
- **SpecQuery** — Dependency graphs, update maps, parameter tracking, causal chains

**Total: 140 example tests.** Run with `uv run pytest examples/ -v`.

---

## Feature Coverage Matrix

| Feature | SIR | Thermostat | Lotka-V | Prisoner's D | Insurance |
|---|:---:|:---:|:---:|:---:|:---:|
| BoundaryAction | ✓ | ✓ | ✓ | ✓ | ✓ |
| Policy | ✓ | ✓ | ✓ | ✓ | ✓ |
| Mechanism | ✓ | ✓ | ✓ | ✓ | ✓ |
| ControlAction | | ✓ | | | ✓ |
| `>>` (sequential) | ✓ | ✓ | ✓ | ✓ | ✓ |
| `\|` (parallel) | ✓ | | ✓ | ✓ | |
| `.feedback()` | | ✓ | | | |
| `.loop()` | | | ✓ | ✓ | |
| CONTRAVARIANT wiring | | ✓ | | | |
| Temporal wiring | | | ✓ | ✓ | |
| Multi-variable Entity | | ✓ | | ✓ | ✓ |
| Multiple entities | ✓ | | ✓ | ✓ | ✓ |
| Parameters (Θ) | ✓ | ✓ | ✓ | | ✓ |

---

## Building New Examples

See [CLAUDE.md](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

## Credits & Attribution

### Development & Implementation
* **Primary Author:** [Rohan Mehta](mailto:rohan@block.science)
* **Organization:** [BlockScience](https://block.science/)

### Theoretical Foundation
This codebase is a direct implementation of the research and mathematical frameworks developed by:
* **Dr. Jamsheed Shorish** ([@jshorish](https://github.com/jshorish)) and **Dr. Michael Zargham** ([@mzargham](https://github.com/mzargham)).
* **Key Reference:** [Generalized Dynamical Systems, Part I: Foundations](https://blog.block.science/generalized-dynamical-systems-part-i-foundations-2/) (BlockScience, 2021).

### Architectural Inspiration
The design patterns and structural approach of this library are heavily influenced by the prior work of **Sean McOwen** ([@SeanMcOwen](https://github.com/SeanMcOwen)), specifically:
* [MSML](https://github.com/BlockScience/MSML): For system specification logic.
* [bdp-lib](https://github.com/BlockScience/bdp-lib): For block-data processing architecture.

### Contributors
* **Peter Hacker** ([@phacker3](https://github.com/phacker3)) — Code auditing and review (BlockScience).

### Intellectual Lineage
This project exists within the broader ecosystem of:
* [cadCAD](https://github.com/cadCAD-org/cadCAD): For foundational philosophy in Complex Adaptive Dynamics.
