Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • normann/preprocessor
  • Dynare/preprocessor
  • FerhatMihoubi/preprocessor
  • MichelJuillard/preprocessor
  • sebastien/preprocessor
  • lnsongxf/preprocessor
  • albop/preprocessor
  • DoraK/preprocessor
  • amg/preprocessor
  • wmutschl/preprocessor
  • JohannesPfeifer/preprocessor
11 results
Select Git revision
Show changes
Showing
with 10129 additions and 8159 deletions
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/* -*- C++ -*- */
/*
* Copyright © 2003-2019 Dynare Team
* Copyright © 2003-2025 Dynare Team
*
* This file is part of Dynare.
*
......@@ -15,16 +15,15 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
%{
using namespace std;
#include <cstring>
#include "ParsingDriver.hh"
using namespace std;
// Announce to Flex the prototype we want for lexing function
#define YY_DECL \
Dynare::parser::token_type \
......@@ -41,11 +40,10 @@ using token = Dynare::parser::token;
#define yyterminate() return Dynare::parser::token_type(0);
int comment_caller, line_caller;
/* Particular value : when sigma_e command is found
this flag is set to 1, when command finished it is set to 0
*/
int sigma_e = 0;
string eofbuff;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
%}
%option c++
......@@ -61,7 +59,6 @@ string eofbuff;
%x VERBATIM_BLOCK
%x NATIVE
%x NATIVE_COMMENT
%x DATES_STATEMENT
%x LINE1
%x LINE2
%x LINE3
......@@ -71,7 +68,9 @@ string eofbuff;
#define YY_USER_ACTION location_increment(yylloc, yytext);
%}
DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
NAME [a-z_][a-z0-9_]*
FLOAT_NUMBER ((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+[ed][-+]?[0-9]+)
DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|[sh][12])
%%
/* Code put at the beginning of yylex() */
......@@ -83,7 +82,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
/* Rules for matching $line directives */
<*>^@#line\ \" { line_caller = YYSTATE; BEGIN(LINE1); }
<LINE1>[^\"]* {
filename = string(yytext);
filename = yytext;
BEGIN(LINE2);
}
<LINE2>\" BEGIN(LINE3);
......@@ -93,12 +92,12 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
}
/* spaces, tabs and carriage returns are ignored */
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,DATES_STATEMENT,LINE1,LINE2,LINE3>[[:space:]]+ { yylloc->step(); }
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,LINE1,LINE2,LINE3>[[:space:]]+ { yylloc->step(); }
/* Comments */
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>%.*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>"//".*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,DATES_STATEMENT>"/*" {comment_caller = YY_START; BEGIN COMMENT;}
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>%.*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>"//".*
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK>"/*" {comment_caller = YY_START; BEGIN COMMENT;}
<COMMENT>"*/" {BEGIN comment_caller;}
<COMMENT>.
......@@ -112,10 +111,9 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>predetermined_variables {BEGIN DYNARE_STATEMENT; return token::PREDETERMINED_VARIABLES;}
<INITIAL>parameters {BEGIN DYNARE_STATEMENT; return token::PARAMETERS;}
<INITIAL>model_local_variable {BEGIN DYNARE_STATEMENT; return token::MODEL_LOCAL_VARIABLE;}
<INITIAL>periods {BEGIN DYNARE_STATEMENT; return token::PERIODS;}
<INITIAL>heterogeneity_dimension {BEGIN DYNARE_STATEMENT; return token::HETEROGENEITY_DIMENSION;}
<INITIAL>model_info {BEGIN DYNARE_STATEMENT; return token::MODEL_INFO;}
<INITIAL>estimation {BEGIN DYNARE_STATEMENT; return token::ESTIMATION;}
<INITIAL>var_estimation {BEGIN DYNARE_STATEMENT; return token::VAR_ESTIMATION;}
<INITIAL>set_time {BEGIN DYNARE_STATEMENT; return token::SET_TIME;}
<INITIAL>data {BEGIN DYNARE_STATEMENT; return token::DATA;}
<INITIAL>varobs {BEGIN DYNARE_STATEMENT; return token::VAROBS;}
......@@ -144,16 +142,22 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>var_expectation_model {BEGIN DYNARE_STATEMENT; return token::VAR_EXPECTATION_MODEL;}
<INITIAL>pac_model {BEGIN DYNARE_STATEMENT; return token::PAC_MODEL;}
<INITIAL>dsample {BEGIN DYNARE_STATEMENT; return token::DSAMPLE;}
<INITIAL>Sigma_e {BEGIN DYNARE_STATEMENT; sigma_e = 1; return token::SIGMA_E;}
<INITIAL>planner_objective {BEGIN DYNARE_STATEMENT; return token::PLANNER_OBJECTIVE;}
<INITIAL>ramsey_model {BEGIN DYNARE_STATEMENT; return token::RAMSEY_MODEL;}
<INITIAL>ramsey_policy {BEGIN DYNARE_STATEMENT; return token::RAMSEY_POLICY;}
<INITIAL>evaluate_planner_objective {BEGIN DYNARE_STATEMENT; return token::EVALUATE_PLANNER_OBJECTIVE;}
<INITIAL>occbin_setup {BEGIN DYNARE_STATEMENT; return token::OCCBIN_SETUP;}
<INITIAL>occbin_solver {BEGIN DYNARE_STATEMENT; return token::OCCBIN_SOLVER;}
<INITIAL>occbin_write_regimes {BEGIN DYNARE_STATEMENT; return token::OCCBIN_WRITE_REGIMES;}
<INITIAL>occbin_graph {BEGIN DYNARE_STATEMENT; return token::OCCBIN_GRAPH;}
<INITIAL>discretionary_policy {BEGIN DYNARE_STATEMENT; return token::DISCRETIONARY_POLICY;}
<INITIAL>identification {BEGIN DYNARE_STATEMENT; return token::IDENTIFICATION;}
<INITIAL>bvar_density {BEGIN DYNARE_STATEMENT; return token::BVAR_DENSITY; }
<INITIAL>bvar_forecast {BEGIN DYNARE_STATEMENT; return token::BVAR_FORECAST; }
<INITIAL>dynare_sensitivity {BEGIN DYNARE_STATEMENT; return token::DYNARE_SENSITIVITY;}
<INITIAL>bvar_irf {BEGIN DYNARE_STATEMENT; return token::BVAR_IRF; }
<INITIAL>sensitivity {BEGIN DYNARE_STATEMENT; return token::SENSITIVITY;}
<INITIAL>dynare_sensitivity {BEGIN DYNARE_STATEMENT; return token::DYNARE_SENSITIVITY;} // Deprecated
<INITIAL>initval_file {BEGIN DYNARE_STATEMENT; return token::INITVAL_FILE;}
<INITIAL>histval_file {BEGIN DYNARE_STATEMENT; return token::HISTVAL_FILE;}
<INITIAL>forecast {BEGIN DYNARE_STATEMENT; return token::FORECAST;}
......@@ -161,6 +165,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>realtime_shock_decomposition {BEGIN DYNARE_STATEMENT; return token::REALTIME_SHOCK_DECOMPOSITION;}
<INITIAL>plot_shock_decomposition {BEGIN DYNARE_STATEMENT; return token::PLOT_SHOCK_DECOMPOSITION;}
<INITIAL>initial_condition_decomposition {BEGIN DYNARE_STATEMENT; return token::INITIAL_CONDITION_DECOMPOSITION;}
<INITIAL>squeeze_shock_decomposition {BEGIN DYNARE_STATEMENT; return token::SQUEEZE_SHOCK_DECOMPOSITION;}
<INITIAL>sbvar {BEGIN DYNARE_STATEMENT; return token::SBVAR;}
<INITIAL>ms_estimation {BEGIN DYNARE_STATEMENT; return token::MS_ESTIMATION;}
<INITIAL>ms_simulation {BEGIN DYNARE_STATEMENT; return token::MS_SIMULATION;}
......@@ -171,8 +176,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>ms_variance_decomposition {BEGIN DYNARE_STATEMENT; return token::MS_VARIANCE_DECOMPOSITION;}
<INITIAL>conditional_forecast {BEGIN DYNARE_STATEMENT; return token::CONDITIONAL_FORECAST;}
<INITIAL>plot_conditional_forecast {BEGIN DYNARE_STATEMENT; return token::PLOT_CONDITIONAL_FORECAST;}
<INITIAL>gmm_estimation {BEGIN DYNARE_STATEMENT; return token::GMM_ESTIMATION;}
<INITIAL>smm_estimation {BEGIN DYNARE_STATEMENT; return token::SMM_ESTIMATION;}
<INITIAL>method_of_moments {BEGIN DYNARE_STATEMENT; return token::METHOD_OF_MOMENTS;}
<INITIAL>markov_switching {BEGIN DYNARE_STATEMENT; return token::MARKOV_SWITCHING;}
<INITIAL>svar {BEGIN DYNARE_STATEMENT; return token::SVAR;}
......@@ -185,13 +189,15 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>smoother2histval {BEGIN DYNARE_STATEMENT; return token::SMOOTHER2HISTVAL;}
<INITIAL>perfect_foresight_setup {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SETUP;}
<INITIAL>perfect_foresight_solver {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SOLVER;}
<INITIAL>det_cond_forecast {BEGIN DYNARE_STATEMENT; return token::DET_COND_FORECAST;}
<INITIAL>perfect_foresight_with_expectation_errors_setup {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SETUP;}
<INITIAL>perfect_foresight_with_expectation_errors_solver {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_WITH_EXPECTATION_ERRORS_SOLVER;}
<INITIAL>compilation_setup {BEGIN DYNARE_STATEMENT; return token::COMPILATION_SETUP;}
<INITIAL>model_remove {BEGIN DYNARE_STATEMENT; return token::MODEL_REMOVE;}
<INITIAL>model_options {BEGIN DYNARE_STATEMENT; return token::MODEL_OPTIONS;}
<INITIAL>var_remove {BEGIN DYNARE_STATEMENT; return token::VAR_REMOVE;}
<INITIAL>resid {BEGIN DYNARE_STATEMENT; return token::RESID;}
<DYNARE_STATEMENT>; {
if (!sigma_e)
BEGIN INITIAL;
return Dynare::parser::token_type (yytext[0]);
}
<DYNARE_STATEMENT>; {BEGIN INITIAL; return Dynare::parser::token_type (yytext[0]);}
/* Begin of a Dynare block */
......@@ -200,8 +206,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>initval {BEGIN DYNARE_BLOCK; return token::INITVAL;}
<INITIAL>endval {BEGIN DYNARE_BLOCK; return token::ENDVAL;}
<INITIAL>histval {BEGIN DYNARE_BLOCK; return token::HISTVAL;}
<INITIAL>filter_initial_state {BEGIN DYNARE_BLOCK; return token::FILTER_INITIAL_STATE;}
<INITIAL>shocks {BEGIN DYNARE_BLOCK; return token::SHOCKS;}
<INITIAL>heteroskedastic_shocks {BEGIN DYNARE_BLOCK; return token::HETEROSKEDASTIC_SHOCKS;}
<INITIAL>shock_groups {BEGIN DYNARE_BLOCK; return token::SHOCK_GROUPS;}
<INITIAL>init2shocks {BEGIN DYNARE_BLOCK; return token::INIT2SHOCKS;}
<INITIAL>mshocks {BEGIN DYNARE_BLOCK; return token::MSHOCKS;}
<INITIAL>estimated_params {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS;}
<INITIAL>epilogue {BEGIN DYNARE_BLOCK; return token::EPILOGUE;}
......@@ -209,8 +218,10 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>priors {BEGIN DYNARE_BLOCK;return token::ESTIMATED_PARAMS;}
<INITIAL>estimated_params_init {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_INIT;}
<INITIAL>estimated_params_bounds {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_BOUNDS;}
<INITIAL>estimated_params_remove {BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_REMOVE;}
<INITIAL>osr_params_bounds {BEGIN DYNARE_BLOCK; return token::OSR_PARAMS_BOUNDS;}
<INITIAL>observation_trends {BEGIN DYNARE_BLOCK; return token::OBSERVATION_TRENDS;}
<INITIAL>deterministic_trends {BEGIN DYNARE_BLOCK; return token::DETERMINISTIC_TRENDS;}
<INITIAL>optim_weights {BEGIN DYNARE_BLOCK; return token::OPTIM_WEIGHTS;}
<INITIAL>homotopy_setup {BEGIN DYNARE_BLOCK; return token::HOMOTOPY_SETUP;}
<INITIAL>conditional_forecast_paths {BEGIN DYNARE_BLOCK; return token::CONDITIONAL_FORECAST_PATHS;}
......@@ -218,8 +229,14 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>moment_calibration {BEGIN DYNARE_BLOCK; return token::MOMENT_CALIBRATION;}
<INITIAL>irf_calibration {BEGIN DYNARE_BLOCK; return token::IRF_CALIBRATION;}
<INITIAL>ramsey_constraints {BEGIN DYNARE_BLOCK; return token::RAMSEY_CONSTRAINTS;}
<INITIAL>restrictions {BEGIN DYNARE_BLOCK; return token::RESTRICTIONS;}
<INITIAL>generate_irfs {BEGIN DYNARE_BLOCK; return token::GENERATE_IRFS;}
<INITIAL>matched_moments {BEGIN DYNARE_BLOCK; return token::MATCHED_MOMENTS;}
<INITIAL>occbin_constraints {BEGIN DYNARE_BLOCK; return token::OCCBIN_CONSTRAINTS;}
<INITIAL>model_replace {BEGIN DYNARE_BLOCK; return token::MODEL_REPLACE;}
<INITIAL>pac_target_info {BEGIN DYNARE_BLOCK; return token::PAC_TARGET_INFO;}
<INITIAL>matched_irfs {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS;}
<INITIAL>matched_irfs_weights {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS_WEIGHTS;}
<INITIAL>perfect_foresight_controlled_paths {BEGIN DYNARE_BLOCK; return token::PERFECT_FORESIGHT_CONTROLLED_PATHS;}
/* For the semicolon after an "end" keyword */
<INITIAL>; {return Dynare::parser::token_type (yytext[0]);}
......@@ -230,7 +247,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>subsamples {return token::SUBSAMPLES;}
<DYNARE_STATEMENT>options {return token::OPTIONS;}
<DYNARE_STATEMENT>prior {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::PRIOR;
}
<INITIAL>std {BEGIN DYNARE_STATEMENT; return token::STD;}
......@@ -240,31 +257,12 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<INITIAL>prior_function {BEGIN DYNARE_STATEMENT; return token::PRIOR_FUNCTION;}
<INITIAL>posterior_function {BEGIN DYNARE_STATEMENT; return token::POSTERIOR_FUNCTION;}
/* Inside of a Dynare statement */
<DYNARE_STATEMENT>{DATE} {
char *yycopy = strdup(yytext);
char *uput = yycopy + yyleng;
unput(')');
unput('\'');
while (uput > yycopy)
unput(*--uput);
unput('\'');
unput('(');
unput('s');
unput('e');
unput('t');
unput('a');
unput('d');
free( yycopy );
<DYNARE_STATEMENT,DYNARE_BLOCK>{DATE} {
yylval->emplace<string>(yytext);
return token::DATE;
}
<DYNARE_STATEMENT>${DATE} { yylloc->step();
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
yyout << yytext + 1;
#else
*yyout << yytext + 1;
#endif
}
<DYNARE_STATEMENT>dates {dates_parens_nb=0; BEGIN DATES_STATEMENT; yylval->build<string>("dates");}
/* Inside a Dynare statement */
<DYNARE_STATEMENT>file {return token::FILE;}
<DYNARE_STATEMENT>datafile {return token::DATAFILE;}
<DYNARE_STATEMENT>dirname {return token::DIRNAME;}
......@@ -274,7 +272,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>mean {return token::MEAN;}
<DYNARE_STATEMENT>stdev {return token::STDEV;}
<DYNARE_STATEMENT>truncate {return token::TRUNCATE;}
<DYNARE_STATEMENT>domain {return token::DOMAINN;}
<DYNARE_STATEMENT>domain {return token::DOMAINN;} // Use altered token name to avoid identifier collision on Windows and macOS
<DYNARE_STATEMENT>variance {return token::VARIANCE;}
<DYNARE_STATEMENT>mode {return token::MODE;}
<DYNARE_STATEMENT>interval {return token::INTERVAL;}
......@@ -285,22 +283,22 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>jscale {return token::JSCALE;}
<DYNARE_STATEMENT>prefilter {return token::PREFILTER;}
<DYNARE_STATEMENT>presample {return token::PRESAMPLE;}
<DYNARE_STATEMENT>lik_algo {return token::LIK_ALGO;}
<DYNARE_STATEMENT>lik_init {return token::LIK_INIT;}
<DYNARE_STATEMENT>taper_steps {return token::TAPER_STEPS;}
<DYNARE_STATEMENT>geweke_interval {return token::GEWEKE_INTERVAL;}
<DYNARE_STATEMENT>raftery_lewis_qrs {return token::RAFTERY_LEWIS_QRS;}
<DYNARE_STATEMENT>raftery_lewis_diagnostics {return token::RAFTERY_LEWIS_DIAGNOSTICS;}
<DYNARE_STATEMENT>brooks_gelman_plotrows {return token::BROOKS_GELMAN_PLOTROWS;}
<DYNARE_STATEMENT>graph {return token::GRAPH;}
<DYNARE_STATEMENT>nograph {return token::NOGRAPH;}
<DYNARE_STATEMENT>posterior_graph {return token::POSTERIOR_GRAPH;}
<DYNARE_STATEMENT>posterior_nograph {return token::POSTERIOR_NOGRAPH;}
<DYNARE_STATEMENT>nodisplay {return token::NODISPLAY;}
<DYNARE_STATEMENT>graph_format {return token::GRAPH_FORMAT;}
<DYNARE_STATEMENT>eps {yylval->build<string>(yytext); return token::EPS;}
<DYNARE_STATEMENT>pdf {yylval->build<string>(yytext); return token::PDF;}
<DYNARE_STATEMENT>fig {yylval->build<string>(yytext); return token::FIG;}
<DYNARE_STATEMENT>none {yylval->build<string>(yytext); return token::NONE;}
<DYNARE_STATEMENT>eps {yylval->emplace<string>(yytext); return token::EPS;}
<DYNARE_STATEMENT>pdf {yylval->emplace<string>(yytext); return token::PDF;}
<DYNARE_STATEMENT>fig {yylval->emplace<string>(yytext); return token::FIG;}
<DYNARE_STATEMENT>none {yylval->emplace<string>(yytext); return token::NONE;}
<DYNARE_STATEMENT>print {return token::PRINT;}
<DYNARE_STATEMENT>noprint {return token::NOPRINT;}
<DYNARE_STATEMENT>conf_sig {return token::CONF_SIG;}
......@@ -309,7 +307,9 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>mh_drop {return token::MH_DROP;}
<DYNARE_STATEMENT>mh_jscale {return token::MH_JSCALE;}
<DYNARE_STATEMENT>mh_init_scale {return token::MH_INIT_SCALE;}
<DYNARE_STATEMENT>mh_init_scale_factor {return token::MH_INIT_SCALE_FACTOR;}
<DYNARE_STATEMENT>mh_tune_jscale {return token::MH_TUNE_JSCALE;}
<DYNARE_STATEMENT>mh_tune_guess {return token::MH_TUNE_GUESS;}
<DYNARE_STATEMENT>mode_file {return token::MODE_FILE;}
<DYNARE_STATEMENT>mode_compute {return token::MODE_COMPUTE;}
<DYNARE_STATEMENT>mode_check {return token::MODE_CHECK;}
......@@ -317,7 +317,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>mode_check_symmetric_plots {return token::MODE_CHECK_SYMMETRIC_PLOTS;}
<DYNARE_STATEMENT>mode_check_number_of_points {return token::MODE_CHECK_NUMBER_OF_POINTS;}
<DYNARE_STATEMENT>prior_trunc {return token::PRIOR_TRUNC;}
<DYNARE_STATEMENT>mh_mode {return token::MH_MODE;}
<DYNARE_STATEMENT>mh_posterior_mode_estimation {return token::MH_POSTERIOR_MODE_ESTIMATION;}
<DYNARE_STATEMENT>mh_nblocks {return token::MH_NBLOCKS;}
<DYNARE_STATEMENT>load_mh_file {return token::LOAD_MH_FILE;}
<DYNARE_STATEMENT>load_results_after_load_mh {return token::LOAD_RESULTS_AFTER_LOAD_MH;}
......@@ -328,6 +328,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>kalman_algo {return token::KALMAN_ALGO;}
<DYNARE_STATEMENT>fast_kalman_filter {return token::FAST_KALMAN_FILTER;}
<DYNARE_STATEMENT>kalman_tol {return token::KALMAN_TOL;}
<DYNARE_STATEMENT>schur_vec_tol {return token::SCHUR_VEC_TOL;}
<DYNARE_STATEMENT>diffuse_kalman_tol {return token::DIFFUSE_KALMAN_TOL;}
<DYNARE_STATEMENT>forecast {return token::FORECAST;}
<DYNARE_STATEMENT>smoother {return token::SMOOTHER;}
......@@ -342,11 +343,14 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT,DYNARE_BLOCK>relative_irf {return token::RELATIVE_IRF;}
<DYNARE_STATEMENT>tex {return token::TEX;}
<DYNARE_STATEMENT>nomoments {return token::NOMOMENTS;}
<DYNARE_STATEMENT>nomodelsummary {return token::NOMODELSUMMARY;}
<DYNARE_STATEMENT>std {return token::STD;}
<DYNARE_STATEMENT>corr {return token::CORR;}
<DYNARE_STATEMENT>nocorr {return token::NOCORR;}
<DYNARE_STATEMENT>optim {return token::OPTIM;}
<DYNARE_STATEMENT>periods {return token::PERIODS;}
<DYNARE_BLOCK>from_initval_to_endval {return token::FROM_INITVAL_TO_ENDVAL;}
<DYNARE_STATEMENT>endval_steady {return token::ENDVAL_STEADY;}
<DYNARE_STATEMENT,DYNARE_BLOCK>model_name {return token::MODEL_NAME;}
<DYNARE_STATEMENT>auxiliary_model_name {return token::AUXILIARY_MODEL_NAME;}
<DYNARE_STATEMENT>endogenous_terminal_period {return token::ENDOGENOUS_TERMINAL_PERIOD;}
......@@ -359,6 +363,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>constant {return token::CONSTANT;}
<DYNARE_STATEMENT>noconstant {return token::NOCONSTANT;}
<DYNARE_STATEMENT>filename {return token::FILENAME;}
<DYNARE_STATEMENT>conditional_likelihood {return token::CONDITIONAL_LIKELIHOOD;}
<DYNARE_STATEMENT>diffuse_filter {return token::DIFFUSE_FILTER;}
<DYNARE_STATEMENT>plot_priors {return token::PLOT_PRIORS;}
<DYNARE_STATEMENT>aim_solver {return token::AIM_SOLVER;}
......@@ -382,8 +387,6 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>restriction_fname {return token::RESTRICTION_FNAME;}
<DYNARE_STATEMENT>nlags {return token::NLAGS;}
<DYNARE_STATEMENT>restrictions {return token::RESTRICTIONS;}
<DYNARE_BLOCK>crossequations {return token::CROSSEQUATIONS;}
<DYNARE_BLOCK>covariance {return token::COVARIANCE;}
<DYNARE_BLOCK>adl {return token::ADL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>diff {return token::DIFF;}
<DYNARE_STATEMENT>cross_restrictions {return token::CROSS_RESTRICTIONS;}
......@@ -403,7 +406,9 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>logarithmic_reduction {return token::LOGARITHMIC_REDUCTION;}
<DYNARE_STATEMENT>use_univariate_filters_if_singularity_is_detected {return token::USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED;}
<DYNARE_STATEMENT>hybrid {return token::HYBRID;}
<DYNARE_STATEMENT>use_first_order_solution {return token::USE_FIRST_ORDER_SOLUTION;}
<DYNARE_STATEMENT>default {return token::DEFAULT;}
<DYNARE_STATEMENT>init2shocks {return token::INIT2SHOCKS;}
<DYNARE_STATEMENT>number_of_particles {return token::NUMBER_OF_PARTICLES;}
<DYNARE_STATEMENT>resampling {return token::RESAMPLING;}
......@@ -414,6 +419,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>kitagawa {return token::KITAGAWA;}
<DYNARE_STATEMENT>smooth {return token::SMOOTH;}
<DYNARE_STATEMENT>stratified {return token::STRATIFIED;}
<DYNARE_STATEMENT>residual {
yylval->emplace<string>(yytext);
return token::RESIDUAL;
}
<DYNARE_STATEMENT>multinomial {return token::MULTINOMIAL;}
<DYNARE_STATEMENT>cpf_weights {return token::CPF_WEIGHTS;}
<DYNARE_STATEMENT>amisanotristani {return token::AMISANOTRISTANI;}
<DYNARE_STATEMENT>murrayjonesparslow {return token::MURRAYJONESPARSLOW;}
......@@ -429,45 +439,46 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>rescale_prediction_error_covariance {return token::RESCALE_PREDICTION_ERROR_COVARIANCE;}
<DYNARE_STATEMENT>use_penalized_objective_for_hessian {return token::USE_PENALIZED_OBJECTIVE_FOR_HESSIAN;}
<DYNARE_STATEMENT>expression {return token::EXPRESSION;}
<DYNARE_STATEMENT>first_simulation_period {return token::FIRST_SIMULATION_PERIOD;}
<DYNARE_STATEMENT>last_simulation_period {return token::LAST_SIMULATION_PERIOD;}
<DYNARE_STATEMENT>no_init_estimation_check_first_obs {return token::NO_INIT_ESTIMATION_CHECK_FIRST_OBS;}
<DYNARE_STATEMENT>fsolve_options {return token::FSOLVE_OPTIONS;}
<DYNARE_STATEMENT>alpha {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::ALPHA;
}
<DYNARE_STATEMENT>beta {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::BETA;
}
<DYNARE_STATEMENT>gamma {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::GAMMA;
}
<DYNARE_STATEMENT>inv_gamma {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::INV_GAMMA;
}
<DYNARE_STATEMENT>inv_gamma1 {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::INV_GAMMA1;
}
<DYNARE_STATEMENT>inv_gamma2 {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::INV_GAMMA2;
}
<DYNARE_STATEMENT>dirichlet {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::DIRICHLET;
}
<DYNARE_STATEMENT>weibull {
yylval->build<string>(yytext);
return token::WEIBULL;
}
<DYNARE_STATEMENT>weibull {return token::WEIBULL;}
<DYNARE_STATEMENT>normal {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::NORMAL;
}
<DYNARE_STATEMENT>uniform {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::UNIFORM;
}
<DYNARE_STATEMENT>gsig2_lmdm {return token::GSIG2_LMDM;}
......@@ -478,13 +489,13 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>ncsk {return token::NCSK;}
<DYNARE_STATEMENT>nstd {return token::NSTD;}
<DYNARE_STATEMENT>ninv {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::NINV;
}
<DYNARE_STATEMENT>indxparr {return token::INDXPARR;}
<DYNARE_STATEMENT>indxovr {return token::INDXOVR;}
<DYNARE_STATEMENT>aband {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::ABAND;
}
<DYNARE_STATEMENT>write_equation_tags {return token::WRITE_EQUATION_TAGS;}
......@@ -501,18 +512,18 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>indxgdls {return token::INDXGDLS;}
<DYNARE_STATEMENT>eq_ms {return token::EQ_MS;}
<DYNARE_STATEMENT>cms {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::CMS;
}
<DYNARE_STATEMENT>ncms {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::NCMS;
}
<DYNARE_STATEMENT>eq_cms {return token::EQ_CMS;}
<DYNARE_STATEMENT>tlindx {return token::TLINDX;}
<DYNARE_STATEMENT>tlnumber {return token::TLNUMBER;}
<DYNARE_STATEMENT>cnum {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::CNUM;
}
<DYNARE_STATEMENT>nodecomposition {return token::NODECOMPOSITION;};
......@@ -550,6 +561,33 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>max_block_iterations {return token::MAX_BLOCK_ITERATIONS;}
<DYNARE_STATEMENT>max_repeated_optimization_runs {return token::MAX_REPEATED_OPTIMIZATION_RUNS;}
<DYNARE_STATEMENT>maxit {return token::MAXIT;}
<DYNARE_STATEMENT>simul_maxit {return token::SIMUL_MAXIT;}
<DYNARE_STATEMENT>likelihood_maxit {return token::LIKELIHOOD_MAXIT;}
<DYNARE_STATEMENT>smoother_maxit {return token::SMOOTHER_MAXIT;}
<DYNARE_STATEMENT>simul_periods {return token::SIMUL_PERIODS;}
<DYNARE_STATEMENT>likelihood_periods {return token::LIKELIHOOD_PERIODS;}
<DYNARE_STATEMENT>smoother_periods {return token::SMOOTHER_PERIODS;}
<DYNARE_STATEMENT>simul_curb_retrench {return token::SIMUL_CURB_RETRENCH;}
<DYNARE_STATEMENT>likelihood_curb_retrench {return token::LIKELIHOOD_CURB_RETRENCH;}
<DYNARE_STATEMENT>smoother_curb_retrench {return token::SMOOTHER_CURB_RETRENCH;}
<DYNARE_STATEMENT>simul_check_ahead_periods {return token::SIMUL_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>simul_max_check_ahead_periods {return token::SIMUL_MAX_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>simul_reset_check_ahead_periods {return token::SIMUL_RESET_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>likelihood_check_ahead_periods {return token::LIKELIHOOD_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>likelihood_max_check_ahead_periods {return token::LIKELIHOOD_MAX_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>smoother_check_ahead_periods {return token::SMOOTHER_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>smoother_max_check_ahead_periods {return token::SMOOTHER_MAX_CHECK_AHEAD_PERIODS;}
<DYNARE_STATEMENT>simul_debug {return token::SIMUL_DEBUG;}
<DYNARE_STATEMENT>smoother_debug {return token::SMOOTHER_DEBUG;}
<DYNARE_STATEMENT>simul_periodic_solution {return token::SIMUL_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>likelihood_periodic_solution {return token::LIKELIHOOD_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>smoother_periodic_solution {return token::SMOOTHER_PERIODIC_SOLUTION;}
<DYNARE_STATEMENT>likelihood_inversion_filter {return token::LIKELIHOOD_INVERSION_FILTER;}
<DYNARE_STATEMENT>likelihood_piecewise_kalman_filter {return token::LIKELIHOOD_PIECEWISE_KALMAN_FILTER;}
<DYNARE_STATEMENT>likelihood_max_kalman_iterations {return token::LIKELIHOOD_MAX_KALMAN_ITERATIONS;}
<DYNARE_STATEMENT>smoother_inversion_filter {return token::SMOOTHER_INVERSION_FILTER;}
<DYNARE_STATEMENT>smoother_piecewise_kalman_filter {return token::SMOOTHER_PIECEWISE_KALMAN_FILTER;}
<DYNARE_STATEMENT>filter_use_relaxation {return token::FILTER_USE_RELEXATION;}
<DYNARE_STATEMENT>function_convergence_criterion {return token::FUNCTION_CONVERGENCE_CRITERION;}
<DYNARE_STATEMENT>parameter_convergence_criterion {return token::PARAMETER_CONVERGENCE_CRITERION;}
<DYNARE_STATEMENT>number_of_large_perturbations {return token::NUMBER_OF_LARGE_PERTURBATIONS;}
......@@ -561,19 +599,15 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>tolf {return token::TOLF;}
<DYNARE_STATEMENT>tolx {return token::TOLX;}
<DYNARE_STATEMENT>opt_algo {return token::OPT_ALGO;}
<DYNARE_STATEMENT>add_flags {return token::ADD_FLAGS;}
<DYNARE_STATEMENT>substitute_flags {return token::SUBSTITUTE_FLAGS;}
<DYNARE_STATEMENT>add_libs {return token::ADD_LIBS;}
<DYNARE_STATEMENT>substitute_libs {return token::SUBSTITUTE_LIBS;}
<DYNARE_STATEMENT>compiler {return token::COMPILER;}
<DYNARE_STATEMENT>instruments {return token::INSTRUMENTS;}
<DYNARE_STATEMENT>hessian {
yylval->build<string>(yytext);
return token::HESSIAN;
}
<DYNARE_STATEMENT>prior_variance {
yylval->build<string>(yytext);
return token::PRIOR_VARIANCE;
}
<DYNARE_STATEMENT>identity_matrix {
yylval->build<string>(yytext);
return token::IDENTITY_MATRIX;
}
<DYNARE_STATEMENT>hessian {return token::HESSIAN;}
<DYNARE_STATEMENT>prior_variance {return token::PRIOR_VARIANCE;}
<DYNARE_STATEMENT>identity_matrix {return token::IDENTITY_MATRIX;}
<DYNARE_STATEMENT>mcmc_jumping_covariance {return token::MCMC_JUMPING_COVARIANCE;}
/* These four (var, varexo, varexo_det, parameters) are for change_type */
......@@ -595,8 +629,21 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>homotopy_mode {return token::HOMOTOPY_MODE; }
<DYNARE_STATEMENT>homotopy_steps {return token::HOMOTOPY_STEPS; }
<DYNARE_STATEMENT>homotopy_force_continue {return token::HOMOTOPY_FORCE_CONTINUE;}
<DYNARE_STATEMENT>homotopy_max_completion_share {return token::HOMOTOPY_MAX_COMPLETION_SHARE;}
<DYNARE_STATEMENT>homotopy_min_step_size {return token::HOMOTOPY_MIN_STEP_SIZE;}
<DYNARE_STATEMENT>homotopy_initial_step_size {return token::HOMOTOPY_INITIAL_STEP_SIZE;}
<DYNARE_STATEMENT>homotopy_step_size_increase_success_count {return token::HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT;}
<DYNARE_STATEMENT>homotopy_linearization_fallback {return token::HOMOTOPY_LINEARIZATION_FALLBACK;}
<DYNARE_STATEMENT>homotopy_marginal_linearization_fallback {return token::HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK;}
<DYNARE_STATEMENT>homotopy_exclude_varexo {return token::HOMOTOPY_EXCLUDE_VAREXO;}
<DYNARE_STATEMENT>nocheck {return token::NOCHECK; }
<DYNARE_STATEMENT>steady_solve_algo {return token::STEADY_SOLVE_ALGO;}
<DYNARE_STATEMENT>steady_maxit {return token::STEADY_MAXIT;}
<DYNARE_STATEMENT>steady_tolf {return token::STEADY_TOLF;}
<DYNARE_STATEMENT>steady_tolx {return token::STEADY_TOLX;}
<DYNARE_STATEMENT>steady_markowitz {return token::STEADY_MARKOWITZ;}
<DYNARE_STATEMENT>controlled_varexo {return token::CONTROLLED_VAREXO; }
<DYNARE_STATEMENT>parameter_set {return token::PARAMETER_SET; }
<DYNARE_STATEMENT>init_state {return token::INIT_STATE; }
......@@ -625,8 +672,10 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>mle_mode {return token::MLE_MODE; }
<DYNARE_STATEMENT>k_order_solver {return token::K_ORDER_SOLVER; }
<DYNARE_STATEMENT>filter_covariance {return token::FILTER_COVARIANCE; }
<DYNARE_STATEMENT>updated_covariance {return token::UPDATED_COVARIANCE; }
<DYNARE_STATEMENT>filter_decomposition {return token::FILTER_DECOMPOSITION; }
<DYNARE_STATEMENT>smoothed_state_uncertainty {return token::SMOOTHED_STATE_UNCERTAINTY; }
<DYNARE_STATEMENT>smoother_redux {return token::SMOOTHER_REDUX; }
<DYNARE_STATEMENT>selected_variables_only {return token::SELECTED_VARIABLES_ONLY; }
<DYNARE_STATEMENT>pruning {return token::PRUNING; }
<DYNARE_STATEMENT>save_draws {return token::SAVE_DRAWS; }
......@@ -635,7 +684,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>epilogue {return token::EPILOGUE;}
<DYNARE_STATEMENT>growth_factor {return token::GROWTH_FACTOR;}
<DYNARE_STATEMENT>log_growth_factor {return token::LOG_GROWTH_FACTOR;}
<DYNARE_STATEMENT>growth {return token::GROWTH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>growth {return token::GROWTH;}
<DYNARE_STATEMENT>cova_compute {return token::COVA_COMPUTE;}
<DYNARE_STATEMENT>discretionary_tol {return token::DISCRETIONARY_TOL;}
<DYNARE_STATEMENT>analytic_derivation {return token::ANALYTIC_DERIVATION;}
......@@ -643,6 +692,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>solver_periods {return token::SOLVER_PERIODS;}
<DYNARE_STATEMENT>endogenous_prior {return token::ENDOGENOUS_PRIOR;}
<DYNARE_STATEMENT>consider_all_endogenous {return token::CONSIDER_ALL_ENDOGENOUS;}
<DYNARE_STATEMENT>consider_all_endogenous_and_auxiliary {return token::CONSIDER_ALL_ENDOGENOUS_AND_AUXILIARY;}
<DYNARE_STATEMENT>consider_only_observed {return token::CONSIDER_ONLY_OBSERVED;}
<DYNARE_STATEMENT>infile {return token::INFILE;}
<DYNARE_STATEMENT>invars {return token::INVARS;}
......@@ -655,25 +705,28 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>posterior_sampler_options {return token::POSTERIOR_SAMPLER_OPTIONS;}
<DYNARE_STATEMENT>silent_optimizer {return token::SILENT_OPTIMIZER;}
<DYNARE_STATEMENT>lmmcp {return token::LMMCP;}
<DYNARE_STATEMENT>occbin {return token::OCCBIN;}
<DYNARE_STATEMENT>centered_moments {return token::CENTERED_MOMENTS; }
<DYNARE_STATEMENT>autolag {return token::AUTOLAG; }
<DYNARE_STATEMENT>recursive_order_estimation {return token::RECURSIVE_ORDER_ESTIMATION; }
<DYNARE_STATEMENT>additional_optimizer_steps {return token::ADDITIONAL_OPTIMIZER_STEPS;}
<DYNARE_STATEMENT>bartlett_kernel_lag {return token::BARTLETT_KERNEL_LAG; }
<DYNARE_STATEMENT>optimal {
yylval->build<string>(yytext);
return token::OPTIMAL;
}
<DYNARE_STATEMENT>diagonal {
yylval->build<string>(yytext);
return token::DIAGONAL;
}
<DYNARE_STATEMENT>gmm {return token::GMM;}
<DYNARE_STATEMENT>smm {return token::SMM;}
<DYNARE_STATEMENT>irf_matching {return token::IRF_MATCHING;}
<DYNARE_STATEMENT>stoch_simul {return token::STOCH_SIMUL;}
<DYNARE_STATEMENT>weighting_matrix {return token::WEIGHTING_MATRIX; }
<DYNARE_STATEMENT>weighting_matrix_scaling_factor {return token::WEIGHTING_MATRIX_SCALING_FACTOR; }
<DYNARE_STATEMENT>analytic_standard_errors {return token::ANALYTIC_STANDARD_ERRORS; }
<DYNARE_STATEMENT>analytic_jacobian {return token::ANALYTIC_JACOBIAN; }
<DYNARE_STATEMENT>mom_method {return token::MOM_METHOD; }
<DYNARE_STATEMENT>simulation_method {return token::SIMULATION_METHOD; }
<DYNARE_STATEMENT>penalized_estimator {return token::PENALIZED_ESTIMATOR; }
<DYNARE_STATEMENT>verbose {return token::VERBOSE; }
<DYNARE_STATEMENT>simulation_multiple {return token::SIMULATION_MULTIPLE; }
<DYNARE_STATEMENT>burnin {return token::BURNIN; }
<DYNARE_STATEMENT>seed {return token::SEED; }
<DYNARE_STATEMENT>se_tolx {return token::SE_TOLX;}
<DYNARE_STATEMENT>bounded_shock_support {return token::BOUNDED_SHOCK_SUPPORT; }
<DYNARE_STATEMENT>irf_matching_file {return token::IRF_MATCHING_FILE;}
<DYNARE_STATEMENT>add_tiny_number_to_cholesky {return token::ADD_TINY_NUMBER_TO_CHOLESKY; }
<DYNARE_STATEMENT>analytical_girf {return token::ANALYTICAL_GIRF; }
<DYNARE_STATEMENT>irf_in_percent {return token::IRF_IN_PERCENT; }
<DYNARE_STATEMENT>emas_girf {return token::EMAS_GIRF; }
......@@ -693,22 +746,52 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>tol_sv {return token::TOL_SV;}
<DYNARE_STATEMENT>checks_via_subsets {return token::CHECKS_VIA_SUBSETS;}
<DYNARE_STATEMENT>max_dim_subsets_groups {return token::MAX_DIM_SUBSETS_GROUPS;}
<DYNARE_STATEMENT>max_nrows {return token::MAX_NROWS;}
<DYNARE_STATEMENT>with_epilogue {return token::WITH_EPILOGUE;}
<DYNARE_STATEMENT>heteroskedastic_filter {return token::HETEROSKEDASTIC_FILTER;}
<DYNARE_STATEMENT>non_zero {return token::NON_ZERO;}
<DYNARE_STATEMENT>preconditioner {return token::PRECONDITIONER;}
<DYNARE_STATEMENT>umfiter {return token::UMFITER;}
<DYNARE_STATEMENT>iterstack {return token::ITERSTACK;}
<DYNARE_STATEMENT>ilu {return token::ILU;}
<DYNARE_STATEMENT>iter_tol {return token::ITER_TOL;}
<DYNARE_STATEMENT>iter_maxit {return token::ITER_MAXIT;}
<DYNARE_STATEMENT>gmres_restart {return token::GMRES_RESTART;}
<DYNARE_STATEMENT>iterstack_maxlu {return token::ITERSTACK_MAXLU;}
<DYNARE_STATEMENT>iterstack_nperiods {return token::ITERSTACK_NPERIODS;}
<DYNARE_STATEMENT>iterstack_nlu {return token::ITERSTACK_NLU;}
<DYNARE_STATEMENT>iterstack_relu {return token::ITERSTACK_RELU;}
<DYNARE_STATEMENT>check_jacobian_singularity {return token::CHECK_JACOBIAN_SINGULARITY;}
<DYNARE_STATEMENT>\$[^$]*\$ {
strtok(yytext+1, "$");
yylval->build<string>(yytext + 1);
yylval->emplace<string>(yytext + 1).pop_back();
return token::TEX_NAME;
}
/* Inside a Dynare block */
<DYNARE_BLOCK>var {return token::VAR;}
<DYNARE_BLOCK>varexo {return token::VAREXO;}
<DYNARE_BLOCK>stderr {return token::STDERR;}
<DYNARE_BLOCK>values {return token::VALUES;}
<DYNARE_BLOCK>corr {return token::CORR;}
<DYNARE_BLOCK>periods {return token::PERIODS;}
<DYNARE_BLOCK>cutoff {return token::CUTOFF;}
<DYNARE_BLOCK>mfs {return token::MFS;}
<DYNARE_BLOCK>balanced_growth_test_tol {return token::BALANCED_GROWTH_TEST_TOL;}
<DYNARE_BLOCK>scales {return token::SCALES;}
<DYNARE_BLOCK>add {
yylval->emplace<string>(yytext);
return token::ADD;
}
<DYNARE_BLOCK>multiply {
yylval->emplace<string>(yytext);
return token::MULTIPLY;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>cutoff {return token::CUTOFF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>mfs {
yylval->emplace<string>(yytext);
return token::MFS;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>static_mfs {return token::STATIC_MFS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>balanced_growth_test_tol {return token::BALANCED_GROWTH_TEST_TOL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>heterogeneity {return token::HETEROGENEITY;}
<DYNARE_BLOCK>gamma_pdf {return token::GAMMA_PDF;}
<DYNARE_BLOCK>beta_pdf {return token::BETA_PDF;}
<DYNARE_BLOCK>normal_pdf {return token::NORMAL_PDF;}
......@@ -718,11 +801,52 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_BLOCK>uniform_pdf {return token::UNIFORM_PDF;}
<DYNARE_BLOCK>weibull_pdf {return token::WEIBULL_PDF;}
<DYNARE_BLOCK>dsge_prior_weight {return token::DSGE_PRIOR_WEIGHT;}
<DYNARE_BLOCK>surprise {return token::SURPRISE;}
<DYNARE_BLOCK>bind {
yylval->emplace<string>(yytext);
return token::BIND;
}
<DYNARE_BLOCK>relax {
yylval->emplace<string>(yytext);
return token::RELAX;
}
<DYNARE_BLOCK>error_bind {
yylval->emplace<string>(yytext);
return token::ERROR_BIND;
}
<DYNARE_BLOCK>error_relax {
yylval->emplace<string>(yytext);
return token::ERROR_RELAX;
}
<DYNARE_BLOCK>relative_to_initval {return token::RELATIVE_TO_INITVAL;}
<DYNARE_BLOCK>; {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_BLOCK># {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_BLOCK>restriction {return token::RESTRICTION;}
<DYNARE_BLOCK>component {return token::COMPONENT;}
<DYNARE_BLOCK>target {return token::TARGET;}
<DYNARE_BLOCK,DYNARE_STATEMENT>auxname {return token::AUXNAME;}
<DYNARE_BLOCK>auxname_target_nonstationary {return token::AUXNAME_TARGET_NONSTATIONARY;}
<DYNARE_BLOCK,DYNARE_STATEMENT>kind {
yylval->emplace<string>(yytext);
return token::KIND;
}
<DYNARE_BLOCK,DYNARE_STATEMENT>ll {
yylval->emplace<string>(yytext);
return token::LL;
}
<DYNARE_BLOCK,DYNARE_STATEMENT>dl {
yylval->emplace<string>(yytext);
return token::DL;
}
<DYNARE_BLOCK,DYNARE_STATEMENT>dd {
yylval->emplace<string>(yytext);
return token::DD;
}
<DYNARE_BLOCK>weights {return token::WEIGHTS;}
<DYNARE_BLOCK>exogenize {return token::EXOGENIZE;}
<DYNARE_BLOCK>endogenize {return token::ENDOGENIZE;}
/* Inside Dynare statement */
<DYNARE_STATEMENT>solve_algo {return token::SOLVE_ALGO;}
......@@ -732,16 +856,16 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>robust_lin_solve {return token::ROBUST_LIN_SOLVE;}
<DYNARE_STATEMENT>drop {return token::DROP;}
<DYNARE_STATEMENT>order {return token::ORDER;}
<DYNARE_STATEMENT>sylvester {return token::SYLVESTER;}
<DYNARE_STATEMENT>lyapunov {return token::LYAPUNOV;}
<DYNARE_STATEMENT>dr {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::DR;
}
<DYNARE_STATEMENT>sylvester_fixed_point_tol {return token::SYLVESTER_FIXED_POINT_TOL;}
<DYNARE_STATEMENT>lyapunov_complex_threshold {return token::LYAPUNOV_COMPLEX_THRESHOLD;}
<DYNARE_STATEMENT>lyapunov_fixed_point_tol {return token::LYAPUNOV_FIXED_POINT_TOL;}
<DYNARE_STATEMENT>lyapunov_doubling_tol {return token::LYAPUNOV_DOUBLING_TOL;}
<DYNARE_STATEMENT>dr_cycle_reduction_tol {return token::DR_CYCLE_REDUCTION_TOL;}
<DYNARE_STATEMENT>dr_cycle_reduction_maxiter {return token::DR_CYCLE_REDUCTION_MAXITER;}
<DYNARE_STATEMENT>dr_logarithmic_reduction_tol {return token::DR_LOGARITHMIC_REDUCTION_TOL;}
<DYNARE_STATEMENT>dr_logarithmic_reduction_maxiter {return token::DR_LOGARITHMIC_REDUCTION_MAXITER;}
<DYNARE_STATEMENT>replic {return token::REPLIC;}
......@@ -753,6 +877,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>one_sided_hp_filter {return token::ONE_SIDED_HP_FILTER;}
<DYNARE_STATEMENT>bandpass_filter {return token::BANDPASS_FILTER;}
<DYNARE_STATEMENT>hp_ngrid {return token::HP_NGRID;}
<DYNARE_STATEMENT>filtered_theoretical_moments_grid {return token::FILTERED_THEORETICAL_MOMENTS_GRID;}
<DYNARE_STATEMENT>simul_seed {return token::SIMUL_SEED;}
<DYNARE_STATEMENT>qz_criterium {return token::QZ_CRITERIUM;}
<DYNARE_STATEMENT>qz_zero_threshold {return token::QZ_ZERO_THRESHOLD;}
......@@ -762,10 +887,20 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>xls_range {return token::XLS_RANGE;}
<DYNARE_STATEMENT>series {return token::SERIES;}
<DYNARE_STATEMENT>mh_recover {return token::MH_RECOVER;}
<DYNARE_STATEMENT>mh_initialize_from_previous_mcmc {return token::MH_INITIALIZE_FROM_PREVIOUS_MCMC;}
<DYNARE_STATEMENT>mh_initialize_from_previous_mcmc_directory {return token::MH_INITIALIZE_FROM_PREVIOUS_MCMC_DIRECTORY;}
<DYNARE_STATEMENT>mh_initialize_from_previous_mcmc_record {return token::MH_INITIALIZE_FROM_PREVIOUS_MCMC_RECORD;}
<DYNARE_STATEMENT>mh_initialize_from_previous_mcmc_prior {return token::MH_INITIALIZE_FROM_PREVIOUS_MCMC_PRIOR;}
<DYNARE_STATEMENT>planner_discount {return token::PLANNER_DISCOUNT;}
<DYNARE_STATEMENT>planner_discount_latex_name {return token::PLANNER_DISCOUNT_LATEX_NAME;}
<DYNARE_STATEMENT>calibration {return token::CALIBRATION;}
<DYNARE_STATEMENT>irf_plot_threshold {return token::IRF_PLOT_THRESHOLD;}
<DYNARE_STATEMENT>no_homotopy {return token::NO_HOMOTOPY;}
<DYNARE_STATEMENT>particle_filter_options {return token::PARTICLE_FILTER_OPTIONS;}
<DYNARE_STATEMENT>constant_simulation_length {return token::CONSTANT_SIMULATION_LENGTH;}
<DYNARE_STATEMENT>block_static { return token::BLOCK_STATIC; }
<DYNARE_STATEMENT>block_dynamic { return token::BLOCK_DYNAMIC; }
<DYNARE_STATEMENT>incidence { return token::INCIDENCE; }
<DYNARE_BLOCK>stderr_multiples {return token::STDERR_MULTIPLES;}
<DYNARE_BLOCK>diagonal_only {return token::DIAGONAL_ONLY;}
......@@ -774,6 +909,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_BLOCK>lag {return token::LAG;}
<DYNARE_BLOCK>coeff {return token::COEFF;}
<DYNARE_BLOCK>overwrite {return token::OVERWRITE;}
<DYNARE_BLOCK>learnt_in {return token::LEARNT_IN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>upper_cholesky {return token::UPPER_CHOLESKY;}
<DYNARE_STATEMENT,DYNARE_BLOCK>lower_cholesky {return token::LOWER_CHOLESKY;}
<DYNARE_STATEMENT>chain {return token::CHAIN;}
......@@ -783,19 +919,28 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>coefficients {return token::COEFFICIENTS;}
<DYNARE_STATEMENT>variances {return token::VARIANCES;}
<DYNARE_STATEMENT>equations {return token::EQUATIONS;}
<DYNARE_STATEMENT>time_shift {return token::TIME_SHIFT;}
<DYNARE_STATEMENT>structural {return token::STRUCTURAL;}
<DYNARE_STATEMENT>true {
yylval->emplace<string>(yytext);
return token::TRUE;
}
<DYNARE_STATEMENT>false {
yylval->emplace<string>(yytext);
return token::FALSE;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>\. {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT>\\ {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT>\' {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_BLOCK>use_dll {return token::USE_DLL;}
<DYNARE_BLOCK>block {return token::BLOCK;}
<DYNARE_BLOCK>bytecode {return token::BYTECODE;}
<DYNARE_BLOCK>linear_decomposition {return token::LINEAR_DECOMPOSITION;}
<DYNARE_STATEMENT,DYNARE_BLOCK>use_dll {return token::USE_DLL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>block {return token::BLOCK;}
<DYNARE_STATEMENT,DYNARE_BLOCK>bytecode {return token::BYTECODE;}
<DYNARE_BLOCK>all_values_required {return token::ALL_VALUES_REQUIRED;}
<DYNARE_BLOCK>no_static {return token::NO_STATIC;}
<DYNARE_BLOCK>differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;}
<DYNARE_BLOCK>parallel_local_files {return token::PARALLEL_LOCAL_FILES;}
<DYNARE_STATEMENT,DYNARE_BLOCK>no_static {return token::NO_STATIC;}
<DYNARE_STATEMENT,DYNARE_BLOCK>differentiate_forward_vars {return token::DIFFERENTIATE_FORWARD_VARS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>parallel_local_files {return token::PARALLEL_LOCAL_FILES;}
<DYNARE_STATEMENT,DYNARE_BLOCK>linear {return token::LINEAR;}
......@@ -803,11 +948,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT,DYNARE_BLOCK>: {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT,DYNARE_BLOCK>[\(\)] {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT,DYNARE_BLOCK>\[ {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT,DYNARE_BLOCK>\] {
if (sigma_e)
sigma_e = 0;
return Dynare::parser::token_type (yytext[0]);
}
<DYNARE_STATEMENT,DYNARE_BLOCK>\] {return Dynare::parser::token_type (yytext[0]);}
<DYNARE_STATEMENT,DYNARE_BLOCK>\+ {return token::PLUS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>- {return token::MINUS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>\* {return token::TIMES;}
......@@ -819,6 +960,8 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT,DYNARE_BLOCK><= {return token::LESS_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>== {return token::EQUAL_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>!= {return token::EXCLAMATION_EQUAL;}
<DYNARE_BLOCK>\+= {return token::PLUS_EQUAL;}
<DYNARE_BLOCK>\*= {return token::TIMES_EQUAL;}
<DYNARE_STATEMENT,DYNARE_BLOCK>\^ {return token::POWER;}
<DYNARE_STATEMENT,DYNARE_BLOCK>exp {return token::EXP;}
<DYNARE_STATEMENT,DYNARE_BLOCK>log {return token::LOG;}
......@@ -830,6 +973,12 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT,DYNARE_BLOCK>asin {return token::ASIN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>acos {return token::ACOS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>atan {return token::ATAN;}
<DYNARE_STATEMENT,DYNARE_BLOCK>sinh {return token::SINH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>cosh {return token::COSH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>tanh {return token::TANH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>asinh {return token::ASINH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>acosh {return token::ACOSH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>atanh {return token::ATANH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>sqrt {return token::SQRT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>cbrt {return token::CBRT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>max {return token::MAX;}
......@@ -839,17 +988,21 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT,DYNARE_BLOCK>normcdf {return token::NORMCDF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>normpdf {return token::NORMPDF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>erf {return token::ERF;}
<DYNARE_STATEMENT,DYNARE_BLOCK>erfc {return token::ERFC;}
<DYNARE_STATEMENT,DYNARE_BLOCK>steady_state {return token::STEADY_STATE;}
<DYNARE_STATEMENT,DYNARE_BLOCK>expectation {return token::EXPECTATION;}
<DYNARE_BLOCK>var_expectation {return token::VAR_EXPECTATION;}
<DYNARE_BLOCK>pac_expectation {return token::PAC_EXPECTATION;}
<DYNARE_BLOCK>pac_target_nonstationary {return token::PAC_TARGET_NONSTATIONARY;}
<DYNARE_BLOCK>sum {return token::SUM;}
<DYNARE_STATEMENT>discount {return token::DISCOUNT;}
<DYNARE_STATEMENT>steady_state_growth {return token::STEADY_STATE_GROWTH;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varobs {return token::VAROBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>varexobs {return token::VAREXOBS;}
<DYNARE_STATEMENT,DYNARE_BLOCK>nan {return token::NAN_CONSTANT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>inf {return token::INF_CONSTANT;}
<DYNARE_STATEMENT,DYNARE_BLOCK>constants {return token::CONSTANTS;}
<DYNARE_BLOCK>⟂ {return token::PERPENDICULAR;}
<DYNARE_BLOCK>_\|_ {return token::PERPENDICULAR;}
/* options for GSA module by Marco Ratto */
<DYNARE_STATEMENT>identification {return token::IDENTIFICATION;}
......@@ -897,38 +1050,27 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<DYNARE_STATEMENT>use_shock_groups {return token::USE_SHOCK_GROUPS;}
<DYNARE_STATEMENT>colormap {return token::COLORMAP;}
<DYNARE_STATEMENT,DYNARE_BLOCK>[a-z_][a-z0-9_]* {
yylval->build<string>(yytext);
<DYNARE_STATEMENT,DYNARE_BLOCK>{NAME} {
yylval->emplace<string>(yytext);
return token::NAME;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+[ed][-+]?[0-9]+) {
yylval->build<string>(yytext);
<DYNARE_STATEMENT,DYNARE_BLOCK>{FLOAT_NUMBER} {
yylval->emplace<string>(yytext);
return token::FLOAT_NUMBER;
}
<DYNARE_STATEMENT,DYNARE_BLOCK>[0-9]+ {
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::INT_NUMBER;
}
<DATES_STATEMENT>\( { yylval->as<string>().append(yytext); dates_parens_nb++; }
<DATES_STATEMENT>\) {
yylval->as<string>().append(yytext);
if (--dates_parens_nb == 0)
{
BEGIN DYNARE_STATEMENT;
return token::DATES;
}
}
<DATES_STATEMENT>. { yylval->as<string>().append(yytext); }
<DYNARE_BLOCK>\|e { return token::PIPE_E; }
<DYNARE_BLOCK>\|x { return token::PIPE_X; }
<DYNARE_BLOCK>\|p { return token::PIPE_P; }
<DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']+\' {
yylval->build<string>(yytext + 1).pop_back();
<DYNARE_STATEMENT,DYNARE_BLOCK>\'[^\']*\' {
yylval->emplace<string>(yytext + 1).pop_back();
return token::QUOTED_STRING;
}
......@@ -960,11 +1102,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
element in initval (in which case Dynare recognizes the matrix name as an external
function symbol), and may want to modify the matrix later with Matlab statements.
*/
<INITIAL>[a-z_][a-z0-9_]* {
<INITIAL>{NAME} {
if (driver.symbol_exists_and_is_not_modfile_local_or_external_function(yytext))
{
BEGIN DYNARE_STATEMENT;
yylval->build<string>(yytext);
yylval->emplace<string>(yytext);
return token::NAME;
}
else
......@@ -975,11 +1117,18 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
}
}
/* For joint prior statement, match [symbol, symbol, ...]
/*
For joint prior statement, match [symbol, symbol, ...]
If no match, begin native and push everything back on stack
We produce SYMBOL_VEC in Flex (instead of matching `'[' symbol_list ']'`
in Bison because the pattern also matches potential native statements
(e.g. function returns from a MATLAB/Octave function). Hence, we need to
be able to back out of the statement if we realize it's a native statement
and move to the NATIVE context
*/
<INITIAL>\[([[:space:]]*[a-z_][a-z0-9_]*[[:space:]]*,{1}[[:space:]]*)*([[:space:]]*[a-z_][a-z0-9_]*[[:space:]]*){1}\] {
string yytextcpy = string(yytext);
<INITIAL>\[([[:space:]]*{NAME}[[:space:]]*,{1}[[:space:]]*)*([[:space:]]*{NAME}[[:space:]]*){1}\] {
string yytextcpy{yytext};
yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), '['), yytextcpy.end());
yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), ']'), yytextcpy.end());
yytextcpy.erase(remove(yytextcpy.begin(), yytextcpy.end(), ' '), yytextcpy.end());
......@@ -1002,7 +1151,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
if (dynare_statement)
{
BEGIN DYNARE_STATEMENT;
yylval->build<vector<string>>(val);
yylval->emplace<vector<string>>(val);
return token::SYMBOL_VEC;
}
}
......@@ -1018,7 +1167,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
\"[^\"\n]*\" |
\.{1,2} |
\* |
\/ { yymore(); eofbuff = string(yytext); }
\/ { yymore(); eofbuff = yytext; }
\.{3,}[[:space:]]*\n { driver.add_native_remove_charset(yytext, "\n"); }
\n {
if (strlen(yytext) > 1)
......@@ -1047,11 +1196,13 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
<NATIVE_COMMENT>"*/"[[:space:]]*\n { BEGIN NATIVE; }
<NATIVE_COMMENT>.
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,DATES_STATEMENT,LINE1,LINE2,LINE3,NATIVE_COMMENT><<EOF>> { yyterminate(); }
<INITIAL,DYNARE_STATEMENT,DYNARE_BLOCK,COMMENT,LINE1,LINE2,LINE3,NATIVE_COMMENT><<EOF>> { yyterminate(); }
<*>. { driver.error(*yylloc, "character unrecognized by lexer"); }
%%
#pragma GCC diagnostic pop
DynareFlex::DynareFlex(istream* in, ostream* out)
: DynareFlexLexer{in, out}
{
......
/*
* Copyright © 2003-2019 Dynare Team
* Copyright © 2003-2023 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,62 +14,62 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <regex>
#include <thread>
#include <vector>
#include <cstdlib>
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION 4.
#endif
#include <unistd.h>
#include "ParsingDriver.hh"
#include "Configuration.hh"
#include "ExtendedPreprocessorTypes.hh"
#include "ConfigFile.hh"
#include "ModFile.hh"
#include "ParsingDriver.hh"
/* Prototype for second part of main function
Splitting main() in two parts was necessary because ParsingDriver.h and MacroDriver.h can't be
/* Prototype for the function that handles the macro-expansion of the .mod file
Splitting this out was necessary because ParsingDriver.hh and macro/Driver.hh can't be
included simultaneously (because of Bison limitations).
Function can be found in: MacroExpandModFile.cc
*/
void main2(stringstream &in, const string &basename, bool debug, bool clear_all, bool clear_global,
bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console,
bool nograph, bool nointeractive, bool parallel, const ConfigFile &config_file,
WarningConsolidation &warnings_arg, bool nostrict, bool stochastic, bool check_model_changes,
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
LanguageOutputType lang, int params_derivs_order, bool transform_unary_ops,
const string &exclude_eqs, const string &include_eqs,
JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple,
const string &mexext, const filesystem::path &matlabroot,
const filesystem::path &dynareroot, bool onlymodel);
void main1(const string &filename, const string &basename, istream &modfile, bool debug, bool save_macro, string &save_macro_file,
bool no_line_macro, bool no_empty_line_macro, const vector<pair<string, string>> &defines,
vector<filesystem::path> &paths, stringstream &macro_output);
stringstream macroExpandModFile(const filesystem::path& filename, const istream& modfile,
bool debug, bool save_macro, filesystem::path save_macro_file,
bool line_macro, const vector<pair<string, string>>& defines,
vector<filesystem::path> paths);
void
usage()
{
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=matlab|julia]"
<< " [params_derivs_order=0|1|2] [transform_unary_ops] [exclude_eqs=<equation_tag_list_or_file>] [include_eqs=<equation_tag_list_or_file>]"
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]"
<< " [mexext=<extension>] [matlabroot=<path>] [onlymodel]"
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] "
"[savemacro[=macro_file]] [onlymacro] [linemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] "
"[conffile=path_to_config_file] [parallel_follower_open_mode] "
"[parallel_test] [parallel_use_psexec=true|false]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] "
"[compute_xrefs] [output=first|second|third] [language=matlab|julia]"
<< " [params_derivs_order=0|1|2] [transform_unary_ops] "
"[exclude_eqs=<equation_tag_list_or_file>] [include_eqs=<equation_tag_list_or_file>]"
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] "
"[nopathchange] [nopreprocessoroutput]"
<< " [mexext=<extension>] [matlabroot=<path>] [onlymodel] [notime] [use_dll] "
"[nocommutativity]"
<< endl;
exit(EXIT_FAILURE);
}
/* Looks for an options list in the first line of the mod file (but rewind
the input stream afterwards */
/* Looks for an options list in the first non-empty line of the .mod file (but rewind
the input stream afterwards).
This function should be kept in sync with the one with the same name in matlab/dynare.m */
vector<string>
parse_options_line(istream& modfile)
{
......@@ -79,16 +79,15 @@ parse_options_line(istream &modfile)
smatch matches;
while (getline(modfile, first_nonempty_line))
if (first_nonempty_line != "")
if (!first_nonempty_line.empty())
{
if (regex_search(first_nonempty_line, matches, pat))
if (matches.size() > 1 && matches[1].matched)
if (regex_search(first_nonempty_line, matches, pat) && matches.size() > 1
&& matches[1].matched)
{
regex pat2{R"(([^,\s]+))"};
regex pat2 {R"([^,\s]+)"};
string s {matches[1]};
for (sregex_iterator p(s.begin(), s.end(), pat2);
p != sregex_iterator{}; ++p)
options.push_back((*p)[1]);
for (sregex_iterator p(s.begin(), s.end(), pat2); p != sregex_iterator {}; ++p)
options.push_back(p->str());
}
break;
}
......@@ -114,11 +113,11 @@ main(int argc, char **argv)
usage();
}
string filename = argv[1];
const filesystem::path filename {argv[1]};
ifstream modfile(filename, ios::binary);
if (modfile.fail())
{
cerr << "ERROR: Could not open file: " << argv[1] << endl;
cerr << "ERROR: Could not open file: " << filename.string() << endl;
exit(EXIT_FAILURE);
}
......@@ -128,37 +127,39 @@ main(int argc, char **argv)
options.emplace_back(argv[arg]);
// Parse options
bool notime = false;
bool clear_all = true;
bool clear_global = false;
bool save_macro = false;
string save_macro_file;
filesystem::path save_macro_file;
bool debug = false;
bool no_tmp_terms = false;
bool only_macro = false;
bool no_line_macro = false;
bool no_empty_line_macro = false;
bool no_log = false;
bool line_macro = false;
bool no_warn = false;
int params_derivs_order = 2;
bool warn_uninit = false;
bool console = false;
bool nograph = false;
bool nointeractive = false;
string parallel_config_file;
filesystem::path conffile;
bool parallel = false;
string cluster_name;
bool parallel_slave_open_mode = false;
bool parallel_follower_open_mode
= false; // Must be the same default as in matlab/default_option_values.m
bool parallel_test = false;
bool parallel_use_psexec = true; // Must be the same default as in matlab/default_option_values.m
bool nostrict = false;
bool stochastic = false;
bool check_model_changes = false;
bool minimal_workspace = false;
bool compute_xrefs = false;
bool transform_unary_ops = false;
bool gui = false;
string exclude_eqs, include_eqs;
vector<pair<string, string>> defines;
vector<filesystem::path> paths;
FileOutputType output_mode{FileOutputType::none};
OutputType output_mode {OutputType::standard};
JsonOutputPointType json {JsonOutputPointType::nojson};
JsonFileOutputType json_output_mode {JsonFileOutputType::file};
bool onlyjson = false;
......@@ -166,15 +167,15 @@ main(int argc, char **argv)
LanguageOutputType language {LanguageOutputType::matlab};
string mexext;
filesystem::path matlabroot;
filesystem::path dynareroot{argv[0]};
dynareroot = dynareroot.parent_path();
dynareroot = dynareroot / ".." / "..";
bool onlymodel = false;
bool use_dll = false;
for (auto s : options)
{
if (s == "debug")
debug = true;
else if (s == "notime")
notime = true;
else if (s == "noclearall")
clear_all = false;
else if (s.substr(0, 19) == "params_derivs_order")
......@@ -207,14 +208,15 @@ main(int argc, char **argv)
save_macro_file = s.substr(10);
}
}
else if (s == "nolinemacro")
no_line_macro = true;
else if (s == "noemptylinemacro")
no_empty_line_macro = true;
else if (s == "linemacro")
line_macro = true;
else if (s == "notmpterms")
no_tmp_terms = true;
else if (s == "nolog")
no_log = true;
{
// Do nothing, the option is implemented at the dynare.m level.
// We nevertheless accept it, to avoid an “unknown option” error.
}
else if (s == "nowarn")
no_warn = true;
else if (s == "warn_uninit")
......@@ -232,12 +234,33 @@ main(int argc, char **argv)
cerr << "Incorrect syntax for conffile option" << endl;
usage();
}
parallel_config_file = s.substr(9);
conffile = s.substr(9);
}
else if (s == "parallel_slave_open_mode")
parallel_slave_open_mode = true;
else if (s == "parallel_follower_open_mode"
|| s == "parallel_slave_open_mode") // Kept for backward compatibility, see #86
parallel_follower_open_mode = true;
else if (s == "parallel_test")
parallel_test = true;
else if (s.substr(0, 19) == "parallel_use_psexec")
{
if (s.length() <= 20 || s.at(19) != '=')
{
cerr << "Incorrect syntax for parallel_use_psexec option" << endl;
usage();
}
s.erase(0, 20);
if (s == "true")
parallel_use_psexec = true;
else if (s == "false")
parallel_use_psexec = false;
else
{
cerr << "Incorrect syntax for parallel_use_psexec option" << endl;
usage();
}
}
else if (s == "nostrict")
nostrict = true;
else if (s == "stochastic")
......@@ -272,11 +295,10 @@ main(int argc, char **argv)
usage();
}
auto equal_index = s.find('=');
if (equal_index != string::npos)
if (auto equal_index = s.find('='); equal_index != string::npos)
defines.emplace_back(s.substr(2, equal_index - 2), s.substr(equal_index + 1));
else
defines.emplace_back(s.substr(2), "1");
defines.emplace_back(s.substr(2), "true");
}
else if (s.substr(0, 2) == "-I")
{
......@@ -286,7 +308,7 @@ main(int argc, char **argv)
<< "must not be separated from -I by whitespace." << endl;
usage();
}
paths.push_back(s.substr(2));
paths.emplace_back(s.substr(2));
}
else if (s.substr(0, 6) == "output")
{
......@@ -298,14 +320,12 @@ main(int argc, char **argv)
s.erase(0, 7);
if (s == "dynamic")
output_mode = FileOutputType::dynamic;
else if (s == "first")
output_mode = FileOutputType::first;
if (s == "first")
output_mode = OutputType::first;
else if (s == "second")
output_mode = FileOutputType::second;
output_mode = OutputType::second;
else if (s == "third")
output_mode = FileOutputType::third;
output_mode = OutputType::third;
else
{
cerr << "Incorrect syntax for output option" << endl;
......@@ -402,6 +422,12 @@ main(int argc, char **argv)
}
else if (s == "onlymodel")
onlymodel = true;
else if (s == "gui")
gui = true;
else if (s == "use_dll")
use_dll = true;
else if (s == "nocommutativity")
DataTree::setNoCommutativity();
else
{
cerr << "Unknown option: " << s << endl;
......@@ -411,29 +437,49 @@ main(int argc, char **argv)
cout << "Starting preprocessing of the model file ..." << endl;
// Determine root of Dynare installation
const filesystem::path argv0 {argv[0]};
// Normal case: binary is in preprocessor/dynare-preprocessor(.exe)?
filesystem::path dynareroot = argv0.parent_path().parent_path();
if (argv0.filename().stem() == "dynare_m")
// Special case: backward compatibility location in matlab/preprocessor64/dynare_m(.exe)?
dynareroot = dynareroot.parent_path();
// Construct basename (i.e. remove file extension if there is one)
string basename = argv[1];
size_t pos = basename.find_last_of('.');
if (pos != string::npos)
basename.erase(pos);
/* Calling string() method on filename.stem(): not necessary on GNU/Linux and macOS because there
is an implicit conversion from filesystem:path to string (i.e. basic_string<char>), but needed
on Windows because the implicit conversion is only to wstring (i.e. basic_string<wchar_t>). */
const string basename {filename.stem().string()};
// Forbid some basenames, since they will cause trouble (see preprocessor#62)
set<string> forbidden_basenames = {"T", "y", "x", "params", "steady_state", "it_", "true"};
if (forbidden_basenames.contains(basename))
{
cerr << "ERROR: Please use another name for your .mod file. The one you have chosen ("
<< argv[1] << ") conflicts with internal Dynare names." << endl;
exit(EXIT_FAILURE);
}
WarningConsolidation warnings(no_warn);
// Process config file
ConfigFile config_file(parallel, parallel_test, parallel_slave_open_mode, cluster_name);
config_file.getConfigFileInfo(parallel_config_file);
config_file.checkPass(warnings);
config_file.transformPass();
Configuration config {parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec,
cluster_name};
config.getConfigFileInfo(conffile, warnings);
config.checkPass(warnings);
config.transformPass();
// If Include option was passed to the [paths] block of the config file, add
// it to paths before macroprocessing
for (const auto &it : config_file.getIncludePaths())
for (const auto& it : config.getIncludePaths())
paths.emplace_back(it);
// Do macro processing
stringstream macro_output;
main1(filename, basename, modfile, debug, save_macro, save_macro_file, no_line_macro, no_empty_line_macro,
defines, paths, macro_output);
/*
* Macro-expand MOD file
*/
stringstream macro_output
= macroExpandModFile(filename, modfile, debug, save_macro, move(save_macro_file), line_macro,
defines, move(paths));
if (only_macro)
return EXIT_SUCCESS;
......@@ -444,13 +490,67 @@ main(int argc, char **argv)
exit(EXIT_FAILURE);
}
// Do the rest
main2(macro_output, basename, debug, clear_all, clear_global,
no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace,
compute_xrefs, output_mode, language, params_derivs_order, transform_unary_ops, exclude_eqs, include_eqs,
json, json_output_mode, onlyjson, jsonderivsimple,
mexext, matlabroot, dynareroot, onlymodel);
/*
* Process Macro-expanded MOD file
*/
ParsingDriver p(warnings, nostrict);
filesystem::remove_all(basename + "/model/json");
// Do parsing and construct internal representation of mod file
unique_ptr<ModFile> mod_file = p.parse(macro_output, debug);
// Handle use_dll option specified on the command line
if (use_dll)
mod_file->use_dll = true;
if (mod_file->use_dll && language == LanguageOutputType::julia)
{
cerr << "ERROR: `use_dll` option is not compatible with Julia" << endl;
exit(EXIT_FAILURE);
}
if (mod_file->use_dll)
ModelTree::initializeMEXCompilationWorkers(max(jthread::hardware_concurrency(), 1U), dynareroot,
mexext);
if (json == JsonOutputPointType::parsing)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Run checking pass
mod_file->checkPass(nostrict, stochastic);
if (json == JsonOutputPointType::checkpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Perform transformations on the model (creation of auxiliary vars and equations)
mod_file->transformPass(nostrict, stochastic,
compute_xrefs || json == JsonOutputPointType::transformpass,
transform_unary_ops, exclude_eqs, include_eqs);
if (json == JsonOutputPointType::transformpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Evaluate parameters initialization, initval, endval and pounds
mod_file->evalAllExpressions(warn_uninit);
// Do computations
mod_file->computingPass(no_tmp_terms, output_mode, params_derivs_order);
if (json == JsonOutputPointType::computingpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, jsonderivsimple);
// Write output files
if (language == LanguageOutputType::julia)
mod_file->writeJuliaOutput(basename);
else
mod_file->writeMOutput(basename, clear_all, clear_global, no_warn, console, nograph,
nointeractive, config, check_model_changes, minimal_workspace,
compute_xrefs, mexext, matlabroot, onlymodel, gui, notime);
/* Ensures that workers are not destroyed before they finish compiling.
Also ensures that the preprocessor final message is printed after the end of
compilation (and is not printed in case of compilation failure). */
if (mod_file->use_dll)
ModelTree::waitForMEXCompilationWorkers();
cout << "Preprocessing completed." << endl;
return EXIT_SUCCESS;
}
/*
* Copyright © 2008-2019 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <filesystem>
#include "ParsingDriver.hh"
#include "ModFile.hh"
#include "ConfigFile.hh"
#include "ExtendedPreprocessorTypes.hh"
void
main2(stringstream &in, const string &basename, bool debug, bool clear_all, bool clear_global,
bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console,
bool nograph, bool nointeractive, bool parallel, const ConfigFile &config_file,
WarningConsolidation &warnings, bool nostrict, bool stochastic, bool check_model_changes,
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
LanguageOutputType language, int params_derivs_order, bool transform_unary_ops,
const string &exclude_eqs, const string &include_eqs,
JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple,
const string &mexext, const filesystem::path &matlabroot,
const filesystem::path &dynareroot, bool onlymodel)
{
ParsingDriver p(warnings, nostrict);
filesystem::remove_all(basename + "/model/json");
// Do parsing and construct internal representation of mod file
unique_ptr<ModFile> mod_file = p.parse(in, debug);
if (json == JsonOutputPointType::parsing)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Run checking pass
mod_file->checkPass(nostrict, stochastic);
if (json == JsonOutputPointType::checkpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Perform transformations on the model (creation of auxiliary vars and equations)
mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == JsonOutputPointType::transformpass,
transform_unary_ops, exclude_eqs, include_eqs);
if (json == JsonOutputPointType::transformpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson);
// Evaluate parameters initialization, initval, endval and pounds
mod_file->evalAllExpressions(warn_uninit);
// Do computations
mod_file->computingPass(no_tmp_terms, output_mode, params_derivs_order);
if (json == JsonOutputPointType::computingpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, jsonderivsimple);
// Write outputs
if (output_mode != FileOutputType::none)
mod_file->writeExternalFiles(basename, language);
else
mod_file->writeOutputFiles(basename, clear_all, clear_global, no_log, no_warn, console, nograph,
nointeractive, config_file, check_model_changes, minimal_workspace, compute_xrefs,
mexext, matlabroot, dynareroot, onlymodel);
cout << "Preprocessing completed." << endl;
}
/*
* Copyright © 2020-2025 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include "EquationTags.hh"
#include <ostream>
#include <regex>
#include <utility>
set<int>
EquationTags::getEqnsByKey(const string& key) const
{
set<int> retval;
for (const auto& [eqn, tags] : eqn_tags)
if (tags.contains(key))
retval.insert(eqn);
return retval;
}
set<int>
EquationTags::getEqnsByTag(const string& key, const string& value) const
{
set<int> retval;
for (const auto& [eqn, tags] : eqn_tags)
if (auto tmp = tags.find(key); tmp != tags.end() && tmp->second == value)
retval.insert(eqn);
return retval;
}
optional<int>
EquationTags::getEqnByTag(const string& key, const string& value) const
{
for (const auto& [eqn, tags] : eqn_tags)
if (auto tmp = tags.find(key); tmp != tags.end() && tmp->second == value)
return eqn;
return nullopt;
}
set<int>
EquationTags::getEqnsByTags(const map<string, string>& tags_selected) const
{
set<int> retval;
for (const auto& [eqn, tags] : eqn_tags)
{
for (const auto& [key, value] : tags_selected)
if (auto tmp = tags.find(key); tmp == tags.end() || tmp->second != value)
goto next_eq;
retval.insert(eqn);
next_eq:;
}
return retval;
}
void
EquationTags::erase(const set<int>& eqns, const map<int, int>& old_eqn_num_2_new)
{
for (int eqn : eqns)
eqn_tags.erase(eqn);
for (const auto& [oldeqn, neweqn] : old_eqn_num_2_new)
if (eqn_tags.contains(oldeqn))
{
auto tmp = eqn_tags.extract(oldeqn);
tmp.key() = neweqn;
eqn_tags.insert(move(tmp));
}
}
void
EquationTags::writeCheckSumInfo(ostream& output) const
{
for (const auto& [eqn, tags] : eqn_tags)
for (const auto& [key, value] : tags)
output << " " << eqn + 1 << key << " " << value << endl;
}
void
EquationTags::writeOutput(ostream& output) const
{
output << "M_.equations_tags = {" << endl;
for (const auto& [eqn, tags] : eqn_tags)
for (const auto& [key, value] : tags)
output << " " << eqn + 1 << " , '" << key << "' , '" << value << "' ;" << endl;
output << "};" << endl;
}
void
EquationTags::writeLatexOutput(ostream& output, int eqn) const
{
if (!eqn_tags.contains(eqn))
return;
auto escape_special_latex_symbols = [](string str) {
const regex special_latex_chars(R"([&%$#_{}])");
const regex backslash(R"(\\)");
const regex tilde(R"(~)");
const regex carrot(R"(\^)");
const regex textbackslash(R"(\\textbackslash)");
str = regex_replace(str, backslash, R"(\textbackslash)");
str = regex_replace(str, special_latex_chars, R"(\$&)");
str = regex_replace(str, carrot, R"(\^{})");
str = regex_replace(str, tilde, R"(\textasciitilde{})");
return regex_replace(str, textbackslash, R"(\textbackslash{})");
};
output << R"(\noindent[)";
for (bool wrote_eq_tag {false}; const auto& [key, value] : eqn_tags.at(eqn))
{
if (exchange(wrote_eq_tag, true))
output << ", ";
output << escape_special_latex_symbols(key);
if (!value.empty())
output << "= `" << escape_special_latex_symbols(value) << "'";
}
output << "]" << endl;
}
void
EquationTags::writeJsonAST(ostream& output, int eqn) const
{
if (!eqn_tags.contains(eqn))
return;
output << R"(, "tags": {)";
for (bool wroteFirst {false}; const auto& [key, value] : eqn_tags.at(eqn))
{
if (exchange(wroteFirst, true))
output << ", ";
output << R"(")" << key << R"(": ")" << value << R"(")";
}
output << "}";
}
/*
* Copyright © 2020-2023 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef EQUATION_TAGS_HH
#define EQUATION_TAGS_HH
#include <map>
#include <optional>
#include <set>
#include <string>
using namespace std;
class EquationTags
{
private:
map<int, map<string, string>> eqn_tags;
public:
// Add multiple equation tags for the given equation
void
add(int eqn, map<string, string> tags)
{
if (eqn_tags.contains(eqn))
eqn_tags[eqn].insert(move_iterator {tags.begin()}, move_iterator {tags.end()});
else
eqn_tags[eqn] = move(tags);
}
//! Add a single equation tag for the given equation
void
add(int eqn, string key, string value)
{
eqn_tags[eqn][move(key)] = move(value);
}
//! Clear all equation tag information
void
clear()
{
eqn_tags.clear();
}
//! Erase tags for given equations, using old_eqn_num_2_new as the mapping
//! to use for the remaining equation numbers
void erase(const set<int>& eqns, const map<int, int>& old_eqn_num_2_new);
//! Various functions to get info from equation tags
//! Get equation tags for a given equation
[[nodiscard]] map<string, string>
getTagsByEqn(int eqn) const
{
if (auto it = eqn_tags.find(eqn); it != eqn_tags.end())
return it->second;
return {};
}
//! Get equations that have the given key
[[nodiscard]] set<int> getEqnsByKey(const string& key) const;
//! Get equations that have the given key and value
[[nodiscard]] set<int> getEqnsByTag(const string& key, const string& value) const;
//! Get the first equation that has the given key and value
[[nodiscard]] optional<int> getEqnByTag(const string& key, const string& value) const;
// Get equations that have all the given keys and values (seen as a conjunction)
[[nodiscard]] set<int> getEqnsByTags(const map<string, string>& tags_selected) const;
//! Get the tag value given the equation number and key
[[nodiscard]] optional<string>
getTagValueByEqnAndKey(int eqn, const string& key) const
{
if (auto it = eqn_tags.find(eqn); it != eqn_tags.end())
if (auto it2 = it->second.find(key); it2 != it->second.end())
return it2->second;
return nullopt;
}
//! Get the equations marked dynamic
[[nodiscard]] set<int>
getDynamicEqns() const
{
return getEqnsByTag("dynamic", "");
}
//! Returns true if equation tag with key and value exists
[[nodiscard]] bool
exists(const string& key, const string& value) const
{
return getEqnByTag(key, value).has_value();
}
//! Returns true if equation tag with key exists for a given equation
[[nodiscard]] bool
exists(int eqn, const string& key) const
{
auto it = eqn_tags.find(eqn);
return it != eqn_tags.end() && it->second.contains(key);
}
//! Various functions to write equation tags
void writeCheckSumInfo(ostream& output) const;
void writeOutput(ostream& output) const;
void writeLatexOutput(ostream& output, int eqn) const;
void writeJsonAST(ostream& output, int eq) const;
};
#endif
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/*
* Copyright © 2007-2019 Dynare Team
* Copyright © 2007-2025 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,24 +14,28 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EXPR_NODE_HH
#define _EXPR_NODE_HH
#ifndef EXPR_NODE_HH
#define EXPR_NODE_HH
#include <set>
#include <concepts>
#include <functional>
#include <map>
#include <vector>
#include <optional>
#include <ostream>
#include <functional>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
#include "SymbolTable.hh"
#include "CodeInterpreter.hh"
#include "Bytecode.hh"
#include "CommonEnums.hh"
#include "ExternalFunctionsTable.hh"
#include "SymbolList.hh"
class DataTree;
class NumConstNode;
......@@ -49,18 +53,14 @@ struct ExprNodeLess;
see the definition of ExprNodeLess */
using temporary_terms_t = set<expr_t, ExprNodeLess>;
/*! Keeps track of array indices of temporary_terms for writing */
using temporary_terms_idxs_t = map<expr_t, int>;
//! set of temporary terms used in a block
using temporary_terms_inuse_t = set<int>;
using map_idx_t = map<int, int>;
using temporary_terms_idxs_t = unordered_map<expr_t, int>;
//! Type for evaluation contexts
/*! The key is a symbol id. Lags are assumed to be null */
using eval_context_t = map<int, double>;
//! Type for tracking first/second derivative functions that have already been written as temporary terms
//! Type for tracking first/second derivative functions that have already been written as temporary
//! terms
using deriv_node_temp_terms_t = map<pair<int, vector<expr_t>>, int>;
//! Type for the substitution map used for creating aux. vars for diff and unary_ops
......@@ -85,64 +85,84 @@ using deriv_node_temp_terms_t = map<pair<int, vector<expr_t>>, int>;
expressions with which they should be substituted. */
using lag_equivalence_table_t = map<expr_t, map<int, expr_t>>;
//! Possible types of output when writing ExprNode(s)
//! Possible types of output when writing ExprNode(s) (not used for bytecode)
enum class ExprNodeOutputType
{
matlabStaticModel, //!< Matlab code, static model
matlabDynamicModel, //!< Matlab code, dynamic model
matlabStaticModelSparse, //!< Matlab code, static block decomposed model
matlabDynamicModelSparse, //!< Matlab code, dynamic block decomposed model
CDynamicModel, //!< C code, dynamic model
CStaticModel, //!< C code, static model
juliaStaticModel, //!< Julia code, static model
juliaDynamicModel, //!< Julia code, dynamic model
matlabStaticModel, //!< Matlab code, static model, legacy representation
matlabDynamicModel, //!< Matlab code, dynamic model, legacy representation
matlabSparseStaticModel, //!< Matlab code, static model, sparse representation
matlabSparseDynamicModel, //!< Matlab code, dynamic model, sparse representation
CDynamicModel, //!< C code, dynamic model, legacy representation
CStaticModel, //!< C code, static model, legacy representation
CSparseDynamicModel, //!< C code, dynamic model, sparse representation
CSparseStaticModel, //!< C code, static model, sparse representation
juliaStaticModel, //!< Julia code, static model, legacy representation
juliaDynamicModel, //!< Julia code, dynamic model, legacy representation
juliaSparseStaticModel, //!< Julia code, static model, sparse representation
juliaSparseDynamicModel, //!< Julia code, dynamic model, sparse representation
matlabOutsideModel, //!< Matlab code, outside model block (for example in initval)
latexStaticModel, //!< LaTeX code, static model
latexDynamicModel, //!< LaTeX code, dynamic model
latexDynamicSteadyStateOperator, //!< LaTeX code, dynamic model, inside a steady state operator
matlabDynamicSteadyStateOperator, //!< Matlab code, dynamic model, inside a steady state operator
matlabDynamicSparseSteadyStateOperator, //!< Matlab code, dynamic block decomposed model, inside a steady state operator
CDynamicSteadyStateOperator, //!< C code, dynamic model, inside a steady state operator
juliaDynamicSteadyStateOperator, //!< Julia code, dynamic model, inside a steady state operator
steadyStateFile, //!< Matlab code, in the generated steady state file
juliaSteadyStateFile, //!< Julia code, in the generated steady state file
matlabDseries, //!< Matlab code for dseries
epilogueFile //!< Matlab code, in the generated epilogue file
juliaTimeDataFrame, //!< Julia code for TimeDataFrame objects
epilogueFile, //!< Matlab code, in the generated epilogue file
occbinDifferenceFile //!< MATLAB, in the generated occbin_difference file
};
// Possible types of output when writing ExprNode(s) in bytecode
enum class ExprNodeBytecodeOutputType
{
dynamicModel,
staticModel,
dynamicSteadyStateOperator, // Inside a steady_state operator
dynamicAssignmentLHS, // Assignment of a dynamic variable on the LHS of a (recursive) equation
staticAssignmentLHS // Assignment of a static variable on the LHS of a (recursive) equation
};
inline bool
constexpr bool
isMatlabOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::matlabStaticModel
|| output_type == ExprNodeOutputType::matlabDynamicModel
|| output_type == ExprNodeOutputType::matlabSparseStaticModel
|| output_type == ExprNodeOutputType::matlabSparseDynamicModel
|| output_type == ExprNodeOutputType::matlabOutsideModel
|| output_type == ExprNodeOutputType::matlabStaticModelSparse
|| output_type == ExprNodeOutputType::matlabDynamicModelSparse
|| output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::matlabDynamicSparseSteadyStateOperator
|| output_type == ExprNodeOutputType::steadyStateFile
|| output_type == ExprNodeOutputType::matlabDseries
|| output_type == ExprNodeOutputType::epilogueFile;
|| output_type == ExprNodeOutputType::epilogueFile
|| output_type == ExprNodeOutputType::occbinDifferenceFile;
}
inline bool
constexpr bool
isJuliaOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::juliaStaticModel
|| output_type == ExprNodeOutputType::juliaDynamicModel
|| output_type == ExprNodeOutputType::juliaSparseStaticModel
|| output_type == ExprNodeOutputType::juliaSparseDynamicModel
|| output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::juliaSteadyStateFile;
|| output_type == ExprNodeOutputType::juliaSteadyStateFile
|| output_type == ExprNodeOutputType::juliaTimeDataFrame;
}
inline bool
constexpr bool
isCOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::CDynamicModel
|| output_type == ExprNodeOutputType::CStaticModel
|| output_type == ExprNodeOutputType::CSparseDynamicModel
|| output_type == ExprNodeOutputType::CSparseStaticModel
|| output_type == ExprNodeOutputType::CDynamicSteadyStateOperator;
}
inline bool
constexpr bool
isLatexOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::latexStaticModel
......@@ -150,17 +170,66 @@ isLatexOutput(ExprNodeOutputType output_type)
|| output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator;
}
constexpr bool
isSteadyStateOperatorOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::CDynamicSteadyStateOperator
|| output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator;
}
constexpr bool
isSparseModelOutput(ExprNodeOutputType output_type)
{
return output_type == ExprNodeOutputType::matlabSparseStaticModel
|| output_type == ExprNodeOutputType::matlabSparseDynamicModel
|| output_type == ExprNodeOutputType::juliaSparseStaticModel
|| output_type == ExprNodeOutputType::juliaSparseDynamicModel
|| output_type == ExprNodeOutputType::CSparseDynamicModel
|| output_type == ExprNodeOutputType::CSparseStaticModel;
}
constexpr bool
isAssignmentLHSBytecodeOutput(ExprNodeBytecodeOutputType output_type)
{
return output_type == ExprNodeBytecodeOutputType::staticAssignmentLHS
|| output_type == ExprNodeBytecodeOutputType::dynamicAssignmentLHS;
}
/* Equal to 1 for Matlab langage or Julia, or to 0 for C language. Not defined for LaTeX.
In Matlab and Julia, array indexes begin at 1, while they begin at 0 in C */
#define ARRAY_SUBSCRIPT_OFFSET(output_type) (static_cast<int>(isMatlabOutput(output_type) || isJuliaOutput(output_type)))
constexpr int
ARRAY_SUBSCRIPT_OFFSET(ExprNodeOutputType output_type)
{
return static_cast<int>(isMatlabOutput(output_type) || isJuliaOutput(output_type));
}
// Left and right array subscript delimiters: '(' and ')' for Matlab, '[' and ']' for C
#define LEFT_ARRAY_SUBSCRIPT(output_type) (isMatlabOutput(output_type) ? '(' : '[')
#define RIGHT_ARRAY_SUBSCRIPT(output_type) (isMatlabOutput(output_type) ? ')' : ']')
constexpr char
LEFT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)
{
return isMatlabOutput(output_type) ? '(' : '[';
}
constexpr char
RIGHT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)
{
return isMatlabOutput(output_type) ? ')' : ']';
}
// Left and right parentheses
#define LEFT_PAR(output_type) (isLatexOutput(output_type) ? "\\left(" : "(")
#define RIGHT_PAR(output_type) (isLatexOutput(output_type) ? "\\right)" : ")")
inline string
LEFT_PAR(ExprNodeOutputType output_type)
{
return isLatexOutput(output_type) ? "\\left(" : "(";
}
inline string
RIGHT_PAR(ExprNodeOutputType output_type)
{
return isLatexOutput(output_type) ? "\\right)" : ")";
}
//! Base class for expression nodes
class ExprNode
......@@ -178,11 +247,20 @@ class ExprNode
friend class AbstractExternalFunctionNode;
friend class VarExpectationNode;
friend class PacExpectationNode;
private:
//! Computes derivative w.r. to a derivation ID (but doesn't store it in derivatives map)
/*! You shoud use getDerivative() to get the benefit of symbolic a priori and of caching */
virtual expr_t computeDerivative(int deriv_id) = 0;
/* Internal helper for getChainRuleDerivative(), that does the computation
but assumes that the caching of this is handled elsewhere */
virtual expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache)
= 0;
protected:
//! Reference to the enclosing DataTree
DataTree& datatree;
......@@ -201,21 +279,38 @@ class ExprNode
constexpr static int min_cost_matlab {40 * 90};
constexpr static int min_cost_c {40 * 4};
inline static int min_cost(bool is_matlab) { return(is_matlab ? min_cost_matlab : min_cost_c); };
constexpr static int
min_cost(bool is_matlab)
{
return is_matlab ? min_cost_matlab : min_cost_c;
}
//! Initializes data member non_null_derivatives
virtual void prepareForDerivation() = 0;
/* Computes the derivatives which are potentially non-null, using symbolic a
priori, similarly to prepareForDerivation(), but in a chain rule
derivation context. See getChainRuleDerivation() for the meaning of
“recursive_variables”. Note that all non-endogenous variables are
automatically considered to have a zero derivative (since they’re never
used in a chain rule context) */
virtual void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const
= 0;
//! Cost of computing current node
/*! Nodes included in temporary_terms are considered having a null cost */
virtual int cost(int cost, bool is_matlab) const;
virtual int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const;
virtual int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const;
[[nodiscard]] virtual int cost(int cost, bool is_matlab) const;
[[nodiscard]] virtual int
cost(const vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms, bool is_matlab) const;
[[nodiscard]] virtual int cost(const map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab) const;
//! For creating equation cross references
struct EquationInfo
{
set<pair<int, int>> param;
set<pair<int, int>> endo;
set<pair<int, int>> exo;
set<pair<int, int>> exo_det;
set<pair<int, int>> param, endo, exo, exo_det;
};
//! If this node is a temporary term, writes its temporary term representation
......@@ -225,41 +320,70 @@ class ExprNode
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs) const;
// Same as above, for the bytecode case
bool
checkIfTemporaryTermThenWriteBytecode(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs) const;
// Internal helper for matchVariableTimesConstantTimesParam()
virtual void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const;
virtual void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id,
double& constant, bool at_denominator) const;
/* Computes the representative element and the index under the
lag-equivalence relationship. See the comment above
lag_equivalence_table_t for an explanation of these concepts. */
pair<expr_t, int> getLagEquivalenceClass() const;
[[nodiscard]] pair<expr_t, int> getLagEquivalenceClass() const;
/* Computes the set of all sub-expressions that contain the variable
(symb_id, lag).
Note that if a diff operator is encountered:
- diff(expr) will be added to the output set if either expr or expr(-1)
contains the variable;
- the method will be called recursively on expr-expr(-1) */
virtual void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const
= 0;
public:
ExprNode(DataTree& datatree_arg, int idx_arg);
virtual ~ExprNode() = default;
ExprNode(const ExprNode&) = delete;
ExprNode(ExprNode &&) = delete;
ExprNode& operator=(const ExprNode&) = delete;
ExprNode & operator=(ExprNode &&) = delete;
//! Initializes data member non_null_derivatives
virtual void prepareForDerivation() = 0;
//! Returns derivative w.r. to derivation ID
/*! Uses a symbolic a priori to pre-detect null derivatives, and caches the result for other derivatives (to avoid computing it several times)
For an equal node, returns the derivative of lhs minus rhs */
/*! Uses a symbolic a priori to pre-detect null derivatives, and caches the result for other
derivatives (to avoid computing it several times) For an equal node, returns the derivative of
lhs minus rhs */
expr_t getDerivative(int deriv_id);
//! Computes derivatives by applying the chain rule for some variables
/*!
\param deriv_id The derivation ID with respect to which we are derivating
\param recursive_variables Contains the derivation ID for which chain rules must be applied. Keys are derivation IDs, values are equations of the form x=f(y) where x is the key variable and x doesn't appear in y
*/
virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) = 0;
/* Computes derivatives by applying the chain rule for some variables.
— “recursive_variables” contains the derivation ID for which chain rules
must be applied. Keys are derivation IDs, values are equations of the
form x=f(y) where x is the key variable and x doesn't appear in y
— “non_null_chain_rule_derivatives” is used to store the indices of
variables that are potentially non-null (using symbolic a priori),
similarly to ExprNode::non_null_derivatives.
— “cache” is used to store already-computed derivatives (in a map
<expression, deriv_id> → derivative)
NB: always returns zero when “deriv_id” corresponds to a non-endogenous
variable (since such variables are never used in a chain rule context).
NB 2: “non_null_chain_rule_derivatives” and “cache” are specific to a given
value of “recursive_variables”, and thus should not be reused accross
calls that use different values of “recursive_variables”.
NB 3: the use of std::unordered_map instead of std::map for caching
purposes improves performance on very very large models (tens of thousands
of equations) */
expr_t getChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache);
//! Returns precedence of node
/*! Equals 100 for constants, variables, unary ops, and temporary terms */
virtual int precedence(ExprNodeOutputType output_t, const temporary_terms_t &temporary_terms) const;
[[nodiscard]] virtual int precedence(ExprNodeOutputType output_t,
const temporary_terms_t& temporary_terms) const;
//! Compute temporary terms in this expression
/*!
......@@ -276,13 +400,37 @@ class ExprNode
A node will be marked as a temporary term if it is referenced at least
two times (i.e. has at least two parents), and has a computing cost
(multiplied by reference count) greater to datatree.min_cost
NB: the use of std::unordered_map instead of std::map for caching
purposes improves performance on very large models (⩾5000 equations)
*/
virtual void computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const;
virtual void computeTemporaryTerms(
const pair<int, int>& derivOrder, map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count, bool is_matlab) const;
//! Compute temporary terms in this expression for block decomposed model
/*!
\param[in] blk the block number
\param[in] eq the equation number (within the block)
\param[out] blocks_temporary_terms the computed temporary terms, per block
and per equation in the block
\param[out] reference_count a temporary structure, used to count
references to each node (first integer is the
reference count, second integer is the number of the block in which the
expression first appears, third integer is the equation number within the block)
Same rules as computeTemporaryTerms() for computing cost.
NB: the use of std::unordered_{set,map} instead of std::{set,map} for caching
and output improves performance on very large models (⩾5000 equations)
*/
virtual void
computeBlockTemporaryTerms(int blk, int eq,
vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const;
//! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the set of already written external functions
//! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the
//! set of already written external functions
/*!
\param[in] output the output stream
\param[in] output_type the type of output (MATLAB, C, LaTeX...)
......@@ -292,10 +440,14 @@ class ExprNode
when writing MATLAB with block decomposition)
\param[in] tef_terms the set of already written external function nodes
*/
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const = 0;
virtual void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const
= 0;
//! returns true if the expr node contains an external function
virtual bool containsExternalFunction() const = 0;
[[nodiscard]] virtual bool containsExternalFunction() const = 0;
//! Writes output of node (with no temporary terms and with "outside model" output type)
void writeOutput(ostream& output) const;
......@@ -304,17 +456,26 @@ class ExprNode
void writeOutput(ostream& output, ExprNodeOutputType output_type) const;
//! Writes output of node, using a Txxx notation for nodes in temporary_terms
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs) const;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs) const;
//! Writes output of node in JSON syntax
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const = 0;
virtual void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms,
bool isdynamic = true) const
= 0;
// Returns a string representation of the expression, used by the GDB pretty printer
[[nodiscard]] string toString() const;
//! Writes the Abstract Syntax Tree in JSON
virtual void writeJsonAST(ostream& output) const = 0;
virtual int precedenceJson(const temporary_terms_t &temporary_terms) const;
[[nodiscard]] virtual int precedenceJson(const temporary_terms_t& temporary_terms) const;
//! Writes the output for an external function, ensuring that the external function is called as few times as possible using temporary terms
//! Writes the output for an external function, ensuring that the external function is called as
//! few times as possible using temporary terms
virtual void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -325,14 +486,15 @@ class ExprNode
virtual void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic = true) const;
bool isdynamic = true) const;
virtual void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
virtual void writeBytecodeExternalFunctionOutput(
Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const;
//! Computes the set of all variables of a given symbol type in the expression (with information on lags)
//! Computes the set of all variables of a given symbol type in the expression (with information
//! on lags)
/*!
Variables are stored as integer pairs of the form (symb_id, lag).
They are added to the set given in argument.
......@@ -341,16 +503,14 @@ class ExprNode
*/
virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const = 0;
//! Find lowest lag for VAR
virtual int VarMinLag() const = 0;
//! Find the maximum lag in a VAR: handles case where LHS is diff
virtual int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const = 0;
[[nodiscard]] virtual int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const = 0;
//! Finds LHS variable in a VAR equation
virtual void collectVARLHSVariable(set<expr_t>& result) const = 0;
//! Computes the set of all variables of a given symbol type in the expression (without information on lags)
//! Computes the set of all variables of a given symbol type in the expression (without
//! information on lags)
/*!
Variables are stored as symb_id.
They are added to the set given in argument.
......@@ -365,103 +525,94 @@ class ExprNode
They are added to the set given in argument.
Note that model local variables are substituted by their expression in the computation.
*/
virtual void collectEndogenous(set<pair<int, int>> &result) const;
//! Computes the set of exogenous variables in the expression
/*!
Exogenous are stored as integer pairs of the form (type_specific_id, lag).
They are added to the set given in argument.
Note that model local variables are substituted by their expression in the computation.
*/
virtual void collectExogenous(set<pair<int, int>> &result) const;
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const = 0;
virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const;
void collectEndogenous(set<pair<int, int>>& result) const;
class EvalException
{
};
class EvalExternalFunctionException : public EvalException
{
};
virtual double eval(const eval_context_t &eval_context) const noexcept(false) = 0;
virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const = 0;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic) const;
[[nodiscard]] virtual double eval(const eval_context_t& eval_context) const noexcept(false) = 0;
// Write output to bytecode file
virtual void writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const
= 0;
//! Creates a static version of this node
/*!
This method duplicates the current node by creating a similar node from which all leads/lags have been stripped,
adds the result in the static_datatree argument (and not in the original datatree), and returns it.
This method duplicates the current node by creating a similar node from which all leads/lags
have been stripped, adds the result in the static_datatree argument (and not in the original
datatree), and returns it.
*/
virtual expr_t toStatic(DataTree& static_datatree) const = 0;
/*!
Compute cross references for equations
*/
// virtual void computeXrefs(set<int> &param, set<int> &endo, set<int> &exo, set<int> &exo_det) const = 0;
// virtual void computeXrefs(set<int> &param, set<int> &endo, set<int> &exo, set<int> &exo_det)
// const = 0;
virtual void computeXrefs(EquationInfo& ei) const = 0;
//! Try to normalize an equation linear in its endogenous variable
virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const = 0;
//! Returns the maximum lead of endogenous in this expression
/*! Always returns a non-negative value */
virtual int maxEndoLead() const = 0;
//! Helper for normalization of equations
/*! Normalize the equation this = rhs.
Must be called on a node containing the desired LHS variable.
Returns an equal node of the form: LHS variable = new RHS.
Must be given the set of all subexpressions that contain the desired LHS variable.
Throws a NormallizationFailed() exception if normalization is not possible. */
virtual BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const
= 0;
class NormalizationFailed
{
};
//! Returns the maximum lead of exogenous in this expression
//! Returns the maximum lead of endogenous in this expression (not incl. heterogeneous endo)
/*! Always returns a non-negative value */
virtual int maxExoLead() const = 0;
[[nodiscard]] virtual int maxEndoLead() const = 0;
//! Returns the maximum lag of endogenous in this expression
//! Returns the maximum lead of exogenous in this expression (not incl. heterogeneous exo)
/*! Always returns a non-negative value */
virtual int maxEndoLag() const = 0;
[[nodiscard]] virtual int maxExoLead() const = 0;
//! Returns the maximum lag of exogenous in this expression
//! Returns the maximum lag of endogenous in this expression (not incl. heterogeneous endo)
/*! Always returns a non-negative value */
virtual int maxExoLag() const = 0;
[[nodiscard]] virtual int maxEndoLag() const = 0;
//! Returns the maximum lead of endo/exo/exodet in this expression
/*! A negative value means that the expression contains only lagged
variables. A value of numeric_limits<int>::min() means that there is
no variable. */
virtual int maxLead() const = 0;
//! Returns the maximum lag of endo/exo/exodet in this expression
/*! A negative value means that the expression contains only leaded
variables. A value of numeric_limits<int>::min() means that there is
no variable. */
virtual int maxLag() const = 0;
//! Returns the maximum lag of exogenous in this expression (not incl. heterogeneous exo)
/*! Always returns a non-negative value */
[[nodiscard]] virtual int maxExoLag() const = 0;
//! Returns the maximum lag of endo/exo/exodet, as if diffs were expanded
/*! This function behaves as maxLag(), except that it treats diff()
differently. For e.g., on diff(diff(x(-1))), maxLag() returns 1 while
maxLagWithDiffsExpanded() returns 3. */
virtual int maxLagWithDiffsExpanded() const = 0;
/* Returns the maximum lead of endo/exo/exodet in this expression (including heterogeneous
endo/exo). A negative value means that the expression contains only lagged variables. A value
of numeric_limits<int>::min() means that there is no variable. */
[[nodiscard]] virtual int maxLead() const = 0;
//! Get Max lag of var associated with Pac model
//! Takes account of undiffed LHS variables in calculating the max lag
virtual int PacMaxLag(int lhs_symb_id) const = 0;
/* Returns the maximum lag of endo/exo/exodet in this expression (including heterogeneous
endo/exo). A negative value means that the expression contains only leaded variables. A value
of numeric_limits<int>::min() means that there is no variable. */
[[nodiscard]] virtual int maxLag() const = 0;
//! Get the target variable of the PAC model
virtual int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const = 0;
/* Returns the maximum lag of endo/exo/exodet (including heterogeneous endo/exo), as if diffs were
expanded. This function behaves as maxLag(), except that it treats diff() differently. For
e.g., on diff(diff(x(-1))), maxLag() returns 1 while maxLagWithDiffsExpanded() returns 3. */
[[nodiscard]] virtual int maxLagWithDiffsExpanded() const = 0;
virtual expr_t undiff() const = 0;
[[nodiscard]] virtual expr_t undiff() const = 0;
//! Returns a new expression where all the leads/lags have been shifted backwards by the same amount
//! Returns a new expression where all the leads/lags have been shifted backwards by the same
//! amount
/*!
Only acts on endogenous, exogenous, exogenous det
\param[in] n The number of lags by which to shift
\return The same expression except that leads/lags have been shifted backwards
*/
virtual expr_t decreaseLeadsLags(int n) const = 0;
[[nodiscard]] virtual expr_t decreaseLeadsLags(int n) const = 0;
//! Type for the substitution map used in the process of creating auxiliary vars
using subst_table_t = map<const ExprNode*, const VariableNode*>;
......@@ -471,102 +622,135 @@ class ExprNode
//! Creates auxiliary endo lead variables corresponding to this expression
/*!
If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table.
\pre This expression is assumed to have maximum endogenous lead >= 2
\param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\return The new variable node corresponding to the current expression
If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and
will add the equations of the form aux1 = aux2(+1) to the substitution table. \pre This
expression is assumed to have maximum endogenous lead >= 2 \param[in,out] subst_table The table
to which new auxiliary variables and their correspondance will be added \param[out] neweqs
Equations to be added to the model to match the creation of auxiliary variables. \return The new
variable node corresponding to the current expression
*/
VariableNode *createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
VariableNode* createEndoLeadAuxiliaryVarForMyself(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const;
//! Creates auxiliary exo lead variables corresponding to this expression
/*!
If maximum exogenous lead >= 2, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table.
\pre This expression is assumed to have maximum exogenous lead >= 1
\param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\return The new variable node corresponding to the current expression
If maximum exogenous lead >= 2, this method will also create intermediary auxiliary var, and
will add the equations of the form aux1 = aux2(+1) to the substitution table. \pre This
expression is assumed to have maximum exogenous lead >= 1 \param[in,out] subst_table The table
to which new auxiliary variables and their correspondance will be added \param[out] neweqs
Equations to be added to the model to match the creation of auxiliary variables. \return The new
variable node corresponding to the current expression
*/
VariableNode *createExoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
VariableNode* createExoLeadAuxiliaryVarForMyself(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const;
//! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables
//! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced
//! by auxiliary variables
/*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\param[in,out] subst_table Map used to store expressions that have already be substituted and
their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables.
If the method detects a sub-expr which needs to be substituted, two cases are possible:
- if this expr is in the table, then it will use the corresponding variable and return the substituted expression
- if this expr is not in the table, then it will create an auxiliary endogenous variable, add the substitution in the table and return the substituted expression
- if this expr is in the table, then it will use the corresponding variable and return the
substituted expression
- if this expr is not in the table, then it will create an auxiliary endogenous variable, add
the substitution in the table and return the substituted expression
\return A new equivalent expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables
\return A new equivalent expression where sub-expressions with max endo lead >= 2 have been
replaced by auxiliary variables
*/
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const = 0;
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const
= 0;
//! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by auxiliary variables
//! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by
//! auxiliary variables
/*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\param[in,out] subst_table Map used to store expressions that have already be substituted and
their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables.
*/
virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
//! Constructs a new expression where exogenous variables with a lead have been replaced by auxiliary variables
//! Constructs a new expression where exogenous variables with a lead have been replaced by
//! auxiliary variables
/*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\param[in,out] subst_table Map used to store expressions that have already be substituted and
their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables.
*/
virtual expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const = 0;
//! Constructs a new expression where exogenous variables with a lag have been replaced by auxiliary variables
virtual expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const
= 0;
//! Constructs a new expression where exogenous variables with a lag have been replaced by
//! auxiliary variables
/*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\param[in,out] subst_table Map used to store expressions that have already be substituted and
their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables.
*/
virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
virtual expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const
= 0;
//! Constructs a new expression where the expectation operator has been replaced by auxiliary variables
//! Constructs a new expression where the expectation operator has been replaced by auxiliary
//! variables
/*!
\param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\param[in] partial_information_model Are we substituting in a partial information model?
\param[in,out] subst_table Map used to store expressions that have already be substituted and
their corresponding variable, in order to avoid creating two auxiliary variables for the same
sub-expr. \param[out] neweqs Equations to be added to the model to match the creation of
auxiliary variables. \param[in] partial_information_model Are we substituting in a partial
information model?
*/
virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const = 0;
virtual expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const
= 0;
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const = 0;
[[nodiscard]] virtual expr_t decreaseLeadsLagsPredeterminedVariables() const = 0;
//! Constructs a new expression where forward variables (supposed to be at most in t+1) have been replaced by themselves at t, plus a new aux var representing their (time) differentiate
//! Constructs a new expression where forward variables (supposed to be at most in t+1) have been
//! replaced by themselves at t, plus a new aux var representing their (time) differentiate
/*!
\param[in] subset variables to which to limit the transformation; transform
all fwrd vars if empty
\param[in,out] subst_table Map used to store mapping between a given
forward variable and the aux var that contains its differentiate
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary
variables.
*/
virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
virtual expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
//! Return true if the nodeID is a numerical constant equal to value and false otherwise
/*!
\param[in] value of the numerical constante
\param[out] the boolean equal to true if NodeId is a constant equal to value
*/
virtual bool isNumConstNodeEqualTo(double value) const = 0;
//! Returns true if the expression contains one or several endogenous variable
virtual bool containsEndogenous() const = 0;
//! Returns true if the expression contains one or several exogenous variable
virtual bool containsExogenous() const = 0;
[[nodiscard]] virtual bool isNumConstNodeEqualTo(double value) const = 0;
//! Returns the maximum number of nested diffs in the expression
virtual int countDiffs() const = 0;
[[nodiscard]] virtual int countDiffs() const = 0;
//! Return true if the nodeID is a variable withe a type equal to type_arg, a specific variable id aqual to varfiable_id and a lag equal to lag_arg and false otherwise
//! Return true if the nodeID is a variable withe a type equal to type_arg, a specific variable id
//! aqual to varfiable_id and a lag equal to lag_arg and false otherwise
/*!
\param[in] the type (type_arg), specifique variable id (variable_id and the lag (lag_arg)
\param[out] the boolean equal to true if NodeId is the variable
*/
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const = 0;
[[nodiscard]] virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const
= 0;
//! Replaces the Trend var with datatree.One
virtual expr_t replaceTrendVar() const = 0;
[[nodiscard]] virtual expr_t replaceTrendVar() const = 0;
//! Constructs a new expression where the variable indicated by symb_id has been detrended
/*!
......@@ -578,10 +762,15 @@ class ExprNode
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0;
//! Substitute adl operator
virtual expr_t substituteAdl() const = 0;
[[nodiscard]] virtual expr_t substituteAdl() const = 0;
//! Substitute out model-local variables
[[nodiscard]] virtual expr_t substituteModelLocalVariables() const = 0;
//! Substitute VarExpectation nodes
virtual expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const = 0;
[[nodiscard]] virtual expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const
= 0;
//! Mark diff nodes to be substituted
/*! The various nodes that are equivalent up to a shift of leads/lags are
......@@ -589,7 +778,9 @@ class ExprNode
lag_equivalence_table_t for more details. */
virtual void findDiffNodes(lag_equivalence_table_t& nodes) const = 0;
//! Substitute diff operator
virtual expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
virtual expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
//! Mark unary ops nodes to be substituted
/*! The various nodes that are equivalent up to a shift of leads/lags are
......@@ -597,60 +788,96 @@ class ExprNode
lag_equivalence_table_t for more details. */
virtual void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const = 0;
//! Substitute unary ops nodes
virtual expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
virtual expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes,
subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
//! Substitute pac_expectation operator
virtual expr_t substitutePacExpectation(const string& name, expr_t subexpr) = 0;
virtual int findTargetVariable(int lhs_symb_id) const = 0;
//! Substitute pac_target_nonstationary operator
virtual expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) = 0;
[[nodiscard]] virtual optional<int> findTargetVariable(int lhs_symb_id) const = 0;
//! Add ExprNodes to the provided datatree
virtual expr_t clone(DataTree &datatree) const = 0;
virtual expr_t clone(DataTree& alt_datatree) const = 0;
//! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
virtual expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const = 0;
//! Returns true if the expression is in static form (no lead, no lag, no expectation, no STEADY_STATE)
virtual bool isInStaticForm() const = 0;
[[nodiscard]] virtual expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const
= 0;
//! Substitute auxiliary variables by their expression in static model
virtual expr_t substituteStaticAuxiliaryVariable() const = 0;
//! Returns true if the expression is in static form (no lead, no lag, no expectation, no
//! STEADY_STATE)
[[nodiscard]] virtual bool isInStaticForm() const = 0;
//! Returns true if model_info_name is referenced by a VarExpectationNode
virtual bool isVarModelReferenced(const string &model_info_name) const = 0;
//! Matches a linear combination of variables, where scalars can be constant*parameter
//! Matches a linear combination of variables (endo or exo), where scalars can be
//! constant*parameter
/*! Returns a list of (variable_id, lag, param_id, constant)
corresponding to the terms in the expression. When there is no
parameter in a term, param_id == -1.
parameter in a term, param_id is nullopt.
Can throw a MatchFailureException.
if `variable_obligatory_in_each_term` is true, then every part of the linear combination must contain a variable;
otherwise, if `variable_obligatory_in_each_term`, then any linear combination of constant/variable/param is matched
*/
vector<tuple<int, int, int, double>> matchLinearCombinationOfVariables(bool variable_obligatory_in_each_term = true) const;
[[nodiscard]] vector<tuple<int, int, optional<int>, double>>
matchLinearCombinationOfVariables() const;
pair<int, vector<tuple<int, int, int, double>>> matchParamTimesLinearCombinationOfVariables() const;
/* Matches a linear combination of variables (endo or exo), where scalars can
be constant*parameter. In addition, there may be one or more scalar terms
(i.e. without a variable).
Returns a list of (variable_id, lag, param_id, constant)
corresponding to the terms in the expression. When there is no
parameter in a term, param_id is nullopt. When the term is scalar (i.e.
no variable), then variable_id is nullopt.
Can throw a MatchFailureException.
*/
[[nodiscard]] vector<tuple<optional<int>, int, optional<int>, double>>
matchLinearCombinationOfVariablesPlusConstant() const;
/* Matches a parameter, times a linear combination of variables (endo or
exo), where scalars can be constant*parameters.
The first output argument is the symbol ID of the parameter.
The second output argument is the linear combination, in the same format
as the output of matchLinearCombinationOfVariables(). */
[[nodiscard]] pair<int, vector<tuple<int, int, optional<int>, double>>>
matchParamTimesLinearCombinationOfVariables() const;
/* Matches a linear combination of endogenous, where scalars can be any
constant expression (i.e. containing no endogenous, no exogenous and no
exogenous deterministic). The linear combination can contain constant
terms (intercept).
Returns a pair composed of:
– the terms of the form endogenous*scalar, as a list of (endo_id, constant expr);
– the sum of all constant (intercept) terms */
[[nodiscard]] pair<vector<pair<int, expr_t>>, expr_t>
matchLinearCombinationOfEndogenousWithConstant() const;
/* Matches an expression of the form parameter*(var1-endo2).
endo2 must correspond to symb_id. var1 must be an endogenous or an
exogenous; it must be of the form X(-1) or log(X(-1)) or log(X)(-1) (unary ops aux var),
where X itself is *not* an aux var.
Returns the symbol IDs of the parameter and of var1.
Throws a MatchFailureException otherwise */
[[nodiscard]] pair<int, int> matchParamTimesTargetMinusVariable(int symb_id) const;
//! Returns true if expression is of the form:
//! param * (endog op endog op ...) + param * (endog op endog op ...) + ...
virtual bool isParamTimesEndogExpr() const = 0;
[[nodiscard]] virtual bool isParamTimesEndogExpr() const = 0;
//! Fills the EC matrix structure
void fillErrorCorrectionRow(int eqn, const vector<int> &nontarget_lhs, const vector<int> &target_lhs,
map<tuple<int, int, int>, expr_t> &A0,
map<tuple<int, int, int>, expr_t> &A0star) const;
void fillErrorCorrectionRow(int eqn, const vector<int>& nontarget_lhs,
const vector<int>& target_lhs, map<tuple<int, int>, expr_t>& A0,
map<tuple<int, int>, expr_t>& A0star) const;
//! Finds equations where a variable is equal to a constant
virtual void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const = 0;
//! Replaces variables found in findConstantEquations() with their constant values
//! Replaces variables found in BinaryOpNode::findConstantEquations() with their constant values
virtual expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const = 0;
//! Returns true if PacExpectationNode encountered
virtual bool containsPacExpectation(const string &pac_model_name = "") const = 0;
[[nodiscard]] virtual bool containsPacExpectation(const string& pac_model_name = "") const = 0;
//! Fills map
virtual void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const = 0;
//! Returns true if PacTargetNonstationaryNode encountered
[[nodiscard]] virtual bool containsPacTargetNonstationary(const string& pac_model_name = "") const
= 0;
//! Decompose an expression into its additive terms
/*! Returns a list of terms, with their sign (either 1 or -1, depending
......@@ -659,27 +886,72 @@ class ExprNode
If current_sign == -1, then all signs are inverted */
virtual void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign = 1) const;
//! Decompose an expression into its multiplicative factors
/*! Returns a list of factors, with their exponents (either 1 or -1, depending
on whether the factors appear at the numerator or the denominator).
The current_exponent argument should normally be left to 1.
If current_exponent == -1, then all exponents are inverted */
virtual void decomposeMultiplicativeFactors(vector<pair<expr_t, int>>& factors,
int current_exponent = 1) const;
// Matches an expression of the form variable*constant*parameter
/* Returns a tuple (variable_id, lag, param_id, constant).
The variable must be an exogenous or an endogenous.
If `variable_obligatory` is true, then the expression must contain a variable.
If present, the variable must be an exogenous or an endogenous. If absent,
and `variable_obligatory` is false, then variable_id is nullopt.
The constant is optional (in which case 1 is returned); there can be
several multiplicative constants; constants can also appear at the
denominator (i.e. after a divide sign).
The parameter is optional (in which case param_id == -1).
The parameter is optional (in which case param_id is nullopt).
If the expression is not of the expected form, throws a
MatchFailureException
if `variable_obligatory` is true, then the linear combination must contain a variable;
otherwise, if `variable_obligatory`, then an expression is matched that has any mix of constant/variable/param
*/
tuple<int, int, int, double> matchVariableTimesConstantTimesParam(bool variable_obligatory = true) const;
//! Exception thrown by matchVariableTimesConstantTimesParam when matching fails
class MatchFailureException
[[nodiscard]] tuple<optional<int>, int, optional<int>, double>
matchVariableTimesConstantTimesParam(bool variable_obligatory) const;
/* Matches an expression of the form endogenous*constant where constant is an
expression containing no endogenous, no exogenous and no exogenous deterministic.
Returns (endo_id, constant expr).
Note that it will also match a simple endogenous (in which case the
constant will of course be equal to one). */
[[nodiscard]] virtual pair<int, expr_t> matchEndogenousTimesConstant() const;
//! Exception thrown when matching fails
struct MatchFailureException
{
public:
const string message;
MatchFailureException(string message_arg) : message{move(message_arg)} {};
};
/* Match an expression of the form ∏ x(l)ᵏ, where x are endogenous, as used
in the match_moments block.
For each factor, adds an integer in the 3 vectors in argument (symb_id in
the first, lag in the second, exponent in the third).
Throws a MatchFailureException if not of the right form. */
virtual void matchMatchedMoment(vector<int>& symb_ids, vector<int>& lags,
vector<int>& powers) const;
/* Returns true if the expression contains no endogenous, no exogenous and no
exogenous deterministic */
[[nodiscard]] bool isConstant() const;
// Returns true if the expression contains an exogenous or an exogenous deterministic
[[nodiscard]] bool hasExogenous() const;
// Substitutes orig_symb_id(±l) with exp(aux_symb_id(±l)) (used for “var(log)”)
[[nodiscard]] virtual expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const = 0;
/* Matches an expression that constitutes a complementarity condition.
If successful, returns a triplet (endo_symb_id, lower_bound, upper_bound).
Otherwise, throws a MatchFailureException. */
[[nodiscard]] virtual tuple<int, expr_t, expr_t>
matchComplementarityCondition(const optional<int>& heterogeneity_dimension = nullopt) const;
/* Replaces aggregation operators (e.g. SUM()) by new auxiliary variables.
Also declares those aggregation operators in the HeterogeneityTable, so as to
compute their index in the dedicated vector in argument of the dynamic/static files. */
[[nodiscard]] virtual expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const
= 0;
};
//! Object used to compare two nodes (using their indexes)
......@@ -696,168 +968,237 @@ struct ExprNodeLess
};
//! Numerical constant node
/*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class level) */
/*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class
* level) */
class NumConstNode : public ExprNode
{
public:
//! Id from numerical constants table
const int id;
private:
expr_t computeDerivative(int deriv_id) override;
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
protected:
void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id, double& constant,
bool at_denominator) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
public:
NumConstNode(DataTree& datatree_arg, int idx_arg, int id_arg);
void prepareForDerivation() override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override;
int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
int PacMaxLag(int lhs_symb_id) const override;
int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
[[nodiscard]] expr_t undiff() const override;
[[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
bool isInStaticForm() const override;
void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
expr_t substituteStaticAuxiliaryVariable() const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
};
//! Symbol or variable node
class VariableNode : public ExprNode
{
friend class UnaryOpNode;
public:
//! Id from the symbol table
const int symb_id;
//! A positive value is a lead, a negative is a lag
const int lag;
private:
expr_t computeDerivative(int deriv_id) override;
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
protected:
void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id, double& constant,
bool at_denominator) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
public:
VariableNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, int lag_arg);
void prepareForDerivation() override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
[[nodiscard]] SymbolType get_type() const;
[[nodiscard]] string getName() const;
[[nodiscard]] int getDerivID() const;
[[nodiscard]] int getTypeSpecificID() const;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void computeTemporaryTerms(map<expr_t, int > &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
SymbolType get_type() const;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override;
int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
int PacMaxLag(int lhs_symb_id) const override;
int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
[[nodiscard]] expr_t undiff() const override;
[[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
bool isInStaticForm() const override;
void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
void matchMatchedMoment(vector<int>& symb_ids, vector<int>& lags,
vector<int>& powers) const override;
[[nodiscard]] pair<int, expr_t> matchEndogenousTimesConstant() const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
};
//! Unary operator node
class UnaryOpNode : public ExprNode
{
protected:
void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id, double& constant,
bool at_denominator) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
// Returns the node obtained by applying a transformation recursively on the argument (in same
// datatree)
template<typename Callable, typename... Args>
requires invocable<Callable, expr_t, Args...>
expr_t
recurseTransform(Callable&& op, Args&&... args) const
{
expr_t substarg {invoke(forward<Callable>(op), arg, forward<Args>(args)...)};
return buildSimilarUnaryOpNode(substarg, datatree);
}
public:
const expr_t arg;
//! Stores the information set. Only used for expectation operator
......@@ -867,24 +1208,40 @@ public:
const UnaryOpcode op_code;
const string adl_param_name;
const vector<int> adl_lags;
private:
expr_t computeDerivative(int deriv_id) override;
int cost(int cost, bool is_matlab) const override;
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
[[nodiscard]] int cost(int cost, bool is_matlab) const override;
[[nodiscard]] int cost(const vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
bool is_matlab) const override;
[[nodiscard]] int cost(const map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab) const override;
//! Returns the derivative of this node if darg is the derivative of the argument
expr_t composeDerivatives(expr_t darg, int deriv_id);
public:
UnaryOpNode(DataTree &datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg);
void prepareForDerivation() override;
UnaryOpNode(DataTree& datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg,
int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg,
string adl_param_name_arg, vector<int> adl_lags_arg);
void computeTemporaryTerms(const pair<int, int>& derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
bool is_matlab) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -892,110 +1249,147 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
static double eval_opcode(UnaryOpcode op_code, double v) noexcept(false);
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override;
int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
int PacMaxLag(int lhs_symb_id) const override;
int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
//! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and argument
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
[[nodiscard]] expr_t undiff() const override;
[[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
//! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and
//! argument
expr_t buildSimilarUnaryOpNode(expr_t alt_arg, DataTree& alt_datatree) const;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
bool createAuxVarForUnaryOpNode() const;
[[nodiscard]] bool createAuxVarForUnaryOpNode() const;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
bool isInStaticForm() const override;
void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign) const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
};
//! Binary operator node
class BinaryOpNode : public ExprNode
{
protected:
void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id, double& constant,
bool at_denominator) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
public:
const expr_t arg1, arg2;
const BinaryOpcode op_code;
const int powerDerivOrder;
const string adlparam;
private:
expr_t computeDerivative(int deriv_id) override;
int cost(int cost, bool is_matlab) const override;
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
[[nodiscard]] int cost(int cost, bool is_matlab) const override;
[[nodiscard]] int cost(const vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
bool is_matlab) const override;
[[nodiscard]] int cost(const map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab) const override;
//! Returns the derivative of this node if darg1 and darg2 are the derivatives of the arguments
expr_t composeDerivatives(expr_t darg1, expr_t darg2);
// Returns the node obtained by applying a transformation recursively on the arguments (in same
// datatree)
template<typename Callable, typename... Args>
requires invocable<Callable, expr_t, Args...>
expr_t
recurseTransform(Callable&& op, Args&&... args) const
{
expr_t substarg1 {invoke(forward<Callable>(op), arg1, forward<Args>(args)...)};
expr_t substarg2 {invoke(forward<Callable>(op), arg2, forward<Args>(args)...)};
return buildSimilarBinaryOpNode(substarg1, substarg2, datatree);
}
public:
BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder);
void prepareForDerivation() override;
int precedenceJson(const temporary_terms_t &temporary_terms) const override;
int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
BinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg, BinaryOpcode op_code_arg,
const expr_t arg2_arg, int powerDerivOrder);
[[nodiscard]] int precedenceJson(const temporary_terms_t& temporary_terms) const override;
[[nodiscard]] int precedence(ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms) const override;
void computeTemporaryTerms(const pair<int, int>& derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
bool is_matlab) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -1003,131 +1397,198 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
static double eval_opcode(double v1, BinaryOpcode op_code, double v2, int derivOrder) noexcept(false);
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
static double eval_opcode(double v1, BinaryOpcode op_code, double v2,
int derivOrder) noexcept(false);
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const;
expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override;
int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
int PacMaxLag(int lhs_symb_id) const override;
int getPacTargetSymbIdHelper(int lhs_symb_id, int undiff_lhs_symb_id, const set<pair<int, int>> & endogs) const;
int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
//! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and arguments
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
//! Try to normalize an equation with respect to a given dynamic variable.
/*! Should only be called on Equal nodes. The variable must appear in the equation. */
[[nodiscard]] BinaryOpNode* normalizeEquation(int symb_id, int lag) const;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
[[nodiscard]] expr_t undiff() const override;
[[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
//! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and
//! arguments
expr_t buildSimilarBinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, DataTree& alt_datatree) const;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
bool findTargetVariableHelper1(int lhs_symb_id, int rhs_symb_id) const;
int findTargetVariableHelper(const expr_t arg1, const expr_t arg2, int lhs_symb_id) const;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
[[nodiscard]] bool findTargetVariableHelper1(int lhs_symb_id, int rhs_symb_id) const;
optional<int> findTargetVariableHelper(const expr_t arg1, const expr_t arg2,
int lhs_symb_id) const;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
//! Function to write out the oPowerNode in expr_t terms as opposed to writing out the function itself
expr_t unpackPowerDeriv() const;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
//! Function to write out the oPowerNode in expr_t terms as opposed to writing out the function
//! itself
[[nodiscard]] expr_t unpackPowerDeriv() const;
//! Returns MULT_i*(lhs-rhs) = 0, creating multiplier MULT_i
expr_t addMultipliersToConstraints(int i);
//! Returns the non-zero hand-side of an equation (that must have a hand side equal to zero)
expr_t getNonZeroPartofEquation() const;
bool isInStaticForm() const override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const;
void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
//! Returns the non-zero hand side of an equation (that must have a hand side equal to zero)
[[nodiscard]] expr_t getNonZeroPartofEquation() const;
[[nodiscard]] bool isInStaticForm() const override;
void fillAutoregressiveRow(int eqn, const vector<int>& lhs,
map<tuple<int, int, int>, expr_t>& AR) const;
//! Finds equations where a variable is equal to a constant
void findConstantEquations(map<VariableNode*, NumConstNode*>& table) const;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
pair<int, vector<tuple<int, bool, int>>> getPacEC(BinaryOpNode *bopn, int lhs_symb_id, int lhs_orig_symb_id) const;
void getPacAREC(int lhs_symb_id, int lhs_orig_symb_id,
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
/*
ec_params_and_vars:
- 1st element = feedback force parameter
- 2nd element = list of terms in the cointegration relationship (symb_id,
is target ?, multiplicative scalar); this form theoretically allows for a
linear combination in the cointegration, though for the time being we allow
less than that
ar_params_and_vars: elements are indexed according to lag (index 0 is lag
1); each tuple is (parameter_id, variable_id, variable_lag) where
variable_lag is *not* the lag order in the AR
(because variable is an AUX_DIFF_LAG)
*/
void getPacAREC(
int lhs_symb_id, int lhs_orig_symb_id,
pair<int, vector<tuple<int, bool, int>>>& ec_params_and_vars,
set<pair<int, pair<int, int>>> &ar_params_and_vars,
vector<tuple<int, int, int, double>> &additive_vars_params_and_constants) const;
vector<tuple<optional<int>, optional<int>, int>>& ar_params_and_vars,
vector<tuple<int, int, optional<int>, double>>& additive_vars_params_and_constants) const;
//! Finds the share of optimizing agents in the PAC equation,
//! the expr node associated with it,
//! and the expr node associated with the non-optimizing part
tuple<int, expr_t, expr_t, expr_t> getPacOptimizingShareAndExprNodes(int lhs_symb_id, int lhs_orig_symb_id) const;
pair<int, expr_t> getPacOptimizingShareAndExprNodesHelper(BinaryOpNode *bopn, int lhs_symb_id, int lhs_orig_symb_id) const;
expr_t getPacNonOptimizingPart(BinaryOpNode *bopn, int optim_share) const;
bool getPacNonOptimizingPartHelper(BinaryOpNode *bopn, int optim_share) const;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
//! Substitute auxiliary variables by their expression in static model auxiliary variable definition
expr_t substituteStaticAuxiliaryDefinition() const;
[[nodiscard]] tuple<optional<int>, expr_t, expr_t, expr_t>
getPacOptimizingShareAndExprNodes(int lhs_orig_symb_id) const;
[[nodiscard]] pair<optional<int>, expr_t>
getPacOptimizingShareAndExprNodesHelper(int lhs_orig_symb_id) const;
[[nodiscard]] expr_t getPacNonOptimizingPart(int optim_share_symb_id) const;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign) const override;
void decomposeMultiplicativeFactors(vector<pair<expr_t, int>>& factors,
int current_exponent = 1) const override;
void matchMatchedMoment(vector<int>& symb_ids, vector<int>& lags,
vector<int>& powers) const override;
[[nodiscard]] pair<int, expr_t> matchEndogenousTimesConstant() const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] tuple<int, expr_t, expr_t>
matchComplementarityCondition(const optional<int>& heterogeneity_dimension
= nullopt) const override;
};
//! Trinary operator node
class TrinaryOpNode : public ExprNode
{
friend class ModelTree;
public:
const expr_t arg1, arg2, arg3;
const TrinaryOpcode op_code;
protected:
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
private:
expr_t computeDerivative(int deriv_id) override;
int cost(int cost, bool is_matlab) const override;
int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
//! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the arguments
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
[[nodiscard]] int cost(int cost, bool is_matlab) const override;
[[nodiscard]] int cost(const vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
bool is_matlab) const override;
[[nodiscard]] int cost(const map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
bool is_matlab) const override;
//! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the
//! arguments
expr_t composeDerivatives(expr_t darg1, expr_t darg2, expr_t darg3);
// Returns the node obtained by applying a transformation recursively on the arguments (in same
// datatree)
template<typename Callable, typename... Args>
requires invocable<Callable, expr_t, Args...>
expr_t
recurseTransform(Callable&& op, Args&&... args) const
{
expr_t substarg1 {invoke(forward<Callable>(op), arg1, forward<Args>(args)...)};
expr_t substarg2 {invoke(forward<Callable>(op), arg2, forward<Args>(args)...)};
expr_t substarg3 {invoke(forward<Callable>(op), arg3, forward<Args>(args)...)};
return buildSimilarTrinaryOpNode(substarg1, substarg2, substarg3, datatree);
}
public:
TrinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg,
TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg);
void prepareForDerivation() override;
int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
[[nodiscard]] int precedence(ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms) const override;
void computeTemporaryTerms(const pair<int, int>& derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
bool is_matlab) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -1135,75 +1596,79 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) noexcept(false);
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override;
int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
int PacMaxLag(int lhs_symb_id) const override;
int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
//! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and arguments
expr_t buildSimilarTrinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, expr_t alt_arg3, DataTree &alt_datatree) const;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
[[nodiscard]] expr_t undiff() const override;
[[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
//! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and
//! arguments
expr_t buildSimilarTrinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, expr_t alt_arg3,
DataTree& alt_datatree) const;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
bool isInStaticForm() const override;
void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
};
//! External function node
......@@ -1212,134 +1677,197 @@ class AbstractExternalFunctionNode : public ExprNode
public:
const int symb_id;
const vector<expr_t> arguments;
private:
expr_t computeDerivative(int deriv_id) override;
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
virtual expr_t composeDerivatives(const vector<expr_t>& dargs) = 0;
// Computes the maximum of f applied to all arguments (result will always be non-negative)
int maxHelper(const function<int(expr_t)>& f) const;
// Returns the node obtained by applying a transformation recursively on the arguments (in same
// datatree)
template<typename Callable, typename... Args>
requires invocable<Callable, expr_t, Args...>
expr_t
recurseTransform(Callable&& op, Args&&... args) const
{
vector<expr_t> arguments_subst;
for (auto argument : arguments)
arguments_subst.push_back(invoke(forward<Callable>(op), argument, forward<Args>(args)...));
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
}
protected:
//! Thrown when trying to access an unknown entry in external_function_node_map
class UnknownFunctionNameAndArgs
{
};
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
//! Returns true if the given external function has been written as a temporary term
bool alreadyWrittenAsTefTerm(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const;
[[nodiscard]] bool alreadyWrittenAsTefTerm(int the_symb_id,
const deriv_node_temp_terms_t& tef_terms) const;
//! Returns the index in the tef_terms map of this external function
int getIndxInTefTerms(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const noexcept(false);
[[nodiscard]] int getIndxInTefTerms(int the_symb_id,
const deriv_node_temp_terms_t& tef_terms) const
noexcept(false);
//! Helper function to write output arguments of any given external function
void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
void writeExternalFunctionArguments(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const;
void writeJsonASTExternalFunctionArguments(ostream& output) const;
void writeJsonExternalFunctionArguments(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
void writeJsonExternalFunctionArguments(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const;
void writeBytecodeExternalFunctionArguments(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const;
/*! Returns a predicate that tests whether an other ExprNode is an external
function which is computed by the same external function call (i.e. it has
the same so-called "Tef" index) */
virtual function<bool (expr_t)> sameTefTermPredicate() const = 0;
[[nodiscard]] virtual function<bool(expr_t)> sameTefTermPredicate() const = 0;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
public:
AbstractExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg,
vector<expr_t> arguments_arg);
void prepareForDerivation() override;
[[nodiscard]] string getName() const;
void computeTemporaryTerms(const pair<int, int>& derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
bool is_matlab) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override = 0;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override
= 0;
void writeJsonAST(ostream& output) const override = 0;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const override = 0;
bool containsExternalFunction() const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms,
bool isdynamic = true) const override
= 0;
[[nodiscard]] bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const override = 0;
deriv_node_temp_terms_t& tef_terms) const override
= 0;
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic = true) const override = 0;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const override = 0;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override = 0;
bool isdynamic = true) const override
= 0;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override
= 0;
void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
double eval(const eval_context_t &eval_context) const noexcept(false) override;
unsigned int compileExternalFunctionArguments(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override = 0;
expr_t toStatic(DataTree &static_datatree) const override = 0;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override
= 0;
expr_t toStatic(DataTree& static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override = 0;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override;
int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
int PacMaxLag(int lhs_symb_id) const override;
int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
[[nodiscard]] expr_t undiff() const override;
[[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const = 0;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
bool isNumConstNodeEqualTo(double value) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms, const string &ending) const;
expr_t replaceTrendVar() const override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
DataTree& alt_datatree) const
= 0;
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] int countDiffs() const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
void writePrhs(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t clone(DataTree &datatree) const override = 0;
expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
bool isInStaticForm() const override;
void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
};
class ExternalFunctionNode : public AbstractExternalFunctionNode
{
friend class FirstDerivExternalFunctionNode;
friend class SecondDerivExternalFunctionNode;
private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public:
ExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg,
const vector<expr_t>& arguments_arg);
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
......@@ -1347,49 +1875,45 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
expr_t clone(DataTree &datatree) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
DataTree& alt_datatree) const override;
};
class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode
{
public:
const int inputIndex;
private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public:
FirstDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,
int inputIndex_arg);
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
FirstDerivExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int top_level_symb_id_arg,
const vector<expr_t>& arguments_arg, int inputIndex_arg);
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
......@@ -1398,15 +1922,15 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
expr_t clone(DataTree &datatree) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
DataTree& alt_datatree) const override;
};
class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode
......@@ -1414,28 +1938,27 @@ class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode
public:
const int inputIndex1;
const int inputIndex2;
private:
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
public:
SecondDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,
int inputIndex1_arg,
SecondDerivExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int top_level_symb_id_arg,
const vector<expr_t>& arguments_arg, int inputIndex1_arg,
int inputIndex2_arg);
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void writeExternalFunctionOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
......@@ -1444,176 +1967,168 @@ public:
void writeJsonExternalFunctionOutput(vector<string>& efout,
const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms,
const bool isdynamic) const override;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo& ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
expr_t clone(DataTree &datatree) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
DataTree& alt_datatree) const override;
};
class VarExpectationNode : public ExprNode
/* Common superclass for nodes that have the following two characteristics:
– they take a submodel name as an argument
– they will be substituted out in the middle of the transform pass
*/
class SubModelNode : public ExprNode
{
public:
const string model_name;
VarExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name_arg);
SubModelNode(DataTree& datatree_arg, int idx_arg, string model_name_arg);
void computeTemporaryTerms(const pair<int, int>& derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
map<pair<int, int>, unordered_set<expr_t>>& temp_terms_map,
unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
bool is_matlab) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void computeBlockTemporaryTerms(
int blk, int eq, vector<vector<unordered_set<expr_t>>>& blocks_temporary_terms,
unordered_map<expr_t, tuple<int, int, int>>& reference_count) const override;
expr_t toStatic(DataTree& static_datatree) const override;
expr_t clone(DataTree &datatree) const override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override;
int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
int PacMaxLag(int lhs_symb_id) const override;
int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
void prepareForDerivation() override;
expr_t computeDerivative(int deriv_id) override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
bool containsExternalFunction() const override;
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void computeXrefs(EquationInfo &ei) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
[[nodiscard]] int maxEndoLead() const override;
[[nodiscard]] int maxExoLead() const override;
[[nodiscard]] int maxEndoLag() const override;
[[nodiscard]] int maxExoLag() const override;
[[nodiscard]] int maxLead() const override;
[[nodiscard]] int maxLag() const override;
[[nodiscard]] int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const override;
[[nodiscard]] expr_t undiff() const override;
[[nodiscard]] expr_t decreaseLeadsLags(int n) const override;
[[nodiscard]] int countDiffs() const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExoLead(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
[[nodiscard]] bool containsExternalFunction() const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void computeXrefs(EquationInfo& ei) const override;
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
bool partial_information_model) const override;
[[nodiscard]] expr_t substituteAdl() const override;
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substitutePacExpectation(const string & name, expr_t subexpr) override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isNumConstNodeEqualTo(double value) const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
bool isInStaticForm() const override;
void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
[[nodiscard]] bool isNumConstNodeEqualTo(double value) const override;
[[nodiscard]] bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
int lag_arg) const override;
[[nodiscard]] bool isInStaticForm() const override;
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
expr_t substituteStaticAuxiliaryVariable() const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
[[nodiscard]] bool isParamTimesEndogExpr() const override;
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
[[nodiscard]] expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
[[nodiscard]] expr_t substituteAggregationOperators(subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override;
protected:
void prepareForDerivation() override;
void prepareForChainRuleDerivation(
const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
void computeSubExprContainingVariable(int symb_id, int lag,
set<expr_t>& contain_var) const override;
private:
expr_t
computeChainRuleDerivative(int deriv_id, const map<int, BinaryOpNode*>& recursive_variables,
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives,
unordered_map<expr_t, map<int, expr_t>>& cache) override;
};
class PacExpectationNode : public ExprNode
class VarExpectationNode : public SubModelNode
{
public:
const string model_name;
VarExpectationNode(DataTree& datatree_arg, int idx_arg, string model_name_arg);
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
};
class PacExpectationNode : public SubModelNode
{
public:
PacExpectationNode(DataTree& datatree_arg, int idx_arg, string model_name);
void computeTemporaryTerms(const pair<int, int> &derivOrder,
map<pair<int, int>, temporary_terms_t> &temp_terms_map,
map<expr_t, pair<int, pair<int, int>>> &reference_count,
bool is_matlab) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int>> &first_occurence,
int Curr_block,
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
expr_t toStatic(DataTree &static_datatree) const override;
expr_t clone(DataTree &datatree) const override;
int maxEndoLead() const override;
int maxExoLead() const override;
int maxEndoLag() const override;
int maxExoLag() const override;
int maxLead() const override;
int maxLag() const override;
int maxLagWithDiffsExpanded() const override;
int VarMinLag() const override;
int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
int PacMaxLag(int lhs_symb_id) const override;
int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
expr_t undiff() const override;
expr_t decreaseLeadsLags(int n) const override;
void prepareForDerivation() override;
expr_t computeDerivative(int deriv_id) override;
expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
bool containsExternalFunction() const override;
double eval(const eval_context_t &eval_context) const noexcept(false) override;
void computeXrefs(EquationInfo &ei) const override;
expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
expr_t substituteAdl() const override;
expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
void findDiffNodes(lag_equivalence_table_t &nodes) const override;
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
int findTargetVariable(int lhs_symb_id) const override;
expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
};
class PacTargetNonstationaryNode : public SubModelNode
{
public:
PacTargetNonstationaryNode(DataTree& datatree_arg, int idx_arg, string model_name);
void writeOutput(ostream& output, ExprNodeOutputType output_type,
const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override;
void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
void collectVARLHSVariable(set<expr_t> &result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
bool containsEndogenous() const override;
bool containsExogenous() const override;
int countDiffs() const override;
bool isNumConstNodeEqualTo(double value) const override;
expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
expr_t decreaseLeadsLagsPredeterminedVariables() const override;
bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
expr_t replaceTrendVar() const override;
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
bool isInStaticForm() const override;
void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
bool isParamTimesEndogExpr() const override;
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
expr_t substituteStaticAuxiliaryVariable() const override;
expr_t clone(DataTree& alt_datatree) const override;
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
[[nodiscard]] expr_t
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
= "") const override;
void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
};
#endif
/*
* Copyright © 2014-2019 Dynare Team
* Copyright © 2014-2023 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,24 +14,25 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EXTENDED_PREPROCESSOR_TYPES_HH
#define _EXTENDED_PREPROCESSOR_TYPES_HH
#ifndef EXTENDED_PREPROCESSOR_TYPES_HH
#define EXTENDED_PREPROCESSOR_TYPES_HH
enum class FileOutputType
// Values for the “output” option
enum class OutputType
{
none, // outputs files for Matlab/Octave processing
dynamic, // outputs <fname>_dynamic.* and related files
first, // outputs <fname>_first_derivatives.* and related files
second, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.* and related files
third, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.*, <fname>_third_derivatives.* and related files
standard, // Default value, infer the derivation order from .mod file only
first, // Output only 1st dynamic derivatives with no other computations
second, // Output at least 2nd dynamic derivatives
third, // Output at least 3rd dynamic derivatives
};
// Values for the “language” option
enum class LanguageOutputType
{
matlab, // outputs files for Matlab/Octave processing
matlab, // outputs files for MATLAB/Octave processing
julia, // outputs files for Julia
};
......@@ -41,6 +42,7 @@ enum class JsonFileOutputType
standardout, // output JSON files to stdout
};
// Values for the “json” option
enum class JsonOutputPointType
{
nojson, // don't output JSON
......@@ -49,4 +51,5 @@ enum class JsonOutputPointType
transformpass, // output JSON after the transform pass
computingpass // output JSON after the computing pass
};
#endif
......@@ -14,19 +14,20 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include "ExternalFunctionsTable.hh"
#include "SymbolTable.hh"
void
ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs)
ExternalFunctionsTable::addExternalFunction(
int symb_id, const external_function_options& external_function_options_arg, bool track_nargs)
{
assert(symb_id >= 0);
assert(external_function_options_arg.nargs > 0);
......@@ -63,11 +64,14 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function
if (external_function_options_chng.secondDerivSymbID != IDNotSet
&& external_function_options_chng.firstDerivSymbID == IDNotSet)
{
cerr << "ERROR: If the second derivative is provided, the first derivative must also be provided." << endl;
cerr << "ERROR: If the second derivative is provided, the first derivative must also be "
"provided."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID == external_function_options_chng.firstDerivSymbID
if (external_function_options_chng.secondDerivSymbID
== external_function_options_chng.firstDerivSymbID
&& external_function_options_chng.firstDerivSymbID != symb_id
&& external_function_options_chng.firstDerivSymbID != IDNotSet)
{
......@@ -80,29 +84,40 @@ ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function
if (exists(symb_id))
{
bool ok_to_overwrite = false;
if (getNargs(symb_id) == IDNotSet) // implies that the information stored about this function is not important
if (getNargs(symb_id)
== IDNotSet) // implies that the information stored about this function is not important
ok_to_overwrite = true;
if (!ok_to_overwrite) // prevents multiple non-compatible calls to external_function(name=funcname)
if (!ok_to_overwrite) // prevents multiple non-compatible calls to
// external_function(name=funcname)
{ // e.g. e_f(name=a,nargs=1,fd,sd) and e_f(name=a,nargs=2,fd=b,sd=c) should cause an error
if (external_function_options_chng.nargs != getNargs(symb_id))
{
cerr << "ERROR: The number of arguments passed to the external_function() statement do not "
<< "match the number of arguments passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The number of arguments passed to the external_function() statement "
"do not "
<< "match the number of arguments passed to a previous call or declaration of "
"the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.firstDerivSymbID != getFirstDerivSymbID(symb_id))
{
cerr << "ERROR: The first derivative function passed to the external_function() statement does not "
<< "match the first derivative function passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The first derivative function passed to the external_function() "
"statement does not "
<< "match the first derivative function passed to a previous call or "
"declaration of the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID != getSecondDerivSymbID(symb_id))
{
cerr << "ERROR: The second derivative function passed to the external_function() statement does not "
<< "match the second derivative function passed to a previous call or declaration of the top-level function."<< endl;
cerr << "ERROR: The second derivative function passed to the external_function() "
"statement does not "
<< "match the second derivative function passed to a previous call or "
"declaration of the top-level function."
<< endl;
exit(EXIT_FAILURE);
}
}
......
/*
* Copyright © 2010-2015 Dynare Team
* Copyright © 2010-2023 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,32 +14,29 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EXTERNALFUNCTIONSTABLE_HH
#define _EXTERNALFUNCTIONSTABLE_HH
using namespace std;
#ifndef EXTERNAL_FUNCTIONS_TABLE_HH
#define EXTERNAL_FUNCTIONS_TABLE_HH
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <map>
using namespace std;
//! Handles external functions
class ExternalFunctionsTable
{
public:
//! Thrown when trying to access an unknown symbol (by id)
class UnknownExternalFunctionSymbolIDException
struct UnknownExternalFunctionSymbolIDException
{
public:
//! Symbol ID
int id;
explicit UnknownExternalFunctionSymbolIDException(int id_arg) : id{id_arg}
{
}
};
/* For all arguments, -2 means not set
......@@ -58,67 +55,57 @@ public:
constexpr static int IDSetButNoNameProvided = -2;
//! Default number of arguments when nargs is not specified
constexpr static int defaultNargs = 1;
private:
//! Map containing options provided to external_functions()
external_function_table_type externalFunctionTable;
public:
//! Adds an external function to the table as well as its derivative functions
void addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs);
void addExternalFunction(int symb_id,
const external_function_options& external_function_options_arg,
bool track_nargs);
//! See if the function exists in the External Functions Table
inline bool exists(int symb_id) const;
[[nodiscard]] inline bool exists(int symb_id) const;
//! Get the number of arguments for a given external function
inline int getNargs(int symb_id) const noexcept(false);
[[nodiscard]] inline int getNargs(int symb_id) const noexcept(false);
//! Get the symbol_id of the first derivative function
inline int getFirstDerivSymbID(int symb_id) const noexcept(false);
[[nodiscard]] inline int getFirstDerivSymbID(int symb_id) const noexcept(false);
//! Get the symbol_id of the second derivative function
inline int getSecondDerivSymbID(int symb_id) const noexcept(false);
//! Returns the total number of unique external functions declared or used in the .mod file
inline int get_total_number_of_unique_model_block_external_functions() const;
[[nodiscard]] inline int getSecondDerivSymbID(int symb_id) const noexcept(false);
};
inline bool
ExternalFunctionsTable::exists(int symb_id) const
{
auto iter = externalFunctionTable.find(symb_id);
return (iter != externalFunctionTable.end());
return externalFunctionTable.contains(symb_id);
}
inline int
ExternalFunctionsTable::getNargs(int symb_id) const noexcept(false)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.nargs;
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.nargs;
else
throw UnknownExternalFunctionSymbolIDException(symb_id);
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
inline int
ExternalFunctionsTable::getFirstDerivSymbID(int symb_id) const noexcept(false)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.firstDerivSymbID;
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.firstDerivSymbID;
else
throw UnknownExternalFunctionSymbolIDException(symb_id);
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
inline int
ExternalFunctionsTable::getSecondDerivSymbID(int symb_id) const noexcept(false)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.secondDerivSymbID;
if (auto it = externalFunctionTable.find(symb_id); it != externalFunctionTable.end())
return it->second.secondDerivSymbID;
else
throw UnknownExternalFunctionSymbolIDException(symb_id);
}
inline int
ExternalFunctionsTable::get_total_number_of_unique_model_block_external_functions() const
{
int number_of_unique_model_block_external_functions = 0;
for (auto it : externalFunctionTable)
if (it.second.nargs > 0)
number_of_unique_model_block_external_functions++;
return number_of_unique_model_block_external_functions;
throw UnknownExternalFunctionSymbolIDException {symb_id};
}
#endif
/*
* Copyright © 2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <utility>
#include "HeterogeneityTable.hh"
#include "SymbolTable.hh"
void
HeterogeneityTable::setSymbolTable(SymbolTable* symbol_table_arg)
{
symbol_table = symbol_table_arg;
}
int
HeterogeneityTable::addDimension(string name)
{
if (name_to_id.contains(name))
throw AlreadyDeclaredDimensionException {move(name)};
int id {static_cast<int>(id_to_name.size())};
name_to_id.emplace(name, id);
id_to_name.push_back(move(name));
return id;
}
bool
HeterogeneityTable::exists(const string& name) const
{
return name_to_id.contains(name);
}
int
HeterogeneityTable::getID(const string& name) const
{
if (auto it = name_to_id.find(name); it != name_to_id.end())
return it->second;
else
throw UnknownDimensionNameException {name};
}
string
HeterogeneityTable::getName(int id) const
{
if (id < 0 || id >= static_cast<int>(id_to_name.size()))
throw UnknownDimensionIDException {id};
else
return id_to_name[id];
}
bool
HeterogeneityTable::empty() const
{
return name_to_id.empty();
}
vector<string>
HeterogeneityTable::getDimensions() const
{
return id_to_name;
}
int
HeterogeneityTable::size() const
{
return static_cast<int>(name_to_id.size());
}
void
HeterogeneityTable::addSummedHeterogeneousEndogenous(int symb_id)
{
assert(symbol_table->getType(symb_id) == SymbolType::heterogeneousEndogenous);
if (summed_het_endo_to_index.contains(symb_id))
throw AlreadyDeclaredSummedHeterogeneousEndogenousException {symb_id};
int index {static_cast<int>(index_to_summed_het_endo.size())};
summed_het_endo_to_index.emplace(symb_id, index);
index_to_summed_het_endo.push_back(symb_id);
}
int
HeterogeneityTable::getSummedHeterogenousEndogenousIndex(int symb_id) const
{
if (auto it = summed_het_endo_to_index.find(symb_id); it != summed_het_endo_to_index.end())
return it->second;
else
throw UnknownSummedHeterogeneousEndogenousException {symb_id};
}
int
HeterogeneityTable::aggregateEndoSize() const
{
return index_to_summed_het_endo.size();
}
void
HeterogeneityTable::writeOutput(ostream& output) const
{
for (size_t id {0}; id < id_to_name.size(); id++)
output << "M_.heterogeneity(" << id + 1 << ").dimension_name = '" << id_to_name[id] << "';"
<< endl;
output << "M_.heterogeneity_aggregates = {" << endl;
for (int symb_id : index_to_summed_het_endo)
output << "'sum', " << symbol_table->getHeterogeneityDimension(symb_id) + 1 << ", "
<< symbol_table->getTypeSpecificID(symb_id) + 1 << ";" << endl;
output << "};" << endl;
}
void
HeterogeneityTable::writeJsonOutput(ostream& output) const
{
assert(!empty());
output << R"("heterogeneity_dimension": [)";
for (bool first_written {false}; const auto& dim : id_to_name)
{
if (exchange(first_written, true))
output << ", ";
output << '"' << dim << '"';
}
output << "]" << endl;
}
/*
* Copyright © 2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef HETEROGENEITY_TABLE_HH
#define HETEROGENEITY_TABLE_HH
#include <map>
#include <ostream>
#include <string>
#include <vector>
using namespace std;
class SymbolTable; // Forward declaration, to avoid circularity
/*
There is a guarantee that heterogeneity IDs are increasing, i.e. if dimension A is added after
dimension B, then the ID of A is greater than the ID of B.
Moreover, the IDs form a contiguous interval starting at 0.
*/
class HeterogeneityTable
{
private:
// Maps dimension names to IDs
map<string, int> name_to_id;
// Maps dimension IDs to names
vector<string> id_to_name;
SymbolTable* symbol_table {nullptr}; // Cannot be a reference, because of circularity
/* Keeps track of the SUM() operator instances.
Maps a symbol ID that appears inside a SUM() operator into an index in
M_.heterogeneity_aggregates */
map<int, int> summed_het_endo_to_index;
// Maps an index in M_.heterogeneity_aggregates into a symbol ID
vector<int> index_to_summed_het_endo;
public:
void setSymbolTable(SymbolTable* symbol_table_arg);
struct AlreadyDeclaredDimensionException
{
// Dimension name
const string name;
};
struct UnknownDimensionNameException
{
// Dimension name
const string name;
};
struct UnknownDimensionIDException
{
// Dimension ID
const int id;
};
// Returns the dimension ID
int addDimension(string name);
[[nodiscard]] bool exists(const string& name) const;
[[nodiscard]] int getID(const string& name) const;
[[nodiscard]] string getName(int id) const;
[[nodiscard]] bool empty() const;
[[nodiscard]] vector<string> getDimensions() const;
[[nodiscard]] int size() const;
struct AlreadyDeclaredSummedHeterogeneousEndogenousException
{
const int symb_id;
};
struct UnknownSummedHeterogeneousEndogenousException
{
const int symb_id;
};
void addSummedHeterogeneousEndogenous(int symb_id);
[[nodiscard]] int getSummedHeterogenousEndogenousIndex(int symb_id) const;
[[nodiscard]] int aggregateEndoSize() const;
void writeOutput(ostream& output) const;
void writeJsonOutput(ostream& output) const;
};
#endif
/*
* Copyright © 2024-2025 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <iostream>
#include "HeterogeneousModel.hh"
HeterogeneousModel::HeterogeneousModel(SymbolTable& symbol_table_arg,
NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg,
int heterogeneity_dimension_arg) :
ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg,
heterogeneity_table_arg, true},
heterogeneity_dimension {heterogeneity_dimension_arg}
{
}
HeterogeneousModel&
HeterogeneousModel::operator=(const HeterogeneousModel& m)
{
ModelTree::operator=(m);
assert(heterogeneity_dimension == m.heterogeneity_dimension);
deriv_id_table = m.deriv_id_table;
inv_deriv_id_table = m.inv_deriv_id_table;
return *this;
}
void
HeterogeneousModel::computeChainRuleJacobian()
{
cerr << "Heterogeneous::computeChainRuleJacobian(): unimplemented" << endl;
exit(EXIT_FAILURE);
}
int
HeterogeneousModel::getBlockJacobianEndoCol([[maybe_unused]] int blk, [[maybe_unused]] int var,
[[maybe_unused]] int lead_lag) const
{
cerr << "Heterogeneous::getBlockJacobianEndoCol(): unimplemented" << endl;
exit(EXIT_FAILURE);
}
int
HeterogeneousModel::getMFS() const
{
cerr << "Heterogeneous::getMFS(): unimplemented" << endl;
exit(EXIT_FAILURE);
}
void
HeterogeneousModel::computeDerivIDs()
{
set<pair<int, int>> dynvars;
for (auto& equation : equations)
{
equation->collectDynamicVariables(SymbolType::heterogeneousEndogenous, dynvars);
equation->collectDynamicVariables(SymbolType::heterogeneousExogenous, dynvars);
equation->collectDynamicVariables(SymbolType::endogenous, dynvars);
equation->collectDynamicVariables(SymbolType::exogenous, dynvars);
equation->collectDynamicVariables(SymbolType::parameter, dynvars);
}
for (const auto& [symb_id, lead_lag] : dynvars)
{
auto type {symbol_table.getType(symb_id)};
if (isHeterogeneous(type))
assert(symbol_table.getHeterogeneityDimension(symb_id) == heterogeneity_dimension);
if (type == SymbolType::heterogeneousEndogenous || type == SymbolType::endogenous)
assert(abs(lead_lag) <= 1);
if (type == SymbolType::heterogeneousExogenous || type == SymbolType::exogenous)
assert(lead_lag == 0);
int deriv_id {static_cast<int>(deriv_id_table.size())};
deriv_id_table.emplace(pair {symb_id, lead_lag}, deriv_id);
inv_deriv_id_table.emplace_back(symb_id, lead_lag);
}
}
void
HeterogeneousModel::computingPass(int derivsOrder, bool no_tmp_terms, bool use_dll)
{
assert(!use_dll); // Not yet implemented
computeDerivIDs();
set<int> vars;
for (auto& [symb_lag, deriv_id] : deriv_id_table)
if (symbol_table.getType(symb_lag.first) != SymbolType::parameter)
vars.insert(deriv_id);
cout << "Computing " << modelClassName() << " derivatives (order " << derivsOrder << ")." << endl;
computeDerivatives(derivsOrder, vars);
computeTemporaryTerms(!use_dll, no_tmp_terms);
computeMCPEquationsReordering(heterogeneity_dimension);
}
void
HeterogeneousModel::writeModelFiles(const string& basename, bool julia) const
{
assert(!julia); // Not yet implemented
writeSparseModelMFiles<true>(basename, heterogeneity_dimension);
writeComplementarityConditionsFile<true>(basename, heterogeneity_dimension);
}
int
HeterogeneousModel::getJacobianCol(int deriv_id, bool sparse) const
{
assert(sparse);
SymbolType type {getTypeByDerivID(deriv_id)};
int tsid {getTypeSpecificIDByDerivID(deriv_id)};
int lag {getLagByDerivID(deriv_id)};
if (type == SymbolType::heterogeneousEndogenous)
return tsid + (lag + 1) * symbol_table.het_endo_nbr(heterogeneity_dimension);
int shift {3 * symbol_table.het_endo_nbr(heterogeneity_dimension)};
if (type == SymbolType::heterogeneousExogenous)
return shift + tsid;
shift += symbol_table.het_exo_nbr(heterogeneity_dimension);
if (type == SymbolType::endogenous)
return shift + tsid + (lag + 1) * symbol_table.endo_nbr();
shift += symbol_table.endo_nbr();
if (type == SymbolType::exogenous)
return shift + tsid;
throw UnknownDerivIDException();
}
int
HeterogeneousModel::getJacobianColsNbr(bool sparse) const
{
assert(sparse);
return 3 * (symbol_table.het_endo_nbr(heterogeneity_dimension) + symbol_table.endo_nbr())
+ symbol_table.het_exo_nbr(heterogeneity_dimension) + symbol_table.exo_nbr();
}
SymbolType
HeterogeneousModel::getTypeByDerivID(int deriv_id) const noexcept(false)
{
return symbol_table.getType(getSymbIDByDerivID(deriv_id));
}
int
HeterogeneousModel::getLagByDerivID(int deriv_id) const noexcept(false)
{
if (deriv_id < 0 || deriv_id >= static_cast<int>(inv_deriv_id_table.size()))
throw UnknownDerivIDException();
return inv_deriv_id_table[deriv_id].second;
}
int
HeterogeneousModel::getSymbIDByDerivID(int deriv_id) const noexcept(false)
{
if (deriv_id < 0 || deriv_id >= static_cast<int>(inv_deriv_id_table.size()))
throw UnknownDerivIDException();
return inv_deriv_id_table[deriv_id].first;
}
int
HeterogeneousModel::getTypeSpecificIDByDerivID(int deriv_id) const
{
return symbol_table.getTypeSpecificID(getSymbIDByDerivID(deriv_id));
}
int
HeterogeneousModel::getDerivID(int symb_id, int lead_lag) const noexcept(false)
{
if (auto it = deriv_id_table.find({symb_id, lead_lag}); it == deriv_id_table.end())
throw UnknownDerivIDException();
else
return it->second;
}
void
HeterogeneousModel::writeDriverOutput(ostream& output) const
{
std::vector<int> state_var;
for (int endoID = 0; endoID < symbol_table.het_endo_nbr(heterogeneity_dimension); endoID++)
try
{
getDerivID(symbol_table.getID(SymbolType::heterogeneousEndogenous, endoID,
heterogeneity_dimension),
-1);
if (ranges::find(state_var, endoID) == state_var.end())
state_var.push_back(endoID);
}
catch (UnknownDerivIDException& e)
{
}
output << "M_.heterogeneity(" << heterogeneity_dimension + 1 << ").state_var = [";
for (int it : state_var)
output << it + 1 << " ";
output << "];" << endl;
output << "M_.heterogeneity(" << heterogeneity_dimension + 1 << ").dynamic_tmp_nbr = [";
for (const auto& it : temporary_terms_derivatives)
output << it.size() << "; ";
output << "];" << endl;
writeDriverSparseIndicesHelper(
"heterogeneity("s + to_string(heterogeneity_dimension + 1) + ").dynamic", output);
output << "M_.heterogeneity(" << heterogeneity_dimension + 1
<< ").dynamic_mcp_equations_reordering = [";
for (auto i : mcp_equations_reordering)
output << i + 1 << "; ";
output << "];" << endl;
}
/*
* Copyright © 2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef HETEROGENEOUS_MODEL_HH
#define HETEROGENEOUS_MODEL_HH
#include <string>
#include "ModelTree.hh"
using namespace std;
class HeterogeneousModel : public ModelTree
{
public:
const int heterogeneity_dimension;
HeterogeneousModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg, int heterogeneity_dimension_arg);
HeterogeneousModel(const HeterogeneousModel& m) = default;
HeterogeneousModel& operator=(const HeterogeneousModel& m);
void computingPass(int derivsOrder, bool no_tmp_terms, bool use_dll);
void writeModelFiles(const string& basename, bool julia) const;
void writeDriverOutput(ostream& output) const;
[[nodiscard]] int getJacobianCol(int deriv_id, bool sparse) const override;
[[nodiscard]] int getJacobianColsNbr(bool sparse) const override;
#if 0
void substituteEndoLeadGreaterThanTwo();
//! Transforms the model by removing all lags greater or equal than 2 on endos
void substituteEndoLagGreaterThanTwo();
//! Transforms the model by removing all leads on exos
/*! Note that this can create new lags on endos and exos */
void substituteExoLead();
//! Transforms the model by removing all lags on exos
void substituteExoLag();
//! Transforms the model by removing all UnaryOpcode::expectation
void substituteExpectation(bool partial_information_model);
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations
//! by one
void transformPredeterminedVariables();
//! Substitutes out all model-local variables
void substituteModelLocalVariables();
#endif
// FIXME: the following 5 functions are identical to those in DynamicModel. Factorization?
[[nodiscard]] int getDerivID(int symb_id, int lead_lag) const noexcept(false) override;
[[nodiscard]] SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;
[[nodiscard]] int getLagByDerivID(int deriv_id) const noexcept(false) override;
[[nodiscard]] int getSymbIDByDerivID(int deriv_id) const noexcept(false) override;
[[nodiscard]] int getTypeSpecificIDByDerivID(int deriv_id) const override;
protected:
void computeChainRuleJacobian() override;
int getBlockJacobianEndoCol(int blk, int var, int lead_lag) const override;
string
modelClassName() const override
{
return "dynamic model for heterogeneity dimension '"
+ heterogeneity_table.getName(heterogeneity_dimension) + "'";
}
int getMFS() const override;
private:
// Maps a pair (symbol ID, lead/lag) to a deriv ID
map<pair<int, int>, int> deriv_id_table;
// Maps a deriv ID to a pair (symbol ID, lead/lag)
vector<pair<int, int>> inv_deriv_id_table;
// Allocates the derivation IDs for all endogenous variables for this heterogeneity dimension
void computeDerivIDs();
};
#endif
/*
* Copyright © 2015-2019 Dynare Team
* Copyright © 2015-2023 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,46 +14,63 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <fstream>
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <regex>
#include <sstream>
#include "macro/Driver.hh"
bool compareNewline (int i, int j) {
return i == '\n' && j == '\n';
}
void
main1(const string &filename, const string &basename, istream &modfile, bool debug, bool save_macro, string &save_macro_file,
bool no_line_macro_arg, bool no_empty_line_macro, const vector<pair<string, string>> &defines,
vector<filesystem::path> &paths, stringstream &macro_output)
stringstream
macroExpandModFile(const filesystem::path& filename, const istream& modfile, bool debug,
bool save_macro, filesystem::path save_macro_file, bool line_macro,
const vector<pair<string, string>>& defines, vector<filesystem::path> paths)
{
// Do macro processing
stringstream macro_output;
macro::Environment env = macro::Environment();
macro::Driver m(env, no_line_macro_arg);
m.parse(filename, basename, modfile, macro_output, debug, defines, paths);
macro::Driver m;
/* Calling string() method on filename: not necessary on GNU/Linux and macOS because there is an
implicit conversion from filesystem:path to string (i.e. basic_string<char>), but needed on
Windows because the implicit conversion is only to wstring (i.e. basic_string<wchar_t>). */
m.parse(filename.string(), modfile, debug, defines, env, paths, macro_output);
if (save_macro)
{
if (save_macro_file.empty())
save_macro_file = basename + "-macroexp.mod";
ofstream macro_output_file(save_macro_file);
save_macro_file = filename.stem().string() + "_macroexp.mod";
ofstream macro_output_file {save_macro_file};
if (macro_output_file.fail())
{
cerr << "Cannot open " << save_macro_file << " for macro output" << endl;
cerr << "Cannot open " << save_macro_file.string() << " for macro output" << endl;
exit(EXIT_FAILURE);
}
string str(macro_output.str());
if (no_empty_line_macro)
if (!line_macro)
{
str.erase(0, str.find_first_not_of('\n'));
str.erase(unique(str.begin(), str.end(), compareNewline), str.end());
/* Remove the @#line directives.
Unfortunately GCC 11 does not yet support std::regex::multiline
(despite it being in the C++17 standard), so we are forced to use
a trick to emulate the “usual” behaviour of the caret ^;
here, the latter only matches the beginning of file.
This also means that we are forced to remove the EOL before the
@#line, and not the one after it (matching the EOL before and the
EOL after in the same regexp does not work). */
str = regex_replace(str, regex(R"((^|\r?\n)@#line.*)"), "");
/* Remove the EOLs at the beginning of the output, the first one
being a remnant of the first @#line directive. */
str = regex_replace(str, regex(R"(^(\r?\n)+)"), "");
/* Replace sequences of several newlines by a single newline (in
both LF and CR+LF conventions). */
str = regex_replace(str, regex(R"(\n{2,})"), "\n");
str = regex_replace(str, regex(R"((\r\n){2,})"), "\r\n");
}
macro_output_file << str;
macro_output_file.close();
}
return macro_output;
}
SUBDIRS = macro
BUILT_SOURCES = DynareBison.hh location.hh DynareBison.cc DynareFlex.cc FlexLexer.h
bin_PROGRAMS = dynare_m
# We don't put BUILT_SOURCES in dynare_m_SOURCES, otherwise DynareBison.o and DynareFlex.o will be linked two times (Automake translates DynareFlex.ll and DynareBison.yy into their respective .o); so BUILT_SOURCES is in EXTRA_DIST
dynare_m_SOURCES = \
DynareFlex.ll \
DynareBison.yy \
ComputingTasks.cc \
ComputingTasks.hh \
ModelTree.cc \
ModelTree.hh \
StaticModel.cc \
StaticModel.hh \
DynamicModel.cc \
DynamicModel.hh \
NumericalConstants.cc \
NumericalConstants.hh \
NumericalInitialization.cc \
NumericalInitialization.hh \
Shocks.cc \
Shocks.hh \
SigmaeInitialization.cc \
SigmaeInitialization.hh \
SymbolTable.cc \
SymbolTable.hh \
SymbolList.cc \
SymbolList.hh \
ParsingDriver.cc \
ParsingDriver.hh \
DataTree.cc \
DataTree.hh \
ModFile.cc \
ModFile.hh \
ConfigFile.cc \
ConfigFile.hh \
Statement.cc \
Statement.hh \
ExprNode.cc \
ExprNode.hh \
MinimumFeedbackSet.cc \
MinimumFeedbackSet.hh \
DynareMain.cc \
DynareMain1.cc \
DynareMain2.cc \
CodeInterpreter.hh \
ExternalFunctionsTable.cc \
ExternalFunctionsTable.hh \
ModelEquationBlock.hh \
ModelEquationBlock.cc \
WarningConsolidation.hh \
WarningConsolidation.cc \
ExtendedPreprocessorTypes.hh \
SubModel.cc \
SubModel.hh
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = \
Doxyfile \
$(BUILT_SOURCES)
# The -I. is for <FlexLexer.h>
dynare_m_CPPFLAGS = $(BOOST_CPPFLAGS) -I.
dynare_m_LDFLAGS = $(AM_LDFLAGS) $(BOOST_LDFLAGS)
dynare_m_LDADD = macro/libmacro.a -lstdc++fs
DynareFlex.cc: DynareFlex.ll
$(LEX) -o DynareFlex.cc DynareFlex.ll
FlexLexer.h:
cp $(LEXINC)/FlexLexer.h . || test -f ./FlexLexer.h
dynare_m-DynareFlex.$(OBJEXT): CXXFLAGS += -Wno-old-style-cast
# We do not use a multiple target rule for Bison, because otherwise it will be
# run several times in parallel builds
DynareBison.cc: DynareBison.yy
$(YACC) -W -o $@ $<
DynareBison.hh location.hh: DynareBison.cc
all-local: $(PROGRAMS)
if HAVE_DOXYGEN
html-local:
$(DOXYGEN)
endif
clean-local:
rm -rf doc/html/
/*
* Copyright © 2009-2017 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include "MinimumFeedbackSet.hh"
using namespace boost;
namespace MFS
{
void
Suppress(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G)
{
clear_vertex(vertex_to_eliminate, G);
remove_vertex(vertex_to_eliminate, G);
}
void
Suppress(int vertex_num, AdjacencyList_t &G)
{
Suppress(vertex(vertex_num, G), G);
}
void
Eliminate(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G)
{
if (in_degree(vertex_to_eliminate, G) > 0 && out_degree(vertex_to_eliminate, G) > 0)
{
AdjacencyList_t::in_edge_iterator it_in, in_end;
AdjacencyList_t::out_edge_iterator it_out, out_end;
for (tie(it_in, in_end) = in_edges(vertex_to_eliminate, G); it_in != in_end; ++it_in)
for (tie(it_out, out_end) = out_edges(vertex_to_eliminate, G); it_out != out_end; ++it_out)
{
AdjacencyList_t::edge_descriptor ed;
bool exist;
tie(ed, exist) = edge(source(*it_in, G), target(*it_out, G), G);
if (!exist)
add_edge(source(*it_in, G), target(*it_out, G), G);
}
}
Suppress(vertex_to_eliminate, G);
}
bool
has_cycle_dfs(AdjacencyList_t &g, AdjacencyList_t::vertex_descriptor u, color_t &color, vector<int> &circuit_stack)
{
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, g);
color[u] = gray_color;
graph_traits<AdjacencyList_t>::out_edge_iterator vi, vi_end;
for (tie(vi, vi_end) = out_edges(u, g); vi != vi_end; ++vi)
if (color[target(*vi, g)] == white_color && has_cycle_dfs(g, target(*vi, g), color, circuit_stack))
{
// cycle detected, return immediately
circuit_stack.push_back(v_index[target(*vi, g)]);
return true;
}
else if (color[target(*vi, g)] == gray_color)
{
// *vi is an ancestor!
circuit_stack.push_back(v_index[target(*vi, g)]);
return true;
}
color[u] = black_color;
return false;
}
bool
has_cycle(vector<int> &circuit_stack, AdjacencyList_t &g)
{
// Initialize color map to white
color_t color;
graph_traits<AdjacencyList_t>::vertex_iterator vi, vi_end;
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
color[*vi] = white_color;
// Perform depth-first search
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
if (color[*vi] == white_color && has_cycle_dfs(g, *vi, color, circuit_stack))
return true;
return false;
}
void
Print(AdjacencyList_t &G)
{
AdjacencyList_t::vertex_iterator it, it_end;
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "Graph\n";
cout << "-----\n";
for (tie(it, it_end) = vertices(G); it != it_end; ++it)
{
cout << "vertex[" << v_index[*it] + 1 << "] <-";
AdjacencyList_t::in_edge_iterator it_in, in_end;
for (tie(it_in, in_end) = in_edges(*it, G); it_in != in_end; ++it_in)
cout << v_index[source(*it_in, G)] + 1 << " ";
cout << "\n ->";
AdjacencyList_t::out_edge_iterator it_out, out_end;
for (tie(it_out, out_end) = out_edges(*it, G); it_out != out_end; ++it_out)
cout << v_index[target(*it_out, G)] + 1 << " ";
cout << "\n";
}
}
AdjacencyList_t
AM_2_AdjacencyList(bool *AM, unsigned int n)
{
AdjacencyList_t G(n);
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
for (unsigned int i = 0; i < n; i++)
{
put(v_index, vertex(i, G), i);
put(v_index1, vertex(i, G), i);
}
for (unsigned int i = 0; i < n; i++)
for (unsigned int j = 0; j < n; j++)
if (AM[i*n+j])
add_edge(vertex(j, G), vertex(i, G), G);
return G;
}
AdjacencyList_t
extract_subgraph(AdjacencyList_t &G1, set<int> select_index)
{
unsigned int n = select_index.size();
AdjacencyList_t G(n);
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
property_map<AdjacencyList_t, vertex_index_t>::type v1_index = get(vertex_index, G1);
map<int, int> reverse_index;
set<int>::iterator it;
unsigned int i;
for (it = select_index.begin(), i = 0; i < n; i++, ++it)
{
reverse_index[get(v1_index, vertex(*it, G1))] = i;
put(v_index, vertex(i, G), get(v1_index, vertex(*it, G1)));
put(v_index1, vertex(i, G), i);
}
for (it = select_index.begin(), i = 0; i < n; i++, ++it)
{
AdjacencyList_t::out_edge_iterator it_out, out_end;
AdjacencyList_t::vertex_descriptor vi = vertex(*it, G1);
for (tie(it_out, out_end) = out_edges(vi, G1); it_out != out_end; ++it_out)
{
int ii = v1_index[target(*it_out, G1)];
if (select_index.find(ii) != select_index.end())
add_edge(vertex(reverse_index[get(v1_index, source(*it_out, G1))], G), vertex(reverse_index[get(v1_index, target(*it_out, G1))], G), G);
}
}
return G;
}
vector_vertex_descriptor_t
Collect_Doublet(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G)
{
AdjacencyList_t::in_edge_iterator it_in, in_end;
AdjacencyList_t::out_edge_iterator it_out, out_end;
vector<AdjacencyList_t::vertex_descriptor> Doublet;
if (in_degree(vertex, G) > 0 && out_degree(vertex, G) > 0)
for (tie(it_in, in_end) = in_edges(vertex, G); it_in != in_end; ++it_in)
for (tie(it_out, out_end) = out_edges(vertex, G); it_out != out_end; ++it_out)
if (source(*it_in, G) == target(*it_out, G) && source(*it_in, G) != target(*it_in, G)) // not a loop
Doublet.push_back(source(*it_in, G));
return Doublet;
}
bool
Vertex_Belong_to_a_Clique(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G)
{
vector<AdjacencyList_t::vertex_descriptor> liste;
bool agree = true;
AdjacencyList_t::in_edge_iterator it_in, in_end;
AdjacencyList_t::out_edge_iterator it_out, out_end;
tie(it_in, in_end) = in_edges(vertex, G);
tie(it_out, out_end) = out_edges(vertex, G);
while (it_in != in_end && it_out != out_end && agree)
{
agree = (source(*it_in, G) == target(*it_out, G) && source(*it_in, G) != target(*it_in, G)); //not a loop
liste.push_back(source(*it_in, G));
++it_in;
++it_out;
}
if (agree)
{
if (it_in != in_end || it_out != out_end)
agree = false;
unsigned int i = 1;
while (i < liste.size() && agree)
{
unsigned int j = i + 1;
while (j < liste.size() && agree)
{
AdjacencyList_t::edge_descriptor ed;
bool exist1, exist2;
tie(ed, exist1) = edge(liste[i], liste[j], G);
tie(ed, exist2) = edge(liste[j], liste[i], G);
agree = (exist1 && exist2);
j++;
}
i++;
}
}
return agree;
}
bool
Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(AdjacencyList_t &G)
{
bool something_has_been_done = false;
bool not_a_loop;
int i;
AdjacencyList_t::vertex_iterator it, it1, ita, it_end;
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
{
int in_degree_n = in_degree(*it, G);
int out_degree_n = out_degree(*it, G);
if (in_degree_n <= 1 || out_degree_n <= 1)
{
not_a_loop = true;
if (in_degree_n >= 1 && out_degree_n >= 1) // Do not eliminate a vertex if it loops on itself!
{
AdjacencyList_t::in_edge_iterator it_in, in_end;
for (tie(it_in, in_end) = in_edges(*it, G); it_in != in_end; ++it_in)
if (source(*it_in, G) == target(*it_in, G))
{
#ifdef verbose
cout << v_index[source(*it_in, G)] << " == " << v_index[target(*it_in, G)] << "\n";
#endif
not_a_loop = false;
}
}
if (not_a_loop)
{
#ifdef verbose
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "->eliminate vertex[" << v_index[*it] + 1 << "]\n";
#endif
Eliminate(*it, G);
#ifdef verbose
Print(G);
#endif
something_has_been_done = true;
if (i > 0)
it = ita;
else
{
tie(it, it_end) = vertices(G);
i--;
}
}
}
ita = it;
}
return something_has_been_done;
}
bool
Elimination_of_Vertex_belonging_to_a_clique_Step(AdjacencyList_t &G)
{
AdjacencyList_t::vertex_iterator it, it1, ita, it_end;
bool something_has_been_done = false;
int i;
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
{
if (Vertex_Belong_to_a_Clique(*it, G))
{
#ifdef verbose
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "eliminate vertex[" << v_index[*it] + 1 << "]\n";
#endif
Eliminate(*it, G);
something_has_been_done = true;
if (i > 0)
it = ita;
else
{
tie(it, it_end) = vertices(G);
i--;
}
}
ita = it;
}
return something_has_been_done;
}
bool
Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(set<int> &feed_back_vertices, AdjacencyList_t &G)
{
bool something_has_been_done = false;
AdjacencyList_t::vertex_iterator it, it_end, ita;
int i = 0;
for (tie(it, it_end) = vertices(G); it != it_end; ++it, i++)
{
AdjacencyList_t::edge_descriptor ed;
bool exist;
tie(ed, exist) = edge(*it, *it, G);
if (exist)
{
#ifdef verbose
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "store v[*it] = " << v_index[*it]+1 << "\n";
#endif
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
feed_back_vertices.insert(v_index1[*it]);
/*property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
feed_back_vertices.insert(v_index[*it] );*/
Suppress(*it, G);
something_has_been_done = true;
if (i > 0)
it = ita;
else
{
tie(it, it_end) = vertices(G);
i--;
}
}
ita = it;
}
return something_has_been_done;
}
AdjacencyList_t
Minimal_set_of_feedback_vertex(set<int> &feed_back_vertices, const AdjacencyList_t &G1)
{
bool something_has_been_done = true;
int cut_ = 0;
feed_back_vertices.clear();
AdjacencyList_t G(G1);
while (num_vertices(G) > 0)
{
while (something_has_been_done && num_vertices(G) > 0)
{
//Rule 1
something_has_been_done = (Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(G) /*or something_has_been_done*/);
#ifdef verbose
cout << "1 something_has_been_done=" << something_has_been_done << "\n";
#endif
//Rule 2
something_has_been_done = (Elimination_of_Vertex_belonging_to_a_clique_Step(G) || something_has_been_done);
#ifdef verbose
cout << "2 something_has_been_done=" << something_has_been_done << "\n";
#endif
//Rule 3
something_has_been_done = (Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(feed_back_vertices, G) || something_has_been_done);
#ifdef verbose
cout << "3 something_has_been_done=" << something_has_been_done << "\n";
#endif
}
vector<int> circuit;
if (!has_cycle(circuit, G))
{
#ifdef verbose
cout << "has_cycle=false\n";
#endif
//sort(feed_back_vertices.begin(), feed_back_vertices.end());
return G;
}
if (num_vertices(G) > 0)
{
/*if nothing has been done in the five previous rule then cut the vertex with the maximum in_degree+out_degree*/
unsigned int max_degree = 0, num = 0;
AdjacencyList_t::vertex_iterator it, it_end, max_degree_index;
for (tie(it, it_end) = vertices(G); it != it_end; ++it, num++)
{
if (in_degree(*it, G) + out_degree(*it, G) > max_degree)
{
max_degree = in_degree(*it, G) + out_degree(*it, G);
max_degree_index = it;
}
}
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
feed_back_vertices.insert(v_index1[*max_degree_index]);
/*property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
feed_back_vertices.insert(v_index[*max_degree_index]);*/
//cout << "v_index1[*max_degree_index] = " << v_index1[*max_degree_index] << "\n";
cut_++;
#ifdef verbose
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "--> cut vertex " << v_index[*max_degree_index] + 1 << "\n";
#endif
Suppress(*max_degree_index, G);
something_has_been_done = true;
}
}
#ifdef verbose
cout << "cut_=" << cut_ << "\n";
#endif
//sort(feed_back_vertices.begin(), feed_back_vertices.end());
return G;
}
struct rev
{
bool
operator()(const int a, const int b) const
{
return (a > b);
}
};
void
Reorder_the_recursive_variables(const AdjacencyList_t &G1, set<int> &feedback_vertices, vector< int> &Reordered_Vertices)
{
AdjacencyList_t G(G1);
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
set<int>::iterator its, ita;
set<int, rev> fv;
for (its = feedback_vertices.begin(); its != feedback_vertices.end(); its++)
fv.insert(*its);
int i = 0;
for (its = fv.begin(); its != fv.end(); ++its, i++)
Suppress(*its, G);
bool something_has_been_done = true;
while (something_has_been_done)
{
something_has_been_done = false;
AdjacencyList_t::vertex_iterator it, it_end, ita;
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
{
if (in_degree(*it, G) == 0)
{
Reordered_Vertices.push_back(v_index[*it]);
Suppress(*it, G);
something_has_been_done = true;
if (i > 0)
it = ita;
else
{
tie(it, it_end) = vertices(G);
i--;
}
}
ita = it;
}
}
if (num_vertices(G))
cout << "Error in the computation of feedback vertex set\n";
}
}
/*
* Copyright © 2009-2019 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MINIMUMFEEDBACKSET_HH
#define _MINIMUMFEEDBACKSET_HH
#include <map>
#include <vector>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/graph/adjacency_list.hpp>
#pragma GCC diagnostic pop
using namespace std;
namespace MFS
{
using VertexProperty_t = boost::property<boost::vertex_index_t, int,
boost::property<boost::vertex_index1_t, int,
boost::property<boost::vertex_degree_t, int,
boost::property<boost::vertex_in_degree_t, int,
boost::property<boost::vertex_out_degree_t, int >>>>>;
using AdjacencyList_t = boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, VertexProperty_t>;
using color_t = map<boost::graph_traits<AdjacencyList_t>::vertex_descriptor, boost::default_color_type>;
using vector_vertex_descriptor_t = vector<AdjacencyList_t::vertex_descriptor>;
//! Eliminate a vertex i
/*! For a vertex i replace all edges e_k_i and e_i_j by a shorcut e_k_j and then Suppress the vertex i*/
void Eliminate(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G);
//! Collect all doublets (edges e_i_k such that there is an edge e_k_i with k!=i in the graph)
/*! Returns the vector of doublets */
vector_vertex_descriptor_t Collect_Doublet(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G);
//! Detect all the clique (all vertex in a clique are related to each other) in the graph
bool Vertex_Belong_to_a_Clique(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G);
//! Graph reduction: eliminating purely intermediate variables or variables outside of any circuit
bool Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(AdjacencyList_t &G);
//! Graph reduction: elimination of a vertex inside a clique
bool Elimination_of_Vertex_belonging_to_a_clique_Step(AdjacencyList_t &G);
//! A vertex belong to the feedback vertex set if the vertex loops on itself.
/*! We have to suppress this vertex and store it into the feedback set.*/
bool Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(set<int> &feed_back_vertices, AdjacencyList_t &G1);
//! Print the Graph
void Print(AdjacencyList_t &G);
//! Create an adjacency graph from a Adjacency Matrix (an incidence Matrix without the diagonal terms)
AdjacencyList_t AM_2_AdjacencyList(bool *AMp, unsigned int n);
//! Extracts a subgraph
/*!
\param[in] G1 The original graph
\param[in] select_index The vertex indices to select
\return The subgraph
The property vertex_index of the subgraph contains indices of the original
graph, the property vertex_index1 contains new contiguous indices specific
to the subgraph.
*/
AdjacencyList_t extract_subgraph(AdjacencyList_t &G1, set<int> select_index);
//! Check if the graph contains any cycle (true if the model contains at least one cycle, false otherwise)
bool has_cycle(vector<int> &circuit_stack, AdjacencyList_t &g);
bool has_cycle_dfs(AdjacencyList_t &g, AdjacencyList_t::vertex_descriptor u, color_t &color, vector<int> &circuit_stack);
//! Return the feedback set
AdjacencyList_t Minimal_set_of_feedback_vertex(set<int> &feed_back_vertices, const AdjacencyList_t &G);
//! Clear all in and out edges of vertex_to_eliminate and remove vertex_to_eliminate from the graph
void Suppress(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G);
void Suppress(int vertex_num, AdjacencyList_t &G);
//! Reorder the recursive variables
/*! They appear first in a quasi triangular form and they are followed by the feedback variables */
void Reorder_the_recursive_variables(const AdjacencyList_t &G1, set<int> &feedback_vertices, vector< int> &Reordered_Vertices);
};
#endif // _MINIMUMFEEDBACKSET_HH
/*
* Copyright © 2006-2019 Dynare Team
* Copyright © 2006-2025 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,51 +14,71 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <typeinfo>
#include <cassert>
#include <iostream>
#include <random>
#include <typeinfo>
#include <filesystem>
#include "ModFile.hh"
#include "ConfigFile.hh"
#include "ComputingTasks.hh"
#include "ModFile.hh"
#include "Shocks.hh"
ModFile::ModFile(WarningConsolidation &warnings_arg)
: var_model_table{symbol_table},
ModFile::ModFile(WarningConsolidation& warnings_arg) :
symbol_table {heterogeneity_table},
var_model_table {symbol_table},
trend_component_model_table {symbol_table},
expressions_tree{symbol_table, num_constants, external_functions_table},
original_model{symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
dynamic_model{symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
trend_dynamic_model{symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
ramsey_FOC_equations_dynamic_model{symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
orig_ramsey_dynamic_model{symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
non_linear_equations_dynamic_model{symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
epilogue{symbol_table, num_constants, external_functions_table,
trend_component_model_table, var_model_table},
static_model{symbol_table, num_constants, external_functions_table},
steady_state_model{symbol_table, num_constants, external_functions_table, static_model},
var_expectation_model_table {symbol_table},
pac_model_table {symbol_table},
expressions_tree {symbol_table, num_constants, external_functions_table, heterogeneity_table},
original_model {symbol_table,
num_constants,
external_functions_table,
heterogeneity_table,
trend_component_model_table,
var_model_table},
dynamic_model {symbol_table,
num_constants,
external_functions_table,
heterogeneity_table,
trend_component_model_table,
var_model_table},
trend_dynamic_model {symbol_table,
num_constants,
external_functions_table,
heterogeneity_table,
trend_component_model_table,
var_model_table},
orig_ramsey_dynamic_model {symbol_table,
num_constants,
external_functions_table,
heterogeneity_table,
trend_component_model_table,
var_model_table},
epilogue {symbol_table,
num_constants,
external_functions_table,
heterogeneity_table,
trend_component_model_table,
var_model_table},
static_model {symbol_table, num_constants, external_functions_table, heterogeneity_table},
steady_state_model {symbol_table, num_constants, external_functions_table, heterogeneity_table,
static_model},
warnings {warnings_arg}
{
heterogeneity_table.setSymbolTable(&symbol_table);
}
void
ModFile::evalAllExpressions(bool warn_uninit)
{
cout << "Evaluating expressions...";
cout << "Evaluating expressions..." << endl;
// Loop over all statements, and fill global eval context if relevant
for (auto& st : statements)
......@@ -76,18 +96,17 @@ ModFile::evalAllExpressions(bool warn_uninit)
// Evaluate model local variables
dynamic_model.fillEvalContext(global_eval_context);
cout << "done" << endl;
// Check if some symbols are not initialized, and give them a zero value then
for (int id = 0; id <= symbol_table.maxID(); id++)
if (auto type = symbol_table.getType(id);
(type == SymbolType::endogenous || type == SymbolType::exogenous || type == SymbolType::exogenousDet
|| type == SymbolType::parameter || type == SymbolType::modelLocalVariable)
&& global_eval_context.find(id) == global_eval_context.end())
(type == SymbolType::endogenous || type == SymbolType::exogenous
|| type == SymbolType::exogenousDet || type == SymbolType::parameter
|| type == SymbolType::modelLocalVariable)
&& !global_eval_context.contains(id))
{
if (warn_uninit)
warnings << "WARNING: Can't find a numeric initial value for "
<< symbol_table.getName(id) << ", using zero" << endl;
warnings << "WARNING: Can't find a numeric initial value for " << symbol_table.getName(id)
<< ", using zero" << endl;
global_eval_context[id] = 0;
}
}
......@@ -114,12 +133,16 @@ ModFile::checkPass(bool nostrict, bool stochastic)
steady_state_model.checkPass(mod_file_struct, warnings);
// Check epilogue block
epilogue.checkPass(warnings);
epilogue.checkPass(mod_file_struct);
if (mod_file_struct.write_latex_steady_state_model_present &&
!mod_file_struct.steady_state_model_present)
pac_model_table.checkPass(mod_file_struct);
if (mod_file_struct.write_latex_steady_state_model_present
&& !mod_file_struct.steady_state_model_present)
{
cerr << "ERROR: You cannot have a write_latex_steady_state_model statement without a steady_state_model block." << endl;
cerr << "ERROR: You cannot have a write_latex_steady_state_model statement without a "
"steady_state_model block."
<< endl;
exit(EXIT_FAILURE);
}
......@@ -131,30 +154,28 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (param_used_with_lead_lag)
warnings << "WARNING: A parameter was used with a lead or a lag in the model block" << endl;
bool stochastic_statement_present = mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present
|| mod_file_struct.osr_present
|| mod_file_struct.ramsey_policy_present
|| mod_file_struct.discretionary_policy_present
|| mod_file_struct.calib_smoother_present
|| mod_file_struct.identification_present
|| mod_file_struct.sensitivity_present
bool stochastic_statement_present
= mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present
|| mod_file_struct.osr_present || mod_file_struct.discretionary_policy_present
|| mod_file_struct.calib_smoother_present || mod_file_struct.identification_present
|| mod_file_struct.mom_estimation_present || mod_file_struct.sensitivity_present
|| stochastic;
// Allow empty model only when doing a standalone BVAR estimation
if (dynamic_model.equation_number() == 0
&& (mod_file_struct.check_present
|| mod_file_struct.perfect_foresight_solver_present
&& (mod_file_struct.check_present || mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
|| stochastic_statement_present))
{
cerr << "ERROR: At least one model equation must be declared!" << endl;
exit(EXIT_FAILURE);
}
if ((mod_file_struct.ramsey_model_present || mod_file_struct.ramsey_policy_present)
&& mod_file_struct.discretionary_policy_present)
if (mod_file_struct.ramsey_model_present && mod_file_struct.discretionary_policy_present)
{
cerr << "ERROR: You cannot use the discretionary_policy command when you use either ramsey_model or ramsey_policy and vice versa" << endl;
cerr << "ERROR: You cannot use the discretionary_policy command when you use either "
"ramsey_model or ramsey_policy and vice versa"
<< endl;
exit(EXIT_FAILURE);
}
......@@ -163,64 +184,63 @@ ModFile::checkPass(bool nostrict, bool stochastic)
|| (!(mod_file_struct.ramsey_model_present || mod_file_struct.discretionary_policy_present)
&& mod_file_struct.planner_objective_present))
{
cerr << "ERROR: A planner_objective statement must be used with a ramsey_model, a ramsey_policy or a discretionary_policy statement and vice versa." << endl;
exit(EXIT_FAILURE);
}
if ((mod_file_struct.osr_present && (!mod_file_struct.osr_params_present || !mod_file_struct.optim_weights_present))
|| ((!mod_file_struct.osr_present || !mod_file_struct.osr_params_present) && mod_file_struct.optim_weights_present)
|| ((!mod_file_struct.osr_present || !mod_file_struct.optim_weights_present) && mod_file_struct.osr_params_present))
{
cerr << "ERROR: The osr statement must be used with osr_params and optim_weights." << endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.perfect_foresight_solver_present && stochastic_statement_present)
{
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver,simul} and one of {stoch_simul, estimation, osr, ramsey_policy, discretionary_policy}. This is not possible: one cannot mix perfect foresight context with stochastic context in the same file." << endl;
cerr << "ERROR: A planner_objective statement must be used with a ramsey_model, a "
"ramsey_policy or a discretionary_policy statement and vice versa."
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.k_order_solver && byte_code)
if (!ramsey_constraints.empty() && !mod_file_struct.ramsey_model_present)
{
cerr << "ERROR: 'k_order_solver' (which is implicit if order >= 3), is not yet compatible with 'bytecode'." << endl;
cerr << "ERROR: A ramsey_constraints block requires the presence of a ramsey_model or "
"ramsey_policy statement"
<< endl;
exit(EXIT_FAILURE);
}
if (use_dll && (block || byte_code || linear_decomposition))
if ((mod_file_struct.osr_present
&& (!mod_file_struct.osr_params_present || !mod_file_struct.optim_weights_present))
|| ((!mod_file_struct.osr_present || !mod_file_struct.osr_params_present)
&& mod_file_struct.optim_weights_present)
|| ((!mod_file_struct.osr_present || !mod_file_struct.optim_weights_present)
&& mod_file_struct.osr_params_present))
{
cerr << "ERROR: In 'model' block, 'use_dll' option is not compatible with 'block', 'bytecode' or 'linear_decomposition'" << endl;
exit(EXIT_FAILURE);
}
if (block && linear_decomposition)
{
cerr << "ERROR: In 'model' block, 'block' option is not compatible with 'linear_decomposition'" << endl;
cerr << "ERROR: The osr statement must be used with osr_params and optim_weights." << endl;
exit(EXIT_FAILURE);
}
if (!byte_code && linear_decomposition)
if ((mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
&& stochastic_statement_present)
{
cerr << "ERROR: For the moment in 'model' block, 'linear_decomposition' option is compatible only with 'bytecode' option" << endl;
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, "
"perfect_foresight_with_expectation_errors_solver} and one of {stoch_simul, "
"estimation, osr, ramsey_policy, discretionary_policy}. This is not possible: one "
"cannot mix perfect foresight context with stochastic context in the same file."
<< endl;
exit(EXIT_FAILURE);
}
if (block || byte_code)
if (dynamic_model.isModelLocalVariableUsed())
if (use_dll && bytecode)
{
cerr << "ERROR: In 'model' block, 'block' or 'bytecode' options are not yet compatible with pound expressions" << endl;
cerr << "ERROR: In 'model' block, 'use_dll' option is not compatible with 'bytecode'" << endl;
exit(EXIT_FAILURE);
}
if ((stochastic_statement_present || mod_file_struct.check_present || mod_file_struct.steady_present) && no_static)
if ((stochastic_statement_present || mod_file_struct.check_present
|| mod_file_struct.steady_present)
&& no_static)
{
cerr << "ERROR: no_static option is incompatible with stoch_simul, estimation, osr, ramsey_policy, discretionary_policy, steady and check commands" << endl;
cerr << "ERROR: no_static option is incompatible with stoch_simul, estimation, osr, "
"ramsey_policy, discretionary_policy, steady and check commands"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.dsge_var_estimated)
if (!mod_file_struct.dsge_prior_weight_in_estimated_params)
if (mod_file_struct.dsge_var_estimated && !mod_file_struct.dsge_prior_weight_in_estimated_params)
{
cerr << "ERROR: When estimating a DSGE-VAR model and estimating the weight of the prior, dsge_prior_weight must "
cerr << "ERROR: When estimating a DSGE-VAR model and estimating the weight of the prior, "
"dsge_prior_weight must "
<< "be referenced in the estimated_params block." << endl;
exit(EXIT_FAILURE);
}
......@@ -239,19 +259,23 @@ ModFile::checkPass(bool nostrict, bool stochastic)
if (mod_file_struct.dsge_var_estimated || !mod_file_struct.dsge_var_calibrated.empty())
{
cerr << "ERROR: dsge_prior_weight can either be declared as a parameter (deprecated) or via the dsge_var option "
cerr << "ERROR: dsge_prior_weight can either be declared as a parameter (deprecated) or "
"via the dsge_var option "
<< "to the estimation statement (preferred), but not both." << endl;
exit(EXIT_FAILURE);
}
if (!mod_file_struct.dsge_prior_weight_initialized && !mod_file_struct.dsge_prior_weight_in_estimated_params)
if (!mod_file_struct.dsge_prior_weight_initialized
&& !mod_file_struct.dsge_prior_weight_in_estimated_params)
{
cerr << "ERROR: If dsge_prior_weight is declared as a parameter, it must either be initialized or placed in the "
cerr << "ERROR: If dsge_prior_weight is declared as a parameter, it must either be "
"initialized or placed in the "
<< "estimated_params block." << endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.dsge_prior_weight_initialized && mod_file_struct.dsge_prior_weight_in_estimated_params)
if (mod_file_struct.dsge_prior_weight_initialized
&& mod_file_struct.dsge_prior_weight_in_estimated_params)
{
cerr << "ERROR: dsge_prior_weight cannot be both initialized and estimated." << endl;
exit(EXIT_FAILURE);
......@@ -259,29 +283,43 @@ ModFile::checkPass(bool nostrict, bool stochastic)
}
if (mod_file_struct.dsge_prior_weight_in_estimated_params)
{
if (!mod_file_struct.dsge_var_estimated && !mod_file_struct.dsge_var_calibrated.empty())
{
cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, the prior weight cannot be calibrated "
cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, the prior weight "
"cannot be calibrated "
<< "via the dsge_var option in the estimation statement." << endl;
exit(EXIT_FAILURE);
}
else if (!mod_file_struct.dsge_var_estimated && !symbol_table.exists("dsge_prior_weight"))
{
cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, it must either be declared as a parameter "
<< "(deprecated) or the dsge_var option must be passed to the estimation statement (preferred)." << endl;
cerr << "ERROR: If dsge_prior_weight is in the estimated_params block, it must either be "
"declared as a parameter "
<< "(deprecated) or the dsge_var option must be passed to the estimation statement "
"(preferred)."
<< endl;
exit(EXIT_FAILURE);
}
}
/* This check must come before checking that there are as many static-only as dynamic-only
equations, see #103 */
dynamic_model.checkOccbinRegimes();
if (dynamic_model.staticOnlyEquationsNbr() != dynamic_model.dynamicOnlyEquationsNbr())
{
cerr << "ERROR: the number of equations marked [static] must be equal to the number of equations marked [dynamic]" << endl;
cerr << "ERROR: the number of equations marked [static] must be equal to the number of "
"equations marked [dynamic]"
<< endl;
exit(EXIT_FAILURE);
}
if (dynamic_model.staticOnlyEquationsNbr() > 0
&& (mod_file_struct.ramsey_model_present || mod_file_struct.discretionary_policy_present))
{
cerr << "ERROR: marking equations as [static] or [dynamic] is not possible with ramsey_model, ramsey_policy or discretionary_policy" << endl;
cerr << "ERROR: marking equations as [static] or [dynamic] is not possible with "
"ramsey_model, ramsey_policy or discretionary_policy"
<< endl;
exit(EXIT_FAILURE);
}
......@@ -296,7 +334,9 @@ ModFile::checkPass(bool nostrict, bool stochastic)
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::lessEqual)
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::equalEqual)
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::different)))
warnings << R"(WARNING: you are using a function (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) which is unsuitable for a stochastic context; see the reference manual, section about "Expressions", for more details.)" << endl;
warnings
<< R"(WARNING: you are using a function (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) which is unsuitable for a stochastic context; see the reference manual, section about "Expressions", for more details.)"
<< endl;
if (linear
&& (dynamic_model.isUnaryOpUsedOnType(SymbolType::endogenous, UnaryOpcode::sign)
......@@ -316,8 +356,8 @@ ModFile::checkPass(bool nostrict, bool stochastic)
exit(EXIT_FAILURE);
}
if (linear
&& !mod_file_struct.perfect_foresight_solver_present
if (linear && !mod_file_struct.perfect_foresight_solver_present
&& !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
&& (dynamic_model.isUnaryOpUsedOnType(SymbolType::exogenous, UnaryOpcode::sign)
|| dynamic_model.isUnaryOpUsedOnType(SymbolType::exogenous, UnaryOpcode::abs)
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::max)
......@@ -338,30 +378,28 @@ ModFile::checkPass(bool nostrict, bool stochastic)
// Test if some estimated parameters are used within the values of shocks
// statements (see issue #469)
set<int> parameters_intersect;
set_intersection(mod_file_struct.parameters_within_shocks_values.begin(),
mod_file_struct.parameters_within_shocks_values.end(),
mod_file_struct.estimated_parameters.begin(),
mod_file_struct.estimated_parameters.end(),
ranges::set_intersection(mod_file_struct.parameters_within_shocks_values,
mod_file_struct.estimated_parameters,
inserter(parameters_intersect, parameters_intersect.begin()));
if (parameters_intersect.size() > 0)
{
cerr << "ERROR: some estimated parameters (";
for (auto it = parameters_intersect.begin();
it != parameters_intersect.end();)
for (bool printed_something {false}; int symb_id : parameters_intersect)
{
cerr << symbol_table.getName(*it);
if (++it != parameters_intersect.end())
if (exchange(printed_something, true))
cerr << ", ";
cerr << symbol_table.getName(symb_id);
}
cerr << ") also appear in the expressions defining the variance/covariance matrix of shocks; this is not allowed." << endl;
cerr << ") also appear in the expressions defining the variance/covariance matrix of shocks; "
"this is not allowed."
<< endl;
exit(EXIT_FAILURE);
}
// Check if some exogenous is not used in the model block, Issue #841
set<int> unusedExo0 = dynamic_model.findUnusedExogenous();
set<int> unusedExo;
set_difference(unusedExo0.begin(), unusedExo0.end(),
mod_file_struct.pac_params.begin(), mod_file_struct.pac_params.end(),
ranges::set_difference(unusedExo0, mod_file_struct.pac_params,
inserter(unusedExo, unusedExo.begin()));
if (unusedExo.size() > 0)
{
......@@ -374,17 +412,137 @@ ModFile::checkPass(bool nostrict, bool stochastic)
<< "not used in model block, removed by nostrict command-line option" << endl;
else
{
cerr << "ERROR: " << unused_exos.str() << "not used in model block. To bypass this error, use the `nostrict` option. This may lead to crashes or unexpected behavior." << endl;
cerr << "ERROR: " << unused_exos.str()
<< "not used in model block. To bypass this error, use the `nostrict` option. This "
"may lead to crashes or unexpected behavior."
<< endl;
exit(EXIT_FAILURE);
}
}
if (!heterogeneity_table.empty())
{
if (block)
{
cerr << "ERROR: the 'block' option of the 'model' block is not supported for "
"heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.check_present)
{
cerr << "ERROR: The 'check' command is not supported for heterogeneous models" << endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.steady_present)
{
cerr << "ERROR: The 'steady' command is not supported for heterogeneous models" << endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.perfect_foresight_solver_present)
{
cerr << "ERROR: The 'perfect_foresight_solver' command is not supported for "
"heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
cerr << "ERROR: The 'perfect_foresight_with_expectation_errors_solver' command is not "
"supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.stoch_simul_present)
{
cerr << "ERROR: The 'stoch_simul' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.estimation_present)
{
cerr << "ERROR: The 'estimation' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.osr_present)
{
cerr << "ERROR: The 'osr' command is not supported for heterogeneous models" << endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.osr_params_present)
{
cerr << "ERROR: The 'osr_params' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.optim_weights_present)
{
cerr << "ERROR: The 'optim_weights' block is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.ramsey_model_present)
{
cerr << "ERROR: The 'ramsey_model' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.discretionary_policy_present)
{
cerr << "ERROR: The 'discretionary_policy' command is not supported for heterogeneous "
"models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.planner_objective_present)
{
cerr << "ERROR: The 'planner_objective' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.extended_path_present)
{
cerr << "ERROR: The 'extended_path' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.identification_present)
{
cerr << "ERROR: The 'identification' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.sensitivity_present)
{
cerr << "ERROR: The 'sensitivity' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.mom_estimation_present)
{
cerr
<< "ERROR: The 'methods_of_moments' command is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.occbin_constraints_present)
{
cerr << "ERROR: The 'occbin_constraints' block is not supported for heterogeneous models"
<< endl;
exit(EXIT_FAILURE);
}
}
}
void
ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool transform_unary_ops,
ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, bool transform_unary_ops,
const string& exclude_eqs, const string& include_eqs)
{
/* Save the original model (must be done before any model transformations by preprocessor)
— except predetermined variables (which must be handled before the call to
setLeadsLagsOrig(), see #47, and also before equation simplification,
since the latter uses leads/lags, see #83)
— except substituting out variables which we know are constant (they
appear in an equation of the form: X = constant)
— except adl operators which we always want expanded
......@@ -393,12 +551,17 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
*/
dynamic_model.includeExcludeEquations(exclude_eqs, true);
dynamic_model.includeExcludeEquations(include_eqs, false);
if (symbol_table.predeterminedNbr() > 0)
dynamic_model.transformPredeterminedVariables();
dynamic_model.simplifyEquations();
dynamic_model.substituteAdl();
dynamic_model.setLeadsLagsOrig();
original_model = dynamic_model;
dynamic_model.expandEqTags();
// Replace all model-local variables by their expression
dynamic_model.substituteModelLocalVariables();
// Check that all declared endogenous are used in equations
set<int> unusedEndogs = dynamic_model.findUnusedEndogenous();
bool unusedEndogsIsErr = !nostrict && !mod_file_struct.bvar_present && unusedEndogs.size();
......@@ -410,101 +573,59 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
<< "' not used in model block, removed by nostrict command-line option" << endl;
}
else if (unusedEndogsIsErr)
cerr << "Error: " << symbol_table.getName(unusedEndog) << " not used in the model block"<< endl;
cerr << "Error: " << symbol_table.getName(unusedEndog) << " not used in the model block"
<< endl;
if (unusedEndogsIsErr)
exit(EXIT_FAILURE);
// Declare endogenous used for PAC model-consistent expectations
for (auto & statement : statements)
if (auto pms = dynamic_cast<PacModelStatement *>(statement.get());
pms != nullptr)
{
if (pms->growth != nullptr)
pac_growth.push_back(pms->growth);
if (pms->aux_model_name == "")
dynamic_model.declarePacModelConsistentExpectationEndogs(pms->name);
}
/* Get the list of equations in which to scan for and substitute unary ops:
– equations which are part of VARs and Trend Component Models
– PAC equations (those with a pac_expectation operator) */
set<string> var_tcm_eqtags;
for (const auto& [name, tags] : trend_component_model_table.getEqTags())
for (auto& tag : tags)
var_tcm_eqtags.insert(tag);
for (const auto& [name, tags] : var_model_table.getEqTags())
for (auto& tag : tags)
var_tcm_eqtags.insert(tag);
// Get all equation tags associated with VARs and Trend Component Models
set<string> eqtags;
for (const auto & it : trend_component_model_table.getEqTags())
for (auto & it1 : it.second)
eqtags.insert(it1);
set<int> unary_ops_eqs = dynamic_model.getEquationNumbersFromTags(var_tcm_eqtags);
unary_ops_eqs.merge(dynamic_model.findPacExpectationEquationNumbers());
for (const auto & it : var_model_table.getEqTags())
for (auto & it1 : it.second)
eqtags.insert(it1);
// Check that no variable in VAR/TCM/PAC equations was declared with “var(log)”
dynamic_model.checkNoWithLogTransform(unary_ops_eqs);
// Create auxiliary variables and equations for unary ops
lag_equivalence_table_t unary_ops_nodes;
ExprNode::subst_table_t unary_ops_subst_table;
if (transform_unary_ops)
tie(unary_ops_nodes, unary_ops_subst_table) = dynamic_model.substituteUnaryOps();
tie(unary_ops_nodes, unary_ops_subst_table)
= dynamic_model.substituteUnaryOps(var_expectation_model_table, pac_model_table);
else
// substitute only those unary ops that appear in auxiliary model equations
tie(unary_ops_nodes, unary_ops_subst_table) = dynamic_model.substituteUnaryOps(eqtags);
// substitute only those unary ops that appear in VAR, TCM and PAC model equations
tie(unary_ops_nodes, unary_ops_subst_table) = dynamic_model.substituteUnaryOps(
unary_ops_eqs, var_expectation_model_table, pac_model_table);
// Create auxiliary variable and equations for Diff operators
auto [diff_nodes, diff_subst_table] = dynamic_model.substituteDiff(pac_growth);
auto [diff_nodes, diff_subst_table]
= dynamic_model.substituteDiff(var_expectation_model_table, pac_model_table);
// Fill Trend Component Model Table
// Fill trend component and VAR model tables
dynamic_model.fillTrendComponentModelTable();
original_model.fillTrendComponentModelTableFromOrigModel();
dynamic_model.fillTrendComponentmodelTableAREC(diff_subst_table);
dynamic_model.fillTrendComponentModelTableAREC(diff_subst_table);
dynamic_model.fillVarModelTable();
original_model.fillVarModelTableFromOrigModel();
// Pac Model
int i = 0;
for (auto & statement : statements)
if (auto pms = dynamic_cast<PacModelStatement *>(statement.get()); pms != nullptr)
{
if (pms->growth != nullptr)
pms->overwriteGrowth(pac_growth.at(i++));
// VAR expectation models
var_expectation_model_table.transformPass(diff_subst_table, dynamic_model, var_model_table,
trend_component_model_table);
int max_lag;
vector<int> lhs;
vector<bool> nonstationary;
string aux_model_type;
if (trend_component_model_table.isExistingTrendComponentModelName(pms->aux_model_name))
{
aux_model_type = "trend_component";
max_lag = trend_component_model_table.getMaxLag(pms->aux_model_name) + 1;
lhs = dynamic_model.getUndiffLHSForPac(pms->aux_model_name, diff_subst_table);
// All lhs variables in a trend component model are nonstationary
nonstationary.insert(nonstationary.end(), trend_component_model_table.getDiff(pms->aux_model_name).size(), true);
}
else if (var_model_table.isExistingVarModelName(pms->aux_model_name))
{
aux_model_type = "var";
max_lag = var_model_table.getMaxLag(pms->aux_model_name);
lhs = var_model_table.getLhs(pms->aux_model_name);
// nonstationary variables in a VAR are those that are in diff
nonstationary = var_model_table.getDiff(pms->aux_model_name);
}
else if (pms->aux_model_name == "")
max_lag = 0;
else
{
cerr << "Error: aux_model_name not recognized as VAR model or Trend Component model" << endl;
exit(EXIT_FAILURE);
}
auto eqtag_and_lag = dynamic_model.walkPacParameters(pms->name);
original_model.getPacMaxLag(pms->name, eqtag_and_lag);
if (pms->aux_model_name == "")
dynamic_model.addPacModelConsistentExpectationEquation(pms->name, symbol_table.getID(pms->discount),
eqtag_and_lag, diff_subst_table);
else
dynamic_model.fillPacModelInfo(pms->name, lhs, max_lag, aux_model_type,
eqtag_and_lag, nonstationary, pms->growth);
dynamic_model.substitutePacExpectation(pms->name);
}
dynamic_model.addEquationsForVar();
if (symbol_table.predeterminedNbr() > 0)
dynamic_model.transformPredeterminedVariables();
// PAC model
pac_model_table.transformPass(unary_ops_nodes, unary_ops_subst_table, diff_nodes,
diff_subst_table, dynamic_model, var_model_table,
trend_component_model_table);
// Create auxiliary vars for Expectation operator
dynamic_model.substituteExpectation(mod_file_struct.partial_information);
......@@ -514,23 +635,30 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
dynamic_model.detrendEquations();
trend_dynamic_model = dynamic_model;
dynamic_model.removeTrendVariableFromEquations();
const auto& trend_symbols = dynamic_model.getTrendSymbolsMap();
const auto& nonstationary_symbols = dynamic_model.getNonstationarySymbolsMap();
epilogue.detrend(trend_symbols, nonstationary_symbols);
}
mod_file_struct.orig_eq_nbr = dynamic_model.equation_number();
epilogue.toStatic();
if (mod_file_struct.ramsey_model_present)
{
mod_file_struct.ramsey_orig_eq_nbr = dynamic_model.equation_number();
PlannerObjectiveStatement* pos = nullptr;
for (auto& statement : statements)
if (auto pos2 = dynamic_cast<PlannerObjectiveStatement *>(statement.get()); pos2 != nullptr)
if (pos != nullptr)
if (auto pos2 = dynamic_cast<PlannerObjectiveStatement*>(statement.get()); pos2)
{
if (pos)
{
cerr << "ERROR: there can only be one planner_objective statement" << endl;
exit(EXIT_FAILURE);
}
else
pos = pos2;
assert(pos != nullptr);
const StaticModel &planner_objective = pos->getPlannerObjective();
}
assert(pos);
const PlannerObjective& planner_objective = pos->getPlannerObjective();
/*
clone the model then clone the new equations back to the original because
......@@ -538,98 +666,47 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
*/
if (linear)
orig_ramsey_dynamic_model = dynamic_model;
DynamicModel ramsey_FOC_equations_dynamic_model {symbol_table,
num_constants,
external_functions_table,
heterogeneity_table,
trend_component_model_table,
var_model_table};
ramsey_FOC_equations_dynamic_model = dynamic_model;
ramsey_FOC_equations_dynamic_model.computeRamseyPolicyFOCs(planner_objective);
auto clone_if_not_null
= [&](expr_t e) { return e ? e->clone(ramsey_FOC_equations_dynamic_model) : nullptr; };
map<int, pair<expr_t, expr_t>> cloned_ramsey_constraints;
for (const auto& [symb_id, bounds] : ramsey_constraints)
cloned_ramsey_constraints.try_emplace(symb_id, clone_if_not_null(bounds.first),
clone_if_not_null(bounds.second));
mod_file_struct.ramsey_orig_endo_nbr
= ramsey_FOC_equations_dynamic_model.computeRamseyPolicyFOCs(planner_objective,
cloned_ramsey_constraints);
ramsey_FOC_equations_dynamic_model.replaceMyEquations(dynamic_model);
mod_file_struct.ramsey_eq_nbr = dynamic_model.equation_number() - mod_file_struct.orig_eq_nbr;
}
/* Handle var_expectation_model statements: collect information about them,
create the new corresponding parameters, and the expressions to replace
the var_expectation statements.
TODO: move information collection to checkPass(), within a new
VarModelTable class */
map<string, expr_t> var_expectation_subst_table;
for (auto & statement : statements)
{
auto vems = dynamic_cast<VarExpectationModelStatement *>(statement.get());
if (!vems)
continue;
int max_lag;
vector<int> lhs;
auto &model_name = vems->model_name;
if (var_model_table.isExistingVarModelName(vems->aux_model_name))
{
max_lag = var_model_table.getMaxLag(vems->aux_model_name);
lhs = var_model_table.getLhs(vems->aux_model_name);
}
else if (trend_component_model_table.isExistingTrendComponentModelName(vems->aux_model_name))
{
max_lag = trend_component_model_table.getMaxLag(vems->aux_model_name) + 1;
lhs = dynamic_model.getUndiffLHSForPac(vems->aux_model_name, diff_subst_table);
}
else
{
cerr << "ERROR: var_expectation_model " << model_name
<< " refers to nonexistent auxiliary model " << vems->aux_model_name << endl;
exit(EXIT_FAILURE);
}
/* Substitute unary and diff operators in the 'expression' option, then
match the linear combination in the expression option */
vems->substituteUnaryOpNodes(unary_ops_nodes, unary_ops_subst_table);
vems->substituteDiff(diff_nodes, diff_subst_table);
vems->matchExpression();
dynamic_model.createVariableMapping();
/* Create auxiliary parameters and the expression to be substituted into
the var_expectations statement */
auto subst_expr = dynamic_model.Zero;
for (int lag = 0; lag < max_lag; lag++)
for (auto variable : lhs)
{
string param_name = "var_expectation_model_" + model_name + '_' + symbol_table.getName(variable) + '_' + to_string(lag);
int new_param_id = symbol_table.addSymbol(param_name, SymbolType::parameter);
vems->aux_params_ids.push_back(new_param_id);
// Must come after detrending of variables and Ramsey policy transformation
dynamic_model.substituteLogTransform();
subst_expr = dynamic_model.AddPlus(subst_expr,
dynamic_model.AddTimes(dynamic_model.AddVariable(new_param_id),
dynamic_model.AddVariable(variable, -lag)));
}
if (!heterogeneity_table.empty())
dynamic_model.substituteAggregationOperators();
if (var_expectation_subst_table.find(model_name) != var_expectation_subst_table.end())
{
cerr << "ERROR: model name '" << model_name << "' is used by several var_expectation_model statements" << endl;
exit(EXIT_FAILURE);
}
var_expectation_subst_table[model_name] = subst_expr;
}
// And finally perform the substitutions
dynamic_model.substituteVarExpectation(var_expectation_subst_table);
dynamic_model.createVariableMapping(original_model.equation_number());
if (mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present
|| mod_file_struct.osr_present
|| mod_file_struct.ramsey_policy_present
|| mod_file_struct.discretionary_policy_present
|| mod_file_struct.calib_smoother_present
|| mod_file_struct.identification_present
|| mod_file_struct.sensitivity_present
|| stochastic )
{
// In stochastic models, create auxiliary vars for leads and lags greater than 2, on both endos and exos
dynamic_model.substituteEndoLeadGreaterThanTwo(false);
dynamic_model.substituteExoLead(false);
dynamic_model.substituteEndoLagGreaterThanTwo(false);
dynamic_model.substituteExoLag(false);
}
else
{
// In deterministic models, create auxiliary vars for leads and lags endogenous greater than 2, only on endos (useless on exos)
dynamic_model.substituteEndoLeadGreaterThanTwo(true);
dynamic_model.substituteEndoLagGreaterThanTwo(true);
}
/* Create auxiliary vars for leads and lags greater than 2, on both endos and
exos. The transformation is not exactly the same on stochastic and
deterministic models, because there is no need to take into account the
Jensen inequality on the latter. */
bool deterministic_model
= !(mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present
|| mod_file_struct.osr_present || mod_file_struct.discretionary_policy_present
|| mod_file_struct.calib_smoother_present || mod_file_struct.identification_present
|| mod_file_struct.mom_estimation_present || mod_file_struct.sensitivity_present
|| stochastic);
dynamic_model.substituteEndoLeadGreaterThanTwo(deterministic_model);
dynamic_model.substituteExoLead(deterministic_model);
dynamic_model.substituteEndoLagGreaterThanTwo(deterministic_model);
dynamic_model.substituteExoLag(deterministic_model);
dynamic_model.updateVarAndTrendModel();
......@@ -641,8 +718,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
{
int sid = symbol_table.addSymbol("dsge_prior_weight", SymbolType::parameter);
if (!mod_file_struct.dsge_var_calibrated.empty())
addStatementAtFront(make_unique<InitParamStatement>(sid,
expressions_tree.AddNonNegativeConstant(mod_file_struct.dsge_var_calibrated),
addStatementAtFront(make_unique<InitParamStatement>(
sid, expressions_tree.AddNonNegativeConstant(mod_file_struct.dsge_var_calibrated),
symbol_table));
}
catch (SymbolTable::AlreadyDeclaredException& e)
......@@ -652,6 +729,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
exit(EXIT_FAILURE);
}
dynamic_model.reorderAuxiliaryEquations();
// Freeze the symbol table
symbol_table.freeze();
......@@ -666,33 +745,74 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
*/
if (!(mod_file_struct.ramsey_model_present || mod_file_struct.discretionary_policy_present)
&& !(mod_file_struct.bvar_present && dynamic_model.equation_number() == 0)
&& !(mod_file_struct.occbin_option)
&& (dynamic_model.equation_number() != symbol_table.endo_nbr()))
{
cerr << "ERROR: There are " << dynamic_model.equation_number() << " equations but " << symbol_table.endo_nbr() << " endogenous variables!" << endl;
cerr << "ERROR: There are " << dynamic_model.equation_number() << " equations but "
<< symbol_table.endo_nbr() << " endogenous variables!" << endl;
exit(EXIT_FAILURE);
}
if (symbol_table.exo_det_nbr() > 0 && mod_file_struct.perfect_foresight_solver_present)
if (symbol_table.exo_det_nbr() > 0
&& (mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present))
{
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul} and varexo_det declaration (all exogenous variables are deterministic in this case)" << endl;
cerr << "ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul, "
"perfect_foresight_with_expectation_errors_solver} and varexo_det declaration (all "
"exogenous variables are deterministic in this case)"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.ramsey_policy_present && symbol_table.exo_det_nbr() > 0)
if (mod_file_struct.ramsey_model_present && symbol_table.exo_det_nbr() > 0)
{
cerr << "ERROR: ramsey_policy is incompatible with deterministic exogenous variables" << endl;
cerr << "ERROR: ramsey_model and ramsey_policy are incompatible with deterministic exogenous "
"variables"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.ramsey_policy_present)
for (auto & statement : statements)
if (auto *rps = dynamic_cast<RamseyPolicyStatement *>(statement.get()); rps != nullptr)
rps->checkRamseyPolicyList();
if (mod_file_struct.identification_present && symbol_table.exo_det_nbr() > 0)
{
cerr << "ERROR: identification is incompatible with deterministic exogenous variables" << endl;
cerr << "ERROR: identification is incompatible with deterministic exogenous variables"
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.occbin_constraints_present
&& (mod_file_struct.osr_present || mod_file_struct.mom_estimation_present
|| mod_file_struct.ramsey_model_present || mod_file_struct.discretionary_policy_present
|| mod_file_struct.extended_path_present || mod_file_struct.identification_present
|| mod_file_struct.sensitivity_present))
{
cerr << "ERROR: the 'occbin_constraints' block is not compatible with commands other than "
"'estimation', 'stoch_simul', and 'calib_smoother'."
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.shocks_surprise_present && !mod_file_struct.occbin_constraints_present)
{
cerr << "ERROR: the 'shocks(surprise)' block can only be used in conjunction with the "
"'occbin_constraints' block."
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.shocks_learnt_in_present
&& !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
cerr << "ERROR: the 'shocks(learnt_in=…)' block can only be used in conjunction with the "
"'perfect_foresight_with_expectation_errors_solver' command."
<< endl;
exit(EXIT_FAILURE);
}
if (mod_file_struct.endval_learnt_in_present
&& !mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
cerr << "ERROR: the 'endval(learnt_in=…)' block can only be used in conjunction with the "
"'perfect_foresight_with_expectation_errors_solver' command."
<< endl;
exit(EXIT_FAILURE);
}
......@@ -700,22 +820,25 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
cout << "Found " << dynamic_model.equation_number() << " equation(s)." << endl;
else
{
cout << "Found " << mod_file_struct.orig_eq_nbr << " equation(s)." << endl;
cout << "Found " << dynamic_model.equation_number() << " FOC equation(s) for Ramsey Problem." << endl;
cout << "Found " << mod_file_struct.ramsey_orig_eq_nbr << " equation(s)." << endl;
cout << "Found " << dynamic_model.equation_number() << " FOC equation(s) for Ramsey Problem."
<< endl;
}
if (symbol_table.exists("dsge_prior_weight"))
{
if (mod_file_struct.bayesian_irf_present)
{
if (symbol_table.exo_nbr() != symbol_table.observedVariablesNbr())
{
cerr << "ERROR: When estimating a DSGE-Var and the bayesian_irf option is passed to the estimation "
<< "statement, the number of shocks must equal the number of observed variables." << endl;
cerr << "ERROR: When estimating a DSGE-Var and the bayesian_irf option is passed to "
"the estimation "
<< "statement, the number of shocks must equal the number of observed variables."
<< endl;
exit(EXIT_FAILURE);
}
}
else
if (symbol_table.exo_nbr() < symbol_table.observedVariablesNbr())
else if (symbol_table.exo_nbr() < symbol_table.observedVariablesNbr())
{
cerr << "ERROR: When estimating a DSGE-Var, the number of shocks must be "
<< "greater than or equal to the number of observed variables." << endl;
......@@ -723,8 +846,19 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
}
}
for (int dim {0}; dim < heterogeneity_table.size(); dim++)
if (heterogeneous_models.at(dim).equation_number() != symbol_table.het_endo_nbr(dim))
{
cerr << "ERROR: There are " << heterogeneous_models.at(dim).equation_number()
<< " equations but " << symbol_table.het_endo_nbr(dim)
<< " endogenous variables in the model for heterogeneity dimension '"
<< heterogeneity_table.getName(dim) << "'!" << endl;
exit(EXIT_FAILURE);
}
}
void
ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_derivs_order)
ModFile::computingPass(bool no_tmp_terms, OutputType output, int params_derivs_order)
{
// Mod file may have no equation (for example in a standalone BVAR estimation)
if (dynamic_model.equation_number() > 0)
......@@ -734,143 +868,200 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_deri
// Compute static model and its derivatives
static_model = static_cast<StaticModel>(dynamic_model);
if (linear_decomposition)
{
non_linear_equations_dynamic_model = dynamic_model;
non_linear_equations_dynamic_model.set_cutoff_to_zero();
non_linear_equations_dynamic_model.computingPass(true, 1, 0, global_eval_context, no_tmp_terms, block, use_dll, byte_code, linear_decomposition);
}
if (!no_static)
{
if (mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present || mod_file_struct.osr_present
|| mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present)
if (mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present
|| mod_file_struct.osr_present || mod_file_struct.ramsey_model_present
|| mod_file_struct.identification_present || mod_file_struct.calib_smoother_present
|| mod_file_struct.mom_estimation_present)
static_model.set_cutoff_to_zero();
int derivsOrder = 1;
int paramsDerivsOrder = 0;
if (mod_file_struct.identification_present || mod_file_struct.estimation_analytic_derivation)
{
if (mod_file_struct.identification_present
|| mod_file_struct.estimation_analytic_derivation)
derivsOrder = 2;
if (mod_file_struct.identification_present
|| mod_file_struct.estimation_analytic_derivation
|| mod_file_struct.osr_analytic_derivation
|| (mod_file_struct.GMM_present
&& (mod_file_struct.analytic_standard_errors_present
|| mod_file_struct.analytic_jacobian_present)))
paramsDerivsOrder = params_derivs_order;
}
static_model.computingPass(derivsOrder, paramsDerivsOrder, global_eval_context, no_tmp_terms, block, byte_code);
static_model.computingPass(derivsOrder, paramsDerivsOrder, global_eval_context,
no_tmp_terms, block, use_dll);
if (mod_file_struct.ramsey_model_present)
static_model.computeRamseyMultipliersDerivatives(mod_file_struct.ramsey_orig_endo_nbr,
!use_dll, no_tmp_terms);
}
// Set things to compute for dynamic model
if (mod_file_struct.perfect_foresight_solver_present || mod_file_struct.check_present
|| mod_file_struct.stoch_simul_present
if (mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present
|| mod_file_struct.check_present || mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present || mod_file_struct.osr_present
|| mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present)
|| mod_file_struct.calib_smoother_present || mod_file_struct.mom_estimation_present)
{
if (mod_file_struct.perfect_foresight_solver_present)
dynamic_model.computingPass(true, 1, 0, global_eval_context, no_tmp_terms, block, use_dll, byte_code, linear_decomposition);
if (mod_file_struct.perfect_foresight_solver_present
|| mod_file_struct.perfect_foresight_with_expectation_errors_solver_present)
{
int derivsOrder = 1;
if (output == OutputType::second)
derivsOrder = 2;
else if (output == OutputType::third)
derivsOrder = 3;
dynamic_model.computingPass(derivsOrder, 0, global_eval_context, no_tmp_terms, block,
use_dll);
}
else
{
if (mod_file_struct.stoch_simul_present
|| mod_file_struct.estimation_present || mod_file_struct.osr_present
|| mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present)
if (mod_file_struct.stoch_simul_present || mod_file_struct.estimation_present
|| mod_file_struct.osr_present || mod_file_struct.ramsey_model_present
|| mod_file_struct.identification_present
|| mod_file_struct.calib_smoother_present
|| mod_file_struct.mom_estimation_present)
dynamic_model.set_cutoff_to_zero();
if (mod_file_struct.order_option < 1)
{
cerr << "ERROR: Incorrect order option..." << endl;
exit(EXIT_FAILURE);
}
int derivsOrder = max(mod_file_struct.order_option,
mod_file_struct.identification_order + 1);
if (mod_file_struct.sensitivity_present || linear || output == FileOutputType::second)
int derivsOrder
= max(mod_file_struct.order_option,
mod_file_struct.identification_order + 1); // See preprocessor#40
if (mod_file_struct.GMM_present
&& (mod_file_struct.analytic_standard_errors_present
|| mod_file_struct.analytic_jacobian_present)) // analytic_standard_errors or
// analytic_jacobian require
// one order more
derivsOrder
= max(mod_file_struct.order_option,
max(mod_file_struct.identification_order, mod_file_struct.mom_order)
+ 1); // See preprocessor#40
if (mod_file_struct.sensitivity_present || linear || output == OutputType::second)
derivsOrder = max(derivsOrder, 2);
if (mod_file_struct.estimation_analytic_derivation || output == FileOutputType::third)
if (mod_file_struct.estimation_analytic_derivation || output == OutputType::third)
derivsOrder = max(derivsOrder, 3);
int paramsDerivsOrder = 0;
if (mod_file_struct.identification_present || mod_file_struct.estimation_analytic_derivation)
if (mod_file_struct.identification_present
|| mod_file_struct.estimation_analytic_derivation
|| mod_file_struct.osr_analytic_derivation
|| (mod_file_struct.GMM_present
&& (mod_file_struct.analytic_standard_errors_present
|| mod_file_struct.analytic_jacobian_present)))
paramsDerivsOrder = params_derivs_order;
dynamic_model.computingPass(true, derivsOrder, paramsDerivsOrder, global_eval_context, no_tmp_terms, block, use_dll, byte_code, linear_decomposition);
dynamic_model.computingPass(derivsOrder, paramsDerivsOrder, global_eval_context,
no_tmp_terms, block, use_dll);
if (linear && mod_file_struct.ramsey_model_present)
orig_ramsey_dynamic_model.computingPass(true, 2, paramsDerivsOrder, global_eval_context, no_tmp_terms, block, use_dll, byte_code, linear_decomposition);
orig_ramsey_dynamic_model.computingPass(2, paramsDerivsOrder, global_eval_context,
no_tmp_terms, block, use_dll);
}
}
else // No computing task requested, compute derivatives up to 2nd order by default
dynamic_model.computingPass(true, 2, 0, global_eval_context, no_tmp_terms, block, use_dll, byte_code, linear_decomposition);
map<int, string> eqs;
if (mod_file_struct.ramsey_model_present)
orig_ramsey_dynamic_model.setNonZeroHessianEquations(eqs);
else
dynamic_model.setNonZeroHessianEquations(eqs);
if (linear && !eqs.empty())
else // No computing task requested, compute derivatives up to 2nd order by default unless
// output=first (preprocessor#100) or third (preprocessor#121) is requested
{
cerr << "ERROR: If the model is declared linear the second derivatives must be equal to zero." << endl
<< " The following equations had non-zero second derivatives:" << endl;
for (map<int, string >::const_iterator it = eqs.begin(); it != eqs.end(); it++)
switch (output)
{
cerr << " * Eq # " << it->first+1;
if (!it->second.empty())
cerr << " [" << it->second << "]";
cerr << endl;
case OutputType::first:
dynamic_model.computingPass(1, 0, global_eval_context, no_tmp_terms, block, use_dll);
break;
case OutputType::third:
dynamic_model.computingPass(3, 0, global_eval_context, no_tmp_terms, block, use_dll);
break;
default:
dynamic_model.computingPass(2, 0, global_eval_context, no_tmp_terms, block, use_dll);
break;
}
exit(EXIT_FAILURE);
}
if (linear)
{
if (mod_file_struct.ramsey_model_present)
orig_ramsey_dynamic_model.checkIsLinear();
else
dynamic_model.checkIsLinear();
}
}
// Those matrices can only be filled here, because we use derivatives
dynamic_model.fillVarModelTableMatrices();
for (auto& hm : heterogeneous_models)
hm.computingPass(mod_file_struct.order_option, no_tmp_terms, use_dll);
for (auto& statement : statements)
statement->computingPass();
statement->computingPass(mod_file_struct);
// Compute epilogue derivatives (but silence standard output)
streambuf* oldcout = cout.rdbuf();
cout.rdbuf(nullptr);
epilogue.computingPass(true, 2, 0, global_eval_context, true, false, false, false, false);
epilogue.computingPass(2, 0, global_eval_context, true, false, false);
cout.rdbuf(oldcout);
}
void
ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_global, bool no_log, bool no_warn,
bool console, bool nograph, bool nointeractive, const ConfigFile &config_file,
ModFile::remove_directory_with_matlab_lock(const filesystem::path& dir)
{
auto dirStatus {status(dir)};
if (!exists(dirStatus))
return;
if (is_directory(dirStatus))
for (const auto& e : filesystem::directory_iterator {dir})
if (e.is_directory())
remove_directory_with_matlab_lock(e);
auto tmp {unique_path()};
rename(dir, tmp);
remove_all(tmp);
}
void
ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global, bool no_warn,
bool console, bool nograph, bool nointeractive, const Configuration& config,
bool check_model_changes, bool minimal_workspace, bool compute_xrefs,
const string &mexext,
const filesystem::path &matlabroot,
const filesystem::path &dynareroot, bool onlymodel) const
const string& mexext, const filesystem::path& matlabroot, bool onlymodel,
bool gui, bool notime) const
{
bool hasModelChanged = !dynamic_model.isChecksumMatching(basename, block) || !check_model_changes;
if (basename.empty())
{
cerr << "ERROR: Missing file name" << endl;
exit(EXIT_FAILURE);
}
auto plusfolder {DataTree::packageDir(basename)};
if (check_model_changes && !heterogeneity_table.empty())
{
cerr << "ERROR: the 'fast' option is not supported for heterogeneous models" << endl;
exit(EXIT_FAILURE);
}
bool hasModelChanged = !dynamic_model.isChecksumMatching(basename) || !check_model_changes;
if (hasModelChanged)
{
// Erase possible remnants of previous runs
/* Under MATLAB+Windows (but not under Octave nor under GNU/Linux or
macOS), if we directly remove the "+" subdirectory, then the
preprocessor is not able to recreate it afterwards (presumably because
MATLAB maintains some sort of lock on it). The workaround is to rename
it before deleting it (the renaming must occur in the same directory,
otherwise it may file if the destination is not on the same
filesystem). */
if (filesystem::exists("+" + basename))
{
auto tmp = unique_path();
filesystem::rename("+" + basename, tmp);
filesystem::remove_all(tmp);
}
MATLAB maintains some sort of lock on it). So we use a hack. */
remove_directory_with_matlab_lock(plusfolder);
filesystem::remove_all(basename + "/model/src");
filesystem::remove_all(basename + "/model/bytecode");
// Do not remove basename/model/julia/, otherwise it would break calls to
// writeToFileIfModified()
}
ofstream mOutputFile;
if (basename.size())
{
filesystem::create_directory("+" + basename);
string fname = "+" + basename + "/driver.m";
mOutputFile.open(fname, ios::out | ios::binary);
create_directory(plusfolder);
filesystem::path fname {plusfolder / "driver.m"};
ofstream mOutputFile {fname, ios::out | ios::binary};
if (!mOutputFile.is_open())
{
cerr << "ERROR: Can't open file " << fname << " for writing" << endl;
exit(EXIT_FAILURE);
}
}
else
{
cerr << "ERROR: Missing file name" << endl;
cerr << "ERROR: Can't open file " << fname.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
......@@ -878,24 +1069,27 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
<< "% Status : main Dynare file" << endl
<< "%" << endl
<< "% Warning : this file is generated automatically by Dynare" << endl
<< "% from model file (.mod)" << endl << endl;
<< "% from model file (.mod)" << endl
<< endl;
if (no_warn)
mOutputFile << "warning off" << endl; // This will be executed *after* function warning_config()
if (clear_all)
mOutputFile << "if isoctave || matlab_ver_less_than('8.6')" << endl
<< " clear all" << endl
<< "else" << endl
<< " clearvars -global" << endl
<< " clear_persistent_variables(fileparts(which('dynare')), false)" << endl
<< "end" << endl;
mOutputFile << "clearvars -global" << endl
<< "clear_persistent_variables(fileparts(which('dynare')), false)" << endl;
else if (clear_global)
mOutputFile << "clear M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info ys0_ ex0_;" << endl;
mOutputFile << "clearvars -global M_ options_ oo_ estim_params_ bayestopt_ dataset_ "
"dataset_info estimation_info;"
<< endl;
if (!notime)
mOutputFile << "tic0 = tic;" << endl;
mOutputFile << "tic0 = tic;" << endl
mOutputFile
<< "% Define global variables." << endl
<< "global M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info ys0_ ex0_" << endl
<< "global M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info"
<< endl
<< "options_ = [];" << endl
<< "M_.fname = '" << basename << "';" << endl
<< "M_.dynare_version = '" << PACKAGE_VERSION << "';" << endl
......@@ -905,18 +1099,11 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
<< "% Some global variables initialization" << endl
<< "%" << endl;
if (!onlymodel)
config_file.writeHooks(mOutputFile);
mOutputFile << "global_initialization;" << endl
<< "diary off;" << endl;
if (!no_log)
mOutputFile << "diary('" << basename << ".log');" << endl;
if (minimal_workspace)
mOutputFile << "options_.minimal_workspace = true;" << endl;
config.writeHooks(mOutputFile);
mOutputFile << "global_initialization;" << endl;
if (console)
mOutputFile << "options_.console_mode = true;" << endl
<< "options_.nodisplay = true;" << endl;
mOutputFile << "options_.console_mode = true;" << endl << "options_.nodisplay = true;" << endl;
if (nograph)
mOutputFile << "options_.nograph = true;" << endl;
......@@ -926,18 +1113,23 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
if (param_used_with_lead_lag)
mOutputFile << "M_.parameter_used_with_lead_lag = true;" << endl;
cout << "Processing outputs ..." << endl;
symbol_table.writeOutput(mOutputFile);
heterogeneity_table.writeOutput(mOutputFile);
var_model_table.writeOutput(basename, mOutputFile);
trend_component_model_table.writeOutput(basename, mOutputFile);
var_expectation_model_table.writeOutput(mOutputFile);
pac_model_table.writeOutput(mOutputFile);
// Initialize M_.Sigma_e, M_.Correlation_matrix, M_.H, and M_.Correlation_matrix_ME
mOutputFile << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ");" << endl
mOutputFile << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", " << symbol_table.exo_nbr()
<< ");" << endl
<< "M_.Correlation_matrix = eye(" << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ");" << endl;
for (int hd {0}; hd < heterogeneity_table.size(); hd++)
mOutputFile << "M_.heterogeneity(" << hd + 1 << ").Sigma_e = zeros("
<< symbol_table.het_exo_nbr(hd) << ", " << symbol_table.het_exo_nbr(hd) << ");"
<< endl;
if (mod_file_struct.calibrated_measurement_errors)
mOutputFile << "M_.H = zeros(" << symbol_table.observedVariablesNbr() << ", "
......@@ -945,22 +1137,35 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
<< "M_.Correlation_matrix_ME = eye(" << symbol_table.observedVariablesNbr() << ", "
<< symbol_table.observedVariablesNbr() << ");" << endl;
else
mOutputFile << "M_.H = 0;" << endl
<< "M_.Correlation_matrix_ME = 1;" << endl;
mOutputFile << "M_.H = 0;" << endl << "M_.Correlation_matrix_ME = 1;" << endl;
// May be later modified by a shocks block
mOutputFile << "M_.sigma_e_is_diagonal = true;" << endl;
// Initialize M_.det_shocks
mOutputFile << "M_.det_shocks = [];" << endl;
auto to_matlab_logical = [](bool m) { return m ? "true" : "false"; };
mOutputFile << "options_.linear = " << to_matlab_logical(linear) << ";" << endl
<< "options_.block = " << to_matlab_logical(block) << ";" << endl
<< "options_.bytecode = " << to_matlab_logical(byte_code) << ";" << endl
<< "options_.use_dll = " << to_matlab_logical(use_dll) << ";" << endl
<< "options_.linear_decomposition = " << to_matlab_logical(linear_decomposition) << ";" << endl;
/* Initialize the structures created for several blocks, as part of the implementation of the
“overwrite” option */
mOutputFile << "M_.det_shocks = [];" << endl
<< "M_.surprise_shocks = [];" << endl
<< "M_.learnt_shocks = [];" << endl
<< "M_.learnt_endval = [];" << endl
<< "M_.heteroskedastic_shocks.Qvalue_orig = [];" << endl
<< "M_.heteroskedastic_shocks.Qscale_orig = [];" << endl
<< "M_.matched_irfs = {};" << endl
<< "M_.matched_irfs_weights = {};" << endl
<< "M_.perfect_foresight_controlled_paths = [];" << endl;
// NB: options_.{ramsey,discretionary}_policy should rather be fields of M_
mOutputFile << boolalpha << "options_.linear = " << linear << ";" << endl
<< "options_.block = " << block << ";" << endl
<< "options_.bytecode = " << bytecode << ";" << endl
<< "options_.use_dll = " << use_dll << ";" << endl
<< "options_.ramsey_policy = " << mod_file_struct.ramsey_model_present << ";" << endl
<< "options_.discretionary_policy = " << mod_file_struct.discretionary_policy_present
<< ";" << endl;
if (mod_file_struct.discretionary_policy_present)
mOutputFile << "M_.discretionary_orig_eq_nbr = " << original_model.equation_number() << ";"
<< endl;
if (parallel_local_files.size() > 0)
{
......@@ -972,47 +1177,57 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
mOutputFile << "'', '" << parallel_local_file << "';" << endl;
else
mOutputFile << "'" << parallel_local_file.substr(0, j + 1) << "', '"
<< parallel_local_file.substr(j+1, string::npos) << "';" << endl;
<< parallel_local_file.substr(j + 1) << "';" << endl;
}
mOutputFile << "};" << endl;
}
if (dynamic_model.isHessianComputed())
{
mOutputFile << "M_.nonzero_hessian_eqs = ";
if (mod_file_struct.ramsey_model_present)
orig_ramsey_dynamic_model.printNonZeroHessianEquations(mOutputFile);
else
dynamic_model.printNonZeroHessianEquations(mOutputFile);
mOutputFile << ";" << endl
<< "M_.hessian_eq_zero = isempty(M_.nonzero_hessian_eqs);" << endl;
mOutputFile << ";" << endl << "M_.hessian_eq_zero = isempty(M_.nonzero_hessian_eqs);" << endl;
}
if (!onlymodel)
config_file.writeCluster(mOutputFile);
config.writeCluster(mOutputFile);
if (byte_code)
if (bytecode)
mOutputFile << "if exist('bytecode') ~= 3" << endl
<< " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the ''bytecode'' option.')" << endl
<< " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the "
"''bytecode'' option.')"
<< endl
<< "end" << endl;
mOutputFile << "M_.orig_eq_nbr = " << mod_file_struct.orig_eq_nbr << ";" << endl
<< "M_.eq_nbr = " << dynamic_model.equation_number() << ";" << endl
<< "M_.ramsey_eq_nbr = " << mod_file_struct.ramsey_eq_nbr << ";" << endl
<< "M_.set_auxiliary_variables = exist(['./+' M_.fname '/set_auxiliary_variables.m'], 'file') == 2;" << endl;
mOutputFile << "M_.eq_nbr = " << dynamic_model.equation_number() << ";" << endl
<< "M_.ramsey_orig_eq_nbr = " << mod_file_struct.ramsey_orig_eq_nbr << ";" << endl
<< "M_.ramsey_orig_endo_nbr = " << mod_file_struct.ramsey_orig_endo_nbr << ";" << endl
<< "M_.set_auxiliary_variables = exist(['./+' M_.fname "
"'/set_auxiliary_variables.m'], 'file') == 2;"
<< endl;
epilogue.writeOutput(mOutputFile);
if (dynamic_model.equation_number() > 0)
{
if (linear_decomposition)
non_linear_equations_dynamic_model.writeOutput(mOutputFile, basename, block, true, byte_code, use_dll, mod_file_struct.order_option, mod_file_struct.estimation_present, compute_xrefs, false);
dynamic_model.writeOutput(mOutputFile, basename, block, false, byte_code, use_dll, mod_file_struct.order_option, mod_file_struct.estimation_present, compute_xrefs, false);
dynamic_model.writeDriverOutput(mOutputFile, compute_xrefs);
if (!no_static)
static_model.writeOutput(mOutputFile, block);
{
static_model.writeDriverOutput(mOutputFile);
if (mod_file_struct.ramsey_model_present)
static_model.writeDriverRamseyMultipliersDerivativesSparseIndices(mOutputFile);
}
}
if (onlymodel)
for (auto &statement : statements)
for (const auto& hm : heterogeneous_models)
hm.writeDriverOutput(mOutputFile);
if (onlymodel || gui)
for (const auto& statement : statements)
{
/* Special treatment for initval block: insert initial values for the
auxiliary variables and initialize exo det */
if (auto *ivs = dynamic_cast<InitValStatement *>(statement.get()); ivs != nullptr)
if (auto ivs = dynamic_cast<InitValStatement*>(statement.get()); ivs)
{
ivs->writeOutput(mOutputFile, basename, minimal_workspace);
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
......@@ -1020,70 +1235,100 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
}
// Special treatment for endval block: insert initial values for the auxiliary variables
if (auto *evs = dynamic_cast<EndValStatement *>(statement.get()); evs != nullptr)
if (auto evs = dynamic_cast<EndValStatement*>(statement.get()); evs)
{
evs->writeOutput(mOutputFile, basename, minimal_workspace);
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
}
if (auto *ips = dynamic_cast<InitParamStatement *>(statement.get()); ips != nullptr)
if (auto ips = dynamic_cast<InitParamStatement*>(statement.get()); ips)
ips->writeOutput(mOutputFile, basename, minimal_workspace);
if (auto *ss = dynamic_cast<ShocksStatement *>(statement.get()); ss != nullptr)
if (auto ss = dynamic_cast<ShocksStatement*>(statement.get()); ss)
ss->writeOutput(mOutputFile, basename, minimal_workspace);
if (auto *eps = dynamic_cast<EstimatedParamsStatement *>(statement.get()); eps != nullptr)
if (auto eps = dynamic_cast<EstimatedParamsStatement*>(statement.get()); eps)
eps->writeOutput(mOutputFile, basename, minimal_workspace);
if (auto *sgs = dynamic_cast<ShockGroupsStatement *>(statement.get()); sgs != nullptr)
if (auto sgs = dynamic_cast<ShockGroupsStatement*>(statement.get()); sgs)
sgs->writeOutput(mOutputFile, basename, minimal_workspace);
if (gui)
if (auto it = dynamic_cast<NativeStatement*>(statement.get()); it)
it->writeOutput(mOutputFile, basename, minimal_workspace);
}
else
{
for (auto &statement : statements)
for (const auto& statement : statements)
{
statement->writeOutput(mOutputFile, basename, minimal_workspace);
/* Special treatment for initval block: insert initial values for the
auxiliary variables and initialize exo det */
if (auto ivs = dynamic_cast<InitValStatement *>(statement.get()); ivs != nullptr)
if (auto ivs = dynamic_cast<InitValStatement*>(statement.get()); ivs)
{
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
ivs->writeOutputPostInit(mOutputFile);
}
// Special treatment for endval block: insert initial values for the auxiliary variables
if (auto evs = dynamic_cast<EndValStatement *>(statement.get()); evs != nullptr)
if (auto evs = dynamic_cast<EndValStatement*>(statement.get()); evs)
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
// Special treatment for load params and steady state statement: insert initial values for the auxiliary variables
if (auto lpass = dynamic_cast<LoadParamsAndSteadyStateStatement *>(statement.get()); lpass && !no_static)
// Special treatment for load params and steady state statement: insert initial values for
// the auxiliary variables
if (auto lpass = dynamic_cast<LoadParamsAndSteadyStateStatement*>(statement.get());
lpass && !no_static)
static_model.writeAuxVarInitval(mOutputFile, ExprNodeOutputType::matlabOutsideModel);
}
mOutputFile << "save('" << basename << "_results.mat', 'oo_', 'M_', 'options_');" << endl
if (!notime)
mOutputFile << endl
<< endl
<< "oo_.time = toc(tic0);" << endl
<< "disp(['Total computing time : ' dynsec2hms(oo_.time) ]);" << endl;
mOutputFile << "if ~exist([M_.dname filesep 'Output'],'dir')" << endl
<< " mkdir(M_.dname,'Output');" << endl
<< "end" << endl
<< "save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'oo_', 'M_', 'options_');" << endl
<< "if exist('estim_params_', 'var') == 1" << endl
<< " save('" << basename << "_results.mat', 'estim_params_', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'estim_params_', '-append');" << endl
<< "end" << endl
<< "if exist('bayestopt_', 'var') == 1" << endl
<< " save('" << basename << "_results.mat', 'bayestopt_', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'bayestopt_', '-append');" << endl
<< "end" << endl
<< "if exist('dataset_', 'var') == 1" << endl
<< " save('" << basename << "_results.mat', 'dataset_', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'dataset_', '-append');" << endl
<< "end" << endl
<< "if exist('estimation_info', 'var') == 1" << endl
<< " save('" << basename << "_results.mat', 'estimation_info', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'estimation_info', '-append');" << endl
<< "end" << endl
<< "if exist('dataset_info', 'var') == 1" << endl
<< " save('" << basename << "_results.mat', 'dataset_info', '-append');" << endl << "end" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'dataset_info', '-append');" << endl
<< "end" << endl
<< "if exist('oo_recursive_', 'var') == 1" << endl
<< " save('" << basename << "_results.mat', 'oo_recursive_', '-append');" << endl << "end" << endl;
config_file.writeEndParallel(mOutputFile);
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'oo_recursive_', '-append');" << endl
<< "end" << endl
<< "if exist('options_mom_', 'var') == 1" << endl
<< " save([M_.dname filesep 'Output' filesep '" << basename
<< "_results.mat'], 'options_mom_', '-append');" << endl
<< "end" << endl;
mOutputFile << endl << endl
<< "disp(['Total computing time : ' dynsec2hms(toc(tic0)) ]);" << endl;
config.writeEndParallel(mOutputFile);
if (!no_warn)
{
if (warnings.countWarnings() > 0)
mOutputFile << "disp('Note: " << warnings.countWarnings() << " warning(s) encountered in the preprocessor')" << endl;
if (int num_warnings {warnings.numWarnings()}; num_warnings > 0)
mOutputFile << "disp('Note: " << num_warnings
<< " warning(s) encountered in the preprocessor')" << endl;
mOutputFile << "if ~isempty(lastwarn)" << endl
<< " disp('Note: warning(s) encountered in MATLAB/Octave code')" << endl
......@@ -1091,9 +1336,6 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
}
}
if (!no_log)
mOutputFile << "diary off" << endl;
mOutputFile.close();
if (hasModelChanged)
......@@ -1103,175 +1345,56 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
{
if (!no_static)
{
static_model.writeStaticFile(basename, block, byte_code, use_dll, mexext, matlabroot, dynareroot, false);
static_model.writeParamsDerivativesFile(basename, false);
}
if (linear_decomposition)
static_model.writeStaticFile(basename, use_dll, mexext, matlabroot, false);
static_model.writeParamsDerivativesFile<false>(basename);
if (mod_file_struct.ramsey_model_present)
{
non_linear_equations_dynamic_model.writeDynamicFile(basename, block, linear_decomposition, byte_code, use_dll, mexext, matlabroot, dynareroot, mod_file_struct.order_option, false);
non_linear_equations_dynamic_model.writeParamsDerivativesFile(basename, false);
if (use_dll)
static_model.writeRamseyMultipliersDerivativesCFile(
basename, mexext, matlabroot, mod_file_struct.ramsey_orig_endo_nbr);
else
static_model.writeRamseyMultipliersDerivativesMFile(
basename, mod_file_struct.ramsey_orig_endo_nbr);
}
}
dynamic_model.writeDynamicFile(basename, block, false, byte_code, use_dll, mexext, matlabroot, dynareroot, mod_file_struct.order_option, false);
dynamic_model.writeParamsDerivativesFile(basename, false);
dynamic_model.writeDynamicFile(basename, use_dll, mexext, matlabroot, false);
dynamic_model.writeDynamicJacobianNonZeroElts(basename);
dynamic_model.writeParamsDerivativesFile<false>(basename);
}
// Create steady state file
steady_state_model.writeSteadyStateFile(basename, mod_file_struct.ramsey_model_present, false);
steady_state_model.writeSteadyStateFile(basename, false);
// Create epilogue file
epilogue.writeEpilogueFile(basename);
}
cout << "done" << endl;
}
pac_model_table.writeTargetCoefficientsFile(basename);
void
ModFile::writeExternalFiles(const string &basename, LanguageOutputType language) const
{
switch (language)
{
case LanguageOutputType::julia:
writeExternalFilesJulia(basename);
break;
case LanguageOutputType::matlab:
cerr << "The 'output' option cannot be used when language=matlab" << endl;
exit(EXIT_FAILURE);
for (const auto& hm : heterogeneous_models)
hm.writeModelFiles(basename, false);
}
}
void
ModFile::writeExternalFilesJulia(const string &basename) const
{
ofstream jlOutputFile;
if (basename.size())
{
string fname(basename);
fname += ".jl";
jlOutputFile.open(fname, ios::out | ios::binary);
if (!jlOutputFile.is_open())
{
cerr << "ERROR: Can't open file " << fname
<< " for writing" << endl;
exit(EXIT_FAILURE);
}
}
else
ModFile::writeJuliaOutput(const string& basename) const
{
cerr << "ERROR: Missing file name" << endl;
exit(EXIT_FAILURE);
}
jlOutputFile << "module " << basename << endl
<< "#" << endl
<< "# NB: this file was automatically generated by Dynare" << endl
<< "# from " << basename << ".mod" << endl
<< "#" << endl << endl
<< "using DynareModel" << endl
<< "using DynareOptions" << endl
<< "using DynareOutput" << endl << endl
<< "using Utils" << endl
<< "using SteadyState" << endl << endl
<< "using " << basename << "Static" << endl
<< "using " << basename << "Dynamic" << endl
<< R"(if isfile(")" << basename << R"(SteadyState.jl"))" << endl
<< " using " << basename << "SteadyState" << endl
<< "end" << endl
<< R"(if isfile(")" << basename << R"(SteadyState2.jl"))" << endl
<< " using " << basename << "SteadyState2" << endl
<< "end" << endl << endl
<< "export model_, options_, oo_" << endl;
// Write Output
jlOutputFile << endl
<< "oo_ = dynare_output()" << endl
<< R"(oo_.dynare_version = ")" << PACKAGE_VERSION << R"(")" << endl;
// Write Options
jlOutputFile << endl
<< "options_ = dynare_options()" << endl
<< R"(options_.dynare_version = ")" << PACKAGE_VERSION << R"(")" << endl;
if (linear)
jlOutputFile << "options_.linear = true" << endl;
// Write Model
jlOutputFile << endl
<< "model_ = dynare_model()" << endl
<< R"(model_.fname = ")" << basename << R"(")" << endl
<< R"(model_.dynare_version = ")" << PACKAGE_VERSION << R"(")" << endl
<< "model_.sigma_e = zeros(Float64, " << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ")" << endl
<< "model_.correlation_matrix = ones(Float64, " << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ")" << endl
<< "model_.orig_eq_nbr = " << mod_file_struct.orig_eq_nbr << endl
<< "model_.eq_nbr = " << dynamic_model.equation_number() << endl
<< "model_.ramsey_eq_nbr = " << mod_file_struct.ramsey_eq_nbr << endl;
if (mod_file_struct.calibrated_measurement_errors)
jlOutputFile << "model_.h = zeros(Float64,"
<< symbol_table.observedVariablesNbr() << ", "
<< symbol_table.observedVariablesNbr() << ");" << endl
<< "model_.correlation_matrix_me = ones(Float64, "
<< symbol_table.observedVariablesNbr() << ", "
<< symbol_table.observedVariablesNbr() << ");" << endl;
else
jlOutputFile << "model_.h = zeros(Float64, 1, 1)" << endl
<< "model_.correlation_matrix_me = ones(Float64, 1, 1)" << endl;
cout << "Processing outputs ..." << endl;
symbol_table.writeJuliaOutput(jlOutputFile);
if (dynamic_model.equation_number() > 0)
{
dynamic_model.writeOutput(jlOutputFile, basename, false, false, false, false,
mod_file_struct.order_option,
mod_file_struct.estimation_present, false, true);
if (!no_static)
{
static_model.writeStaticFile(basename, false, false, false, "", {}, {}, true);
static_model.writeParamsDerivativesFile(basename, true);
static_model.writeStaticFile(basename, false, "", {}, true);
static_model.writeParamsDerivativesFile<true>(basename);
}
dynamic_model.writeDynamicFile(basename, block, linear_decomposition, byte_code, use_dll,
"", {}, {}, mod_file_struct.order_option, true);
dynamic_model.writeParamsDerivativesFile(basename, true);
dynamic_model.writeDynamicFile(basename, use_dll, "", {}, true);
dynamic_model.writeParamsDerivativesFile<true>(basename);
}
steady_state_model.writeSteadyStateFile(basename, mod_file_struct.ramsey_model_present, true);
// Print statements (includes parameter values)
for (auto &statement : statements)
statement->writeJuliaOutput(jlOutputFile, basename);
jlOutputFile << "model_.static = " << basename << "Static.static!" << endl
<< "model_.dynamic = " << basename << "Dynamic.dynamic!" << endl
<< "model_.temporaries.static = " << basename << "Static.tmp_nbr" << endl
<< "model_.temporaries.dynamic = " << basename << "Dynamic.tmp_nbr" << endl
<< R"(if isfile(")" << basename << R"(SteadyState.jl"))" << endl
<< " model_.user_written_analytical_steady_state = true" << endl
<< " model_.steady_state = " << basename << "SteadyState.steady_state!" << endl
<< "end" << endl
<< R"(if isfile(")" << basename << R"(SteadyState2.jl"))" << endl
<< " model_.analytical_steady_state = true" << endl
<< " model_.steady_state = " << basename << "SteadyState2.steady_state!" << endl
<< "end" << endl
<< R"(if isfile(")" << basename << R"(StaticParamsDerivs.jl"))" << endl
<< " using " << basename << "StaticParamsDerivs" << endl
<< " model_.static_params_derivs = " << basename << "StaticParamsDerivs.params_derivs" << endl
<< "end" << endl
<< R"(if isfile(")" << basename << R"(DynamicParamsDerivs.jl"))" << endl
<< " using " << basename << "DynamicParamsDerivs" << endl
<< " model_.dynamic_params_derivs = " << basename << "DynamicParamsDerivs.params_derivs" << endl
<< "end" << endl
<< "end" << endl;
jlOutputFile.close();
cout << "done" << endl;
steady_state_model.writeSteadyStateFile(basename, true);
}
void
ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple)
ModFile::writeJsonOutput(const string& basename, JsonOutputPointType json,
JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple)
{
if (json == JsonOutputPointType::nojson)
return;
......@@ -1280,10 +1403,11 @@ ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonF
symbol_table.freeze();
if (json_output_mode == JsonFileOutputType::standardout)
cout << "//-- BEGIN JSON --// " << endl
<< "{" << endl;
cout << "//-- BEGIN JSON --// " << endl << "{" << endl;
writeJsonOutputParsingCheck(basename, json_output_mode, json == JsonOutputPointType::transformpass, json == JsonOutputPointType::computingpass);
writeJsonOutputParsingCheck(basename, json_output_mode,
json == JsonOutputPointType::transformpass,
json == JsonOutputPointType::computingpass);
if (json == JsonOutputPointType::parsing || json == JsonOutputPointType::checkpass)
symbol_table.unfreeze();
......@@ -1292,8 +1416,7 @@ ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonF
writeJsonComputingPassOutput(basename, json_output_mode, jsonderivsimple);
if (json_output_mode == JsonFileOutputType::standardout)
cout << "}" << endl
<< "//-- END JSON --// " << endl;
cout << "}" << endl << "//-- END JSON --// " << endl;
switch (json)
{
......@@ -1319,18 +1442,24 @@ ModFile::writeJsonOutput(const string &basename, JsonOutputPointType json, JsonF
}
void
ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType json_output_mode, bool transformpass, bool computingpass) const
ModFile::writeJsonOutputParsingCheck(const string& basename, JsonFileOutputType json_output_mode,
bool transformpass, bool computingpass) const
{
ostringstream output;
output << "{" << endl;
symbol_table.writeJsonOutput(output);
output << ", ";
if (!heterogeneity_table.empty())
{
heterogeneity_table.writeJsonOutput(output);
output << ", ";
}
dynamic_model.writeJsonOutput(output);
output << ", ";
static_model.writeJsonOutput(output);
if (!statements.empty()
|| !var_model_table.empty()
|| !trend_component_model_table.empty())
if (!statements.empty() || !var_model_table.empty() || !trend_component_model_table.empty())
{
output << R"(, "statements": [)";
if (!var_model_table.empty())
......@@ -1345,12 +1474,23 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
output << ", ";
}
for (auto it = statements.begin();
it != statements.end(); it++)
if (!var_expectation_model_table.empty())
{
var_expectation_model_table.writeJsonOutput(output);
output << ", ";
}
if (!pac_model_table.empty())
{
if (it != statements.begin())
pac_model_table.writeJsonOutput(output);
output << ", ";
}
for (bool printed_something {false}; auto& it : statements)
{
if (exchange(printed_something, true))
output << ", " << endl;
(*it)->writeJsonOutput(output);
it->writeJsonOutput(output);
}
output << "]" << endl;
}
......@@ -1360,6 +1500,9 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
output << ",";
dynamic_model.writeJsonDynamicModelInfo(output);
}
output << R"(, "steady_state_model": )" << mod_file_struct.steady_state_model_present << endl;
output << "}" << endl;
ostringstream original_model_output;
......@@ -1381,10 +1524,14 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
trend_component_model_table.writeJsonOutput(original_model_output);
original_model_output << ", ";
}
int i = 0;
for (const auto & it : statements)
if (!pac_model_table.empty())
{
pac_model_table.writeJsonOutput(original_model_output);
original_model_output << ", ";
}
for (bool printed_something {false}; const auto& it : statements)
{
original_model_output << (i++ > 0 ? "," : "") << endl;
original_model_output << (exchange(printed_something, true) ? "," : "") << endl;
it->writeJsonOutput(original_model_output);
}
original_model_output << "]" << endl;
......@@ -1412,22 +1559,18 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
}
else
{
ofstream jsonOutputFile;
if (basename.size())
{
filesystem::create_directories(basename + "/model/json");
string fname{basename + "/model/json/modfile.json"};
jsonOutputFile.open(fname, ios::out | ios::binary);
if (!jsonOutputFile.is_open())
if (!basename.size())
{
cerr << "ERROR: Can't open file " << fname << " for writing" << endl;
cerr << "ERROR: Missing file name" << endl;
exit(EXIT_FAILURE);
}
}
else
filesystem::create_directories(basename + "/model/json");
const filesystem::path fname {basename + "/model/json/modfile.json"};
ofstream jsonOutputFile {fname, ios::out | ios::binary};
if (!jsonOutputFile.is_open())
{
cerr << "ERROR: Missing file name" << endl;
cerr << "ERROR: Can't open file " << fname.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
......@@ -1438,11 +1581,11 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
{
if (basename.size())
{
string fname{basename + "/model/json/modfile-original.json"};
const filesystem::path fname {basename + "/model/json/modfile-original.json"};
jsonOutputFile.open(fname, ios::out | ios::binary);
if (!jsonOutputFile.is_open())
{
cerr << "ERROR: Can't open file " << fname << " for writing" << endl;
cerr << "ERROR: Can't open file " << fname.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
}
......@@ -1459,11 +1602,11 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
{
if (basename.size())
{
string fname{basename + "/model/json/steady_state_model.json"};
const filesystem::path fname {basename + "/model/json/steady_state_model.json"};
jsonOutputFile.open(fname, ios::out | ios::binary);
if (!jsonOutputFile.is_open())
{
cerr << "ERROR: Can't open file " << fname << " for writing" << endl;
cerr << "ERROR: Can't open file " << fname.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
}
......@@ -1480,7 +1623,8 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
}
void
ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonderivsimple) const
ModFile::writeJsonComputingPassOutput(const string& basename, JsonFileOutputType json_output_mode,
bool jsonderivsimple) const
{
if (basename.empty() && json_output_mode != JsonFileOutputType::standardout)
{
......@@ -1488,7 +1632,8 @@ ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType
exit(EXIT_FAILURE);
}
ostringstream tmp_out, static_output, dynamic_output, static_paramsd_output, dynamic_paramsd_output;
ostringstream tmp_out, static_output, dynamic_output, static_paramsd_output,
dynamic_paramsd_output;
static_output << "{";
static_model.writeJsonComputingPassOutput(static_output, !jsonderivsimple);
......@@ -1498,15 +1643,12 @@ ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType
dynamic_model.writeJsonComputingPassOutput(dynamic_output, !jsonderivsimple);
dynamic_output << "}";
tmp_out << "";
static_paramsd_output << "";
static_model.writeJsonParamsDerivativesFile(tmp_out, !jsonderivsimple);
static_model.writeJsonParamsDerivatives(tmp_out, !jsonderivsimple);
if (!tmp_out.str().empty())
static_paramsd_output << "{" << tmp_out.str() << "}" << endl;
tmp_out.str("");
dynamic_paramsd_output << "";
dynamic_model.writeJsonParamsDerivativesFile(tmp_out, !jsonderivsimple);
dynamic_model.writeJsonParamsDerivatives(tmp_out, !jsonderivsimple);
if (!tmp_out.str().empty())
dynamic_paramsd_output << "{" << tmp_out.str() << "}" << endl;
......@@ -1529,7 +1671,8 @@ ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType
writeJsonFileHelper(basename + "/model/json/dynamic.json", dynamic_output);
if (!static_paramsd_output.str().empty())
writeJsonFileHelper(basename + "/model/json/static_params_derivs.json", static_paramsd_output);
writeJsonFileHelper(basename + "/model/json/static_params_derivs.json",
static_paramsd_output);
if (!dynamic_paramsd_output.str().empty())
writeJsonFileHelper(basename + "/model/json/params_derivs.json", dynamic_paramsd_output);
......@@ -1537,13 +1680,12 @@ ModFile::writeJsonComputingPassOutput(const string &basename, JsonFileOutputType
}
void
ModFile::writeJsonFileHelper(const string &fname, ostringstream &output) const
ModFile::writeJsonFileHelper(const filesystem::path& fname, ostringstream& output) const
{
ofstream jsonOutput;
jsonOutput.open(fname, ios::out | ios::binary);
ofstream jsonOutput {fname, ios::out | ios::binary};
if (!jsonOutput.is_open())
{
cerr << "ERROR: Can't open file " << fname << " for writing" << endl;
cerr << "ERROR: Can't open file " << fname.string() << " for writing" << endl;
exit(EXIT_FAILURE);
}
jsonOutput << output.str();
......@@ -1557,7 +1699,7 @@ ModFile::unique_path()
string possible_characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
random_device rd;
mt19937 generator(rd());
uniform_int_distribution<int> distribution{0, static_cast<int>(possible_characters.size())-1};
uniform_int_distribution distribution {0, static_cast<int>(possible_characters.size()) - 1};
do
{
constexpr int rand_length = 10;
......@@ -1566,7 +1708,7 @@ ModFile::unique_path()
dis = possible_characters[distribution(generator)];
path = rand_str;
}
while (filesystem::exists(path));
while (exists(path));
return path;
}