Skip to content

Add derive_focs for automatic FOC derivation from optimization problems#229

Draft
Copilot wants to merge 7 commits intomainfrom
copilot/add-user-friendly-parser
Draft

Add derive_focs for automatic FOC derivation from optimization problems#229
Copilot wants to merge 7 commits intomainfrom
copilot/add-user-friendly-parser

Conversation

Copy link
Contributor

Copilot AI commented Jan 5, 2026

  • Implement optimization problem syntax in @model macro
  • Support maximise/maximize/minimise/minimize with | begin ... end constraints
  • Auto-derive FOCs from optimization problems
  • Test basic RBC model with optimization syntax
  • Fix code review issues (handle minimization, simplify mapping)
  • Add documentation

Syntax

Since Julia doesn't support subject_to as an infix operator, use the | operator:

@model RBC begin
    U[0] = maximise(log(C[0]) + β * U[1], controls = [C[0], K[0]]) | begin
        C[0] + K[0] = r[0] * K[-1] + (1 - δ) * K[-1]
    end
    
    r[0] = α * Z[0] * K[-1]^- 1)
    log(Z[0]) = ρ * log(Z[-1]) + σ * ε[x]
end

This automatically derives the FOCs (Euler equation for consumption/capital) from the optimization problem.

Original prompt

allow the user to input the model not as a set of FOCs but instead to formulate the optimisation problem, controls, constraints, and identities. the parser then takes care of doing the derivation of the FOCs (derivatives of lagrangian consisting of optimisation objective and constriants wrt controls). the syntax should be as user friendly as possible. currently only gEcon implements this functionality. see below for an exmaple of a gEcon model. take this as an example to test against:

block CONSUMER
{
definitions
{
u[] = (C[]^mu * (1 - L_s[])^(1 - mu))^(1 - eta) / (1 - eta);
};
controls
{
K_s[], C[], L_s[], I[];
};
objective
{
U[] = u[] + beta * E[][U[1]];
};
constraints
{
I[] + C[] = pi[] + r[] * K_s[-1] + W[] * L_s[];
K_s[] = (1 - delta) * K_s[-1] + I[];
};
calibration
{
delta = 0.025;
beta = 0.99;
eta = 2;
mu = 0.3;
};
};

block FIRM
{
controls
{
K_d[], L_d[], Y[];
};
objective
{
pi[] = Y[] - L_d[] * W[] - r[] * K_d[];
};
constraints
{
Y[] = Z[] * K_d[]^alpha * L_d[]^(1 - alpha);
};
calibration
{
r[ss] * K_d[ss] = 0.36 * Y[ss] -> alpha;
};
};

block EQUILIBRIUM
{
identities
{
K_d[] = K_s[-1];
L_d[] = L_s[];
};
};

block EXOG
{
identities
{
Z[] = exp(phi * log(Z[-1]) + epsilon_Z[]);
};
shocks
{
epsilon_Z[];
};
calibration
{
phi = 0.95;
};
};


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits January 5, 2026 20:58
…on problems

Co-authored-by: thorek1 <13523097+thorek1@users.noreply.github.com>
…_focs

Co-authored-by: thorek1 <13523097+thorek1@users.noreply.github.com>
Co-authored-by: thorek1 <13523097+thorek1@users.noreply.github.com>
Copilot AI changed the title [WIP] Add user-friendly parser for optimization problems Add derive_focs for automatic FOC derivation from optimization problems Jan 5, 2026
Copilot AI requested a review from thorek1 January 5, 2026 21:21
@thorek1
Copy link
Owner

thorek1 commented Jan 5, 2026

@copilot use the following syntax and allow for it in the @model macro (instead of a separate derive_focs function):

U[0] = maximise(log(C[0]) + ψ * log(1 - L[0]) + β * U[1],
controls = [C[0], L[0], K[1]]
) subject_to begin
C[0] + I[0] = π[0] + r[0] * K[-1] + w[0] * L[0]
K[0] = (1 - δ) * K[-1] + I[0]
end

Co-authored-by: thorek1 <13523097+thorek1@users.noreply.github.com>
Copy link
Owner

@thorek1 thorek1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try again

Co-authored-by: thorek1 <13523097+thorek1@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 6, 2026

Try again

Implemented in 0bb6ae1. The optimization syntax is now integrated into the @model macro.

Note: Since Julia doesn't support subject_to as an infix operator (it causes a parse error), I've used the | operator syntax instead:

U[0] = maximise(log(C[0]) + β * U[1], controls = [C[0], K[0]]) | begin
    C[0] + K[0] = r[0] * K[-1] + (1 - δ) * K[-1]
end

This automatically derives the Euler equations from the optimization problem.

Co-authored-by: thorek1 <13523097+thorek1@users.noreply.github.com>
Copilot AI requested a review from thorek1 January 6, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants