Skip to content

Symbol Reference Table

Single Source of Truth for Bellman calculus Notation

Core Convention

  • Spaces: Capital sans-serif (\(\mathsf X_{\prec}\), \(\mathsf X\), \(\mathsf X_{\succ}\))
  • Elements: Lowercase italic with perch subscript (\(x_{\prec}\), \(x\), \(x_{\succ}\))
  • Functions / maps: Upright roman (\(\mathrm{f}\), \(\mathrm{g}\), \(\mathrm{r}\), \(\mathrm{v}\))
  • Operators / movers: Blackboard bold (\(\mathbb{B}\), \(\mathbb{I}\), \(\mathbb{T}\), \(\mathbb{F}\))
  • Formal role: Determined by syntactic definition (@def, @in), not by naming

Perch index alphabet

Perch Math subscript YAML tag (preferred) YAML tag (long form)
Arrival \(\prec\) [<] arvl
Decision \(\sim\) [~] dcsn
Continuation \(\succ\) [>] cntn

Decision-perch objects are unmarked in surface syntax (V, x, dV). Arrival and continuation perches use [<] and [>].

Justification of the perch index notation

Definition. Let \((\mathcal{F}_\prec,\, \mathcal{F}_\sim,\, \mathcal{F}_\succ)\) be a filtration chain with \(\mathcal{F}_\prec \subseteq \mathcal{F}_\sim \subseteq \mathcal{F}_\succ\), where \(\mathcal{F}_i\) is induced by the state variables observable at perch \(i\):

\[\mathcal{F}_\prec \coloneqq \sigma(x_\prec), \qquad \mathcal{F}_\sim \coloneqq \sigma(x_\prec, x_\sim), \qquad \mathcal{F}_\succ \coloneqq \sigma(x_\prec, x_\sim, x_\succ)\]

Designate \(\mathcal{F}_\sim\) as the reference (decision) filtration. The perch subscripts are the predicate induced by fixing one argument of the inclusion order:

  • \(x_\prec\): a random variable \(\mathcal{F}_\prec\)-measurable, where \(\mathcal{F}_\prec \prec \mathcal{F}_\sim\) (strictly coarser than the decision)
  • \(x\) (unmarked): a random variable \(\mathcal{F}_\sim\)-measurable (the reference)
  • \(x_\succ\): a random variable \(\mathcal{F}_\succ\)-measurable, where \(\mathcal{F}_\succ \succ \mathcal{F}_\sim\) (strictly finer than the decision)

The subscripts \(\prec\) and \(\succ\) are not names — they are the order relation of the filtration, with the decision as the fixed argument. This is the same notational pattern as \(\mathbb{R}_{>0} = \{x \in \mathbb{R} : x > 0\}\): the subscript is a predicate (a defining condition relative to a reference point), not a label. The subscript \(\prec\) states the fact that the arrival filtration is strictly coarser than the decision filtration.

The YAML surface forms [<] and [>] are the ASCII rendering of \(\prec\) and \(\succ\).

Remark (novelty and precedents). Using an order relation as a subscript to index position in a filtration appears to be new in the dynamic programming literature. The closest precedents are: (i) the filtration limits \(\mathcal{F}_{t^-}\), \(\mathcal{F}_{t^+}\) in stochastic calculus, which use order-relative logic on a continuous parameter; (ii) the incoming/outgoing boundary notation \(\partial^{\pm}M\) in TQFT; (iii) pre-place/post-place notation \({}^{\bullet}t\), \(t^{\bullet}\) in Petri nets. The motivation for this convention is that perch indices should be compositional (relative to the stage, not to absolute time) and self-describing (the symbol encodes its meaning).

Derivative notation and the _{.} operator convention

The _{...} convention: when _{...} appears after an operator name, the content inside the braces specifies with respect to what the operator acts. This is distinct from plain underscore _, which is a name separator (e.g. m_d is "the variable named m-d", not "derivative of m").

Syntax pattern Meaning Mathematical
d_{a}V Partial derivative of \(V\) wrt \(a\) \(\partial_a \mathrm{v}\)
d_{h}V Partial derivative of \(V\) wrt \(h\) \(\partial_h \mathrm{v}\)
d_{a}V[<] \(\partial_a \mathrm{v}\) at arrival perch \(\partial_a \mathrm{v}_\prec\)
d_{a}V[>] \(\partial_a \mathrm{v}\) at continuation perch \(\partial_a \mathrm{v}_\succ\)
d_{a,a}V Second derivative wrt \(a\) \(\partial_{aa} \mathrm{v}\)
d_{a}d_{h}V Cross partial \(\partial_a \partial_h \mathrm{v}\)
E_{θ}(V) Expectation wrt \(\theta\) \(\mathbb{E}_\theta[\mathrm{v}]\)
max_{c}{...} Maximise over \(c\) \(\sup_c\{\cdots\}\)

The convention applies uniformly to all operators: d_{.} for derivatives, E_{.} for expectations, max_{.} for maximisation. The variable inside _{...} must be a declared symbol (state, control, or exogenous).

Reserved operator names for differentiation:

Operator Mathematical Meaning
d \(\partial\) Partial derivatived_{x}V means \(\partial V / \partial x\), holding all other arguments fixed
D \(\mathrm{D}\) Total derivative (Jacobian / Fréchet) — D_{x}V means \(\mathrm{D}_x V\), the total derivative including indirect dependence through other variables

In most stage equations, d (partial) is the relevant operator — envelope conditions, Euler equations, and EGM all use partial derivatives. D (total) arises in chain-rule contexts (e.g. computing the total effect of a state change through a transition).

No naming conflict with variables. A bare d (e.g. d: '@in {keep, adjust}') is a valid variable name. The derivative operator is only triggered by the pattern d_{...} — the _{ token is what distinguishes operator-with-subscript from a plain identifier. The parser never confuses d (a variable) with d_{a} (partial derivative wrt \(a\)).

Disambiguation: _{...} (with braces) always means "with respect to." Plain underscore without braces is always a name separator. There is no ambiguity:

Expression Meaning
d_{a}V Derivative of \(V\) wrt \(a\)
m_d Variable named "m-d" (decision-perch cash-on-hand)
V_own Value function named "V-own" (branch label)
d_{a}V_own Derivative of \(V_{\text{own}}\) wrt \(a\)

Declaring marginal values in values_marginal:

When a stage has multiple state variables and the method requires separate marginals (e.g. multi-dimensional EGM), declare one entry per (variable, perch) pair:

values_marginal:
  d_{a}V[<]: "@in R"       # ∂ₐv at arrival
  d_{h}V[<]: "@in R"       # ∂ₕv at arrival
  d_{a}V: "@in R"           # ∂ₐv at decision
  d_{h}V: "@in R"           # ∂ₕv at decision
  d_{a}V[>]: "@in R+"       # ∂ₐv at continuation
  d_{h}V[>]: "@in R+"       # ∂ₕv at continuation

For stages with a single state variable, the _{...} subscript may be omitted since the differentiation variable is unambiguous:

values_marginal:
  dV[<]: "@in R+"
  dV: "@in R+"
  dV[>]: "@in R+"

Legacy notation: dV_a (plain underscore) is deprecated. Use d_{a}V instead.

Open design question: declared symbol vs canonical operator

It is currently unresolved whether d_{a}V[<] should be:

  1. A declared symbol — the user explicitly lists d_{a}V[<]: "@in R" in values_marginal, creating a named object that equations reference. The d_{a} prefix is a naming convention with no computational meaning at the SYM layer.

  2. A canonical operator applicationd_{a} is a first-class operator that the system applies to V[<] automatically. No declaration in values_marginal is needed; the system infers the marginal's existence and type from the operator and its argument.

Under interpretation (1), the system could also accept d_a_V as a plain variable name for the same object (underscore as name separator). Under interpretation (2), d_{a}V[<] is computed, not declared, and d_a_V would be a distinct user-defined symbol with no automatic relationship to the derivative.

Current stance: v0.1 uses interpretation (1) — marginals are declared symbols. The _{...} convention is a naming discipline, not a computational operator. Whether to elevate d_{.} to a true operator (interpretation 2) is deferred to a future spec revision.

ambiguity #values-marginal #operator-vs-symbol #todo

Rosetta Stone: Math ↔ YAML

Mathematical Dolo+ syntax Description Declaration Note
\(\mathsf X_{\prec}\) prestate: space (implied by domain of prestate variable) Arrival state space Optional (implied by domain)
\(\mathsf X\) states: space Decision state space Optional (implied by domain)
\(\mathsf X_{\succ}\) poststates: space Continuation state space Optional (implied by domain) Poststate and continuation state may differ; e.g. in a primal Bellman representation the continuation state is next-period market resources.
\(x_{\prec}\) Variable in prestate, tagged x[<]. Declaring m in prestate implies x[<] = [m]. Arrival state variable Variable name and domain required In a measure-theoretic framework these are random variables on an underlying probability space.
\(x\) Variable in states, tagged x (unmarked) Decision state variable Variable name and domain required
\(x_{\succ}\) Variable in poststates, tagged x[>] Continuation state variable Variable name and domain required
\(\mathrm{v}_{\prec}\) V[<] — sugar for \(\mathrm{v}_{\prec}(x_{\prec})\). Interpreted as V_fn[<](x[<]). Can be a tuple [V_adj[<], V_nadj[<]]. Arrival value function Domain must agree with perch state dimension
\(\mathrm{v}\) V (unmarked) Decision value function Domain must agree with perch state dimension
\(\mathrm{v}_{\succ}\) V[>] Continuation value function Domain must agree with perch state dimension
\(\partial_m\mathrm{v}\) d_{m}V (preferred), dV (single-state shorthand) Marginal decision value Required only if method needs it For multi-state stages, declare one per state variable: d_{a}V, d_{h}V.
\(\partial_a\mathrm{v}_{\succ}\) d_{a}V[>] (preferred), dV[>] (single-state shorthand) Marginal continuation value Required only if method needs it
\(\mathrm{g}_{\prec\sim}\) arvl_to_dcsn_transition; optional tag g[<] Arrival → decision transition Required if non-trivial; must satisfy measurability at perches
\(\mathrm{g}_{\sim\succ}\) dcsn_to_cntn_transition; optional tag g[>] Decision → continuation transition Required if non-trivial
\(\mathbb{B}\) cntn_to_dcsn_mover; optional tag BB Decision mover (backward, cntn → dcsn) Required if non-trivial; sub-equations depend on chosen method
\(\mathbb{I}\) dcsn_to_arvl_mover; optional tag II Arrival mover (backward, dcsn → arvl) Required if non-trivial
\(\mathbb{T}_{[S]} = \mathbb{I}\,\mathbb{B}\) Stage YAML file; sugar: \(\mathbb{S}\) Stage operator (composite) Stage name declared at period level
\(\Gamma(x)\) Feasibility constraint via declarations below equation Action correspondence Optional
\(\mathrm{r}\) rwd_function; sugar r — expands to r_fn(x, a) Stage reward Required if not declared in Bellman operator
\(\beta\) beta in parameters Discount factor
\(\zeta\) Shock in exogenous (pre-decision) Pre-decision shock
\(\eta\) Shock in exogenous (post-decision) Post-decision shock
\(\mathbb{E}_{\succ}\{\cdot\}\) E_{shock_name}(·) Expectation operator
\(\sup_{a\in\Gamma(x)}\) max_{c}{} Maximisation operator
\(\arg\sup_{a\in\Gamma}\) argmax_{c}{} Policy operator
\(\mathrm{a}\colon\mathsf X\to\mathsf A\) Policy/action/control function; can substitute a declared control variable c Optimal policy Canonically sugared to a_fn(x) since a sits at the decision perch.
\(a\) Control variable
\(N_+\) Set of branch labels (in branching connector/twister) Valid successor stage kinds Required for branching stages (kind: "branching") Each \(j \in N_+\) indexes a distinct successor with its own state space.
\(p(j \mid x_v, \pi)\) Appears explicitly in cntn_to_dcsn_mover.Bellman as a coefficient in a weighted sum (exogenous or computed in-equation, e.g. softmax) Branching probability for branch \(j\) Required for probabilistic branching; \(\sum_j p_j = 1\) Uses standard exogenous/parameter declarations or explicit probability-generation equations — no special YAML metadata is required.
\(\mathrm{v}_{\prec,j}\) Arrival value of branch target \(j\) (e.g. V_own, V_rent; bound by values.V[>] as {own: V_own, rent: V_rent}) Branch-specific arrival value function One per branch; separate named object Value functions along each branch are named and separable.
\(\mathrm{g}_{\sim\succ,j}\) dcsn_to_cntn_transition.{label} (e.g. dcsn_to_cntn_transition.own; legacy: dcsn_to_cntn_own_transition) Branch-specific transition One per branch; may map to different state spaces
\(\mathsf X_{\succ,j}\) poststates: {label}: sub-block (e.g. own:, rent:; legacy: cntn_{label}) Branch-specific continuation space One per branch

Argument delimiters (SYM surface syntax)

  • Perch tags: x[<], x[~], x[>] are perch indices (measurability declarations), not function application.
  • Function evaluation: f[x], f[x, y] (preferred SYM form for “evaluate f at arguments”).
  • Operator application (higher-order operators acting on expressions/functions):
  • Operator bodies use braces {…} (e.g. max_c{…}, argmax_c{…}).
  • Some named operators use parentheses (…) (e.g. E_y(V)); treat these as operator arguments, not as general function-call syntax.

Open questions

  • Declaration of distributions that depend on the state.
  • Function arguments / intermediate evaluation
  • Whether to allow () notation for arbitrary function evaluation at intermediate variables that are not states. Suggestion: only if a function is explicitly declared with a name (e.g. consumed_func: c = y, then consumed_func[y]).
  • Intermediate rule: we use [] to define function-argument evaluation in SYM.
  • Use mathematical rules in T core to define/validate function arguments. #function-arguments #functin-arguments #ambiguity #ddsl-core #t-core #function-definition #core-vs-sym

1. The Stage (ADC Structure)

Perches (nodes)

Each stage has three perches forming a filtration \(\mathcal{F}_{\prec} \subseteq \mathcal{F}_{\sim} \subseteq \mathcal{F}_{\succ}\).

Perch Math state Math value YAML tag YAML section
Arrival (\(\prec\)) \(x_{\prec}\in\mathsf X_{\prec}\) \(\mathrm{v}_{\prec}\) [<] (preferred), arvl prestate
Decision (\(\sim\)) \(x\in\mathsf X\) \(\mathrm{v}\) (unmarked), dcsn states
Continuation (\(\succ\)) \(x_{\succ}\in\mathsf X_{\succ}\) \(\mathrm{v}_{\succ}\) [>] (preferred), cntn poststates

Perch tags are measurability declarations: z[<] asserts that \(z\) is \(\mathcal{F}_{\prec}\)-measurable; z[>] asserts \(\mathcal{F}_{\succ}\)-measurability. Decision-perch variables are unmarked.

Movers (edges)

Edge Forward (transition) Backward (value) YAML forward YAML backward
Arrival → Decision \(x = \mathrm{g}_{\prec\sim}(x_{\prec},\,\zeta)\) \(\mathrm{v}_{\prec} = \mathbb{I}\,\mathrm{v}\) arvl_to_dcsn_transition dcsn_to_arvl_mover
Decision → Continuation \(x_{\succ} = \mathrm{g}_{\sim\succ}(x,\,a,\,\eta)\) \(\mathrm{v} = \mathbb{B}\,\mathrm{v}_{\succ}\) dcsn_to_cntn_transition cntn_to_dcsn_mover

The composite stage operator is \(\mathbb{T} = \mathbb{I}\circ\mathbb{B}\colon\mathscr{B}(\mathsf X_{\succ})\to\mathscr{B}(\mathsf X_{\prec})\).

Branching stages

A branching stage (kind: "branching") has multiple continuation perches, one per branch \(j \in N_+\):

Perch Math state Math value YAML section
Continuation \(j\) (\(\succ_j\)) \(x_{\succ,j}\in\mathsf X_{\succ,j}\) \(\mathrm{v}_{\succ,j}\) poststates: {label}:

Each branch has its own state space \(\mathsf X_{\succ,j}\), transition \(\mathrm{g}_{\sim\succ,j}\), and value function \(\mathrm{v}_{\succ,j}\). Branching arises when these state spaces are heterogeneous (different dimensions or domains across branches).

The continuation space is formally a coproduct \(\mathsf X_{\succ} = \coprod_{j \in N_+} \mathsf X_{\succ,j}\), with elements \((j, x_j)\) — a discrete label paired with a branch-specific (typically continuous) state. When all branches share the same continuous space \(\mathsf X_c\), this collapses to a product \(N_+ \times \mathsf X_c\). Value functions on a coproduct decompose as \(\mathrm{v}_{\succ} \in \mathcal{V}(\mathsf X_{\succ}) \iff (\mathrm{v}_{\succ,j})_{j} \in \prod_j \mathcal{V}(\mathsf X_{\succ,j})\) — the named sub-blocks in poststates are the syntactic representation of this decomposition.

The backward mover at a branching stage receives multiple continuation values and aggregates:

Aggregation Backward mover \(\mathbb{B}\) Forward operator
max (discrete choice) \(\mathrm{v}(x) = \max_{j \in N_+} \mathrm{v}_{\succ,j}\!\bigl(\mathrm{g}_{\sim\succ,j}(x)\bigr)\) Route to \(j^* = \arg\max_j\); population partitions
expectation (stochastic) \(\mathrm{v}(x) = \sum_{j \in N_+} p_j(x)\,\mathrm{v}_{\succ,j}\!\bigl(\mathrm{g}_{\sim\succ,j}(x)\bigr)\) Draw \(j \sim p(\cdot\mid x)\); population splits by weight

Within-stage discrete choice over a homogeneous finite set (e.g. \(H' \in \mathcal{H}\), same state space for all choices) does not require branching — use max_{c}{…} instead. Branching is for heterogeneous successors: different state spaces, different value functions, different downstream stages. See Spec 0.1l §9 for the full distinction.

Connectors and twisters are unchanged. Branching is entirely a stage-level concept. Composition between a branching stage's continuation perches and successor stages uses the existing namespace rule: field names match implicitly, or standard rename connectors/twisters provide the mapping. Branching probabilities are declared as standard exogenous: or parameters: in the stage YAML.

Sub-equations within movers

Each mover can contain a list of sub-equations; methods supply mover-equation recipes (e.g. EGM).

At minimum the value recursion (V[<] or V) and control recovery (c[>]) must be specified.

Sub-equation Purpose Typical content
Bellman Value recursion V = max_{c}(u(c) + β*V[>])
InvEuler Inverse Euler (EGM) c[>] = (β*dV[>])^(-1/ρ)
MarginalBellman Envelope condition dV = u'(c)
ShadowBellman Marginal expectation dV[<] = R * E_{θ}(dV)

To do — interpretation of sub-equations. The sub-equations listed above can be viewed in (at least) two ways:

  1. As implementation schemes: each sub-equation is a recipe that a particular numerical method (VFI, EGM, …) uses to implement the abstract mover \(\mathbb{B}\) or \(\mathbb{I}\). Different methods select different subsets of these equations. Under this view, Bellman and InvEuler are alternative routes to the same operator — one via direct maximisation, the other via the inverse Euler step.

  2. As a decomposition of the mover into named sub-operators: each sub-equation defines a distinct functional object (value recursion, envelope condition, shadow value, etc.) and the mover is the composition or coupling of these objects. Under this view, the sub-equations are part of the mathematical specification, not just solver details.

Clarifying which view is canonical (or whether both coexist at different layers — e.g. view 2 at the SYM/T core level, view 1 at the methodization level) is an open design question.

Forward operators

Distribution evolution is described as pushforward under the transition kernels:

  • Arrival → Decision: push \(\mu_{\prec}\) forward under \((x_{\prec},\zeta)\mapsto\mathrm{g}_{\prec\sim}(x_{\prec},\zeta)\).
  • Decision → Continuation: push \(\mu\) forward under \((x,a,\eta)\mapsto\mathrm{g}_{\sim\succ}(x,a,\eta)\) (with \(a=\pi(x)\)).

The backward mover \(\mathbb{I}\) is the integral operator adjoint to pushforward under \(\mathrm{g}_{\prec\sim}\):

\[\langle (\mathrm{g}_{\prec\sim})_{\#}\,\mu_{\prec},\;\mathrm{v}\rangle \;=\; \langle\mu_{\prec},\;\mathbb{I}\,\mathrm{v}\rangle,\]

and similarly \(\mathbb{B}\) is adjoint to pushforward under \(\mathrm{g}_{\sim\succ}\). (Categorically, this is an adjunction \(K_{\#}\dashv K^{*}\) in the Kleisli category of the Giry monad.)

2. Shock Configurations

Configuration \(\mathsf Z_{\prec}\) \(\mathsf Z_{\succ}\) Arrival → Decision kernel \(\mathrm{g}_{\prec\sim}\) Decision → Continuation kernel \(\mathrm{g}_{\sim\succ}\)
Pre-decision only non-trivial \(\{\varnothing\}\) \(\mathrm{g}_{\prec\sim}(x_{\prec},\zeta)\) \(\mathrm{g}_{\sim\succ}(x,a)\)
Post-decision only \(\{\varnothing\}\) non-trivial identity: \(\mathrm{g}_{\prec\sim}(x_{\prec})=x\) \(\mathrm{g}_{\sim\succ}(x,a,\eta)\)
Both non-trivial non-trivial general general
Deterministic \(\{\varnothing\}\) \(\{\varnothing\}\) identity: \(\mathrm{g}_{\prec\sim}(x_{\prec})=x\) \(\mathrm{g}_{\sim\succ}(x,a)\)

3. Composition

Concept Mathematical YAML Description Note
Stage operator \(\mathbb{T}_{[S]} = \mathbb{I}_{[S]}\circ\mathbb{B}_{[S]}\) Stage YAML file Single stage backward sweep
Intra-period connector \(\mathrm{g}_{\succ,\prec}\) connectors: with rename: Intra-period field renaming Same syntax for sequential and branching — connectors just rename. Branching wiring is implied by the stage's multiple continuation perches and the namespace.
Period operator Given by the stage graph stages: list in period YAML Composed backward sweep For branching periods, the stage graph is a DAG; solve order is topological sort.
Inter-period connector \(\chi_{j,j+1}\) twisters: with rename: Inter-period field renaming Same syntax for sequential and branching. DAG nests add explicit to: for target period.

Viewing composition as a graph greatly simplifies the definition of inter- and intra-stage links: no domain, range, or stage-specific measurable functions are needed—only pairs of field names.

Period and stage indexing (in progress)

To do. Standardise notation for:

  • Stage occurrences within a period (e.g. \(j\), \(s_j\), \(\mathbb{T}_j\)), and
  • Period instances within a nest (e.g. \(t\), \(\mathbb{T}^{(t)}\)),

together with SYM surface spelling rules (so these do not get confused with within-stage perch tags [<], (unmarked), [>]).

4. YAML Syntax

Top-level sections

symbols:
  spaces:           # Space/domain definitions (@def)
  prestate:         # Arrival state variables (@in)
  states:           # Decision state variables (@in)
  poststates:       # Continuation state variables (@in)
  controls:         # Action variables (@in)
  exogenous:        # Shocks with distributions (@in, @dist)
  values:           # Value function objects (V[<], V, V[>])
  values_marginal:  # Marginal value objects (dV[<], dV, dV[>])
  parameters:       # Problem constants (Υ-level)
  settings:         # Numerical configuration (ρ-level)

equations:
  arvl_to_dcsn_transition: |   # g_{≺○} kernel (arrival → decision)
  dcsn_to_cntn_transition: |   # g_{○≻} kernel (decision → continuation)
  cntn_to_dcsn_mover:          # 𝔹 backward mover
    Bellman: |
    InvEuler: |
    MarginalBellman: |
  dcsn_to_arvl_mover:          # 𝕀 backward mover
    Bellman: |
    ShadowBellman: |

Type operators

Operator Meaning Example
@def Define space/type ("is defined as") Xm: "@def R++"
@in Membership declaration ("∈") m: "@in Xm"
@dist Distribution family "@dist LogNormal(μ_θ, σ_θ)"

Equation operators

Operator YAML form Mathematical
Expectation E_{θ}(V[>]) \(\mathbb{E}_{\theta}[\mathrm{v}_{\succ}]\)
Maximisation max_{c}(u + β*V[>]) \(\sup_{c}\{u + \beta\,\mathrm{v}_{\succ}\}\)
argmax argmax_{c}(u + β*V[>]) \(\arg\sup_{c}\{u + \beta\,\mathrm{v}_{\succ}\}\)

Worked example: cons_stage

symbols:
  spaces:
    Xm: "@def R++"
    Xa: "@def R+"
  prestate:
    m: "@in Xm"
  states:
    m_d: "@in Xm"
  poststates:
    a: "@in Xa"
  controls:
    c: "@in Xm"
  values:
    V[<]: "@in R"
    V: "@in R"
    V[>]: "@in R"
  values_marginal:
    dV: "@in R+"
    dV[>]: "@in R+"
  parameters: [β, ρ]

equations:
  arvl_to_dcsn_transition: |
    m_d = m
  dcsn_to_cntn_transition: |
    a = m_d - c

  cntn_to_dcsn_mover:
    Bellman: |
      V = max_{c}(u(c) + β*V[>])
    InvEuler: |
      c[>] = (β*dV[>])^(-1/ρ)
    MarginalBellman: |
      dV = (c)^(-ρ)
  dcsn_to_arvl_mover:
    Bellman: |
      V[<] = V

Stage operator: \((\mathbb{B}\,\mathrm{v}_{\succ})(m) = \max_{c\in(0,m)}\{u(c) + \beta\,\mathrm{v}_{\succ}(m-c)\}\); \(\mathbb{I}=\mathrm{id}\).

Worked example: noport_stage

symbols:
  spaces:
    Xk: "@def R++"
    Xm: "@def R++"
    Θ: "@def R++"
  prestate:
    k: "@in Xk"
  states:
    k_d: "@in Xk"
  poststates:
    m: "@in Xm"
  exogenous:
    θ:
      - "@in Θ"
      - "@dist LogNormal(μ_θ, σ_θ)"
  values:
    V[<]: "@in R"
    V: "@in R"
    V[>]: "@in R"
  parameters: [R, μ_θ, σ_θ]

equations:
  arvl_to_dcsn_transition: |
    k_d = k
  dcsn_to_cntn_transition: |
    m = k_d*R + θ

  cntn_to_dcsn_mover:
    Bellman: |
      V = E_{θ}(V[>])
  dcsn_to_arvl_mover:
    Bellman: |
      V[<] = V

Stage operator: \((\mathbb{B}\,\mathrm{v}_{\succ})(k) = \mathbb{E}_{\theta}[\mathrm{v}_{\succ}(kR + \theta)]\); \(\mathbb{I}=\mathrm{id}\).

Worked example: tenure_choice (branching stage)

symbols:
  spaces:
    Xa: "@def R+"
    XH: "@def linspace(H_min, H_max, n_H)"
    XY: "@def {1, ..., n_y}"
  prestate:
    a: "@in Xa"
    H: "@in XH"
    y_pre: "@in XY"
  states:
    a: "@in Xa"
    H: "@in XH"
    y: "@in XY"
  poststates:
    own:
      a: "@in Xa"
      H: "@in XH"
      y: "@in XY"
    rent:
      w: "@in Xa"
      y: "@in XY"
  controls:
    d: "@in {own, rent}"
  exogenous:
    y:
      - "@in XY"
      - "@dist MarkovChain(Pi, z_vals)"
  values:
    V[<]: "@in R"
    V: "@in R"
    V[>]:
      own: V_own
      rent: V_rent
    V_own: "@in R"
    V_rent: "@in R"
  parameters: [beta, r]

stage:
  kind: "branching"

equations:
  arvl_to_dcsn_transition: |
    a = a[<]
    H = H[<]
    y = y_shock

  dcsn_to_cntn_transition:
    own: |
      a[>] = a
      H[>] = H
      y[>] = y

    rent: |
      w[>] = (1+r)*a + H
      y[>] = y

  cntn_to_dcsn_mover:
    Bellman: |
      V = max_d{V_own[>], V_rent[>]}

  dcsn_to_arvl_mover:
    Bellman: |
      V[<] = E_{y}(V)

Branching stage operator: \((\mathbb{B}\,(\mathrm{v}_{\succ,\text{own}}, \mathrm{v}_{\succ,\text{rent}}))(a,H,y) = \max\bigl\{\mathrm{v}_{\succ,\text{own}}(a,H,y),\;\mathrm{v}_{\succ,\text{rent}}\bigl((1\!+\!r)a+H,\,y\bigr)\bigr\}\); \(\mathbb{I}\,\mathrm{v} = \mathbb{E}_y[\mathrm{v}]\).

The tenure choice stage is branching because own and rent paths have different state spaces (\(\mathsf X_{\succ,\text{own}} = \mathbb{R}_+ \times \mathcal{H} \times \mathcal{Y}\) vs \(\mathsf X_{\succ,\text{rent}} = \mathbb{R}_+ \times \mathcal{Y}\)). Contrast with the downstream OwnerHousingChoice stage, which has a within-stage discrete choice over \(H' \in \mathcal{H}\) (homogeneous set, same state space for all choices) — that uses max_{c}{}, not branching.

5. Parameters vs Settings

Category Level Defines Examples
Parameters Υ (math) The mathematical problem \(\beta\), \(\rho\), \(R\), \(\mu_{\theta}\), \(\sigma_{\theta}\), grid bounds for discrete spaces
Settings ρ (code) Numerical/solver configuration n_m, n_a (grid sizes), tolerances, max iterations

Key principle: Changing a parameter changes the mathematical problem. Changing a setting changes only the numerical approximation.

6. ASCII Diagram Conventions

     ┌─────── S₀ ────────┐               ┌─────── S₁ ────────┐
           g≺○       g○≻                        g≺○       g○≻
     ≺₀  ───→  ○₀  ───→  ≻₀  ══shared══  ≺₁  ───→  ○₁  ───→  ≻₁
         ←┄┄┄      ←┄┄┄                       ←┄┄┄      ←┄┄┄
           𝕀         𝔹                           𝕀         𝔹

Solid arrows: forward transitions (\(\mathrm{g}_{\prec\sim}\), \(\mathrm{g}_{\sim\succ}\)). Dashed arrows: backward movers (\(\mathbb{I}\), \(\mathbb{B}\)). Double line (══shared══): the continuation space of \(S_0\) coincides with the arrival space of \(S_1\) (shared boundary perch).

Branching stage diagram

                              ┌── g○≻_own ──→  ≻_own  ══→  S_own  ──→ ...
     ┌───── S_branch ────┐   │
           g≺○       ○   ────┤  (max or Σpⱼ)
     ≺   ───→  ○   ────┐    │
         ←┄┄┄      ←┄┄┄     └── g○≻_rent ──→  ≻_rent ══→  S_rent ──→ ...
           𝕀       𝔹(multi)

Fan-out from the decision perch: each branch \(j\) has its own transition \(\mathrm{g}_{\sim\succ,j}\), continuation perch \(\succ_j\), and downstream stages. The backward mover \(\mathbb{B}\) receives values from all branches and aggregates (max for discrete choice, \(\sum p_j\) for stochastic).


Hardwired Symbols (Pre-defined in DDSL/Dolo+)

See Dolo+ Primitives for the full reference of built-in domains, distributions, stochastic processes, mathematical functions, operations, grid discretization methods, and reserved keywords.