v4 preprocessor:
* fixed bug related to column numbering of exogenous variables in dynamic jacobian * gave more explicit names to some methods in VariableTable, and other cosmetic changes git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@1990 ac1d8469-bf42-47a9-8791-bf33cf982152issue#70
parent
ead500e4b0
commit
43c5fd18e6
|
@ -276,7 +276,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|
||||||
{
|
{
|
||||||
case oMatlabDynamicModel:
|
case oMatlabDynamicModel:
|
||||||
case oCDynamicModel:
|
case oCDynamicModel:
|
||||||
i = datatree.variable_table.getSortID(var_id) + OFFSET(output_type);
|
i = datatree.variable_table.getDynJacobianCol(var_id) + OFFSET(output_type);
|
||||||
output << "y" << LPAR(output_type) << i << RPAR(output_type);
|
output << "y" << LPAR(output_type) << i << RPAR(output_type);
|
||||||
break;
|
break;
|
||||||
case oMatlabStaticModel:
|
case oMatlabStaticModel:
|
||||||
|
|
36
ModelTree.cc
36
ModelTree.cc
|
@ -1694,14 +1694,10 @@ ModelTree::writeDynamicCFile(const string &dynamic_basename) const
|
||||||
<< " g1 = NULL;" << endl
|
<< " g1 = NULL;" << endl
|
||||||
<< " if (nlhs >= 2)" << endl
|
<< " if (nlhs >= 2)" << endl
|
||||||
<< " {" << endl
|
<< " {" << endl
|
||||||
<< " /* Set the output pointer to the output matrix g1. */" << endl;
|
<< " /* Set the output pointer to the output matrix g1. */" << endl
|
||||||
|
|
||||||
if (computeJacobianExo)
|
<< " plhs[1] = mxCreateDoubleMatrix(" << equations.size() << ", " << variable_table.getDynJacobianColsNbr(computeJacobianExo) << ", mxREAL);" << endl
|
||||||
mDynamicModelFile << " plhs[1] = mxCreateDoubleMatrix(" << equations.size() << ", " << variable_table.get_dyn_var_nbr() << ", mxREAL);" << endl;
|
<< " /* Create a C pointer to a copy of the output matrix g1. */" << endl
|
||||||
else if (computeJacobian)
|
|
||||||
mDynamicModelFile << " plhs[1] = mxCreateDoubleMatrix(" << equations.size() << ", " << variable_table.var_endo_nbr << ", mxREAL);" << endl;
|
|
||||||
|
|
||||||
mDynamicModelFile << " /* Create a C pointer to a copy of the output matrix g1. */" << endl
|
|
||||||
<< " g1 = mxGetPr(plhs[1]);" << endl
|
<< " g1 = mxGetPr(plhs[1]);" << endl
|
||||||
<< " }" << endl
|
<< " }" << endl
|
||||||
<< endl
|
<< endl
|
||||||
|
@ -1709,7 +1705,7 @@ ModelTree::writeDynamicCFile(const string &dynamic_basename) const
|
||||||
<< " if (nlhs >= 3)" << endl
|
<< " if (nlhs >= 3)" << endl
|
||||||
<< " {" << endl
|
<< " {" << endl
|
||||||
<< " /* Set the output pointer to the output matrix g2. */" << endl
|
<< " /* Set the output pointer to the output matrix g2. */" << endl
|
||||||
<< " plhs[2] = mxCreateDoubleMatrix(" << equations.size() << ", " << variable_table.get_dyn_var_nbr()*variable_table.get_dyn_var_nbr() << ", mxREAL);" << endl
|
<< " plhs[2] = mxCreateDoubleMatrix(" << equations.size() << ", " << variable_table.getDynJacobianColsNbr(computeJacobianExo)*variable_table.getDynJacobianColsNbr(computeJacobianExo) << ", mxREAL);" << endl
|
||||||
<< " /* Create a C pointer to a copy of the output matrix g1. */" << endl
|
<< " /* Create a C pointer to a copy of the output matrix g1. */" << endl
|
||||||
<< " g2 = mxGetPr(plhs[2]);" << endl
|
<< " g2 = mxGetPr(plhs[2]);" << endl
|
||||||
<< " }" << endl
|
<< " }" << endl
|
||||||
|
@ -3295,11 +3291,7 @@ ModelTree::writeDynamicModel(ostream &DynamicOutput) const
|
||||||
writeModelEquations(model_output, output_type);
|
writeModelEquations(model_output, output_type);
|
||||||
|
|
||||||
int nrows = equations.size();
|
int nrows = equations.size();
|
||||||
int nvars;
|
int nvars = variable_table.getDynJacobianColsNbr(computeJacobianExo);
|
||||||
if (computeJacobianExo)
|
|
||||||
nvars = variable_table.get_dyn_var_nbr();
|
|
||||||
else
|
|
||||||
nvars = variable_table.var_endo_nbr;
|
|
||||||
int nvars_sq = nvars * nvars;
|
int nvars_sq = nvars * nvars;
|
||||||
|
|
||||||
// Writing Jacobian
|
// Writing Jacobian
|
||||||
|
@ -3315,7 +3307,7 @@ ModelTree::writeDynamicModel(ostream &DynamicOutput) const
|
||||||
{
|
{
|
||||||
ostringstream g1;
|
ostringstream g1;
|
||||||
g1 << " g1";
|
g1 << " g1";
|
||||||
matrixHelper(g1, eq, variable_table.getSortID(var), output_type);
|
matrixHelper(g1, eq, variable_table.getDynJacobianCol(var), output_type);
|
||||||
|
|
||||||
jacobian_output << g1.str() << "=" << g1.str() << "+";
|
jacobian_output << g1.str() << "=" << g1.str() << "+";
|
||||||
d1->writeOutput(jacobian_output, output_type, temporary_terms);
|
d1->writeOutput(jacobian_output, output_type, temporary_terms);
|
||||||
|
@ -3333,8 +3325,8 @@ ModelTree::writeDynamicModel(ostream &DynamicOutput) const
|
||||||
int var2 = it->first.second.second;
|
int var2 = it->first.second.second;
|
||||||
NodeID d2 = it->second;
|
NodeID d2 = it->second;
|
||||||
|
|
||||||
int id1 = variable_table.getSortID(var1);
|
int id1 = variable_table.getDynJacobianCol(var1);
|
||||||
int id2 = variable_table.getSortID(var2);
|
int id2 = variable_table.getDynJacobianCol(var2);
|
||||||
|
|
||||||
int col_nb = id1*nvars+id2;
|
int col_nb = id1*nvars+id2;
|
||||||
int col_nb_sym = id2*nvars+id1;
|
int col_nb_sym = id2*nvars+id1;
|
||||||
|
@ -3367,9 +3359,9 @@ ModelTree::writeDynamicModel(ostream &DynamicOutput) const
|
||||||
int var3 = it->first.second.second.second;
|
int var3 = it->first.second.second.second;
|
||||||
NodeID d3 = it->second;
|
NodeID d3 = it->second;
|
||||||
|
|
||||||
int id1 = variable_table.getSortID(var1);
|
int id1 = variable_table.getDynJacobianCol(var1);
|
||||||
int id2 = variable_table.getSortID(var2);
|
int id2 = variable_table.getDynJacobianCol(var2);
|
||||||
int id3 = variable_table.getSortID(var3);
|
int id3 = variable_table.getDynJacobianCol(var3);
|
||||||
|
|
||||||
// Reference column number for the g3 matrix
|
// Reference column number for the g3 matrix
|
||||||
int ref_col = id1 * nvars_sq + id2 * nvars + id3;
|
int ref_col = id1 * nvars_sq + id2 * nvars + id3;
|
||||||
|
@ -3507,7 +3499,7 @@ ModelTree::writeOutput(ostream &output) const
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int varID = variable_table.getID(eEndogenous, endoID, lag);
|
int varID = variable_table.getID(eEndogenous, endoID, lag);
|
||||||
output << " " << variable_table.getSortID(varID) + 1;
|
output << " " << variable_table.getDynJacobianCol(varID) + 1;
|
||||||
}
|
}
|
||||||
catch(VariableTable::UnknownVariableKeyException &e)
|
catch(VariableTable::UnknownVariableKeyException &e)
|
||||||
{
|
{
|
||||||
|
@ -3689,8 +3681,8 @@ ModelTree::computingPass(const eval_context_type &eval_context)
|
||||||
{
|
{
|
||||||
cout << equations.size() << " equation(s) found" << endl;
|
cout << equations.size() << " equation(s) found" << endl;
|
||||||
|
|
||||||
// Sorting variable table
|
// Computes dynamic jacobian columns
|
||||||
variable_table.sort();
|
variable_table.computeDynJacobianCols();
|
||||||
|
|
||||||
// Determine derivation order
|
// Determine derivation order
|
||||||
int order = 1;
|
int order = 1;
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "VariableTable.hh"
|
#include "VariableTable.hh"
|
||||||
|
|
||||||
VariableTable::VariableTable(const SymbolTable &symbol_table_arg) :
|
VariableTable::VariableTable(const SymbolTable &symbol_table_arg) :
|
||||||
|
@ -31,10 +33,10 @@ VariableTable::VariableTable(const SymbolTable &symbol_table_arg) :
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
VariableTable::addVariable(Type type, int symb_id, int lag) throw (AlreadySortedException)
|
VariableTable::addVariable(Type type, int symb_id, int lag) throw (DynJacobianColsAlreadyComputedException)
|
||||||
{
|
{
|
||||||
if (sorted_ids_table.size() != 0)
|
if (dyn_jacobian_cols_table.size() != 0)
|
||||||
throw AlreadySortedException();
|
throw DynJacobianColsAlreadyComputedException();
|
||||||
|
|
||||||
var_key_type key = make_pair(make_pair(type, lag), symb_id);
|
var_key_type key = make_pair(make_pair(type, lag), symb_id);
|
||||||
|
|
||||||
|
@ -48,13 +50,6 @@ VariableTable::addVariable(Type type, int symb_id, int lag) throw (AlreadySorted
|
||||||
variable_table[key] = var_id;
|
variable_table[key] = var_id;
|
||||||
inv_variable_table[var_id] = key;
|
inv_variable_table[var_id] = key;
|
||||||
|
|
||||||
if (type == eEndogenous)
|
|
||||||
var_endo_nbr++;
|
|
||||||
if (type == eExogenous)
|
|
||||||
var_exo_nbr++;
|
|
||||||
if (type == eExogenousDet)
|
|
||||||
var_exo_det_nbr++;
|
|
||||||
|
|
||||||
// Setting maximum and minimum lags
|
// Setting maximum and minimum lags
|
||||||
if (max_lead < lag)
|
if (max_lead < lag)
|
||||||
max_lead = lag;
|
max_lead = lag;
|
||||||
|
@ -64,18 +59,21 @@ VariableTable::addVariable(Type type, int symb_id, int lag) throw (AlreadySorted
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case eEndogenous:
|
case eEndogenous:
|
||||||
|
var_endo_nbr++;
|
||||||
if (max_endo_lead < lag)
|
if (max_endo_lead < lag)
|
||||||
max_endo_lead = lag;
|
max_endo_lead = lag;
|
||||||
else if (-max_endo_lag > lag)
|
else if (-max_endo_lag > lag)
|
||||||
max_endo_lag = -lag;
|
max_endo_lag = -lag;
|
||||||
break;
|
break;
|
||||||
case eExogenous:
|
case eExogenous:
|
||||||
|
var_exo_nbr++;
|
||||||
if (max_exo_lead < lag)
|
if (max_exo_lead < lag)
|
||||||
max_exo_lead = lag;
|
max_exo_lead = lag;
|
||||||
else if (-max_exo_lag > lag)
|
else if (-max_exo_lag > lag)
|
||||||
max_exo_lag = -lag;
|
max_exo_lag = -lag;
|
||||||
break;
|
break;
|
||||||
case eExogenousDet:
|
case eExogenousDet:
|
||||||
|
var_exo_det_nbr++;
|
||||||
if (max_exo_det_lead < lag)
|
if (max_exo_det_lead < lag)
|
||||||
max_exo_det_lead = lag;
|
max_exo_det_lead = lag;
|
||||||
else if (-max_exo_det_lag > lag)
|
else if (-max_exo_det_lag > lag)
|
||||||
|
@ -88,21 +86,39 @@ VariableTable::addVariable(Type type, int symb_id, int lag) throw (AlreadySorted
|
||||||
max_recur_lag = -lag;
|
max_recur_lag = -lag;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
cerr << "VariableTable::addVariable(): forbidden variable type" << endl;
|
||||||
|
exit(-1);
|
||||||
}
|
}
|
||||||
return var_id;
|
return var_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VariableTable::sort() throw (AlreadySortedException)
|
VariableTable::computeDynJacobianCols() throw (DynJacobianColsAlreadyComputedException)
|
||||||
{
|
{
|
||||||
if (sorted_ids_table.size() != 0)
|
if (dyn_jacobian_cols_table.size() != 0)
|
||||||
throw AlreadySortedException();
|
throw DynJacobianColsAlreadyComputedException();
|
||||||
|
|
||||||
|
dyn_jacobian_cols_table.resize(size());
|
||||||
|
|
||||||
|
variable_table_type::const_iterator it = variable_table.begin();
|
||||||
|
|
||||||
|
// Assign the first columns to endogenous, using the lexicographic order over (lag, symbol_id) implemented in variable_table map
|
||||||
int sorted_id = 0;
|
int sorted_id = 0;
|
||||||
sorted_ids_table.resize(size());
|
while(it->first.first.first == eEndogenous)
|
||||||
|
{
|
||||||
|
dyn_jacobian_cols_table[it->second] = sorted_id++;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
for(variable_table_type::const_iterator it = variable_table.begin();
|
// Assign subsequent columns to exogenous and then exogenous deterministic, using an offset + symbol_id
|
||||||
it != variable_table.end(); it++)
|
while(it->first.first.first == eExogenous)
|
||||||
sorted_ids_table[it->second] = sorted_id++;
|
{
|
||||||
|
dyn_jacobian_cols_table[it->second] = var_endo_nbr + it->first.second;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
while(it->first.first.first == eExogenousDet)
|
||||||
|
{
|
||||||
|
dyn_jacobian_cols_table[it->second] = var_endo_nbr + symbol_table.exo_nbr + it->first.second;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ const int EVALUATE_FOREWARD_R=8;
|
||||||
const int EVALUATE_BACKWARD_R=9;
|
const int EVALUATE_BACKWARD_R=9;
|
||||||
|
|
||||||
//! Enumeration of possible symbol types
|
//! Enumeration of possible symbol types
|
||||||
/*! Warning: do not to change existing values: the order matters for VariableTable (at least ensure that eEndogenous is the first one), and the values matter for homotopy_setup command */
|
/*! Warning: do not to change existing values: the order matters for VariableTable (at least for endogenous and exogenous types), and the values matter for homotopy_setup command */
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
eEndogenous = 0, //!< Endogenous
|
eEndogenous = 0, //!< Endogenous
|
||||||
|
|
|
@ -35,7 +35,7 @@ private:
|
||||||
//! A reference to the symbol table
|
//! A reference to the symbol table
|
||||||
const SymbolTable &symbol_table;
|
const SymbolTable &symbol_table;
|
||||||
//! A variable is a tuple (type, lag, symbol_id)
|
//! A variable is a tuple (type, lag, symbol_id)
|
||||||
/*! Warning: don't change the order of elements in the tuple, since this determines the lexicographic ordering in sort() */
|
/*! Warning: don't change the order of elements in the tuple, since this determines the lexicographic ordering in computeDynJacobianCols() */
|
||||||
typedef pair<pair<Type, int>, int> var_key_type;
|
typedef pair<pair<Type, int>, int> var_key_type;
|
||||||
|
|
||||||
typedef map<var_key_type, int> variable_table_type;
|
typedef map<var_key_type, int> variable_table_type;
|
||||||
|
@ -45,16 +45,18 @@ private:
|
||||||
typedef map<int, var_key_type> inv_variable_table_type;
|
typedef map<int, var_key_type> inv_variable_table_type;
|
||||||
//! Maps a variable ID to a tuple (type, lag, symbol_id)
|
//! Maps a variable ID to a tuple (type, lag, symbol_id)
|
||||||
inv_variable_table_type inv_variable_table;
|
inv_variable_table_type inv_variable_table;
|
||||||
//! Contains the sorted IDs (indexed by variable IDs)
|
|
||||||
vector<int> sorted_ids_table;
|
|
||||||
public:
|
|
||||||
VariableTable(const SymbolTable &symbol_table_arg);
|
|
||||||
//! Number of dynamic endogenous variables inside the model block
|
//! Number of dynamic endogenous variables inside the model block
|
||||||
int var_endo_nbr;
|
int var_endo_nbr;
|
||||||
//! Number of dynamic exogenous variables inside the model block
|
//! Number of dynamic exogenous variables inside the model block
|
||||||
int var_exo_nbr;
|
int var_exo_nbr;
|
||||||
//! Number of dynamic deterministic exogenous variables inside the model block
|
//! Number of dynamic deterministic exogenous variables inside the model block
|
||||||
int var_exo_det_nbr;
|
int var_exo_det_nbr;
|
||||||
|
|
||||||
|
//! Contains the columns indices for the dynamic jacobian (indexed by variable IDs)
|
||||||
|
vector<int> dyn_jacobian_cols_table;
|
||||||
|
public:
|
||||||
|
VariableTable(const SymbolTable &symbol_table_arg);
|
||||||
//! Maximum lag over all types of variables (positive value)
|
//! Maximum lag over all types of variables (positive value)
|
||||||
int max_lag;
|
int max_lag;
|
||||||
//! Maximum lead over all types of variables
|
//! Maximum lead over all types of variables
|
||||||
|
@ -91,17 +93,17 @@ public:
|
||||||
int id;
|
int id;
|
||||||
UnknownVariableIDException(int id_arg) : id(id_arg) {}
|
UnknownVariableIDException(int id_arg) : id(id_arg) {}
|
||||||
};
|
};
|
||||||
//! Thrown when getSortID() called before sort()
|
//! Thrown when getDynJacobianCol() called before computeDynJacobianCols()
|
||||||
class NotYetSortedException
|
class DynJacobianColsNotYetComputedException
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
//! Thrown when sort() or addVariable() called after sort()
|
//! Thrown when computeDynJacobianCols() or addVariable() called after computeDynJacobianCols()
|
||||||
class AlreadySortedException
|
class DynJacobianColsAlreadyComputedException
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
//! Adds a variable in the table, and returns its (newly allocated) variable ID
|
//! Adds a variable in the table, and returns its (newly allocated) variable ID
|
||||||
/*! Also works if the variable already exists */
|
/*! Also works if the variable already exists */
|
||||||
int addVariable(Type type, int symb_id, int lag) throw (AlreadySortedException);
|
int addVariable(Type type, int symb_id, int lag) throw (DynJacobianColsAlreadyComputedException);
|
||||||
//! Return variable ID
|
//! Return variable ID
|
||||||
inline int getID(Type type, int symb_id, int lag) const throw (UnknownVariableKeyException);
|
inline int getID(Type type, int symb_id, int lag) const throw (UnknownVariableKeyException);
|
||||||
//! Return lag of variable
|
//! Return lag of variable
|
||||||
|
@ -112,26 +114,24 @@ public:
|
||||||
inline Type getType(int var_id) const throw (UnknownVariableIDException);
|
inline Type getType(int var_id) const throw (UnknownVariableIDException);
|
||||||
//! Get number of variables
|
//! Get number of variables
|
||||||
inline int size() const;
|
inline int size() const;
|
||||||
//! Get variable ID of sorted variable table
|
//! Get column index in dynamic jacobian
|
||||||
/*! In practice, only used for endogenous variables */
|
inline int getDynJacobianCol(int var_id) const throw (DynJacobianColsNotYetComputedException, UnknownVariableIDException);
|
||||||
inline int getSortID(int var_id) const throw (NotYetSortedException, UnknownVariableIDException);
|
//! Computes column indices in dynamic jacobian
|
||||||
//! Sorts variable table
|
void computeDynJacobianCols() throw (DynJacobianColsAlreadyComputedException);
|
||||||
/*! The order used is a lexicographic order over the tuple (type, lag, symbol_id) */
|
//! Get the number of columns of dynamic jacobian (depending on whether we compute derivatives w.r. to exogenous)
|
||||||
void sort() throw (AlreadySortedException);
|
inline int getDynJacobianColsNbr(bool computeJacobianExo) const;
|
||||||
//! Get the number of dynamic variables
|
|
||||||
inline int get_dyn_var_nbr() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
VariableTable::getSortID(int var_id) const throw (NotYetSortedException, UnknownVariableIDException)
|
VariableTable::getDynJacobianCol(int var_id) const throw (DynJacobianColsNotYetComputedException, UnknownVariableIDException)
|
||||||
{
|
{
|
||||||
if (sorted_ids_table.size() == 0)
|
if (dyn_jacobian_cols_table.size() == 0)
|
||||||
throw NotYetSortedException();
|
throw DynJacobianColsNotYetComputedException();
|
||||||
|
|
||||||
if (var_id < 0 || var_id >= size())
|
if (var_id < 0 || var_id >= size())
|
||||||
throw UnknownVariableIDException(var_id);
|
throw UnknownVariableIDException(var_id);
|
||||||
|
|
||||||
return sorted_ids_table[var_id];
|
return dyn_jacobian_cols_table[var_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
|
@ -181,9 +181,12 @@ VariableTable::size() const
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
VariableTable::get_dyn_var_nbr() const
|
VariableTable::getDynJacobianColsNbr(bool computeJacobianExo) const
|
||||||
{
|
{
|
||||||
return var_endo_nbr + symbol_table.exo_nbr + symbol_table.exo_det_nbr;
|
if (computeJacobianExo)
|
||||||
|
return var_endo_nbr + symbol_table.exo_nbr + symbol_table.exo_det_nbr;
|
||||||
|
else
|
||||||
|
return var_endo_nbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue