Skip to content

1.3 Equations and operators

This section covers the equations: blocks in a Dolo+ stage: how to write transitions and movers, what they mean at a high level, and a few concrete YAML patterns.

Main goal: keep stage YAML close to the economic model (fields + timing + equations). Translation to T core builds the corresponding typed operators; methodization decides how to compute them.

1.3.1 Main ideas

In v0.1, equation blocks come in two families:

  • Transitions (forward equations): define how perch-local state fields are produced as information arrives and decisions are applied.
  • Movers (backward equations): define how value objects (and optionally shadow/marginal objects and policies) move backward across perches.

Most stages have the following four blocks:

  • arvl_to_dcsn_transition (arrival → decision)
  • dcsn_to_cntn_transition (decision → continuation)
  • cntn_to_dcsn_mover (continuation → decision)
  • dcsn_to_arvl_mover (decision → arrival)

Equation payloads are Dolang+ expressions. Perch tags ([<], unmarked, [>]) are measurability/evaluation assertions (see Spec 1.2); they are not global time subscripts.

Expectation location (keep it readable)

Put E_shock(·) in the mover that crosses the shock edge you are integrating out.

In the common case “a shock is realized between arrival and decision”, expectation belongs in dcsn_to_arvl_mover: V[<] = E_y(V).

1.3.2 Equation-block shapes (syntax rules) #syntax-rules

Under equations:, each entry is either:

  • a string payload (block scalar) — typical for transitions, or
  • a single-level mapping — typical for movers (to hold multiple named sub-equations like Bellman, InvEuler, ...).

1.3.2.1 Sub-equations (within movers)

A mover may include multiple named sub-equations as keys mapping to string payloads, e.g.:

  • Bellman: | ...
  • ShadowBellman: | ...
  • InvEuler: | ... (method-specific, e.g. EGM)

These labels are primarily for readability and for attaching methodization/implementation choices later.

1.3.2.2 Movers are “equations-only” (v0.1l direction)

We avoid structured mover metadata keys (e.g. sources, aggregation, weights) and instead express branching logic directly in equation payloads.

Structural invariant (v0.1): under a mover, entries are only named sub-equations mapping to string payloads (Bellman, ShadowBellman, InvEuler, …). Branching is expressed by:

  • referencing a branch-indexed continuation-value family (e.g. V_cntn[own], V_cntn[rent]), and
  • combining those terms using max_d{…} or an explicit weighted sum.

Labels vs canonical symbols

The YAML key names are human-facing. Translation to T core consumes canonical operator symbols (derived by the compiler/translator). As an author, you should normally stick to the standard keys above.

1.3.3 Transitions (forward equations)

1.3.3.1 Arrival → decision: arvl_to_dcsn_transition

Use arvl_to_dcsn_transition to define decision-perch fields from arrival-perch fields plus any shocks that become observed at the decision perch. Typical patterns:

  • copy/rename fields: w = w[<]
  • incorporate a realized shock: y = y_shock

1.3.3.2 Decision → continuation: dcsn_to_cntn_transition

Use dcsn_to_cntn_transition to define continuation/poststate fields (tagged [>]) from decision-perch fields and controls.

Branching stages generalize this to “one transition per continuation branch”. Canonical v0.1l spelling keeps the key dcsn_to_cntn_transition, but allows it to become a branch-keyed mapping:

equations:
  dcsn_to_cntn_transition:
    own: |
      # ... produce `own`-branch poststates (tagged `[>]`)
    rent: |
      # ... produce `rent`-branch poststates (tagged `[>]`)

For a smooth transition, legacy spellings like dcsn_to_cntn_{label}_transition remain acceptable as a desugaring target.

1.3.3.3 Optional inverse transition: cntn_to_dcsn_transition (method/representation)

Some solution methods (notably EGM-style representations) use a continuation-grid representation for certain objects. In those cases it can be useful to provide a “reverse state” mapping cntn_to_dcsn_transition. This is a representation convenience; it does not introduce a new perch.

1.3.4 Movers (backward equations)

1.3.4.1 cntn_to_dcsn_mover (optimization / envelope / method-specific steps)

cntn_to_dcsn_mover is where you typically write:

  • the optimization step (max_c{...}, max_d{...}, …),
  • any method-specific constructions (e.g. InvEuler for EGM),
  • shadow/marginal relationships (ShadowBellman).

1.3.4.2 dcsn_to_arvl_mover (expectation location)

dcsn_to_arvl_mover is where you typically locate explicit expectations over shocks observed between arrival and decision:

  • V[<] = E_y(V)
  • dV[<] = r * E_y(dV)

1.3.4.3 Branching movers (equation-only surface syntax)

In a branching stage, the cntn_to_dcsn_mover is still “just equations”. You write the branch combination directly:

equations:
  cntn_to_dcsn_mover:
    Bellman: |
      V = max_d{V_cntn[own], V_cntn[rent]}

For endogenous probabilities (e.g. logit/softmax taste shocks), keep the syntax thin:

  • declare a probability vector field p (recommended: under values:; it is derived, not chosen),
  • compute it inside the mover equations (e.g. p = softmax(...)),
  • then use p as coefficients in a weighted sum.

The domain syntax for probability vectors (e.g. @in simplex(K)) is still being pinned down. #todo

1.3.5 Concrete YAML excerpts

1.3.5.1 Expectation location (shock between arrival and decision)

equations:
  arvl_to_dcsn_transition: |
    y = y_shock
    w = exp(y) + b[<] * r

  dcsn_to_cntn_transition: |
    a[>] = w - c

  cntn_to_dcsn_mover:
    Bellman: |
      V = max_c{u(c) + β*V[>]}

  dcsn_to_arvl_mover:
    Bellman: |
      V[<] = E_y(V)

Interpretation:

  • V (unmarked) is a decision-perch object: “post-shock / conditional on what is known at decision time”.
  • V[<] is an arrival-perch object: “pre-shock / integrated over y”.

1.3.5.2 Multi sub-equation mover (EGM-style pattern)

equations:
  cntn_to_dcsn_mover:
    Bellman: |
      V = max_c{u(c) + β*V[>]}
    InvEuler: |
      c[>] = (β*dV[>])^(-1/γ)
    ShadowBellman: |
      dV = (c)^(-γ)

1.3.5.3 Endogenous branch probabilities (thin branching pattern)

equations:
  cntn_to_dcsn_mover:
    Bellman: |
      p = softmax(V_cntn[pi1], V_cntn[pi2], V_cntn[pi3]; sigma_pi)
      V = p(1)*V_cntn[pi1] + p(2)*V_cntn[pi2] + p(3)*V_cntn[pi3]