From 92bb2a5831ca6e7f1bda013321f3dfd69954e5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org> Date: Tue, 16 Apr 2024 15:44:57 +0200 Subject: [PATCH] New syntax for complementarity conditions, using the perpendicular symbol In particular, adapt the manual and the testsuite. --- doc/manual/source/conf.py | 4 +++ doc/manual/source/the-model-file.rst | 31 +++++++++---------- preprocessor | 2 +- .../histval_initval_test.mod | 6 ++-- .../initval_endval_test.mod | 6 ++-- tests/ep/rbcii_MCP.mod | 3 +- tests/ep/rs2.mod | 8 ++--- tests/lmmcp/MCP_ramsey.mod | 5 ++- tests/lmmcp/SMOPEC.mod | 6 ++-- tests/lmmcp/purely_backward.mod | 4 +-- tests/lmmcp/purely_forward.mod | 1 + tests/lmmcp/rbcii.mod | 3 +- tests/lmmcp/sw_lmmcp.mod | 3 +- tests/path/lcp/mod1.mod | 5 ++- 14 files changed, 42 insertions(+), 45 deletions(-) diff --git a/doc/manual/source/conf.py b/doc/manual/source/conf.py index 064b224d38..eb9c74cca0 100644 --- a/doc/manual/source/conf.py +++ b/doc/manual/source/conf.py @@ -71,6 +71,10 @@ latex_elements = { warningBorderColor={RGB}{255,50,50},OuterLinkColor={RGB}{34,139,34}, \ InnerLinkColor={RGB}{51,51,255},TitleColor={RGB}{51,51,255}', 'papersize': 'a4paper', + # Add support for the perpendicular symbol input as UTF-8 + 'preamble': r''' +\DeclareUnicodeCharacter{27C2}{\ensuremath{\perp}} +''' } latex_documents = [ diff --git a/doc/manual/source/the-model-file.rst b/doc/manual/source/the-model-file.rst index c0185e6a33..d4c2aaaa17 100644 --- a/doc/manual/source/the-model-file.rst +++ b/doc/manual/source/the-model-file.rst @@ -992,7 +992,7 @@ The model is declared inside a ``model`` block: model; - [name='Taylor rule',mcp = 'r > -1.94478'] + [name='Taylor rule', endogenous='r'] r = rho*r(-1) + (1-rho)*(gpi*Infl+gy*YGap) + e; end; @@ -2975,14 +2975,14 @@ Finding the steady state with Dynare nonlinear solver Levenberg-Marquardt mixed complementarity problem (LMMCP) solver (*Kanzow and Petra (2004)*). The complementarity - conditions are specified with an ``mcp`` equation tag, see + conditions are specified using the perpendicular symbol, see :opt:`lmmcp`. ``11`` PATH mixed complementarity problem solver of *Ferris and Munson (1999)*. The complementarity conditions are - specified with an ``mcp`` equation tag, see + specified using the perpendicular symbol, see :opt:`lmmcp`. Dynare only provides the interface for using the solver. Due to licence restrictions, you have to download the solver’s most current version yourself @@ -3884,18 +3884,18 @@ speed-up on large models. where :math:`X` denotes the vector of endogenous variables, :math:`F(X)` the equations of the model, :math:`LB` denotes a lower bound, and :math:`UB` an upper bound. Such a setup - is implemented by attaching an equation tag (see :ref:`model-decl`) - with the ``mcp`` keyword to the affected equations. This tag states that - the equation to which the tag is attached has to hold unless the inequality - constraint within the tag is binding. + is implemented by specifying the complementarity condition after the + equation to which it is attached, the two being separated by the + perpendicular symbol (the latter can be input either in UTF-8, as ⟂, + corresponding to Unicode codepoint U+27C2; or alternatively as pure ASCII, as + _|_, *i.e.* a vertical bar enclosed within two underscores). For instance, a ZLB on the nominal interest rate would be specified as follows in the model block:: model; ... - [mcp = 'r > -1.94478'] - r = rho*r(-1) + (1-rho)*(gpi*Infl+gy*YGap) + e; + r = rho*r(-1) + (1-rho)*(gpi*Infl+gy*YGap) + e ⟂ r > -1.94478; ... end; @@ -3906,12 +3906,11 @@ speed-up on large models. ``r<=-1.94478``, in which case the ``r`` is fixed at ``-1.94478`` (thereby being equivalent to a complementary slackness condition). By restricting the value of ``r`` coming - out of this equation, the ``mcp`` tag also avoids using + out of this equation, the complementarity condition also avoids using ``max(r,-1.94478)`` for other occurrences of ``r`` in the rest - of the model. Two things are important to keep in mind. First, because the - ``mcp`` tag effectively replaces a complementary slackness - condition, it cannot be simply attached to any - equation. Rather, it must be attached to the correct affected + of the model. Two things are important to keep in mind. First, the complementary slackness + condition cannot be simply attached to any + equation; it must be attached to the correct affected equation as otherwise the solver will solve a different problem than originally intended. Second, the sign of the residual of the dynamic equation must conform to the MCP setup outlined above. In case of the ZLB, @@ -3931,7 +3930,7 @@ speed-up on large models. would be wrong. Note that in the current implementation, the content of the - ``mcp`` equation tag is not parsed by the preprocessor. The + complementarity condition is not parsed by the preprocessor. The inequalities must therefore be as simple as possible: an endogenous variable, followed by a relational operator, followed by a number (not a variable, parameter or expression). @@ -5182,7 +5181,7 @@ which is described below. (2004)*), which allows to consider inequality constraints on the endogenous variables (such as a ZLB on the nominal interest rate or a model with irreversible investment). For specifying the - necessary ``mcp`` tag, see :opt:`lmmcp`. + necessary complementarity conditions, see :opt:`lmmcp`. Typology and ordering of variables diff --git a/preprocessor b/preprocessor index bdb8ef9961..8bfe3ef4bc 160000 --- a/preprocessor +++ b/preprocessor @@ -1 +1 @@ -Subproject commit bdb8ef996192b15cf8398d7d58d59954a9bb248b +Subproject commit 8bfe3ef4bc8973589aa35d1a3cb265fb954748ee diff --git a/tests/deterministic_simulations/initval_endval_blocks/histval_initval_test.mod b/tests/deterministic_simulations/initval_endval_blocks/histval_initval_test.mod index 1d93c5e71d..ddc4868398 100644 --- a/tests/deterministic_simulations/initval_endval_blocks/histval_initval_test.mod +++ b/tests/deterministic_simulations/initval_endval_blocks/histval_initval_test.mod @@ -19,8 +19,8 @@ model; //[name = 'FOC wrt L', mcp = 'L>0'] (1-alpha)*A*((K)^alpha)*(L^(-alpha)) = w*(1-eta); -[name = 'FOC wrt K(+1)', mcp = 'q>0'] -beta*alpha*A*(K(+1)^(alpha-1))*(L(+1)^(1-alpha)) + beta*(1-delta)*q(+1) = q; +[name = 'FOC wrt K(+1)'] +beta*alpha*A*(K(+1)^(alpha-1))*(L(+1)^(1-alpha)) + beta*(1-delta)*q(+1) = q ⟂ q>0; KL_ratio = K/L; @@ -73,4 +73,4 @@ end if oo_.endo_simul(strmatch('K',M_.endo_names,'exact'),end)~=1000 error('endval does not match') -end \ No newline at end of file +end diff --git a/tests/deterministic_simulations/initval_endval_blocks/initval_endval_test.mod b/tests/deterministic_simulations/initval_endval_blocks/initval_endval_test.mod index 153de9c243..3a1df9aa18 100644 --- a/tests/deterministic_simulations/initval_endval_blocks/initval_endval_test.mod +++ b/tests/deterministic_simulations/initval_endval_blocks/initval_endval_test.mod @@ -19,8 +19,8 @@ model; //[name = 'FOC wrt L', mcp = 'L>0'] (1-alpha)*A*((K)^alpha)*(L^(-alpha)) = w*(1-eta); -[name = 'FOC wrt K(+1)', mcp = 'q>0'] -beta*alpha*A*(K(+1)^(alpha-1))*(L(+1)^(1-alpha)) + beta*(1-delta)*q(+1) = q; +[name = 'FOC wrt K(+1)'] +beta*alpha*A*(K(+1)^(alpha-1))*(L(+1)^(1-alpha)) + beta*(1-delta)*q(+1) = q ⟂ q>0; KL_ratio = K/L; @@ -73,4 +73,4 @@ end if oo_.endo_simul(strmatch('K',M_.endo_names,'exact'),end)~=1000 error('endval does not match') -end \ No newline at end of file +end diff --git a/tests/ep/rbcii_MCP.mod b/tests/ep/rbcii_MCP.mod index 69bb5912e4..ffad81e926 100644 --- a/tests/ep/rbcii_MCP.mod +++ b/tests/ep/rbcii_MCP.mod @@ -18,8 +18,7 @@ model(use_dll); beta*(c(+1)^theta*(1-L(+1))^(1-theta))^(1-tau)/c(+1) *(alpha*(y(+1)/k)^(1-psi)+1-delta)+mu(+1)*(1-delta); i=y-c; - [ mcp = 'i > 0' ] - mu = 0; + mu = 0 ⟂ i > 0; end; diff --git a/tests/ep/rs2.mod b/tests/ep/rs2.mod index f213b12569..7fbcd45b66 100644 --- a/tests/ep/rs2.mod +++ b/tests/ep/rs2.mod @@ -65,8 +65,7 @@ exp(lC)^-phi = beta *exp(10*Int1-10*lpi1(+1)) *exp(lC(+1))^-phi *exp(lDZ(+1))^-p // Finally; the scaling and unscaling of Valphaexp by the constant VAIMSS and DZBar improves the // numerical behavior of the model; without it; the steady-state value of Valphaexp can be minuscule // (e.g.; 10^-50); which requires Mathematica to use astronomical levels of precision to solve. *) -[mcp = 'Valphaexp > 1e-5'] -Valphaexp = (V(+1) *exp(lDZ(+1))^(1-phi) /VAIMSS /DZBar^(1-phi))^(1-alpha); +Valphaexp = (V(+1) *exp(lDZ(+1))^(1-phi) /VAIMSS /DZBar^(1-phi))^(1-alpha) ⟂ Valphaexp > 1e-5; Vkp = VAIMSS *DZBar^(1-phi) *Valphaexp^(1/(1-alpha)); exp(lzn) = (1+theta) *MC *exp(lY) + xi *beta *exp(lC(+1)-lC)^-phi *exp(lDZ(+1))^-phi @@ -77,8 +76,7 @@ exp(lp0)^(1+(1+theta)/theta *(1-eta)/eta) = exp(lzn-lzd); exp(lpi)^(-1/theta) = (1-xi) *exp(lp0+lpi)^(-1/theta) + xi; // Marginal cost and real wage MC = exp(lwreal) /eta *exp(lY)^((1-eta)/eta) /exp(lA)^(1/eta) /KBar^((1-eta)/eta); -[mcp = 'lL < 1.0986'] -chi0 *(LMax-exp(lL))^-chi /exp(lC)^-phi = exp(lwreal); +chi0 *(LMax-exp(lL))^-chi /exp(lC)^-phi = exp(lwreal) ⟂ lL < 1.0986; // Output equations exp(lY) = exp(lA) *KBar^(1-eta) *exp(lL)^eta /exp(lDisp); exp(lDisp)^(1/eta) = (1-xi) *exp(lp0)^(-(1+theta)/theta/eta) @@ -153,4 +151,4 @@ end; //stoch_simul(order=3,periods=50000,pruning); -extended_path(order=0,periods=3); \ No newline at end of file +extended_path(order=0,periods=3); diff --git a/tests/lmmcp/MCP_ramsey.mod b/tests/lmmcp/MCP_ramsey.mod index 34775e5883..e7be421168 100644 --- a/tests/lmmcp/MCP_ramsey.mod +++ b/tests/lmmcp/MCP_ramsey.mod @@ -13,8 +13,7 @@ lambda2 = 0.1; pi_bar = 2.0; model; -[mcp = 'i > 0'] -y = beta1*y(-1) + beta2*y(+1) + beta3*(i-pi(+1)) + e_y; +y = beta1*y(-1) + beta2*y(+1) + beta3*(i-pi(+1)) + e_y ⟂ i > 0; pi = lambda1*pi(+1) + (1-lambda1)*pi(-1) + lambda2*y + e_pi; end; @@ -30,4 +29,4 @@ steady; perfect_foresight_setup(periods=50); perfect_foresight_solver(lmmcp); -rplot i; \ No newline at end of file +rplot i; diff --git a/tests/lmmcp/SMOPEC.mod b/tests/lmmcp/SMOPEC.mod index 9aa97bf9d7..d5ccff5a7f 100644 --- a/tests/lmmcp/SMOPEC.mod +++ b/tests/lmmcp/SMOPEC.mod @@ -59,8 +59,8 @@ model; y + d= c + (1+r_bar)*d(-1); [name='Endowment'] y = 1; - [name='Euler equation', mcp = 'd<2'] - beta*(1+r_bar)*1/c(+1)-1/c=0; + [name='Euler equation'] + beta*(1+r_bar)*1/c(+1)-1/c=0 ⟂ d<2; end; initval; @@ -70,4 +70,4 @@ c=y-r_bar*d; end; resid; steady(solve_algo=10); -resid; \ No newline at end of file +resid; diff --git a/tests/lmmcp/purely_backward.mod b/tests/lmmcp/purely_backward.mod index 7d3bce2727..c96f45e536 100644 --- a/tests/lmmcp/purely_backward.mod +++ b/tests/lmmcp/purely_backward.mod @@ -1,4 +1,5 @@ // Regression test for bug #1720 (in the purely backward case) +// Also tests the alternative (ASCII) representation for the perpendicular symbol var y; @@ -9,8 +10,7 @@ parameters rho; rho = 0.9; model; - [ mcp = 'y>1' ] - y = y(-1)^rho*exp(eps); + y = y(-1)^rho*exp(eps) _|_ y>1; end; initval; diff --git a/tests/lmmcp/purely_forward.mod b/tests/lmmcp/purely_forward.mod index eb61ad29e8..c27ec4581b 100644 --- a/tests/lmmcp/purely_forward.mod +++ b/tests/lmmcp/purely_forward.mod @@ -1,4 +1,5 @@ // Regression test for bug #1720 (in the purely forward case) +// Also tests the obsolete “mcp†tag syntax var y; diff --git a/tests/lmmcp/rbcii.mod b/tests/lmmcp/rbcii.mod index 90b63d292d..03590cabd3 100644 --- a/tests/lmmcp/rbcii.mod +++ b/tests/lmmcp/rbcii.mod @@ -21,8 +21,7 @@ model; k = y-c+(1-delta)*k(-1); i = k-(1-delta)*k(-1); -[ mcp = 'i > 0' ] - mu = 0; + mu = 0 ⟂ i > 0; end; steady_state_model; diff --git a/tests/lmmcp/sw_lmmcp.mod b/tests/lmmcp/sw_lmmcp.mod index 59758a55c7..cb42bdcc7d 100644 --- a/tests/lmmcp/sw_lmmcp.mod +++ b/tests/lmmcp/sw_lmmcp.mod @@ -45,8 +45,7 @@ model; +(1-xi_w)*(1-beta_bar*gamma*xi_w)/((1+beta_bar*gamma)*xi_w)*(1/((phi_w-1)*curv_w+1))* (sigma_l*l + (1/(1-lambda/gamma))*c - ((lambda/gamma)/(1-lambda/gamma))*c(-1) -w) + 1*eps_w ; - [mcp='r > -1.944781619515523'] - r = r_pi * (1-rho) * pinf + r_y * (1-rho) * (y-yf) + r_dy * ( y - yf - (y(-1) - yf(-1))) + rho * r(-1) + eps_r; + r = r_pi * (1-rho) * pinf + r_y * (1-rho) * (y-yf) + r_dy * ( y - yf - (y(-1) - yf(-1))) + rho * r(-1) + eps_r ⟂ r > -1.944781619515523; eps_a = rho_a * eps_a(-1) + eta_a; eps_b = rho_b * eps_b(-1) + eta_b; eps_g = rho_g * eps_g(-1) + eta_g + rho_ga * eta_a; diff --git a/tests/path/lcp/mod1.mod b/tests/path/lcp/mod1.mod index 8db04f3753..75eb641b07 100644 --- a/tests/path/lcp/mod1.mod +++ b/tests/path/lcp/mod1.mod @@ -19,8 +19,7 @@ model(linear,use_dll); pi = pi_bar*(1-alpha_1-(1-alpha_1)*alpha_2) + alpha_1*pi(-1) + (1-alpha_1)*alpha_2*pi(+1) + alpha_3*y + e_pi; y = beta_1*y(-1) + (1-beta_1)*y(+1) - beta_2*(rl-rr_bar - pi(+1)) + e_y; rs_shadow = gamma_r*rs(-1) + (1-gamma_r)*(rr_bar + pi_bar + gamma_pi*(pi-pi_bar) + gamma_y*y); - [mcp = 'rs_shadow > 0'] - rs_1 = rs_shadow; + rs_1 = rs_shadow ⟂ rs_shadow > 0; // [mcp = 'pi > 1.4'] rs = rs_1; rl = 400*(((1+rs/400) @@ -60,4 +59,4 @@ perfect_foresight_solver(stack_solve_algo=7); rplot rs; //rplot rl; //rplot y; -//rplot pi; \ No newline at end of file +//rplot pi; -- GitLab