Model Structure¶
The Dolo Model Object¶
The Model class (dolo/compiler/model.py) is the central data structure in dolo. It contains everything about your economic model.
Core Components¶
1. Symbols (model.symbols)¶
A dictionary categorizing all variables in your model:
model.symbols = {
'exogenous': ['y'], # Exogenous shocks
'states': ['w'], # State variables
'controls': ['c'], # Choice/control variables
'expectations': ['mr'], # Expectation variables
'poststates': ['a'], # Post-decision states
'parameters': ['β', 'γ', 'σ', 'ρ', 'r'] # Fixed parameters
}
Key Points:
- Each category can have multiple variables: states: [k, h, z]
- Order matters - it determines array indexing
- Parameters are treated separately from dynamic variables
2. Equations (model.equations)¶
Dictionary of equation blocks from your YAML:
model.equations = {
'transition': 'w[t] = exp(y[t]) + (w[t-1]-c[t-1])*r',
'arbitrage': 'β*(c[t+1]/c[t])^(-γ)*r - 1',
'auxiliary_direct_egm': 'a[t] = w[t] - c[t]',
# ... more equation blocks
}
Types of Equations:
- transition - State evolution
- arbitrage - Optimality conditions (Euler equations)
- expectation - Computing expectations
- auxiliary_* - Helper equations for solution methods
- Custom blocks for specific algorithms
3. Calibration (model.calibration)¶
Parameter values and initial conditions:
model.calibration = CalibrationDict({
# Parameters
'β': 0.96,
'γ': 4.0,
'σ': 0.1,
'ρ': 0.0,
'r': 1.0,
# Initial values for variables
'w': 1.0,
'c': 0.9,
# ...
})
Access Methods:
# Get flat dictionary
params = model.calibration.flat
# Access individual values
beta = model.calibration['β']
# Iterate
for param_name in model.calibration:
value = model.calibration[param_name]
4. Functions (model.functions)¶
Compiled, vectorized versions of equations:
model.functions = LoosyDict({
'transition': <standard_function>,
'arbitrage': <standard_function>,
'expectation': <standard_function>,
# ... one for each equation block
})
Properties of Functions:
- Type: dolang.vectorize.standard_function
- Wraps numpy ufuncs for vectorization
- Callable with array inputs
- Support automatic differentiation
5. Domain (model.domain)¶
State space bounds and constraints:
6. Exogenous Process (model.exogenous)¶
Stochastic process specification:
model.exogenous = UNormal(sigma=0.1) # IID normal shocks
# or
model.exogenous = VAR1(...) # AR(1) process
# or
model.exogenous = MarkovChain(...) # Discrete Markov chain
7. Options (model.options)¶
Solver and grid specifications:
model.options = {
'grid': Cartesian(
orders=[100], # Grid points
bounds=[[0.0, 4.0]] # Grid bounds
)
}
Model Class Hierarchy¶
Model (main class)
├── SymbolicModel (handles symbolic expressions)
│ ├── symbols
│ ├── equations
│ └── definitions
└── NumericModel (handles numeric operations)
├── calibration
├── functions (compiled)
├── domain
└── exogenous
Key Methods¶
Property Methods (Lazy Evaluation)¶
@property
def functions(self):
if self.__functions__ is None:
self.__compile_functions__()
return self.__functions__
Functions are compiled on first access, not at model creation.
Compilation Methods¶
def __compile_functions__(self):
# 1. Get all equation names
funnames = [*self.equations.keys()]
# 2. For each equation, create compiled function
for funname in funnames:
factory = get_factory(self, funname)
fun, gufun = make_method_from_factory(factory)
functions[funname] = standard_function(gufun, n_output)
Internal Storage¶
The Model uses several private attributes for caching:
self.__functions__ = None # Compiled functions (lazy)
self.__symbols__ = None # Symbol dictionary (lazy)
self.__equations__ = None # Parsed equations (lazy)
self.__calibration__ = None # Calibration dict (lazy)
These are populated on first access to avoid unnecessary computation.
Data Flow¶
YAML Data (self.data)
↓
Symbol Extraction (self.symbols)
↓
Equation Parsing (self.equations)
↓
Function Compilation (self.functions)
↓
Ready for Numerical Methods
Special Features¶
LoosyDict¶
Custom dictionary with equivalence mappings:
functions = LoosyDict(equivalences={'equilibrium': 'arbitrage'})
# Can access functions['equilibrium'] or functions['arbitrage']
CalibrationDict¶
Special dictionary for parameters that: - Handles symbolic expressions - Provides flat access - Supports dependencies between parameters