2008-02-03 11:28:36 +01:00
|
|
|
|
/*
|
2023-02-28 15:33:24 +01:00
|
|
|
|
* Copyright © 2007-2023 Dynare Team
|
2008-02-03 11:28:36 +01:00
|
|
|
|
*
|
|
|
|
|
* 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
|
2021-06-09 16:52:20 +02:00
|
|
|
|
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2008-02-03 11:28:36 +01:00
|
|
|
|
*/
|
|
|
|
|
|
2023-12-01 15:39:01 +01:00
|
|
|
|
#ifndef EXPR_NODE_HH
|
|
|
|
|
#define EXPR_NODE_HH
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
2018-05-29 17:07:18 +02:00
|
|
|
|
#include <functional>
|
2023-11-30 15:28:57 +01:00
|
|
|
|
#include <map>
|
2022-05-05 18:39:04 +02:00
|
|
|
|
#include <optional>
|
2023-11-30 15:28:57 +01:00
|
|
|
|
#include <ostream>
|
|
|
|
|
#include <set>
|
2023-04-05 14:16:22 +02:00
|
|
|
|
#include <unordered_map>
|
2023-04-05 14:53:47 +02:00
|
|
|
|
#include <unordered_set>
|
2023-11-30 15:28:57 +01:00
|
|
|
|
#include <utility>
|
|
|
|
|
#include <vector>
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
2013-12-30 14:45:17 +01:00
|
|
|
|
using namespace std;
|
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
#include "Bytecode.hh"
|
2022-06-16 17:52:14 +02:00
|
|
|
|
#include "CommonEnums.hh"
|
2010-02-22 17:33:38 +01:00
|
|
|
|
#include "ExternalFunctionsTable.hh"
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
|
|
|
|
class DataTree;
|
2019-01-29 17:29:24 +01:00
|
|
|
|
class NumConstNode;
|
2009-09-30 17:10:31 +02:00
|
|
|
|
class VariableNode;
|
2018-03-02 12:32:01 +01:00
|
|
|
|
class UnaryOpNode;
|
2009-09-30 17:10:31 +02:00
|
|
|
|
class BinaryOpNode;
|
2018-02-07 10:05:32 +01:00
|
|
|
|
class PacExpectationNode;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
using expr_t = class ExprNode*;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
|
|
|
|
struct ExprNodeLess;
|
|
|
|
|
|
|
|
|
|
//! Type for set of temporary terms
|
2018-05-28 15:50:29 +02:00
|
|
|
|
/*! The ExprNodeLess ordering is important for the temporary terms algorithm,
|
2019-12-20 16:59:30 +01:00
|
|
|
|
see the definition of ExprNodeLess */
|
2018-06-04 14:31:26 +02:00
|
|
|
|
using temporary_terms_t = set<expr_t, ExprNodeLess>;
|
2018-03-27 17:14:30 +02:00
|
|
|
|
/*! Keeps track of array indices of temporary_terms for writing */
|
2023-04-05 14:53:47 +02:00
|
|
|
|
using temporary_terms_idxs_t = unordered_map<expr_t, int>;
|
2009-04-17 18:26:23 +02:00
|
|
|
|
|
2009-04-30 15:14:33 +02:00
|
|
|
|
//! Type for evaluation contexts
|
|
|
|
|
/*! The key is a symbol id. Lags are assumed to be null */
|
2018-06-04 14:31:26 +02:00
|
|
|
|
using eval_context_t = map<int, double>;
|
2009-04-30 15:14:33 +02:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Type for tracking first/second derivative functions that have already been written as temporary
|
|
|
|
|
//! terms
|
2018-06-04 14:31:26 +02:00
|
|
|
|
using deriv_node_temp_terms_t = map<pair<int, vector<expr_t>>, int>;
|
2010-03-04 16:40:07 +01:00
|
|
|
|
|
2019-10-22 14:56:28 +02:00
|
|
|
|
//! Type for the substitution map used for creating aux. vars for diff and unary_ops
|
|
|
|
|
/*! Let ≅ be the equivalence relationship such that two expressions e₁ and e₂
|
|
|
|
|
are equivalent iff e₁ can be obtained from e₂ by shifting all leads/lags by
|
|
|
|
|
the same number of periods (e.g. x₋₁+y₂≅x₁+y₄).
|
|
|
|
|
|
|
|
|
|
For each equivalence class, we select a representative element, which is
|
|
|
|
|
the class member which has no lead and a variable appearing at current
|
|
|
|
|
period (in the previous example, it would be x₋₃+y). (Obviously, if there
|
|
|
|
|
is no variable in the expression, then there is only one element in the
|
|
|
|
|
class, and that one is the representative)
|
|
|
|
|
|
|
|
|
|
Each member of an equivalence class is represented by an integer,
|
|
|
|
|
corresponding to its distance to the representative element (e.g. x₋₁+y₂
|
|
|
|
|
has index 2 and x₁+y₄ has index 4). The representative element has index 0
|
|
|
|
|
by definition.
|
|
|
|
|
|
|
|
|
|
The keys in the std::map are the representative elements of the various
|
|
|
|
|
equivalence classes. The values are themselves std::map that describe the
|
|
|
|
|
equivalence class: they associate indices of class members to the
|
|
|
|
|
expressions with which they should be substituted. */
|
|
|
|
|
using lag_equivalence_table_t = map<expr_t, map<int, expr_t>>;
|
2018-02-28 17:33:00 +01:00
|
|
|
|
|
2022-07-06 16:44:51 +02:00
|
|
|
|
//! Possible types of output when writing ExprNode(s) (not used for bytecode)
|
2018-09-05 18:27:13 +02:00
|
|
|
|
enum class ExprNodeOutputType
|
2023-11-30 15:28:57 +01:00
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
|
juliaTimeDataFrame, //!< Julia code for TimeDataFrame objects
|
|
|
|
|
epilogueFile, //!< Matlab code, in the generated epilogue file
|
|
|
|
|
occbinDifferenceFile //!< MATLAB, in the generated occbin_difference file
|
|
|
|
|
};
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
2022-07-06 16:44:51 +02:00
|
|
|
|
// Possible types of output when writing ExprNode(s) in bytecode
|
|
|
|
|
enum class ExprNodeBytecodeOutputType
|
2023-11-30 15:28:57 +01:00
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
};
|
2022-07-06 16:44:51 +02:00
|
|
|
|
|
2022-06-24 14:50:40 +02:00
|
|
|
|
constexpr bool
|
2018-09-05 18:27:13 +02:00
|
|
|
|
isMatlabOutput(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return output_type == ExprNodeOutputType::matlabStaticModel
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|| output_type == ExprNodeOutputType::matlabDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::matlabSparseStaticModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::matlabSparseDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::matlabOutsideModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
|
|
|
|
|
|| output_type == ExprNodeOutputType::steadyStateFile
|
|
|
|
|
|| output_type == ExprNodeOutputType::matlabDseries
|
|
|
|
|
|| output_type == ExprNodeOutputType::epilogueFile
|
|
|
|
|
|| output_type == ExprNodeOutputType::occbinDifferenceFile;
|
2018-09-05 18:27:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 14:50:40 +02:00
|
|
|
|
constexpr bool
|
2018-09-05 18:27:13 +02:00
|
|
|
|
isJuliaOutput(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return output_type == ExprNodeOutputType::juliaStaticModel
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|| output_type == ExprNodeOutputType::juliaDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::juliaSparseStaticModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::juliaSparseDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator
|
|
|
|
|
|| output_type == ExprNodeOutputType::juliaSteadyStateFile
|
|
|
|
|
|| output_type == ExprNodeOutputType::juliaTimeDataFrame;
|
2018-09-05 18:27:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 14:50:40 +02:00
|
|
|
|
constexpr bool
|
2018-09-05 18:27:13 +02:00
|
|
|
|
isCOutput(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return output_type == ExprNodeOutputType::CDynamicModel
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|| output_type == ExprNodeOutputType::CStaticModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::CSparseDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::CSparseStaticModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::CDynamicSteadyStateOperator;
|
2018-09-05 18:27:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 14:50:40 +02:00
|
|
|
|
constexpr bool
|
2018-09-05 18:27:13 +02:00
|
|
|
|
isLatexOutput(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return output_type == ExprNodeOutputType::latexStaticModel
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|| output_type == ExprNodeOutputType::latexDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator;
|
2018-09-05 18:27:13 +02:00
|
|
|
|
}
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
2022-07-05 15:04:36 +02:00
|
|
|
|
constexpr bool
|
|
|
|
|
isSteadyStateOperatorOutput(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|| output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
|
|
|
|
|
|| output_type == ExprNodeOutputType::CDynamicSteadyStateOperator
|
|
|
|
|
|| output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator;
|
2022-07-05 15:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-14 17:07:08 +02:00
|
|
|
|
constexpr bool
|
|
|
|
|
isSparseModelOutput(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return output_type == ExprNodeOutputType::matlabSparseStaticModel
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|| output_type == ExprNodeOutputType::matlabSparseDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::juliaSparseStaticModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::juliaSparseDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::CSparseDynamicModel
|
|
|
|
|
|| output_type == ExprNodeOutputType::CSparseStaticModel;
|
2022-09-14 17:07:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-06 16:44:51 +02:00
|
|
|
|
constexpr bool
|
|
|
|
|
isAssignmentLHSBytecodeOutput(ExprNodeBytecodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return output_type == ExprNodeBytecodeOutputType::staticAssignmentLHS
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|| output_type == ExprNodeBytecodeOutputType::dynamicAssignmentLHS;
|
2022-07-06 16:44:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-21 16:44:55 +02:00
|
|
|
|
/* 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 */
|
2022-06-24 14:50:40 +02:00
|
|
|
|
constexpr int
|
2019-12-16 19:42:59 +01:00
|
|
|
|
ARRAY_SUBSCRIPT_OFFSET(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<int>(isMatlabOutput(output_type) || isJuliaOutput(output_type));
|
|
|
|
|
}
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
2009-04-30 15:14:33 +02:00
|
|
|
|
// Left and right array subscript delimiters: '(' and ')' for Matlab, '[' and ']' for C
|
2022-06-24 14:50:40 +02:00
|
|
|
|
constexpr char
|
2019-12-16 19:42:59 +01:00
|
|
|
|
LEFT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return isMatlabOutput(output_type) ? '(' : '[';
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 14:50:40 +02:00
|
|
|
|
constexpr char
|
2019-12-16 19:42:59 +01:00
|
|
|
|
RIGHT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return isMatlabOutput(output_type) ? ')' : ']';
|
|
|
|
|
}
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
2009-04-30 15:14:33 +02:00
|
|
|
|
// Left and right parentheses
|
2019-12-16 19:42:59 +01:00
|
|
|
|
inline string
|
|
|
|
|
LEFT_PAR(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return isLatexOutput(output_type) ? "\\left(" : "(";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline string
|
|
|
|
|
RIGHT_PAR(ExprNodeOutputType output_type)
|
|
|
|
|
{
|
|
|
|
|
return isLatexOutput(output_type) ? "\\right)" : ")";
|
|
|
|
|
}
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
|
|
|
|
//! Base class for expression nodes
|
2018-02-07 10:05:32 +01:00
|
|
|
|
class ExprNode
|
2019-12-20 16:59:30 +01:00
|
|
|
|
{
|
|
|
|
|
friend class DataTree;
|
|
|
|
|
friend class DynamicModel;
|
|
|
|
|
friend class StaticModel;
|
|
|
|
|
friend class ModelTree;
|
|
|
|
|
friend struct ExprNodeLess;
|
|
|
|
|
friend class NumConstNode;
|
|
|
|
|
friend class VariableNode;
|
|
|
|
|
friend class UnaryOpNode;
|
|
|
|
|
friend class BinaryOpNode;
|
|
|
|
|
friend class TrinaryOpNode;
|
|
|
|
|
friend class AbstractExternalFunctionNode;
|
|
|
|
|
friend class VarExpectationNode;
|
|
|
|
|
friend class PacExpectationNode;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2022-11-08 12:28:48 +01:00
|
|
|
|
/* Internal helper for getChainRuleDerivative(), that does the computation
|
|
|
|
|
but assumes that the caching of this is handled elsewhere */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2022-11-08 12:28:48 +01:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
protected:
|
|
|
|
|
//! Reference to the enclosing DataTree
|
2023-11-30 15:28:57 +01:00
|
|
|
|
DataTree& datatree;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Index number
|
|
|
|
|
const int idx;
|
|
|
|
|
|
|
|
|
|
//! Is the data member non_null_derivatives initialized ?
|
2023-11-30 15:28:57 +01:00
|
|
|
|
bool preparedForDerivation {false};
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Set of derivation IDs with respect to which the derivative is potentially non-null
|
|
|
|
|
set<int> non_null_derivatives;
|
|
|
|
|
|
|
|
|
|
//! Used for caching of first order derivatives (when non-null)
|
|
|
|
|
map<int, expr_t> derivatives;
|
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
constexpr static int min_cost_matlab {40 * 90};
|
|
|
|
|
constexpr static int min_cost_c {40 * 4};
|
2022-06-24 14:50:40 +02:00
|
|
|
|
constexpr static int
|
2019-12-20 16:59:30 +01:00
|
|
|
|
min_cost(bool is_matlab)
|
|
|
|
|
{
|
2022-06-02 10:50:21 +02:00
|
|
|
|
return is_matlab ? min_cost_matlab : min_cost_c;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
};
|
|
|
|
|
|
2023-03-02 16:08:32 +01:00
|
|
|
|
//! Initializes data member non_null_derivatives
|
|
|
|
|
virtual void prepareForDerivation() = 0;
|
|
|
|
|
|
2023-03-02 17:49:16 +01:00
|
|
|
|
/* 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) */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void prepareForChainRuleDerivation(
|
|
|
|
|
const map<int, BinaryOpNode*>& recursive_variables,
|
|
|
|
|
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const
|
|
|
|
|
= 0;
|
2023-03-02 17:49:16 +01:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
//! Cost of computing current node
|
|
|
|
|
/*! Nodes included in temporary_terms are considered having a null cost */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! For creating equation cross references
|
|
|
|
|
struct EquationInfo
|
|
|
|
|
{
|
2022-06-02 10:50:21 +02:00
|
|
|
|
set<pair<int, int>> param, endo, exo, exo_det;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//! If this node is a temporary term, writes its temporary term representation
|
|
|
|
|
/*! Returns true if node is a temporary term and has therefore been
|
|
|
|
|
written to output*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
bool checkIfTemporaryTermThenWrite(ostream& output, ExprNodeOutputType output_type,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2022-06-23 14:28:13 +02:00
|
|
|
|
// Same as above, for the bytecode case
|
2023-11-30 15:28:57 +01:00
|
|
|
|
bool
|
2023-12-14 14:52:50 +01:00
|
|
|
|
checkIfTemporaryTermThenWriteBytecode(Bytecode::Writer& code_file,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs) const;
|
2022-06-23 14:28:13 +02:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
// Internal helper for matchVariableTimesConstantTimesParam()
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void matchVTCTPHelper(optional<int>& var_id, int& lag, optional<int>& param_id,
|
|
|
|
|
double& constant, bool at_denominator) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
/* 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. */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] pair<expr_t, int> getLagEquivalenceClass() const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2022-10-18 17:24:51 +02:00
|
|
|
|
/* 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) */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void computeSubExprContainingVariable(int symb_id, int lag,
|
|
|
|
|
set<expr_t>& contain_var) const
|
|
|
|
|
= 0;
|
2022-10-18 17:24:51 +02:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
ExprNode(DataTree& datatree_arg, int idx_arg);
|
2019-12-20 16:59:30 +01:00
|
|
|
|
virtual ~ExprNode() = default;
|
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
ExprNode(const ExprNode&) = delete;
|
|
|
|
|
ExprNode& operator=(const ExprNode&) = delete;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Returns derivative w.r. to derivation ID
|
2023-11-30 15:28:57 +01:00
|
|
|
|
/*! 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 */
|
2019-12-20 16:59:30 +01:00
|
|
|
|
expr_t getDerivative(int deriv_id);
|
|
|
|
|
|
2022-11-08 12:28:48 +01:00
|
|
|
|
/* 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
|
2023-03-02 17:49:16 +01:00
|
|
|
|
— “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.
|
2022-11-08 12:28:48 +01:00
|
|
|
|
— “cache” is used to store already-computed derivatives (in a map
|
2023-03-02 17:49:16 +01:00
|
|
|
|
<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
|
2023-04-05 14:16:22 +02:00
|
|
|
|
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) */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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);
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Returns precedence of node
|
|
|
|
|
/*! Equals 100 for constants, variables, unary ops, and temporary terms */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int precedence(ExprNodeOutputType output_t,
|
|
|
|
|
const temporary_terms_t& temporary_terms) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Compute temporary terms in this expression
|
|
|
|
|
/*!
|
|
|
|
|
\param[in] derivOrder the derivation order (first w.r.t. endo/exo,
|
|
|
|
|
second w.r.t. params)
|
|
|
|
|
\param[out] temp_terms_map the computed temporary terms, associated
|
|
|
|
|
with their derivation order
|
|
|
|
|
\param[out] reference_count a temporary structure, used to count
|
|
|
|
|
references to each node (integer in outer pair is the
|
|
|
|
|
reference count, the inner pair is the derivation order)
|
|
|
|
|
\param[in] is_matlab whether we are in a MATLAB context, since that
|
|
|
|
|
affects the cost of each operator
|
|
|
|
|
|
|
|
|
|
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
|
2023-04-05 14:53:47 +02:00
|
|
|
|
|
|
|
|
|
NB: the use of std::unordered_map instead of std::map for caching
|
|
|
|
|
purposes improves performance on very large models (⩾5000 equations)
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2020-05-06 17:13:47 +02:00
|
|
|
|
//! Compute temporary terms in this expression for block decomposed model
|
|
|
|
|
/*!
|
|
|
|
|
\param[in] blk the block number
|
2020-05-13 16:58:19 +02:00
|
|
|
|
\param[in] eq the equation number (within the block)
|
2020-05-06 17:13:47 +02:00
|
|
|
|
\param[out] blocks_temporary_terms the computed temporary terms, per block
|
2020-05-13 16:58:19 +02:00
|
|
|
|
and per equation in the block
|
2020-05-06 17:13:47 +02:00
|
|
|
|
\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
|
2020-05-13 16:58:19 +02:00
|
|
|
|
expression first appears, third integer is the equation number within the block)
|
2020-05-06 17:13:47 +02:00
|
|
|
|
|
|
|
|
|
Same rules as computeTemporaryTerms() for computing cost.
|
2023-04-05 14:53:47 +02:00
|
|
|
|
|
|
|
|
|
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)
|
2020-05-06 17:13:47 +02:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2020-05-06 17:13:47 +02:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the
|
|
|
|
|
//! set of already written external functions
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
|
|
|
|
\param[in] output the output stream
|
|
|
|
|
\param[in] output_type the type of output (MATLAB, C, LaTeX...)
|
|
|
|
|
\param[in] temporary_terms the nodes that are marked as temporary terms
|
|
|
|
|
\param[in] a map from temporary_terms to integers indexes (in the
|
|
|
|
|
MATLAB, C or Julia vector of temporary terms); can be empty
|
|
|
|
|
when writing MATLAB with block decomposition)
|
|
|
|
|
\param[in] tef_terms the set of already written external function nodes
|
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! returns true if the expr node contains an external function
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual bool containsExternalFunction() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Writes output of node (with no temporary terms and with "outside model" output type)
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void writeOutput(ostream& output) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Writes output of node (with no temporary terms)
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void writeOutput(ostream& output, ExprNodeOutputType output_type) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Writes output of node, using a Txxx notation for nodes in temporary_terms
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void writeOutput(ostream& output, ExprNodeOutputType output_type,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Writes output of node in JSON syntax
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
|
|
|
|
|
const deriv_node_temp_terms_t& tef_terms,
|
|
|
|
|
bool isdynamic = true) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2022-01-26 15:16:22 +01:00
|
|
|
|
// Returns a string representation of the expression, used by the GDB pretty printer
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] string toString() const;
|
2022-01-26 15:16:22 +01:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
//! Writes the Abstract Syntax Tree in JSON
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void writeJsonAST(ostream& output) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int precedenceJson(const temporary_terms_t& temporary_terms) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! 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,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Write the JSON output of an external function in a string vector
|
|
|
|
|
//! Allows the insertion of commas if necessary
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void writeJsonExternalFunctionOutput(vector<string>& efout,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms,
|
2019-12-20 16:59:30 +01:00
|
|
|
|
bool isdynamic = true) const;
|
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void writeBytecodeExternalFunctionOutput(
|
2023-12-14 14:52:50 +01:00
|
|
|
|
Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Computes the set of all variables of a given symbol type in the expression (with information
|
|
|
|
|
//! on lags)
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
|
|
|
|
Variables are stored as integer pairs of the form (symb_id, lag).
|
|
|
|
|
They are added to the set given in argument.
|
|
|
|
|
Note that model local variables are substituted by their expression in the computation
|
|
|
|
|
(and added if type_arg = ModelLocalVariable).
|
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Find the maximum lag in a VAR: handles case where LHS is diff
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int VarMaxLag(const set<expr_t>& lhs_lag_equiv) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Finds LHS variable in a VAR equation
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void collectVARLHSVariable(set<expr_t>& result) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Computes the set of all variables of a given symbol type in the expression (without
|
|
|
|
|
//! information on lags)
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
|
|
|
|
Variables are stored as symb_id.
|
|
|
|
|
They are added to the set given in argument.
|
|
|
|
|
Note that model local variables are substituted by their expression in the computation
|
|
|
|
|
(and added if type_arg = ModelLocalVariable).
|
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void collectVariables(SymbolType type_arg, set<int>& result) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Computes the set of endogenous variables in the expression
|
|
|
|
|
/*!
|
|
|
|
|
Endogenous 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.
|
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void collectEndogenous(set<pair<int, int>>& result) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
class EvalException
|
|
|
|
|
{
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class EvalExternalFunctionException : public EvalException
|
|
|
|
|
{
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual double eval(const eval_context_t& eval_context) const noexcept(false) = 0;
|
2022-07-06 16:44:51 +02:00
|
|
|
|
|
|
|
|
|
// Write output to bytecode file
|
2023-12-14 14:52:50 +01:00
|
|
|
|
virtual void writeBytecodeOutput(Bytecode::Writer& code_file,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2022-05-20 11:43:02 +02:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
//! Creates a static version of this node
|
|
|
|
|
/*!
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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.
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t toStatic(DataTree& static_datatree) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Compute cross references for equations
|
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
// virtual void computeXrefs(set<int> ¶m, set<int> &endo, set<int> &exo, set<int> &exo_det)
|
|
|
|
|
// const = 0;
|
|
|
|
|
virtual void computeXrefs(EquationInfo& ei) const = 0;
|
2020-04-02 14:36:26 +02:00
|
|
|
|
|
|
|
|
|
//! 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. */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const
|
|
|
|
|
= 0;
|
|
|
|
|
class NormalizationFailed
|
|
|
|
|
{
|
|
|
|
|
};
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Returns the maximum lead of endogenous in this expression
|
|
|
|
|
/*! Always returns a non-negative value */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int maxEndoLead() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Returns the maximum lead of exogenous in this expression
|
|
|
|
|
/*! Always returns a non-negative value */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int maxExoLead() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Returns the maximum lag of endogenous in this expression
|
|
|
|
|
/*! Always returns a non-negative value */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int maxEndoLag() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Returns the maximum lag of exogenous in this expression
|
|
|
|
|
/*! Always returns a non-negative value */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int maxExoLag() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! 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. */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int maxLead() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! 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. */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int maxLag() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! 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. */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int maxLagWithDiffsExpanded() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t undiff() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Returns a new expression where all the leads/lags have been shifted backwards by the same
|
|
|
|
|
//! amount
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
|
|
|
|
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
|
|
|
|
|
*/
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t decreaseLeadsLags(int n) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Type for the substitution map used in the process of creating auxiliary vars
|
2023-11-30 15:28:57 +01:00
|
|
|
|
using subst_table_t = map<const ExprNode*, const VariableNode*>;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Type for the substitution map used in the process of substituting adl expressions
|
2023-11-30 15:28:57 +01:00
|
|
|
|
using subst_table_adl_t = map<const ExprNode*, const expr_t>;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Creates auxiliary endo lead variables corresponding to this expression
|
|
|
|
|
/*!
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
VariableNode* createEndoLeadAuxiliaryVarForMyself(subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Creates auxiliary exo lead variables corresponding to this expression
|
|
|
|
|
/*!
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
VariableNode* createExoLeadAuxiliaryVarForMyself(subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced
|
|
|
|
|
//! by auxiliary variables
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
2023-11-30 15:28:57 +01:00
|
|
|
|
\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.
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
If the method detects a sub-expr which needs to be substituted, two cases are possible:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
- 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
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
\return A new equivalent expression where sub-expressions with max endo lead >= 2 have been
|
|
|
|
|
replaced by auxiliary variables
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs,
|
|
|
|
|
bool deterministic_model) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by
|
|
|
|
|
//! auxiliary variables
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
2023-11-30 15:28:57 +01:00
|
|
|
|
\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.
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Constructs a new expression where exogenous variables with a lead have been replaced by
|
|
|
|
|
//! auxiliary variables
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
2023-11-30 15:28:57 +01:00
|
|
|
|
\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.
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
2023-11-30 15:28:57 +01:00
|
|
|
|
\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.
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t substituteExoLag(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Constructs a new expression where the expectation operator has been replaced by auxiliary
|
|
|
|
|
//! variables
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
2023-11-30 15:28:57 +01:00
|
|
|
|
\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?
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
|
|
|
|
|
bool partial_information_model) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t decreaseLeadsLagsPredeterminedVariables() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! 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
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
|
|
|
|
\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
|
2023-11-30 15:28:57 +01:00
|
|
|
|
\param[out] neweqs Equations to be added to the model to match the creation of auxiliary
|
|
|
|
|
variables.
|
2019-12-20 16:59:30 +01:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! 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
|
|
|
|
|
*/
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual bool isNumConstNodeEqualTo(double value) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Returns the maximum number of nested diffs in the expression
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual int countDiffs() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! 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
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*!
|
|
|
|
|
\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
|
|
|
|
|
*/
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id,
|
|
|
|
|
int lag_arg) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Replaces the Trend var with datatree.One
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t replaceTrendVar() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Constructs a new expression where the variable indicated by symb_id has been detrended
|
|
|
|
|
/*!
|
|
|
|
|
\param[in] symb_id indicating the variable to be detrended
|
|
|
|
|
\param[in] log_trend indicates if the trend is in log
|
|
|
|
|
\param[in] trend indicating the trend
|
|
|
|
|
\return the new binary op pointing to a detrended variable
|
|
|
|
|
*/
|
|
|
|
|
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0;
|
|
|
|
|
|
|
|
|
|
//! Substitute adl operator
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t substituteAdl() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2020-11-10 18:04:05 +01:00
|
|
|
|
//! Substitute out model-local variables
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t substituteModelLocalVariables() const = 0;
|
2020-11-10 18:04:05 +01:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
//! Substitute VarExpectation nodes
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t
|
|
|
|
|
substituteVarExpectation(const map<string, expr_t>& subst_table) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Mark diff nodes to be substituted
|
|
|
|
|
/*! The various nodes that are equivalent up to a shift of leads/lags are
|
|
|
|
|
grouped together in the “nodes” table. See the comment above
|
|
|
|
|
lag_equivalence_table_t for more details. */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void findDiffNodes(lag_equivalence_table_t& nodes) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
//! Substitute diff operator
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t substituteDiff(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Mark unary ops nodes to be substituted
|
|
|
|
|
/*! The various nodes that are equivalent up to a shift of leads/lags are
|
|
|
|
|
grouped together in the “nodes” table. See the comment above
|
|
|
|
|
lag_equivalence_table_t for more details. */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
//! Substitute unary ops nodes
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes,
|
|
|
|
|
subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Substitute pac_expectation operator
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t substitutePacExpectation(const string& name, expr_t subexpr) = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2021-10-26 18:06:26 +02:00
|
|
|
|
//! Substitute pac_target_nonstationary operator
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) = 0;
|
2021-10-26 18:06:26 +02:00
|
|
|
|
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual optional<int> findTargetVariable(int lhs_symb_id) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Add ExprNodes to the provided datatree
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t clone(DataTree& alt_datatree) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const
|
|
|
|
|
= 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Returns true if the expression is in static form (no lead, no lag, no expectation, no
|
|
|
|
|
//! STEADY_STATE)
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual bool isInStaticForm() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Matches a linear combination of variables (endo or exo), where scalars can be
|
|
|
|
|
//! constant*parameter
|
2019-12-20 16:59:30 +01:00
|
|
|
|
/*! Returns a list of (variable_id, lag, param_id, constant)
|
|
|
|
|
corresponding to the terms in the expression. When there is no
|
2022-05-16 17:42:24 +02:00
|
|
|
|
parameter in a term, param_id is nullopt.
|
2019-12-20 16:59:30 +01:00
|
|
|
|
Can throw a MatchFailureException.
|
|
|
|
|
*/
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] vector<tuple<int, int, optional<int>, double>>
|
|
|
|
|
matchLinearCombinationOfVariables() const;
|
2022-05-16 17:42:24 +02:00
|
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
|
*/
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] vector<tuple<optional<int>, int, optional<int>, double>>
|
2023-11-30 15:28:57 +01:00
|
|
|
|
matchLinearCombinationOfVariablesPlusConstant() const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2022-01-28 17:24:48 +01:00
|
|
|
|
/* 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(). */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] pair<int, vector<tuple<int, int, optional<int>, double>>>
|
2023-11-30 15:28:57 +01:00
|
|
|
|
matchParamTimesLinearCombinationOfVariables() const;
|
2022-01-28 17:24:48 +01:00
|
|
|
|
|
2021-10-26 18:06:26 +02:00
|
|
|
|
/* 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 */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] pair<vector<pair<int, expr_t>>, expr_t>
|
|
|
|
|
matchLinearCombinationOfEndogenousWithConstant() const;
|
2021-10-26 18:06:26 +02:00
|
|
|
|
|
2020-07-23 14:45:32 +02:00
|
|
|
|
/* Matches an expression of the form parameter*(var1-endo2).
|
|
|
|
|
endo2 must correspond to symb_id. var1 must be an endogenous or an
|
2020-07-24 12:28:13 +02:00
|
|
|
|
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.
|
2020-07-23 14:45:32 +02:00
|
|
|
|
Returns the symbol IDs of the parameter and of var1.
|
|
|
|
|
Throws a MatchFailureException otherwise */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] pair<int, int> matchParamTimesTargetMinusVariable(int symb_id) const;
|
2020-07-23 14:45:32 +02:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
//! Returns true if expression is of the form:
|
|
|
|
|
//! param * (endog op endog op ...) + param * (endog op endog op ...) + ...
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual bool isParamTimesEndogExpr() const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Fills the EC matrix structure
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2020-09-29 17:58:41 +02:00
|
|
|
|
//! Replaces variables found in BinaryOpNode::findConstantEquations() with their constant values
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
|
|
|
|
//! Returns true if PacExpectationNode encountered
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual bool containsPacExpectation(const string& pac_model_name = "") const = 0;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2021-10-26 18:06:26 +02:00
|
|
|
|
//! Returns true if PacTargetNonstationaryNode encountered
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual bool containsPacTargetNonstationary(const string& pac_model_name = "") const
|
|
|
|
|
= 0;
|
2021-10-26 18:06:26 +02:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
//! Decompose an expression into its additive terms
|
|
|
|
|
/*! Returns a list of terms, with their sign (either 1 or -1, depending
|
|
|
|
|
on whether the terms appears with a plus or a minus).
|
|
|
|
|
The current_sign argument should normally be left to 1.
|
|
|
|
|
If current_sign == -1, then all signs are inverted */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign = 1) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2020-10-19 18:26:36 +02:00
|
|
|
|
//! 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 */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void decomposeMultiplicativeFactors(vector<pair<expr_t, int>>& factors,
|
|
|
|
|
int current_exponent = 1) const;
|
2020-10-19 18:26:36 +02:00
|
|
|
|
|
2019-12-20 16:59:30 +01:00
|
|
|
|
// Matches an expression of the form variable*constant*parameter
|
|
|
|
|
/* Returns a tuple (variable_id, lag, param_id, constant).
|
2022-05-16 17:42:24 +02:00
|
|
|
|
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.
|
2019-12-20 16:59:30 +01:00
|
|
|
|
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).
|
2022-05-16 17:42:24 +02:00
|
|
|
|
The parameter is optional (in which case param_id is nullopt).
|
2019-12-20 16:59:30 +01:00
|
|
|
|
If the expression is not of the expected form, throws a
|
|
|
|
|
MatchFailureException
|
|
|
|
|
*/
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] tuple<optional<int>, int, optional<int>, double>
|
2023-11-30 15:28:57 +01:00
|
|
|
|
matchVariableTimesConstantTimesParam(bool variable_obligatory) const;
|
2019-12-20 16:59:30 +01:00
|
|
|
|
|
2021-10-26 18:06:26 +02:00
|
|
|
|
/* 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). */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual pair<int, expr_t> matchEndogenousTimesConstant() const;
|
2021-10-26 18:06:26 +02:00
|
|
|
|
|
|
|
|
|
//! Exception thrown when matching fails
|
2022-07-20 13:22:21 +02:00
|
|
|
|
struct MatchFailureException
|
2019-12-20 16:59:30 +01:00
|
|
|
|
{
|
|
|
|
|
const string message;
|
|
|
|
|
};
|
2020-07-28 18:29:45 +02:00
|
|
|
|
|
|
|
|
|
/* 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. */
|
2023-11-30 15:28:57 +01:00
|
|
|
|
virtual void matchMatchedMoment(vector<int>& symb_ids, vector<int>& lags,
|
|
|
|
|
vector<int>& powers) const;
|
2021-07-07 10:54:04 +02:00
|
|
|
|
|
|
|
|
|
/* Returns true if the expression contains no endogenous, no exogenous and no
|
|
|
|
|
exogenous deterministic */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool isConstant() const;
|
2021-07-20 12:10:58 +02:00
|
|
|
|
|
|
|
|
|
// Returns true if the expression contains an exogenous or an exogenous deterministic
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool hasExogenous() const;
|
2022-03-30 17:40:01 +02:00
|
|
|
|
|
|
|
|
|
// Substitutes orig_symb_id(±l) with exp(aux_symb_id(±l)) (used for “var(log)”)
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const = 0;
|
2018-11-27 18:53:28 +01:00
|
|
|
|
};
|
2008-02-03 11:28:36 +01:00
|
|
|
|
|
|
|
|
|
//! Object used to compare two nodes (using their indexes)
|
2018-05-28 15:50:29 +02:00
|
|
|
|
/*! Note that in this ordering, a subexpression is always less than the
|
2019-12-20 16:59:30 +01:00
|
|
|
|
expression from which it is extracted. This property is used extensively in
|
|
|
|
|
the temporary terms computations. */
|
2008-02-03 11:28:36 +01:00
|
|
|
|
struct ExprNodeLess
|
|
|
|
|
{
|
2009-12-16 18:13:23 +01:00
|
|
|
|
bool
|
2010-09-16 19:18:45 +02:00
|
|
|
|
operator()(expr_t arg1, expr_t arg2) const
|
2008-02-03 11:28:36 +01:00
|
|
|
|
{
|
|
|
|
|
return arg1->idx < arg2->idx;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//! Numerical constant node
|
2023-11-30 15:28:57 +01:00
|
|
|
|
/*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class
|
|
|
|
|
* level) */
|
2008-02-03 11:28:36 +01:00
|
|
|
|
class NumConstNode : public ExprNode
|
|
|
|
|
{
|
2018-11-28 14:32:26 +01:00
|
|
|
|
public:
|
2008-02-03 11:28:36 +01:00
|
|
|
|
//! Id from numerical constants table
|
|
|
|
|
const int id;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
private:
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t computeDerivative(int deriv_id) override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2018-11-28 14:18:08 +01:00
|
|
|
|
protected:
|
2023-03-02 16:08:32 +01:00
|
|
|
|
void prepareForDerivation() override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2008-02-03 11:28:36 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
NumConstNode(DataTree& datatree_arg, int idx_arg, int id_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, bool isdynamic) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsExternalFunction() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void collectVARLHSVariable(set<expr_t>& result) const override;
|
|
|
|
|
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
|
|
|
|
|
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t clone(DataTree& alt_datatree) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
|
|
|
|
|
[[nodiscard]] bool isInStaticForm() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//! Symbol or variable node
|
|
|
|
|
class VariableNode : public ExprNode
|
|
|
|
|
{
|
2011-01-13 18:08:26 +01:00
|
|
|
|
friend class UnaryOpNode;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
public:
|
2008-02-03 11:28:36 +01:00
|
|
|
|
//! Id from the symbol table
|
|
|
|
|
const int symb_id;
|
2010-08-19 15:20:54 +02:00
|
|
|
|
//! A positive value is a lead, a negative is a lag
|
2008-02-03 11:28:36 +01:00
|
|
|
|
const int lag;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
private:
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t computeDerivative(int deriv_id) override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2018-11-28 14:18:08 +01:00
|
|
|
|
protected:
|
2023-03-02 16:08:32 +01:00
|
|
|
|
void prepareForDerivation() override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2008-02-03 11:28:36 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
VariableNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg, int lag_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, bool isdynamic) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsExternalFunction() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void collectVARLHSVariable(set<expr_t>& result) const override;
|
|
|
|
|
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] SymbolType get_type() const;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
|
|
|
|
|
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t clone(DataTree& alt_datatree) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
|
|
|
|
|
[[nodiscard]] bool isInStaticForm() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void matchMatchedMoment(vector<int>& symb_ids, vector<int>& lags,
|
|
|
|
|
vector<int>& powers) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] pair<int, expr_t> matchEndogenousTimesConstant() const override;
|
|
|
|
|
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//! Unary operator node
|
|
|
|
|
class UnaryOpNode : public ExprNode
|
|
|
|
|
{
|
2018-11-28 14:18:08 +01:00
|
|
|
|
protected:
|
2023-03-02 16:08:32 +01:00
|
|
|
|
void prepareForDerivation() override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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)
|
2023-03-23 12:38:44 +01:00
|
|
|
|
template<typename Callable, typename... Args>
|
|
|
|
|
expr_t
|
|
|
|
|
recurseTransform(Callable&& op, Args&&... args) const
|
|
|
|
|
{
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t substarg {invoke(forward<Callable>(op), arg, forward<Args>(args)...)};
|
2023-03-23 12:38:44 +01:00
|
|
|
|
return buildSimilarUnaryOpNode(substarg, datatree);
|
|
|
|
|
}
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
public:
|
2010-09-16 19:18:45 +02:00
|
|
|
|
const expr_t arg;
|
2009-11-06 19:19:52 +01:00
|
|
|
|
//! Stores the information set. Only used for expectation operator
|
|
|
|
|
const int expectation_information_set;
|
2018-07-18 16:18:26 +02:00
|
|
|
|
//! Only used for UnaryOpcode::steadyStateParamDeriv and UnaryOpcode::steadyStateParam2ndDeriv
|
2011-01-13 18:08:26 +01:00
|
|
|
|
const int param1_symb_id, param2_symb_id;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
const UnaryOpcode op_code;
|
2017-07-03 16:38:44 +02:00
|
|
|
|
const string adl_param_name;
|
2017-07-03 17:21:11 +02:00
|
|
|
|
const vector<int> adl_lags;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
private:
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t computeDerivative(int deriv_id) override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2009-07-06 11:34:21 +02:00
|
|
|
|
//! Returns the derivative of this node if darg is the derivative of the argument
|
2011-01-13 18:08:26 +01:00
|
|
|
|
expr_t composeDerivatives(expr_t darg, int deriv_id);
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2008-02-03 11:28:36 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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>, unordered_set<expr_t>>& temp_terms_map,
|
|
|
|
|
unordered_map<expr_t, pair<int, pair<int, int>>>& reference_count,
|
2018-11-30 12:22:13 +01:00
|
|
|
|
bool is_matlab) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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, bool isdynamic) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsExternalFunction() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
void writeJsonExternalFunctionOutput(vector<string>& efout,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms,
|
2019-12-20 16:59:30 +01:00
|
|
|
|
bool isdynamic) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
|
2022-07-06 16:44:51 +02:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms) const override;
|
|
|
|
|
void collectVARLHSVariable(set<expr_t>& result) const override;
|
|
|
|
|
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
|
2018-06-04 12:50:53 +02:00
|
|
|
|
static double eval_opcode(UnaryOpcode op_code, double v) noexcept(false);
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool createAuxVarForUnaryOpNode() const;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t clone(DataTree& alt_datatree) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
|
|
|
|
|
[[nodiscard]] bool isInStaticForm() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void decomposeAdditiveTerms(vector<pair<expr_t, int>>& terms, int current_sign) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//! Binary operator node
|
|
|
|
|
class BinaryOpNode : public ExprNode
|
|
|
|
|
{
|
2018-11-28 14:18:08 +01:00
|
|
|
|
protected:
|
2023-03-02 16:08:32 +01:00
|
|
|
|
void prepareForDerivation() override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
public:
|
2010-09-16 19:18:45 +02:00
|
|
|
|
const expr_t arg1, arg2;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
const BinaryOpcode op_code;
|
2018-11-28 14:32:26 +01:00
|
|
|
|
const int powerDerivOrder;
|
|
|
|
|
const string adlparam;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
private:
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t computeDerivative(int deriv_id) override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2009-07-06 11:34:21 +02:00
|
|
|
|
//! Returns the derivative of this node if darg1 and darg2 are the derivatives of the arguments
|
2010-09-16 19:18:45 +02:00
|
|
|
|
expr_t composeDerivatives(expr_t darg1, expr_t darg2);
|
2023-11-30 15:28:57 +01:00
|
|
|
|
// Returns the node obtained by applying a transformation recursively on the arguments (in same
|
|
|
|
|
// datatree)
|
2023-03-23 12:38:44 +01:00
|
|
|
|
template<typename Callable, typename... Args>
|
|
|
|
|
expr_t
|
|
|
|
|
recurseTransform(Callable&& op, Args&&... args) const
|
|
|
|
|
{
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t substarg1 {invoke(forward<Callable>(op), arg1, forward<Args>(args)...)};
|
|
|
|
|
expr_t substarg2 {invoke(forward<Callable>(op), arg2, forward<Args>(args)...)};
|
2023-03-23 12:38:44 +01:00
|
|
|
|
return buildSimilarBinaryOpNode(substarg1, substarg2, datatree);
|
|
|
|
|
}
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2008-02-03 11:28:36 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
BinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg, BinaryOpcode op_code_arg,
|
|
|
|
|
const expr_t arg2_arg, int powerDerivOrder);
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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,
|
2018-11-30 12:22:13 +01:00
|
|
|
|
bool is_matlab) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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, bool isdynamic) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsExternalFunction() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
void writeJsonExternalFunctionOutput(vector<string>& efout,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms,
|
2019-12-20 16:59:30 +01:00
|
|
|
|
bool isdynamic) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
|
2022-07-06 16:44:51 +02:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms) const override;
|
|
|
|
|
void collectVARLHSVariable(set<expr_t>& result) const override;
|
|
|
|
|
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
|
|
|
|
|
static double eval_opcode(double v1, BinaryOpcode op_code, double v2,
|
|
|
|
|
int derivOrder) noexcept(false);
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
const deriv_node_temp_terms_t& tef_terms) const override;
|
2018-11-27 09:48:59 +01:00
|
|
|
|
expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t toStatic(DataTree& static_datatree) const override;
|
|
|
|
|
void computeXrefs(EquationInfo& ei) const override;
|
|
|
|
|
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
|
2020-04-02 14:36:26 +02:00
|
|
|
|
//! 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. */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
|
|
|
|
|
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool findTargetVariableHelper1(int lhs_symb_id, int rhs_symb_id) const;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
optional<int> findTargetVariableHelper(const expr_t arg1, const expr_t arg2,
|
|
|
|
|
int lhs_symb_id) const;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t clone(DataTree& alt_datatree) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Function to write out the oPowerNode in expr_t terms as opposed to writing out the function
|
|
|
|
|
//! itself
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t unpackPowerDeriv() const;
|
2011-03-28 11:19:10 +02:00
|
|
|
|
//! Returns MULT_i*(lhs-rhs) = 0, creating multiplier MULT_i
|
2011-03-21 18:40:57 +01:00
|
|
|
|
expr_t addMultipliersToConstraints(int i);
|
|
|
|
|
//! Returns the non-zero hand-side of an equation (that must have a hand side equal to zero)
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t getNonZeroPartofEquation() const;
|
|
|
|
|
[[nodiscard]] bool isInStaticForm() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void fillAutoregressiveRow(int eqn, const vector<int>& lhs,
|
|
|
|
|
map<tuple<int, int, int>, expr_t>& AR) const;
|
2020-09-29 17:58:41 +02:00
|
|
|
|
//! Finds equations where a variable is equal to a constant
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findConstantEquations(map<VariableNode*, NumConstNode*>& table) const;
|
|
|
|
|
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
|
|
|
|
|
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
|
|
|
|
|
= "") const override;
|
2020-07-23 14:45:32 +02:00
|
|
|
|
/*
|
|
|
|
|
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
|
2020-09-11 16:45:19 +02:00
|
|
|
|
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)
|
2020-07-23 14:45:32 +02:00
|
|
|
|
*/
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void getPacAREC(
|
|
|
|
|
int lhs_symb_id, int lhs_orig_symb_id,
|
|
|
|
|
pair<int, vector<tuple<int, bool, int>>>& ec_params_and_vars,
|
|
|
|
|
vector<tuple<optional<int>, optional<int>, int>>& ar_params_and_vars,
|
|
|
|
|
vector<tuple<int, int, optional<int>, double>>& additive_vars_params_and_constants) const;
|
2019-02-27 23:12:05 +01:00
|
|
|
|
|
|
|
|
|
//! 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
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] tuple<optional<int>, expr_t, expr_t, expr_t>
|
2023-11-30 15:28:57 +01:00
|
|
|
|
getPacOptimizingShareAndExprNodes(int lhs_orig_symb_id) const;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] pair<int, expr_t> matchEndogenousTimesConstant() const override;
|
|
|
|
|
[[nodiscard]] expr_t substituteLogTransform(int orig_symb_id, int aux_symb_id) const override;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//! Trinary operator node
|
|
|
|
|
class TrinaryOpNode : public ExprNode
|
|
|
|
|
{
|
|
|
|
|
friend class ModelTree;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
public:
|
2010-09-16 19:18:45 +02:00
|
|
|
|
const expr_t arg1, arg2, arg3;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
const TrinaryOpcode op_code;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2022-10-18 17:24:51 +02:00
|
|
|
|
protected:
|
2023-03-02 16:08:32 +01:00
|
|
|
|
void prepareForDerivation() override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
private:
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t computeDerivative(int deriv_id) override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
//! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the
|
|
|
|
|
//! arguments
|
2010-09-16 19:18:45 +02:00
|
|
|
|
expr_t composeDerivatives(expr_t darg1, expr_t darg2, expr_t darg3);
|
2023-11-30 15:28:57 +01:00
|
|
|
|
// Returns the node obtained by applying a transformation recursively on the arguments (in same
|
|
|
|
|
// datatree)
|
2023-03-23 12:38:44 +01:00
|
|
|
|
template<typename Callable, typename... Args>
|
|
|
|
|
expr_t
|
|
|
|
|
recurseTransform(Callable&& op, Args&&... args) const
|
|
|
|
|
{
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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)...)};
|
2023-03-23 12:38:44 +01:00
|
|
|
|
return buildSimilarTrinaryOpNode(substarg1, substarg2, substarg3, datatree);
|
|
|
|
|
}
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2008-02-03 11:28:36 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
TrinaryOpNode(DataTree& datatree_arg, int idx_arg, const expr_t arg1_arg,
|
2010-09-16 19:18:45 +02:00
|
|
|
|
TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg);
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] int precedence(ExprNodeOutputType output_type,
|
|
|
|
|
const temporary_terms_t& temporary_terms) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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,
|
2018-11-30 12:22:13 +01:00
|
|
|
|
bool is_matlab) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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, bool isdynamic) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsExternalFunction() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
void writeJsonExternalFunctionOutput(vector<string>& efout,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms,
|
2019-12-20 16:59:30 +01:00
|
|
|
|
bool isdynamic) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
|
2022-07-06 16:44:51 +02:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms) const override;
|
|
|
|
|
void collectVARLHSVariable(set<expr_t>& result) const override;
|
|
|
|
|
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
|
2018-06-04 12:50:53 +02:00
|
|
|
|
static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) noexcept(false);
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
|
|
|
|
|
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t clone(DataTree& alt_datatree) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
|
|
|
|
|
[[nodiscard]] bool isInStaticForm() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
};
|
|
|
|
|
|
2010-02-22 17:33:38 +01:00
|
|
|
|
//! External function node
|
2014-03-13 11:22:00 +01:00
|
|
|
|
class AbstractExternalFunctionNode : public ExprNode
|
2008-02-03 11:28:36 +01:00
|
|
|
|
{
|
2018-11-28 14:32:26 +01:00
|
|
|
|
public:
|
|
|
|
|
const int symb_id;
|
|
|
|
|
const vector<expr_t> arguments;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2008-02-03 11:28:36 +01:00
|
|
|
|
private:
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t computeDerivative(int deriv_id) override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-02-28 15:33:24 +01:00
|
|
|
|
// Computes the maximum of f applied to all arguments (result will always be non-negative)
|
2023-11-30 15:28:57 +01:00
|
|
|
|
int maxHelper(const function<int(expr_t)>& f) const;
|
|
|
|
|
// Returns the node obtained by applying a transformation recursively on the arguments (in same
|
|
|
|
|
// datatree)
|
2023-03-23 12:38:44 +01:00
|
|
|
|
template<typename Callable, typename... 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);
|
|
|
|
|
}
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2010-02-22 17:33:38 +01:00
|
|
|
|
protected:
|
2010-03-04 16:40:07 +01:00
|
|
|
|
//! Thrown when trying to access an unknown entry in external_function_node_map
|
|
|
|
|
class UnknownFunctionNameAndArgs
|
|
|
|
|
{
|
|
|
|
|
};
|
2023-03-02 16:08:32 +01:00
|
|
|
|
void prepareForDerivation() override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void prepareForChainRuleDerivation(
|
|
|
|
|
const map<int, BinaryOpNode*>& recursive_variables,
|
|
|
|
|
unordered_map<expr_t, set<int>>& non_null_chain_rule_derivatives) const override;
|
2010-03-04 16:40:07 +01:00
|
|
|
|
//! Returns true if the given external function has been written as a temporary term
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool alreadyWrittenAsTefTerm(int the_symb_id,
|
|
|
|
|
const deriv_node_temp_terms_t& tef_terms) const;
|
2010-03-04 16:40:07 +01:00
|
|
|
|
//! Returns the index in the tef_terms map of this external function
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] int getIndxInTefTerms(int the_symb_id,
|
|
|
|
|
const deriv_node_temp_terms_t& tef_terms) const
|
2023-11-30 15:28:57 +01:00
|
|
|
|
noexcept(false);
|
2010-03-04 16:40:07 +01:00
|
|
|
|
//! Helper function to write output arguments of any given external function
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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,
|
|
|
|
|
bool isdynamic) const;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeExternalFunctionArguments(Bytecode::Writer& code_file,
|
2022-07-08 16:00:02 +02:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
const deriv_node_temp_terms_t& tef_terms) const;
|
2018-05-29 17:07:18 +02:00
|
|
|
|
/*! 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) */
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] virtual function<bool(expr_t)> sameTefTermPredicate() const = 0;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void computeSubExprContainingVariable(int symb_id, int lag,
|
|
|
|
|
set<expr_t>& contain_var) const override;
|
|
|
|
|
|
2008-02-03 11:28:36 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
AbstractExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int symb_id_arg,
|
2018-06-04 12:31:07 +02:00
|
|
|
|
vector<expr_t> arguments_arg);
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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,
|
2018-11-30 12:22:13 +01:00
|
|
|
|
bool is_matlab) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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,
|
|
|
|
|
bool isdynamic = true) const override
|
|
|
|
|
= 0;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsExternalFunction() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
void writeJsonExternalFunctionOutput(vector<string>& efout,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms,
|
|
|
|
|
bool isdynamic = true) const override
|
|
|
|
|
= 0;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
|
2022-07-06 16:44:51 +02:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
|
|
|
|
|
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
|
|
|
|
virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t>& alt_args,
|
|
|
|
|
DataTree& alt_datatree) const
|
|
|
|
|
= 0;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t replaceTrendVar() const override;
|
2018-06-04 12:53:26 +02:00
|
|
|
|
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t clone(DataTree& alt_datatree) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t removeTrendLeadLag(const map<int, expr_t>& trend_symbols_map) const override;
|
|
|
|
|
[[nodiscard]] bool isInStaticForm() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2008-02-03 11:28:36 +01:00
|
|
|
|
};
|
|
|
|
|
|
2014-03-13 11:22:00 +01:00
|
|
|
|
class ExternalFunctionNode : public AbstractExternalFunctionNode
|
|
|
|
|
{
|
2018-05-29 17:07:18 +02:00
|
|
|
|
friend class FirstDerivExternalFunctionNode;
|
|
|
|
|
friend class SecondDerivExternalFunctionNode;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2014-03-13 11:22:00 +01:00
|
|
|
|
private:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
|
|
|
|
|
|
2018-05-29 17:07:18 +02:00
|
|
|
|
protected:
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2014-03-13 11:22:00 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 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;
|
|
|
|
|
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;
|
|
|
|
|
void writeJsonExternalFunctionOutput(vector<string>& efout,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms,
|
2019-12-20 16:59:30 +01:00
|
|
|
|
bool isdynamic) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
|
2022-07-06 16:44:51 +02:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2014-03-13 11:22:00 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode
|
2010-02-22 17:33:38 +01:00
|
|
|
|
{
|
2018-11-28 14:32:26 +01:00
|
|
|
|
public:
|
2010-02-22 17:33:38 +01:00
|
|
|
|
const int inputIndex;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
private:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
|
|
|
|
|
|
2018-05-29 17:07:18 +02:00
|
|
|
|
protected:
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2010-02-22 17:33:38 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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, bool isdynamic) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms) const override;
|
|
|
|
|
void writeJsonExternalFunctionOutput(vector<string>& efout,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms,
|
2019-12-20 16:59:30 +01:00
|
|
|
|
bool isdynamic) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
|
2022-07-06 16:44:51 +02:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
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;
|
2010-02-22 17:33:38 +01:00
|
|
|
|
};
|
|
|
|
|
|
2014-03-13 11:22:00 +01:00
|
|
|
|
class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode
|
2010-02-22 17:33:38 +01:00
|
|
|
|
{
|
2018-11-28 14:32:26 +01:00
|
|
|
|
public:
|
2010-02-22 17:33:38 +01:00
|
|
|
|
const int inputIndex1;
|
|
|
|
|
const int inputIndex2;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2018-11-28 14:32:26 +01:00
|
|
|
|
private:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t composeDerivatives(const vector<expr_t>& dargs) override;
|
|
|
|
|
|
2018-05-29 17:07:18 +02:00
|
|
|
|
protected:
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] function<bool(expr_t)> sameTefTermPredicate() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2010-02-22 17:33:38 +01:00
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
SecondDerivExternalFunctionNode(DataTree& datatree_arg, int idx_arg, int top_level_symb_id_arg,
|
|
|
|
|
const vector<expr_t>& arguments_arg, int inputIndex1_arg,
|
2010-02-22 17:33:38 +01:00
|
|
|
|
int inputIndex2_arg);
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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, bool isdynamic) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms) const override;
|
|
|
|
|
void writeJsonExternalFunctionOutput(vector<string>& efout,
|
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
deriv_node_temp_terms_t& tef_terms,
|
2019-12-20 16:59:30 +01:00
|
|
|
|
bool isdynamic) const override;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
|
2022-07-06 16:44:51 +02:00
|
|
|
|
ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
const temporary_terms_t& temporary_terms,
|
|
|
|
|
const temporary_terms_idxs_t& temporary_terms_idxs,
|
|
|
|
|
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;
|
2010-02-22 17:33:38 +01:00
|
|
|
|
};
|
|
|
|
|
|
2021-10-29 12:15:50 +02:00
|
|
|
|
/* 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
|
2016-11-18 16:52:13 +01:00
|
|
|
|
{
|
|
|
|
|
public:
|
2018-11-28 14:32:26 +01:00
|
|
|
|
const string model_name;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
SubModelNode(DataTree& datatree_arg, int idx_arg, string model_name_arg);
|
|
|
|
|
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,
|
2021-10-29 12:55:17 +02:00
|
|
|
|
bool is_matlab) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2021-10-29 12:15:50 +02:00
|
|
|
|
expr_t computeDerivative(int deriv_id) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsExternalFunction() const override;
|
|
|
|
|
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void computeXrefs(EquationInfo& ei) const override;
|
|
|
|
|
expr_t substituteExpectation(subst_table_t& subst_table, vector<BinaryOpNode*>& neweqs,
|
|
|
|
|
bool partial_information_model) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t substituteAdl() const override;
|
|
|
|
|
[[nodiscard]] expr_t substituteModelLocalVariables() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
void findDiffNodes(lag_equivalence_table_t& nodes) const override;
|
|
|
|
|
void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t& nodes) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] optional<int> findTargetVariable(int lhs_symb_id) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-14 14:52:50 +01:00
|
|
|
|
void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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 collectVARLHSVariable(set<expr_t>& result) const override;
|
|
|
|
|
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t replaceVarsInEquation(map<VariableNode*, NumConstNode*>& table) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool isParamTimesEndogExpr() const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t differentiateForwardVars(const vector<string>& subset, subst_table_t& subst_table,
|
|
|
|
|
vector<BinaryOpNode*>& neweqs) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] expr_t decreaseLeadsLagsPredeterminedVariables() const override;
|
|
|
|
|
[[nodiscard]] expr_t replaceTrendVar() const override;
|
2021-10-29 12:55:17 +02:00
|
|
|
|
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[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;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
|
2022-10-18 17:24:51 +02:00
|
|
|
|
protected:
|
2023-03-02 16:08:32 +01:00
|
|
|
|
void prepareForDerivation() override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
|
2022-11-08 12:28:48 +01:00
|
|
|
|
private:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2021-10-29 12:15:50 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class VarExpectationNode : public SubModelNode
|
|
|
|
|
{
|
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
|
|
|
|
|
[[nodiscard]] expr_t
|
|
|
|
|
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
|
|
|
|
|
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
|
|
|
|
|
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
|
|
|
|
|
= "") const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2018-01-30 16:33:16 +01:00
|
|
|
|
};
|
|
|
|
|
|
2021-10-29 12:15:50 +02:00
|
|
|
|
class PacExpectationNode : public SubModelNode
|
2018-01-30 16:33:16 +01:00
|
|
|
|
{
|
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
PacExpectationNode(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;
|
|
|
|
|
expr_t clone(DataTree& alt_datatree) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
|
|
|
|
|
[[nodiscard]] expr_t
|
|
|
|
|
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
|
|
|
|
|
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
|
|
|
|
|
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
|
|
|
|
|
= "") const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2021-10-26 18:06:26 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class PacTargetNonstationaryNode : public SubModelNode
|
|
|
|
|
{
|
|
|
|
|
public:
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
|
|
|
|
expr_t clone(DataTree& alt_datatree) const override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] int maxLagWithDiffsExpanded() const override;
|
|
|
|
|
[[nodiscard]] expr_t
|
|
|
|
|
substituteVarExpectation(const map<string, expr_t>& subst_table) const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
expr_t substitutePacExpectation(const string& name, expr_t subexpr) override;
|
|
|
|
|
expr_t substitutePacTargetNonstationary(const string& name, expr_t subexpr) override;
|
2023-12-01 14:02:38 +01:00
|
|
|
|
[[nodiscard]] bool containsPacExpectation(const string& pac_model_name = "") const override;
|
|
|
|
|
[[nodiscard]] bool containsPacTargetNonstationary(const string& pac_model_name
|
|
|
|
|
= "") const override;
|
2023-11-30 15:28:57 +01:00
|
|
|
|
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;
|
2016-11-18 16:52:13 +01:00
|
|
|
|
};
|
|
|
|
|
|
2008-02-03 11:28:36 +01:00
|
|
|
|
#endif
|