Commit 90e8fbda authored by sebastien's avatar sebastien
Browse files

trunk preprocessor: restructuration of the code before adding derivatives w.r....

trunk preprocessor: restructuration of the code before adding derivatives w.r. to parameters (in particular, removed VariableTable, and replaced it by a system of derivation IDs)


git-svn-id: https://www.dynare.org/svn/dynare/trunk@2597 ac1d8469-bf42-47a9-8791-bf33cf982152
parent 51378821
......@@ -25,8 +25,7 @@
DataTree::DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg) :
symbol_table(symbol_table_arg),
num_constants(num_constants_arg),
node_counter(0),
variable_table(symbol_table_arg)
node_counter(0)
{
Zero = AddNumConstant("0");
One = AddNumConstant("1");
......@@ -68,7 +67,7 @@ DataTree::AddVariableInternal(const string &name, int lag)
if (it != variable_node_map.end())
return it->second;
else
return new VariableNode(*this, symb_id, lag);
return new VariableNode(*this, symb_id, lag, computeDerivID(symb_id, lag));
}
NodeID
......@@ -476,3 +475,26 @@ DataTree::isSymbolUsed(int symb_id) const
return false;
}
int
DataTree::computeDerivID(int symb_id, int lag)
{
return -1;
}
int
DataTree::getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException)
{
throw UnknownDerivIDException();
}
int
DataTree::getDerivIDNbr() const
{
return 0;
}
int
DataTree::getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException)
{
throw UnknownDerivIDException();
}
......@@ -30,7 +30,6 @@ using namespace std;
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
#include "VariableTable.hh"
#include "ExprNode.hh"
#define CONSTANTS_PRECISION 16
......@@ -68,6 +67,9 @@ protected:
//! Internal implementation of AddVariable(), without the check on the lag
NodeID AddVariableInternal(const string &name, int lag);
//! Computes a new deriv_id, or returns -1 if the variable is not one w.r. to which to derive
virtual int computeDerivID(int symb_id, int lag);
private:
typedef list<NodeID> node_list_type;
//! The list of nodes
......@@ -83,8 +85,7 @@ private:
public:
DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg);
virtual ~DataTree();
//! The variable table
VariableTable variable_table;
//! Some predefined constants
NodeID Zero, One, Two, MinusOne, NaN, Infinity, MinusInfinity, Pi;
......@@ -174,6 +175,19 @@ public:
void fillEvalContext(eval_context_type &eval_context) const;
//! Checks if a given symbol is used somewhere in the data tree
bool isSymbolUsed(int symb_id) const;
//! Thrown when trying to access an unknown variable by deriv_id
class UnknownDerivIDException
{
};
//! Returns the derivation ID, or throws an exception if the derivation ID does not exist
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
//! Returns the total number of derivation IDs
/*! Valid derivation IDs are between 0 and getDerivIDNbr()-1 */
virtual int getDerivIDNbr() const;
//! Returns the column of the dynamic Jacobian associated to a derivation ID
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
};
inline NodeID
......
This diff is collapsed.
......@@ -29,6 +29,33 @@ using namespace std;
class DynamicModel : public ModelTree
{
private:
typedef map<pair<int, int>, int> deriv_id_table_t;
//! Maps a pair (symbol_id, lag) to a deriv ID
deriv_id_table_t deriv_id_table;
//! Maps a deriv ID to a pair (symbol_id, lag)
vector<pair<int, int> > inv_deriv_id_table;
//! Maps a deriv_id to the column index of the dynamic Jacobian
/*! Contains only endogenous, exogenous and exogenous deterministic */
map<int, int> dyn_jacobian_cols_table;
//! Number of dynamic endogenous variables inside the model block
/*! Set by computeDerivID() */
int var_endo_nbr;
//! Maximum lag and lead over all types of variables (positive values)
/*! Set by computeDerivID() */
int max_lag, max_lead;
//! Maximum lag and lead over endogenous variables (positive values)
/*! Set by computeDerivID() */
int max_endo_lag, max_endo_lead;
//! Maximum lag and lead over exogenous variables (positive values)
/*! Set by computeDerivID() */
int max_exo_lag, max_exo_lead;
//! Maximum lag and lead over deterministic exogenous variables (positive values)
/*! Set by computeDerivID() */
int max_exo_det_lag, max_exo_det_lead;
//! Writes dynamic model file (Matlab version)
void writeDynamicMFile(const string &dynamic_basename) const;
//! Writes dynamic model file (C version)
......@@ -59,6 +86,18 @@ private:
//! Write derivative code of an equation w.r. to a variable
void compileDerivative(ofstream &code_file, int eq, int symb_id, int lag, ExprNodeOutputType output_type, map_idx_type &map_idx) const;
virtual int computeDerivID(int symb_id, int lag);
//! Get the number of columns of dynamic jacobian
int getDynJacobianColsNbr() const;
//! Get the type corresponding to a derivation ID
int getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Get the lag corresponding to a derivation ID
int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Get the symbol ID corresponding to a derivation ID
int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Compute the column indices of the dynamic Jacobian
void computeDynJacobianCols();
public:
DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants);
//! Adds a variable node
......@@ -94,6 +133,9 @@ public:
//! Converts to static model (only the equations)
/*! It assumes that the static model given in argument has just been allocated */
void toStatic(StaticModel &static_model) const;
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
virtual int getDerivIDNbr() const;
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
};
#endif
......@@ -40,21 +40,21 @@ ExprNode::~ExprNode()
}
NodeID
ExprNode::getDerivative(int varID)
ExprNode::getDerivative(int deriv_id)
{
// Return zero if derivative is necessarily null (using symbolic a priori)
set<int>::const_iterator it = non_null_derivatives.find(varID);
set<int>::const_iterator it = non_null_derivatives.find(deriv_id);
if (it == non_null_derivatives.end())
return datatree.Zero;
// If derivative is stored in cache, use the cached value, otherwise compute it (and cache it)
map<int, NodeID>::const_iterator it2 = derivatives.find(varID);
map<int, NodeID>::const_iterator it2 = derivatives.find(deriv_id);
if (it2 != derivatives.end())
return it2->second;
else
{
NodeID d = computeDerivative(varID);
derivatives[varID] = d;
NodeID d = computeDerivative(deriv_id);
derivatives[deriv_id] = d;
return d;
}
}
......@@ -111,7 +111,7 @@ NumConstNode::NumConstNode(DataTree &datatree_arg, int id_arg) :
}
NodeID
NumConstNode::computeDerivative(int varID)
NumConstNode::computeDerivative(int deriv_id)
{
return datatree.Zero;
}
......@@ -175,23 +175,16 @@ NumConstNode::toStatic(DataTree &static_datatree) const
}
VariableNode::VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg) :
VariableNode::VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg, int deriv_id_arg) :
ExprNode(datatree_arg),
symb_id(symb_id_arg),
type(datatree.symbol_table.getType(symb_id_arg)),
lag(lag_arg)
lag(lag_arg),
deriv_id(deriv_id_arg)
{
// Add myself to the variable map
datatree.variable_node_map[make_pair(symb_id, lag)] = this;
// Add myself to the variable table if necessary and initialize var_id
if (type == eEndogenous
|| type == eExogenousDet
|| type == eExogenous)
var_id = datatree.variable_table.addVariable(symb_id, lag);
else
var_id = -1;
// It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
if ((type == eModelLocalVariable || type == eModFileLocalVariable || type == eUnknownFunction) && lag != 0)
{
......@@ -206,7 +199,7 @@ VariableNode::VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg)
case eExogenous:
case eExogenousDet:
// For a variable, the only non-null derivative is with respect to itself
non_null_derivatives.insert(var_id);
non_null_derivatives.insert(deriv_id);
break;
case eParameter:
// All derivatives are null, do nothing
......@@ -225,21 +218,21 @@ VariableNode::VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg)
}
NodeID
VariableNode::computeDerivative(int varID)
VariableNode::computeDerivative(int deriv_id_arg)
{
switch(type)
{
case eEndogenous:
case eExogenous:
case eExogenousDet:
if (varID == var_id)
if (deriv_id == deriv_id_arg)
return datatree.One;
else
return datatree.Zero;
case eParameter:
return datatree.Zero;
case eModelLocalVariable:
return datatree.local_variables_table[symb_id]->getDerivative(varID);
return datatree.local_variables_table[symb_id]->getDerivative(deriv_id_arg);
case eModFileLocalVariable:
cerr << "ModFileLocalVariable is not derivable" << endl;
exit(EXIT_FAILURE);
......@@ -309,7 +302,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
{
case oMatlabDynamicModel:
case oCDynamicModel:
i = datatree.variable_table.getDynJacobianCol(var_id) + OFFSET(output_type);
i = datatree.getDynJacobianCol(deriv_id) + OFFSET(output_type);
output << "y" << LPAR(output_type) << i << RPAR(output_type);
break;
case oMatlabStaticModel:
......@@ -535,9 +528,9 @@ UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const
}
NodeID
UnaryOpNode::computeDerivative(int varID)
UnaryOpNode::computeDerivative(int deriv_id)
{
NodeID darg = arg->getDerivative(varID);
NodeID darg = arg->getDerivative(deriv_id);
NodeID t11, t12, t13;
......@@ -995,10 +988,10 @@ BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const NodeID arg1_arg,
}
NodeID
BinaryOpNode::computeDerivative(int varID)
BinaryOpNode::computeDerivative(int deriv_id)
{
NodeID darg1 = arg1->getDerivative(varID);
NodeID darg2 = arg2->getDerivative(varID);
NodeID darg1 = arg1->getDerivative(deriv_id);
NodeID darg2 = arg2->getDerivative(deriv_id);
NodeID t11, t12, t13, t14, t15;
......@@ -1524,11 +1517,11 @@ TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, const NodeID arg1_arg,
}
NodeID
TrinaryOpNode::computeDerivative(int varID)
TrinaryOpNode::computeDerivative(int deriv_id)
{
NodeID darg1 = arg1->getDerivative(varID);
NodeID darg2 = arg2->getDerivative(varID);
NodeID darg3 = arg3->getDerivative(varID);
NodeID darg1 = arg1->getDerivative(deriv_id);
NodeID darg2 = arg2->getDerivative(deriv_id);
NodeID darg3 = arg3->getDerivative(deriv_id);
NodeID t11, t12, t13, t14, t15;
......@@ -1812,7 +1805,7 @@ UnknownFunctionNode::UnknownFunctionNode(DataTree &datatree_arg,
}
NodeID
UnknownFunctionNode::computeDerivative(int varID)
UnknownFunctionNode::computeDerivative(int deriv_id)
{
cerr << "UnknownFunctionNode::computeDerivative: operation impossible!" << endl;
exit(EXIT_FAILURE);
......
......@@ -28,7 +28,6 @@ using namespace std;
#include <iostream>
#include <fstream>
#include "SymbolTable.hh"
#include "CodeInterpreter.hh"
......@@ -43,6 +42,7 @@ struct ExprNodeLess;
//! Type for set of temporary terms
/*! They are ordered by index number thanks to ExprNodeLess */
typedef set<NodeID, ExprNodeLess> temporary_terms_type;
typedef map<int,int> map_idx_type;
typedef set<int> temporary_terms_inuse_type;
......@@ -95,9 +95,9 @@ class ExprNode
friend class TrinaryOpNode;
private:
//! Computes derivative w.r. to variable varID (but doesn't store it in derivatives map)
//! 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 NodeID computeDerivative(int varID) = 0;
virtual NodeID computeDerivative(int deriv_id) = 0;
protected:
//! Reference to the enclosing DataTree
......@@ -106,7 +106,7 @@ protected:
//! Index number
int idx;
//! Set of variable IDs with respect to which the derivative is potentially non-null
//! 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)
......@@ -120,10 +120,10 @@ public:
ExprNode(DataTree &datatree_arg);
virtual ~ExprNode();
//! Returns derivative w.r. to variable varID
//! Returns derivative w.r. to derivation ID
/*! Uses a symbolic a priori to pre-detect null derivatives, and caches the result for other derivatives (to avoid computing it several times)
For an equal node, returns the derivative of lhs minus rhs */
NodeID getDerivative(int varID);
NodeID getDerivative(int deriv_id);
//! Returns precedence of node
/*! Equals 100 for constants, variables, unary ops, and temporary terms */
......@@ -183,7 +183,7 @@ class NumConstNode : public ExprNode
private:
//! Id from numerical constants table
const int id;
virtual NodeID computeDerivative(int varID);
virtual NodeID computeDerivative(int deriv_id);
public:
NumConstNode(DataTree &datatree_arg, int id_arg);
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const;
......@@ -203,11 +203,12 @@ private:
const int symb_id;
const SymbolType type;
const int lag;
//! Id from the variable table (-1 if not a endogenous/exogenous/recursive)
int var_id;
virtual NodeID computeDerivative(int varID);
//! Derivation ID
/*! It is comprised between 0 and datatree.getDerivIDNbr()-1, or can be -1 if we don't derive w.r. to this variable */
const int deriv_id;
virtual NodeID computeDerivative(int deriv_id_arg);
public:
VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg);
VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg, int deriv_id_arg);
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms = temporary_terms_type()) const;
virtual void collectEndogenous(set<pair<int, int> > &result) const;
virtual void collectExogenous(set<pair<int, int> > &result) const;
......@@ -230,7 +231,7 @@ class UnaryOpNode : public ExprNode
private:
const NodeID arg;
const UnaryOpcode op_code;
virtual NodeID computeDerivative(int varID);
virtual NodeID computeDerivative(int deriv_id);
virtual int cost(const temporary_terms_type &temporary_terms, bool is_matlab) const;
public:
......@@ -263,7 +264,7 @@ class BinaryOpNode : public ExprNode
private:
const NodeID arg1, arg2;
const BinaryOpcode op_code;
virtual NodeID computeDerivative(int varID);
virtual NodeID computeDerivative(int deriv_id);
virtual int cost(const temporary_terms_type &temporary_terms, bool is_matlab) const;
public:
BinaryOpNode(DataTree &datatree_arg, const NodeID arg1_arg,
......@@ -300,7 +301,7 @@ class TrinaryOpNode : public ExprNode
private:
const NodeID arg1, arg2, arg3;
const TrinaryOpcode op_code;
virtual NodeID computeDerivative(int varID);
virtual NodeID computeDerivative(int deriv_id);
virtual int cost(const temporary_terms_type &temporary_terms, bool is_matlab) const;
public:
TrinaryOpNode(DataTree &datatree_arg, const NodeID arg1_arg,
......@@ -328,10 +329,9 @@ public:
class UnknownFunctionNode : public ExprNode
{
private:
//! Symbol ID (no need to store type: it is necessary eUnknownFunction)
const int symb_id;
const vector<NodeID> arguments;
virtual NodeID computeDerivative(int varID);
virtual NodeID computeDerivative(int deriv_id);
public:
UnknownFunctionNode(DataTree &datatree_arg, int symb_id_arg,
const vector<NodeID> &arguments_arg);
......
......@@ -46,7 +46,6 @@ MAIN_OBJS = \
SigmaeInitialization.o \
SymbolTable.o \
SymbolList.o \
VariableTable.o \
ParsingDriver.o \
DataTree.o \
ModFile.o \
......@@ -73,7 +72,7 @@ MACRO_OBJS = \
all: $(DYNARE_M)
$(DYNARE_M): $(MAIN_OBJS) $(MACRO_OBJS)
$(CXX) $(CXXFLAGS) -o $(DYNARE_M) $(MAIN_OBJS) $(MACRO_OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(DYNARE_M) $(MAIN_OBJS) $(MACRO_OBJS)
cp $(DYNARE_M) ../matlab/
......
......@@ -30,7 +30,6 @@ using namespace std;
#include "NumericalInitialization.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "VariableTable.hh"
#include "Statement.hh"
//! The abstract representation of a "mod" file
......
......@@ -40,7 +40,7 @@ ModelTree::writeDerivative(ostream &output, int eq, int symb_id, int lag,
ExprNodeOutputType output_type,
const temporary_terms_type &temporary_terms) const
{
first_derivatives_type::const_iterator it = first_derivatives.find(make_pair(eq, variable_table.getID(symb_id, lag)));
first_derivatives_type::const_iterator it = first_derivatives.find(make_pair(eq, getDerivID(symb_id, lag)));
if (it != first_derivatives.end())
(it->second)->writeOutput(output, output_type, temporary_terms);
else
......@@ -51,7 +51,7 @@ void
ModelTree::derive(int order)
{
for (int var = 0; var < variable_table.size(); var++)
for (int var = 0; var < getDerivIDNbr(); var++)
for (int eq = 0; eq < (int) equations.size(); eq++)
{
NodeID d1 = equations[eq]->getDerivative(var);
......
......@@ -49,7 +49,7 @@ protected:
//! First order derivatives
/*! First index is equation number, second is variable w.r. to which is computed the derivative.
Only non-null derivatives are stored in the map.
Variable indexes used are those of the variable_table, before sorting.
Variable indices are those of the getDerivID() method.
*/
first_derivatives_type first_derivatives;
......@@ -58,7 +58,7 @@ protected:
/*! First index is equation number, second and third are variables w.r. to which is computed the derivative.
Only non-null derivatives are stored in the map.
Contains only second order derivatives where var1 >= var2 (for obvious symmetry reasons).
Variable indexes used are those of the variable_table, before sorting.
Variable indices are those of the getDerivID() method.
*/
second_derivatives_type second_derivatives;
......@@ -67,7 +67,7 @@ protected:
/*! First index is equation number, second, third and fourth are variables w.r. to which is computed the derivative.
Only non-null derivatives are stored in the map.
Contains only third order derivatives where var1 >= var2 >= var3 (for obvious symmetry reasons).
Variable indexes used are those of the variable_table, before sorting.
Variable indices are those of the getDerivID() method.
*/
third_derivatives_type third_derivatives;
......
......@@ -142,16 +142,13 @@ StaticModel::writeStaticModel(ostream &StaticOutput) const
int var = it->first.second;
NodeID d1 = it->second;
if (variable_table.getType(var) == eEndogenous)
{
ostringstream g1;
g1 << " g1";
matrixHelper(g1, eq, symbol_table.getTypeSpecificID(variable_table.getSymbolID(var)), output_type);
ostringstream g1;
g1 << " g1";
matrixHelper(g1, eq, var, output_type);
jacobian_output << g1.str() << "=" << g1.str() << "+";
d1->writeOutput(jacobian_output, output_type, temporary_terms);
jacobian_output << ";" << endl;
}
jacobian_output << g1.str() << "=" << g1.str() << "+";
d1->writeOutput(jacobian_output, output_type, temporary_terms);
jacobian_output << ";" << endl;
}
// Write Hessian w.r. to endogenous only
......@@ -164,31 +161,23 @@ StaticModel::writeStaticModel(ostream &StaticOutput) const
int var2 = it->first.second.second;
NodeID d2 = it->second;
// Keep only derivatives w.r. to endogenous variables
if (variable_table.getType(var1) == eEndogenous
&& variable_table.getType(var2) == eEndogenous)
int col_nb = var1*symbol_table.endo_nbr()+var2;
int col_nb_sym = var2*symbol_table.endo_nbr()+var1;
hessian_output << " g2";
matrixHelper(hessian_output, eq, col_nb, output_type);
hessian_output << " = ";
d2->writeOutput(hessian_output, output_type, temporary_terms);
hessian_output << ";" << endl;
// Treating symetric elements
if (var1 != var2)
{
int id1 = symbol_table.getTypeSpecificID(variable_table.getSymbolID(var1));
int id2 = symbol_table.getTypeSpecificID(variable_table.getSymbolID(var2));
int col_nb = id1*symbol_table.endo_nbr()+id2;
int col_nb_sym = id2*symbol_table.endo_nbr()+id1;
hessian_output << " g2";
matrixHelper(hessian_output, eq, col_nb, output_type);
hessian_output << " = ";
d2->writeOutput(hessian_output, output_type, temporary_terms);
hessian_output << ";" << endl;
// Treating symetric elements
if (var1 != var2)
{
lsymetric << " g2";
matrixHelper(lsymetric, eq, col_nb_sym, output_type);
lsymetric << " = " << "g2";
matrixHelper(lsymetric, eq, col_nb, output_type);
lsymetric << ";" << endl;
}
lsymetric << " g2";
matrixHelper(lsymetric, eq, col_nb_sym, output_type);
lsymetric << " = " << "g2";
matrixHelper(lsymetric, eq, col_nb, output_type);
lsymetric << ";" << endl;
}
}
......@@ -289,3 +278,27 @@ StaticModel::computingPass(bool no_tmp_terms)
if (!no_tmp_terms)
computeTemporaryTerms(order);
}
int
StaticModel::computeDerivID(int symb_id, int lag)
{
if (symbol_table.getType(symb_id) == eEndogenous)
return symbol_table.getTypeSpecificID(symb_id);
else
return -1;
}
int
StaticModel::getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException)
{
if (symbol_table.getType(symb_id) == eEndogenous)
return symbol_table.getTypeSpecificID(symb_id);
else
throw UnknownDerivIDException();
}
int
StaticModel::getDerivIDNbr() const
{
return symbol_table.endo_nbr();
}
......@@ -36,6 +36,8 @@ private:
//! Writes static model file (C version)
void writeStaticCFile(const string &static_basename) const;
virtual int computeDerivID(int symb_id, int lag);
public:
StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants);
//! Whether static Hessian (w.r. to endogenous only) should be written
......@@ -46,6 +48,9 @@ public:
void computingPass(bool no_tmp_terms);
//! Writes static model file
void writeStaticFile(const string &basename) const;
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
virtual int getDerivIDNbr() const;
};
#endif
/*
* Copyright (C) 2003-2009 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,