Histval block:

- fail when user tries to initialize a variable at a period which is not in the model, and make the error message explicit
- correctly handle exogenous variables in stochastic mode, which are also substituted with an aux var
- added test files
issue#70
Sébastien Villemot 2010-10-20 14:47:03 +02:00
parent 855fdf8c16
commit 615f2ae322
6 changed files with 64 additions and 24 deletions

View File

@ -596,3 +596,14 @@ DataTree::isSecondDerivExternalFunctionUsed(int symb_id) const
return false; return false;
} }
int
DataTree::minLagForSymbol(int symb_id) const
{
int r = 0;
for (variable_node_map_t::const_iterator it = variable_node_map.begin();
it != variable_node_map.end(); ++it)
if (it->first.first == symb_id && it->first.second < r)
r = it->first.second;
return r;
}

View File

@ -208,6 +208,9 @@ public:
bool isFirstDerivExternalFunctionUsed(int symb_id) const; bool isFirstDerivExternalFunctionUsed(int symb_id) const;
//! Checks if a given second derivative external function is used somewhere in the data tree //! Checks if a given second derivative external function is used somewhere in the data tree
bool isSecondDerivExternalFunctionUsed(int symb_id) const; bool isSecondDerivExternalFunctionUsed(int symb_id) const;
//! Returns the minimum lag (as a negative number) of the given symbol in the whole data tree (and not only in the equations !!)
/*! Returns 0 if the symbol is not used */
int minLagForSymbol(int symb_id) const;
//! Thrown when trying to access an unknown variable by deriv_id //! Thrown when trying to access an unknown variable by deriv_id
class UnknownDerivIDException class UnknownDerivIDException
{ {

View File

@ -193,21 +193,27 @@ HistValStatement::writeOutput(ostream &output, const string &basename) const
const expr_t expression = it->second; const expr_t expression = it->second;
SymbolType type = symbol_table.getType(symb_id); SymbolType type = symbol_table.getType(symb_id);
if (type == eEndogenous && lag < 0)
{ // For a lag greater than 1, lookup for auxiliary variable
const int new_symb_id = symbol_table.searchAuxiliaryVars(symb_id,lag); if ((type == eEndogenous || type == eExogenous) && lag < 0)
if (new_symb_id != -1) {
{ try
symb_id = new_symb_id; {
lag = 0; symb_id = symbol_table.searchAuxiliaryVars(symb_id, lag);
} lag = 0;
else if (symbol_table.AuxVarsSize() > 0) }
{ catch (SymbolTable::SearchFailedException &e)
cerr << "Histval: this variable doesn't exist with such a lag in the model" << endl; {
exit(EXIT_FAILURE); if (type == eEndogenous)
} {
cerr << "HISTVAL: internal error of Dynare, please contact the developers";
} exit(EXIT_FAILURE);
}
// We don't fail for exogenous, because they are not replaced by
// auxiliary variables in deterministic mode.
}
}
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1; int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
if (type == eEndogenous) if (type == eEndogenous)

View File

@ -21,6 +21,7 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <cassert> #include <cassert>
#include <sstream>
#include "ParsingDriver.hh" #include "ParsingDriver.hh"
#include "Statement.hh" #include "Statement.hh"
@ -392,11 +393,18 @@ ParsingDriver::hist_val(string *name, string *lag, expr_t rhs)
if (type != eEndogenous if (type != eEndogenous
&& type != eExogenous && type != eExogenous
&& type != eExogenousDet) && type != eExogenousDet)
error("hist_val: " + *name + " should be an endogenous or exogenous variable"); error("histval: " + *name + " should be an endogenous or exogenous variable");
int ilag = atoi(lag->c_str()); int ilag = atoi(lag->c_str());
pair<int, int> key(symb_id, ilag); pair<int, int> key(symb_id, ilag);
if (mod_file->dynamic_model.minLagForSymbol(symb_id) > ilag - 1)
{
ostringstream s;
s << ilag-1;
error("histval: variable " + *name + " does not appear in the model with the lag " + s.str() + " (see the reference manual for the timing convention in 'histval')");
}
if (hist_values.find(key) != hist_values.end()) if (hist_values.find(key) != hist_values.end())
error("hist_val: (" + *name + ", " + *lag + ") declared twice"); error("hist_val: (" + *name + ", " + *lag + ") declared twice");

View File

@ -368,13 +368,13 @@ SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, const st
} }
int int
SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const throw (SearchFailedException)
{ {
for (int i=0; i < aux_vars.size();++i) for (size_t i = 0; i < aux_vars.size(); i++)
if ((aux_vars[i].get_type() == avEndoLag || aux_vars[i].get_type() == avExoLag) if ((aux_vars[i].get_type() == avEndoLag || aux_vars[i].get_type() == avExoLag)
&& aux_vars[i].get_orig_symb_id() == orig_symb_id && aux_vars[i].get_orig_lead_lag() == orig_lead_lag) && aux_vars[i].get_orig_symb_id() == orig_symb_id && aux_vars[i].get_orig_lead_lag() == orig_lead_lag)
return aux_vars[i].get_symb_id(); return aux_vars[i].get_symb_id();
return -1; throw SearchFailedException(orig_symb_id, orig_lead_lag);
} }
void void

View File

@ -47,8 +47,8 @@ class AuxVarInfo
private: private:
int symb_id; //!< Symbol ID of the auxiliary variable int symb_id; //!< Symbol ID of the auxiliary variable
aux_var_t type; //!< Its type aux_var_t type; //!< Its type
int orig_symb_id; //!< Symbol ID of the endo of the original model represented by this aux var. Not used for avEndoLead int orig_symb_id; //!< Symbol ID of the endo of the original model represented by this aux var. Only used for avEndoLag and avExoLag.
int orig_lead_lag; //!< Lead/lag of the endo of the original model represented by this aux var. Not used for avEndoLead int orig_lead_lag; //!< Lead/lag of the endo of the original model represented by this aux var. Only used for avEndoLag and avExoLag.
string expectation_information_set_name; //!< Stores 'full' or 'varobs' for avExpectationRIS. Not used otherwise. string expectation_information_set_name; //!< Stores 'full' or 'varobs' for avExpectationRIS. Not used otherwise.
public: public:
AuxVarInfo(int symb_id_arg, aux_var_t type_arg, int orig_symb_id, int orig_lead_lag, string expectation_information_set_name_arg); AuxVarInfo(int symb_id_arg, aux_var_t type_arg, int orig_symb_id, int orig_lead_lag, string expectation_information_set_name_arg);
@ -161,6 +161,16 @@ public:
class NotYetFrozenException class NotYetFrozenException
{ {
}; };
//! Thrown when searchAuxiliaryVars() failed
class SearchFailedException
{
public:
int orig_symb_id, orig_lead_lag;
SearchFailedException(int orig_symb_id_arg, int orig_lead_lag_arg) : orig_symb_id(orig_symb_id_arg),
orig_lead_lag(orig_lead_lag_arg)
{
}
};
private: private:
//! Factorized code for adding aux lag variables //! Factorized code for adding aux lag variables
@ -204,11 +214,13 @@ public:
\return the symbol ID of the new symbol \return the symbol ID of the new symbol
*/ */
int addExpectationAuxiliaryVar(int information_set, int index, const string &information_set_name) throw (FrozenException); int addExpectationAuxiliaryVar(int information_set, int index, const string &information_set_name) throw (FrozenException);
//! Searches auxiliary variables by symbol_id and lead_lag //! Searches auxiliary variables which are substitutes for a given symbol_id and lead/lag
/*! /*!
\return the symbol ID of the auxiliary variable and -1 if not found The search is only performed among auxiliary variables of endo/exo lag.
\return the symbol ID of the auxiliary variable
Throws an exception if match not found.
*/ */
int searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const; int searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const throw (SearchFailedException);
//! Returns the number of auxiliary variables //! Returns the number of auxiliary variables
int AuxVarsSize() const {return aux_vars.size();}; int AuxVarsSize() const {return aux_vars.size();};
//! Tests if symbol already exists //! Tests if symbol already exists