2.4. Deriving models with rise.microfound
2.4.1. Write the economics, not the algebra
rise.microfound lets you author a DSGE model the way you would write it in a
paper: declare the atoms and their roles, state each agent’s optimization problem
(period objective, choice variables, named constraints), and RISE derives the
first-order conditions symbolically and generates a plain RISE model. It does
not own or augment a model object – its output is ordinary model code you can
read, solve, and edit. Calibration and solving remain the responsibility of
dsge_model.
The builder is a MATLAB handle object with a fluent (chained) interface. It is a
model definition tool only: it never takes parameter values and has no
solve method.
2.4.2. A first example: the RBC model
p = rise.microfound("RBC");
p.endogenous("c","n","k","w","r","Y","A");
p.exogenous("eps");
p.parameter("beta","delta","psi","eta","alpha","rho");
p.agent("household", discount="beta") ...
.maximize("log(c) - psi*n^(1+eta)/(1+eta)") ...
.choose("c","n","k") ...
.subject_to(budget="c + k = w*n + (1-delta+r)*k{-1}");
p.equilibrium( ...
production="Y = A*k{-1}^alpha*n^(1-alpha)", ...
labdemand ="w = (1-alpha)*A*k{-1}^alpha*n^(-alpha)", ...
capdemand ="r = alpha*A*k{-1}^(alpha-1)*n^(1-alpha)", ...
tfp ="A = A{-1}^rho*exp(eps)");
The object can be handed to dsge_model three equivalent ways:
m = dsge_model(p); % (1) directly
m = dsge_model(code(p)); % (2) via the generated cell array of code lines
rs(p,'rbc.rs'); m = dsge_model('rbc.rs'); % (3) via a written .rs file
Parameter values are passed to dsge_model at solve time, as a structure:
params = struct('beta',0.99,'delta',0.025,'psi',1,'eta',1,'alpha',0.36,'rho',0.95);
m = solve(m, 'parameters', params);
% Number of solutions: 1
% steady state: c=2.555, n=0.928, k=35.24, w=2.371, r=0.0351, Y=3.436, A=1
2.4.3. What is generated
code(p) returns the derived model as a column cell array of code lines;
rs(p,file) writes it to a .rs file, and show(p) prints it. For the RBC
above the generated model is:
@endogenous c n k w r Y A household_lambda_budget
@exogenous eps
@parameters beta delta psi eta alpha rho
@model
% production
Y = A*k{-1}^alpha*n^(1-alpha);
% labdemand
w = (1-alpha)*A*k{-1}^alpha*n^(-alpha);
% capdemand
r = alpha*A*k{-1}^(alpha-1)*n^(1-alpha);
% tfp
A = A{-1}^rho*exp(eps);
% household: budget
(c + k)-(w*n + (1-delta+r)*k{-1});
% household: FOC wrt c
(1)/(c)+household_lambda_budget*(1);
% household: FOC wrt n
-(((real_power(n,1+eta,1))*(psi))*(1+eta)/((1+eta)^(2)))+household_lambda_budget*(-(w));
% household: FOC wrt k
household_lambda_budget*(1)+(beta)*household_lambda_budget{+1}*(-(1-delta+r{+1}));
Three conventions to note:
Lagrange multipliers are added automatically as endogenous variables, named
<agent>_lambda_<constraint-label>(herehousehold_lambda_budget). The labour-supply and Euler equations are the derived FOCs; the budget constraint is emitted as a residual.Equation tags. Every derived equation is preceded by a comment identifying its origin:
% <agent>: <constraint-label>for a constraint,% <agent>: FOC wrt <control>for a first-order condition, and the label you gave for an equilibrium equation. These make the generated file self-documenting.No optimization block, nothing hidden. The output is an ordinary RISE model: equilibrium identities, the derived FOCs, the agents’ constraints, and the shock processes. There is no
@optimization_problemblock.
Note
Steady state. microfound does not compute or require the analytical
steady state – providing it would mean hand-deriving exactly the algebra the
tool automates. dsge_model forms the steady-state system from the derived
FOCs and solves it numerically. You may pass p.steady_state(var=expr,...)
with a rough initial guess (a single seed per variable) to help the solver;
it is refined, not taken as the solution, and can often be omitted. This mirrors
gEcon, which likewise derives and numerically solves the steady-state equations.
2.4.4. Multiple agents
An economy can have several agents; each agent(...) block is differentiated
independently and contributes its own FOCs and multipliers. A firm that chooses
capital and labour to maximise profit, for instance, is written as another agent:
p.agent("firm") ...
.maximize("A*k{-1}^alpha*n^(1-alpha) - w*n - r*k{-1}") ...
.choose("k","n");
The gEcon example corpus (consumer + firm problems, adjustment costs, capital laws of motion, two-sector and two-country variants) is reproduced this way; see the validation note below.
2.4.5. Regime switching
Regime switching enters through switching parameters – and nothing else in how the agent’s problem is written changes. Declare a Markov chain, mark the parameters that switch on it, and the derived FOCs become the correct, probability-weighted switching first-order conditions automatically. This is a capability gEcon does not have.
p = rise.microfound("Switching-preferences RBC");
p.endogenous("c","n","k","w","r","Y","A");
p.exogenous("eps");
p.chain("pref", 2); % a 2-state Markov chain named "pref"
p.parameter("beta","delta","eta","alpha","rho");
p.parameter("pref_tp_1_2","pref_tp_2_1"); % chain transition probabilities
p.parameter("psi", switches_on="pref"); % labour disutility switches on "pref"
p.agent("household", discount="beta") ...
.maximize("log(c) - psi*n^(1+eta)/(1+eta)") ...
.choose("c","n","k") ...
.subject_to(budget="c + k = w*n + (1-delta+r)*k{-1}");
% ... equilibrium block unchanged ...
The switching parameter is emitted under a chain-scoped header,
@parameters(pref,2) psi, and the labour FOC references psi (which now
switches). Switching values and transition probabilities are supplied at solve
time with the underscore convention <param>_<chain>_<state> and
<chain>_tp_<i>_<j>:
params = struct('beta',0.99,'delta',0.025,'eta',1,'alpha',0.36,'rho',0.95, ...
'psi_pref_1',1, 'psi_pref_2',3, 'pref_tp_1_2',0.1, 'pref_tp_2_1',0.1);
m = solve(dsge_model(p), 'parameters', params);
% Number of solutions: 1
% regime 1 (psi=1): n=0.928 c=2.555 k=35.24
% regime 2 (psi=3): n=0.536 c=1.475 k=20.35
The steady state is solved per regime from the derived switching FOCs: higher
labour disutility (psi=3) yields lower hours and capital, as expected.
2.4.6. Output methods
Method |
Result |
|---|---|
|
the derived model as a column cell array of code lines (the canonical artifact) |
|
write the derived model to a |
|
print the derived model (optionally one agent’s block) |
|
a LaTeX model appendix (notation + each agent’s problem + derived FOCs) |
2.4.7. API reference
Call |
Meaning |
|---|---|
|
create a builder |
|
declare endogenous variables (inline |
|
declare shocks |
|
declare parameters; |
|
declare a Markov chain |
|
open an agent’s problem (returns a fluent handle) |
|
the period objective |
|
the choice (control) variables |
|
named equality constraints (multiplier |
|
market-clearing / identity equations |
|
optional rough initial guess for the numerical steady state |
2.4.8. Scope and roadmap
Optimal policy. microfound derives the first-order conditions of
private (competitive) agents – it assumes rational expectations with full
commitment and does not solve a planner’s (Ramsey) problem. For optimal
policy, use RISE’s dedicated optimal-policy facilities (the
@optimization_problem planner block); the two share the same underlying FOC
engine (rise.engine.foc). A natural workflow is to generate the competitive
economy with microfound and add a planner block for the Ramsey analysis.
Heterogeneous agents (HANK). The heterogeneity vocabulary is present in the
API – axis(name, points, ...), individual(...), aggregate(...),
aggregation(...), and over= on an agent – so that a HANK layer can emit
@heterogeneity_axis / @endogenous(individual) / @Agg constructs. In the
current release this vocabulary is stored but not yet derived: authoring an
individual’s problem over a wealth grid is a planned (phase-2) capability, not a
functional one today. Representative-agent and regime-switching models are the
supported cases.
2.4.9. Validation
The representative-agent derivation is validated by re-authoring nine gEcon
example models in microfound – basic RBC, RBC with installation costs,
capacity utilisation, habit formation, monopolistic competition (with a
household stochastic discount factor), two sectors, home production,
time-to-build, and two countries with risk sharing. All derive and solve, and
the two-sector model reproduces gEcon’s own derived steady state. See
examples/microfound/ in the toolbox for runnable drivers.