Skip to content

DDSL YAML schema (v0.1)

This page is a shape specification for the YAML objects used to author DDSL v0.1 models in this repo. It is intentionally “schema-like” (types, required keys, invariants), but is not yet a machine-validated JSON Schema.

The guiding architecture is layered (see the dolo-plus syntax guide and Stages/Calibration foundations):

  • Stage: atomic ADC module (perches: arrival/decision/continuation) representing a Bellman equation operator for a generalized Markov decision process.
  • Period: ordered composition of stages + optional connectors (intra-period renames).
  • Nest (lifecycle): ordered composition of periods + twisters (inter-period adapters).

Where applicable, this matches the v0.1 syntax/semantic rules in:

0. Isomorphic mappings

The DDSL architecture maintains two fully isomorphic mappings between three layers. For the core ideas motivating these mappings — information sets within stages, forward–backward duality, and the graph/category view of stage composition — see the project overview.

YAML Syntax  ──Υ──▶  Mathematical Model  ──ρ──▶  Executatable Representation
  (dolo-plus)            (Bellman operators)         (Python/Julia)

Υ: YAML syntax → Mathematical model

The stage YAML (symbols + equations) defines the mathematical model. Parameters and equations are part of the economic problem; settings and methodization are not.

YAML (dolo-plus) Mathematical object
symbols.spaces with @def R+ Measurable space \((X, \Sigma)\)
symbols.spaces with @def linspace(...) Finite discrete space \(\{x_1, \ldots, x_n\}\)
symbols.prestate Arrival state space \(X_{\prec}\)
symbols.states Decision state space \(X\)
symbols.poststates Continuation state space \(X_{\succ}\)
symbols.controls Control set \(C\)
symbols.exogenous with @dist Probability kernel \(P(\cdot \mid \cdot)\)
symbols.values Value function \(V : X \to \mathbb{R}\)
symbols.values_marginal Marginal value \(\partial_x V : X \to \mathbb{R}_+\) (one per state variable via d_{x}V)
symbols.parameters Problem constants \(\theta \in \Theta\)
arvl_to_dcsn_transition Transition kernel \(\mathrm{g}_{\prec\sim} : X_{\prec} \times W \to X\)
dcsn_to_cntn_transition Transition kernel \(\mathrm{g}_{\sim\succ} : X \times C \to X_{\succ}\)
cntn_to_dcsn_mover Backward operator \(\mathbb{B} : \mathcal{V}(X_{\succ}) \to \mathcal{V}(X)\)
dcsn_to_arvl_mover Backward operator \(\mathbb{I} : \mathcal{V}(X) \to \mathcal{V}(X_{\prec})\)
Stage (full YAML) ADC Bellman operator \(\mathbb{T} = \mathbb{I} \circ \mathbb{B}\)
Period (stages + connectors) Composed operator \(\mathcal{T}_{\mathrm{per}} = \mathcal{T}_{s_1} \circ \varphi \circ \mathcal{T}_{s_2}\)
Connector rename: Field isomorphism \(\varphi : X_{\succ}^{(s_1)} \xrightarrow{\sim} X_{\prec}^{(s_2)}\)
Nest (periods + twisters) Lifecycle operator \(\mathcal{T}_{\mathrm{nest}} = \mathcal{T}_{p_1} \circ \psi_1 \circ \mathcal{T}_{p_2} \circ \cdots\)
Twister rename: Field isomorphism \(\psi : X_{\succ}^{(p_i)} \xrightarrow{\sim} X_{\prec}^{(p_{i+1})}\)

Note: symbols.settings and methodization YAML are not part of Υ — they carry no mathematical content. Settings are numerical configuration; methodization selects solver schemes.

ρ: Mathematical model → Executable code

The ρ mapping translates mathematical objects into computational representations. This is where methodization and settings enter: they determine how each mathematical object is discretized and solved.

Mathematical object Code object Determined by
Measurable space \((X, \Sigma)\) Grid object (Cartesian, adaptive) Settings (n_a, a_min, a_max)
Finite discrete space \(\{x_1, \ldots, x_n\}\) Array / enumeration Parameters (n_H, H_min, H_max)
Value function \(V\) Interpolated array V[grid] Grid specification
Marginal value \(\partial V\) Interpolated array dV[grid] Grid specification
Probability kernel \(P\) Quadrature nodes + weights Methodization (!gauss-hermite, etc.)
Transition kernel \(g\) Callable function Direct translation
Backward operator \(\mathcal{B}\) Operator class with __call__ Methodization (!egm, !vfi, etc.)
Forward operator \(\mathcal{F}\) Simulation function Methodization (!monte-carlo, etc.)
Composed operator \(\mathcal{T}_{\mathrm{per}}\) Sequential pipeline Period structure
Field isomorphism \(\varphi\) Array reindex / rename map Connector/twister rename:

Design principle: The separation between Υ and ρ enforces a clean boundary. The mathematical model (stage symbols + equations + parameters) is solver-agnostic: the same model can be solved by VFI, EGM, or any other scheme without changing the stage YAML. Methodization and settings live entirely in ρ.

Discrete vs. continuous grids: When a space is defined by a constructor (e.g. @def linspace(H_min, H_max, n_H)), the constructor arguments are parameters — they define the mathematical model and belong to Υ. When a grid approximates a continuous space, the grid size is a setting — it is numerical configuration and belongs to ρ.

Equality only in the limit: The numerical object under ρ is an approximation of the mathematical object under Υ. Under appropriate assumptions: \(\lim_{n \to \infty} \rho(\mathcal{M}(\mathbb{S}), \mathbb{C}_n) = \Upsilon(\mathbb{S}, \mathbb{C}_{\text{param}})\). (See Representation Maps §6.5.)

1. Common atoms (used throughout)

1.1 Symbols

Identifiers may be ASCII or Unicode (e.g. β, μ_θ, n_m). In DDSL, the same syntax of “a name” is used for multiple kinds of objects, and it’s important not to conflate them.

  • Field variables (economic fields): names declared under symbols.prestate, symbols.states, symbols.poststates, symbols.controls, symbols.exogenous (and the reserved value slots in symbols.values / symbols.values_marginal). These denote random-variable / measurable-function objects that represent economic quantities defined on an information set (filtration). Fields are fixed mathematical objects in \(L^2(\Omega)\)—not placeholders—and composition is defined through field isomorphism, not string equality.
  • Parameters (problem constants): names declared under symbols.parameters. These are deterministic constants of the economic problem (not interface fields). They do not participate in stage/period/nest wiring.
  • Settings (numerical configuration): names declared under symbols.settings. These are configuration symbols (grid sizes, bounds, tolerances, simulation counts), not interface fields. They are consumed by methodization and builder/orchestration code.
  • Spaces (domain names): names declared under symbols.spaces via @def. These are type-level objects used only for typing. When a space is defined by a constructor (e.g. linspace(...)), its arguments are parameters of the mathematical model.

1.2 The _{.} operator convention

When _{...} (underscore followed by braces) appears after an operator name, it specifies with respect to what the operator acts. This is the surface-syntax analogue of Mathematica's positional Derivative[1,0] — but uses named variables instead of slot indices.

Pattern Meaning Mathematical
d_{a}V Partial derivative of \(V\) wrt \(a\) \(\partial_a \mathrm{v}\)
E_{θ}(V) Expectation wrt \(\theta\) \(\mathbb{E}_\theta[\mathrm{v}]\)
max_{c}{...} Maximise over \(c\) \(\sup_c\{\cdots\}\)

Disambiguation from plain underscore: _{...} (with braces) is always "with respect to." Plain underscore without braces is always a name separator (e.g. m_d = "the variable named m-d", V_own = "the value function named V-own"). The two are structurally distinct and cannot be confused.

The variable inside _{...} must be a declared symbol (state, control, or exogenous). For multi-state stages requiring separate marginals, declare one values_marginal entry per (variable, perch) pair: d_{a}V[<], d_{h}V[<], etc.

Open design question: d_{a}V — declared symbol or canonical operator?

Is d_{a}V[<] a declared symbol (user writes it in values_marginal:, naming convention only) or a canonical operator application (the system computes \(\partial_a V_{<}\) automatically from V[<])? Under the symbol view, d_a_V could also name the same object (plain underscore). Under the operator view, d_{a} is a first-class operator and the marginal need not be declared. Current v0.1: declared symbol (interpretation 1). See symbols-conventions.md for details. #ambiguity #operator-vs-symbol #todo

1.3 Domain/typing strings and space constructors

Declarations are typing judgments, encoded as strings (see Symbols & declarations):

  • "@def <SpaceExpr>" declares a space (domain object), e.g. Xm: "@def R++".
  • A space may also be defined by a constructor call, e.g. XH: "@def linspace(H_min, H_max, n_H)" — here the constructor arguments (H_min, H_max, n_H) must be declared as parameters (not settings), since they define the mathematical model.
  • "@in <SpaceExpr-or-SpaceName>" declares the type of a symbol; the symbol's kind is determined by where it is declared:
  • m: "@in Xm" under symbols.prestate declares a field variable
  • β: "@in (0,1)" under symbols.parameters declares a parameter
  • n_m: "@in Z+" under symbols.settings declares a setting

Important: stage files declare types of parameters/settings; numeric values live in calibration/config inputs, not in the stage file.

1.4 Perches (information timing)

Perch tags are the surface syntax for agent problems at information timing / information sets: a symbol tagged [_p] asserts measurability w.r.t. the perch filtration (what is known at that perch). See Perch Annotations and Spec 1.2: Stage structure and timing. A canonical Bellman operator has three perches:

  • [<] arrival (canonical slot \(-1\)); perch associated with information set before any information is revealed and before any actions. Aliases: [_arvl], [<-].
  • unmarked decision (canonical slot \(0\)); perch associated with information set observed by the agent and before any actions. Aliases: [_dcsn], [-].
  • [>] continuation (canonical slot \(+1\)); perch associated with information set after all information revealed and agent decisions made. Aliases: [_cntn], [->].

2. Stage object schema (adc-stage, v0.1)

A stage is a closed declaration environment: every symbol referenced in equations: must be declared under symbols: (or be a reserved perch slot like V[>]).

Open question: What happens to undeclared symbols — are they treated as string placeholders? How are new functions declared? #ambiguity #variable-declarations

2.1 Transition kernels

State variables are functions (fields) measurable w.r.t. the information set at a given perch. The transition from one perch to the next is given by measurable functions that enforce this information structure — the transition kernels arvl_to_dcsn_transition and dcsn_to_cntn_transition are measurable maps between perches. They must respect perch measurability: objects at the decision perch can depend only on information available at that perch, etc. (See Perch Annotations and Spec 1.2.)

2.2 Backward operators

The mover blocks (cntn_to_dcsn_mover, dcsn_to_arvl_mover) are backward Bellman operators: they transform continuation objects \(V[>]\) (and optionally \(dV[>]\)) into earlier-perch value objects via expectation and/or optimization (e.g. E_{θ}(·), max_{c}(·), argmax_{c}(·)). These operator instances are the primary targets of methodization.

Identity transitions (often elidable)

Many stages contain structural identity maps:

  • Within-stage identities: e.g. an arrival→decision identity state (k_d = k) or an identity arrival mover (V[<] = V). These are usually written explicitly for clarity, but they are not semantically informative beyond asserting identity.
  • Within-period identities: when stage interfaces already match, the connector is identity and should be omitted (no connectors: entry).
  • Between-period identities: an identity twister can be written as {} / empty rename.

See §1.2.4 Identity connectors/transitions for the omission convention.

This is the “atomic block” used by the period/nest layer.

# stage.yaml  (DDSL-SYM, adc-stage dialect)
name: <string>                      # required (library-unique identifier)

symbols:                            # required (closed environment)
  spaces:                           # required
    <SpaceName>: "@def <SpaceExpr>"   # e.g. R+, R++, Z+, linspace(...)

  # ──────────────────────────────────────────────────────────────────────────
  # Interface groups (these determine composition)
  # ──────────────────────────────────────────────────────────────────────────
  prestate:                         # required (arrival interface)
    <var>: "@in <SpaceExpr-or-SpaceName>"

  states:                           # required (decision interface; may be empty)
    <var>: "@in <SpaceExpr-or-SpaceName>"

  poststates:                       # required (continuation interface)
    <var>: "@in <SpaceExpr-or-SpaceName>"

  controls:                         # required (may be empty)
    <control>: "@in <SpaceExpr-or-SpaceName>"

  exogenous:                        # optional (shocks)
    <shock>:
      - "@in <SpaceExpr-or-SpaceName>"
      - "@dist <DistExpr>"          # e.g. "@dist LogNormal(μ_θ, σ_θ)"

  # ──────────────────────────────────────────────────────────────────────────
  # Underlying value slots (present in every stage)
  # ──────────────────────────────────────────────────────────────────────────
  values:                           # required
    V[<]: "@in R"
    V: "@in R"
    V[>]: "@in R"

  values_marginal:                  # optional (needed for envelope/EGM)
    # Single-state stages (wrt variable omitted — unambiguous):
    dV[<]: "@in R+"
    dV: "@in R+"
    dV[>]: "@in R+"

    # Multi-state stages (one entry per state variable, using _{.} convention):
    # 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

    # Branching stages: continuation marginals use branch-specific
    # poststate variable names. No branch sub-keys needed — the
    # poststate names are already branch-namespaced.
    #
    # Example (housing keep/adjust):
    #   d_{w_keep}V[>]: "@in R"   # ∂v/∂w_keep (keep branch)
    #   d_{h_keep}V[>]: "@in R"   # ∂v/∂h_keep (keep branch)
    #   d_{w_adj}V[>]: "@in R"    # ∂v/∂w_adj (adjust branch)
    #
    # This is syntactic sugar. Formally, each branch has its own
    # continuation value function (v_{succ,keep}, v_{succ,adjust}).
    # The desugaring rule:
    #
    #   d_{x}V[>]  →  ∂_x v_{succ,j}   where j is the branch
    #                                    in whose poststates x is declared.
    #
    # The branch is inferred from the wrt-variable's declaration
    # scope — possible because poststate names are disjoint across
    # branches (no overloading rule).

  functions:                        # optional (user-defined functions)
    # Arrow syntax: 'args -> body'
    # Arguments before -> are formal parameters; body after -> is
    # the expression. The compiler substitutes at the call site.
    #
    # Single argument:
    #   u_c: 'c -> alpha * c^(1 - gamma_c) / (1 - gamma_c)'
    #   y: 'z -> w_0 + w_1 * z'
    #
    # Multiple arguments:
    #   f: 'x, y -> x^2 + y^2'
    #
    # Usage in equations:
    #   V = max_{c}(u_c(c) + u_h(h) + beta * V[>])
    #
    # All non-argument symbols in the body (alpha, gamma_c, etc.)
    # must be declared parameters.

  parameters:                       # optional (type declarations only)
    <param>: "@in <SpaceExpr>"

  settings:                         # optional (type declarations only)
    <setting>: "@in <SpaceExpr>"

equations:                          # required
  # Stage kernels (pure functions)
  arvl_to_dcsn_transition: |         # required in v0.1 ADC
    <equations...>

  dcsn_to_cntn_transition: |
    <equations...>

  # Backward movers (operators on V, dV; may have sub-equations)
  cntn_to_dcsn_mover:                # required
    <SubEqName>: |
      <equations...>
    # common sub-equation names in v0.1:
    # - Bellman
    # - InvEuler
    # - MarginalBellman / ShadowBellman
    # - cntn_to_dcsn_transition   (reverse-state for EGM, etc.)

  dcsn_to_arvl_mover:                # required
    <SubEqName>: |
      <equations...>

dolo_plus:                           # optional (metadata for tooling)
  dialect: adc-stage
  version: "0.1"

  equation_symbols:                  # canonical math names for translator
    arvl_to_dcsn_transition: g_ad
    dcsn_to_cntn_transition: g_de
    cntn_to_dcsn_mover: T_ed
    dcsn_to_arvl_mover: T_da

  slot_map:                          # prestate → poststate linkage
    prestate: <var>
    poststate: <var>

  validation:                        # perch index aliases
    index_aliases:
      _arvl: -1
      _dcsn: 0
      _cntn: 1

Invariants (stage)

  • No free names: every symbol referenced in equations: is declared in symbols: (or is a reserved perch slot like V[>]).
  • Composition interface: symbols.prestate and symbols.poststates determine the stage's arrival/continuation interfaces \(X_{\prec}, X_{\succ}\).
  • Separation of concerns: method choices and numeric values are not specified here (see methodization + calibration below).

3. Calibration file schema (values)

Calibration binds numbers to declared parameters/settings (see Spec 0.1c).

# calibration.yaml
parameters:
  <param>: <number | list | array-like>

settings:
  <setting>: <number | list | array-like>

Constraints:

  • Keys must be declared in stage.yaml under symbols.parameters / symbols.settings.
  • This file contains values only (no @in / @def typing strings).

4. Methodization file schema (methods)

Methodization attaches schemes/methods to operator instances and mover blocks (see Spec 0.1d).

This is the shape used by the *_stage_methods.yml files in the repo.

# *_methods.yml
stage: <stage-name>                  # OR: library: <library-name>

methods:
  - on: <target-id>                  # e.g. cntn_to_dcsn_mover, cntn_to_dcsn_mover.InvEuler, E_θ
    schemes:
      - scheme: <scheme-id>          # e.g. bellman_backward, expectation, interpolation
        method: !<method-tag>        # e.g. !egm, !gauss-hermite, !Cartesian
        description: <string?>       # optional
        settings:                    # optional: names of settings (resolved by calibration)
          <setting-key>: <setting-symbol>

Notes:

  • Targets may refer to operator instances (E_θ) or mover blocks (cntn_to_dcsn_mover) or sub-equations (cntn_to_dcsn_mover.InvEuler).
  • Settings values are not written here—only symbolic references to settings declared in the stage file and valued in calibration.

5. Period template schema (composition of stages)

A period is an ordered list of stage occurrences plus optional rename connectors for mismatched interfaces (see Spec 0.4 — Periods and models).

Key principle: A period defines composition through interface-compatibility. When stage interfaces match (same field names), composition is implicit. When names differ, an explicit connector provides the rename.

5.1 Simple form (library references)

When stages are defined in a shared library, periods can reference them by name:

# period.yaml (simple form)
name: <string>

stages:                              # required (ordered list of stage names)
  - <stage-name-1>
  - <stage-name-2>

connectors:                          # optional; omit if identity
  - from: <stage-name-1>
    to: <stage-name-2>
    rename: {<out-name>: <in-name>}

5.2 Embedded form (inline stage objects)

Alternatively, stages can be embedded directly as objects:

# period.yaml (embedded form)
name: <string>
description: <string?>               # optional

stages:                              # required (ordered)
  - <occurrence-name-1>: <stage-object-or-include>
  - <occurrence-name-2>: <stage-object-or-include>
  # Each entry is a stage object (inline, anchor, or !include).

connectors:                          # optional; omit if identity
  - from: <occurrence-name-1>
    to: <occurrence-name-2>
    rename: {<out-name>: <in-name>}  # wiring-only adapter (typically a bijective rename)

Constraints

  • If adjacent stage interfaces already match, the connector is identity and should be omitted.
  • Connectors are intra-period wiring only; inter-period wiring is handled by twisters at the nest layer.
  • The period namespace is a set of economic fields (random variables), not merely string labels. Composition is valid when fields match (not just when names coincide).

6. Nest (lifecycle) template schema (composition of periods)

A nest is an ordered list of period objects and a position-aligned list of twisters (see Spec 0.1h).

# nest.yaml
name: <string>
description: <string?>               # optional

periods:                             # required (ordered; contain full period objects)
  - <period-object>
  - <period-object>
  - <period-object>

twisters:                            # optional but typical; length = len(periods)-1
  - rename: {<field>: <field>}       # connects periods[0] → periods[1] (forward time)
  - {}                               # identity twister may be `{}` (or omit rename)

terminal:                            # optional (builder-level boundary condition)
  # How to provide V[>] / dV[>] at the terminal boundary.
  # Commonly provided by the orchestrator, not by syntax.
  kind: <string>
  # ...

Constraints:

  • Time indices do not appear inside stages or periods: “time” lives only in nest position (and the orchestration loop).
  • In v0.1h convention, twisters[i] connects periods[i] → periods[i+1] in forward time (alignment by list position).

7. Single-file recursive “blocks” form (matches the sketch)

If you prefer a single YAML file that is recursively nested “blocks with links”, the same semantics can be written as syntax sugar.

---
kind: nest                            # enum: stage | period | nest
name: <string>
description: <string?>

blocks:                               # periods
  - kind: period
    name: <string?>
    description: <string?>
    blocks:                           # stages
      - kind: stage
        # (insert the stage schema from §2 here)
    links:
      connectors: []                  # same shape as §5 connectors

links:
  twisters: []                        # same shape as §6 twisters

calibration: {}                       # optional global overrides (builder-defined)
options: {}                           # optional solver/builder hints
---

This form is not a new semantic layer: it is just a convenient way to serialize the canonical stage → period → nest structure in one place.

8. Normalized "lifecycle block" schema (CORE-ish)

The canonical v0.1 authoring objects in this repo are stage / period / nest (above). If you want a single recursive block schema shaped like:

  • states: [...], controls: [...], distributions: [...], parameters: [...]
  • equations: {objective, transitions, definitions}
  • recursive blocks: plus links: {block, lifecycle, terminal}

you can treat it as a normalized (CORE-ish) representation that projects to the v0.1 shapes as follows:

  • states: union of dolo-plus symbol groups prestate, states, poststates (use role to distinguish).
  • controls: dolo-plus symbols.controls (decision-perch objects).
  • distributions: dolo-plus symbols.exogenous (domain + @dist …).
  • equations.transitions: dolo-plus equations.arvl_to_dcsn_transition and equations.dcsn_to_cntn_transition.
  • equations.objective: typically a mover sub-equation, e.g. equations.cntn_to_dcsn_mover.Bellman.
  • links.block: period-level connectors (intra-period rename adapters).
  • links.lifecycle: nest-level twisters (inter-period adapters).

Note: this normalized schema is useful for documentation and for builder-layer IRs, but v0.1 parsing/compilation in this repo expects the concrete stage/period/nest shapes in §§2–6.

---
# ─────────────────────────────────────────────────────────────────────────────
# DDSL “Block” (recursive) — normalized authoring schema (documentation/IR)
# ─────────────────────────────────────────────────────────────────────────────
kind: <stage | period | nest>         # required
name: <string>                       # required
description: <string?>               # optional

# Declarations (types only; values live in calibration)
states:                              # stage-level; optional at period/nest
  - name: <string>
    role: <prestate | state | poststate>
    perch: <"<" | (unmarked) | ">"?>   # optional if role implies perch
    description: <string?>
    domain: "@in <SpaceExpr-or-SpaceName>"

controls:                            # stage-level
  - name: <string>
    perch: (unmarked)
    description: <string?>
    domain: "@in <SpaceExpr-or-SpaceName>"

distributions:                       # stage-level (exogenous)
  - name: <string>
    description: <string?>
    domain: "@in <SpaceExpr-or-SpaceName>"
    distribution:
      type: <string>                 # e.g. LogNormal
      args: {<param>: <param>, ...}  # symbolic parameter names

parameters:
  - name: <string>
    description: <string?>
    domain: "@in <SpaceExpr>"
    default: <number?>               # optional; treated as a calibration default if used

settings:
  - name: <string>
    description: <string?>
    domain: "@in <SpaceExpr>"
    default: <number?>

equations:                           # stage-level; period/nest usually omit
  objective: |                       # optional; often lives inside mover sub-equations
    <equations...>

  transitions:                       # optional (often corresponds to g_ad / g_de)
    - name: arvl_to_dcsn_transition
      equation: |
        <equations...>
    - name: dcsn_to_cntn_transition
      equation: |
        <equations...>

  definitions:                       # optional
    - name: <definition-id>
      equation: |
        <equations...>

  movers:                            # optional (Bellman operators)
    - name: cntn_to_dcsn_mover
      subequations:
        Bellman: |
          <equations...>
        # InvEuler / MarginalBellman / etc.

# Recursive composition (nest contains periods; period contains stages)
blocks:                              # optional; recursion permitted
  - <Block>

links:                               # optional; wiring-only (no economics)
  block:                             # intra-period connectors (stage → stage)
    - from: <string>
      to: <string>
      rename: {<out-name>: <in-name>}

  lifecycle:                         # inter-period twisters (period → period)
    - rename: {<field>: <field>}

  terminal:                          # terminal boundary condition (builder-defined)
    kind: <string>
    # ...

# Numeric bindings (values), typically loaded from separate files
calibration:
  parameters: {<param>: <value>, ...}
  settings: {<setting>: <value>, ...}

options: {}                          # solver/builder hints (representation-layer)
---