Skip to content

0.4 Periods and models

This section defines how stages are assembled into periods and models at the syntax level.

The underlying theory is developed in Composition as Twister, which adopts a Backus-style "algebra of programs" viewpoint:

  • Stages and periods are programs (operators on state spaces)
  • Composition is the combining form
  • Twisters are not auxiliary wiring — they are the composition operation

In Dolang+ terms: a period is stage-composition (intra-period), a model is period-composition (inter-period), both governed by interface-compatibility.


0.4.0 Composition as twister (foundation)

We write the typed composition of two modules \(S_1, S_2\) as \(\langle S_1, S_2 \rangle\).

Interfaces and typing

Let:

  • \(X_{\mathrm{arvl}}(S)\) denote the arrival field of \(S\) (inputs \(S\) expects)
  • \(X_{\mathrm{cntn}}(S)\) denote the continuation field of \(S\) (outputs \(S\) provides) Composition is defined when interfaces match (up to bijective rename):
\[ \langle S_1, S_2 \rangle \text{ is valid } \iff X_{\mathrm{cntn}}(S_1) \cong X_{\mathrm{arvl}}(S_2). \]

Informally, we will also say a period is defined by uniquely valid compositions such as \(\langle S_1, S_2 \rangle\).

Terminology (fields). We use field to denote an economic quantity defined over an underlying probability space—formally, an element of \(L^{2}(\Omega)\), for example. for example. For instance, assets \(a \in L^{2}(\Omega)\) is a field. In contrast, "variable" often connotes a scalar \(a \in \mathbb{R}\), which is not a fixed mathematical object but a placeholder. Fields are fixed objects admitting well-defined logical and algebraic operations.

Why fields matter for composition. Defining composition \(\langle S_1, S_2 \rangle\) requires that continuation and arrival interfaces refer to the same underlying object. Defining composition as "the continuation variable name equals the arrival variable name" is ill-posed: label names are not primitives in an MDP. Fields (random variables over a common filtration) are. Stage compositions is thus unambiguously defined through an isomorphism of a field, not a string equality.

Identity vs explicit twisters

When names match, the twister is identity and may be omitted:

\[ \langle S_1, S_2 \rangle \;\equiv\; \langle S_1, \mathrm{id}, S_2 \rangle. \]

When names differ but interfaces are isomorphic, insert an explicit adapter \(\tau\):

\[ \langle S_1, \tau, S_2 \rangle, \qquad \tau\colon X_{\mathrm{cntn}}(S_1) \xrightarrow{\sim} X_{\mathrm{arvl}}(S_2). \]

Notation

Syntax Meaning
\(\langle S_1, S_2 \rangle\) Compose with implicit identity twister
\(\langle S_1, \tau, S_2 \rangle\) Compose with explicit twister \(\tau\)
\(P = \langle S_1, S_2, S_3 \rangle\) Period as composition of stages
\(M = \langle P_0, \tau_0, P_1, \tau_1, \ldots, P_T \rangle\) Model as composition of periods

Default inter-stage wiring (v0.1 convention)

At the surface syntax level, a stage is a stage-local module: it declares perch-local fields and equations without explicit global time subscripts. Time enters only through composition (periods/nests).

In v0.1, the default sequential wiring between adjacent stage occurrences \(S_1\) (earlier) and \(S_2\) (later) is:

  • Forward (state) interface: the continuation perch of \(S_1\) supplies the arrival perch of \(S_2\) (up to rename).

In perch-slot notation, with an explicit adapter \(\tau\):

\[ x_{S_2}[<] \;:=\; \tau\!\bigl(x_{S_1}[>]\bigr), \qquad \tau : X_{\mathrm{cntn}}(S_1) \xrightarrow{\sim} X_{\mathrm{arvl}}(S_2). \]

When interfaces match by name, \(\tau\) is identity and is omitted.

Value-function wiring (backward interface)

Backward induction wires value objects in the opposite direction:

  • Backward (value) interface: the arrival value produced by the successor stage is the continuation value consumed by the predecessor stage (up to pullback by the same adapter).

Schematically:

\[ V_{S_1}[>] \;:=\; \tau^*\!\bigl(V_{S_2}[<]\bigr), \qquad (\tau^* V)(x) := V(\tau(x)). \]

The same wiring applies to any shadow / marginal value objects (e.g. dV).

Stationary fixed-point special case. In a single-stage stationary model, the “successor” is the stage itself, so the recursion identifies output with input:

\[ V[>] \equiv V[<], \qquad dV[>] \equiv dV[<]. \]

MDP well-formedness guarantee (typing first)

At the syntax level, a composed period/nest is well-formed if each adjacent interface match is witnessed by an identity or a rename isomorphism. Under this condition, the composition defines a valid Bellman problem (the remaining analytic assumptions—measurability, integrability, etc.—belong to the semantic layer, not the wiring layer).

This is a declarative specification: it says what the model is. Solving (backward induction, fixed-point iteration) is an interpreter concern.


0.4.1 Period templates

A period template is a timeless syntax directive. It declares:

Field Description
name Template identifier
stages Ordered list of stage objects (not references)
connectors (optional) Intra-period adapters for name mismatches

Key principle: The stages: list contains nested stage objects, not symbolic references via a ddsl syntax (although in practice, one may nest stages into a period in a variety of ways, via links for example or dicts). Each entry is either an inline stage definition or a YAML anchor/file inclusion that resolves to a complete stage. The period is defined by the stages it contains, not by names pointing elsewhere.

Rule (v0.1h): If adjacent stage interfaces have matching names, the connector is identity and must be omitted. Connectors exist only for name mismatches; inter-period wiring is handled by twisters, not by period templates.

Example: single-stage period

name: cons_period
stages:
  - cons_stage: !stage   # !stage denotes an embedded stage object

The tag !stage indicates that the value is a stage object (resolved from a file, anchor, or inline definition). The key cons_stage is an occurrence name scoped to this period—it is not a global reference.

Example: multi-stage period with rename connector

name: cons_port_period
stages:
  - cons_stage: !stage   # first stage occurrence
  - port_stage: !stage   # second stage occurrence

connectors:
  - from: cons_stage
    to: port_stage
    rename: {a: k}

Here cons_stage and port_stage are local occurrence names within this period. The connector's from/to fields refer to these local names, not to external templates.

Branching (deferred)

v0.1h treats stages: as an ordered list. Within-period graphs with branching or merging are deferred to a future layer.


0.4.2 Nest

A nest declares a sequential composition of period objects together with inter-period twisters.

Field Description
name Nest identifier
periods Ordered list of period objects (not references)
twisters Position-aligned list of inter-period adapters

Key principle: The periods: list contains nested period objects. A nest is not a list of template names; it is a collection of period instances (each containing its own stage objects). The nest is the composition structure.

Convention (v0.1h): twisters[i] connects periods[i] to periods[i+1] in forward time. Hence twisters carry no from/to fields — position determines adjacency.

Example: minimal nest template

name: lifecycle_cons_example

periods:
  - !period    # period object at position 0
  - !period    # period object at position 1
  - !period    # period object at position 2
  - !period    # period object at position 3
  - !period    # period object at position 4

twisters:
  - {a: k}
  - {a: k}
  - {a: k}

Each !period tag resolves to a complete period object. The nest contains four period instances; their identity is determined by their position in the list, not by any name field.

Example: explicit period nesting

name: lifecycle_cons_example

periods:
  - !period
      name: p0
      stages:
        - cons_stage: {!stage}
  - !period
      name: p1
      stages:
        - cons_stage: !stage
  - !period
      name: p2
      stages:
        - cons_stage: !stage

twisters:
  - rename: {a: k}
  - rename: {a: k}

The name: fields within periods are optional labels for documentation; they do not affect composition semantics. Composition is determined by list position and twister alignment.

Optional repeat: sugar

name: lifecycle_cons_example
periods:
  - period: cons_period
    repeat: 4

twisters:
  - rename: {a: k}
    repeat: 3

This is builder-level sugar; v0.1h does not require it.

Critical constraint: Time indices (age, \(t\), horizon counters) do not appear in stage or period templates. They belong to the builder/orchestration layer.


0.4.3 Connectors and twisters

Connectors (intra-period)

A connector is an adapter between adjacent stages within a period. Semantically it is an intra-period twister.

connectors:
  - from: cons_stage
    to: port_stage
    rename: {a: k}

If upstream output names equal downstream input names, the connector is identity and should be omitted.

Twisters (inter-period)

A twister specifies how adjacent periods are connected. In v0.1h it is typically a pure rename (possibly empty for identity).

twisters:
  - rename: {a: k}

Identity twister (omit rename or use empty map):

twisters:
  - {}

Abstractly, a twister is a state-space map

\[ g_{ca}: X_{\mathrm{cntn},t} \to X_{\mathrm{arvl},t+1}. \]

This map induces:

  • Pullback on value objects: \((g_{ca}^* V)(x) = V(g_{ca}(x))\)
  • Pushforward on distributions: \((g_{ca})_* \mu\)

In v0.1h most twisters are pure renames. Richer "computed" twisters (aging counters, regime switches) are possible but the wiring-only principle remains: do not embed discounting or economics in twisters.


0.4.4 Model as bindings (semantic contract)

A model is a collection of: 1. Stages — possibly with attached calibration, methodization, settings 2. Periods — ordered compositions of stages 3. Twisters — inter-period adapters This definition is representation-agnostic. Valid materializations include:

  • A folder tree with YAML files
  • Python dicts built incrementally
  • A single serialized object
  • Any form preserving the semantic contract

DDSL specifies what bindings must exist, not how they are produced.

Binding types

For a fully instantiated (solvable) model, each stage is expected to have:

Binding Description
SYM Mathematical content: ADC perches, equations, symbol declarations
Calibration Parameter values
Methodization Scheme/method pairings for operators
Settings Numerical settings (grid sizes, tolerances)
### Degrees of instantiation

Stages (and models) exist at increasing "status" levels:

  • Mathematized: SYM only
  • Calibrated: SYM + parameter bindings
  • Methodized/configured: SYM + calibration + methodization + settings
  • Solved: computational artifacts attached

This is a conceptual ladder, not a prescribed class hierarchy.


0.4.5 Stage-level bindings

Calibration, methodization, and settings are bound at the stage level, not the period level.

Consequences: - Each stage is self-contained at every instantiation level - A period is the union of its constituent stages - There is no "period-level calibration" that overrides stage calibrations

Benefits:

  • Modularity: stages reusable across periods
  • Clarity: parameters, methods, settings co-located
  • Testability: stages validated in isolation If multiple stages share a parameter (e.g., \(\gamma\) for risk aversion), the orchestration layer ensures consistent values — DDSL does not prescribe how.

0.4.6 Syntax collection vs instantiated model

Syntax collection (template library)

A syntax collection is a set of reusable syntactic artifacts:

  • Stage SYM files
  • Period templates
  • Default calibration/methodization templates A syntax collection is not yet a model: it does not commit to a time index set, a period family, or per-stage calibrations.

Directory layout is not part of the specification

syntax-rules #file-organisation

dolo-plus specifies the content of the YAML files (stage structure, symbol declarations, equation blocks, methodization schemes, calibration bindings) but not how those files are organised on disk. A "library" directory grouping stage YAMLs, methods YAMLs, calibration.yaml, and settings.yaml together is a useful convention — not a language requirement. A different project may scatter files across directories, generate them programmatically, or embed them inline. What matters is that the orchestration layer can locate and load the correct artifacts; the folder layout is an implementation choice, not a semantic one.

Instantiated model

An instantiated model is a concrete sequential decision process created by orchestration: 1. Select templates from a syntax collection 2. Bind calibration to each stage 3. Bind methodization and settings 4. Construct periods as compositions of bound stages 5. Construct twisters connecting consecutive periods

The result is a model: a sequence of fully-bound periods with inter-period wiring.


0.4.7 Scope boundaries

Scope Description
Stage Reusable intra-period module with ADC perches and equation blocks
Period Namespace + ordered composition of stages
Model Sequence of periods with twisters

Rule: syntactic stages remain reusable templates; the orchestration layer handles instantiation, calibration binding, and inter-period wiring.


0.4.8 Relationship to future extensions

The v0.1h construction is the sequential (path) special case:

  • Periods totally ordered: \(P_0 \to P_1 \to \cdots \to P_T\)
  • Twisters position-aligned

Future extensions may support:

  • Branching scenario trees (DAGs with nonanticipativity)
  • Explicit loop-closure for infinite-horizon recursion
  • Richer connector types beyond pure renames

The key invariant: the syntax collection vs instantiation boundary. Templates remain reusable; orchestration handles time-indexing, branching, and binding.


0.4.9 Summary

Concept Definition
Period template name:, stages: [...], optional connectors: [...]
Nest template name:, periods: [...], twisters: [...] (position-aligned)
Stage template Reusable stage file (timeless)
Bindings Calibration/methodization/settings at stage level
Connector Intra-period adapter {from, to, rename}
Twister Inter-period adapter; v0.1h: positional, typically {rename: {...}}
Repeat Optional builder sugar repeat: N