This feature is ill-designed and no longer needed by the GUI. And is not very
useful: it is not possible to interact with the preprocessor without using the
filesystem, since the preprocessor creates many files anyways.
If we really need to reimplement such a feature, it should rather be redesigned
by reading the modfile from standard input (cin). That could be triggered by
using "-" as the filename argument (as is already done by several standard Unix
utilities).
The M_.params structure was not correctly passed to
dynamic_set_auxiliary_series.m, leading to crashes if a parameter was needed to
compute an auxiliary variable (typically an auxiliayr lead variable
corresponding to a non-linear term in stochastic setup).
Since 38152c34a4, the M_.endo_histval variable is
generated via dynamic_set_auxiliary_dseries.m. But the latter file does not
handle auxiliary variables for Lagrange multiplier. We therefore now set them
by hand (at an initial value of zero).
Since 38152c34a4, the M_.endo_histval variable is
generated via dynamic_set_auxiliary_dseries.m. The problem is that, for
auxiliary variables corresponding to a lead, this will generate a NaN in
M_.endo_histval. This is conceptually correct, since such variables are never
used as initial conditions, but this is inconsistent with what we do with the
"initval" block, and leads to crashes in some routines where we fail when there
is a NaN. Therefore, replace these with a zero, as it used to be.
The idea is to make use of the dynamic_set_auxiliary_dseries.m file to generate
the initial conditions for all auxiliary variables, including the diffs.
Also remove the check done by the preprocessor for the lags in histval, since
it does not work correctly with the diff operator.
- ExprNode::maxLag() and ExprNode::maxLead() now take into account exogenous
deterministic variables, for consistency with M_.maximum_{lead,lag}
- ExprNode::maxLag() no longer behaves as if diff() operators were
expanded (i.e. it now returns 1 on diff(x(-1))), for consistency with
maxEndoLag() and maxExoLag()
- New ExprNode::maxLagWithDiffsExpanded() method, that behaves as maxLag() used
to behave (except that it also takes exogenous deterministic into account)
Previously, this function was counting the total number of diff() operators in
an expression. But this is not very useful, and is potentially misleading,
because in practice we use this function to compute the maximum lag on
variables in levels.
This function now returns the maximum number of nested diffs.
For example, on diff(x)+diff(diff(y)), this function was returning 3, and it
now returns 2.
The engine is now more robust and should reject any expression that does not
conform to the expected form. It is also able to deal with more cases, such as
terms appearing with a minus sign, or variables in the middle of a
three-factors product.
BTW, use a std::tuple for storing the result of the matching inside
PacExpectationNode, and change the order of components within the
structure (variable first, scalar last).
The preprocessor now writes all the symmetric elements in the "hp"
matrix (derivatives of the hessian w.r.t. parameters), for consistency with all
other derivatives output.
Previously it was only writing one of the two symmetric elements, when indices
of endogenous were different.
Also, no longer compute two times symmetric elements in derivation w.r.t.
parameters at order 2, for consistency with derivation w.r.t. endogenous.
It is therefore now necessary to duplicate them in the output to keep behavior
unchanged.
When creating the sparse matrix (in MATLAB or C mode), since storage is in
column-major order, output the first column, then the second, then the third.
This gives a significant performance boost in use_dll mode (at both compilation
and runtime), because it facilitates memory accesses and expression reusage.
On Windows/MinGW, use the -static linking flag. This enforces static linking of
Boost libraries, which is needed on MSYS2.
Also, use AM_CXXFLAGS and AM_LDFLAGS variables for changing flags, since
CXXFLAGS and LDFLAGS are user variables.
New options "mexext" and "matlabroot" are introduced, so that the preprocessor
knows where to find MATLAB and which architecture to compile for.
Only recent gcc is now supported. A set of optimization flags is used so that
compilation goes reasonably fast on large models.
Consequently, options "msvc", "mingw" and "cygwin" have been removed.
For correlations, there is one extra columns (since there are two symbol
indices). MATLAB automatically adds the missing column, while Octave is
stricter when verifying dimensions.
By the way, add a missing comma.
... when an initial value is given to a parameter that is not
estimated.
The generated driver file was crashing with cryptic error message
because we were searching in the first (and second) column of a
potentially empty array with 0 columns. The fix is to initialize the
fields of estimated_params_ with empty arrays with 10 columns (ie
zeros(0, 10)). Also print a message in the matlab command window if
parameter declared in estimated_params_init is not estimated.
Since, in this case, there are less equations than endogenous, the
variable_reordered structure was not filled with enough element, leading to an
invalid memory read when printing M_.state_var.
Ref #637
In particular, it is necessary to turn back DataTree::AddVariable() into a
non-virtual method, because it is called from DataTree's constructor. Enforcing
the absence of leads/lags is now done using a new boolean DataTree::is_static.
Take advantage of the new copy constructor for handling
PlannerObjectiveStatement more elegantly.
Unfortunately it is not possible to implement *move* constructor / assigment
operators, because the reference ExprNode::datatree is not mutable.
This facilitates switching variable types on the fly. In particular, this
allows removing the hack in DynamicModel::updateAfterVariableChange() that way
basically recreating all the nodes after the type change.
The check is done at the time the preprocessor is compiled, but it ought to be
done at the time when the C source file generated by the preprocessor is compiled…
Anyways, it is probably irrelevant now, since MSVC has supported
acosh/asinh/atanh for a long time now.
This was not conceptually an enum, but rather a collection of unrelated
constants:
- two constants for use as placeholder for symbol IDs at different places
- one constant for the default number of arguments
This mimicks the structure of M-functions (though the logic for filling the
temporary terms vector is a bit different).
This change implied a modification in the way we compute the checksum in case
of block decomposition (the temporary terms for the C output are not correctly
computed in that case).
Due to a limitation of the current implementation, this breaks syntaxes like
[ (i,j) ] (but not [ (2,j) ]; the problem only occurs when an array is
constructed by specifying as first element a tuple whose first element is a
variable name). Solving this problem requires an overhaul of the
macro-processor, with construction of ASTs at parsing time, and evaluation
later on (instead of doing on-the-fly evaluation).
Ref #5
- BTW, store them in a std::vector rather than std::list
- incidentally, fix issue in VariableNode::removeTrendLeadLag where expression
sharing was possibly violated when creating a new VariableNode
- == and != have now lower priority than <= < >= >, for consistency with the
Dynare modelling language (and incidentally C and C++, but not Julia).
- ^ has now higher priority and no associativity, for consistency with the
Dynare modelling language (and usual arithmetic notation).
- & has now higher priority than |, and both have lower priority than + and -,
but higher than inequality comparators. This is not the same as C and C++ (in
which & and | are just above && and ||), but this allows for expressions such
as "a|b == c" to have their most natural semantics (i.e. this will compare
the union of a and b with c; the C/C++ priority level would have resulted in
a type error).
Ref #5.
Given a previously declared var_model, the var_expectation_model statement is
used to declare a way of forming expectations with this VAR (possibly using a
finite or infinite discounted sum). The var_expectation operator now takes a
single argument, the name of the var_expectation_model.
For the moment, this only works when the var_model is using equations
explicitly declared in the model block.
We can therefore manipulate objects by value rather than by pointers, which
saves a lot of memory manipulations (and avoid potential segfaults and memory
leaks).
Note that there is no default action ("$$ = $1") when using the variant type,
so we add them explicitly.
- store objects whose persistence is not guaranteed (e.g. strings) as values
instead of references (to avoid possible segfaults)
- on the contrary, always store the SymbolTable as a reference, since its
persistence is guaranteed, and we don't want to copy it
- use pass-by-value in constructors whenever possible
- remove useless const keyword when passing by value
aux_equations only contain the definition of auxiliary variables, and
may diverge from those in the main model (equations), if other model
transformations applied subsequently. This is not a problem, since
aux_equations is only used for regenerating the values of auxiliaries
given the others.
For example, such a divergence appears when there is an expectation
operator in a ramsey model, see
tests/optimal_policy/nk_ramsey_expectation.mod */
This table serves no useful purpose. It is better to append auxiliary equations
at the time they are created, to avoid messing with the recursive ordering.
Ensure that all diff operators appear once with their argument at current
period (i.e. maxLag=0).
If it is not the case, generate the corresponding expressions.
This is necessary to avoid lags of more than one in the auxiliary
equation, which would then be modified by subsequent transformations
(removing lags > 1), which in turn would break the recursive ordering
of auxiliary equations.
See McModelTeam/McModelProject/issues/95 for an example.
- use std::unique_ptr for MacroDriver::lexer
- use std::shared_ptr for MacroValue objects constructed by the parser
This is made possible using Bison 3.0 variant value type.
Using non-pointer type is not possible since MacroValue is polymorphic.
Using std::unique_ptr is not possible since the value type must be
copyable (see
https://lists.gnu.org/archive/html/bug-bison/2015-03/msg00004.html).
Define a new type MacroValuePtr == shared_ptr<const MacroValue> for code
clarity.
Use the following convention for shared_ptr arguments to functions:
+ if pass-by-value, means that the callee acquires ownership
+ if pass-by-const-reference, the callee does not acquire ownership
- naked pointers are still used for tracking the filename in Bison's location
type, since we don't have control over that
Also, by the way:
- arrays can now contain elements of any type
- simplify MacroDriver::loop_stack using std::tuple
- toArray() method now fails on function objects
- no need to use const qualifiers, since all MacroValue objects are immutable
- use an exception for detecting division by zero
There is no reason to associate an exogenous variable or parameter to a
specific equation. For these types the user can use the pipe
notation (|x, |p) in any equations or the usual parameters and varexo statements.
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.
Most cases can be handled in C++11 by std::stoi() and std::stod().
For the macroprocessor ArrayMV<T>::print() method, use template
specialization (instead of a lexical_cast to detect between T=int and
T=string).
Those were treated as comments.
Incidentally, fix a similar issue in the Dynare parser (which is much less
problematic, since double quotes are not used in the Dynare language).
ClosesDynareTeam/dynare#1621
In the absence of this option, if a var_model statement(s) is present, then aux vars/eqs are created for the same types of unary operators but only for equations specified in the var_model statement
In the absence of both this option and var_model statements, no unary op auxiliary variables are created
diffs continue to be substituted everywhere; for the moment auxiliary variables are created for diffs of expressions. A forthcoming change will allow auxiliary variables created for diffs of expressions to be linked with their lagged expressions as is currently the case for diffs of variables
Given that temporary terms are separated in several functions (residuals,
jacobian, …), we must make sure that all temporary terms derived from a given
external function call are assigned just after that call, and not in an other
function.
More precisely, remove those variants where temporary_terms can be specified
without temporary_terms_idxs, in order to make clear that the latter is
expected. For situations where the tt_idxs are not needed (C, block MATLAB), an
empty map has to be explicitly given.
Incidentally fix bug when a trinary operator becomes a temporary term with
block decomposition (without bytecode).
Also add a safety check to ensure that, if a temporary term is detected, its
index is indeed present in temporary_terms_idxs.
The version with no temporary_terms_idxs argument needs not be virtual, since
it is the same implementation in all derived classes. Rather move it at the
level of the base ExprNode class.
In the presence of MLVs, the temporary terms indexing was corrupted. The code
was using the implicit assumption that the ExprNodeLess ordering was giving the
same ordering as the temporary terms indexes ordering. But MLVs can be higher
in ExprNodeLess ordering than some other temporary terms, while they have the
lowest temporary terms index, hence the bug.
Fix this by no longer relying on the ExprNodeLess ordering, and rather use a
full map<ExprNode *, int> for ModelTree::temporary_terms_idxs. By the way,
simplify the code by removing a few useless data structures (e.g.
ModelTree::temporary_terms_idxs_*).
temporaries.static and temporaries.dynamic are 4*1 vectors of
integers, each element is the number of temporary variables used for
to evaluate the residuals, the jacobian matrix, the hessian matrix and
the matrix of third order derivatives.