move preprocessor to submodule

time-shift
Houtan Bastani 2018-02-16 16:09:46 +01:00
parent 04ce089164
commit fdf9a8a453
61 changed files with 22 additions and 49812 deletions

3
.gitmodules vendored
View File

@ -30,3 +30,6 @@
[submodule "contrib/jsonlab"]
path = contrib/jsonlab
url = https://github.com/fangq/jsonlab.git
[submodule "preprocessor"]
path = preprocessor
url = https://github.com/DynareTeam/dynare-preprocessor.git

View File

@ -35,6 +35,17 @@ EXTRA_DIST = \
scripts \
.dir-locals.el
all-local: preprocessor/src/dynare_m
{ \
if [ -z "`file preprocessor/src/dynare_m | grep x86.64`" ]; then \
ARCH="32"; \
else \
ARCH="64"; \
fi; \
mkdir -p $(abs_srcdir)/matlab/preprocessor$$ARCH; \
cp preprocessor/src/dynare_m $(abs_srcdir)/matlab/preprocessor$$ARCH; \
}
dist-hook:
rm -rf `find $(distdir)/matlab $(distdir)/examples -name *~`
rm -rf $(distdir)/matlab/preprocessor* $(distdir)/matlab/dynare_version.m
@ -51,13 +62,13 @@ install-exec-local:
find $(DESTDIR)$(pkglibdir) -name LICENSE.md -delete
rm -rf $(DESTDIR)$(pkglibdir)/matlab/preprocessor*
{ \
if [ -z "`file preprocessor/dynare_m | grep x86.64`" ]; then \
if [ -z "`file preprocessor/src/dynare_m | grep x86.64`" ]; then \
ARCH="32"; \
else \
ARCH="64"; \
fi; \
mkdir -p $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH; \
cp preprocessor/dynare_m $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH; \
cp preprocessor/src/dynare_m $(DESTDIR)$(pkglibdir)/matlab/preprocessor$$ARCH; \
}
uninstall-local:

View File

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
dnl Copyright (C) 2009-2017 Dynare Team
dnl Copyright (C) 2009-2018 Dynare Team
dnl
dnl This file is part of Dynare.
dnl
@ -19,9 +19,11 @@ dnl along with Dynare. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ([2.62])
AC_INIT([dynare], [4.6-unstable])
AC_CONFIG_SRCDIR([preprocessor/DynareMain.cc])
AC_CONFIG_SRCDIR([preprocessor/src/DynareMain.cc])
AM_INIT_AUTOMAKE([1.11 -Wall -Wno-portability foreign no-dist-gzip dist-xz tar-pax])
AC_CONFIG_SUBDIRS([preprocessor])
AC_PROG_CC
AC_PROG_CXX
@ -61,17 +63,6 @@ AX_PROG_LN_S
AC_PROG_MKDIR_P
AM_PROG_LEX
# Hack to get lex include dir, ticket #575
AC_PATH_PROG([LEXPATH], [$LEX])
AC_SUBST([LEXINC], [`eval "echo $LEXPATH | sed 's|\(.*\)$LEX$|\1../include|'"`])
AC_CHECK_PROG([YACC], [bison], [bison])
if test "x$YACC" = "x"; then
unset YACC # AM_MISSING_PROG needs an unset variable: an empty variable won't do
AM_MISSING_PROG([YACC], [bison])
fi
# We need 1.36 because of unordered_{set,hash} used by Dynare++
AX_BOOST_BASE([1.36], [], [AC_MSG_ERROR([Can't find Boost >= 1.36])])
@ -121,9 +112,6 @@ if test "x$PDFLATEX" != "x" -a "x$BIBTEX" != "x"; then
fi
AM_CONDITIONAL([HAVE_BEAMER], [test "x$ax_latex_have_beamer" = "xyes"])
AC_CHECK_PROG([DOXYGEN], [doxygen], [doxygen])
AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$DOXYGEN" != "x"])
AC_CHECK_PROG([CTANGLE], [ctangle], [ctangle])
AM_CONDITIONAL([HAVE_CTANGLE], [test "x$CTANGLE" != "x"])
if test "x$CTANGLE" = "x"; then
@ -166,8 +154,6 @@ AX_PTHREAD
AC_CONFIG_FILES([Makefile
VERSION
preprocessor/macro/Makefile
preprocessor/Makefile
doc/Makefile
doc/preprocessor/Makefile
doc/macroprocessor/Makefile
@ -220,8 +206,6 @@ AM_CONDITIONAL([ENABLE_ORG_EXPORT], [test "x$enable_org_export" != "x"])
# Construct final output message
BUILD_PREPROCESSOR="yes"
if test "x$ax_blas_ok" = "xyes" -a "x$ax_lapack_ok" = "xyes" -a "x$has_matio" = "xyes"; then
if test x"$ax_pthread_ok" = "xyes"; then
BUILD_DYNAREPLUSPLUS="yes"
@ -250,12 +234,6 @@ else
BUILD_OTHER_PDF_DOC="no (missing pdflatex)"
fi
if test "x$DOXYGEN" != "x"; then
BUILD_DYNARE_PREPROC_DOC="yes"
else
BUILD_DYNARE_PREPROC_DOC="no (missing doxygen)"
fi
if test "x$enable_org_export" != "x"; then
BUILD_DYNARE_INTERNAL_DOC="yes"
else
@ -293,7 +271,6 @@ AC_MSG_NOTICE([
Dynare is now configured for building the following components...
Binaries (with "make"):
Dynare preprocessor: $BUILD_PREPROCESSOR
Dynare++: $BUILD_DYNAREPLUSPLUS
PDF documentation (with "make pdf"):
@ -304,7 +281,6 @@ PDF documentation (with "make pdf"):
HTML documentation (with "make html"):
Dynare reference manual: $BUILD_DYNARE_HTML_MANUAL
Dynare preprocessor developer doc: $BUILD_DYNARE_PREPROC_DOC
Dynare internal doc: $BUILD_DYNARE_INTERNAL_DOC
Info documentation (with "make info"): $BUILD_DYNARE_INFO

View File

@ -1,6 +1,6 @@
mex_PROGRAMS = bytecode
bytecode_CPPFLAGS = -Wno-maybe-uninitialized $(AM_CPPFLAGS) -I$(top_srcdir)/../../sources -I$(top_srcdir)/../../sources/bytecode -I$(top_srcdir)/../../../preprocessor
bytecode_CPPFLAGS = -Wno-maybe-uninitialized $(AM_CPPFLAGS) -I$(top_srcdir)/../../sources -I$(top_srcdir)/../../sources/bytecode -I$(top_srcdir)/../../../preprocessor/src
TOPDIR = $(top_srcdir)/../../sources/bytecode

1
preprocessor Submodule

@ -0,0 +1 @@
Subproject commit 662d3f71cecf0d8a32e94564071bf9cfc27eae4d

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,783 +0,0 @@
/*
* Copyright (C) 2010-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include "ConfigFile.hh"
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
using namespace std;
Hook::Hook(string &global_init_file_arg)
{
if (global_init_file_arg.empty())
{
cerr << "ERROR: The Hook must have a Global Initialization File argument." << endl;
exit(EXIT_FAILURE);
}
hooks["global_init_file"] = global_init_file_arg;
}
Path::Path(vector<string> &includepath_arg)
{
if (includepath_arg.empty())
{
cerr << "ERROR: The Path must have an Include argument." << endl;
exit(EXIT_FAILURE);
}
paths["include"] = includepath_arg;
}
SlaveNode::SlaveNode(string &computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string &userName_arg,
string &password_arg, string &remoteDrive_arg, string &remoteDirectory_arg,
string &dynarePath_arg, string &matlabOctavePath_arg, bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
string &operatingSystem_arg) :
computerName(computerName_arg), port(port_arg), minCpuNbr(minCpuNbr_arg), maxCpuNbr(maxCpuNbr_arg), userName(userName_arg),
password(password_arg), remoteDrive(remoteDrive_arg), remoteDirectory(remoteDirectory_arg), dynarePath(dynarePath_arg),
matlabOctavePath(matlabOctavePath_arg), singleCompThread(singleCompThread_arg), numberOfThreadsPerJob(numberOfThreadsPerJob_arg),
operatingSystem(operatingSystem_arg)
{
if (computerName.empty())
{
cerr << "ERROR: The node must have a ComputerName." << endl;
exit(EXIT_FAILURE);
}
if (!operatingSystem.empty())
if (operatingSystem.compare("windows") != 0 && operatingSystem.compare("unix") != 0)
{
cerr << "ERROR: The OperatingSystem must be either 'unix' or 'windows' (Case Sensitive)." << endl;
exit(EXIT_FAILURE);
}
}
Cluster::Cluster(member_nodes_t member_nodes_arg) :
member_nodes(member_nodes_arg)
{
if (member_nodes.empty())
{
cerr << "ERROR: The cluster must have at least one member node." << endl;
exit(EXIT_FAILURE);
}
}
ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg,
bool parallel_slave_open_mode_arg, const string &cluster_name_arg) :
parallel(parallel_arg), parallel_test(parallel_test_arg),
parallel_slave_open_mode(parallel_slave_open_mode_arg), cluster_name(cluster_name_arg)
{
}
ConfigFile::~ConfigFile()
{
}
void
ConfigFile::getConfigFileInfo(const string &config_file)
{
using namespace boost;
ifstream *configFile;
if (config_file.empty())
{
string defaultConfigFile("");
// Test OS and try to open default file
#if defined(_WIN32) || defined(__CYGWIN32__)
if (getenv("APPDATA") == NULL)
{
if (parallel || parallel_test)
cerr << "ERROR: ";
else
cerr << "WARNING: ";
cerr << "APPDATA environment variable not found." << endl;
if (parallel || parallel_test)
exit(EXIT_FAILURE);
}
else
{
defaultConfigFile += getenv("APPDATA");
defaultConfigFile += "\\dynare.ini";
}
#else
if (getenv("HOME") == NULL)
{
if (parallel || parallel_test)
cerr << "ERROR: ";
else
cerr << "WARNING: ";
cerr << "HOME environment variable not found." << endl;
if (parallel || parallel_test)
exit(EXIT_FAILURE);
}
else
{
defaultConfigFile += getenv("HOME");
defaultConfigFile += "/.dynare";
}
#endif
configFile = new ifstream(defaultConfigFile.c_str(), fstream::in);
if (!configFile->is_open())
if (parallel || parallel_test)
{
cerr << "ERROR: Could not open the default config file (" << defaultConfigFile << ")" << endl;
exit(EXIT_FAILURE);
}
else
return;
}
else
{
configFile = new ifstream(config_file.c_str(), fstream::in);
if (!configFile->is_open())
{
cerr << "ERROR: Couldn't open file " << config_file << endl;;
exit(EXIT_FAILURE);
}
}
string name, computerName, port, userName, password, remoteDrive,
remoteDirectory, dynarePath, matlabOctavePath, operatingSystem,
global_init_file;
vector<string> includepath;
int minCpuNbr = 0, maxCpuNbr = 0;
int numberOfThreadsPerJob = 1;
bool singleCompThread = false;
member_nodes_t member_nodes;
bool inHooks = false;
bool inNode = false;
bool inCluster = false;
bool inPaths = false;
while (configFile->good())
{
string line;
getline(*configFile, line);
trim(line);
if (line.empty() || !line.compare(0, 1, "#"))
continue;
if (!line.compare("[node]")
|| !line.compare("[cluster]")
|| !line.compare("[hooks]")
|| !line.compare("[paths]"))
{
if (!global_init_file.empty())
// we were just in [hooks]
addHooksConfFileElement(global_init_file);
else if (!includepath.empty())
// we were just in [paths]
addPathsConfFileElement(includepath);
else
// we were just in [node] or [cluster]
addParallelConfFileElement(inNode, inCluster, member_nodes, name,
computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory,
dynarePath, matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem);
//! Reset communication vars / option defaults
if (!line.compare("[hooks]"))
{
inHooks = true;
inNode = false;
inCluster = false;
inPaths = false;
}
else if (!line.compare("[node]"))
{
inHooks = false;
inNode = true;
inCluster = false;
inPaths = false;
}
else if (!line.compare("[paths]"))
{
inHooks = false;
inNode = false;
inCluster = false;
inPaths = true;
}
else
{
inHooks = false;
inNode = false;
inCluster = true;
inPaths = false;
}
name = userName = computerName = port = password = remoteDrive
= remoteDirectory = dynarePath = matlabOctavePath
= operatingSystem = global_init_file = "";
includepath.clear();
minCpuNbr = maxCpuNbr = 0;
numberOfThreadsPerJob = 1;
singleCompThread = false;
member_nodes.clear();
}
else
{
vector<string> tokenizedLine;
split(tokenizedLine, line, is_any_of("="));
if (tokenizedLine.size() != 2)
{
cerr << "ERROR (in config file): Options should be formatted as 'option = value'." << endl;
exit(EXIT_FAILURE);
}
trim(tokenizedLine.front());
trim(tokenizedLine.back());
if (inHooks)
if (!tokenizedLine.front().compare("GlobalInitFile"))
if (global_init_file.empty())
global_init_file = tokenizedLine.back();
else
{
cerr << "ERROR: May not have more than one GlobalInitFile option in [hooks] block." << endl;
exit(EXIT_FAILURE);
}
else
{
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [hooks] block." << endl;
exit(EXIT_FAILURE);
}
else if (inPaths)
if (!tokenizedLine.front().compare("Include"))
if (includepath.empty())
{
vector<string> tokenizedPath;
split(tokenizedPath, tokenizedLine.back(), is_any_of(":"), token_compress_on);
for (vector<string>::iterator it = tokenizedPath.begin();
it != tokenizedPath.end(); it++)
if (!it->empty())
{
trim(*it);
includepath.push_back(*it);
}
}
else
{
cerr << "ERROR: May not have more than one Include option in [paths] block." << endl;
exit(EXIT_FAILURE);
}
else
{
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [paths] block." << endl;
exit(EXIT_FAILURE);
}
else
if (!tokenizedLine.front().compare("Name"))
name = tokenizedLine.back();
else if (!tokenizedLine.front().compare("CPUnbr"))
{
vector<string> tokenizedCpuNbr;
split(tokenizedCpuNbr, tokenizedLine.back(), is_any_of(":"));
try
{
if (tokenizedCpuNbr.size() == 1)
{
minCpuNbr = 1;
maxCpuNbr = lexical_cast< int >(tokenizedCpuNbr.front());
}
else if (tokenizedCpuNbr.size() == 2
&& tokenizedCpuNbr[0].at(0) == '['
&& tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size()-1) == ']')
{
tokenizedCpuNbr[0].erase(0, 1);
tokenizedCpuNbr[1].erase(tokenizedCpuNbr[1].size()-1, 1);
minCpuNbr = lexical_cast< int >(tokenizedCpuNbr[0]);
maxCpuNbr = lexical_cast< int >(tokenizedCpuNbr[1]);
}
}
catch (const bad_lexical_cast &)
{
cerr << "ERROR: Could not convert value to integer for CPUnbr." << endl;
exit(EXIT_FAILURE);
}
if (minCpuNbr <= 0 || maxCpuNbr <= 0)
{
cerr << "ERROR: Syntax for the CPUnbr option is as follows:" << endl
<< " 1) CPUnbr = <int>" << endl
<< " or 2) CPUnbr = [<int>:<int>]" << endl
<< " where <int> is an Integer > 0." << endl;
exit(EXIT_FAILURE);
}
minCpuNbr--;
maxCpuNbr--;
if (minCpuNbr > maxCpuNbr)
{
int tmp = maxCpuNbr;
maxCpuNbr = minCpuNbr;
minCpuNbr = tmp;
}
}
else if (!tokenizedLine.front().compare("Port"))
port = tokenizedLine.back();
else if (!tokenizedLine.front().compare("ComputerName"))
computerName = tokenizedLine.back();
else if (!tokenizedLine.front().compare("UserName"))
userName = tokenizedLine.back();
else if (!tokenizedLine.front().compare("Password"))
password = tokenizedLine.back();
else if (!tokenizedLine.front().compare("RemoteDrive"))
remoteDrive = tokenizedLine.back();
else if (!tokenizedLine.front().compare("RemoteDirectory"))
remoteDirectory = tokenizedLine.back();
else if (!tokenizedLine.front().compare("DynarePath"))
dynarePath = tokenizedLine.back();
else if (!tokenizedLine.front().compare("MatlabOctavePath"))
matlabOctavePath = tokenizedLine.back();
else if (!tokenizedLine.front().compare("NumberOfThreadsPerJob"))
numberOfThreadsPerJob = atoi(tokenizedLine.back().c_str());
else if (!tokenizedLine.front().compare("SingleCompThread"))
if (tokenizedLine.back().compare("true") == 0)
singleCompThread = true;
else if (tokenizedLine.back().compare("false") == 0)
singleCompThread = false;
else
{
cerr << "ERROR (in config file): The value passed to SingleCompThread may only be 'true' or 'false'." << endl;
exit(EXIT_FAILURE);
}
else if (!tokenizedLine.front().compare("OperatingSystem"))
operatingSystem = tokenizedLine.back();
else if (!tokenizedLine.front().compare("Members"))
{
char_separator<char> sep(" ,;", "()", drop_empty_tokens);
tokenizer<char_separator<char> > tokens(tokenizedLine.back(), sep);
bool begin_weight = false;
string node_name;
for (tokenizer<char_separator<char> >::iterator it = tokens.begin();
it != tokens.end(); it++)
{
string token(*it);
if (token.compare("(") == 0)
{
begin_weight = true;
continue;
}
else if (token.compare(")") == 0)
{
node_name.clear();
begin_weight = false;
continue;
}
if (!begin_weight)
{
if (!node_name.empty())
if (member_nodes.find(node_name) != member_nodes.end())
{
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl;
exit(EXIT_FAILURE);
}
else
member_nodes[node_name] = 1.0;
node_name = token;
}
else
try
{
double weight = lexical_cast<double>(token.c_str());
if (weight <= 0)
{
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl;
exit(EXIT_FAILURE);
}
member_nodes[node_name] = weight;
}
catch (bad_lexical_cast &)
{
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl;
exit(EXIT_FAILURE);
}
}
if (!node_name.empty())
if (member_nodes.find(node_name) == member_nodes.end())
member_nodes[node_name] = 1.0;
else
{
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl;
exit(EXIT_FAILURE);
}
}
else
{
cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid." << endl;
exit(EXIT_FAILURE);
}
}
}
if (!global_init_file.empty())
addHooksConfFileElement(global_init_file);
else if (!includepath.empty())
addPathsConfFileElement(includepath);
else
addParallelConfFileElement(inNode, inCluster, member_nodes, name,
computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory,
dynarePath, matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem);
configFile->close();
delete configFile;
}
void
ConfigFile::addHooksConfFileElement(string &global_init_file)
{
if (global_init_file.empty())
{
cerr << "ERROR: The global initialization file must be passed to the GlobalInitFile option." << endl;
exit(EXIT_FAILURE);
}
else
hooks.push_back(new Hook(global_init_file));
}
void
ConfigFile::addPathsConfFileElement(vector<string> &includepath)
{
if (includepath.empty())
{
cerr << "ERROR: The path to be included must be passed to the Include option." << endl;
exit(EXIT_FAILURE);
}
else
paths.push_back(new Path(includepath));
}
void
ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, member_nodes_t member_nodes,
string &name, string &computerName, string port, int minCpuNbr, int maxCpuNbr, string &userName,
string &password, string &remoteDrive, string &remoteDirectory,
string &dynarePath, string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob,
string &operatingSystem)
{
//! ADD NODE
if (inNode)
if (!member_nodes.empty())
{
cerr << "Invalid option passed to [node]." << endl;
exit(EXIT_FAILURE);
}
else
if (name.empty() || slave_nodes.find(name) != slave_nodes.end())
{
cerr << "ERROR: Every node must be assigned a unique name." << endl;
exit(EXIT_FAILURE);
}
else
slave_nodes[name] = new SlaveNode(computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory, dynarePath,
matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem);
//! ADD CLUSTER
else if (inCluster)
if (minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty()
|| !password.empty() || !remoteDrive.empty() || !remoteDirectory.empty()
|| !dynarePath.empty() || !matlabOctavePath.empty() || !operatingSystem.empty())
{
cerr << "Invalid option passed to [cluster]." << endl;
exit(EXIT_FAILURE);
}
else
if (name.empty() || clusters.find(name) != clusters.end())
{
cerr << "ERROR: The cluster must be assigned a unique name." << endl;
exit(EXIT_FAILURE);
}
else
{
if (clusters.empty())
firstClusterName = name;
clusters[name] = new Cluster(member_nodes);
}
}
void
ConfigFile::checkPass(WarningConsolidation &warnings) const
{
bool global_init_file_declared = false;
for (vector<Hook *>::const_iterator it = hooks.begin(); it != hooks.end(); it++)
{
const map <string, string> hookmap = (*it)->get_hooks();
for (map <string, string>::const_iterator mapit = hookmap.begin(); mapit != hookmap.end(); mapit++)
if (mapit->first.compare("global_init_file") == 0)
if (global_init_file_declared == true)
{
cerr << "ERROR: Only one global initialization file may be provided." << endl;
exit(EXIT_FAILURE);
}
else
global_init_file_declared = true;
}
if (!parallel && !parallel_test)
return;
//! Check Slave Nodes
if (slave_nodes.empty())
{
cerr << "ERROR: At least one node must be defined in the config file." << endl;
exit(EXIT_FAILURE);
}
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
it != slave_nodes.end(); it++)
{
#if !defined(_WIN32) && !defined(__CYGWIN32__)
//For Linux/Mac, check that cpuNbr starts at 0
if (it->second->minCpuNbr != 0)
warnings << "WARNING: On Unix-based operating systems, you cannot specify the CPU that is "
<< "used in parallel processing. This will be adjusted for you such that the "
<< "same number of CPUs are used." << endl;
#endif
if (!it->second->port.empty())
try
{
boost::lexical_cast< int >(it->second->port);
}
catch (const boost::bad_lexical_cast &)
{
cerr << "ERROR (node " << it->first << "): the port must be an integer." << endl;
exit(EXIT_FAILURE);
}
if (!it->second->computerName.compare("localhost")) // We are working locally
{
if (!it->second->remoteDrive.empty())
{
cerr << "ERROR (node " << it->first << "): the RemoteDrive option may not be passed for a local node." << endl;
exit(EXIT_FAILURE);
}
if (!it->second->remoteDirectory.empty())
{
cerr << "ERROR (node " << it->first << "): the RemoteDirectory option may not be passed for a local node." << endl;
exit(EXIT_FAILURE);
}
}
else
{
if (it->second->userName.empty())
{
cerr << "ERROR (node " << it->first << "): the UserName option must be passed for every remote node." << endl;
exit(EXIT_FAILURE);
}
if (it->second->operatingSystem.compare("windows") == 0)
{
if (it->second->password.empty())
{
cerr << "ERROR (node " << it->first << "): the Password option must be passed under Windows for every remote node." << endl;
exit(EXIT_FAILURE);
}
if (it->second->remoteDrive.empty())
{
cerr << "ERROR (node " << it->first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl;
exit(EXIT_FAILURE);
}
}
#if defined(_WIN32) || defined(__CYGWIN32__)
if (it->second->operatingSystem.empty())
{
if (it->second->password.empty())
{
cerr << "ERROR (node " << it->first << "): the Password option must be passed under Windows for every remote node." << endl;
exit(EXIT_FAILURE);
}
if (it->second->remoteDrive.empty())
{
cerr << "ERROR (node " << it->first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl;
exit(EXIT_FAILURE);
}
}
#endif
if (it->second->remoteDirectory.empty())
{
cerr << "ERROR (node " << it->first << "): the RemoteDirectory must be specified for every remote node." << endl;
exit(EXIT_FAILURE);
}
}
}
//! Check Clusters
if (clusters.empty())
{
cerr << "ERROR: At least one cluster must be defined in the config file." << endl;
exit(EXIT_FAILURE);
}
if (!cluster_name.empty() && clusters.find(cluster_name) == clusters.end())
{
cerr << "ERROR: Cluster Name " << cluster_name << " was not found in the config file." << endl;
exit(EXIT_FAILURE);
}
for (map<string, Cluster *>::const_iterator it = clusters.begin();
it != clusters.end(); it++)
for (member_nodes_t::const_iterator itmn = it->second->member_nodes.begin();
itmn != it->second->member_nodes.end(); itmn++)
if (slave_nodes.find(itmn->first) == slave_nodes.end())
{
cerr << "Error: node " << itmn->first << " specified in cluster " << it->first << " was not found" << endl;
exit(EXIT_FAILURE);
}
}
void
ConfigFile::transformPass()
{
if (!parallel && !parallel_test)
return;
#if !defined(_WIN32) && !defined(__CYGWIN32__)
//For Linux/Mac, check that cpuNbr starts at 0
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
it != slave_nodes.end(); it++)
if (it->second->minCpuNbr != 0)
{
it->second->maxCpuNbr = it->second->maxCpuNbr - it->second->minCpuNbr;
it->second->minCpuNbr = 0;
}
#endif
map<string, Cluster *>::const_iterator cluster_it;
if (cluster_name.empty())
cluster_it = clusters.find(firstClusterName);
else
cluster_it = clusters.find(cluster_name);
double weight_denominator = 0.0;
for (member_nodes_t::const_iterator it = cluster_it->second->member_nodes.begin();
it != cluster_it->second->member_nodes.end(); it++)
weight_denominator += it->second;
for (member_nodes_t::iterator it = cluster_it->second->member_nodes.begin();
it != cluster_it->second->member_nodes.end(); it++)
it->second /= weight_denominator;
}
vector<string>
ConfigFile::getIncludePaths() const
{
vector<string> include_paths;
for (vector<Path *>::const_iterator it = paths.begin(); it != paths.end(); it++)
{
map <string, vector<string> > pathmap = (*it)->get_paths();
for (map <string, vector<string> >::const_iterator mapit = pathmap.begin(); mapit != pathmap.end(); mapit++)
for (vector<string>::const_iterator vecit = mapit->second.begin(); vecit != mapit->second.end(); vecit++)
include_paths.push_back(*vecit);
}
return include_paths;
}
void
ConfigFile::writeHooks(ostream &output) const
{
for (vector<Hook *>::const_iterator it = hooks.begin(); it != hooks.end(); it++)
{
map <string, string> hookmap = (*it)->get_hooks();
for (map <string, string>::const_iterator mapit = hookmap.begin(); mapit != hookmap.end(); mapit++)
output << "options_." << mapit->first << " = '" << mapit->second << "';" << endl;
}
}
void
ConfigFile::writeCluster(ostream &output) const
{
if (!parallel && !parallel_test)
return;
map<string, Cluster *>::const_iterator cluster_it;
if (cluster_name.empty())
cluster_it = clusters.find(firstClusterName);
else
cluster_it = clusters.find(cluster_name);
int i = 1;
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
it != slave_nodes.end(); it++)
{
bool slave_node_in_member_nodes = false;
for (member_nodes_t::const_iterator itmn = cluster_it->second->member_nodes.begin();
itmn != cluster_it->second->member_nodes.end(); itmn++)
if (!it->first.compare(itmn->first))
slave_node_in_member_nodes = true;
if (!slave_node_in_member_nodes)
continue;
output << "options_.parallel";
if (i > 1)
output << "(" << i << ")";
i++;
output << " = struct('Local', ";
if (it->second->computerName.compare("localhost"))
output << "0, ";
else
output << "1, ";
output << "'ComputerName', '" << it->second->computerName << "', "
<< "'Port', '" << it->second->port << "', "
<< "'CPUnbr', [" << it->second->minCpuNbr << ":" << it->second->maxCpuNbr << "], "
<< "'UserName', '" << it->second->userName << "', "
<< "'Password', '" << it->second->password << "', "
<< "'RemoteDrive', '" << it->second->remoteDrive << "', "
<< "'RemoteDirectory', '" << it->second->remoteDirectory << "', "
<< "'DynarePath', '" << it->second->dynarePath << "', "
<< "'MatlabOctavePath', '" << it->second->matlabOctavePath << "', "
<< "'OperatingSystem', '" << it->second->operatingSystem << "', "
<< "'NodeWeight', '" << (cluster_it->second->member_nodes.find(it->first))->second << "', "
<< "'NumberOfThreadsPerJob', " << it->second->numberOfThreadsPerJob << ", ";
if (it->second->singleCompThread)
output << "'SingleCompThread', 'true');" << endl;
else
output << "'SingleCompThread', 'false');" << endl;
}
if (parallel_slave_open_mode)
output << "options_.parallel_info.leaveSlaveOpen = 1;" << endl;
output << "InitializeComputationalEnvironment();" << endl;
if (parallel_test)
output << "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);" << endl
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' num2str(ErrorCode)]);" << endl
<< "diary off;" << endl
<< "return;" << endl;
}
void
ConfigFile::writeEndParallel(ostream &output) const
{
if ((!parallel && !parallel_test) || !parallel_slave_open_mode)
return;
output << "if options_.parallel_info.leaveSlaveOpen == 1" << endl
<< " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl
<< "end" << endl;
}

View File

@ -1,147 +0,0 @@
/*
* Copyright (C) 2010-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CONFIG_FILE_HH
#define _CONFIG_FILE_HH
#include <map>
#include <vector>
#include "WarningConsolidation.hh"
using namespace std;
typedef map<string, double> member_nodes_t;
class Hook
{
public:
Hook(string &global_init_file_arg);
~Hook();
private:
map<string, string> hooks;
public:
inline map<string, string>
get_hooks()
{
return hooks;
};
};
class Path
{
public:
Path(vector<string> &includepath_arg);
~Path();
private:
map<string, vector<string> > paths;
public:
inline map<string, vector<string> >
get_paths()
{
return paths;
};
};
class SlaveNode
{
friend class ConfigFile;
public:
SlaveNode(string &computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string &userName_arg,
string &password_arg, string &remoteDrive_arg, string &remoteDirectory_arg,
string &dynarePath_arg, string &matlabOctavePath_arg, bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
string &operatingSystem_arg);
~SlaveNode();
protected:
const string computerName;
const string port;
int minCpuNbr;
int maxCpuNbr;
const string userName;
const string password;
const string remoteDrive;
const string remoteDirectory;
const string dynarePath;
const string matlabOctavePath;
const bool singleCompThread;
const int numberOfThreadsPerJob;
const string operatingSystem;
};
class Cluster
{
friend class ConfigFile;
public:
Cluster(member_nodes_t member_nodes_arg);
~Cluster();
protected:
member_nodes_t member_nodes;
};
//! The abstract representation of a "config" file
class ConfigFile
{
public:
ConfigFile(bool parallel_arg, bool parallel_test_arg, bool parallel_slave_open_mode_arg, const string &cluster_name);
~ConfigFile();
private:
const bool parallel;
const bool parallel_test;
const bool parallel_slave_open_mode;
const string cluster_name;
string firstClusterName;
//! Hooks
vector<Hook *> hooks;
//! Paths
vector<Path *> paths;
//! Cluster Table
map<string, Cluster *> clusters;
//! Node Map
map<string, SlaveNode *> slave_nodes;
//! Add Hooks
void addHooksConfFileElement(string &global_init_file);
//! Add Paths
void addPathsConfFileElement(vector<string> &includepath);
//! Add a SlaveNode or a Cluster object
void addParallelConfFileElement(bool inNode, bool inCluster, member_nodes_t member_nodes, string &name,
string &computerName, string port, int minCpuNbr, int maxCpuNbr, string &userName,
string &password, string &remoteDrive, string &remoteDirectory,
string &dynarePath, string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob,
string &operatingSystem);
public:
//! Parse config file
void getConfigFileInfo(const string &parallel_config_file);
//! Check Pass
void checkPass(WarningConsolidation &warnings) const;
//! Check Pass
void transformPass();
//! Get Path Info
vector<string> getIncludePaths() const;
//! Write any hooks
void writeHooks(ostream &output) const;
//! Create options_.parallel structure, write options
void writeCluster(ostream &output) const;
//! Close slave nodes if needed
void writeEndParallel(ostream &output) const;
};
#endif // ! CONFIG_FILE_HH

View File

@ -1,755 +0,0 @@
/*
* Copyright (C) 2003-2016 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <iostream>
#include "DataTree.hh"
DataTree::DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg) :
symbol_table(symbol_table_arg),
num_constants(num_constants_arg),
external_functions_table(external_functions_table_arg),
node_counter(0)
{
Zero = AddNonNegativeConstant("0");
One = AddNonNegativeConstant("1");
Two = AddNonNegativeConstant("2");
MinusOne = AddUMinus(One);
NaN = AddNonNegativeConstant("NaN");
Infinity = AddNonNegativeConstant("Inf");
MinusInfinity = AddUMinus(Infinity);
Pi = AddNonNegativeConstant("3.141592653589793");
}
DataTree::~DataTree()
{
for (node_list_t::iterator it = node_list.begin(); it != node_list.end(); it++)
delete *it;
}
expr_t
DataTree::AddNonNegativeConstant(const string &value)
{
int id = num_constants.AddNonNegativeConstant(value);
num_const_node_map_t::iterator it = num_const_node_map.find(id);
if (it != num_const_node_map.end())
return it->second;
else
return new NumConstNode(*this, id);
}
VariableNode *
DataTree::AddVariableInternal(int symb_id, int lag)
{
variable_node_map_t::iterator it = variable_node_map.find(make_pair(symb_id, lag));
if (it != variable_node_map.end())
return it->second;
else
return new VariableNode(*this, symb_id, lag);
}
bool
DataTree::ParamUsedWithLeadLagInternal() const
{
for (variable_node_map_t::const_iterator it = variable_node_map.begin();
it != variable_node_map.end(); it++)
if (symbol_table.getType(it->first.first) == eParameter && it->first.second != 0)
return true;
return false;
}
VariableNode *
DataTree::AddVariable(int symb_id, int lag)
{
assert(lag == 0);
return AddVariableInternal(symb_id, lag);
}
expr_t
DataTree::AddPlus(expr_t iArg1, expr_t iArg2)
{
if (iArg1 != Zero && iArg2 != Zero)
{
// Simplify x+(-y) in x-y
UnaryOpNode *uarg2 = dynamic_cast<UnaryOpNode *>(iArg2);
if (uarg2 != NULL && uarg2->get_op_code() == oUminus)
return AddMinus(iArg1, uarg2->get_arg());
// To treat commutativity of "+"
// Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx)
{
expr_t tmp = iArg1;
iArg1 = iArg2;
iArg2 = tmp;
}
return AddBinaryOp(iArg1, oPlus, iArg2);
}
else if (iArg1 != Zero)
return iArg1;
else if (iArg2 != Zero)
return iArg2;
else
return Zero;
}
expr_t
DataTree::AddMinus(expr_t iArg1, expr_t iArg2)
{
if (iArg2 == Zero)
return iArg1;
if (iArg1 == Zero)
return AddUMinus(iArg2);
if (iArg1 == iArg2)
return Zero;
return AddBinaryOp(iArg1, oMinus, iArg2);
}
expr_t
DataTree::AddUMinus(expr_t iArg1)
{
if (iArg1 != Zero)
{
// Simplify -(-x) in x
UnaryOpNode *uarg = dynamic_cast<UnaryOpNode *>(iArg1);
if (uarg != NULL && uarg->get_op_code() == oUminus)
return uarg->get_arg();
return AddUnaryOp(oUminus, iArg1);
}
else
return Zero;
}
expr_t
DataTree::AddTimes(expr_t iArg1, expr_t iArg2)
{
if (iArg1 == MinusOne)
return AddUMinus(iArg2);
else if (iArg2 == MinusOne)
return AddUMinus(iArg1);
else if (iArg1 != Zero && iArg1 != One && iArg2 != Zero && iArg2 != One)
{
// To treat commutativity of "*"
// Nodes iArg1 and iArg2 are sorted by index
if (iArg1->idx > iArg2->idx)
{
expr_t tmp = iArg1;
iArg1 = iArg2;
iArg2 = tmp;
}
return AddBinaryOp(iArg1, oTimes, iArg2);
}
else if (iArg1 != Zero && iArg1 != One && iArg2 == One)
return iArg1;
else if (iArg2 != Zero && iArg2 != One && iArg1 == One)
return iArg2;
else if (iArg2 == One && iArg1 == One)
return One;
else
return Zero;
}
expr_t
DataTree::AddDivide(expr_t iArg1, expr_t iArg2) throw (DivisionByZeroException)
{
if (iArg2 == One)
return iArg1;
// This test should be before the next two, otherwise 0/0 won't be rejected
if (iArg2 == Zero)
{
cerr << "ERROR: Division by zero!" << endl;
throw DivisionByZeroException();
}
if (iArg1 == Zero)
return Zero;
if (iArg1 == iArg2)
return One;
return AddBinaryOp(iArg1, oDivide, iArg2);
}
expr_t
DataTree::AddLess(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oLess, iArg2);
}
expr_t
DataTree::AddGreater(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oGreater, iArg2);
}
expr_t
DataTree::AddLessEqual(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oLessEqual, iArg2);
}
expr_t
DataTree::AddGreaterEqual(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oGreaterEqual, iArg2);
}
expr_t
DataTree::AddEqualEqual(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oEqualEqual, iArg2);
}
expr_t
DataTree::AddDifferent(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oDifferent, iArg2);
}
expr_t
DataTree::AddPower(expr_t iArg1, expr_t iArg2)
{
if (iArg1 != Zero && iArg2 != Zero && iArg1 != One && iArg2 != One)
return AddBinaryOp(iArg1, oPower, iArg2);
else if (iArg1 == One)
return One;
else if (iArg2 == One)
return iArg1;
else if (iArg2 == Zero)
return One;
else
return Zero;
}
expr_t
DataTree::AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder)
{
assert(powerDerivOrder > 0);
return AddBinaryOp(iArg1, oPowerDeriv, iArg2, powerDerivOrder);
}
expr_t
DataTree::AddExp(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oExp, iArg1);
else
return One;
}
expr_t
DataTree::AddLog(expr_t iArg1)
{
if (iArg1 != Zero && iArg1 != One)
return AddUnaryOp(oLog, iArg1);
else if (iArg1 == One)
return Zero;
else
{
cerr << "ERROR: log(0) not defined!" << endl;
exit(EXIT_FAILURE);
}
}
expr_t
DataTree::AddLog10(expr_t iArg1)
{
if (iArg1 != Zero && iArg1 != One)
return AddUnaryOp(oLog10, iArg1);
else if (iArg1 == One)
return Zero;
else
{
cerr << "ERROR: log10(0) not defined!" << endl;
exit(EXIT_FAILURE);
}
}
expr_t
DataTree::AddCos(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oCos, iArg1);
else
return One;
}
expr_t
DataTree::AddSin(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oSin, iArg1);
else
return Zero;
}
expr_t
DataTree::AddTan(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oTan, iArg1);
else
return Zero;
}
expr_t
DataTree::AddAcos(expr_t iArg1)
{
if (iArg1 != One)
return AddUnaryOp(oAcos, iArg1);
else
return Zero;
}
expr_t
DataTree::AddAsin(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oAsin, iArg1);
else
return Zero;
}
expr_t
DataTree::AddAtan(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oAtan, iArg1);
else
return Zero;
}
expr_t
DataTree::AddCosh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oCosh, iArg1);
else
return One;
}
expr_t
DataTree::AddSinh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oSinh, iArg1);
else
return Zero;
}
expr_t
DataTree::AddTanh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oTanh, iArg1);
else
return Zero;
}
expr_t
DataTree::AddAcosh(expr_t iArg1)
{
if (iArg1 != One)
return AddUnaryOp(oAcosh, iArg1);
else
return Zero;
}
expr_t
DataTree::AddAsinh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oAsinh, iArg1);
else
return Zero;
}
expr_t
DataTree::AddAtanh(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oAtanh, iArg1);
else
return Zero;
}
expr_t
DataTree::AddSqrt(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oSqrt, iArg1);
else
return Zero;
}
expr_t
DataTree::AddAbs(expr_t iArg1)
{
if (iArg1 == Zero)
return Zero;
if (iArg1 == One)
return One;
else
return AddUnaryOp(oAbs, iArg1);
}
expr_t
DataTree::AddSign(expr_t iArg1)
{
if (iArg1 == Zero)
return Zero;
if (iArg1 == One)
return One;
else
return AddUnaryOp(oSign, iArg1);
}
expr_t
DataTree::AddErf(expr_t iArg1)
{
if (iArg1 != Zero)
return AddUnaryOp(oErf, iArg1);
else
return Zero;
}
expr_t
DataTree::AddMax(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oMax, iArg2);
}
expr_t
DataTree::AddMin(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oMin, iArg2);
}
expr_t
DataTree::AddNormcdf(expr_t iArg1, expr_t iArg2, expr_t iArg3)
{
return AddTrinaryOp(iArg1, oNormcdf, iArg2, iArg3);
}
expr_t
DataTree::AddNormpdf(expr_t iArg1, expr_t iArg2, expr_t iArg3)
{
return AddTrinaryOp(iArg1, oNormpdf, iArg2, iArg3);
}
expr_t
DataTree::AddSteadyState(expr_t iArg1)
{
return AddUnaryOp(oSteadyState, iArg1);
}
expr_t
DataTree::AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id)
{
return AddUnaryOp(oSteadyStateParamDeriv, iArg1, 0, param_symb_id);
}
expr_t
DataTree::AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id)
{
return AddUnaryOp(oSteadyStateParam2ndDeriv, iArg1, 0, param1_symb_id, param2_symb_id);
}
expr_t
DataTree::AddExpectation(int iArg1, expr_t iArg2)
{
return AddUnaryOp(oExpectation, iArg2, iArg1);
}
expr_t
DataTree::AddEqual(expr_t iArg1, expr_t iArg2)
{
return AddBinaryOp(iArg1, oEqual, iArg2);
}
void
DataTree::AddLocalVariable(int symb_id, expr_t value) throw (LocalVariableException)
{
assert(symbol_table.getType(symb_id) == eModelLocalVariable);
// Throw an exception if symbol already declared
map<int, expr_t>::iterator it = local_variables_table.find(symb_id);
if (it != local_variables_table.end())
throw LocalVariableException(symbol_table.getName(symb_id));
local_variables_table[symb_id] = value;
local_variables_vector.push_back(symb_id);
}
expr_t
DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments)
{
assert(symbol_table.getType(symb_id) == eExternalFunction);
external_function_node_map_t::iterator it = external_function_node_map.find(make_pair(arguments, symb_id));
if (it != external_function_node_map.end())
return it->second;
return new ExternalFunctionNode(*this, symb_id, arguments);
}
expr_t
DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index)
{
assert(symbol_table.getType(top_level_symb_id) == eExternalFunction);
first_deriv_external_function_node_map_t::iterator it
= first_deriv_external_function_node_map.find(make_pair(make_pair(arguments, input_index),
top_level_symb_id));
if (it != first_deriv_external_function_node_map.end())
return it->second;
return new FirstDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index);
}
expr_t
DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2)
{
assert(symbol_table.getType(top_level_symb_id) == eExternalFunction);
second_deriv_external_function_node_map_t::iterator it
= second_deriv_external_function_node_map.find(make_pair(make_pair(arguments,
make_pair(input_index1, input_index2)),
top_level_symb_id));
if (it != second_deriv_external_function_node_map.end())
return it->second;
return new SecondDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index1, input_index2);
}
bool
DataTree::isSymbolUsed(int symb_id) const
{
for (variable_node_map_t::const_iterator it = variable_node_map.begin();
it != variable_node_map.end(); it++)
if (it->first.first == symb_id)
return true;
if (local_variables_table.find(symb_id) != local_variables_table.end())
return true;
return false;
}
int
DataTree::getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException)
{
throw UnknownDerivIDException();
}
SymbolType
DataTree::getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException)
{
throw UnknownDerivIDException();
}
int
DataTree::getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException)
{
throw UnknownDerivIDException();
}
int
DataTree::getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException)
{
throw UnknownDerivIDException();
}
void
DataTree::addAllParamDerivId(set<int> &deriv_id_set)
{
}
int
DataTree::getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException)
{
throw UnknownDerivIDException();
}
bool
DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
{
for (unary_op_node_map_t::const_iterator it = unary_op_node_map.begin();
it != unary_op_node_map.end(); it++)
if (it->first.first.second == opcode)
return true;
return false;
}
bool
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
{
for (binary_op_node_map_t::const_iterator it = binary_op_node_map.begin();
it != binary_op_node_map.end(); it++)
if (it->first.second == opcode)
return true;
return false;
}
bool
DataTree::isTrinaryOpUsed(TrinaryOpcode opcode) const
{
for (trinary_op_node_map_t::const_iterator it = trinary_op_node_map.begin();
it != trinary_op_node_map.end(); it++)
if (it->first.second == opcode)
return true;
return false;
}
bool
DataTree::isExternalFunctionUsed(int symb_id) const
{
for (external_function_node_map_t::const_iterator it = external_function_node_map.begin();
it != external_function_node_map.end(); it++)
if (it->first.second == symb_id)
return true;
return false;
}
bool
DataTree::isFirstDerivExternalFunctionUsed(int symb_id) const
{
for (first_deriv_external_function_node_map_t::const_iterator it = first_deriv_external_function_node_map.begin();
it != first_deriv_external_function_node_map.end(); it++)
if (it->first.second == symb_id)
return true;
return false;
}
bool
DataTree::isSecondDerivExternalFunctionUsed(int symb_id) const
{
for (second_deriv_external_function_node_map_t::const_iterator it = second_deriv_external_function_node_map.begin();
it != second_deriv_external_function_node_map.end(); it++)
if (it->first.second == symb_id)
return true;
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;
}
void
DataTree::writePowerDerivCHeader(ostream &output) const
{
if (isBinaryOpUsed(oPowerDeriv))
output << "double getPowerDeriv(double, double, int);" << endl;
}
void
DataTree::writePowerDeriv(ostream &output) const
{
if (isBinaryOpUsed(oPowerDeriv))
output << "/*" << endl
<< " * The k-th derivative of x^p" << endl
<< " */" << endl
<< "double getPowerDeriv(double x, double p, int k)" << endl
<< "{" << endl
<< "#ifdef _MSC_VER" << endl
<< "# define nearbyint(x) (fabs((x)-floor(x)) < fabs((x)-ceil(x)) ? floor(x) : ceil(x))" << endl
<< "#endif" << endl
<< " if ( fabs(x) < " << NEAR_ZERO << " && p > 0 && k > p && fabs(p-nearbyint(p)) < " << NEAR_ZERO << " )" << endl
<< " return 0.0;" << endl
<< " else" << endl
<< " {" << endl
<< " int i = 0;" << endl
<< " double dxp = pow(x, p-k);" << endl
<< " for (; i<k; i++)" << endl
<< " dxp *= p--;" << endl
<< " return dxp;" << endl
<< " }" << endl
<< "}" << endl;
}
void
DataTree::writeNormcdfCHeader(ostream &output) const
{
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
if (isTrinaryOpUsed(oNormcdf))
output << "#ifdef _MSC_VER" << endl
<< "double normcdf(double);" << endl
<< "#endif" << endl;
#endif
}
void
DataTree::writeNormcdf(ostream &output) const
{
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
if (isTrinaryOpUsed(oNormcdf))
output << endl
<< "#ifdef _MSC_VER" << endl
<< "/*" << endl
<< " * Define normcdf for MSVC compiler" << endl
<< " */" << endl
<< "double normcdf(double x)" << endl
<< "{" << endl
<< "#if _MSC_VER >= 1700" << endl
<< " return 0.5 * erfc(-x * M_SQRT1_2);" << endl
<< "#else" << endl
<< " // From http://www.johndcook.com/blog/cpp_phi" << endl
<< " double a1 = 0.254829592;" << endl
<< " double a2 = -0.284496736;" << endl
<< " double a3 = 1.421413741;" << endl
<< " double a4 = -1.453152027;" << endl
<< " double a5 = 1.061405429;" << endl
<< " double p = 0.3275911;" << endl
<< " int sign = (x < 0) ? -1 : 1;" << endl
<< " x = fabs(x)/sqrt(2.0);" << endl
<< " // From the Handbook of Mathematical Functions by Abramowitz and Stegun, formula 7.1.26" << endl
<< " double t = 1.0/(1.0 + p*x);" << endl
<< " double y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);" << endl
<< " return 0.5*(1.0 + sign*y);" << endl
<< "#endif" << endl
<< "}" << endl
<< "#endif" << endl;
#endif
}

View File

@ -1,378 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DATATREE_HH
#define _DATATREE_HH
using namespace std;
#include <string>
#include <map>
#include <list>
#include <sstream>
#include <iomanip>
#include <cmath>
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
#include "ExternalFunctionsTable.hh"
#include "ExprNode.hh"
#define CONSTANTS_PRECISION 16
class DataTree
{
friend class ExprNode;
friend class NumConstNode;
friend class VariableNode;
friend class UnaryOpNode;
friend class BinaryOpNode;
friend class TrinaryOpNode;
friend class AbstractExternalFunctionNode;
friend class ExternalFunctionNode;
friend class FirstDerivExternalFunctionNode;
friend class SecondDerivExternalFunctionNode;
protected:
//! A reference to the symbol table
SymbolTable &symbol_table;
//! Reference to numerical constants table
NumericalConstants &num_constants;
//! A reference to the external functions table
ExternalFunctionsTable &external_functions_table;
typedef map<int, NumConstNode *> num_const_node_map_t;
num_const_node_map_t num_const_node_map;
//! Pair (symbol_id, lag) used as key
typedef map<pair<int, int>, VariableNode *> variable_node_map_t;
variable_node_map_t variable_node_map;
//! Pair( Pair(arg1, UnaryOpCode), Pair( Expectation Info Set, Pair(param1_symb_id, param2_symb_id)) ))
typedef map<pair<pair<expr_t, UnaryOpcode>, pair<int, pair<int, int> > >, UnaryOpNode *> unary_op_node_map_t;
unary_op_node_map_t unary_op_node_map;
//! Pair( Pair( Pair(arg1, arg2), order of Power Derivative), opCode)
typedef map<pair<pair<pair<expr_t, expr_t>, int>, BinaryOpcode>, BinaryOpNode *> binary_op_node_map_t;
binary_op_node_map_t binary_op_node_map;
typedef map<pair<pair<pair<expr_t, expr_t>, expr_t>, TrinaryOpcode>, TrinaryOpNode *> trinary_op_node_map_t;
trinary_op_node_map_t trinary_op_node_map;
// (arguments, symb_id) -> ExternalFunctionNode
typedef map<pair<vector<expr_t>, int>, ExternalFunctionNode *> external_function_node_map_t;
external_function_node_map_t external_function_node_map;
// ((arguments, deriv_idx), symb_id) -> FirstDerivExternalFunctionNode
typedef map<pair<pair<vector<expr_t>, int>, int>, FirstDerivExternalFunctionNode *> first_deriv_external_function_node_map_t;
first_deriv_external_function_node_map_t first_deriv_external_function_node_map;
// ((arguments, (deriv_idx1, deriv_idx2)), symb_id) -> SecondDerivExternalFunctionNode
typedef map<pair<pair<vector<expr_t>, pair<int, int> >, int>, SecondDerivExternalFunctionNode *> second_deriv_external_function_node_map_t;
second_deriv_external_function_node_map_t second_deriv_external_function_node_map;
//! Stores local variables value (maps symbol ID to corresponding node)
map<int, expr_t> local_variables_table;
//! Stores the order of appearance of local variables in the model block. Needed following change in #563
vector<int> local_variables_vector;
//! Internal implementation of AddVariable(), without the check on the lag
VariableNode *AddVariableInternal(int symb_id, int lag);
//! Internal implementation of ParamUsedWithLeadLag()
bool ParamUsedWithLeadLagInternal() const;
private:
typedef list<expr_t> node_list_t;
//! The list of nodes
node_list_t node_list;
//! A counter for filling ExprNode's idx field
int node_counter;
inline expr_t AddPossiblyNegativeConstant(double val);
inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0, int param1_symb_id = 0, int param2_symb_id = 0);
inline expr_t AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder = 0);
inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3);
public:
DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
virtual
~DataTree();
//! Some predefined constants
expr_t Zero, One, Two, MinusOne, NaN, Infinity, MinusInfinity, Pi;
//! Raised when a local parameter is declared twice
class LocalVariableException
{
public:
string name;
LocalVariableException(const string &name_arg) : name(name_arg)
{
}
};
class DivisionByZeroException
{
};
//! Adds a non-negative numerical constant (possibly Inf or NaN)
expr_t AddNonNegativeConstant(const string &value);
//! Adds a variable
/*! The default implementation of the method refuses any lag != 0 */
virtual VariableNode *AddVariable(int symb_id, int lag = 0);
//! Adds "arg1+arg2" to model tree
expr_t AddPlus(expr_t iArg1, expr_t iArg2);
//! Adds "arg1-arg2" to model tree
expr_t AddMinus(expr_t iArg1, expr_t iArg2);
//! Adds "-arg" to model tree
expr_t AddUMinus(expr_t iArg1);
//! Adds "arg1*arg2" to model tree
expr_t AddTimes(expr_t iArg1, expr_t iArg2);
//! Adds "arg1/arg2" to model tree
expr_t AddDivide(expr_t iArg1, expr_t iArg2) throw (DivisionByZeroException);
//! Adds "arg1<arg2" to model tree
expr_t AddLess(expr_t iArg1, expr_t iArg2);
//! Adds "arg1>arg2" to model tree
expr_t AddGreater(expr_t iArg1, expr_t iArg2);
//! Adds "arg1<=arg2" to model tree
expr_t AddLessEqual(expr_t iArg1, expr_t iArg2);
//! Adds "arg1>=arg2" to model tree
expr_t AddGreaterEqual(expr_t iArg1, expr_t iArg2);
//! Adds "arg1==arg2" to model tree
expr_t AddEqualEqual(expr_t iArg1, expr_t iArg2);
//! Adds "arg1!=arg2" to model tree
expr_t AddDifferent(expr_t iArg1, expr_t iArg2);
//! Adds "arg1^arg2" to model tree
expr_t AddPower(expr_t iArg1, expr_t iArg2);
//! Adds "getPowerDeriv(arg1, arg2, powerDerivOrder)" to model tree
expr_t AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder);
//! Adds "E(arg1)(arg2)" to model tree
expr_t AddExpectation(int iArg1, expr_t iArg2);
//! Adds "exp(arg)" to model tree
expr_t AddExp(expr_t iArg1);
//! Adds "log(arg)" to model tree
expr_t AddLog(expr_t iArg1);
//! Adds "log10(arg)" to model tree
expr_t AddLog10(expr_t iArg1);
//! Adds "cos(arg)" to model tree
expr_t AddCos(expr_t iArg1);
//! Adds "sin(arg)" to model tree
expr_t AddSin(expr_t iArg1);
//! Adds "tan(arg)" to model tree
expr_t AddTan(expr_t iArg1);
//! Adds "acos(arg)" to model tree
expr_t AddAcos(expr_t iArg1);
//! Adds "asin(arg)" to model tree
expr_t AddAsin(expr_t iArg1);
//! Adds "atan(arg)" to model tree
expr_t AddAtan(expr_t iArg1);
//! Adds "cosh(arg)" to model tree
expr_t AddCosh(expr_t iArg1);
//! Adds "sinh(arg)" to model tree
expr_t AddSinh(expr_t iArg1);
//! Adds "tanh(arg)" to model tree
expr_t AddTanh(expr_t iArg1);
//! Adds "acosh(arg)" to model tree
expr_t AddAcosh(expr_t iArg1);
//! Adds "asinh(arg)" to model tree
expr_t AddAsinh(expr_t iArg1);
//! Adds "atanh(args)" to model tree
expr_t AddAtanh(expr_t iArg1);
//! Adds "sqrt(arg)" to model tree
expr_t AddSqrt(expr_t iArg1);
//! Adds "abs(arg)" to model tree
expr_t AddAbs(expr_t iArg1);
//! Adds "sign(arg)" to model tree
expr_t AddSign(expr_t iArg1);
//! Adds "erf(arg)" to model tree
expr_t AddErf(expr_t iArg1);
//! Adds "max(arg1,arg2)" to model tree
expr_t AddMax(expr_t iArg1, expr_t iArg2);
//! Adds "min(arg1,arg2)" to model tree
expr_t AddMin(expr_t iArg1, expr_t iArg2);
//! Adds "normcdf(arg1,arg2,arg3)" to model tree
expr_t AddNormcdf(expr_t iArg1, expr_t iArg2, expr_t iArg3);
//! Adds "normpdf(arg1,arg2,arg3)" to model tree
expr_t AddNormpdf(expr_t iArg1, expr_t iArg2, expr_t iArg3);
//! Adds "steadyState(arg)" to model tree
expr_t AddSteadyState(expr_t iArg1);
//! Add derivative of steady state w.r.t. parameter to model tree
expr_t AddSteadyStateParamDeriv(expr_t iArg1, int param_symb_id);
//! Add 2nd derivative of steady state w.r.t. parameter to model tree
expr_t AddSteadyStateParam2ndDeriv(expr_t iArg1, int param1_symb_id, int param2_symb_id);
//! Adds "arg1=arg2" to model tree
expr_t AddEqual(expr_t iArg1, expr_t iArg2);
//! Adds a model local variable with its value
void AddLocalVariable(int symb_id, expr_t value) throw (LocalVariableException);
//! Adds an external function node
expr_t AddExternalFunction(int symb_id, const vector<expr_t> &arguments);
//! Adds an external function node for the first derivative of an external function
expr_t AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index);
//! Adds an external function node for the second derivative of an external function
expr_t AddSecondDerivExternalFunction(int top_level_symb_id, const vector<expr_t> &arguments, int input_index1, int input_index2);
//! Checks if a given symbol is used somewhere in the data tree
bool isSymbolUsed(int symb_id) const;
//! Checks if a given unary op is used somewhere in the data tree
bool isUnaryOpUsed(UnaryOpcode opcode) const;
//! Checks if a given binary op is used somewhere in the data tree
bool isBinaryOpUsed(BinaryOpcode opcode) const;
//! Checks if a given trinary op is used somewhere in the data tree
bool isTrinaryOpUsed(TrinaryOpcode opcode) const;
//! Checks if a given external function is used somewhere in the data tree
bool isExternalFunctionUsed(int symb_id) const;
//! Checks if a given first derivative external function is used somewhere in the data tree
bool isFirstDerivExternalFunctionUsed(int symb_id) const;
//! Checks if a given second derivative external function is used somewhere in the data tree
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;
//! Write the C Header for getPowerDeriv when use_dll is used
void writePowerDerivCHeader(ostream &output) const;
//! Write getPowerDeriv in C
void writePowerDeriv(ostream &output) const;
//! Write the C Header for normcdf when use_dll is used
void writeNormcdfCHeader(ostream &output) const;
//! Write normcdf in C
void writeNormcdf(ostream &output) const;
//! Thrown when trying to access an unknown variable by deriv_id
class UnknownDerivIDException
{
};
//! Raised when a trend is declared twice
class TrendException
{
public:
string name;
TrendException(const string &name_arg) : name(name_arg)
{
}
};
//! 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);
virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException);
virtual int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException);
virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Returns the column of the dynamic Jacobian associated to a derivation ID
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
//! Adds to the set all the deriv IDs corresponding to parameters
virtual void addAllParamDerivId(set<int> &deriv_id_set);
//! Returns bool indicating whether DataTree represents a Dynamic Model (returns true in DynamicModel.hh)
virtual bool
isDynamic() const
{
return false;
};
};
inline expr_t
DataTree::AddPossiblyNegativeConstant(double v)
{
/* Treat NaN and Inf separately. In particular, under Windows, converting
them to a string does not work as expected */
if (isnan(v))
return NaN;
if (isinf(v))
return (v < 0 ? MinusInfinity : Infinity);
bool neg = false;
if (v < 0)
{
v = -v;
neg = true;
}
ostringstream ost;
ost << setprecision(CONSTANTS_PRECISION) << v;
expr_t cnode = AddNonNegativeConstant(ost.str());
if (neg)
return AddUMinus(cnode);
else
return cnode;
}
inline expr_t
DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int param1_symb_id, int param2_symb_id)
{
// If the node already exists in tree, share it
unary_op_node_map_t::iterator it = unary_op_node_map.find(make_pair(make_pair(arg, op_code), make_pair(arg_exp_info_set, make_pair(param1_symb_id, param2_symb_id))));
if (it != unary_op_node_map.end())
return it->second;
// Try to reduce to a constant
// Case where arg is a constant and op_code == oUminus (i.e. we're adding a negative constant) is skipped
NumConstNode *carg = dynamic_cast<NumConstNode *>(arg);
if (op_code != oUminus || carg == NULL)
{
try
{
double argval = arg->eval(eval_context_t());
double val = UnaryOpNode::eval_opcode(op_code, argval);
return AddPossiblyNegativeConstant(val);
}
catch (ExprNode::EvalException &e)
{
}
}
return new UnaryOpNode(*this, op_code, arg, arg_exp_info_set, param1_symb_id, param2_symb_id);
}
inline expr_t
DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerDerivOrder)
{
binary_op_node_map_t::iterator it = binary_op_node_map.find(make_pair(make_pair(make_pair(arg1, arg2), powerDerivOrder), op_code));
if (it != binary_op_node_map.end())
return it->second;
// Try to reduce to a constant
try
{
double argval1 = arg1->eval(eval_context_t());
double argval2 = arg2->eval(eval_context_t());
double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2, powerDerivOrder);
return AddPossiblyNegativeConstant(val);
}
catch (ExprNode::EvalException &e)
{
}
return new BinaryOpNode(*this, arg1, op_code, arg2, powerDerivOrder);
}
inline expr_t
DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3)
{
trinary_op_node_map_t::iterator it = trinary_op_node_map.find(make_pair(make_pair(make_pair(arg1, arg2), arg3), op_code));
if (it != trinary_op_node_map.end())
return it->second;
// Try to reduce to a constant
try
{
double argval1 = arg1->eval(eval_context_t());
double argval2 = arg2->eval(eval_context_t());
double argval3 = arg3->eval(eval_context_t());
double val = TrinaryOpNode::eval_opcode(argval1, op_code, argval2, argval3);
return AddPossiblyNegativeConstant(val);
}
catch (ExprNode::EvalException &e)
{
}
return new TrinaryOpNode(*this, arg1, op_code, arg2, arg3);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,579 +0,0 @@
/*
* Copyright (C) 2003-2018 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DYNAMICMODEL_HH
#define _DYNAMICMODEL_HH
using namespace std;
#define ZERO_BAND 1e-8
#include <fstream>
#include <boost/crc.hpp>
#include "StaticModel.hh"
//! Stores a dynamic model
class DynamicModel : public ModelTree
{
private:
//! Stores equations declared as [static]
/*! They will be used in toStatic() to replace equations marked as [dynamic] */
vector<BinaryOpNode *> static_only_equations;
//! Stores line numbers of equations declared as [static]
vector<int> static_only_equations_lineno;
//! Stores the equation tags of equations declared as [static]
vector<vector<pair<string, string> > > static_only_equations_equation_tags;
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;
//! Maximum lag and lead over all types of variables (positive values)
/*! Set by computeDerivIDs() */
int max_lag, max_lead;
//! Maximum lag and lead over endogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_endo_lag, max_endo_lead;
//! Maximum lag and lead over exogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_exo_lag, max_exo_lead;
//! Maximum lag and lead over deterministic exogenous variables (positive values)
/*! Set by computeDerivIDs() */
int max_exo_det_lag, max_exo_det_lead;
//! Maximum lag and lead over all types of variables (positive values) of original model
int max_lag_orig, max_lead_orig;
//! Maximum lag and lead over endogenous variables (positive values) of original model
int max_endo_lag_orig, max_endo_lead_orig;
//! Maximum lag and lead over exogenous variables (positive values) of original model
int max_exo_lag_orig, max_exo_lead_orig;
//! Maximum lag and lead over deterministic exogenous variables (positive values) of original model
int max_exo_det_lag_orig, max_exo_det_lead_orig;
//! Cross reference information
map<int, ExprNode::EquationInfo> xrefs;
map<pair<int, int>, set<int> > xref_param;
map<pair<int, int>, set<int> > xref_endo;
map<pair<int, int>, set<int> > xref_exo;
map<pair<int, int>, set<int> > xref_exo_det;
//! Nonzero equations in the Hessian
map<int, string> nonzero_hessian_eqs;
//! Number of columns of dynamic jacobian
/*! Set by computeDerivID()s and computeDynJacobianCols() */
int dynJacobianColsNbr;
//! Temporary terms for block decomposed models
vector< vector<temporary_terms_t> > v_temporary_terms;
vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
//! Store the derivatives or the chainrule derivatives:map<pair< equation, pair< variable, lead_lag >, expr_t>
typedef map< pair< int, pair< int, int> >, expr_t> first_chain_rule_derivatives_t;
first_chain_rule_derivatives_t first_chain_rule_derivatives;
//! Writes dynamic model file (Matlab version)
void writeDynamicMFile(const string &dynamic_basename) const;
//! Writes dynamic model file (Julia version)
void writeDynamicJuliaFile(const string &dynamic_basename) const;
//! Writes dynamic model file (C version)
/*! \todo add third derivatives handling */
void writeDynamicCFile(const string &dynamic_basename, const int order) const;
//! Writes dynamic model file when SparseDLL option is on
void writeSparseDynamicMFile(const string &dynamic_basename, const string &basename) const;
//! Writes the dynamic model equations and its derivatives
/*! \todo add third derivatives handling in C output */
void writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia) const;
//! Writes the Block reordred structure of the model in M output
void writeModelEquationsOrdered_M(const string &dynamic_basename) const;
//! Writes the code of the Block reordred structure of the model in virtual machine bytecode
void writeModelEquationsCode_Block(string &file_name, const string &bin_basename, const map_idx_t &map_idx) const;
//! Writes the code of the model in virtual machine bytecode
void writeModelEquationsCode(string &file_name, const string &bin_basename, const map_idx_t &map_idx) const;
//! Computes jacobian and prepares for equation normalization
/*! Using values from initval/endval blocks and parameter initializations:
- computes the jacobian for the model w.r. to contemporaneous variables
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
*/
//void evaluateJacobian(const eval_context_t &eval_context, jacob_map *j_m, bool dynamic);
//! return a map on the block jacobian
map<pair<pair<int, pair<int, int> >, pair<int, int> >, int> get_Derivatives(int block);
//! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables
void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives);
string reform(string name) const;
map_idx_t map_idx;
//! sorts the temporary terms in the blocks order
void computeTemporaryTermsOrdered();
//! creates a mapping from the index of temporary terms to a natural index
void computeTemporaryTermsMapping();
//! Write derivative code of an equation w.r. to a variable
void compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, int lag, const map_idx_t &map_idx) const;
//! Write chain rule derivative code of an equation w.r. to a variable
void compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int var, int lag, const map_idx_t &map_idx) const;
//! Get the type corresponding to a derivation ID
virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Get the lag corresponding to a derivation ID
virtual int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Get the symbol ID corresponding to a derivation ID
virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Compute the column indices of the dynamic Jacobian
void computeDynJacobianCols(bool jacobianExo);
//! Computes derivatives of the Jacobian w.r. to trend vars and tests that they are equal to zero
void testTrendDerivativesEqualToZero(const eval_context_t &eval_context);
//! Collect only the first derivatives
map<pair<int, pair<int, int> >, expr_t> collect_first_order_derivatives_endogenous();
//! Allocates the derivation IDs for all dynamic variables of the model
/*! Also computes max_{endo,exo}_{lead_lag}, and initializes dynJacobianColsNbr to the number of dynamic endos */
void computeDerivIDs();
//! Write chain rule derivative of a recursive equation w.r. to a variable
void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
void collect_block_first_order_derivatives();
//! Collecte the informations about exogenous, deterministic exogenous and endogenous from the previous block for each block
void collectBlockVariables();
//! Factorized code for substitutions of leads/lags
/*! \param[in] type determines which type of variables is concerned
\param[in] deterministic_model whether we are in a deterministic model (only for exogenous leads/lags)
\param[in] subset variables to which to apply the transformation (only for diff of forward vars)
*/
void substituteLeadLagInternal(aux_var_t type, bool deterministic_model, const vector<string> &subset);
private:
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
bool global_temporary_terms;
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
//! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size > >
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
//! for all blocks derivatives description
blocks_derivatives_t blocks_derivatives;
//! The jacobian without the elements below the cutoff
dynamic_jacob_map_t dynamic_jacobian;
//! Vector indicating if the block is linear in endogenous variable (true) or not (false)
vector<bool> blocks_linear;
//! Map the derivatives for a block pair<lag, make_pair(make_pair(eq, var)), expr_t>
typedef map<pair< int, pair<int, int> >, expr_t> derivative_t;
//! Vector of derivative for each blocks
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
//!List for each block and for each lag-lead all the other endogenous variables and exogenous variables
typedef set<int> var_t;
typedef map<int, var_t> lag_var_t;
vector<lag_var_t> other_endo_block, exo_block, exo_det_block;
//!List for each block the exogenous variables
vector<pair<var_t, int> > block_var_exo;
map< int, map<int, int> > block_exo_index, block_det_exo_index, block_other_endo_index;
//! for each block described the number of static, forward, backward and mixed variables in the block
/*! pair< pair<static, forward>, pair<backward,mixed> > */
vector<pair< pair<int, int>, pair<int, int> > > block_col_type;
//! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc)
void computeRevXref(map<pair<int, int>, set<int> > &xrefset, const set<pair<int, int> > &eiref, int eqn);
//! Write reverse cross references
void writeRevXrefs(ostream &output, const map<pair<int, int>, set<int> > &xrefmap, const string &type) const;
//! List for each variable its block number and its maximum lag and lead inside the block
vector<pair<int, pair<int, int> > > variable_block_lead_lag;
//! List for each equation its block number
vector<int> equation_block;
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
vector<pair<int, int> > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
public:
DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_argx);
//! Adds a variable node
/*! This implementation allows for non-zero lag */
virtual VariableNode *AddVariable(int symb_id, int lag = 0);
//! Compute cross references
void computeXrefs();
//! Write cross references
void writeXrefs(ostream &output) const;
//! Execute computations (variable sorting + derivation)
/*!
\param jacobianExo whether derivatives w.r. to exo and exo_det should be in the Jacobian (derivatives w.r. to endo are always computed)
\param hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed (implies jacobianExo = true)
\param thirdDerivatives whether 3rd derivatives w.r. to endo/exo/exo_det should be computed (implies jacobianExo = true)
\param paramsDerivsOrder order of derivatives w.r. to a pair (endo/exo/exo_det, parameter) to be computed (>0 implies jacobianExo = true)
\param eval_context evaluation context for normalization
\param no_tmp_terms if true, no temporary terms will be computed in the dynamic files
*/
void computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, int paramsDerivsOrder,
const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode, const bool nopreprocessoroutput);
//! Writes model initialization and lead/lag incidence matrix to output
void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const;
//! Write JSON Output
void writeJsonOutput(ostream &output) const;
//! Write JSON Output representation of original dynamic model
void writeJsonOriginalModelOutput(ostream &output) const;
//! Write JSON Output representation of model info (useful stuff from M_)
void writeJsonDynamicModelInfo(ostream &output) const;
//! Write JSON Output representation of dynamic model after computing pass
void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
//! Write JSON prams derivatives file
void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const;
//! Write cross reference output if the xref maps have been filed
void writeJsonXrefs(ostream &output) const;
void writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int> > &xrefs) const;
//! Print equations that have non-zero second derivatives
void printNonZeroHessianEquations(ostream &output) const;
//! Set the equations that have non-zero second derivatives
void setNonZeroHessianEquations(map<int, string> &eqs);
//! Adds informations for simulation in a binary file
void Write_Inf_To_Bin_File_Block(const string &dynamic_basename, const string &bin_basename,
const int &num, int &u_count_int, bool &file_open, bool is_two_boundaries) const;
//! Writes dynamic model file
void writeDynamicFile(const string &basename, bool block, bool bytecode, bool use_dll, int order, bool julia) const;
//! Writes file containing parameters derivatives
void writeParamsDerivativesFile(const string &basename, bool julia) const;
//! 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;
//! Find endogenous variables not used in model
set<int> findUnusedEndogenous();
//! Find exogenous variables not used in model
set<int> findUnusedExogenous();
//! Set the max leads/lags of the original model
void setLeadsLagsOrig();
//! Copies a dynamic model (only the equations)
/*! It assumes that the dynamic model given in argument has just been allocated */
void cloneDynamic(DynamicModel &dynamic_model) const;
//! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
void computeRamseyPolicyFOCs(const StaticModel &static_model, const bool nopreprocessoroutput);
//! Replaces the model equations in dynamic_model with those in this model
void replaceMyEquations(DynamicModel &dynamic_model) const;
//! Adds an equation marked as [static]
void addStaticOnlyEquation(expr_t eq, int lineno, const vector<pair<string, string> > &eq_tags);
//! Returns number of static only equations
size_t staticOnlyEquationsNbr() const;
//! Returns number of dynamic only equations
size_t dynamicOnlyEquationsNbr() const;
//! Writes LaTeX file with the equations of the dynamic model
void writeLatexFile(const string &basename, const bool write_equation_tags) const;
//! Writes LaTeX file with the equations of the dynamic model (for the original model)
void writeLatexOriginalFile(const string &basename, const bool write_equation_tags) const;
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
virtual void addAllParamDerivId(set<int> &deriv_id_set);
//! Returns true indicating that this is a dynamic model
virtual bool
isDynamic() const
{
return true;
};
//! Drive test of detrended equations
void runTrendTest(const eval_context_t &eval_context);
//! Transforms the model by removing all leads greater or equal than 2 on endos
/*! Note that this can create new lags on endos and exos */
void substituteEndoLeadGreaterThanTwo(bool deterministic_model);
//! Transforms the model by removing all lags greater or equal than 2 on endos
void substituteEndoLagGreaterThanTwo(bool deterministic_model);
//! Transforms the model by removing all leads on exos
/*! Note that this can create new lags on endos and exos */
void substituteExoLead(bool deterministic_model);
//! Transforms the model by removing all lags on exos
void substituteExoLag(bool deterministic_model);
//! Transforms the model by removing all oExpectation
void substituteExpectation(bool partial_information_model);
//! Transforms the model by decreasing the lead/lag of predetermined variables in model equations by one
void transformPredeterminedVariables();
//! Transforms the model by removing trends specified by the user
void detrendEquations();
//! Transforms the model by replacing trend variables with a 1
void removeTrendVariableFromEquations();
//! Transforms the model by creating aux vars for the diff of forward vars
/*! If subset is empty, does the transformation for all fwrd vars; otherwise
restrict it to the vars in subset */
void differentiateForwardVars(const vector<string> &subset);
//! Fills eval context with values of model local variables and auxiliary variables
void fillEvalContext(eval_context_t &eval_context) const;
//! Return the number of blocks
virtual unsigned int
getNbBlocks() const
{
return (block_type_firstequation_size_mfs.size());
};
//! Determine the simulation type of each block
virtual BlockSimulationType
getBlockSimulationType(int block_number) const
{
return (block_type_firstequation_size_mfs[block_number].first.first);
};
//! Return the first equation number of a block
virtual unsigned int
getBlockFirstEquation(int block_number) const
{
return (block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the size of the block block_number
virtual unsigned int
getBlockSize(int block_number) const
{
return (block_type_firstequation_size_mfs[block_number].second.first);
};
//! Return the number of exogenous variable in the block block_number
virtual unsigned int
getBlockExoSize(int block_number) const
{
return (block_var_exo[block_number].first.size());
};
//! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
virtual unsigned int
getBlockExoColSize(int block_number) const
{
return (block_var_exo[block_number].second);
};
//! Return the number of feedback variable of the block block_number
virtual unsigned int
getBlockMfs(int block_number) const
{
return (block_type_firstequation_size_mfs[block_number].second.second);
};
//! Return the maximum lag in a block
virtual unsigned int
getBlockMaxLag(int block_number) const
{
return (block_lag_lead[block_number].first);
};
//! Return the maximum lead in a block
virtual unsigned int
getBlockMaxLead(int block_number) const
{
return (block_lag_lead[block_number].second);
};
//! Return the type of equation (equation_number) belonging to the block block_number
virtual EquationType
getBlockEquationType(int block_number, int equation_number) const
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first);
};
//! Return true if the equation has been normalized
virtual bool
isBlockEquationRenormalized(int block_number, int equation_number) const
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first == E_EVALUATE_S);
};
//! Return the expr_t of the equation equation_number belonging to the block block_number
virtual expr_t
getBlockEquationExpr(int block_number, int equation_number) const
{
return (equations[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]]);
};
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
virtual expr_t
getBlockEquationRenormalizedExpr(int block_number, int equation_number) const
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].second);
};
//! Return the original number of equation equation_number belonging to the block block_number
virtual int
getBlockEquationID(int block_number, int equation_number) const
{
return (equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]);
};
//! Return the original number of variable variable_number belonging to the block block_number
virtual int
getBlockVariableID(int block_number, int variable_number) const
{
return (variable_reordered[block_type_firstequation_size_mfs[block_number].first.second+variable_number]);
};
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number
virtual int
getBlockVariableExoID(int block_number, int variable_number) const
{
map<int, var_t>::const_iterator it = exo_block[block_number].find(variable_number);
return (it->first);
};
//! Return the position of equation_number in the block number belonging to the block block_number
virtual int
getBlockInitialEquationID(int block_number, int equation_number) const
{
return ((int) inv_equation_reordered[equation_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the position of variable_number in the block number belonging to the block block_number
virtual int
getBlockInitialVariableID(int block_number, int variable_number) const
{
return ((int) inv_variable_reordered[variable_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the block number containing the endogenous variable variable_number
int
getBlockVariableID(int variable_number) const
{
return (variable_block_lead_lag[variable_number].first);
};
//! Return the position of the exogenous variable_number in the block number belonging to the block block_number
virtual int
getBlockInitialExogenousID(int block_number, int variable_number) const
{
map< int, map<int, int> >::const_iterator it = block_exo_index.find(block_number);
if (it != block_exo_index.end())
{
map<int, int>::const_iterator it1 = it->second.find(variable_number);
if (it1 != it->second.end())
return it1->second;
else
return -1;
}
else
return (-1);
};
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
virtual int
getBlockInitialDetExogenousID(int block_number, int variable_number) const
{
map< int, map<int, int> >::const_iterator it = block_det_exo_index.find(block_number);
if (it != block_det_exo_index.end())
{
map<int, int>::const_iterator it1 = it->second.find(variable_number);
if (it1 != it->second.end())
return it1->second;
else
return -1;
}
else
return (-1);
};
//! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
virtual int
getBlockInitialOtherEndogenousID(int block_number, int variable_number) const
{
map< int, map<int, int> >::const_iterator it = block_other_endo_index.find(block_number);
if (it != block_other_endo_index.end())
{
map<int, int>::const_iterator it1 = it->second.find(variable_number);
if (it1 != it->second.end())
return it1->second;
else
return -1;
}
else
return (-1);
};
bool isModelLocalVariableUsed() const;
//! Returns true if a parameter was used in the model block with a lead or lag
bool ParamUsedWithLeadLag() const;
//! Writes model initialization and lead/lag incidence matrix to C output
void writeCOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present) const;
//! Writes model initialization and lead/lag incidence matrix to Cpp output
void writeCCOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present) const;
//! Writes C file containing residuals
void writeResidualsC(const string &basename, bool cuda) const;
//! Writes C file containing first order derivatives of model evaluated at steady state
void writeFirstDerivativesC(const string &basename, bool cuda) const;
//! Writes C file containing first order derivatives of model evaluated at steady state (conpressed sparse column)
void writeFirstDerivativesC_csr(const string &basename, bool cuda) const;
//! Writes C file containing second order derivatives of model evaluated at steady state (compressed sparse column)
void writeSecondDerivativesC_csr(const string &basename, bool cuda) const;
//! Writes C file containing third order derivatives of model evaluated at steady state (compressed sparse column)
void writeThirdDerivativesC_csr(const string &basename, bool cuda) const;
bool isChecksumMatching(const string &basename) const;
};
//! Classes to re-order derivatives for various sparse storage formats
class derivative
{
public:
long unsigned int linear_address;
long unsigned int col_nbr;
unsigned int row_nbr;
expr_t value;
derivative(long unsigned int arg1, long unsigned int arg2, int arg3, expr_t arg4) :
linear_address(arg1), col_nbr(arg2), row_nbr(arg3), value(arg4)
{
};
};
class derivative_less_than
{
public:
bool
operator()(const derivative &d1, const derivative &d2) const
{
return d1.linear_address < d2.linear_address;
}
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,413 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION 4.
#endif
#include <unistd.h>
#include "ParsingDriver.hh"
#include "ExtendedPreprocessorTypes.hh"
#include "ConfigFile.hh"
/* Prototype for second part of main function
Splitting main() in two parts was necessary because ParsingDriver.h and MacroDriver.h can't be
included simultaneously (because of Bison limitations).
*/
void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear_global,
bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console,
bool nograph, bool nointeractive, bool parallel, ConfigFile &config_file,
WarningConsolidation &warnings_arg, bool nostrict, bool stochastic, bool check_model_changes,
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
LanguageOutputType lang, int params_derivs_order
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
, bool cygwin, bool msvc, bool mingw
#endif
, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple
, bool nopreprocessoroutput
);
void main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file,
bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream &macro_output);
void
usage()
{
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=C|C++|julia]"
<< " [params_derivs_order=0|1|2]"
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
<< " [cygwin] [msvc] [mingw]"
#endif
<< " [json=parse|check|transform|compute] [jsonstdout] [onlyjson] [jsonderivsimple] [nopathchange] [nopreprocessoroutput]"
<< endl;
exit(EXIT_FAILURE);
}
int
main(int argc, char **argv)
{
/*
Redirect stderr to stdout.
Made necessary because MATLAB/Octave can only capture stdout (but not
stderr), in order to put it in the logfile (see issue #306)
*/
dup2(STDOUT_FILENO, STDERR_FILENO);
if (argc < 2)
{
cerr << "Missing model file!" << endl;
usage();
}
bool clear_all = true;
bool clear_global = false;
bool save_macro = false;
string save_macro_file;
bool debug = false;
bool no_tmp_terms = false;
bool only_macro = false;
bool no_line_macro = false;
bool no_empty_line_macro = false;
bool no_log = false;
bool no_warn = false;
int params_derivs_order = 2;
bool warn_uninit = false;
bool console = false;
bool nograph = false;
bool nointeractive = false;
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
bool cygwin = false;
bool msvc = false;
bool mingw = false;
#endif
string parallel_config_file;
bool parallel = false;
string cluster_name;
bool parallel_slave_open_mode = false;
bool parallel_test = false;
bool nostrict = false;
bool stochastic = false;
bool check_model_changes = false;
bool minimal_workspace = false;
bool compute_xrefs = false;
map<string, string> defines;
vector<string> path;
FileOutputType output_mode = none;
JsonOutputPointType json = nojson;
JsonFileOutputType json_output_mode = file;
bool onlyjson = false;
bool jsonderivsimple = false;
LanguageOutputType language = matlab;
bool nopreprocessoroutput = false;
// Parse options
for (int arg = 2; arg < argc; arg++)
{
if (!strcmp(argv[arg], "debug"))
debug = true;
else if (!strcmp(argv[arg], "noclearall"))
clear_all = false;
else if (strlen(argv[arg]) >= 19 && !strncmp(argv[arg], "params_derivs_order", 19))
{
if (strlen(argv[arg]) >= 22 || argv[arg][19] != '='
|| !(argv[arg][20] == '0' || argv[arg][20] == '1' || argv[arg][20] == '2'))
{
cerr << "Incorrect syntax for params_derivs_order option" << endl;
usage();
}
params_derivs_order = atoi(argv[arg] + 20);
}
else if (!strcmp(argv[arg], "onlyclearglobals"))
{
clear_all = false;
clear_global = true;
}
else if (!strcmp(argv[arg], "onlymacro"))
only_macro = true;
else if (strlen(argv[arg]) >= 9 && !strncmp(argv[arg], "savemacro", 9))
{
save_macro = true;
if (strlen(argv[arg]) > 9)
{
if (strlen(argv[arg]) == 10 || argv[arg][9] != '=')
{
cerr << "Incorrect syntax for savemacro option" << endl;
usage();
}
save_macro_file = string(argv[arg] + 10);
}
}
else if (!strcmp(argv[arg], "nolinemacro"))
no_line_macro = true;
else if (!strcmp(argv[arg], "noemptylinemacro"))
no_empty_line_macro = true;
else if (!strcmp(argv[arg], "notmpterms"))
no_tmp_terms = true;
else if (!strcmp(argv[arg], "nolog"))
no_log = true;
else if (!strcmp(argv[arg], "nowarn"))
no_warn = true;
else if (!strcmp(argv[arg], "warn_uninit"))
warn_uninit = true;
else if (!strcmp(argv[arg], "console"))
console = true;
else if (!strcmp(argv[arg], "nograph"))
nograph = true;
else if (!strcmp(argv[arg], "nointeractive"))
nointeractive = true;
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
else if (!strcmp(argv[arg], "cygwin"))
cygwin = true;
else if (!strcmp(argv[arg], "msvc"))
msvc = true;
else if (!strcmp(argv[arg], "mingw"))
mingw = true;
#endif
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "conffile", 8))
{
if (strlen(argv[arg]) <= 9 || argv[arg][8] != '=')
{
cerr << "Incorrect syntax for conffile option" << endl;
usage();
}
parallel_config_file = string(argv[arg] + 9);
}
else if (!strcmp(argv[arg], "parallel_slave_open_mode"))
parallel_slave_open_mode = true;
else if (!strcmp(argv[arg], "parallel_test"))
parallel_test = true;
else if (!strcmp(argv[arg], "nostrict"))
nostrict = true;
else if (!strcmp(argv[arg], "stochastic"))
stochastic = true;
else if (!strcmp(argv[arg], "fast"))
check_model_changes = true;
else if (!strcmp(argv[arg], "minimal_workspace"))
minimal_workspace = true;
else if (!strcmp(argv[arg], "compute_xrefs"))
compute_xrefs = true;
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "parallel", 8))
{
parallel = true;
if (strlen(argv[arg]) > 8)
{
if (strlen(argv[arg]) == 9 || argv[arg][8] != '=')
{
cerr << "Incorrect syntax for parallel option" << endl;
usage();
}
cluster_name = string(argv[arg] + 9);
}
}
else if (strlen(argv[arg]) >= 2 && !strncmp(argv[arg], "-D", 2))
{
if (strlen(argv[arg]) == 2)
{
cerr << "Incorrect syntax for command line define: the defined variable "
<< "must not be separated from -D by whitespace." << endl;
usage();
}
size_t equal_index = string(argv[arg]).find('=');
if (equal_index != string::npos)
{
string key = string(argv[arg]).erase(equal_index).erase(0, 2);
defines[key] = string(argv[arg]).erase(0, equal_index+1);
}
else
{
string key = string(argv[arg]).erase(0, 2);
defines[key] = "1";
}
}
else if (strlen(argv[arg]) >= 2 && !strncmp(argv[arg], "-I", 2))
{
if (strlen(argv[arg]) == 2)
{
cerr << "Incorrect syntax for command line define: the defined variable "
<< "must not be separated from -I by whitespace." << endl;
usage();
}
path.push_back(string(argv[arg]).erase(0, 2));
}
else if (strlen(argv[arg]) >= 6 && !strncmp(argv[arg], "output", 6))
{
if (strlen(argv[arg]) <= 7 || argv[arg][6] != '=')
{
cerr << "Incorrect syntax for output option" << endl;
usage();
}
if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 7, "dynamic", 7))
output_mode = dynamic;
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "first", 5))
output_mode = first;
else if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 7, "second", 6))
output_mode = second;
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "third", 5))
output_mode = third;
else
{
cerr << "Incorrect syntax for output option" << endl;
usage();
}
}
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "language", 8))
{
if (strlen(argv[arg]) <= 9 || argv[arg][8] != '=')
{
cerr << "Incorrect syntax for language option" << endl;
usage();
}
if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 9, "julia", 5))
language = julia;
else
{
// we don't want temp terms in external functions (except Julia)
no_tmp_terms = true;
if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 9, "C", 1))
language = c;
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 9, "C++", 3))
language = cpp;
else if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 9, "cuda", 4))
language = cuda;
else if (strlen(argv[arg]) == 15 && !strncmp(argv[arg] + 9, "python", 6))
language = python;
else
{
cerr << "Incorrect syntax for language option" << endl;
usage();
}
}
}
else if (!strcmp(argv[arg], "jsonstdout"))
json_output_mode = standardout;
else if (!strcmp(argv[arg], "onlyjson"))
onlyjson = true;
else if (!strcmp(argv[arg], "nopreprocessoroutput"))
nopreprocessoroutput = true;
else if (!strcmp(argv[arg], "jsonderivsimple"))
jsonderivsimple = true;
else if (strlen(argv[arg]) >= 4 && !strncmp(argv[arg], "json", 4))
{
if (strlen(argv[arg]) <= 5 || argv[arg][4] != '=')
{
cerr << "Incorrect syntax for json option" << endl;
usage();
}
if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 5, "parse", 5))
json = parsing;
else if (strlen(argv[arg]) == 10 && !strncmp(argv[arg] + 5, "check", 5))
json = checkpass;
else if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 5, "transform", 9))
json = transformpass;
else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 5, "compute", 7))
json = computingpass;
else
{
cerr << "Incorrect syntax for json option" << endl;
usage();
}
}
else
{
cerr << "Unknown option: " << argv[arg] << endl;
usage();
}
}
if (!nopreprocessoroutput)
cout << "Starting Dynare (version " << PACKAGE_VERSION << ")." << endl
<< "Starting preprocessing of the model file ..." << endl;
// Construct basename (i.e. remove file extension if there is one)
string basename = argv[1];
string modfile, modfiletxt;
size_t fsc = basename.find_first_of(';');
if (fsc != string::npos)
{
// If a semicolon is found in argv[1], treat it as the text of the modfile
modfile = "mod_file_passed_as_string.mod";
basename = "mod_file_passed_as_string";
modfiletxt = argv[1];
}
else
{
// If a semicolon is NOT found in argv[1], treat it as the name of the modfile
modfile = argv[1];
size_t pos = basename.find_last_of('.');
if (pos != string::npos)
basename.erase(pos);
ifstream modfile(argv[1], ios::binary);
if (modfile.fail())
{
cerr << "ERROR: Could not open file: " << argv[1] << endl;
exit(EXIT_FAILURE);
}
stringstream buffer;
buffer << modfile.rdbuf();
modfiletxt = buffer.str();
}
WarningConsolidation warnings(no_warn);
// Process config file
ConfigFile config_file(parallel, parallel_test, parallel_slave_open_mode, cluster_name);
config_file.getConfigFileInfo(parallel_config_file);
config_file.checkPass(warnings);
config_file.transformPass();
// If Include option was passed to the [paths] block of the config file, add
// it to paths before macroprocessing
vector<string> config_include_paths = config_file.getIncludePaths();
for (vector<string>::const_iterator it = config_include_paths.begin();
it != config_include_paths.end(); it++)
path.push_back(*it);
// Do macro processing
stringstream macro_output;
main1(modfile, basename, modfiletxt, debug, save_macro, save_macro_file, no_line_macro, no_empty_line_macro,
defines, path, macro_output);
if (only_macro)
return EXIT_SUCCESS;
// Do the rest
main2(macro_output, basename, debug, clear_all, clear_global,
no_tmp_terms, no_log, no_warn, warn_uninit, console, nograph, nointeractive,
parallel, config_file, warnings, nostrict, stochastic, check_model_changes, minimal_workspace,
compute_xrefs, output_mode, language, params_derivs_order
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
, cygwin, msvc, mingw
#endif
, json, json_output_mode, onlyjson, jsonderivsimple, nopreprocessoroutput
);
return EXIT_SUCCESS;
}

View File

@ -1,54 +0,0 @@
/*
* Copyright (C) 2015-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <fstream>
#include "macro/MacroDriver.hh"
bool compareNewline (int i, int j) {
return i == '\n' && j == '\n';
}
void
main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file,
bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream &macro_output)
{
// Do macro processing
MacroDriver m;
m.parse(modfile, basename, modfiletxt, macro_output, debug, no_line_macro, defines, path);
if (save_macro)
{
if (save_macro_file.empty())
save_macro_file = basename + "-macroexp.mod";
ofstream macro_output_file(save_macro_file.c_str());
if (macro_output_file.fail())
{
cerr << "Cannot open " << save_macro_file << " for macro output" << endl;
exit(EXIT_FAILURE);
}
string str (macro_output.str());
if (no_empty_line_macro)
str.erase(unique(str.begin(), str.end(), compareNewline), str.end());
macro_output_file << str;
macro_output_file.close();
}
}

View File

@ -1,82 +0,0 @@
/*
* Copyright (C) 2008-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include "ParsingDriver.hh"
#include "ModFile.hh"
#include "ConfigFile.hh"
#include "ExtendedPreprocessorTypes.hh"
void
main2(stringstream &in, string &basename, bool debug, bool clear_all, bool clear_global,
bool no_tmp_terms, bool no_log, bool no_warn, bool warn_uninit, bool console,
bool nograph, bool nointeractive, bool parallel, ConfigFile &config_file,
WarningConsolidation &warnings, bool nostrict, bool stochastic, bool check_model_changes,
bool minimal_workspace, bool compute_xrefs, FileOutputType output_mode,
LanguageOutputType language, int params_derivs_order
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
, bool cygwin, bool msvc, bool mingw
#endif
, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, bool jsonderivsimple
, bool nopreprocessoroutput
)
{
ParsingDriver p(warnings, nostrict);
// Do parsing and construct internal representation of mod file
ModFile *mod_file = p.parse(in, debug);
if (json == parsing)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
// Run checking pass
mod_file->checkPass(nostrict, stochastic);
if (json == checkpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
// Perform transformations on the model (creation of auxiliary vars and equations)
mod_file->transformPass(nostrict, stochastic, compute_xrefs || json == transformpass, nopreprocessoroutput);
if (json == transformpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput);
// Evaluate parameters initialization, initval, endval and pounds
mod_file->evalAllExpressions(warn_uninit, nopreprocessoroutput);
// Do computations
mod_file->computingPass(no_tmp_terms, output_mode, params_derivs_order, nopreprocessoroutput);
if (json == computingpass)
mod_file->writeJsonOutput(basename, json, json_output_mode, onlyjson, nopreprocessoroutput, jsonderivsimple);
// Write outputs
if (output_mode != none)
mod_file->writeExternalFiles(basename, output_mode, language, nopreprocessoroutput);
else
mod_file->writeOutputFiles(basename, clear_all, clear_global, no_log, no_warn, console, nograph,
nointeractive, config_file, check_model_changes, minimal_workspace, compute_xrefs
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
, cygwin, msvc, mingw
#endif
, nopreprocessoroutput
);
delete mod_file;
if (!nopreprocessoroutput)
cout << "Preprocessing completed." << endl;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) 2014-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EXTENDED_PREPROCESSOR_TYPES_HH
#define _EXTENDED_PREPROCESSOR_TYPES_HH
enum FileOutputType
{
none, // outputs files for Matlab/Octave processing
dynamic, // outputs <fname>_dynamic.* and related files
first, // outputs <fname>_first_derivatives.* and related files
second, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.* and related files
third, // outputs <fname>_first_derivatives.*, <fname>_second_derivatives.*, <fname>_third_derivatives.* and related files
};
enum LanguageOutputType
{
matlab, // outputs files for Matlab/Octave processing
c, // outputs files for C
cpp, // outputs files for C++
cuda, // outputs files for CUDA (not yet implemented)
julia, // outputs files for Julia
python, // outputs files for Python (not yet implemented) (not yet implemented)
};
enum JsonFileOutputType
{
file, // output JSON files to file
standardout, // output JSON files to stdout
};
enum JsonOutputPointType
{
nojson, // don't output JSON
parsing, // output JSON after the parsing step
checkpass, // output JSON after the check pass
transformpass, // output JSON after the transform pass
computingpass // output JSON after the computing pass
};
#endif

View File

@ -1,117 +0,0 @@
/*
* Copyright (C) 2010-2015 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <cerrno>
#include <cmath>
#include <iostream>
#include "ExternalFunctionsTable.hh"
#include "SymbolTable.hh"
ExternalFunctionsTable::ExternalFunctionsTable()
{
}
void
ExternalFunctionsTable::addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs)
{
assert(symb_id >= 0);
assert(external_function_options_arg.nargs > 0);
// Change options to be saved so the table is consistent
external_function_options external_function_options_chng = external_function_options_arg;
if (external_function_options_arg.firstDerivSymbID == eExtFunSetButNoNameProvided)
external_function_options_chng.firstDerivSymbID = symb_id;
if (external_function_options_arg.secondDerivSymbID == eExtFunSetButNoNameProvided)
external_function_options_chng.secondDerivSymbID = symb_id;
if (!track_nargs)
external_function_options_chng.nargs = eExtFunNotSet;
// Ensure 1st & 2nd deriv option consistency
if (external_function_options_chng.secondDerivSymbID == symb_id
&& external_function_options_chng.firstDerivSymbID != symb_id)
{
cerr << "ERROR: If the second derivative is provided by the top-level function "
<< "the first derivative must also be provided by the same function." << endl;
exit(EXIT_FAILURE);
}
if ((external_function_options_chng.secondDerivSymbID != symb_id
&& external_function_options_chng.firstDerivSymbID == symb_id)
&& external_function_options_chng.secondDerivSymbID != eExtFunNotSet)
{
cerr << "ERROR: If the first derivative is provided by the top-level function, the "
<< "second derivative cannot be provided by any other external function." << endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID != eExtFunNotSet
&& external_function_options_chng.firstDerivSymbID == eExtFunNotSet)
{
cerr << "ERROR: If the second derivative is provided, the first derivative must also be provided." << endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID == external_function_options_chng.firstDerivSymbID
&& external_function_options_chng.firstDerivSymbID != symb_id
&& external_function_options_chng.firstDerivSymbID != eExtFunNotSet)
{
cerr << "ERROR: If the Jacobian and Hessian are provided by the same function, that "
<< "function must be the top-level function." << endl;
exit(EXIT_FAILURE);
}
// Ensure that if we're overwriting something, we mean to do it
if (exists(symb_id))
{
bool ok_to_overwrite = false;
if (getNargs(symb_id) == eExtFunNotSet) // implies that the information stored about this function is not important
ok_to_overwrite = true;
if (!ok_to_overwrite) // prevents multiple non-compatible calls to external_function(name=funcname)
{ // e.g. e_f(name=a,nargs=1,fd,sd) and e_f(name=a,nargs=2,fd=b,sd=c) should cause an error
if (external_function_options_chng.nargs != getNargs(symb_id))
{
cerr << "ERROR: The number of arguments passed to the external_function() statement do not "
<< "match the number of arguments passed to a previous call or declaration of the top-level function."<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.firstDerivSymbID != getFirstDerivSymbID(symb_id))
{
cerr << "ERROR: The first derivative function passed to the external_function() statement does not "
<< "match the first derivative function passed to a previous call or declaration of the top-level function."<< endl;
exit(EXIT_FAILURE);
}
if (external_function_options_chng.secondDerivSymbID != getSecondDerivSymbID(symb_id))
{
cerr << "ERROR: The second derivative function passed to the external_function() statement does not "
<< "match the second derivative function passed to a previous call or declaration of the top-level function."<< endl;
exit(EXIT_FAILURE);
}
}
}
externalFunctionTable[symb_id] = external_function_options_chng;
}

View File

@ -1,127 +0,0 @@
/*
* Copyright (C) 2010-2015 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EXTERNALFUNCTIONSTABLE_HH
#define _EXTERNALFUNCTIONSTABLE_HH
using namespace std;
#include <iostream>
#include <string>
#include <vector>
#include <map>
enum ExternalFunctionSetOrNot
{
eExtFunSetButNoNameProvided = -2, //! Signifies that the derivative is obtained from the top-level function
eExtFunNotSet = -1, //! Signifies that no external function exists that calculates the derivative
eExtFunSetDefaultNargs = 1 //! This is the default number of arguments when nargs is not specified
};
//! Handles external functions
class ExternalFunctionsTable
{
public:
//! Thrown when trying to access an unknown symbol (by id)
class UnknownExternalFunctionSymbolIDException
{
public:
//! Symbol ID
int id;
UnknownExternalFunctionSymbolIDException(int id_arg) : id(id_arg)
{
}
};
/* For all arguments, -2 means not set
* For firstDerivSymbID and secondDerivSymbID, -1 means that the derivatives are
* provided in the main function given in the by the "name" option to the
* external_function() statement.
*/
struct external_function_options
{
int nargs, firstDerivSymbID, secondDerivSymbID;
};
typedef map<int, external_function_options> external_function_table_type;
private:
//! Map containing options provided to external_functions()
external_function_table_type externalFunctionTable;
public:
ExternalFunctionsTable();
//! Adds an external function to the table as well as its derivative functions
void addExternalFunction(int symb_id, const external_function_options &external_function_options_arg, bool track_nargs);
//! See if the function exists in the External Functions Table
inline bool exists(int symb_id) const;
//! Get the number of arguments for a given external function
inline int getNargs(int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
//! Get the symbol_id of the first derivative function
inline int getFirstDerivSymbID(int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
//! Get the symbol_id of the second derivative function
inline int getSecondDerivSymbID(int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
//! Returns the total number of unique external functions declared or used in the .mod file
inline int get_total_number_of_unique_model_block_external_functions() const;
};
inline bool
ExternalFunctionsTable::exists(int symb_id) const
{
external_function_table_type::const_iterator iter = externalFunctionTable.find(symb_id);
return (iter != externalFunctionTable.end());
}
inline int
ExternalFunctionsTable::getNargs(int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.nargs;
else
throw UnknownExternalFunctionSymbolIDException(symb_id);
}
inline int
ExternalFunctionsTable::getFirstDerivSymbID(int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.firstDerivSymbID;
else
throw UnknownExternalFunctionSymbolIDException(symb_id);
}
inline int
ExternalFunctionsTable::getSecondDerivSymbID(int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
{
if (exists(symb_id))
return externalFunctionTable.find(symb_id)->second.secondDerivSymbID;
else
throw UnknownExternalFunctionSymbolIDException(symb_id);
}
inline int
ExternalFunctionsTable::get_total_number_of_unique_model_block_external_functions() const
{
int number_of_unique_model_block_external_functions = 0;
for (external_function_table_type::const_iterator it = externalFunctionTable.begin();
it != externalFunctionTable.end(); it++)
if (it->second.nargs > 0)
number_of_unique_model_block_external_functions++;
return number_of_unique_model_block_external_functions;
}
#endif

View File

@ -1,95 +0,0 @@
SUBDIRS = macro
BUILT_SOURCES = DynareBison.hh stack.hh position.hh location.hh DynareBison.cc DynareFlex.cc FlexLexer.h
matlabdir = $(pkglibdir)/matlab
matlab_PROGRAMS = dynare_m
# We don't put BUILT_SOURCES in dynare_m_SOURCES, otherwise DynareBison.o and DynareFlex.o will be linked two times (Automake translates DynareFlex.ll and DynareBison.yy into their respective .o); so BUILT_SOURCES is in EXTRA_DIST
dynare_m_SOURCES = \
DynareFlex.ll \
DynareBison.yy \
ComputingTasks.cc \
ComputingTasks.hh \
ModelTree.cc \
ModelTree.hh \
StaticModel.cc \
StaticModel.hh \
DynamicModel.cc \
DynamicModel.hh \
NumericalConstants.cc \
NumericalConstants.hh \
NumericalInitialization.cc \
NumericalInitialization.hh \
Shocks.cc \
Shocks.hh \
SigmaeInitialization.cc \
SigmaeInitialization.hh \
SymbolTable.cc \
SymbolTable.hh \
SymbolList.cc \
SymbolList.hh \
ParsingDriver.cc \
ParsingDriver.hh \
DataTree.cc \
DataTree.hh \
ModFile.cc \
ModFile.hh \
ConfigFile.cc \
ConfigFile.hh \
Statement.cc \
Statement.hh \
ExprNode.cc \
ExprNode.hh \
MinimumFeedbackSet.cc \
MinimumFeedbackSet.hh \
DynareMain.cc \
DynareMain1.cc \
DynareMain2.cc \
CodeInterpreter.hh \
ExternalFunctionsTable.cc \
ExternalFunctionsTable.hh \
SteadyStateModel.hh \
SteadyStateModel.cc \
WarningConsolidation.hh \
WarningConsolidation.cc \
ExtendedPreprocessorTypes.hh
# The -I. is for <FlexLexer.h>
dynare_m_CPPFLAGS = $(BOOST_CPPFLAGS) -I.
dynare_m_LDFLAGS = $(BOOST_LDFLAGS)
dynare_m_LDADD = macro/libmacro.a
DynareFlex.cc FlexLexer.h: DynareFlex.ll
$(LEX) -o DynareFlex.cc DynareFlex.ll
cp $(LEXINC)/FlexLexer.h . || test -f ./FlexLexer.h
DynareBison.cc DynareBison.hh location.hh stack.hh position.hh: DynareBison.yy
$(YACC) -o DynareBison.cc DynareBison.yy
all-local: $(PROGRAMS)
if [ -z "`file $(PROGRAMS) | grep x86.64`" ]; then \
ARCH="32"; \
else \
ARCH="64"; \
fi; \
mkdir -p ../matlab/preprocessor$$ARCH ; \
cd ../matlab/preprocessor$$ARCH && $(LN_S) -f $(abs_srcdir)/$(PROGRAMS) $(PROGRAMS) ; \
mkdir -p ../../julia/preprocessor$$ARCH ; \
cd ../../julia/preprocessor$$ARCH && $(LN_S) -f $(abs_srcdir)/$(PROGRAMS) $(PROGRAMS)
if HAVE_DOXYGEN
html-local:
$(DOXYGEN)
endif
clean-local:
rm -rf ../matlab/preprocessor* ../julia/preprocessor*
rm -rf doc/html/
EXTRA_DIST = $(BUILT_SOURCES) Doxyfile
install-exec-local:
$(MKDIR_P) $(DESTDIR)$(pkglibdir)/matlab

View File

@ -1,457 +0,0 @@
/*
* Copyright (C) 2009-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include "MinimumFeedbackSet.hh"
namespace MFS
{
void
Suppress(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G)
{
clear_vertex(vertex_to_eliminate, G);
remove_vertex(vertex_to_eliminate, G);
}
void
Suppress(int vertex_num, AdjacencyList_t &G)
{
Suppress(vertex(vertex_num, G), G);
}
void
Eliminate(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G)
{
if (in_degree(vertex_to_eliminate, G) > 0 && out_degree(vertex_to_eliminate, G) > 0)
{
AdjacencyList_t::in_edge_iterator it_in, in_end;
AdjacencyList_t::out_edge_iterator it_out, out_end;
for (tie(it_in, in_end) = in_edges(vertex_to_eliminate, G); it_in != in_end; ++it_in)
for (tie(it_out, out_end) = out_edges(vertex_to_eliminate, G); it_out != out_end; ++it_out)
{
AdjacencyList_t::edge_descriptor ed;
bool exist;
tie(ed, exist) = edge(source(*it_in, G), target(*it_out, G), G);
if (!exist)
add_edge(source(*it_in, G), target(*it_out, G), G);
}
}
Suppress(vertex_to_eliminate, G);
}
bool
has_cycle_dfs(AdjacencyList_t &g, AdjacencyList_t::vertex_descriptor u, color_t &color, vector<int> &circuit_stack)
{
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, g);
color[u] = gray_color;
graph_traits<AdjacencyList_t>::out_edge_iterator vi, vi_end;
for (tie(vi, vi_end) = out_edges(u, g); vi != vi_end; ++vi)
if (color[target(*vi, g)] == white_color && has_cycle_dfs(g, target(*vi, g), color, circuit_stack))
{
// cycle detected, return immediately
circuit_stack.push_back(v_index[target(*vi, g)]);
return true;
}
else if (color[target(*vi, g)] == gray_color)
{
// *vi is an ancestor!
circuit_stack.push_back(v_index[target(*vi, g)]);
return true;
}
color[u] = black_color;
return false;
}
bool
has_cycle(vector<int> &circuit_stack, AdjacencyList_t &g)
{
// Initialize color map to white
color_t color;
graph_traits<AdjacencyList_t>::vertex_iterator vi, vi_end;
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
color[*vi] = white_color;
// Perform depth-first search
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
if (color[*vi] == white_color && has_cycle_dfs(g, *vi, color, circuit_stack))
return true;
return false;
}
void
Print(AdjacencyList_t &G)
{
AdjacencyList_t::vertex_iterator it, it_end;
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "Graph\n";
cout << "-----\n";
for (tie(it, it_end) = vertices(G); it != it_end; ++it)
{
cout << "vertex[" << v_index[*it] + 1 << "] <-";
AdjacencyList_t::in_edge_iterator it_in, in_end;
for (tie(it_in, in_end) = in_edges(*it, G); it_in != in_end; ++it_in)
cout << v_index[source(*it_in, G)] + 1 << " ";
cout << "\n ->";
AdjacencyList_t::out_edge_iterator it_out, out_end;
for (tie(it_out, out_end) = out_edges(*it, G); it_out != out_end; ++it_out)
cout << v_index[target(*it_out, G)] + 1 << " ";
cout << "\n";
}
}
AdjacencyList_t
AM_2_AdjacencyList(bool *AM, unsigned int n)
{
AdjacencyList_t G(n);
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
for (unsigned int i = 0; i < n; i++)
{
put(v_index, vertex(i, G), i);
put(v_index1, vertex(i, G), i);
}
for (unsigned int i = 0; i < n; i++)
for (unsigned int j = 0; j < n; j++)
if (AM[i*n+j])
add_edge(vertex(j, G), vertex(i, G), G);
return G;
}
AdjacencyList_t
extract_subgraph(AdjacencyList_t &G1, set<int> select_index)
{
unsigned int n = select_index.size();
AdjacencyList_t G(n);
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
property_map<AdjacencyList_t, vertex_index_t>::type v1_index = get(vertex_index, G1);
map<int, int> reverse_index;
set<int>::iterator it;
unsigned int i;
for (it = select_index.begin(), i = 0; i < n; i++, ++it)
{
reverse_index[get(v1_index, vertex(*it, G1))] = i;
put(v_index, vertex(i, G), get(v1_index, vertex(*it, G1)));
put(v_index1, vertex(i, G), i);
}
for (it = select_index.begin(), i = 0; i < n; i++, ++it)
{
AdjacencyList_t::out_edge_iterator it_out, out_end;
AdjacencyList_t::vertex_descriptor vi = vertex(*it, G1);
for (tie(it_out, out_end) = out_edges(vi, G1); it_out != out_end; ++it_out)
{
int ii = v1_index[target(*it_out, G1)];
if (select_index.find(ii) != select_index.end())
add_edge(vertex(reverse_index[get(v1_index, source(*it_out, G1))], G), vertex(reverse_index[get(v1_index, target(*it_out, G1))], G), G);
}
}
return G;
}
vector_vertex_descriptor_t
Collect_Doublet(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G)
{
AdjacencyList_t::in_edge_iterator it_in, in_end;
AdjacencyList_t::out_edge_iterator it_out, out_end;
vector<AdjacencyList_t::vertex_descriptor> Doublet;
if (in_degree(vertex, G) > 0 && out_degree(vertex, G) > 0)
for (tie(it_in, in_end) = in_edges(vertex, G); it_in != in_end; ++it_in)
for (tie(it_out, out_end) = out_edges(vertex, G); it_out != out_end; ++it_out)
if (source(*it_in, G) == target(*it_out, G) && source(*it_in, G) != target(*it_in, G)) // not a loop
Doublet.push_back(source(*it_in, G));
return Doublet;
}
bool
Vertex_Belong_to_a_Clique(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G)
{
vector<AdjacencyList_t::vertex_descriptor> liste;
bool agree = true;
AdjacencyList_t::in_edge_iterator it_in, in_end;
AdjacencyList_t::out_edge_iterator it_out, out_end;
tie(it_in, in_end) = in_edges(vertex, G);
tie(it_out, out_end) = out_edges(vertex, G);
while (it_in != in_end && it_out != out_end && agree)
{
agree = (source(*it_in, G) == target(*it_out, G) && source(*it_in, G) != target(*it_in, G)); //not a loop
liste.push_back(source(*it_in, G));
++it_in;
++it_out;
}
if (agree)
{
if (it_in != in_end || it_out != out_end)
agree = false;
unsigned int i = 1;
while (i < liste.size() && agree)
{
unsigned int j = i + 1;
while (j < liste.size() && agree)
{
AdjacencyList_t::edge_descriptor ed;
bool exist1, exist2;
tie(ed, exist1) = edge(liste[i], liste[j], G);
tie(ed, exist2) = edge(liste[j], liste[i], G);
agree = (exist1 && exist2);
j++;
}
i++;
}
}
return agree;
}
bool
Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(AdjacencyList_t &G)
{
bool something_has_been_done = false;
bool not_a_loop;
int i;
AdjacencyList_t::vertex_iterator it, it1, ita, it_end;
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
{
int in_degree_n = in_degree(*it, G);
int out_degree_n = out_degree(*it, G);
if (in_degree_n <= 1 || out_degree_n <= 1)
{
not_a_loop = true;
if (in_degree_n >= 1 && out_degree_n >= 1) // Do not eliminate a vertex if it loops on itself!
{
AdjacencyList_t::in_edge_iterator it_in, in_end;
for (tie(it_in, in_end) = in_edges(*it, G); it_in != in_end; ++it_in)
if (source(*it_in, G) == target(*it_in, G))
{
#ifdef verbose
cout << v_index[source(*it_in, G)] << " == " << v_index[target(*it_in, G)] << "\n";
#endif
not_a_loop = false;
}
}
if (not_a_loop)
{
#ifdef verbose
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "->eliminate vertex[" << v_index[*it] + 1 << "]\n";
#endif
Eliminate(*it, G);
#ifdef verbose
Print(G);
#endif
something_has_been_done = true;
if (i > 0)
it = ita;
else
{
tie(it, it_end) = vertices(G);
i--;
}
}
}
ita = it;
}
return something_has_been_done;
}
bool
Elimination_of_Vertex_belonging_to_a_clique_Step(AdjacencyList_t &G)
{
AdjacencyList_t::vertex_iterator it, it1, ita, it_end;
bool something_has_been_done = false;
int i;
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
{
if (Vertex_Belong_to_a_Clique(*it, G))
{
#ifdef verbose
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "eliminate vertex[" << v_index[*it] + 1 << "]\n";
#endif
Eliminate(*it, G);
something_has_been_done = true;
if (i > 0)
it = ita;
else
{
tie(it, it_end) = vertices(G);
i--;
}
}
ita = it;
}
return something_has_been_done;
}
bool
Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(set<int> &feed_back_vertices, AdjacencyList_t &G)
{
bool something_has_been_done = false;
AdjacencyList_t::vertex_iterator it, it_end, ita;
int i = 0;
for (tie(it, it_end) = vertices(G); it != it_end; ++it, i++)
{
AdjacencyList_t::edge_descriptor ed;
bool exist;
tie(ed, exist) = edge(*it, *it, G);
if (exist)
{
#ifdef verbose
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "store v[*it] = " << v_index[*it]+1 << "\n";
#endif
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
feed_back_vertices.insert(v_index1[*it]);
/*property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
feed_back_vertices.insert(v_index[*it] );*/
Suppress(*it, G);
something_has_been_done = true;
if (i > 0)
it = ita;
else
{
tie(it, it_end) = vertices(G);
i--;
}
}
ita = it;
}
return something_has_been_done;
}
AdjacencyList_t
Minimal_set_of_feedback_vertex(set<int> &feed_back_vertices, const AdjacencyList_t &G1)
{
bool something_has_been_done = true;
int cut_ = 0;
feed_back_vertices.clear();
AdjacencyList_t G(G1);
while (num_vertices(G) > 0)
{
while (something_has_been_done && num_vertices(G) > 0)
{
//Rule 1
something_has_been_done = (Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(G) /*or something_has_been_done*/);
#ifdef verbose
cout << "1 something_has_been_done=" << something_has_been_done << "\n";
#endif
//Rule 2
something_has_been_done = (Elimination_of_Vertex_belonging_to_a_clique_Step(G) || something_has_been_done);
#ifdef verbose
cout << "2 something_has_been_done=" << something_has_been_done << "\n";
#endif
//Rule 3
something_has_been_done = (Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(feed_back_vertices, G) || something_has_been_done);
#ifdef verbose
cout << "3 something_has_been_done=" << something_has_been_done << "\n";
#endif
}
vector<int> circuit;
if (!has_cycle(circuit, G))
{
#ifdef verbose
cout << "has_cycle=false\n";
#endif
//sort(feed_back_vertices.begin(), feed_back_vertices.end());
return G;
}
if (num_vertices(G) > 0)
{
/*if nothing has been done in the five previous rule then cut the vertex with the maximum in_degree+out_degree*/
unsigned int max_degree = 0, num = 0;
AdjacencyList_t::vertex_iterator it, it_end, max_degree_index;
for (tie(it, it_end) = vertices(G); it != it_end; ++it, num++)
{
if (in_degree(*it, G) + out_degree(*it, G) > max_degree)
{
max_degree = in_degree(*it, G) + out_degree(*it, G);
max_degree_index = it;
}
}
property_map<AdjacencyList_t, vertex_index1_t>::type v_index1 = get(vertex_index1, G);
feed_back_vertices.insert(v_index1[*max_degree_index]);
/*property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
feed_back_vertices.insert(v_index[*max_degree_index]);*/
//cout << "v_index1[*max_degree_index] = " << v_index1[*max_degree_index] << "\n";
cut_++;
#ifdef verbose
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
cout << "--> cut vertex " << v_index[*max_degree_index] + 1 << "\n";
#endif
Suppress(*max_degree_index, G);
something_has_been_done = true;
}
}
#ifdef verbose
cout << "cut_=" << cut_ << "\n";
#endif
//sort(feed_back_vertices.begin(), feed_back_vertices.end());
return G;
}
struct rev
{
bool
operator()(const int a, const int b) const
{
return (a > b);
}
};
void
Reorder_the_recursive_variables(const AdjacencyList_t &G1, set<int> &feedback_vertices, vector< int> &Reordered_Vertices)
{
AdjacencyList_t G(G1);
property_map<AdjacencyList_t, vertex_index_t>::type v_index = get(vertex_index, G);
set<int>::iterator its, ita;
set<int, rev> fv;
for (its = feedback_vertices.begin(); its != feedback_vertices.end(); its++)
fv.insert(*its);
int i = 0;
for (its = fv.begin(); its != fv.end(); ++its, i++)
Suppress(*its, G);
bool something_has_been_done = true;
while (something_has_been_done)
{
something_has_been_done = false;
AdjacencyList_t::vertex_iterator it, it_end, ita;
for (tie(it, it_end) = vertices(G), i = 0; it != it_end; ++it, i++)
{
if (in_degree(*it, G) == 0)
{
Reordered_Vertices.push_back(v_index[*it]);
Suppress(*it, G);
something_has_been_done = true;
if (i > 0)
it = ita;
else
{
tie(it, it_end) = vertices(G);
i--;
}
}
ita = it;
}
}
if (num_vertices(G))
cout << "Error in the computation of feedback vertex set\n";
}
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (C) 2009-2010 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MINIMUMFEEDBACKSET_HH
#define _MINIMUMFEEDBACKSET_HH
#include <map>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
using namespace std;
using namespace boost;
namespace MFS
{
typedef property<vertex_index_t, int,
property<vertex_index1_t, int,
property<vertex_degree_t, int,
property<vertex_in_degree_t, int,
property<vertex_out_degree_t, int > > > > > VertexProperty_t;
typedef adjacency_list<listS, listS, bidirectionalS, VertexProperty_t> AdjacencyList_t;
typedef map<graph_traits<AdjacencyList_t>::vertex_descriptor, default_color_type> color_t;
typedef vector<AdjacencyList_t::vertex_descriptor> vector_vertex_descriptor_t;
//! Eliminate a vertex i
/*! For a vertex i replace all edges e_k_i and e_i_j by a shorcut e_k_j and then Suppress the vertex i*/
void Eliminate(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G);
//! Collect all doublets (edges e_i_k such that there is an edge e_k_i with k!=i in the graph)
/*! Returns the vector of doublets */
vector_vertex_descriptor_t Collect_Doublet(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G);
//! Detect all the clique (all vertex in a clique are related to each other) in the graph
bool Vertex_Belong_to_a_Clique(AdjacencyList_t::vertex_descriptor vertex, AdjacencyList_t &G);
//! Graph reduction: eliminating purely intermediate variables or variables outside of any circuit
bool Elimination_of_Vertex_With_One_or_Less_Indegree_or_Outdegree_Step(AdjacencyList_t &G);
//! Graph reduction: elimination of a vertex inside a clique
bool Elimination_of_Vertex_belonging_to_a_clique_Step(AdjacencyList_t &G);
//! A vertex belong to the feedback vertex set if the vertex loops on itself.
/*! We have to suppress this vertex and store it into the feedback set.*/
bool Suppression_of_Vertex_X_if_it_loops_store_in_set_of_feedback_vertex_Step(set<int> &feed_back_vertices, AdjacencyList_t &G1);
//! Print the Graph
void Print(AdjacencyList_t &G);
//! Create an adjacency graph from a Adjacency Matrix (an incidence Matrix without the diagonal terms)
AdjacencyList_t AM_2_AdjacencyList(bool *AMp, unsigned int n);
//! Extracts a subgraph
/*!
\param[in] G1 The original graph
\param[in] select_index The vertex indices to select
\return The subgraph
The property vertex_index of the subgraph contains indices of the original
graph, the property vertex_index1 contains new contiguous indices specific
to the subgraph.
*/
AdjacencyList_t extract_subgraph(AdjacencyList_t &G1, set<int> select_index);
//! Check if the graph contains any cycle (true if the model contains at least one cycle, false otherwise)
bool has_cycle(vector<int> &circuit_stack, AdjacencyList_t &g);
bool has_cycle_dfs(AdjacencyList_t &g, AdjacencyList_t::vertex_descriptor u, color_t &color, vector<int> &circuit_stack);
//! Return the feedback set
AdjacencyList_t Minimal_set_of_feedback_vertex(set<int> &feed_back_vertices, const AdjacencyList_t &G);
//! Clear all in and out edges of vertex_to_eliminate and remove vertex_to_eliminate from the graph
void Suppress(AdjacencyList_t::vertex_descriptor vertex_to_eliminate, AdjacencyList_t &G);
void Suppress(int vertex_num, AdjacencyList_t &G);
//! Reorder the recursive variables
/*! They appear first in a quasi triangular form and they are followed by the feedback variables */
void Reorder_the_recursive_variables(const AdjacencyList_t &G1, set<int> &feedback_vertices, vector< int> &Reordered_Vertices);
};
#endif // _MINIMUMFEEDBACKSET_HH

File diff suppressed because it is too large Load Diff

View File

@ -1,181 +0,0 @@
/*
* Copyright (C) 2006-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MOD_FILE_HH
#define _MOD_FILE_HH
using namespace std;
#include <ostream>
#include <ctime>
#include <iostream>
#include <sstream>
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
#include "NumericalInitialization.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "SteadyStateModel.hh"
#include "Statement.hh"
#include "ExternalFunctionsTable.hh"
#include "ConfigFile.hh"
#include "WarningConsolidation.hh"
#include "ExtendedPreprocessorTypes.hh"
// for checksum computation
#ifndef PRIVATE_BUFFER_SIZE
# define PRIVATE_BUFFER_SIZE 1024
#endif
//! The abstract representation of a "mod" file
class ModFile
{
public:
ModFile(WarningConsolidation &warnings_arg);
~ModFile();
//! Symbol table
SymbolTable symbol_table;
//! External Functions table
ExternalFunctionsTable external_functions_table;
//! Numerical constants table
NumericalConstants num_constants;
//! Expressions outside model block
DataTree expressions_tree;
//! Original model, as declared in the "model" block, that won't be modified by the preprocessor
DynamicModel original_model;
//! Dynamic model, as declared in the "model" block
DynamicModel dynamic_model;
//! A copy of Dynamic model, for testing trends declared by user
DynamicModel trend_dynamic_model;
//! A model in which to create the FOC for the ramsey problem
DynamicModel ramsey_FOC_equations_dynamic_model;
//! A copy of the original model, used to test model linearity under ramsey problem
DynamicModel orig_ramsey_dynamic_model;
//! Static model, as derived from the "model" block when leads and lags have been removed
StaticModel static_model;
//! Static model, as declared in the "steady_state_model" block if present
SteadyStateModel steady_state_model;
//! Option linear
bool linear;
//! Is the model block decomposed?
bool block;
//! Is the model stored in bytecode format (byte_code=true) or in a M-file (byte_code=false)
bool byte_code;
//! Is the model stored in a MEX file ? (option "use_dll" of "model")
bool use_dll;
//! Is the static model have to computed (no_static=false) or not (no_static=true). Option of 'model'
bool no_static;
//! Is the 'differentiate_forward_vars' option used?
bool differentiate_forward_vars;
/*! If the 'differentiate_forward_vars' option is used, contains the set of
endogenous with respect to which to do the transformation;
if empty, means that the transformation must be applied to all endos
with a lead */
vector<string> differentiate_forward_vars_subset;
//! Are nonstationary variables present ?
bool nonstationary_variables;
//! Global evaluation context
/*! Filled using initval blocks and parameters initializations */
eval_context_t global_eval_context;
//! Parameter used with lead/lag
bool param_used_with_lead_lag;
//! Stores the list of extra files to be transefered during a parallel run
/*! (i.e. option parallel_local_files of model block) */
vector<string> parallel_local_files;
private:
//! List of statements
vector<Statement *> statements;
//! Structure of the mod file
ModFileStructure mod_file_struct;
//! Warnings Encountered
WarningConsolidation &warnings;
//! Functions used in writing of JSON outut. See writeJsonOutput
void writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType json_output_mode, bool transformpass, bool computingpass) const;
void writeJsonComputingPassOutput(const string &basename, JsonFileOutputType json_output_mode, bool jsonderivsimple) const;
void writeJsonFileHelper(string &fname, ostringstream &output) const;
public:
//! Add a statement
void addStatement(Statement *st);
//! Add a statement at the front of the statements vector
void addStatementAtFront(Statement *st);
//! Evaluate all the statements
/*! \param warn_uninit Should a warning be displayed for uninitialized endogenous/exogenous/parameters ? */
void evalAllExpressions(bool warn_uninit, const bool nopreprocessoroutput);
//! Do some checking and fills mod_file_struct
/*! \todo add check for number of equations and endogenous if ramsey_policy is present */
void checkPass(bool nostrict, bool stochastic);
//! Perform some transformations on the model (creation of auxiliary vars and equations)
/*! \param compute_xrefs if true, equation cross references will be computed */
void transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const bool nopreprocessoroutput);
//! Execute computations
/*! \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic files */
/*! \param params_derivs_order compute this order of derivs wrt parameters */
void computingPass(bool no_tmp_terms, FileOutputType output, int params_derivs_order, const bool nopreprocessoroutput);
//! Writes Matlab/Octave output files
/*!
\param basename The base name used for writing output files. Should be the name of the mod file without its extension
\param clear_all Should a "clear all" instruction be written to output ?
\param console Are we in console mode ?
\param nograph Should we build the figures?
\param nointeractive Should Dynare request user input?
\param cygwin Should the MEX command of use_dll be adapted for Cygwin?
\param msvc Should the MEX command of use_dll be adapted for MSVC?
\param mingw Should the MEX command of use_dll be adapted for MinGW?
\param compute_xrefs if true, equation cross references will be computed
*/
void writeOutputFiles(const string &basename, bool clear_all, bool clear_global, bool no_log, bool no_warn,
bool console, bool nograph, bool nointeractive, const ConfigFile &config_file,
bool check_model_changes, bool minimal_workspace, bool compute_xrefs
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
, bool cygwin, bool msvc, bool mingw
#endif
, const bool nopreprocessoroutput
) const;
void writeExternalFiles(const string &basename, FileOutputType output, LanguageOutputType language, const bool nopreprocessoroutput) const;
void writeExternalFilesC(const string &basename, FileOutputType output) const;
void writeExternalFilesCC(const string &basename, FileOutputType output) const;
void writeExternalFilesJulia(const string &basename, FileOutputType output, const bool nopreprocessoroutput) const;
//! Writes C output files only => No further Matlab processing
void writeCOutputFiles(const string &basename) const;
void writeModelC(const string &basename) const;
//! Writes Cpp output files only => No further Matlab processing
void writeCCOutputFiles(const string &basename) const;
void writeModelCC(const string &basename) const;
void computeChecksum();
//! Write JSON representation of ModFile object
//! Initially created to enable Julia to work with .mod files
//! Potentially outputs ModFile after the various parts of processing (parsing, checkPass, transformPass, computingPass)
//! Allows user of other host language platforms (python, fortran, etc) to provide support for dynare .mod files
void writeJsonOutput(const string &basename, JsonOutputPointType json, JsonFileOutputType json_output_mode, bool onlyjson, const bool nopreprocessoroutput, bool jsonderivsimple = false);
};
#endif // ! MOD_FILE_HH

File diff suppressed because it is too large Load Diff

View File

@ -1,412 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MODELTREE_HH
#define _MODELTREE_HH
using namespace std;
#include <string>
#include <vector>
#include <deque>
#include <map>
#include <ostream>
#include "DataTree.hh"
#include "ExtendedPreprocessorTypes.hh"
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
typedef vector<pair<EquationType, expr_t > > equation_type_and_normalized_equation_t;
//! Vector describing variables: max_lag in the block, max_lead in the block
typedef vector<pair< int, int> > lag_lead_vector_t;
//! for each block contains pair< pair<Simulation_Type, first_equation>, pair < Block_Size, Recursive_part_Size > >
typedef vector<pair< pair< BlockSimulationType, int>, pair<int, int> > > block_type_firstequation_size_mfs_t;
//! for a block contains derivatives pair< pair<block_equation_number, block_variable_number> , pair<lead_lag, expr_t> >
typedef vector< pair<pair<int, int>, pair< int, expr_t > > > block_derivatives_equation_variable_laglead_nodeid_t;
//! for all blocks derivatives description
typedef vector<block_derivatives_equation_variable_laglead_nodeid_t> blocks_derivatives_t;
//! Shared code for static and dynamic models
class ModelTree : public DataTree
{
friend class DynamicModel;
friend class StaticModel;
protected:
//! Stores declared and generated auxiliary equations
vector<BinaryOpNode *> equations;
//! Stores line numbers of declared equations; -1 means undefined
vector<int> equations_lineno;
//! Only stores generated auxiliary equations, in an order meaningful for evaluation
deque<BinaryOpNode *> aux_equations;
//! Stores equation tags
vector<pair<int, pair<string, string> > > equation_tags;
//! Number of non-zero derivatives
int NNZDerivatives[3];
typedef map<pair<int, int>, expr_t> first_derivatives_t;
//! 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 indices are those of the getDerivID() method.
*/
first_derivatives_t first_derivatives;
typedef map<pair<int, pair<int, int> >, expr_t> second_derivatives_t;
//! Second order derivatives
/*! 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 indices are those of the getDerivID() method.
*/
second_derivatives_t second_derivatives;
typedef map<pair<int, pair<int, pair<int, int> > >, expr_t> third_derivatives_t;
//! Third order derivatives
/*! 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 indices are those of the getDerivID() method.
*/
third_derivatives_t third_derivatives;
//! Derivatives of the residuals w.r. to parameters
/*! First index is equation number, second is parameter.
Only non-null derivatives are stored in the map.
Parameter indices are those of the getDerivID() method.
*/
first_derivatives_t residuals_params_derivatives;
//! Second derivatives of the residuals w.r. to parameters
/*! First index is equation number, second and third indeces are parameters.
Only non-null derivatives are stored in the map.
Parameter indices are those of the getDerivID() method.
*/
second_derivatives_t residuals_params_second_derivatives;
//! Derivatives of the jacobian w.r. to parameters
/*! First index is equation number, second is endo/exo/exo_det variable, and third is parameter.
Only non-null derivatives are stored in the map.
Variable and parameter indices are those of the getDerivID() method.
*/
second_derivatives_t jacobian_params_derivatives;
//! Second derivatives of the jacobian w.r. to parameters
/*! First index is equation number, second is endo/exo/exo_det variable, and third and fourth are parameters.
Only non-null derivatives are stored in the map.
Variable and parameter indices are those of the getDerivID() method.
*/
third_derivatives_t jacobian_params_second_derivatives;
//! Derivatives of the hessian w.r. to parameters
/*! First index is equation number, first and second are endo/exo/exo_det variable, and third is parameter.
Only non-null derivatives are stored in the map.
Variable and parameter indices are those of the getDerivID() method.
*/
third_derivatives_t hessian_params_derivatives;
//! Temporary terms for the static/dynamic file (those which will be noted Txxxx)
temporary_terms_t temporary_terms;
temporary_terms_t temporary_terms_res;
temporary_terms_t temporary_terms_g1;
temporary_terms_t temporary_terms_g2;
temporary_terms_t temporary_terms_g3;
//! Temporary terms for the file containing parameters derivatives
temporary_terms_t params_derivs_temporary_terms;
temporary_terms_t params_derivs_temporary_terms_res;
temporary_terms_t params_derivs_temporary_terms_g1;
temporary_terms_t params_derivs_temporary_terms_res2;
temporary_terms_t params_derivs_temporary_terms_g12;
temporary_terms_t params_derivs_temporary_terms_g2;
//! Trend variables and their growth factors
map<int, expr_t> trend_symbols_map;
//! for all trends; the boolean is true if this is a log-trend, false otherwise
typedef map<int, pair<bool, expr_t> > nonstationary_symbols_map_t;
//! Nonstationary variables and their deflators
nonstationary_symbols_map_t nonstationary_symbols_map;
//! vector of block reordered variables and equations
vector<int> equation_reordered, variable_reordered, inv_equation_reordered, inv_variable_reordered;
//! the file containing the model and the derivatives code
ofstream code_file;
//! Computes 1st derivatives
/*! \param vars the derivation IDs w.r. to which compute the derivatives */
void computeJacobian(const set<int> &vars);
//! Computes 2nd derivatives
/*! \param vars the derivation IDs w.r. to which derive the 1st derivatives */
void computeHessian(const set<int> &vars);
//! Computes 3rd derivatives
/*! \param vars the derivation IDs w.r. to which derive the 2nd derivatives */
void computeThirdDerivatives(const set<int> &vars);
//! Computes derivatives of the Jacobian and Hessian w.r. to parameters
void computeParamsDerivatives(int paramsDerivsOrder);
//! Write derivative of an equation w.r. to a variable
void writeDerivative(ostream &output, int eq, int symb_id, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
//! Computes temporary terms (for all equations and derivatives)
void computeTemporaryTerms(bool is_matlab);
//! Computes temporary terms for the file containing parameters derivatives
void computeParamsDerivativesTemporaryTerms();
//! Writes temporary terms
void writeTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
void writeJsonTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output, deriv_node_temp_terms_t &tef_terms, string &concat) const;
//! Compiles temporary terms
void compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, map_idx_t map_idx, bool dynamic, bool steady_dynamic) const;
//! Adds informations for simulation in a binary file
void Write_Inf_To_Bin_File(const string &basename, int &u_count_int, bool &file_open, bool is_two_boundaries, int block_mfs) const;
//! Fixes output when there are more than 32 nested parens, Issue #1201
void fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_paren_vars, bool &message_printed) const;
//! Tests if string contains more than 32 nested parens, Issue #1201
bool testNestedParenthesis(const string &str) const;
//! Writes model local variables
/*! No temporary term is used in the output, so that local parameters declarations can be safely put before temporary terms declaration in the output files */
void writeModelLocalVariables(ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
//! Writes model equations
void writeModelEquations(ostream &output, ExprNodeOutputType output_type) const;
//! Writes JSON model equations
//! if residuals = true, we are writing the dynamic/static model.
//! Otherwise, just the model equations (with line numbers, no tmp terms)
void writeJsonModelEquations(ostream &output, bool residuals) const;
void writeJsonModelLocalVariables(ostream &output, deriv_node_temp_terms_t &tef_terms) const;
//! Compiles model equations
void compileModelEquations(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic) const;
//! Writes LaTeX model file
void writeLatexModelFile(const string &basename, ExprNodeOutputType output_type, const bool write_equation_tags) const;
//! Sparse matrix of double to store the values of the Jacobian
/*! First index is equation number, second index is endogenous type specific ID */
typedef map<pair<int, int>, double> jacob_map_t;
//! Sparse matrix of double to store the values of the Jacobian
/*! First index is lag, second index is equation number, third index is endogenous type specific ID */
typedef map<pair<int, pair<int, int> >, expr_t> dynamic_jacob_map_t;
//! Normalization of equations
/*! Maps endogenous type specific IDs to equation numbers */
vector<int> endo2eq;
//! number of equation in the prologue and in the epilogue
unsigned int epilogue, prologue;
//! for each block contains pair< max_lag, max_lead>
lag_lead_vector_t block_lag_lead;
//! Compute the matching between endogenous and variable using the jacobian contemporaneous_jacobian
/*!
\param contemporaneous_jacobian Jacobian used as an incidence matrix: all elements declared in the map (even if they are zero), are used as vertices of the incidence matrix
\return True if a complete normalization has been achieved
*/
bool computeNormalization(const jacob_map_t &contemporaneous_jacobian, bool verbose);
//! Try to compute the matching between endogenous and variable using a decreasing cutoff
/*!
Applied to the jacobian contemporaneous_jacobian and stop when a matching is found.
If no matching is found using a strictly positive cutoff, then a zero cutoff is applied (i.e. use a symbolic normalization); in that case, the method adds zeros in the jacobian matrices to reflect all the edges in the symbolic incidence matrix.
If no matching is found with a zero cutoff close to zero an error message is printout.
*/
void computeNonSingularNormalization(jacob_map_t &contemporaneous_jacobian, double cutoff, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian);
//! Try to normalized each unnormalized equation (matched endogenous variable only on the LHS)
void computeNormalizedEquations(multimap<int, int> &endo2eqs) const;
//! Evaluate the jacobian and suppress all the elements below the cutoff
void evaluateAndReduceJacobian(const eval_context_t &eval_context, jacob_map_t &contemporaneous_jacobian, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian, double cutoff, bool verbose);
//! Search the equations and variables belonging to the prologue and the epilogue of the model
void computePrologueAndEpilogue(const jacob_map_t &static_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered);
//! Determine the type of each equation of model and try to normalized the unnormalized equation using computeNormalizedEquations
equation_type_and_normalized_equation_t equationTypeDetermination(const map<pair<int, pair<int, int> >, expr_t> &first_order_endo_derivatives, const vector<int> &Index_Var_IM, const vector<int> &Index_Equ_IM, int mfs) const;
//! Compute the block decomposition and for a non-recusive block find the minimum feedback set
void computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const dynamic_jacob_map_t &dynamic_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered, vector<pair<int, int> > &blocks, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_, bool select_feedback_variable, int mfs, vector<int> &inv_equation_reordered, vector<int> &inv_variable_reordered, lag_lead_vector_t &equation_lag_lead, lag_lead_vector_t &variable_lag_lead_t, vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed) const;
//! Reduce the number of block merging the same type equation in the prologue and the epilogue and determine the type of each block
block_type_firstequation_size_mfs_t reduceBlocksAndTypeDetermination(const dynamic_jacob_map_t &dynamic_jacobian, vector<pair<int, int> > &blocks, const equation_type_and_normalized_equation_t &Equation_Type, const vector<int> &variable_reordered, const vector<int> &equation_reordered, vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed, vector<pair< pair<int, int>, pair<int, int> > > &block_col_type);
//! Determine the maximum number of lead and lag for the endogenous variable in a bloc
void getVariableLeadLagByBlock(const dynamic_jacob_map_t &dynamic_jacobian, const vector<int> &components_set, int nb_blck_sim, lag_lead_vector_t &equation_lead_lag, lag_lead_vector_t &variable_lead_lag, const vector<int> &equation_reordered, const vector<int> &variable_reordered) const;
//! Print an abstract of the block structure of the model
void printBlockDecomposition(const vector<pair<int, int> > &blocks) const;
//! Determine for each block if it is linear or not
vector<bool> BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vector<int> &variable_reordered) const;
//! Determine the simulation type of each block
virtual BlockSimulationType getBlockSimulationType(int block_number) const = 0;
//! Return the number of blocks
virtual unsigned int getNbBlocks() const = 0;
//! Return the first equation number of a block
virtual unsigned int getBlockFirstEquation(int block_number) const = 0;
//! Return the size of the block block_number
virtual unsigned int getBlockSize(int block_number) const = 0;
//! Return the number of exogenous variable in the block block_number
virtual unsigned int getBlockExoSize(int block_number) const = 0;
//! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
virtual unsigned int getBlockExoColSize(int block_number) const = 0;
//! Return the number of feedback variable of the block block_number
virtual unsigned int getBlockMfs(int block_number) const = 0;
//! Return the maximum lag in a block
virtual unsigned int getBlockMaxLag(int block_number) const = 0;
//! Return the maximum lead in a block
virtual unsigned int getBlockMaxLead(int block_number) const = 0;
inline void
setBlockLeadLag(int block, int max_lag, int max_lead)
{
block_lag_lead[block] = make_pair(max_lag, max_lead);
};
//! Return the type of equation (equation_number) belonging to the block block_number
virtual EquationType getBlockEquationType(int block_number, int equation_number) const = 0;
//! Return true if the equation has been normalized
virtual bool isBlockEquationRenormalized(int block_number, int equation_number) const = 0;
//! Return the expr_t of the equation equation_number belonging to the block block_number
virtual expr_t getBlockEquationExpr(int block_number, int equation_number) const = 0;
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
virtual expr_t getBlockEquationRenormalizedExpr(int block_number, int equation_number) const = 0;
//! Return the original number of equation equation_number belonging to the block block_number
virtual int getBlockEquationID(int block_number, int equation_number) const = 0;
//! Return the original number of variable variable_number belonging to the block block_number
virtual int getBlockVariableID(int block_number, int variable_number) const = 0;
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number
virtual int getBlockVariableExoID(int block_number, int variable_number) const = 0;
//! Return the position of equation_number in the block number belonging to the block block_number
virtual int getBlockInitialEquationID(int block_number, int equation_number) const = 0;
//! Return the position of variable_number in the block number belonging to the block block_number
virtual int getBlockInitialVariableID(int block_number, int variable_number) const = 0;
//! Return the position of variable_number in the block number belonging to the block block_number
virtual int getBlockInitialExogenousID(int block_number, int variable_number) const = 0;
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
virtual int getBlockInitialDetExogenousID(int block_number, int variable_number) const = 0;
//! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
virtual int getBlockInitialOtherEndogenousID(int block_number, int variable_number) const = 0;
//! Initialize equation_reordered & variable_reordered
void initializeVariablesAndEquations();
public:
ModelTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
//! Absolute value under which a number is considered to be zero
double cutoff;
//! Compute the minimum feedback set
/*! 0 : all endogenous variables are considered as feedback variables
1 : the variables belonging to non normalized equation are considered as feedback variables
2 : the variables belonging to a non linear equation are considered as feedback variables
3 : the variables belonging to a non normalizable non linear equation are considered as feedback variables
default value = 0 */
int mfs;
//! Declare a node as an equation of the model; also give its line number
void addEquation(expr_t eq, int lineno);
//! Declare a node as an equation of the model, also giving its tags
void addEquation(expr_t eq, int lineno, const vector<pair<string, string> > &eq_tags);
//! Declare a node as an auxiliary equation of the model, adding it at the end of the list of auxiliary equations
void addAuxEquation(expr_t eq);
//! Returns the number of equations in the model
int equation_number() const;
//! Adds a trend variable with its growth factor
void addTrendVariables(vector<int> trend_vars, expr_t growth_factor) throw (TrendException);
//! Adds a nonstationary variables with their (common) deflator
void addNonstationaryVariables(vector<int> nonstationary_vars, bool log_deflator, expr_t deflator) throw (TrendException);
//! Is a given variable non-stationary?
bool isNonstationary(int symb_id) const;
void set_cutoff_to_zero();
//! Helper for writing the Jacobian elements in MATLAB and C
/*! Writes either (i+1,j+1) or [i+j*no_eq] */
void jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const;
//! Helper for writing the sparse Hessian or third derivatives in MATLAB and C
/*! If order=2, writes either v2(i+1,j+1) or v2[i+j*NNZDerivatives[1]]
If order=3, writes either v3(i+1,j+1) or v3[i+j*NNZDerivatives[2]] */
void sparseHelper(int order, ostream &output, int row_nb, int col_nb, ExprNodeOutputType output_type) const;
inline static std::string
c_Equation_Type(int type)
{
char c_Equation_Type[4][13] =
{
"E_UNKNOWN ",
"E_EVALUATE ",
"E_EVALUATE_S",
"E_SOLVE "
};
return (c_Equation_Type[type]);
};
inline static std::string
BlockType0(BlockType type)
{
switch (type)
{
case SIMULTANS:
return ("SIMULTANEOUS TIME SEPARABLE ");
break;
case PROLOGUE:
return ("PROLOGUE ");
break;
case EPILOGUE:
return ("EPILOGUE ");
break;
case SIMULTAN:
return ("SIMULTANEOUS TIME UNSEPARABLE");
break;
default:
return ("UNKNOWN ");
break;
}
};
inline static std::string
BlockSim(int type)
{
switch (type)
{
case EVALUATE_FORWARD:
return ("EVALUATE FORWARD ");
break;
case EVALUATE_BACKWARD:
return ("EVALUATE BACKWARD ");
break;
case SOLVE_FORWARD_SIMPLE:
return ("SOLVE FORWARD SIMPLE ");
break;
case SOLVE_BACKWARD_SIMPLE:
return ("SOLVE BACKWARD SIMPLE ");
break;
case SOLVE_TWO_BOUNDARIES_SIMPLE:
return ("SOLVE TWO BOUNDARIES SIMPLE ");
break;
case SOLVE_FORWARD_COMPLETE:
return ("SOLVE FORWARD COMPLETE ");
break;
case SOLVE_BACKWARD_COMPLETE:
return ("SOLVE BACKWARD COMPLETE ");
break;
case SOLVE_TWO_BOUNDARIES_COMPLETE:
return ("SOLVE TWO BOUNDARIES COMPLETE");
break;
default:
return ("UNKNOWN ");
break;
}
};
};
#endif

View File

@ -1,63 +0,0 @@
/*
* Copyright (C) 2003-2012 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <cerrno>
#include <cmath>
#include <iostream>
#include "NumericalConstants.hh"
int
NumericalConstants::AddNonNegativeConstant(const string &iConst)
{
map<string, int>::const_iterator iter = numConstantsIndex.find(iConst);
if (iter != numConstantsIndex.end())
return iter->second;
int id = (int) mNumericalConstants.size();
mNumericalConstants.push_back(iConst);
numConstantsIndex[iConst] = id;
double val = strtod(iConst.c_str(), NULL);
/* Note that we allow underflows (will be converted to 0) and overflows (will
be converted to Inf), as MATLAB and Octave do. */
assert(val >= 0 || isnan(val)); // Check we have a positive constant or a NaN
double_vals.push_back(val);
return id;
}
string
NumericalConstants::get(int ID) const
{
assert(ID >= 0 && ID < (int) mNumericalConstants.size());
return mNumericalConstants[ID];
}
double
NumericalConstants::getDouble(int ID) const
{
assert(ID >= 0 && ID < (int) double_vals.size());
return (double_vals[ID]);
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (C) 2003-2016 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NUMERICALCONSTANTS_HH
#define _NUMERICALCONSTANTS_HH
using namespace std;
#include <string>
#include <vector>
#include <map>
//! Handles non-negative numerical constants
class NumericalConstants
{
private:
//! Vector of numerical constants
vector<string> mNumericalConstants;
//! Double values of these constants
vector<double> double_vals;
//! Map matching constants to their id
map<string, int> numConstantsIndex;
public:
//! Adds a non-negative constant (possibly Inf or NaN) and returns its ID
int AddNonNegativeConstant(const string &iConst);
//! Get a constant in string form
string get(int ID) const;
//! Get a constant in double form
double getDouble(int ID) const;
};
#endif

View File

@ -1,649 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include "NumericalInitialization.hh"
InitParamStatement::InitParamStatement(int symb_id_arg,
const expr_t param_value_arg,
const SymbolTable &symbol_table_arg) :
symb_id(symb_id_arg),
param_value(param_value_arg),
symbol_table(symbol_table_arg)
{
}
void
InitParamStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
if (symbol_table.getName(symb_id) == "dsge_prior_weight")
mod_file_struct.dsge_prior_weight_initialized = true;
}
void
InitParamStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
int id = symbol_table.getTypeSpecificID(symb_id) + 1;
output << "M_.params( " << id << " ) = ";
param_value->writeOutput(output);
output << ";" << endl;
if (!minimal_workspace)
output << symbol_table.getName(symb_id) << " = M_.params( " << id << " );" << endl;
}
void
InitParamStatement::writeJuliaOutput(ostream &output, const string &basename)
{
int id = symbol_table.getTypeSpecificID(symb_id) + 1;
output << "model_.params[ " << id << " ] = ";
param_value->writeOutput(output);
output << endl;
// Do we really need this?
// if (!minimal_workspace)
// output << symbol_table.getName(symb_id) << " = model_.params[ " << id << " ]" << endl;
}
void
InitParamStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"param_init\", \"name\": \"" << symbol_table.getName(symb_id) << "\", " << "\"value\": \"";
param_value->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
void
InitParamStatement::writeCOutput(ostream &output, const string &basename)
{
int id = symbol_table.getTypeSpecificID(symb_id);
output << "params[ " << id << " ] = ";
param_value->writeOutput(output);
output << ";" << endl;
output << "double " << symbol_table.getName(symb_id) << " = params[ " << id << " ];" << endl;
}
void
InitParamStatement::fillEvalContext(eval_context_t &eval_context) const
{
try
{
eval_context[symb_id] = param_value->eval(eval_context);
}
catch (ExprNode::EvalException &e)
{
// Do nothing
}
}
InitOrEndValStatement::InitOrEndValStatement(const init_values_t &init_values_arg,
const SymbolTable &symbol_table_arg,
const bool &all_values_required_arg) :
init_values(init_values_arg),
symbol_table(symbol_table_arg),
all_values_required(all_values_required_arg)
{
}
void
InitOrEndValStatement::fillEvalContext(eval_context_t &eval_context) const
{
for (init_values_t::const_iterator it = init_values.begin();
it != init_values.end(); it++)
{
try
{
eval_context[it->first] = (it->second)->eval(eval_context);
}
catch (ExprNode::EvalException &e)
{
// Do nothing
}
}
}
set<int>
InitOrEndValStatement::getUninitializedVariables(SymbolType type)
{
set<int> unused;
if (!all_values_required)
return unused;
if (type == eEndogenous)
unused = symbol_table.getEndogenous();
else if (type == eExogenous)
unused = symbol_table.getExogenous();
else
{
cerr << "ERROR: Shouldn't arrive here." << endl;
exit(EXIT_FAILURE);
}
set<int>::iterator sit;
for (init_values_t::const_iterator it = init_values.begin();
it != init_values.end(); it++)
{
sit = unused.find(it->first);
if (sit != unused.end())
unused.erase(sit);
}
return unused;
}
void
InitOrEndValStatement::writeInitValues(ostream &output) const
{
for (init_values_t::const_iterator it = init_values.begin();
it != init_values.end(); it++)
{
const int symb_id = it->first;
const expr_t expression = it->second;
SymbolType type = symbol_table.getType(symb_id);
int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
if (type == eEndogenous)
output << "oo_.steady_state";
else if (type == eExogenous)
output << "oo_.exo_steady_state";
else if (type == eExogenousDet)
output << "oo_.exo_det_steady_state";
output << "( " << tsid << " ) = ";
expression->writeOutput(output);
output << ";" << endl;
}
}
void
InitOrEndValStatement::writeJsonInitValues(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
for (init_values_t::const_iterator it = init_values.begin();
it != init_values.end(); it++)
{
if (it != init_values.begin())
output << ", ";
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", " << "\"value\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
}
InitValStatement::InitValStatement(const init_values_t &init_values_arg,
const SymbolTable &symbol_table_arg,
const bool &all_values_required_arg) :
InitOrEndValStatement(init_values_arg, symbol_table_arg, all_values_required_arg)
{
}
void
InitValStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
set<int> exogs = getUninitializedVariables(eExogenous);
set<int> endogs = getUninitializedVariables(eEndogenous);
if (endogs.size() > 0)
{
cerr << "ERROR: You have not set the following endogenous variables in initval:";
for (set<int>::const_iterator it = endogs.begin(); it != endogs.end(); it++)
cerr << " " << symbol_table.getName(*it);
cerr << endl;
}
if (exogs.size() > 0)
{
cerr << "ERROR: You have not set the following exogenous variables in initval:";
for (set<int>::const_iterator it = exogs.begin(); it != exogs.end(); it++)
cerr << " " << symbol_table.getName(*it);
cerr << endl;
}
if (endogs.size() > 0 || exogs.size() > 0)
exit(EXIT_FAILURE);
}
void
InitValStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "%" << endl
<< "% INITVAL instructions" << endl
<< "%" << endl;
// Writing initval block to set initial values for variables
output << "options_.initval_file = 0;" << endl;
writeInitValues(output);
}
void
InitValStatement::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"init_val\", \"vals\": [";
writeJsonInitValues(output);
output << "]}";
}
void
InitValStatement::writeOutputPostInit(ostream &output) const
{
output << "if M_.exo_nbr > 0" << endl
<< "\too_.exo_simul = ones(M_.maximum_lag,1)*oo_.exo_steady_state';" << endl
<<"end" << endl
<< "if M_.exo_det_nbr > 0" << endl
<< "\too_.exo_det_simul = ones(M_.maximum_lag,1)*oo_.exo_det_steady_state';" << endl
<<"end" << endl;
}
EndValStatement::EndValStatement(const init_values_t &init_values_arg,
const SymbolTable &symbol_table_arg,
const bool &all_values_required_arg) :
InitOrEndValStatement(init_values_arg, symbol_table_arg, all_values_required_arg)
{
}
void
EndValStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
set<int> exogs = getUninitializedVariables(eExogenous);
set<int> endogs = getUninitializedVariables(eEndogenous);
if (endogs.size() > 0)
{
cerr << "ERROR: You have not set the following endogenous variables in endval:";
for (set<int>::const_iterator it = endogs.begin(); it != endogs.end(); it++)
cerr << " " << symbol_table.getName(*it);
cerr << endl;
}
if (exogs.size() > 0)
{
cerr << "ERROR: You have not set the following exogenous variables in endval:";
for (set<int>::const_iterator it = exogs.begin(); it != exogs.end(); it++)
cerr << " " << symbol_table.getName(*it);
cerr << endl;
}
if (endogs.size() > 0 || exogs.size() > 0)
exit(EXIT_FAILURE);
}
void
EndValStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "%" << endl
<< "% ENDVAL instructions" << endl
<< "%" << endl;
// Writing endval block to set terminal values for variables
output << "ys0_= oo_.steady_state;" << endl
<< "ex0_ = oo_.exo_steady_state;" << endl;
writeInitValues(output);
}
void
EndValStatement::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"end_val\", \"vals\": [";
writeJsonInitValues(output);
output << "]}";
}
HistValStatement::HistValStatement(const hist_values_t &hist_values_arg,
const hist_vals_wrong_lag_t hist_vals_wrong_lag_arg,
const SymbolTable &symbol_table_arg,
const bool &all_values_required_arg) :
hist_values(hist_values_arg),
hist_vals_wrong_lag(hist_vals_wrong_lag_arg),
symbol_table(symbol_table_arg),
all_values_required(all_values_required_arg)
{
}
void
HistValStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
if (all_values_required)
{
set<int> unused_endo = symbol_table.getEndogenous();
set<int> unused_exo = symbol_table.getExogenous();
set<int>::iterator sit;
for (hist_values_t::const_iterator it = hist_values.begin();
it != hist_values.end(); it++)
{
sit = unused_endo.find(it->first.first);
if (sit != unused_endo.end())
unused_endo.erase(sit);
sit = unused_exo.find(it->first.first);
if (sit != unused_exo.end())
unused_exo.erase(sit);
}
if (unused_endo.size() > 0)
{
cerr << "ERROR: You have not set the following endogenous variables in histval:";
for (set<int>::const_iterator it = unused_endo.begin(); it != unused_endo.end(); it++)
cerr << " " << symbol_table.getName(*it);
cerr << endl;
}
if (unused_exo.size() > 0)
{
cerr << "ERROR: You have not set the following exogenous variables in endval:";
for (set<int>::const_iterator it = unused_exo.begin(); it != unused_exo.end(); it++)
cerr << " " << symbol_table.getName(*it);
cerr << endl;
}
if (unused_endo.size() > 0 || unused_exo.size() > 0)
exit(EXIT_FAILURE);
}
mod_file_struct.hist_vals_wrong_lag = hist_vals_wrong_lag;
}
void
HistValStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "%" << endl
<< "% HISTVAL instructions" << endl
<< "%" << endl
<< "M_.endo_histval = zeros(M_.endo_nbr,M_.maximum_lag);" << endl
<< "M_.exo_histval = zeros(M_.exo_nbr,M_.maximum_lag);" << endl
<< "M_.exo_det_histval = zeros(M_.exo_det_nbr,M_.maximum_lag);" << endl;
for (hist_values_t::const_iterator it = hist_values.begin();
it != hist_values.end(); it++)
{
int symb_id = it->first.first;
int lag = it->first.second;
const expr_t expression = it->second;
SymbolType type = symbol_table.getType(symb_id);
// For a lag greater than 1 on endo, or for any exo, lookup for auxiliary variable
if ((type == eEndogenous && lag < 0) || type == eExogenous)
{
try
{
// This function call must remain the 1st statement in this block
symb_id = symbol_table.searchAuxiliaryVars(symb_id, lag);
lag = 0;
type = eEndogenous;
}
catch (SymbolTable::SearchFailedException &e)
{
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;
if (type == eEndogenous)
output << "M_.endo_histval( " << tsid << ", M_.maximum_lag + " << lag << ") = ";
else if (type == eExogenous)
output << "M_.exo_histval( " << tsid << ", M_.maximum_lag + " << lag << ") = ";
else if (type == eExogenousDet)
output << "M_.exo_det_histval( " << tsid << ", M_.maximum_lag + " << lag << ") = ";
expression->writeOutput(output);
output << ";" << endl;
}
}
void
HistValStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"hist_val\", \"vals\": [";
for (hist_values_t::const_iterator it = hist_values.begin();
it != hist_values.end(); it++)
{
if (it != hist_values.begin())
output << ", ";
output << "{ \"name\": \"" << symbol_table.getName(it->first.first) << "\""
<< ", \"lag\": " << it->first.second
<< ", \"value\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
output << "]}";
}
InitvalFileStatement::InitvalFileStatement(const string &filename_arg) :
filename(filename_arg)
{
}
void
InitvalFileStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "%" << endl
<< "% INITVAL_FILE statement" << endl
<< "%" << endl
<< "options_.initval_file = 1;" << endl
<< "initvalf('" << filename << "');" << endl;
}
void
InitvalFileStatement::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"init_val_file\""
<< ", \"filename\": \"" << filename << "\""
<< "}";
}
HistvalFileStatement::HistvalFileStatement(const string &filename_arg) :
filename(filename_arg)
{
}
void
HistvalFileStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "histvalf('" << filename << "');" << endl;
}
void
HistvalFileStatement::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"hist_val_file\""
<< ", \"filename\": \"" << filename << "\""
<< "}";
}
HomotopyStatement::HomotopyStatement(const homotopy_values_t &homotopy_values_arg,
const SymbolTable &symbol_table_arg) :
homotopy_values(homotopy_values_arg),
symbol_table(symbol_table_arg)
{
}
void
HomotopyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "%" << endl
<< "% HOMOTOPY_SETUP instructions" << endl
<< "%" << endl
<< "options_.homotopy_values = [];" << endl;
for (homotopy_values_t::const_iterator it = homotopy_values.begin();
it != homotopy_values.end(); it++)
{
const int &symb_id = it->first;
const expr_t expression1 = it->second.first;
const expr_t expression2 = it->second.second;
const SymbolType type = symbol_table.getType(symb_id);
const int tsid = symbol_table.getTypeSpecificID(symb_id) + 1;
output << "options_.homotopy_values = vertcat(options_.homotopy_values, [ " << type << ", " << tsid << ", ";
if (expression1 != NULL)
expression1->writeOutput(output);
else
output << "NaN";
output << ", ";
expression2->writeOutput(output);
output << "]);" << endl;
}
}
void
HomotopyStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"homotopy\", "
<< "\"values\": [";
for (homotopy_values_t::const_iterator it = homotopy_values.begin();
it != homotopy_values.end(); it++)
{
if (it != homotopy_values.begin())
output << ", ";
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\""
<< ", \"initial_value\": \"";
if (it->second.first != NULL)
it->second.first->writeJsonOutput(output, temporary_terms_t(), tef_terms);
else
output << "NaN";
output << "\", \"final_value\": \"";
it->second.second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
output << "]"
<< "}";
}
SaveParamsAndSteadyStateStatement::SaveParamsAndSteadyStateStatement(const string &filename_arg) :
filename(filename_arg)
{
}
void
SaveParamsAndSteadyStateStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "save_params_and_steady_state('" << filename << "');" << endl;
}
void
SaveParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"save_params_and_steady_state\""
<< ", \"filename\": \"" << filename << "\""
<< "}";
}
LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(const string &filename,
const SymbolTable &symbol_table_arg,
WarningConsolidation &warnings) :
symbol_table(symbol_table_arg)
{
cout << "Reading " << filename << "." << endl;
ifstream f;
f.open(filename.c_str(), ios::in);
if (f.fail())
{
cerr << "ERROR: Can't open " << filename << endl;
exit(EXIT_FAILURE);
}
while (true)
{
string symb_name, value;
f >> symb_name >> value;
if (f.eof())
break;
try
{
int symb_id = symbol_table.getID(symb_name);
content[symb_id] = value;
}
catch (SymbolTable::UnknownSymbolNameException &e)
{
warnings << "WARNING: Unknown symbol " << symb_name << " in " << filename << endl;
}
}
f.close();
}
void
LoadParamsAndSteadyStateStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
for (map<int, string>::const_iterator it = content.begin();
it != content.end(); it++)
{
switch (symbol_table.getType(it->first))
{
case eParameter:
output << "M_.params";
break;
case eEndogenous:
output << "oo_.steady_state";
break;
case eExogenous:
output << "oo_.exo_steady_state";
break;
case eExogenousDet:
output << "oo_.exo_det_steady_state";
break;
default:
cerr << "ERROR: Unsupported variable type for " << symbol_table.getName(it->first) << " in load_params_and_steady_state" << endl;
exit(EXIT_FAILURE);
}
int tsid = symbol_table.getTypeSpecificID(it->first) + 1;
output << "(" << tsid << ") = " << it->second << ";" << endl;
}
}
void
LoadParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"load_params_and_steady_state\""
<< "\"values\": [";
for (map<int, string>::const_iterator it = content.begin();
it != content.end(); it++)
{
if (it != content.begin())
output << ", ";
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\""
<< ", \"value\": \"" << it->second << "\"}";
}
output << "]"
<< "}";
}
void
LoadParamsAndSteadyStateStatement::fillEvalContext(eval_context_t &eval_context) const
{
for (map<int, string>::const_iterator it = content.begin();
it != content.end(); it++)
eval_context[it->first] = atof(it->second.c_str());
}

View File

@ -1,190 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _NUMERICALINITIALIZATION_HH
#define _NUMERICALINITIALIZATION_HH
using namespace std;
#include <string>
#include <vector>
#include <map>
#include "SymbolTable.hh"
#include "ExprNode.hh"
#include "Statement.hh"
class InitParamStatement : public Statement
{
private:
const int symb_id;
const expr_t param_value;
const SymbolTable &symbol_table;
public:
InitParamStatement(int symb_id_arg, const expr_t param_value_arg,
const SymbolTable &symbol_table_arg);
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJuliaOutput(ostream &output, const string &basename);
virtual void writeCOutput(ostream &output, const string &basename);
virtual void writeJsonOutput(ostream &output) const;
//! Fill eval context with parameter value
void fillEvalContext(eval_context_t &eval_context) const;
};
class InitOrEndValStatement : public Statement
{
public:
/*!
We use a vector instead of a map, since the order of declaration matters:
an initialization can depend on a previously initialized variable inside the block
*/
typedef vector<pair<int, expr_t> > init_values_t;
protected:
const init_values_t init_values;
const SymbolTable &symbol_table;
const bool all_values_required;
public:
InitOrEndValStatement(const init_values_t &init_values_arg,
const SymbolTable &symbol_table_arg,
const bool &all_values_required_arg);
//! Return set of unused variables by type
set<int> getUninitializedVariables(SymbolType type);
//! Fill eval context with variables values
void fillEvalContext(eval_context_t &eval_context) const;
protected:
void writeInitValues(ostream &output) const;
void writeJsonInitValues(ostream &output) const;
};
class InitValStatement : public InitOrEndValStatement
{
public:
InitValStatement(const init_values_t &init_values_arg,
const SymbolTable &symbol_table_arg,
const bool &all_values_required_arg);
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
//! Writes initializations for oo_.exo_simul and oo_.exo_det_simul
void writeOutputPostInit(ostream &output) const;
};
class EndValStatement : public InitOrEndValStatement
{
public:
EndValStatement(const init_values_t &init_values_arg,
const SymbolTable &symbol_table_arg,
const bool &all_values_required_arg);
//! Workaround for trac ticket #35
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class HistValStatement : public Statement
{
public:
/*!
Contrary to Initval and Endval, we use a map, since it is impossible to reuse
a given initialization value in a second initialization inside the block.
Maps pairs (symbol_id, lag) to expr_t
*/
typedef map<pair<int, int>, expr_t> hist_values_t;
typedef map<int, int> hist_vals_wrong_lag_t;
private:
const hist_values_t hist_values;
const hist_vals_wrong_lag_t hist_vals_wrong_lag;
const SymbolTable &symbol_table;
const bool all_values_required;
public:
HistValStatement(const hist_values_t &hist_values_arg,
const hist_vals_wrong_lag_t hist_vals_wrong_lag_arg,
const SymbolTable &symbol_table_arg,
const bool &all_values_required_arg);
//! Workaround for trac ticket #157
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class InitvalFileStatement : public Statement
{
private:
const string filename;
public:
InitvalFileStatement(const string &filename_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class HistvalFileStatement : public Statement
{
private:
const string filename;
public:
HistvalFileStatement(const string &filename_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class HomotopyStatement : public Statement
{
public:
//! Stores the declarations of homotopy_setup
/*! Order matter so we use a vector. First expr_t can be NULL if no initial value given. */
typedef vector<pair<int, pair<expr_t, expr_t> > > homotopy_values_t;
private:
const homotopy_values_t homotopy_values;
const SymbolTable &symbol_table;
public:
HomotopyStatement(const homotopy_values_t &homotopy_values_arg,
const SymbolTable &symbol_table_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class SaveParamsAndSteadyStateStatement : public Statement
{
private:
const string filename;
public:
SaveParamsAndSteadyStateStatement(const string &filename_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class LoadParamsAndSteadyStateStatement : public Statement
{
private:
const SymbolTable &symbol_table;
//! Content of the file
/*! Maps symbol ID to numeric value (stored as string) */
map<int, string> content;
public:
LoadParamsAndSteadyStateStatement(const string &filename,
const SymbolTable &symbol_table_arg,
WarningConsolidation &warnings);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
//! Fill eval context with parameters/variables values
void fillEvalContext(eval_context_t &eval_context) const;
virtual void writeJsonOutput(ostream &output) const;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,780 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _PARSING_DRIVER_HH
#define _PARSING_DRIVER_HH
#ifdef _MACRO_DRIVER_HH
# error Impossible to include both ParsingDriver.hh and MacroDriver.hh
#endif
#include <string>
#include <vector>
#include <istream>
#include <stack>
#include "ModFile.hh"
#include "SymbolList.hh"
class ParsingDriver;
#include "ExprNode.hh"
#include "DynareBison.hh"
#include "ComputingTasks.hh"
#include "Shocks.hh"
#include "SigmaeInitialization.hh"
#include "NumericalInitialization.hh"
#include "DynamicModel.hh"
using namespace std;
// Declare DynareFlexLexer class
#ifndef __FLEX_LEXER_H
# define yyFlexLexer DynareFlexLexer
# include <FlexLexer.h>
# undef yyFlexLexer
#endif
//! The lexer class
/*! Actually it was necessary to subclass the DynareFlexLexer class generated by Flex,
since the prototype for DynareFlexLexer::yylex() was not convenient.
*/
class DynareFlex : public DynareFlexLexer
{
public:
DynareFlex(istream *in = 0, ostream *out = 0);
//! The main lexing function
Dynare::parser::token_type lex(Dynare::parser::semantic_type *yylval,
Dynare::parser::location_type *yylloc,
ParsingDriver &driver);
//! The filename being parsed
/*! The bison parser locations (begin and end) contain a pointer to that string */
string filename;
//! Increment the location counter given a token
void location_increment(Dynare::parser::location_type *yylloc, const char *yytext);
//! Count parens in dates statement
int dates_parens_nb;
};
//! Drives the scanning and parsing of the .mod file, and constructs its abstract representation
/*! It is built along the guidelines given in Bison 2.3 manual. */
class ParsingDriver
{
private:
//! Checks that a given symbol exists, and stops with an error message if it doesn't
void check_symbol_existence(const string &name);
//! Checks that a given symbol exists and is a parameter, and stops with an error message if it isn't
void check_symbol_is_parameter(string *name);
//! Checks that a given symbol was assigned within a Statement
void check_symbol_is_statement_variable(string *name);
//! Checks that a given symbol exists and is a endogenous or exogenous, and stops with an error message if it isn't
void check_symbol_is_endogenous_or_exogenous(string *name);
//! Checks that a given symbol exists and is a exogenous, and stops with an error message if it isn't
void check_symbol_is_exogenous(string *name);
//! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to be printed at
//! the end of the model block
void check_symbol_existence_in_model_block(const string &name);
//! Helper to add a symbol declaration
void declare_symbol(const string *name, SymbolType type, const string *tex_name, const vector<pair<string *, string *> *> *partition_value);
//! Creates option "optim_opt" in OptionsList if it doesn't exist, else add a comma, and adds the option name
void optim_options_helper(const string &name);
void sampling_options_helper(const string &name);
//! Stores temporary symbol table
SymbolList symbol_list;
//! The data tree in which to add expressions currently parsed
DataTree *data_tree;
//! The model tree in which to add expressions currently parsed
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a ModelTree instance */
ModelTree *model_tree;
//! The dynamic model tree in which to add expressions currently parsed
/*! It is only a dynamic cast of data_tree pointer, and is therefore null if data_tree is not a DynamicModel instance */
DynamicModel *dynamic_model;
//! Sets data_tree and model_tree pointers
void set_current_data_tree(DataTree *data_tree_arg);
//! Stores options lists
OptionsList options_list;
//! Temporary storage for trend elements
ObservationTrendsStatement::trend_elements_t trend_elements;
//! Temporary storage for filename list of ModelComparison (contains weights)
ModelComparisonStatement::filename_list_t filename_list;
//! Temporary storage for list of EstimationParams (from estimated_params* statements)
vector<EstimationParams> estim_params_list;
//! Temporary storage for list of OsrParams (from osr_params_block statements)
vector<OsrParams> osr_params_list;
//! Temporary storage of variances from optim_weights
OptimWeightsStatement::var_weights_t var_weights;
//! Temporary storage of covariances from optim_weights
OptimWeightsStatement::covar_weights_t covar_weights;
//! Temporary storage for deterministic shocks
ShocksStatement::det_shocks_t det_shocks;
//! Temporary storage for periods of deterministic shocks
vector<pair<int, int> > det_shocks_periods;
//! Temporary storage for values of deterministic shocks
vector<expr_t> det_shocks_values;
//! Temporary storage for variances of shocks
ShocksStatement::var_and_std_shocks_t var_shocks;
//! Temporary storage for standard errors of shocks
ShocksStatement::var_and_std_shocks_t std_shocks;
//! Temporary storage for covariances of shocks
ShocksStatement::covar_and_corr_shocks_t covar_shocks;
//! Temporary storage for correlations of shocks
ShocksStatement::covar_and_corr_shocks_t corr_shocks;
//! Temporary storage for Sigma_e rows
SigmaeStatement::row_t sigmae_row;
//! Temporary storage for Sigma_e matrix
SigmaeStatement::matrix_t sigmae_matrix;
//! Temporary storage for initval/endval blocks
InitOrEndValStatement::init_values_t init_values;
//! Temporary storage for histval blocks
HistValStatement::hist_values_t hist_values;
//! Temporary storage for histval blocks
HistValStatement::hist_vals_wrong_lag_t hist_vals_wrong_lag;
//! Temporary storage for homotopy_setup blocks
HomotopyStatement::homotopy_values_t homotopy_values;
//! Temporary storage for moment_calibration
MomentCalibration::constraints_t moment_calibration_constraints;
//! Temporary storage for irf_calibration
IrfCalibration::constraints_t irf_calibration_constraints;
//! Temporary storage for ramsey_constraints
RamseyConstraintsStatement::constraints_t ramsey_constraints;
//! Temporary storage for svar_identification blocks
SvarIdentificationStatement::svar_identification_restrictions_t svar_ident_restrictions;
//! Temporary storage for mapping the equation number to the restrictions within an svar_identification block
map<int, vector<int> > svar_equation_restrictions;
//! Temporary storage for restrictions in an equation within an svar_identification block
vector<int> svar_restriction_symbols;
//! Temporary storage for constants exculsion within an svar_identification
bool svar_constants_exclusion;
//! Temporary storage for upper cholesky within an svar_identification block
bool svar_upper_cholesky;
//! Temporary storage for lower cholesky within an svar_identification block
bool svar_lower_cholesky;
//! Temporary storage for equation number for a restriction within an svar_identification block
int svar_equation_nbr;
//! Temporary storage for left/right handside of a restriction equation within an svar_identificaton block
bool svar_left_handside;
//! Temporary storage for current restriction number in svar_identification block
map<int, int> svar_Qi_restriction_nbr;
map<int, int> svar_Ri_restriction_nbr;
//! Stores undeclared model variables
set<string> undeclared_model_vars;
//! Temporary storage for restriction type
enum SvarRestrictionType
{
NOT_SET,
Qi_TYPE,
Ri_TYPE
};
SvarRestrictionType svar_restriction_type;
//! Temporary storage for generate_irfs
vector<string> generate_irf_names;
vector<map<string, double> > generate_irf_elements;
map<string, double> generate_irf_exos;
//! Temporary storage for argument list of external function
stack<vector<expr_t> > stack_external_function_args;
//! Temporary storage for parameters in joint prior statement
vector<string> joint_parameters;
//! Temporary storage for the symb_id associated with the "name" symbol of the current external_function statement
int current_external_function_id;
//! Temporary storage for option list provided to external_function()
ExternalFunctionsTable::external_function_options current_external_function_options;
//! Temporary storage for declaring trend variables
vector<int> declared_trend_vars;
//! Temporary storage for declaring nonstationary variables
vector<int> declared_nonstationary_vars;
//! Temporary storage for a variance declared in the prior statement
expr_t prior_variance;
SubsamplesStatement::subsample_declaration_map_t subsample_declaration_map;
//! Temporary storage for subsample statement: map<pair<var_name1, var_name2>>, subsample_declaration_map >
typedef map<pair<string, string >, SubsamplesStatement::subsample_declaration_map_t > subsample_declarations_t;
subsample_declarations_t subsample_declarations;
//! Temporary storage for shock_groups
vector<string> shock_group;
vector<ShockGroupsStatement::Group> shock_groups;
//! Temporary storage for ramsey policy. Workaround for issue #1355
vector<string> ramsey_policy_list;
//! reset the values for temporary storage
void reset_current_external_function_options();
//! Adds a model lagged variable to ModelTree and VariableTable
expr_t add_model_variable(int symb_id, int lag);
//! For parsing the graph_format option
SymbolList graph_formats;
//! Temporary storage for equation tags
vector<pair<string, string> > eq_tags;
//! The mod file representation constructed by this ParsingDriver
ModFile *mod_file;
WarningConsolidation &warnings;
bool nostrict;
bool model_error_encountered;
ostringstream model_errors;
public:
ParsingDriver(WarningConsolidation &warnings_arg, bool nostrict_arg) : warnings(warnings_arg), nostrict(nostrict_arg), model_error_encountered(false)
{
};
//! Starts parsing, and constructs the MOD file representation
/*! The returned pointer should be deleted after use */
ModFile *parse(istream &in, bool debug);
//! Reference to the lexer
class DynareFlex *lexer;
//! Copy of parsing location, maintained by YYLLOC_DEFAULT macro in DynareBison.yy
Dynare::parser::location_type location;
//! Estimation parameters
EstimationParams estim_params;
//! OSR parameters
OsrParams osr_params;
//! Temporary storage for the prior shape
PriorDistributions prior_shape;
//! Error handler with explicit location
void error(const Dynare::parser::location_type &l, const string &m) __attribute__ ((noreturn));
//! Error handler using saved location
void error(const string &m) __attribute__ ((noreturn));
//! Warning handler using saved location
void warning(const string &m);
//! Error handler with explicit location (used in model block, accumulating error messages to be printed later)
void model_error(const string &m);
//! Code shared between model_error() and error()
void create_error_string(const Dynare::parser::location_type &l, const string &m, ostream &stream);
//! Check if a given symbol exists in the parsing context, and is not a mod file local variable
bool symbol_exists_and_is_not_modfile_local_or_external_function(const char *s);
//! Sets mode of ModelTree class to use C output
void use_dll();
//! the modelis block decomposed
void block();
//! the model is stored in a binary file
void byte_code();
//! the static model is not computed
void no_static();
//! the differentiate_forward_vars option is enabled (for all vars)
void differentiate_forward_vars_all();
//! the differentiate_forward_vars option is enabled (for a subset of vars)
void differentiate_forward_vars_some();
//! cutoff option of model block
void cutoff(string *value);
//! mfs option of model block
void mfs(string *value);
//! Sets the FILENAME for the initial value in initval
void initval_file(string *filename);
//! Declares an endogenous variable
void declare_endogenous(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
//! Declares an exogenous variable
void declare_exogenous(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
//! Declares an exogenous deterministic variable
void declare_exogenous_det(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
//! Declares a parameter
void declare_parameter(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
//! Declares a model local variable
void declare_model_local_variable(string *name, string *tex_name = NULL);
//! Declares a statement local variable
void declare_statement_local_variable(string *name);
//! Completes a subsample statement
void set_subsamples(string *name1, string *name2);
//! Declares a subsample, assigning the value to name
void set_subsample_name_equal_to_date_range(string *name, string *date1, string *date2);
//! Checks that a subsample statement (and given name) were provided for the pair name1 & name2
void check_subsample_declaration_exists(string *name1, string *subsample_name);
void check_subsample_declaration_exists(string *name1, string *name2, string *subsample_name);
//! Copies the set of subsamples from_name to_name
void copy_subsamples(string *to_name1, string *to_name2, string *from_name1, string *from_name2);
//! Declares declare_optimal_policy_discount_factor as a parameter and initializes it to exprnode
void declare_optimal_policy_discount_factor_parameter(expr_t exprnode);
//! Adds a predetermined_variable
void add_predetermined_variable(string *name);
//! Declares and initializes a local parameter
void declare_and_init_model_local_variable(string *name, expr_t rhs);
//! Changes type of a symbol
void change_type(SymbolType new_type, vector<string *> *var_list);
//! Adds a list of tags for the current equation
void add_equation_tags(string *key, string *value);
//! Adds a non-negative constant to DataTree
expr_t add_non_negative_constant(string *constant);
//! Adds a NaN constant to DataTree
expr_t add_nan_constant();
//! Adds an Inf constant to DataTree
expr_t add_inf_constant();
//! Adds a model variable to ModelTree and VariableTable
expr_t add_model_variable(string *name);
//! Adds an Expression's variable
expr_t add_expression_variable(string *name);
//! Adds a "periods" statement
void periods(string *periods);
//! Adds a "dsample" statement
void dsample(string *arg1);
//! Adds a "dsample" statement
void dsample(string *arg1, string *arg2);
//! Writes parameter intitialisation expression
void init_param(string *name, expr_t rhs);
//! Writes an initval block
void init_val(string *name, expr_t rhs);
//! Writes an histval block
void hist_val(string *name, string *lag, expr_t rhs);
//! Adds an entry in a homotopy_setup block
/*! Second argument "val1" can be NULL if no initial value provided */
void homotopy_val(string *name, expr_t val1, expr_t val2);
//! Writes end of an initval block
void end_initval(bool all_values_required);
//! Writes end of an endval block
void end_endval(bool all_values_required);
//! Writes end of an histval block
void end_histval(bool all_values_required);
//! Writes end of an homotopy_setup block
void end_homotopy();
//! Begin a model block
void begin_model();
//! End a model block, printing errors that were encountered in parsing
void end_model();
//! Writes a shocks statement
void end_shocks(bool overwrite);
//! Writes a mshocks statement
void end_mshocks(bool overwrite);
//! Adds a deterministic shock or a path element inside a conditional_forecast_paths block
void add_det_shock(string *var, bool conditional_forecast);
//! Adds a std error chock
void add_stderr_shock(string *var, expr_t value);
//! Adds a variance chock
void add_var_shock(string *var, expr_t value);
//! Adds a covariance chock
void add_covar_shock(string *var1, string *var2, expr_t value);
//! Adds a correlated chock
void add_correl_shock(string *var1, string *var2, expr_t value);
//! Adds a shock period range
void add_period(string *p1, string *p2);
//! Adds a shock period
void add_period(string *p1);
//! Adds a deterministic shock value
void add_value(expr_t value);
//! Adds a deterministic shock value
/*! \param v a string containing a (possibly negative) numeric constant */
void add_value(string *v);
//! Writes a Sigma_e block
void do_sigma_e();
//! Ends row of Sigma_e block
void end_of_row();
//! Adds a constant element to current row of Sigma_e
void add_to_row_const(string *v);
//! Adds an expression element to current row of Sigma_e
void add_to_row(expr_t v);
//! Write a steady command
void steady();
//! Sets an option to a numerical value
void option_num(const string &name_option, string *opt);
//! Sets an option to a numerical value
void option_num(const string &name_option, const string &opt);
//! Sets an option to a numerical value
void option_num(const string &name_option, string *opt1, string *opt2);
//! Sets an option to a string value
void option_str(const string &name_option, string *opt);
//! Sets an option to a string value
void option_str(const string &name_option, const string &opt);
//! Sets an option to a date value
void option_date(const string &name_option, string *opt);
//! Sets an option to a date value
void option_date(const string &name_option, const string &opt);
//! Sets an option to a list of symbols (used in conjunction with add_in_symbol_list())
void option_symbol_list(const string &name_option);
//! Sets an option to a vector of integers
void option_vec_int(const string &name_option, const vector<int> *opt);
//! Indicates that the model is linear
void linear();
//! Adds a variable to temporary symbol list
void add_in_symbol_list(string *tmp_var);
//! Writes a rplot() command
void rplot();
//! Writes a stock_simul command
void stoch_simul();
//! Writes a simul command
void simul();
//! Writes check command
void check();
//! Writes model_info command
void model_info();
//! Writes estimated params command
void estimated_params();
//! Writes estimated params init command
void estimated_params_init(bool use_calibration = false);
//! Writes estimated params bound command
void estimated_params_bounds();
//! Adds a declaration for a user-defined external function
void external_function();
//! Sets an external_function option to a string value
void external_function_option(const string &name_option, string *opt);
//! Sets an external_function option to a string value
void external_function_option(const string &name_option, const string &opt);
//! Add a line in an estimated params block
void add_estimated_params_element();
//! Writes osr params bounds command
void osr_params_bounds();
//! Add a line in an osr params block
void add_osr_params_element();
//! Sets the frequency of the data
void set_time(string *arg);
//! Estimation Data
void estimation_data();
//! Sets the prior for a parameter
void set_prior(string *arg1, string *arg2);
//! Sets the joint prior for a set of parameters
void set_joint_prior(vector<string *> *symbol_vec);
//! Adds a parameters to the list of joint parameters
void add_joint_parameter(string *name);
//! Adds the variance option to its temporary holding place
void set_prior_variance(expr_t variance = NULL);
//! Copies the prior from_name to_name
void copy_prior(string *to_declaration_type, string *to_name1, string *to_name2, string *to_subsample_name,
string *from_declaration_type, string *from_name1, string *from_name2, string *from_subsample_name);
//! Sets the options for a parameter
void set_options(string *arg1, string *arg2);
//! Copies the options from_name to_name
void copy_options(string *to_declaration_type, string *to_name1, string *to_name2, string *to_subsample_name,
string *from_declaration_type, string *from_name1, string *from_name2, string *from_subsample_name);
//! Sets the prior for estimated std dev
void set_std_prior(string *arg1, string *arg2);
//! Sets the options for estimated std dev
void set_std_options(string *arg1, string *arg2);
//! Sets the prior for estimated correlation
void set_corr_prior(string *arg1, string *arg2, string *arg3);
//! Sets the options for estimated correlation
void set_corr_options(string *arg1, string *arg2, string *arg3);
//! Runs estimation process
void run_estimation();
//! Runs dynare_sensitivy()
void dynare_sensitivity();
//! Adds an optimization option (string value)
void optim_options_string(string *name, string *value);
//! Adds an optimization option (numeric value)
void optim_options_num(string *name, string *value);
//! Adds an sampling option (string value)
void sampling_options_string(string *name, string *value);
//! Adds an sampling option (numeric value)
void sampling_options_num(string *name, string *value);
//! Check that no observed variable has yet be defined
void check_varobs();
//! Add a new observed variable
void add_varobs(string *name);
//! Svar_Identification Statement
void begin_svar_identification();
void end_svar_identification();
//! Svar_Identification Statement: match list of restrictions and equation number with lag
void combine_lag_and_restriction(string *lag);
//! Svar_Identification Statement: match list of restrictions with equation number
void add_restriction_in_equation(string *equation);
//! Svar_Identification Statement: add list of restriction symbol ids
void add_in_svar_restriction_symbols(string *name);
//! Svar_Identification Statement: add exclusions of constants
void add_constants_exclusion();
//! Svar_Identification Statement: add equation number for following restriction equations
void add_restriction_equation_nbr(string *eq_nbr);
//! Svar_Identification Statement: record presence of equal sign
void add_restriction_equal();
//! Svar_Idenditification Statement: add coefficient of a linear restriction (positive value)
void add_positive_restriction_element(expr_t value, string *variable, string *lag);
//! Svar_Idenditification Statement: add unit coefficient of a linear restriction
void add_positive_restriction_element(string *variable, string *lag);
//! Svar_Idenditification Statement: add coefficient of a linear restriction (negative value)
void add_negative_restriction_element(expr_t value, string *variable, string *lag);
//! Svar_Idenditification Statement: add negative unit coefficient of a linear restriction
void add_negative_restriction_element(string *variable, string *lag);
//! Svar_Idenditification Statement: add restriction element
void add_restriction_element(expr_t value, string *variable, string *lag);
//! Svar_Identification Statement: check that restriction is homogenous
void check_restriction_expression_constant(expr_t value);
//! Svar_Identification Statement: restriction of form upper cholesky
void add_upper_cholesky();
//! Svar_Identification Statement: restriction of form lower cholesky
void add_lower_cholesky();
//! Svar_Global_Identification_Check Statement
void add_svar_global_identification_check();
//! generate_irfs Block
void end_generate_irfs();
void add_generate_irfs_element(string *name);
void add_generate_irfs_exog_element(string *exo, string *value);
//! Forecast Statement
void forecast();
void set_trends();
void set_trend_element(string *arg1, expr_t arg2);
void set_unit_root_vars();
void optim_weights();
void set_optim_weights(string *name, expr_t value);
void set_optim_weights(string *name1, string *name2, expr_t value);
void set_osr_params();
void run_osr();
void run_dynasave(string *filename);
void run_dynatype(string *filename);
void run_load_params_and_steady_state(string *filename);
void run_save_params_and_steady_state(string *filename);
void run_identification();
void add_mc_filename(string *filename, string *prior = new string ("1"));
void run_model_comparison();
//! Begin a planner_objective statement
void begin_planner_objective();
//! End a planner objective statement
void end_planner_objective(expr_t expr);
//! Ramsey model statement
void ramsey_model();
//! Ramsey constraints statement
void add_ramsey_constraints_statement();
//! Ramsey less constraint
void ramsey_constraint_add_less(const string *name, const expr_t rhs);
//! Ramsey greater constraint
void ramsey_constraint_add_greater(const string *name, const expr_t rhs);
//! Ramsey less or equal constraint
void ramsey_constraint_add_less_equal(const string *name, const expr_t rhs);
//! Ramsey greater or equal constraint
void ramsey_constraint_add_greater_equal(const string *name, const expr_t rhs);
//! Ramsey constraint helper function
void add_ramsey_constraint(const string *name, BinaryOpcode op_code, const expr_t rhs);
//! Ramsey policy statement
void ramsey_policy();
//! Discretionary policy statement
void discretionary_policy();
//! Adds a write_latex_dynamic_model statement
void write_latex_dynamic_model(bool write_equation_tags);
//! Adds a write_latex_static_model statement
void write_latex_static_model(bool write_equation_tags);
//! Adds a write_latex_original_model statement
void write_latex_original_model(bool write_equation_tags);
//! Adds a write_latex_steady_state_model statement
void write_latex_steady_state_model();
//! BVAR marginal density
void bvar_density(string *maxnlags);
//! BVAR forecast
void bvar_forecast(string *nlags);
//! SBVAR statement
void sbvar();
//! Markov Switching Statement: Estimation
void ms_estimation();
//! Markov Switching Statement: Simulation
void ms_simulation();
//! Markov Switching Statement: MDD
void ms_compute_mdd();
//! Markov Switching Statement: Probabilities
void ms_compute_probabilities();
//! Markov Switching Statement: IRF
void ms_irf();
//! Markov Switching Statement: Forecast
void ms_forecast();
//! Markov Switching Statement: Variance Decomposition
void ms_variance_decomposition();
//! Svar statement
void svar();
//! MarkovSwitching statement
void markov_switching();
//! Shock decomposition
void shock_decomposition();
//! Realtime Shock decomposition
void realtime_shock_decomposition();
//! Plot Shock decomposition
void plot_shock_decomposition();
//! Initial Condition decomposition
void initial_condition_decomposition();
//! Conditional forecast statement
void conditional_forecast();
//! Conditional forecast paths block
void conditional_forecast_paths();
//! Plot conditional forecast statement
void plot_conditional_forecast(string *periods = NULL);
//! Smoother on calibrated models
void calib_smoother();
//! Extended path
void extended_path();
//! Writes token "arg1=arg2" to model tree
expr_t add_model_equal(expr_t arg1, expr_t arg2);
//! Writes token "arg=0" to model tree
expr_t add_model_equal_with_zero_rhs(expr_t arg);
//! Writes token "arg1+arg2" to model tree
expr_t add_plus(expr_t arg1, expr_t arg2);
//! Writes token "arg1-arg2" to model tree
expr_t add_minus(expr_t arg1, expr_t arg2);
//! Writes token "-arg1" to model tree
expr_t add_uminus(expr_t arg1);
//! Writes token "arg1*arg2" to model tree
expr_t add_times(expr_t arg1, expr_t arg2);
//! Writes token "arg1/arg2" to model tree
expr_t add_divide(expr_t arg1, expr_t arg2);
//! Writes token "arg1<arg2" to model tree
expr_t add_less(expr_t arg1, expr_t arg2);
//! Writes token "arg1>arg2" to model treeexpr_t
expr_t add_greater(expr_t arg1, expr_t arg2);
//! Writes token "arg1<=arg2" to model treeexpr_t
expr_t add_less_equal(expr_t arg1, expr_t arg2);
//! Writes token "arg1>=arg2" to model treeexpr_t
expr_t add_greater_equal(expr_t arg1, expr_t arg2);
//! Writes token "arg1==arg2" to model treeexpr_texpr_t
expr_t add_equal_equal(expr_t arg1, expr_t arg2);
//! Writes token "arg1!=arg2" to model treeexpr_texpr_t
expr_t add_different(expr_t arg1, expr_t arg2);
//! Writes token "arg1^arg2" to model tree
expr_t add_power(expr_t arg1, expr_t arg2);
//! Writes token "E(arg1)(arg2)" to model tree
expr_t add_expectation(string *arg1, expr_t arg2);
//! Writes token "exp(arg1)" to model tree
expr_t add_exp(expr_t arg1);
//! Writes token "log(arg1)" to model tree
expr_t add_log(expr_t arg1);
//! Writes token "log10(arg1)" to model tree
expr_t add_log10(expr_t arg1);
//! Writes token "cos(arg1)" to model tree
expr_t add_cos(expr_t arg1);
//! Writes token "sin(arg1)" to model tree
expr_t add_sin(expr_t arg1);
//! Writes token "tan(arg1)" to model tree
expr_t add_tan(expr_t arg1);
//! Writes token "acos(arg1)" to model tree
expr_t add_acos(expr_t arg1);
//! Writes token "asin(arg1)" to model tree
expr_t add_asin(expr_t arg1);
//! Writes token "atan(arg1)" to model tree
expr_t add_atan(expr_t arg1);
//! Writes token "cosh(arg1)" to model tree
expr_t add_cosh(expr_t arg1);
//! Writes token "sinh(arg1)" to model tree
expr_t add_sinh(expr_t arg1);
//! Writes token "tanh(arg1)" to model tree
expr_t add_tanh(expr_t arg1);
//! Writes token "acosh(arg1)" to model tree
expr_t add_acosh(expr_t arg1);
//! Writes token "asin(arg1)" to model tree
expr_t add_asinh(expr_t arg1);
//! Writes token "atanh(arg1)" to model tree
expr_t add_atanh(expr_t arg1);
//! Writes token "sqrt(arg1)" to model tree
expr_t add_sqrt(expr_t arg1);
//! Writes token "abs(arg1)" to model tree
expr_t add_abs(expr_t arg1);
//! Writes token "sign(arg1)" to model tree
expr_t add_sign(expr_t arg1);
//! Writes token "max(arg1,arg2)" to model tree
expr_t add_max(expr_t arg1, expr_t arg2);
//! Writes token "min(arg1,arg2)" to model tree
expr_t add_min(expr_t arg1, expr_t arg2);
//! Writes token "normcdf(arg1,arg2,arg3)" to model tree
expr_t add_normcdf(expr_t arg1, expr_t arg2, expr_t arg3);
//! Writes token "normcdf(arg,0,1)" to model tree
expr_t add_normcdf(expr_t arg);
//! Writes token "normpdf(arg1,arg2,arg3)" to model tree
expr_t add_normpdf(expr_t arg1, expr_t arg2, expr_t arg3);
//! Writes token "normpdf(arg,0,1)" to model tree
expr_t add_normpdf(expr_t arg);
//! Writes token "erf(arg)" to model tree
expr_t add_erf(expr_t arg);
//! Writes token "steadyState(arg1)" to model tree
expr_t add_steady_state(expr_t arg1);
//! Pushes empty vector onto stack when a symbol is encountered (mod_var or ext_fun)
void push_external_function_arg_vector_onto_stack();
//! Adds an external function argument
void add_external_function_arg(expr_t arg);
//! Test to see if model/external function has exactly one integer argument
pair<bool, double> is_there_one_integer_argument() const;
//! Adds an external function call node
expr_t add_model_var_or_external_function(string *function_name, bool in_model_block);
//! Adds a native statement
void add_native(const string &s);
//! Adds a native statement, first removing the set of characters passed in token (and everything after)
void add_native_remove_charset(const char *s, const string &token);
//! Adds a verbatim statement
void add_verbatim(const string &s);
//! Adds a verbatim statement, first removing the set of characters passed in token (and everything after)
void add_verbatim_remove_charset(const char *s, const string &token);
//! Resets data_tree and model_tree pointers to default (i.e. mod_file->expressions_tree)
void reset_data_tree();
//! Begin a steady_state_model block
void begin_steady_state_model();
//! Add an assignment equation in steady_state_model block
void add_steady_state_model_equal(string *varname, expr_t expr);
//! Add a multiple assignment equation in steady_state_model block
void add_steady_state_model_equal_multiple(expr_t expr);
//! Switches datatree
void begin_trend();
//! Declares a trend variable with its growth factor
void declare_trend_var(bool log_trend, string *name, string *tex_name = NULL);
//! Ends declaration of trend variable
void end_trend_var(expr_t growth_factor);
//! Declares a nonstationary variable with its deflator
void declare_nonstationary_var(string *name, string *tex_name = NULL, vector<pair<string *, string *> *> *partition_value = NULL);
//! Ends declaration of nonstationary variable
void end_nonstationary_var(bool log_deflator, expr_t deflator);
//! Add a graph format to the list of formats requested
void add_graph_format(const string &name);
//! Add the graph_format option to the OptionsList structure
void process_graph_format_option();
//! Add the graph_format option to the plot_shock_decomp substructure of the OptionsList structure
void plot_shock_decomp_process_graph_format_option();
//! Model diagnostics
void model_diagnostics();
//! Processing the parallel_local_files option
void add_parallel_local_file(string *filename);
//! Add an item of a moment_calibration statement
void add_moment_calibration_item(string *endo1, string *endo2, string *lags, vector<string *> *range);
//! End a moment_calibration statement
void end_moment_calibration();
//! Add an item of an irf_calibration statement
void add_irf_calibration_item(string *endo, string *periods, string *exo, vector<string *> *range);
//! End a moment_calibration statement
void end_irf_calibration();
//! Add a shock to a group
void add_shock_group_element(string *name);
//! Add a set of shock groups
void add_shock_group(string *name);
//! End shock groups declaration
void end_shock_groups(const string *name);
//! Add an element to the ramsey policy list
void add_to_ramsey_policy_list(string *name);
void smoother2histval();
void histval_file(string *filename);
void perfect_foresight_setup();
void perfect_foresight_solver();
void prior_posterior_function(bool prior_func);
//! GMM Estimation statement
void gmm_estimation();
//! SMM Estimation statement
void smm_estimation();
};
#endif // ! PARSING_DRIVER_HH

View File

@ -1,631 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <cstdlib>
#include <iostream>
#include "Shocks.hh"
AbstractShocksStatement::AbstractShocksStatement(bool mshocks_arg,
bool overwrite_arg,
const det_shocks_t &det_shocks_arg,
const SymbolTable &symbol_table_arg) :
mshocks(mshocks_arg),
overwrite(overwrite_arg),
det_shocks(det_shocks_arg),
symbol_table(symbol_table_arg)
{
}
void
AbstractShocksStatement::writeDetShocks(ostream &output) const
{
int exo_det_length = 0;
for (det_shocks_t::const_iterator it = det_shocks.begin();
it != det_shocks.end(); it++)
{
int id = symbol_table.getTypeSpecificID(it->first) + 1;
bool exo_det = (symbol_table.getType(it->first) == eExogenousDet);
for (size_t i = 0; i < it->second.size(); i++)
{
const int &period1 = it->second[i].period1;
const int &period2 = it->second[i].period2;
const expr_t value = it->second[i].value;
output << "M_.det_shocks = [ M_.det_shocks;" << endl
<< "struct('exo_det'," << (int) exo_det
<< ",'exo_id'," << id
<< ",'multiplicative'," << (int) mshocks
<< ",'periods'," << period1 << ":" << period2
<< ",'value',";
value->writeOutput(output);
output << ") ];" << endl;
if (exo_det && (period2 > exo_det_length))
exo_det_length = period2;
}
}
output << "M_.exo_det_length = " << exo_det_length << ";\n";
}
void
AbstractShocksStatement::writeJsonDetShocks(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "\"deterministic_shocks\": [";
for (det_shocks_t::const_iterator it = det_shocks.begin();
it != det_shocks.end(); it++)
{
if (it != det_shocks.begin())
output << ", ";
output << "{\"var\": \"" << symbol_table.getName(it->first) << "\", "
<< "\"values\": [";
for (vector<DetShockElement>::const_iterator it1 = it->second.begin();
it1 != it->second.end(); it1++)
{
if (it1 != it->second.begin())
output << ", ";
output << "{\"period1\": " << it1->period1 << ", "
<< "\"period2\": " << it1->period2 << ", "
<< "\"value\": \"";
it1->value->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
output << "]}";
}
output << "]";
}
ShocksStatement::ShocksStatement(bool overwrite_arg,
const det_shocks_t &det_shocks_arg,
const var_and_std_shocks_t &var_shocks_arg,
const var_and_std_shocks_t &std_shocks_arg,
const covar_and_corr_shocks_t &covar_shocks_arg,
const covar_and_corr_shocks_t &corr_shocks_arg,
const SymbolTable &symbol_table_arg) :
AbstractShocksStatement(false, overwrite_arg, det_shocks_arg, symbol_table_arg),
var_shocks(var_shocks_arg),
std_shocks(std_shocks_arg),
covar_shocks(covar_shocks_arg),
corr_shocks(corr_shocks_arg)
{
}
void
ShocksStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "%" << endl
<< "% SHOCKS instructions" << endl
<< "%" << endl;
if (overwrite)
{
output << "M_.det_shocks = [];" << endl;
output << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ");" << endl
<< "M_.Correlation_matrix = eye(" << symbol_table.exo_nbr() << ", "
<< symbol_table.exo_nbr() << ");" << endl;
if (has_calibrated_measurement_errors())
output << "M_.H = zeros(" << symbol_table.observedVariablesNbr() << ", "
<< symbol_table.observedVariablesNbr() << ");" << endl
<< "M_.Correlation_matrix_ME = eye(" << symbol_table.observedVariablesNbr() << ", "
<< symbol_table.observedVariablesNbr() << ");" << endl;
else
output << "M_.H = 0;" << endl
<< "M_.Correlation_matrix_ME = 1;" << endl;
}
writeDetShocks(output);
writeVarAndStdShocks(output);
writeCovarAndCorrShocks(output);
/* M_.sigma_e_is_diagonal is initialized to 1 by ModFile.cc.
If there are no off-diagonal elements, and we are not in overwrite mode,
then we don't reset it to 1, since there might be previous shocks blocks
with off-diagonal elements. */
if (covar_shocks.size()+corr_shocks.size() > 0)
output << "M_.sigma_e_is_diagonal = 0;" << endl;
else if (overwrite)
output << "M_.sigma_e_is_diagonal = 1;" << endl;
}
void
ShocksStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"shocks\""
<< ", \"overwrite\": ";
if (overwrite)
output << "true";
else
output << "false";
if (!det_shocks.empty())
{
output << ", ";
writeJsonDetShocks(output);
}
output<< ", \"variance\": [";
for (var_and_std_shocks_t::const_iterator it = var_shocks.begin(); it != var_shocks.end(); it++)
{
if (it != var_shocks.begin())
output << ", ";
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", "
<< "\"variance\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
output << "]"
<< ", \"stderr\": [";
for (var_and_std_shocks_t::const_iterator it = std_shocks.begin(); it != std_shocks.end(); it++)
{
if (it != std_shocks.begin())
output << ", ";
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", "
<< "\"stderr\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
output << "]"
<< ", \"covariance\": [";
for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin(); it != covar_shocks.end(); it++)
{
if (it != covar_shocks.begin())
output << ", ";
output << "{"
<< "\"name\": \"" << symbol_table.getName(it->first.first) << "\", "
<< "\"name2\": \"" << symbol_table.getName(it->first.second) << "\", "
<< "\"covariance\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
output << "]"
<< ", \"correlation\": [";
for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin(); it != corr_shocks.end(); it++)
{
if (it != corr_shocks.begin())
output << ", ";
output << "{"
<< "\"name\": \"" << symbol_table.getName(it->first.first) << "\", "
<< "\"name2\": \"" << symbol_table.getName(it->first.second) << "\", "
<< "\"correlation\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
output << "\"}";
}
output << "]"
<< "}";
}
void
ShocksStatement::writeVarOrStdShock(ostream &output, var_and_std_shocks_t::const_iterator &it,
bool stddev) const
{
SymbolType type = symbol_table.getType(it->first);
assert(type == eExogenous || symbol_table.isObservedVariable(it->first));
int id;
if (type == eExogenous)
{
output << "M_.Sigma_e(";
id = symbol_table.getTypeSpecificID(it->first) + 1;
}
else
{
output << "M_.H(";
id = symbol_table.getObservedVariableIndex(it->first) + 1;
}
output << id << ", " << id << ") = ";
if (stddev)
output << "(";
it->second->writeOutput(output);
if (stddev)
output << ")^2";
output << ";" << endl;
}
void
ShocksStatement::writeVarAndStdShocks(ostream &output) const
{
var_and_std_shocks_t::const_iterator it;
for (it = var_shocks.begin(); it != var_shocks.end(); it++)
writeVarOrStdShock(output, it, false);
for (it = std_shocks.begin(); it != std_shocks.end(); it++)
writeVarOrStdShock(output, it, true);
}
void
ShocksStatement::writeCovarOrCorrShock(ostream &output, covar_and_corr_shocks_t::const_iterator &it,
bool corr) const
{
SymbolType type1 = symbol_table.getType(it->first.first);
SymbolType type2 = symbol_table.getType(it->first.second);
assert((type1 == eExogenous && type2 == eExogenous)
|| (symbol_table.isObservedVariable(it->first.first) && symbol_table.isObservedVariable(it->first.second)));
string matrix, corr_matrix;
int id1, id2;
if (type1 == eExogenous)
{
matrix = "M_.Sigma_e";
corr_matrix = "M_.Correlation_matrix";
id1 = symbol_table.getTypeSpecificID(it->first.first) + 1;
id2 = symbol_table.getTypeSpecificID(it->first.second) + 1;
}
else
{
matrix = "M_.H";
corr_matrix = "M_.Correlation_matrix_ME";
id1 = symbol_table.getObservedVariableIndex(it->first.first) + 1;
id2 = symbol_table.getObservedVariableIndex(it->first.second) + 1;
}
output << matrix << "(" << id1 << ", " << id2 << ") = ";
it->second->writeOutput(output);
if (corr)
output << "*sqrt(" << matrix << "(" << id1 << ", " << id1 << ")*"
<< matrix << "(" << id2 << ", " << id2 << "))";
output << ";" << endl
<< matrix << "(" << id2 << ", " << id1 << ") = "
<< matrix << "(" << id1 << ", " << id2 << ");" << endl;
if (corr)
{
output << corr_matrix << "(" << id1 << ", " << id2 << ") = ";
it->second->writeOutput(output);
output << ";" << endl
<< corr_matrix << "(" << id2 << ", " << id1 << ") = "
<< corr_matrix << "(" << id1 << ", " << id2 << ");" << endl;
}
}
void
ShocksStatement::writeCovarAndCorrShocks(ostream &output) const
{
covar_and_corr_shocks_t::const_iterator it;
for (it = covar_shocks.begin(); it != covar_shocks.end(); it++)
writeCovarOrCorrShock(output, it, false);
for (it = corr_shocks.begin(); it != corr_shocks.end(); it++)
writeCovarOrCorrShock(output, it, true);
}
void
ShocksStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
/* Error out if variables are not of the right type. This must be done here
and not at parsing time (see #448).
Also Determine if there is a calibrated measurement error */
for (var_and_std_shocks_t::const_iterator it = var_shocks.begin();
it != var_shocks.end(); it++)
{
if (symbol_table.getType(it->first) != eExogenous
&& !symbol_table.isObservedVariable(it->first))
{
cerr << "shocks: setting a variance on '"
<< symbol_table.getName(it->first) << "' is not allowed, because it is neither an exogenous variable nor an observed endogenous variable" << endl;
exit(EXIT_FAILURE);
}
}
for (var_and_std_shocks_t::const_iterator it = std_shocks.begin();
it != std_shocks.end(); it++)
{
if (symbol_table.getType(it->first) != eExogenous
&& !symbol_table.isObservedVariable(it->first))
{
cerr << "shocks: setting a standard error on '"
<< symbol_table.getName(it->first) << "' is not allowed, because it is neither an exogenous variable nor an observed endogenous variable" << endl;
exit(EXIT_FAILURE);
}
}
for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin();
it != covar_shocks.end(); it++)
{
int symb_id1 = it->first.first;
int symb_id2 = it->first.second;
if (!((symbol_table.getType(symb_id1) == eExogenous
&& symbol_table.getType(symb_id2) == eExogenous)
|| (symbol_table.isObservedVariable(symb_id1)
&& symbol_table.isObservedVariable(symb_id2))))
{
cerr << "shocks: setting a covariance between '"
<< symbol_table.getName(symb_id1) << "' and '"
<< symbol_table.getName(symb_id2) << "'is not allowed; covariances can only be specified for exogenous or observed endogenous variables of same type" << endl;
exit(EXIT_FAILURE);
}
}
for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin();
it != corr_shocks.end(); it++)
{
int symb_id1 = it->first.first;
int symb_id2 = it->first.second;
if (!((symbol_table.getType(symb_id1) == eExogenous
&& symbol_table.getType(symb_id2) == eExogenous)
|| (symbol_table.isObservedVariable(symb_id1)
&& symbol_table.isObservedVariable(symb_id2))))
{
cerr << "shocks: setting a correlation between '"
<< symbol_table.getName(symb_id1) << "' and '"
<< symbol_table.getName(symb_id2) << "'is not allowed; correlations can only be specified for exogenous or observed endogenous variables of same type" << endl;
exit(EXIT_FAILURE);
}
}
// Determine if there is a calibrated measurement error
mod_file_struct.calibrated_measurement_errors |= has_calibrated_measurement_errors();
// Fill in mod_file_struct.parameters_with_shocks_values (related to #469)
for (var_and_std_shocks_t::const_iterator it = var_shocks.begin();
it != var_shocks.end(); ++it)
it->second->collectVariables(eParameter, mod_file_struct.parameters_within_shocks_values);
for (var_and_std_shocks_t::const_iterator it = std_shocks.begin();
it != std_shocks.end(); ++it)
it->second->collectVariables(eParameter, mod_file_struct.parameters_within_shocks_values);
for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin();
it != covar_shocks.end(); ++it)
it->second->collectVariables(eParameter, mod_file_struct.parameters_within_shocks_values);
for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin();
it != corr_shocks.end(); ++it)
it->second->collectVariables(eParameter, mod_file_struct.parameters_within_shocks_values);
}
bool
ShocksStatement::has_calibrated_measurement_errors() const
{
for (var_and_std_shocks_t::const_iterator it = var_shocks.begin();
it != var_shocks.end(); it++)
if (symbol_table.isObservedVariable(it->first))
return true;
for (var_and_std_shocks_t::const_iterator it = std_shocks.begin();
it != std_shocks.end(); it++)
if (symbol_table.isObservedVariable(it->first))
return true;
for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin();
it != covar_shocks.end(); it++)
if (symbol_table.isObservedVariable(it->first.first)
|| symbol_table.isObservedVariable(it->first.second))
return true;
for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin();
it != corr_shocks.end(); it++)
if (symbol_table.isObservedVariable(it->first.first)
|| symbol_table.isObservedVariable(it->first.second))
return true;
return false;
}
MShocksStatement::MShocksStatement(bool overwrite_arg,
const det_shocks_t &det_shocks_arg,
const SymbolTable &symbol_table_arg) :
AbstractShocksStatement(true, overwrite_arg, det_shocks_arg, symbol_table_arg)
{
}
void
MShocksStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "%" << endl
<< "% MSHOCKS instructions" << endl
<< "%" << endl;
if (overwrite)
output << "M_.det_shocks = [];" << endl;
writeDetShocks(output);
}
ConditionalForecastPathsStatement::ConditionalForecastPathsStatement(const AbstractShocksStatement::det_shocks_t &paths_arg,
const SymbolTable &symbol_table_arg) :
paths(paths_arg),
symbol_table(symbol_table_arg),
path_length(-1)
{
}
void
ConditionalForecastPathsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
for (AbstractShocksStatement::det_shocks_t::const_iterator it = paths.begin();
it != paths.end(); it++)
{
int this_path_length = 0;
const vector<AbstractShocksStatement::DetShockElement> &elems = it->second;
for (int i = 0; i < (int) elems.size(); i++)
// Period1 < Period2, as enforced in ParsingDriver::add_period()
this_path_length = max(this_path_length, elems[i].period2);
if (path_length == -1)
path_length = this_path_length;
else if (path_length != this_path_length)
{
cerr << "conditional_forecast_paths: all constrained paths must have the same length!" << endl;
exit(EXIT_FAILURE);
}
}
}
void
ConditionalForecastPathsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
assert(path_length > 0);
output << "constrained_vars_ = [];" << endl
<< "constrained_paths_ = zeros(" << paths.size() << ", " << path_length << ");" << endl;
int k = 1;
for (AbstractShocksStatement::det_shocks_t::const_iterator it = paths.begin();
it != paths.end(); it++, k++)
{
if (it == paths.begin())
output << "constrained_vars_ = " << symbol_table.getTypeSpecificID(it->first) + 1 << ";" << endl;
else
output << "constrained_vars_ = [constrained_vars_; " << symbol_table.getTypeSpecificID(it->first) + 1 << "];" << endl;
const vector<AbstractShocksStatement::DetShockElement> &elems = it->second;
for (int i = 0; i < (int) elems.size(); i++)
for (int j = elems[i].period1; j <= elems[i].period2; j++)
{
output << "constrained_paths_(" << k << "," << j << ")=";
elems[i].value->writeOutput(output);
output << ";" << endl;
}
}
}
MomentCalibration::MomentCalibration(const constraints_t &constraints_arg,
const SymbolTable &symbol_table_arg)
: constraints(constraints_arg), symbol_table(symbol_table_arg)
{
}
void
MomentCalibration::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "options_.endogenous_prior_restrictions.moment = {" << endl;
for (size_t i = 0; i < constraints.size(); i++)
{
const Constraint &c = constraints[i];
output << "'" << symbol_table.getName(c.endo1) << "', "
<< "'" << symbol_table.getName(c.endo2) << "', "
<< c.lags << ", "
<< "[ " << c.lower_bound << ", " << c.upper_bound << " ];"
<< endl;
}
output << "};" << endl;
}
void
MomentCalibration::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"moment_calibration\""
<< ", \"moment_calibration_criteria\": [";
for (constraints_t::const_iterator it = constraints.begin(); it != constraints.end(); it++)
{
if (it != constraints.begin())
output << ", ";
output << "{\"endogenous1\": \"" << symbol_table.getName(it->endo1) << "\""
<< ", \"endogenous2\": \"" << symbol_table.getName(it->endo2) << "\""
<< ", \"lags\": \"" << it->lags << "\""
<< ", \"lower_bound\": \"" << it->lower_bound << "\""
<< ", \"upper_bound\": \"" << it->upper_bound << "\""
<< "}";
}
output << "]"
<< "}";
}
IrfCalibration::IrfCalibration(const constraints_t &constraints_arg,
const SymbolTable &symbol_table_arg,
const OptionsList &options_list_arg)
: constraints(constraints_arg), symbol_table(symbol_table_arg), options_list(options_list_arg)
{
}
void
IrfCalibration::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
options_list.writeOutput(output);
output << "options_.endogenous_prior_restrictions.irf = {" << endl;
for (size_t i = 0; i < constraints.size(); i++)
{
const Constraint &c = constraints[i];
output << "'" << symbol_table.getName(c.endo) << "', "
<< "'" << symbol_table.getName(c.exo) << "', "
<< c.periods << ", "
<< "[ " << c.lower_bound << ", " << c.upper_bound << " ];"
<< endl;
}
output << "};" << endl;
}
void
IrfCalibration::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"irf_calibration\"";
if (options_list.getNumberOfOptions())
{
output << ", ";
options_list.writeJsonOutput(output);
}
output << ", \"irf_restrictions\": [";
for (constraints_t::const_iterator it = constraints.begin(); it != constraints.end(); it++)
{
if (it != constraints.begin())
output << ", ";
output << "{\"endogenous\": \"" << symbol_table.getName(it->endo) << "\""
<< ", \"exogenous\": \"" << symbol_table.getName(it->exo) << "\""
<< ", \"periods\": \"" << it->periods << "\""
<< ", \"lower_bound\": \"" << it->lower_bound << "\""
<< ", \"upper_bound\": \"" << it->upper_bound << "\""
<< "}";
}
output << "]"
<< "}";
}
ShockGroupsStatement::ShockGroupsStatement(const group_t &shock_groups_arg, const string &name_arg)
: shock_groups(shock_groups_arg), name(name_arg)
{
}
void
ShockGroupsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
int i = 1;
bool unique_label = true;
for (vector<Group>::const_iterator it = shock_groups.begin(); it != shock_groups.end(); it++, unique_label = true)
{
for (vector<Group>::const_iterator it1 = it+1; it1 != shock_groups.end(); it1++)
if (it->name == it1->name)
{
unique_label = false;
cerr << "Warning: shock group label '" << it->name << "' has been reused. "
<< "Only using the last definition." << endl;
break;
}
if (unique_label)
{
output << "M_.shock_groups." << name
<< ".group" << i << ".label = '" << it->name << "';" << endl
<< "M_.shock_groups." << name
<< ".group" << i << ".shocks = {";
for (vector<string>::const_iterator it1 = it->list.begin(); it1 != it->list.end(); it1++)
output << " '" << *it1 << "'";
output << "};" << endl;
i++;
}
}
}

View File

@ -1,168 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SHOCKS_HH
#define _SHOCKS_HH
using namespace std;
#include <string>
#include <vector>
#include <map>
#include "Statement.hh"
#include "SymbolTable.hh"
#include "ExprNode.hh"
class AbstractShocksStatement : public Statement
{
public:
struct DetShockElement
{
int period1;
int period2;
expr_t value;
};
//The boolean element indicates if the shock is a surprise (false) or a perfect foresight (true) shock.
//This boolean is used only in case of conditional forecast with extended path method (simulation_type = deterministic).
typedef map<int, vector<DetShockElement> > det_shocks_t;
protected:
//! Is this statement a "mshocks" statement ? (instead of a "shocks" statement)
const bool mshocks;
//! Does this "shocks" statement replace the previous ones?
const bool overwrite;
const det_shocks_t det_shocks;
const SymbolTable &symbol_table;
void writeDetShocks(ostream &output) const;
void writeJsonDetShocks(ostream &output) const;
AbstractShocksStatement(bool mshocks_arg, bool overwrite_arg,
const det_shocks_t &det_shocks_arg,
const SymbolTable &symbol_table_arg);
};
class ShocksStatement : public AbstractShocksStatement
{
public:
typedef map<int, expr_t> var_and_std_shocks_t;
typedef map<pair<int, int>, expr_t> covar_and_corr_shocks_t;
private:
const var_and_std_shocks_t var_shocks, std_shocks;
const covar_and_corr_shocks_t covar_shocks, corr_shocks;
void writeVarOrStdShock(ostream &output, var_and_std_shocks_t::const_iterator &it, bool stddev) const;
void writeVarAndStdShocks(ostream &output) const;
void writeCovarOrCorrShock(ostream &output, covar_and_corr_shocks_t::const_iterator &it, bool corr) const;
void writeCovarAndCorrShocks(ostream &output) const;
bool has_calibrated_measurement_errors() const;
public:
ShocksStatement(bool overwrite_arg,
const det_shocks_t &det_shocks_arg,
const var_and_std_shocks_t &var_shocks_arg,
const var_and_std_shocks_t &std_shocks_arg,
const covar_and_corr_shocks_t &covar_shocks_arg,
const covar_and_corr_shocks_t &corr_shocks_arg,
const SymbolTable &symbol_table_arg);
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class MShocksStatement : public AbstractShocksStatement
{
public:
MShocksStatement(bool overwrite_arg,
const det_shocks_t &det_shocks_arg,
const SymbolTable &symbol_table_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
};
class ConditionalForecastPathsStatement : public Statement
{
private:
const AbstractShocksStatement::det_shocks_t paths;
const SymbolTable &symbol_table;
int path_length;
public:
ConditionalForecastPathsStatement(const AbstractShocksStatement::det_shocks_t &paths_arg,
const SymbolTable &symbol_table_arg);
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
};
class MomentCalibration : public Statement
{
public:
struct Constraint
{
int endo1, endo2;
string lags;
string lower_bound, upper_bound;
};
typedef vector<Constraint> constraints_t;
private:
constraints_t constraints;
const SymbolTable &symbol_table;
public:
MomentCalibration(const constraints_t &constraints_arg,
const SymbolTable &symbol_table_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class IrfCalibration : public Statement
{
public:
struct Constraint
{
int endo;
int exo;
string periods, lower_bound, upper_bound;
};
typedef vector<Constraint> constraints_t;
private:
constraints_t constraints;
const SymbolTable &symbol_table;
const OptionsList options_list;
public:
IrfCalibration(const constraints_t &constraints_arg,
const SymbolTable &symbol_table_arg,
const OptionsList &options_list_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class ShockGroupsStatement : public Statement
{
public:
struct Group
{
string name;
vector<string> list;
};
typedef vector<Group> group_t;
private:
group_t shock_groups;
vector<string> group_names;
string name;
public:
ShockGroupsStatement(const group_t &shock_groups_arg, const string &name_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
};
#endif

View File

@ -1,98 +0,0 @@
/*
* Copyright (C) 2003-2015 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SigmaeInitialization.hh"
SigmaeStatement::SigmaeStatement(const matrix_t &matrix_arg) throw (MatrixFormException) :
matrix(matrix_arg),
matrix_form(determineMatrixForm(matrix))
{
}
SigmaeStatement::matrix_form_t
SigmaeStatement::determineMatrixForm(const matrix_t &matrix) throw (MatrixFormException)
{
size_t nbe;
int inc;
matrix_form_t type;
// Checking if first or last row has one element.
if (matrix.front().size() == 1)
{
inc = 1;
nbe = 2;
type = eLower;
}
else if (matrix.back().size() == 1)
{
inc = -1;
nbe = matrix.front().size()-1;
type = eUpper;
}
else
throw MatrixFormException();
// Checking if matrix is triangular (upper or lower):
// each row has one element more or less than the previous one
// and first or last one has one element.
matrix_t::const_iterator ir;
for (ir = matrix.begin(), ir++; ir != matrix.end(); ir++, nbe += inc)
if (ir->size() != nbe)
throw MatrixFormException();
return type;
}
void
SigmaeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
size_t ic, ic1, ir, ir1;
output << "M_.Sigma_e = [..." << endl;
for (ir = 0; ir < matrix.size(); ir++)
{
for (ic = 0; ic < matrix.size(); ic++)
{
if (ic >= ir && matrix_form == eUpper)
{
ic1 = ic-ir;
ir1 = ir;
}
else if (ic < ir && matrix_form == eUpper)
{
ic1 = ir-ic;
ir1 = ic;
}
else if (ic > ir && matrix_form == eLower)
{
ic1 = ir;
ir1 = ic;
}
else // ic <= ir && matrix_form == eLower
{
ic1 = ic;
ir1 = ir;
}
matrix[ir1][ic1]->writeOutput(output);
output << " ";
}
output << ";..." << endl;
}
output << "];" << endl;
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (C) 2003-2015 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SIGMAEINITIALIZATION_HH
#define _SIGMAEINITIALIZATION_HH
#include <string>
#include <vector>
#include "ExprNode.hh"
#include "Statement.hh"
//! Stores a Sigma_e statement
class SigmaeStatement : public Statement
{
public:
//! Matrix form (lower or upper triangular) enum
enum matrix_form_t
{
eLower = 0, //!< Lower triangular matrix
eUpper = 1 //!< Upper triangular matrix
};
//! Type of a matrix row
typedef vector<expr_t> row_t;
//! Type of a complete matrix
typedef vector<row_t> matrix_t;
//! An exception indicating that a matrix is neither upper triangular nor lower triangular
class MatrixFormException
{
};
private:
//! The matrix
const matrix_t matrix;
//! Matrix form (lower or upper)
const matrix_form_t matrix_form;
//! Returns the type (upper or lower triangular) of a given matrix
/*! Throws an exception if it is neither upper triangular nor lower triangular */
static matrix_form_t determineMatrixForm(const matrix_t &matrix) throw (MatrixFormException);
public:
SigmaeStatement(const matrix_t &matrix_arg) throw (MatrixFormException);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
};
#endif

View File

@ -1,349 +0,0 @@
/*
* Copyright (C) 2006-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Statement.hh"
#include <boost/xpressive/xpressive.hpp>
ModFileStructure::ModFileStructure() :
check_present(false),
steady_present(false),
perfect_foresight_solver_present(false),
stoch_simul_present(false),
estimation_present(false),
osr_present(false),
osr_params_present(false),
optim_weights_present(false),
ramsey_model_present(false),
ramsey_policy_present(false),
discretionary_policy_present(false),
planner_objective_present(false),
extended_path_present(false),
order_option(0),
bvar_present(false),
svar_identification_present(false),
identification_present(false),
estimation_analytic_derivation(false),
partial_information(false),
k_order_solver(false),
calibrated_measurement_errors(false),
dsge_prior_weight_in_estimated_params(false),
dsge_var_calibrated(""),
dsge_var_estimated(false),
bayesian_irf_present(false),
estimation_data_statement_present(false),
last_markov_switching_chain(0),
calib_smoother_present(false),
estim_params_use_calib(false),
prior_statement_present(false),
std_prior_statement_present(false),
corr_prior_statement_present(false),
options_statement_present(false),
std_options_statement_present(false),
corr_options_statement_present(false),
ms_dsge_present(false),
occbin_option(false),
orig_eq_nbr(0),
ramsey_eq_nbr(0),
steady_state_model_present(false),
write_latex_steady_state_model_present(false)
{
}
Statement::~Statement()
{
}
void
Statement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
}
void
Statement::writeCOutput(ostream &output, const string &basename)
{
}
void
Statement::writeJuliaOutput(ostream &output, const string &basename)
{
}
void
Statement::writeJsonOutput(ostream &output) const
{
}
void
Statement::computingPass()
{
}
NativeStatement::NativeStatement(const string &native_statement_arg) :
native_statement(native_statement_arg)
{
}
void
NativeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
using namespace boost::xpressive;
string date_regex = "(-?\\d+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4]\\d|5[0-2])))";
sregex regex_lookbehind = sregex::compile("(?<!\\$|\\d|[a-zA-Z_]|\\')" + date_regex);
sregex regex_dollar = sregex::compile("(\\$)"+date_regex);
string ns = regex_replace(native_statement, regex_lookbehind, "dates('$&')");
ns = regex_replace(ns, regex_dollar, "$2"); //replace $DATE with DATE
output << ns << endl;
}
void
NativeStatement::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"native\""
<< ", \"string\": \"" << native_statement << "\""
<< "}";
}
VerbatimStatement::VerbatimStatement(const string &verbatim_statement_arg) :
verbatim_statement(verbatim_statement_arg)
{
}
void
VerbatimStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << verbatim_statement << endl;
}
void
VerbatimStatement::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"verbatim\""
<< ", \"string\": \"" << verbatim_statement << "\""
<< "}";
}
void
OptionsList::writeOutput(ostream &output) const
{
for (num_options_t::const_iterator it = num_options.begin();
it != num_options.end(); it++)
output << "options_." << it->first << " = " << it->second << ";" << endl;
for (paired_num_options_t::const_iterator it = paired_num_options.begin();
it != paired_num_options.end(); it++)
output << "options_." << it->first << " = [" << it->second.first << "; "
<< it->second.second << "];" << endl;
for (string_options_t::const_iterator it = string_options.begin();
it != string_options.end(); it++)
output << "options_." << it->first << " = '" << it->second << "';" << endl;
for (date_options_t::const_iterator it = date_options.begin();
it != date_options.end(); it++)
output << "options_." << it->first << " = " << it->second << ";" << endl;
for (symbol_list_options_t::const_iterator it = symbol_list_options.begin();
it != symbol_list_options.end(); it++)
it->second.writeOutput("options_." + it->first, output);
for (vec_int_options_t::const_iterator it = vector_int_options.begin();
it != vector_int_options.end(); it++)
{
output << "options_." << it->first << " = ";
if (it->second.size() > 1)
{
output << "[";
for (vector<int>::const_iterator viit = it->second.begin();
viit != it->second.end(); viit++)
output << *viit << ";";
output << "];" << endl;
}
else
output << it->second.front() << ";" << endl;
}
}
void
OptionsList::writeOutput(ostream &output, const string &option_group) const
{
// Initialize option_group as an empty struct iff the field does not exist!
unsigned idx = option_group.find_last_of(".");
if (idx < UINT_MAX)
{
output << "if ~isfield(" << option_group.substr(0, idx) << ",'" << option_group.substr(idx+1) << "')" << endl;
output << " " << option_group << " = struct();" << endl;
output << "end" << endl;
}
else
output << option_group << " = struct();" << endl;
for (num_options_t::const_iterator it = num_options.begin();
it != num_options.end(); it++)
output << option_group << "." << it->first << " = " << it->second << ";" << endl;
for (paired_num_options_t::const_iterator it = paired_num_options.begin();
it != paired_num_options.end(); it++)
output << option_group << "." << it->first << " = [" << it->second.first << "; "
<< it->second.second << "];" << endl;
for (string_options_t::const_iterator it = string_options.begin();
it != string_options.end(); it++)
output << option_group << "." << it->first << " = '" << it->second << "';" << endl;
for (date_options_t::const_iterator it = date_options.begin();
it != date_options.end(); it++)
output << option_group << "." << it->first << " = " << it->second << ";" << endl;
for (symbol_list_options_t::const_iterator it = symbol_list_options.begin();
it != symbol_list_options.end(); it++)
it->second.writeOutput(option_group + "." + it->first, output);
for (vec_int_options_t::const_iterator it = vector_int_options.begin();
it != vector_int_options.end(); it++)
{
output << option_group << "." << it->first << " = ";
if (it->second.size() > 1)
{
output << "[";
for (vector<int>::const_iterator viit = it->second.begin();
viit != it->second.end(); viit++)
output << *viit << ";";
output << "];" << endl;
}
else
output << it->second.front() << ";" << endl;
}
}
void
OptionsList::writeJsonOutput(ostream &output) const
{
if (getNumberOfOptions() == 0)
return;
output << "\"options\": {";
for (num_options_t::const_iterator it = num_options.begin();
it != num_options.end();)
{
output << "\""<< it->first << "\": " << it->second;
it++;
if (it != num_options.end()
|| !(paired_num_options.empty()
&& string_options.empty()
&& date_options.empty()
&& symbol_list_options.empty()
&& vector_int_options.empty()))
output << ", ";
}
for (paired_num_options_t::const_iterator it = paired_num_options.begin();
it != paired_num_options.end();)
{
output << "\""<< it->first << "\": [" << it->second.first << " " << it->second.second << "]";
it++;
if (it != paired_num_options.end()
|| !(string_options.empty()
&& date_options.empty()
&& symbol_list_options.empty()
&& vector_int_options.empty()))
output << ", ";
}
for (string_options_t::const_iterator it = string_options.begin();
it != string_options.end();)
{
output << "\""<< it->first << "\": \"" << it->second << "\"";
it++;
if (it != string_options.end()
|| !(date_options.empty()
&& symbol_list_options.empty()
&& vector_int_options.empty()))
output << ", ";
}
for (date_options_t::const_iterator it = date_options.begin();
it != date_options.end();)
{
output << "\""<< it->first << "\": \"" << it->second << "\"";
it++;
if (it != date_options.end()
|| !(symbol_list_options.empty()
&& vector_int_options.empty()))
output << ", ";
}
for (symbol_list_options_t::const_iterator it = symbol_list_options.begin();
it != symbol_list_options.end(); it++)
{
output << "\""<< it->first << "\":";
it->second.writeJsonOutput(output);
it++;
if (it != symbol_list_options.end()
|| !vector_int_options.empty())
output << ", ";
}
for (vec_int_options_t::const_iterator it = vector_int_options.begin();
it != vector_int_options.end();)
{
output << "\""<< it->first << "\": [";
if (it->second.size() > 1)
{
for (vector<int>::const_iterator viit = it->second.begin();
viit != it->second.end();)
{
output << *viit;
viit++;
if (viit != it->second.end())
output << ", ";
}
}
else
output << it->second.front() << endl;
output << "]";
it++;
if (it != vector_int_options.end())
output << ", ";
}
output << "}";
}
void
OptionsList::clear()
{
num_options.clear();
paired_num_options.clear();
string_options.clear();
date_options.clear();
symbol_list_options.clear();
vector_int_options.clear();
}
int
OptionsList::getNumberOfOptions() const
{
return num_options.size()
+ paired_num_options.size()
+ string_options.size()
+ date_options.size()
+ symbol_list_options.size()
+ vector_int_options.size();
}

View File

@ -1,195 +0,0 @@
/*
* Copyright (C) 2006-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _STATEMENT_HH
#define _STATEMENT_HH
#include <ostream>
#include <string>
#include <map>
#include <set>
#include "SymbolList.hh"
#include "WarningConsolidation.hh"
class ModFileStructure
{
public:
ModFileStructure();
//! Whether check is present
bool check_present;
//! Whether steady is present
bool steady_present;
//! Whether a perfect_foresight_solver/simul statement is present
bool perfect_foresight_solver_present;
//! Whether a stoch_simul statement is present
bool stoch_simul_present;
//! Whether an estimation statement is present
bool estimation_present;
//! Whether an osr statement is present
bool osr_present;
//! Whether an osr params statement is present
bool osr_params_present;
//! Whether an optim weight statement is present
bool optim_weights_present;
//! Whether a ramsey_model statement is present
bool ramsey_model_present;
//! Whether a ramsey_policy statement is present
bool ramsey_policy_present;
//! Whether a discretionary_objective statement is present
bool discretionary_policy_present;
//! Whether a planner_objective statement is present
bool planner_objective_present;
//! Whether an extended_path statement is present
bool extended_path_present;
//! The value of the "order" option of stoch_simul, estimation, osr, ramsey_policy
//! Derivation order
/*! First initialized to zero. If user sets order option somewhere in the MOD file, it will be equal to the maximum of order options. Otherwise will default to 2 */
int order_option;
//! Whether a bvar_density, bvar_forecast, sbvar, ms_sbvar statement is present
bool bvar_present;
//! Whether an svar_identification statement is present
bool svar_identification_present;
//! Whether an identification statement is present or the identification option of dynare_sensitivity statement is equal to one
bool identification_present;
//! Whether the option analytic_derivation is given to estimation
bool estimation_analytic_derivation;
//! Whether the option partial_information is given to stoch_simul/estimation/osr/ramsey_policy
bool partial_information;
//! Whether the "k_order_solver" option is used (explictly, or implicitly if order >= 3)
bool k_order_solver;
//! Whether there is a calibrated measurement error
bool calibrated_measurement_errors;
//! Whether dsge_prior_weight was initialized as a parameter
bool dsge_prior_weight_initialized;
//! Whether dsge_prior_weight is in the estimated_params block
bool dsge_prior_weight_in_estimated_params;
//! Whether there is a dsge_var, with calibrated prior weight
string dsge_var_calibrated;
//! Whether there is a dsge_var, with prior weight that must be estimated
bool dsge_var_estimated;
//! Whether there is a bayesian_irf option passed to the estimation statement
bool bayesian_irf_present;
//! Whether there is a data statement present
bool estimation_data_statement_present;
//! Last chain number for Markov Switching statement2
int last_markov_switching_chain;
//! Whether a calib_smoother statement is present
bool calib_smoother_present;
//! Whether there is an estimated_params_init with use_calibration
bool estim_params_use_calib;
//! Set of parameters used within shocks blocks, inside the expressions
//! defining the values of covariances (stored as symbol ids)
set<int> parameters_within_shocks_values;
//! Set of estimated parameters (stored as symbol ids)
set<int> estimated_parameters;
//! Whether there is a prior statement present
bool prior_statement_present;
//! Whether there is a std prior statement present
bool std_prior_statement_present;
//! Whether there is a corr prior statement present
bool corr_prior_statement_present;
//! Whether there is a options statement present
bool options_statement_present;
//! Whether there is a std options statement present
bool std_options_statement_present;
//! Whether there is a corr options statement present
bool corr_options_statement_present;
//! Whether a Markov Switching DSGE is present
bool ms_dsge_present;
//! Whether occbin is present
bool occbin_option;
//! Stores the original number of equations in the model_block
int orig_eq_nbr;
//! Stores the number of equations added to the Ramsey model
int ramsey_eq_nbr;
//! Whether there was a steady_state_model block
bool steady_state_model_present;
//! Whether there is a write_latex_steady_state_model statement present
bool write_latex_steady_state_model_present;
//! Histval values that do not have the appropriate lag
map<int, int> hist_vals_wrong_lag;
};
class Statement
{
public:
virtual
~Statement();
//! Do some internal check, and fill the ModFileStructure class
/*! Don't forget to update ComputingTasks.hh, Shocks.hh and
NumericalInitialization.hh if you modify the signature of this
method. Otherwise the default implementation (i.e. a no-op) will apply and
some checks won't be run. */
virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void computingPass();
//! Write Matlab output code
/*!
\param output is the output stream of the main matlab file
\param basename is the name of the modfile (without extension) which can be used to build auxiliary files
*/
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const = 0;
virtual void writeCOutput(ostream &output, const string &basename);
virtual void writeJuliaOutput(ostream &output, const string &basename);
virtual void writeJsonOutput(ostream &output) const;
};
class NativeStatement : public Statement
{
private:
const string native_statement;
public:
NativeStatement(const string &native_statement_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class VerbatimStatement : public Statement
{
private:
const string verbatim_statement;
public:
VerbatimStatement(const string &verbatim_statement_arg);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
virtual void writeJsonOutput(ostream &output) const;
};
class OptionsList
{
public:
typedef map<string, string> num_options_t;
typedef map<string, pair<string, string> > paired_num_options_t;
typedef map<string, string> string_options_t;
typedef map<string, string> date_options_t;
typedef map<string, SymbolList> symbol_list_options_t;
typedef map<string, vector<int> > vec_int_options_t;
num_options_t num_options;
paired_num_options_t paired_num_options;
string_options_t string_options;
date_options_t date_options;
symbol_list_options_t symbol_list_options;
vec_int_options_t vector_int_options;
int getNumberOfOptions() const;
void writeOutput(ostream &output) const;
void writeOutput(ostream &output, const string &option_group) const;
void writeJsonOutput(ostream &output) const;
void clear();
};
#endif // ! _STATEMENT_HH

File diff suppressed because it is too large Load Diff

View File

@ -1,332 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _STATIC_MODEL_HH
#define _STATIC_MODEL_HH
using namespace std;
#include <fstream>
#include "ModelTree.hh"
//! Stores a static model, as derived from the "model" block when leads and lags have been removed
class StaticModel : public ModelTree
{
private:
//! global temporary terms for block decomposed models
vector<vector<temporary_terms_t> > v_temporary_terms;
//! local temporary terms for block decomposed models
vector<vector<temporary_terms_t> > v_temporary_terms_local;
vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
typedef map< pair< int, pair< int, int> >, expr_t> first_chain_rule_derivatives_t;
first_chain_rule_derivatives_t first_chain_rule_derivatives;
//! Writes static model file (standard Matlab version)
void writeStaticMFile(const string &static_basename) const;
//! Writes static model file (C version)
void writeStaticCFile(const string &func_name) const;
//! Writes static model file (Julia version)
void writeStaticJuliaFile(const string &basename) const;
//! Writes the static model equations and its derivatives
void writeStaticModel(ostream &StaticOutput, bool use_dll, bool julia) const;
//! Writes the static function calling the block to solve (Matlab version)
void writeStaticBlockMFSFile(const string &basename) const;
//! Writes the Block reordred structure of the model in M output
void writeModelEquationsOrdered_M(const string &dynamic_basename) const;
//! Writes the code of the Block reordred structure of the model in virtual machine bytecode
void writeModelEquationsCode_Block(const string file_name, const string bin_basename, map_idx_t map_idx, vector<map_idx_t> map_idx2) const;
//! Writes the code of the model in virtual machine bytecode
void writeModelEquationsCode(const string file_name, const string bin_basename, map_idx_t map_idx) const;
//! Computes jacobian and prepares for equation normalization
/*! Using values from initval/endval blocks and parameter initializations:
- computes the jacobian for the model w.r. to contemporaneous variables
- removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
*/
void evaluateJacobian(const eval_context_t &eval_context, jacob_map_t *j_m, bool dynamic);
map_idx_t map_idx;
vector<map_idx_t> map_idx2;
//! sorts the temporary terms in the blocks order
void computeTemporaryTermsOrdered();
//! creates a mapping from the index of temporary terms to a natural index
void computeTemporaryTermsMapping(temporary_terms_t &temporary_terms, map_idx_t &map_idx);
//! Write derivative code of an equation w.r. to a variable
void compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, map_idx_t &map_idx, temporary_terms_t temporary_terms) const;
//! Write chain rule derivative code of an equation w.r. to a variable
void compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int var, int lag, map_idx_t &map_idx, temporary_terms_t temporary_terms) const;
//! Get the type corresponding to a derivation ID
virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Get the lag corresponding to a derivation ID
virtual int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Get the symbol ID corresponding to a derivation ID
virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException);
//! Compute the column indices of the static Jacobian
void computeStatJacobianCols();
//! return a map on the block jacobian
map<pair<pair<int, pair<int, int> >, pair<int, int> >, int> get_Derivatives(int block);
//! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables
void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives);
//! Collect only the first derivatives
map<pair<int, pair<int, int> >, expr_t> collect_first_order_derivatives_endogenous();
//! Write chain rule derivative of a recursive equation w.r. to a variable
void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
void collect_block_first_order_derivatives();
protected:
//! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
bool global_temporary_terms;
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
//! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size > >
block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
//! for all blocks derivatives description
blocks_derivatives_t blocks_derivatives;
//! The jacobian without the elements below the cutoff
dynamic_jacob_map_t dynamic_jacobian;
//! Vector indicating if the block is linear in endogenous variable (true) or not (false)
vector<bool> blocks_linear;
//! Map the derivatives for a block pair<lag, make_pair(make_pair(eq, var)), expr_t>
typedef map<pair< int, pair<int, int> >, expr_t> derivative_t;
//! Vector of derivative for each blocks
vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
//!List for each block and for each lag-leag all the other endogenous variables and exogenous variables
typedef set<int> var_t;
typedef map<int, var_t> lag_var_t;
vector<lag_var_t> other_endo_block, exo_block, exo_det_block;
//! for each block described the number of static, forward, backward and mixed variables in the block
/*! pair< pair<static, forward>, pair<backward,mixed> > */
vector<pair< pair<int, int>, pair<int, int> > > block_col_type;
//! List for each variable its block number and its maximum lag and lead inside the block
vector<pair<int, pair<int, int> > > variable_block_lead_lag;
//! List for each equation its block number
vector<int> equation_block;
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
vector<pair<int, int> > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
public:
StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table_arg);
//! Writes information on block decomposition when relevant
void writeOutput(ostream &output, bool block) const;
//! Execute computations (variable sorting + derivation)
/*!
\param eval_context evaluation context for normalization
\param no_tmp_terms if true, no temporary terms will be computed in the static files
\param hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed
\param paramsDerivsOrder order of derivatives w.r. to a pair (endo/exo/exo_det, parameter) to be computed
*/
void computingPass(const eval_context_t &eval_context, bool no_tmp_terms, bool hessian, bool thirdDerivatices, int paramsDerivsOrder, bool block, bool bytecode, const bool nopreprocessoroutput);
//! Adds informations for simulation in a binary file for a block decomposed model
void Write_Inf_To_Bin_File_Block(const string &static_basename, const string &bin_basename, const int &num,
int &u_count_int, bool &file_open) const;
//! Writes static model file
void writeStaticFile(const string &basename, bool block, bool bytecode, bool use_dll, bool julia) const;
//! Write JSON Output (used by PlannerObjectiveStatement)
void writeJsonOutput(ostream &output) const;
//! Write JSON representation of static model
void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
//! Writes file containing static parameters derivatives
void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const;
//! Writes file containing static parameters derivatives
void writeParamsDerivativesFile(const string &basename, bool julia) const;
//! Writes LaTeX file with the equations of the static model
void writeLatexFile(const string &basename, const bool write_equation_tags) const;
//! Writes initializations in oo_.steady_state or steady state file for the auxiliary variables
void writeAuxVarInitval(ostream &output, ExprNodeOutputType output_type) const;
//! Writes definition of the auxiliary variables in a .m or .jl file
void writeSetAuxiliaryVariables(const string &basename, const bool julia) const;
void writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputType output_type) const;
void writeLatexAuxVarRecursiveDefinitions(ostream &output) const;
void writeJsonAuxVarRecursiveDefinitions(ostream &output) const;
//! To ensure that no exogenous is present in the planner objective
//! See #1264
bool exoPresentInEqs() const;
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
virtual void addAllParamDerivId(set<int> &deriv_id_set);
//! Return the number of blocks
virtual unsigned int
getNbBlocks() const
{
return (block_type_firstequation_size_mfs.size());
};
//! Determine the simulation type of each block
virtual BlockSimulationType
getBlockSimulationType(int block_number) const
{
return (block_type_firstequation_size_mfs[block_number].first.first);
};
//! Return the first equation number of a block
virtual unsigned int
getBlockFirstEquation(int block_number) const
{
return (block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the size of the block block_number
virtual unsigned int
getBlockSize(int block_number) const
{
return (block_type_firstequation_size_mfs[block_number].second.first);
};
//! Return the number of exogenous variable in the block block_number
virtual unsigned int
getBlockExoSize(int block_number) const
{
return 0;
};
//! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
virtual unsigned int
getBlockExoColSize(int block_number) const
{
return 0;
}
//! Return the number of feedback variable of the block block_number
virtual unsigned int
getBlockMfs(int block_number) const
{
return (block_type_firstequation_size_mfs[block_number].second.second);
};
//! Return the maximum lag in a block
virtual unsigned int
getBlockMaxLag(int block_number) const
{
return (block_lag_lead[block_number].first);
};
//! Return the maximum lead in a block
virtual unsigned int
getBlockMaxLead(int block_number) const
{
return (block_lag_lead[block_number].second);
};
//! Return the type of equation (equation_number) belonging to the block block_number
virtual EquationType
getBlockEquationType(int block_number, int equation_number) const
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first);
};
//! Return true if the equation has been normalized
virtual bool
isBlockEquationRenormalized(int block_number, int equation_number) const
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first == E_EVALUATE_S);
};
//! Return the expr_t of the equation equation_number belonging to the block block_number
virtual expr_t
getBlockEquationExpr(int block_number, int equation_number) const
{
return (equations[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]]);
};
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
virtual expr_t
getBlockEquationRenormalizedExpr(int block_number, int equation_number) const
{
return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].second);
};
//! Return the original number of equation equation_number belonging to the block block_number
virtual int
getBlockEquationID(int block_number, int equation_number) const
{
return (equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]);
};
//! Return the original number of variable variable_number belonging to the block block_number
virtual int
getBlockVariableID(int block_number, int variable_number) const
{
return (variable_reordered[block_type_firstequation_size_mfs[block_number].first.second+variable_number]);
};
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number
virtual int
getBlockVariableExoID(int block_number, int variable_number) const
{
return 0;
};
//! Return the position of equation_number in the block number belonging to the block block_number
virtual int
getBlockInitialEquationID(int block_number, int equation_number) const
{
return ((int) inv_equation_reordered[equation_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the position of variable_number in the block number belonging to the block block_number
virtual int
getBlockInitialVariableID(int block_number, int variable_number) const
{
return ((int) inv_variable_reordered[variable_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
};
//! Return the position of variable_number in the block number belonging to the block block_number
virtual int
getBlockInitialExogenousID(int block_number, int variable_number) const
{
return -1;
};
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
virtual int
getBlockInitialDetExogenousID(int block_number, int variable_number) const
{
return -1;
};
//! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
virtual int
getBlockInitialOtherEndogenousID(int block_number, int variable_number) const
{
return -1;
};
};
#endif

View File

@ -1,316 +0,0 @@
/*
* Copyright (C) 2010-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <algorithm>
#include "SteadyStateModel.hh"
SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg) :
DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg), static_model(static_model_arg)
{
}
void
SteadyStateModel::addDefinition(int symb_id, expr_t expr)
{
AddVariable(symb_id); // Create the variable node to be used in write method
assert(symbol_table.getType(symb_id) == eEndogenous
|| symbol_table.getType(symb_id) == eModFileLocalVariable
|| symbol_table.getType(symb_id) == eParameter);
// Add the variable
vector<int> v;
v.push_back(symb_id);
def_table.push_back(make_pair(v, expr));
}
void
SteadyStateModel::addMultipleDefinitions(const vector<int> &symb_ids, expr_t expr)
{
for (size_t i = 0; i < symb_ids.size(); i++)
{
AddVariable(symb_ids[i]); // Create the variable nodes to be used in write method
assert(symbol_table.getType(symb_ids[i]) == eEndogenous
|| symbol_table.getType(symb_ids[i]) == eModFileLocalVariable
|| symbol_table.getType(symb_ids[i]) == eParameter);
}
def_table.push_back(make_pair(symb_ids, expr));
}
void
SteadyStateModel::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) const
{
if (def_table.size() == 0)
return;
mod_file_struct.steady_state_model_present = true;
vector<int> so_far_defined;
for (size_t i = 0; i < def_table.size(); i++)
{
const vector<int> &symb_ids = def_table[i].first;
// Check that symbols are not already defined
for (size_t j = 0; j < symb_ids.size(); j++)
if (find(so_far_defined.begin(), so_far_defined.end(), symb_ids[j])
!= so_far_defined.end())
warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(symb_ids[j]) << "' is declared twice" << endl;
// Check that expression has no undefined symbol
if (!mod_file_struct.ramsey_model_present)
{
set<int> used_symbols;
const expr_t &expr = def_table[i].second;
expr->collectVariables(eEndogenous, used_symbols);
expr->collectVariables(eModFileLocalVariable, used_symbols);
for (set<int>::const_iterator it = used_symbols.begin();
it != used_symbols.end(); ++it)
if (find(so_far_defined.begin(), so_far_defined.end(), *it)
== so_far_defined.end())
{
cerr << "ERROR: in the 'steady_state_model' block, variable '" << symbol_table.getName(*it)
<< "' is undefined in the declaration of variable '" << symbol_table.getName(symb_ids[0]) << "'" << endl;
exit(EXIT_FAILURE);
}
}
copy(symb_ids.begin(), symb_ids.end(), back_inserter(so_far_defined));
}
set<int> orig_endogs = symbol_table.getOrigEndogenous();
for (set<int>::const_iterator it = orig_endogs.begin();
it != orig_endogs.end(); ++it)
{
if (find(so_far_defined.begin(), so_far_defined.end(), *it)
== so_far_defined.end())
warnings << "WARNING: in the 'steady_state_model' block, variable '" << symbol_table.getName(*it) << "' is not assigned a value" << endl;
}
}
void
SteadyStateModel::writeLatexSteadyStateFile(const string &basename) const
{
ofstream output, content_output;
string filename = basename + "_steady_state.tex";
string content_basename = basename + "_steady_state_content";
string content_filename = content_basename + ".tex";
output.open(filename.c_str(), ios::out | ios::binary);
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
exit(EXIT_FAILURE);
}
content_output.open(content_filename.c_str(), ios::out | ios::binary);
if (!content_output.is_open())
{
cerr << "ERROR: Can't open file " << content_filename << " for writing" << endl;
exit(EXIT_FAILURE);
}
output << "\\documentclass[10pt,a4paper]{article}" << endl
<< "\\usepackage[landscape]{geometry}" << endl
<< "\\usepackage{fullpage}" << endl
<< "\\usepackage{amsfonts}" << endl
<< "\\usepackage{breqn}" << endl
<< "\\begin{document}" << endl
<< "\\footnotesize" << endl;
for (vector<pair<vector<int>, expr_t> >::const_iterator it = def_table.begin();
it != def_table.end(); it++)
for (vector<int>::const_iterator it1 = it->first.begin(); it1 != it->first.end(); it1++)
{
int id = *it1;
expr_t value = it->second;
content_output << "\\begin{dmath}" << endl
<< symbol_table.getTeXName(id) << " = ";
value->writeOutput(content_output, oLatexStaticModel);
content_output << endl << "\\end{dmath}" << endl;
}
static_model.writeLatexAuxVarRecursiveDefinitions(content_output);
output << "\\include{" << content_basename << "}" << endl
<< "\\end{document}" << endl;
output.close();
content_output.close();
}
void
SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_model, bool julia) const
{
if (def_table.size() == 0)
return;
string filename = julia ? basename + "SteadyState2.jl" : basename + "_steadystate2.m";
ofstream output;
output.open(filename.c_str(), ios::out | ios::binary);
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
exit(EXIT_FAILURE);
}
ExprNodeOutputType output_type = (julia ? oJuliaSteadyStateFile : oSteadyStateFile);
if (!julia)
output << "function [ys_, params, info] = " << basename << "_steadystate2("
<< "ys_, exo_, params)" << endl
<< "% Steady state generated by Dynare preprocessor" << endl
<< " info = 0;" << endl;
else
output << "module " << basename << "SteadyState2" << endl
<< "#" << endl
<< "# NB: this file was automatically generated by Dynare" << endl
<< "# from " << basename << ".mod" << endl
<< "#" << endl
<< "export steady_state!" << endl << endl
<< "function steady_state!(ys_::Vector{Float64}, exo_::Vector{Float64}, "
<< "params::Vector{Float64})" << endl;
for (size_t i = 0; i < def_table.size(); i++)
{
const vector<int> &symb_ids = def_table[i].first;
output << " ";
if (symb_ids.size() > 1)
output << "[";
for (size_t j = 0; j < symb_ids.size(); j++)
{
variable_node_map_t::const_iterator it = variable_node_map.find(make_pair(symb_ids[j], 0));
assert(it != variable_node_map.end());
dynamic_cast<ExprNode *>(it->second)->writeOutput(output, output_type);
if (j < symb_ids.size()-1)
output << ",";
}
if (symb_ids.size() > 1)
output << "]";
output << "=";
def_table[i].second->writeOutput(output, output_type);
output << ";" << endl;
}
if (!julia)
output << " % Auxiliary equations" << endl;
else
output << " # Auxiliary equations" << endl;
static_model.writeAuxVarRecursiveDefinitions(output, output_type);
if (!julia)
output << " check_=0;" << endl;
output << "end" << endl;
if (julia)
output << "end" << endl;
}
void
SteadyStateModel::writeSteadyStateFileC(const string &basename, bool ramsey_model) const
{
string filename = basename + "_steadystate.c";
ofstream output;
output.open(filename.c_str(), ios::out | ios::binary);
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
exit(EXIT_FAILURE);
}
output << "#include <math.h>" << endl;
output << "void steadystate("
<< "const double *exo_, const double *params, double *ys_, int *info)" << endl
<< "// Steady state file generated by Dynare preprocessor" << endl
<< "{" << endl
<< " *info = 0;" << endl;
if (def_table.size() == 0)
{
output << " return;" << endl
<< "}" << endl;
return;
}
for (size_t i = 0; i < def_table.size(); i++)
{
const vector<int> &symb_ids = def_table[i].first;
output << " ";
if (symb_ids.size() > 1)
std::cout << "Error: in C, multiple returns are not permitted in steady_state_model" << std::endl;
variable_node_map_t::const_iterator it = variable_node_map.find(make_pair(symb_ids[0], 0));
assert(it != variable_node_map.end());
if (it->second->get_type() == eModFileLocalVariable)
output << "double ";
dynamic_cast<ExprNode *>(it->second)->writeOutput(output, oCSteadyStateFile);
output << "=";
def_table[i].second->writeOutput(output, oCSteadyStateFile);
output << ";" << endl;
}
output << " // Auxiliary equations" << endl;
static_model.writeAuxVarInitval(output, oCSteadyStateFile);
output << "}" << endl;
}
void
SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComputingPass) const
{
if (def_table.size() == 0)
return;
deriv_node_temp_terms_t tef_terms;
vector<pair<string, string> > eqtags;
temporary_terms_t tt_empty;
output << "{\"steady_state_model\": [";
for (size_t i = 0; i < def_table.size(); i++)
{
const vector<int> &symb_ids = def_table[i].first;
if (i != 0)
output << ",";
output << "{\"lhs\": ";
if (symb_ids.size() > 1)
output << "[";
for (size_t j = 0; j < symb_ids.size(); j++)
{
if (j != 0)
output << ",";
variable_node_map_t::const_iterator it =
variable_node_map.find(make_pair(symb_ids[j], 0));
assert(it != variable_node_map.end());
output << "\"";
dynamic_cast<ExprNode *>(it->second)->writeJsonOutput(output, tt_empty, tef_terms, false);
output << "\"";
}
if (symb_ids.size() > 1)
output << "]";
output << ", \"rhs\":\"";
def_table[i].second->writeJsonOutput(output, tt_empty, tef_terms, false);
output << "\"}" << endl;
}
if (transformComputingPass)
static_model.writeJsonAuxVarRecursiveDefinitions(output);
output << "]}";
}

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2010-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _STEADY_STATE_MODEL_HH
#define _STEADY_STATE_MODEL_HH
#include "DataTree.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "WarningConsolidation.hh"
class SteadyStateModel : public DataTree
{
private:
//! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an expression (their assigned value)
vector<pair<vector<int>, expr_t> > def_table;
//! Reference to static model (for writing auxiliary equations)
const StaticModel &static_model;
public:
SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg);
//! Add an expression of the form "var = expr;"
void addDefinition(int symb_id, expr_t expr);
//! Add an expression of the form "[ var1, var2, ... ] = expr;"
void addMultipleDefinitions(const vector<int> &symb_ids, expr_t expr);
//! Checks that definitions are in a recursive order, and that no variable is declared twice
/*!
\param[in] ramsey_model Is there a Ramsey model in the MOD file? If yes, then disable the check on the recursivity of the declarations
*/
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) const;
//! Write the steady state file
/*!
\param[in] ramsey_model Is there a Ramsey model in the MOD file? If yes, then use the "ys" in argument of the steady state file as initial values
*/
void writeSteadyStateFile(const string &basename, bool ramsey_model, bool julia) const;
void writeSteadyStateFileC(const string &basename, bool ramsey_model) const;
//! Writes LaTeX file with the equations of the dynamic model (for the steady state model)
void writeLatexSteadyStateFile(const string &basename) const;
//! Writes JSON output
void writeJsonSteadyStateFile(ostream &output, bool transformComputingPass) const;
};
#endif

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2003-2018 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SymbolList.hh"
void
SymbolList::addSymbol(const string &symbol)
{
symbols.push_back(symbol);
}
void
SymbolList::writeOutput(const string &varname, ostream &output) const
{
output << varname << " = {";
for (vector<string>::const_iterator it = symbols.begin();
it != symbols.end(); ++it)
{
if (it != symbols.begin())
output << ";";
output << "'" << *it << "'";
}
output << "};" << endl;
}
void
SymbolList::writeJsonOutput(ostream &output) const
{
output << "\"symbol_list\": [";
for (vector<string>::const_iterator it = symbols.begin();
it != symbols.end(); ++it)
{
if (it != symbols.begin())
output << ",";
output << "\"" << *it << "\"";
}
output << "]";
}
void
SymbolList::clear()
{
symbols.clear();
}

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SYMBOL_LIST_HH
#define _SYMBOL_LIST_HH
#include <string>
#include <vector>
#include <ostream>
using namespace std;
//! Used to store a list of symbols
/*! This class is no more than a vector<string>, with a pretty-printer for Matlab */
class SymbolList
{
private:
//! Internal container for symbol list
vector<string> symbols;
public:
//! Adds a symbol to the list
void addSymbol(const string &symbol);
//! Output content in Matlab format
/*! Creates a string array for Matlab, stored in variable "varname" */
void writeOutput(const string &varname, ostream &output) const;
//! Write JSON output
void writeJsonOutput(ostream &output) const;
//! Clears all content
void clear();
//! Get a copy of the string vector
vector<string>
get_symbols() const
{
return symbols;
};
//! Is Empty
int
empty() const
{
return symbols.empty();
};
};
#endif

View File

@ -1,986 +0,0 @@
/*
* Copyright (C) 2003-2018 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cassert>
#include <boost/algorithm/string/replace.hpp>
#include "SymbolTable.hh"
AuxVarInfo::AuxVarInfo(int symb_id_arg, aux_var_t type_arg, int orig_symb_id_arg, int orig_lead_lag_arg,
int equation_number_for_multiplier_arg, int information_set_arg,
expr_t expr_node_arg) :
symb_id(symb_id_arg),
type(type_arg),
orig_symb_id(orig_symb_id_arg),
orig_lead_lag(orig_lead_lag_arg),
equation_number_for_multiplier(equation_number_for_multiplier_arg),
information_set(information_set_arg),
expr_node(expr_node_arg)
{
}
SymbolTable::SymbolTable() : frozen(false)
{
}
int
SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string *, string *> *> *partition_value) throw (AlreadyDeclaredException, FrozenException)
{
if (frozen)
throw FrozenException();
if (exists(name))
{
if (type_table[getID(name)] == type)
throw AlreadyDeclaredException(name, true);
else
throw AlreadyDeclaredException(name, false);
}
string final_tex_name = tex_name;
if (final_tex_name.empty())
{
final_tex_name = name;
size_t pos = 0;
while ((pos = final_tex_name.find('_', pos)) != string::npos)
{
final_tex_name.insert(pos, "\\");
pos += 2;
}
}
string final_long_name = name;
bool non_long_name_partition_exists = false;
if (partition_value)
for (vector<pair<string *, string *> *>::const_iterator it = partition_value->begin();
it != partition_value->end(); it++)
if (*((*it)->first) == "long_name")
final_long_name = *((*it)->second);
else
non_long_name_partition_exists = true;
int id = symbol_table.size();
symbol_table[name] = id;
type_table.push_back(type);
name_table.push_back(name);
tex_name_table.push_back(final_tex_name);
long_name_table.push_back(final_long_name);
if (non_long_name_partition_exists)
{
map<string, string> pmv;
for (vector<pair<string *, string *> *>::const_iterator it = partition_value->begin();
it != partition_value->end(); it++)
pmv[*((*it)->first)] = *((*it)->second);
partition_value_map[id] = pmv;
}
return id;
}
int
SymbolTable::addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException)
{
return addSymbol(name, type, "", NULL);
}
void
SymbolTable::freeze() throw (FrozenException)
{
if (frozen)
throw FrozenException();
frozen = true;
for (int i = 0; i < (int) symbol_table.size(); i++)
{
int tsi;
switch (getType(i))
{
case eEndogenous:
tsi = endo_ids.size();
endo_ids.push_back(i);
break;
case eExogenous:
tsi = exo_ids.size();
exo_ids.push_back(i);
break;
case eExogenousDet:
tsi = exo_det_ids.size();
exo_det_ids.push_back(i);
break;
case eParameter:
tsi = param_ids.size();
param_ids.push_back(i);
break;
default:
tsi = -1;
break;
}
type_specific_ids.push_back(tsi);
}
}
void
SymbolTable::unfreeze()
{
frozen = false;
endo_ids.clear();
exo_ids.clear();
exo_det_ids.clear();
param_ids.clear();
type_specific_ids.clear();
}
void
SymbolTable::changeType(int id, SymbolType newtype) throw (UnknownSymbolIDException, FrozenException)
{
if (frozen)
throw FrozenException();
validateSymbID(id);
type_table[id] = newtype;
}
int
SymbolTable::getID(SymbolType type, int tsid) const throw (UnknownTypeSpecificIDException, NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
switch (type)
{
case eEndogenous:
if (tsid < 0 || tsid >= (int) endo_ids.size())
throw UnknownTypeSpecificIDException(tsid, type);
else
return endo_ids[tsid];
case eExogenous:
if (tsid < 0 || tsid >= (int) exo_ids.size())
throw UnknownTypeSpecificIDException(tsid, type);
else
return exo_ids[tsid];
case eExogenousDet:
if (tsid < 0 || tsid >= (int) exo_det_ids.size())
throw UnknownTypeSpecificIDException(tsid, type);
else
return exo_det_ids[tsid];
case eParameter:
if (tsid < 0 || tsid >= (int) param_ids.size())
throw UnknownTypeSpecificIDException(tsid, type);
else
return param_ids[tsid];
default:
throw UnknownTypeSpecificIDException(tsid, type);
}
}
map<string, map<int, string> >
SymbolTable::getPartitionsForType(enum SymbolType st) const throw (UnknownSymbolIDException)
{
map<string, map<int, string> > partitions;
for (map<int, map<string, string> >::const_iterator it = partition_value_map.begin();
it != partition_value_map.end(); it++)
if (getType(it->first) == st)
for (map<string, string>::const_iterator it1 = it->second.begin();
it1 != it->second.end(); it1++)
{
if (partitions.find(it1->first) == partitions.end())
partitions[it1->first] = map<int, string> ();
partitions[it1->first][it->first] = it1->second;
}
return partitions;
}
void
SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
if (exo_nbr() > 0)
{
output << "M_.exo_names = cell(" << exo_nbr() << ",1);" << endl;
output << "M_.exo_names_tex = cell(" << exo_nbr() << ",1);" << endl;
output << "M_.exo_names_long = cell(" << exo_nbr() << ",1);" << endl;
for (int id = 0; id < exo_nbr(); id++)
output << "M_.exo_names(" << id+1 << ") = {'" << getName(exo_ids[id]) << "'};" << endl
<< "M_.exo_names_tex(" << id+1 << ") = {'" << getTeXName(exo_ids[id]) << "'};" << endl
<< "M_.exo_names_long(" << id+1 << ") = {'" << getLongName(exo_ids[id]) << "'};" << endl;
map<string, map<int, string> > partitions = getPartitionsForType(eExogenous);
for (map<string, map<int, string> >::const_iterator it = partitions.begin();
it != partitions.end(); it++)
if (it->first != "long_name")
{
map<int, string>::const_iterator it1;
output << "M_.exo_partitions." << it->first << " = { ";
for (int id = 0; id < exo_nbr(); id++)
{
output << "'";
it1 = it->second.find(exo_ids[id]);
if (it1 != it->second.end())
output << it1->second;
output << "' ";
}
output << "};" << endl;
}
}
if (exo_det_nbr() > 0)
{
output << "M_.exo_det_names = cell(" << exo_det_nbr() << ",1);" << endl;
output << "M_.exo_det_names_tex = cell(" << exo_det_nbr() << ",1);" << endl;
output << "M_.exo_det_names_long = cell(" << exo_det_nbr() << ",1);" << endl;
for (int id = 0; id < exo_det_nbr(); id++)
output << "M_.exo_det_names(" << id+1 << ") = {'" << getName(exo_det_ids[id]) << "'};" << endl
<< "M_.exo_det_names_tex(" << id+1 << ") = {'" << getTeXName(exo_det_ids[id]) << "'};" << endl
<< "M_.exo_det_names_long(" << id+1 << ") = {'" << getLongName(exo_det_ids[id]) << "'};" << endl;
output << "M_.exo_det_partitions = struct();" << endl;
map<string, map<int, string> > partitions = getPartitionsForType(eExogenousDet);
for (map<string, map<int, string> >::const_iterator it = partitions.begin();
it != partitions.end(); it++)
if (it->first != "long_name")
{
map<int, string>::const_iterator it1;
output << "M_.exo_det_partitions." << it->first << " = { ";
for (int id = 0; id < exo_det_nbr(); id++)
{
output << "'";
it1 = it->second.find(exo_det_ids[id]);
if (it1 != it->second.end())
output << it1->second;
output << "' ";
}
output << "};" << endl;
}
}
if (endo_nbr() > 0)
{
output << "M_.endo_names = cell(" << endo_nbr() << ",1);" << endl;
output << "M_.endo_names_tex = cell(" << endo_nbr() << ",1);" << endl;
output << "M_.endo_names_long = cell(" << endo_nbr() << ",1);" << endl;
for (int id = 0; id < endo_nbr(); id++)
output << "M_.endo_names(" << id+1 << ") = {'" << getName(endo_ids[id]) << "'};" << endl
<< "M_.endo_names_tex(" << id+1 << ") = {'" << getTeXName(endo_ids[id]) << "'};" << endl
<< "M_.endo_names_long(" << id+1 << ") = {'" << getLongName(endo_ids[id]) << "'};" << endl;
output << "M_.endo_partitions = struct();" << endl;
map<string, map<int, string> > partitions = getPartitionsForType(eEndogenous);
for (map<string, map<int, string> >::const_iterator it = partitions.begin();
it != partitions.end(); it++)
if (it->first != "long_name")
{
map<int, string>::const_iterator it1;
output << "M_.endo_partitions." << it->first << " = { ";
for (int id = 0; id < endo_nbr(); id++)
{
output << "'";
it1 = it->second.find(endo_ids[id]);
if (it1 != it->second.end())
output << it1->second;
output << "' ";
}
output << "};" << endl;
}
}
if (param_nbr() > 0)
{
output << "M_.param_names = cell(" << param_nbr() << ",1);" << endl;
output << "M_.param_names_tex = cell(" << param_nbr() << ",1);" << endl;
output << "M_.param_names_long = cell(" << param_nbr() << ",1);" << endl;
for (int id = 0; id < param_nbr(); id++)
{
output << "M_.param_names(" << id+1 << ") = {'" << getName(param_ids[id]) << "'};" << endl
<< "M_.param_names_tex(" << id+1 << ") = {'" << getTeXName(param_ids[id]) << "'};" << endl
<< "M_.param_names_long(" << id+1 << ") = {'" << getLongName(param_ids[id]) << "'};" << endl;
if (getName(param_ids[id]) == "dsge_prior_weight")
output << "options_.dsge_var = 1;" << endl;
}
output << "M_.param_partitions = struct();" << endl;
map<string, map<int, string> > partitions = getPartitionsForType(eParameter);
for (map<string, map<int, string> >::const_iterator it = partitions.begin();
it != partitions.end(); it++)
if (it->first != "long_name")
{
map<int, string>::const_iterator it1;
output << "M_.param_partitions." << it->first << " = { ";
for (int id = 0; id < param_nbr(); id++)
{
output << "'";
it1 = it->second.find(param_ids[id]);
if (it1 != it->second.end())
output << it1->second;
output << "' ";
}
output << "};" << endl;
}
}
output << "M_.exo_det_nbr = " << exo_det_nbr() << ";" << endl
<< "M_.exo_nbr = " << exo_nbr() << ";" << endl
<< "M_.endo_nbr = " << endo_nbr() << ";" << endl
<< "M_.param_nbr = " << param_nbr() << ";" << endl;
// Write the auxiliary variable table
output << "M_.orig_endo_nbr = " << orig_endo_nbr() << ";" << endl;
if (aux_vars.size() == 0)
output << "M_.aux_vars = [];" << endl;
else
for (int i = 0; i < (int) aux_vars.size(); i++)
{
output << "M_.aux_vars(" << i+1 << ").endo_index = " << getTypeSpecificID(aux_vars[i].get_symb_id())+1 << ";" << endl
<< "M_.aux_vars(" << i+1 << ").type = " << aux_vars[i].get_type() << ";" << endl;
switch (aux_vars[i].get_type())
{
case avEndoLead:
case avExoLead:
break;
case avEndoLag:
case avExoLag:
output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ";" << endl
<< "M_.aux_vars(" << i+1 << ").orig_lead_lag = " << aux_vars[i].get_orig_lead_lag() << ";" << endl;
break;
case avMultiplier:
output << "M_.aux_vars(" << i+1 << ").eq_nbr = " << aux_vars[i].get_equation_number_for_multiplier() + 1 << ";" << endl;
break;
case avDiffForward:
output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ";" << endl;
break;
case avExpectation:
output << "M_.aux_vars(" << i+1 << ").orig_expr = '\\mathbb{E}_{t"
<< (aux_vars[i].get_information_set() < 0 ? "" : "+")
<< aux_vars[i].get_information_set() << "}(";
aux_vars[i].get_expr_node()->writeOutput(output, oLatexDynamicModel);
output << ")';" << endl;
break;
}
}
if (predeterminedNbr() > 0)
{
output << "M_.predetermined_variables = [ ";
for (set<int>::const_iterator it = predetermined_variables.begin();
it != predetermined_variables.end(); it++)
output << getTypeSpecificID(*it)+1 << " ";
output << "];" << endl;
}
if (observedVariablesNbr() > 0)
{
int ic = 1;
output << "options_.varobs = cell(" << observedVariablesNbr() << ", 1);" << endl;
for (vector<int>::const_iterator it = varobs.begin();
it != varobs.end(); it++, ic++)
output << "options_.varobs(" << ic << ") = {'" << getName(*it) << "'};" << endl;
output << "options_.varobs_id = [ ";
for (vector<int>::const_iterator it = varobs.begin();
it != varobs.end(); it++)
output << getTypeSpecificID(*it)+1 << " ";
output << " ];" << endl;
}
}
void
SymbolTable::writeCOutput(ostream &output) const throw (NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
output << endl
<< "int exo_nbr = " << exo_nbr() << ";" << endl;
if (exo_nbr() > 0)
{
output << "char *exo_names[" << exo_nbr() << "];" << endl;
for (int id = 0; id < exo_nbr(); id++)
output << "exo_names[" << id << "] = \"" << getName(exo_ids[id]) << "\";" << endl;
}
output << endl
<< "int exo_det_nbr = " << exo_det_nbr() << ";" << endl;
if (exo_det_nbr() > 0)
{
output << "char *exo_det_names[" << exo_det_nbr() << "];" << endl;
for (int id = 0; id < exo_det_nbr(); id++)
output << "exo_det_names[" << id << "] = \"" << getName(exo_det_ids[id]) << "\";" << endl;
}
output << endl
<< "int endo_nbr = " << endo_nbr() << ";" << endl;
if (endo_nbr() > 0)
{
output << "char *endo_names[" << endo_nbr() << "];" << endl;
for (int id = 0; id < endo_nbr(); id++)
output << "endo_names[" << id << "] = \"" << getName(endo_ids[id]) << "\";" << endl;
}
output << endl
<< "int param_nbr = " << param_nbr() << ";" << endl;
if (param_nbr() > 0)
{
output << "char *param_names[" << param_nbr() << "];" << endl;
for (int id = 0; id < param_nbr(); id++)
output << "param_names[" << id << "] = \"" << getName(param_ids[id]) << "\";" << endl;
}
// Write the auxiliary variable table
output << "int aux_var_nbr = " << aux_vars.size() << ";" << endl;
if (aux_vars.size() > 0)
{
output << "struct aux_vars_t *av[" << aux_vars.size() << "];" << endl;
for (int i = 0; i < (int) aux_vars.size(); i++)
{
output << "av[" << i << "].endo_index = " << getTypeSpecificID(aux_vars[i].get_symb_id()) << ";" << endl
<< "av[" << i << "].type = " << aux_vars[i].get_type() << ";" << endl;
switch (aux_vars[i].get_type())
{
case avEndoLead:
case avExoLead:
case avExpectation:
case avMultiplier:
case avDiffForward:
break;
case avEndoLag:
case avExoLag:
output << "av[" << i << "].orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id()) << ";" << endl
<< "av[" << i << "].orig_lead_lag = " << aux_vars[i].get_orig_lead_lag() << ";" << endl;
break;
}
}
}
output << "int predeterminedNbr = " << predeterminedNbr() << ";" << endl;
if (predeterminedNbr() > 0)
{
output << "int predetermined_variables[" << predeterminedNbr() << "] = {";
for (set<int>::const_iterator it = predetermined_variables.begin();
it != predetermined_variables.end(); it++)
{
if (it != predetermined_variables.begin())
output << ",";
output << getTypeSpecificID(*it);
}
output << "};" << endl;
}
output << "int observedVariablesNbr = " << observedVariablesNbr() << ";" << endl;
if (observedVariablesNbr() > 0)
{
output << "int varobs[" << observedVariablesNbr() << "] = {";
for (vector<int>::const_iterator it = varobs.begin();
it != varobs.end(); it++)
{
if (it != varobs.begin())
output << ",";
output << getTypeSpecificID(*it);
}
output << "};" << endl;
}
}
void
SymbolTable::writeCCOutput(ostream &output) const throw (NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
output << endl
<< "exo_nbr = " << exo_nbr() << ";" << endl;
for (int id = 0; id < exo_nbr(); id++)
output << "exo_names[\"" << getName(exo_ids[id]) << "\"] = " << id << ";" << endl;
output << endl
<< "exo_det_nbr = " << exo_det_nbr() << ";" << endl;
for (int id = 0; id < exo_det_nbr(); id++)
output << "exo_det_names[\"" << getName(exo_det_ids[id]) << "\"] = " << id << " ;" << endl;
output << endl
<< "endo_nbr = " << endo_nbr() << ";" << endl;
for (int id = 0; id < endo_nbr(); id++)
output << "endo_names[\"" << getName(endo_ids[id]) << "\"] = " << id << ";" << endl;
output << endl
<< "param_nbr = " << param_nbr() << ";" << endl;
for (int id = 0; id < param_nbr(); id++)
output << "param_names[\"" << getName(param_ids[id]) << "\"] = " << id << ";" << endl;
// Write the auxiliary variable table
for (int i = 0; i < (int) aux_vars.size(); i++)
{
output << "aux_vars_t av" << i << ";" << endl;
output << "av" << i << ".endo_index = " << getTypeSpecificID(aux_vars[i].get_symb_id()) << ";" << endl
<< "av" << i << ".type = " << aux_vars[i].get_type() << ";" << endl;
switch (aux_vars[i].get_type())
{
case avEndoLead:
case avExoLead:
case avExpectation:
case avMultiplier:
case avDiffForward:
break;
case avEndoLag:
case avExoLag:
output << "av" << i << ".orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id()) << ";" << endl
<< "av" << i << ".orig_lead_lag = " << aux_vars[i].get_orig_lead_lag() << ";" << endl;
break;
}
output << "aux_vars.push_back(" << "av" << i << ");" << endl;
}
for (set<int>::const_iterator it = predetermined_variables.begin();
it != predetermined_variables.end(); it++)
output << "predetermined_variables.push_back(" << getTypeSpecificID(*it) << ");" << endl;
for (vector<int>::const_iterator it = varobs.begin();
it != varobs.end(); it++)
output << "varobs.push_back(" << getTypeSpecificID(*it) << ");" << endl;
}
int
SymbolTable::addLeadAuxiliaryVarInternal(bool endo, int index, expr_t expr_arg) throw (FrozenException)
{
ostringstream varname;
if (endo)
varname << "AUX_ENDO_LEAD_";
else
varname << "AUX_EXO_LEAD_";
varname << index;
int symb_id;
try
{
symb_id = addSymbol(varname.str(), eEndogenous);
}
catch (AlreadyDeclaredException &e)
{
cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLead : avExoLead), 0, 0, 0, 0, expr_arg));
return symb_id;
}
int
SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t expr_arg) throw (FrozenException)
{
ostringstream varname;
if (endo)
varname << "AUX_ENDO_LAG_";
else
varname << "AUX_EXO_LAG_";
varname << orig_symb_id << "_" << -orig_lead_lag;
int symb_id;
try
{
symb_id = addSymbol(varname.str(), eEndogenous);
}
catch (AlreadyDeclaredException &e)
{
cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLag : avExoLag), orig_symb_id, orig_lead_lag, 0, 0, expr_arg));
return symb_id;
}
int
SymbolTable::addEndoLeadAuxiliaryVar(int index, expr_t expr_arg) throw (FrozenException)
{
return addLeadAuxiliaryVarInternal(true, index, expr_arg);
}
int
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) throw (FrozenException)
{
return addLagAuxiliaryVarInternal(true, orig_symb_id, orig_lead_lag, expr_arg);
}
int
SymbolTable::addExoLeadAuxiliaryVar(int index, expr_t expr_arg) throw (FrozenException)
{
return addLeadAuxiliaryVarInternal(false, index, expr_arg);
}
int
SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) throw (FrozenException)
{
return addLagAuxiliaryVarInternal(false, orig_symb_id, orig_lead_lag, expr_arg);
}
int
SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, expr_t expr_arg) throw (FrozenException)
{
ostringstream varname;
int symb_id;
varname << "AUX_EXPECT_" << (information_set < 0 ? "LAG" : "LEAD") << "_"
<< abs(information_set) << "_" << index;
try
{
symb_id = addSymbol(varname.str(), eEndogenous);
}
catch (AlreadyDeclaredException &e)
{
cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.push_back(AuxVarInfo(symb_id, avExpectation, 0, 0, 0, information_set, expr_arg));
return symb_id;
}
int
SymbolTable::addMultiplierAuxiliaryVar(int index) throw (FrozenException)
{
ostringstream varname;
int symb_id;
varname << "MULT_" << index+1;
try
{
symb_id = addSymbol(varname.str(), eEndogenous);
}
catch (AlreadyDeclaredException &e)
{
cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.push_back(AuxVarInfo(symb_id, avMultiplier, 0, 0, index, 0, NULL));
return symb_id;
}
int
SymbolTable::addDiffForwardAuxiliaryVar(int orig_symb_id, expr_t expr_arg) throw (FrozenException)
{
ostringstream varname;
int symb_id;
varname << "AUX_DIFF_FWRD_" << orig_symb_id+1;
try
{
symb_id = addSymbol(varname.str(), eEndogenous);
}
catch (AlreadyDeclaredException &e)
{
cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
aux_vars.push_back(AuxVarInfo(symb_id, avDiffForward, orig_symb_id, 0, 0, 0, expr_arg));
return symb_id;
}
int
SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const throw (SearchFailedException)
{
for (size_t i = 0; i < aux_vars.size(); i++)
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)
return aux_vars[i].get_symb_id();
throw SearchFailedException(orig_symb_id, orig_lead_lag);
}
expr_t
SymbolTable::getAuxiliaryVarsExprNode(int symb_id) const throw (SearchFailedException)
// throw exception if it is a Lagrange multiplier
{
for (size_t i = 0; i < aux_vars.size(); i++)
if (aux_vars[i].get_symb_id() == symb_id)
{
expr_t expr_node = aux_vars[i].get_expr_node();
if (expr_node != NULL)
return expr_node;
else
throw SearchFailedException(symb_id);
}
throw SearchFailedException(symb_id);
}
void
SymbolTable::markPredetermined(int symb_id) throw (UnknownSymbolIDException, FrozenException)
{
validateSymbID(symb_id);
if (frozen)
throw FrozenException();
assert(getType(symb_id) == eEndogenous);
predetermined_variables.insert(symb_id);
}
bool
SymbolTable::isPredetermined(int symb_id) const throw (UnknownSymbolIDException)
{
validateSymbID(symb_id);
return (predetermined_variables.find(symb_id) != predetermined_variables.end());
}
int
SymbolTable::predeterminedNbr() const
{
return (predetermined_variables.size());
}
void
SymbolTable::addObservedVariable(int symb_id) throw (UnknownSymbolIDException)
{
validateSymbID(symb_id);
assert(getType(symb_id) == eEndogenous);
varobs.push_back(symb_id);
}
int
SymbolTable::observedVariablesNbr() const
{
return (int) varobs.size();
}
bool
SymbolTable::isObservedVariable(int symb_id) const
{
return (find(varobs.begin(), varobs.end(), symb_id) != varobs.end());
}
int
SymbolTable::getObservedVariableIndex(int symb_id) const
{
vector<int>::const_iterator it = find(varobs.begin(), varobs.end(), symb_id);
assert(it != varobs.end());
return (int) (it - varobs.begin());
}
vector <int>
SymbolTable::getTrendVarIds() const
{
vector <int> trendVars;
for (symbol_table_type::const_iterator it = symbol_table.begin();
it != symbol_table.end(); it++)
if (getType(it->second) == eTrend || getType(it->second) == eLogTrend)
trendVars.push_back(it->second);
return trendVars;
}
set<int>
SymbolTable::getExogenous() const
{
set <int> exogs;
for (symbol_table_type::const_iterator it = symbol_table.begin();
it != symbol_table.end(); it++)
if (getType(it->second) == eExogenous)
exogs.insert(it->second);
return exogs;
}
set<int>
SymbolTable::getEndogenous() const
{
set <int> endogs;
for (symbol_table_type::const_iterator it = symbol_table.begin();
it != symbol_table.end(); it++)
if (getType(it->second) == eEndogenous)
endogs.insert(it->second);
return endogs;
}
bool
SymbolTable::isAuxiliaryVariable(int symb_id) const
{
for (int i = 0; i < (int) aux_vars.size(); i++)
if (aux_vars[i].get_symb_id() == symb_id)
return true;
return false;
}
bool
SymbolTable::isAuxiliaryVariableButNotMultiplier(int symb_id) const
{
for (int i = 0; i < (int) aux_vars.size(); i++)
if (aux_vars[i].get_symb_id() == symb_id && aux_vars[i].get_type() != avMultiplier)
return true;
return false;
}
set<int>
SymbolTable::getOrigEndogenous() const
{
set <int> origendogs;
for (symbol_table_type::const_iterator it = symbol_table.begin();
it != symbol_table.end(); it++)
if (getType(it->second) == eEndogenous && !isAuxiliaryVariable(it->second))
origendogs.insert(it->second);
return origendogs;
}
void
SymbolTable::writeJuliaOutput(ostream &output) const throw (NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
output << "# Endogenous Variables" << endl
<< "model_.endo = [" << endl;
if (endo_nbr() > 0)
for (int id = 0; id < endo_nbr(); id++)
output << " DynareModel.Endo(\""
<< getName(endo_ids[id]) << "\", \""
<< getTeXName(endo_ids[id]) << "\", \""
<< getLongName(endo_ids[id]) << "\")" << endl;
output << " ]" << endl;
output << "# Exogenous Variables" << endl
<< "model_.exo = [" << endl;
if (exo_nbr() > 0)
for (int id = 0; id < exo_nbr(); id++)
output << " DynareModel.Exo(\""
<< getName(exo_ids[id]) << "\", \""
<< getTeXName(exo_ids[id]) << "\", \""
<< getLongName(exo_ids[id]) << "\")" << endl;
output << " ]" << endl;
if (exo_det_nbr() > 0)
{
output << "# Exogenous Deterministic Variables" << endl
<< "model_.exo_det = [" << endl;
if (exo_det_nbr() > 0)
for (int id = 0; id < exo_det_nbr(); id++)
output << " DynareModel.ExoDet(\""
<< getName(exo_det_ids[id]) << "\", \""
<< getTeXName(exo_det_ids[id]) << "\", \""
<< getLongName(exo_det_ids[id]) << "\")" << endl;
output << " ]" << endl;
}
output << "# Parameters" << endl
<< "model_.param = [" << endl;
if (param_nbr() > 0)
for (int id = 0; id < param_nbr(); id++)
output << " DynareModel.Param(\""
<< getName(param_ids[id]) << "\", \""
<< getTeXName(param_ids[id]) << "\", \""
<< getLongName(param_ids[id]) << "\")" << endl;
output << " ]" << endl;
output << "model_.orig_endo_nbr = " << orig_endo_nbr() << endl;
if (aux_vars.size() > 0)
{
output << "# Auxiliary Variables" << endl
<< "model_.aux_vars = [" << endl;
for (int i = 0; i < (int) aux_vars.size(); i++)
{
output << " DynareModel.AuxVars("
<< getTypeSpecificID(aux_vars[i].get_symb_id()) + 1 << ", "
<< aux_vars[i].get_type() << ", ";
switch (aux_vars[i].get_type())
{
case avEndoLead:
case avExoLead:
break;
case avEndoLag:
case avExoLag:
output << getTypeSpecificID(aux_vars[i].get_orig_symb_id()) + 1 << ", "
<< aux_vars[i].get_orig_lead_lag() << ", NaN, NaN";
break;
case avMultiplier:
output << "NaN, NaN, " << aux_vars[i].get_equation_number_for_multiplier() + 1
<< ", NaN";
break;
case avDiffForward:
output << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ", NaN, ";
break;
case avExpectation:
output << "NaN, NaN, NaN, \"\\mathbb{E}_{t"
<< (aux_vars[i].get_information_set() < 0 ? "" : "+")
<< aux_vars[i].get_information_set() << "}(";
aux_vars[i].get_expr_node()->writeOutput(output, oLatexDynamicModel);
output << ")\"";
break;
}
output << ")" << endl;
}
output << "]" << endl;
}
if (predeterminedNbr() > 0)
{
output << "# Predetermined Variables" << endl
<< "model_.pred_vars = [ " << endl;
for (set<int>::const_iterator it = predetermined_variables.begin();
it != predetermined_variables.end(); it++)
output << " DynareModel.PredVars("
<< getTypeSpecificID(*it)+1 << ")" << endl;
output << " ]" << endl;
}
if (observedVariablesNbr() > 0)
{
output << "# Observed Variables" << endl
<< "options_.obs_vars = [" << endl;
for (vector<int>::const_iterator it = varobs.begin();
it != varobs.end(); it++)
output << " DynareModel.ObsVars("
<< getTypeSpecificID(*it)+1 << ")" << endl;
output << " ]" << endl;
}
}
void
SymbolTable::writeJsonOutput(ostream &output) const
{
output << "\"endogenous\": ";
writeJsonVarVector(output, endo_ids);
output << ", \"exogenous\":";
writeJsonVarVector(output, exo_ids);
output << ", \"exogenous_deterministic\": ";
writeJsonVarVector(output, exo_det_ids);
output << ", \"parameters\": ";
writeJsonVarVector(output, param_ids);
}
void
SymbolTable::writeJsonVarVector(ostream &output, const vector<int> &varvec) const
{
output << "[";
for (size_t i = 0; i < varvec.size(); i++)
{
if (i != 0)
output << ", ";
output << "{"
<< "\"name\":\"" << getName(varvec[i]) << "\", "
<< "\"texName\":\"" << boost::replace_all_copy(getTeXName(varvec[i]), "\\", "\\\\") << "\", "
<< "\"longName\":\"" << boost::replace_all_copy(getLongName(varvec[i]), "\\", "\\\\") << "\"}"
<< endl;
}
output << "]" << endl;
}

View File

@ -1,490 +0,0 @@
/*
* Copyright (C) 2003-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SYMBOLTABLE_HH
#define _SYMBOLTABLE_HH
using namespace std;
#include <map>
#include <string>
#include <vector>
#include <set>
#include <ostream>
#include "CodeInterpreter.hh"
#include "ExprNode.hh"
typedef class ExprNode *expr_t;
//! Types of auxiliary variables
enum aux_var_t
{
avEndoLead = 0, //!< Substitute for endo leads >= 2
avEndoLag = 1, //!< Substitute for endo lags >= 2
avExoLead = 2, //!< Substitute for exo leads >= 2
avExoLag = 3, //!< Substitute for exo lags >= 2
avExpectation = 4, //!< Substitute for Expectation Operator
avDiffForward = 5, //!< Substitute for the differentiate of a forward variable
avMultiplier = 6 //!< Multipliers for FOC of Ramsey Problem
};
//! Information on some auxiliary variables
class AuxVarInfo
{
private:
int symb_id; //!< Symbol ID of the auxiliary variable
aux_var_t type; //!< Its type
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. Only used for avEndoLag and avExoLag.
int equation_number_for_multiplier; //!< Stores the original constraint equation number associated with this aux var. Only used for avMultiplier.
int information_set; //! Argument of expectation operator. Only used for avExpectation.
expr_t expr_node; //! Auxiliary variable definition
public:
AuxVarInfo(int symb_id_arg, aux_var_t type_arg, int orig_symb_id, int orig_lead_lag, int equation_number_for_multiplier_arg, int information_set_arg, expr_t expr_node_arg);
int
get_symb_id() const
{
return symb_id;
};
aux_var_t
get_type() const
{
return type;
};
int
get_orig_symb_id() const
{
return orig_symb_id;
};
int
get_orig_lead_lag() const
{
return orig_lead_lag;
};
int
get_equation_number_for_multiplier() const
{
return equation_number_for_multiplier;
};
int
get_information_set() const
{
return information_set;
};
expr_t
get_expr_node() const
{
return expr_node;
};
};
//! Stores the symbol table
/*!
A symbol is given by its name, and is internally represented by a unique integer.
When method freeze() is called, computes a distinct sequence of IDs for some types
(endogenous, exogenous, parameters), which are used by the Matlab/Octave functions.
We call these "type specific IDs".
Also manages a TeX name for each symbol, which by default is an empty string.
*/
class SymbolTable
{
private:
//! Has method freeze() been called?
bool frozen;
typedef map<string, int> symbol_table_type;
//! Maps strings to symbol IDs
symbol_table_type symbol_table;
//! Maps IDs to names
vector<string> name_table;
//! Maps IDs to TeX names
vector<string> tex_name_table;
//! Maps IDs to string names of variables
vector<string> long_name_table;
//! Maps IDs to a pair containing the partition and the partition value
map<int, map<string, string> > partition_value_map;
//! Maps IDs to types
vector<SymbolType> type_table;
//! Maps symbol IDs to type specific IDs
vector<int> type_specific_ids;
//! Maps type specific IDs of endogenous to symbol IDs
vector<int> endo_ids;
//! Maps type specific IDs of exogenous to symbol IDs
vector<int> exo_ids;
//! Maps type specific IDs of exogenous deterministic to symbol IDs
vector<int> exo_det_ids;
//! Maps type specific IDs of parameters to symbol IDs
vector<int> param_ids;
//! Information about auxiliary variables
vector<AuxVarInfo> aux_vars;
//! Stores the predetermined variables (by symbol IDs)
set<int> predetermined_variables;
//! Stores the list of observed variables
vector<int> varobs;
public:
SymbolTable();
//! Thrown when trying to access an unknown symbol (by name)
class UnknownSymbolNameException
{
public:
//! Symbol name
string name;
UnknownSymbolNameException(const string &name_arg) : name(name_arg)
{
}
};
//! Thrown when trying to access an unknown symbol (by id)
class UnknownSymbolIDException
{
public:
//! Symbol ID
int id;
UnknownSymbolIDException(int id_arg) : id(id_arg)
{
}
};
//! Thrown when trying to access an unknown type specific ID
class UnknownTypeSpecificIDException
{
public:
int tsid;
SymbolType type;
UnknownTypeSpecificIDException(int tsid_arg, SymbolType type_arg) : tsid(tsid_arg), type(type_arg)
{
}
};
//! Thrown when trying to declare a symbol twice
class AlreadyDeclaredException
{
public:
//! Symbol name
string name;
//! Was the previous declaration done with the same symbol type ?
bool same_type;
AlreadyDeclaredException(const string &name_arg, bool same_type_arg) : name(name_arg), same_type(same_type_arg)
{
}
};
//! Thrown when table is frozen and trying to modify it
class FrozenException
{
};
//! Thrown when trying to use the result of freeze() while this method has not yet been called
class NotYetFrozenException
{
};
//! Thrown when searchAuxiliaryVars() failed
class SearchFailedException
{
public:
int orig_symb_id, orig_lead_lag, symb_id;
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)
{
}
SearchFailedException(int symb_id_arg) : symb_id(symb_id_arg)
{
}
};
private:
//! Factorized code for adding aux lag variables
int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t arg) throw (FrozenException);
//! Factorized code for adding aux lead variables
int addLeadAuxiliaryVarInternal(bool endo, int index, expr_t arg) throw (FrozenException);
//! Factorized code for Json writing
void writeJsonVarVector(ostream &output, const vector<int> &varvec) const;
//! Factorized code for asserting that 0 <= symb_id <= symbol_table.size()
inline void validateSymbID(int symb_id) const throw (UnknownSymbolIDException);
public:
//! Add a symbol
/*! Returns the symbol ID */
int addSymbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string *, string *> *> *partition_value) throw (AlreadyDeclaredException, FrozenException);
//! Add a symbol without its TeX name (will be equal to its name)
/*! Returns the symbol ID */
int addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException);
//! Adds an auxiliary variable for endogenous with lead >= 2
/*!
\param[in] index Used to construct the variable name
\return the symbol ID of the new symbol */
int addEndoLeadAuxiliaryVar(int index, expr_t arg) throw (FrozenException);
//! Adds an auxiliary variable for endogenous with lag >= 2
/*!
\param[in] orig_symb_id symbol ID of the endogenous declared by the user that this new variable will represent
\param[in] orig_lead_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lead_lag)
\return the symbol ID of the new symbol */
int addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t arg) throw (FrozenException);
//! Adds an auxiliary variable for endogenous with lead >= 1
/*!
\param[in] index Used to construct the variable name
\return the symbol ID of the new symbol */
int addExoLeadAuxiliaryVar(int index, expr_t arg) throw (FrozenException);
//! Adds an auxiliary variable for exogenous with lag >= 1
/*!
\param[in] orig_symb_id symbol ID of the exogenous declared by the user that this new variable will represent
\param[in] orig_lead_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lead_lag)
\return the symbol ID of the new symbol */
int addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t arg) throw (FrozenException);
//! Adds an auxiliary variable for the expectation operator
/*!
\param[in] information_set information set (possibly negative) of the expectation operator
\param[in] index Used to construct the variable name
\return the symbol ID of the new symbol
*/
int addExpectationAuxiliaryVar(int information_set, int index, expr_t arg) throw (FrozenException);
//! Adds an auxiliary variable for the multiplier for the FOCs of the Ramsey Problem
/*!
\param[in] index Used to construct the variable name
\return the symbol ID of the new symbol
*/
int addMultiplierAuxiliaryVar(int index) throw (FrozenException);
//! Adds an auxiliary variable for the (time) differentiate of a forward var
/*!
\param[in] orig_symb_id The symb_id of the forward variable
\return the symbol ID of the new symbol
*/
int addDiffForwardAuxiliaryVar(int orig_symb_id, expr_t arg) throw (FrozenException);
//! Searches auxiliary variables which are substitutes for a given symbol_id and lead/lag
/*!
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 throw (SearchFailedException);
//! Returns the number of auxiliary variables
int
AuxVarsSize() const
{
return aux_vars.size();
};
//! Retruns expr_node for an auxiliary variable
expr_t getAuxiliaryVarsExprNode(int symb_id) const throw (SearchFailedException);
//! Tests if symbol already exists
inline bool exists(const string &name) const;
//! Get symbol name (by ID)
inline string getName(int id) const throw (UnknownSymbolIDException);
//! Get TeX name
inline string getTeXName(int id) const throw (UnknownSymbolIDException);
//! Get long name
inline string getLongName(int id) const throw (UnknownSymbolIDException);
//! Returns true if the partition name is the first encountered for the type of variable represented by id
bool isFirstOfPartitionForType(int id) const throw (UnknownSymbolIDException);
//! Returns a list of partitions and symbols that belong to that partition
map<string, map<int, string> > getPartitionsForType(enum SymbolType st) const throw (UnknownSymbolIDException);
//! Get type (by ID)
inline SymbolType getType(int id) const throw (UnknownSymbolIDException);
//! Get type (by name)
inline SymbolType getType(const string &name) const throw (UnknownSymbolNameException);
//! Get ID (by name)
inline int getID(const string &name) const throw (UnknownSymbolNameException);
//! Get ID (by type specific ID)
int getID(SymbolType type, int tsid) const throw (UnknownTypeSpecificIDException, NotYetFrozenException);
//! Freeze symbol table
void freeze() throw (FrozenException);
//! unreeze symbol table
//! Used after having written JSON files
void unfreeze();
//! Change the type of a symbol
void changeType(int id, SymbolType newtype) throw (UnknownSymbolIDException, FrozenException);
//! Get type specific ID (by symbol ID)
inline int getTypeSpecificID(int id) const throw (UnknownSymbolIDException, NotYetFrozenException);
//! Get type specific ID (by symbol name)
inline int getTypeSpecificID(const string &name) const throw (UnknownSymbolNameException, NotYetFrozenException);
//! Get number of endogenous variables
inline int endo_nbr() const throw (NotYetFrozenException);
//! Get number of exogenous variables
inline int exo_nbr() const throw (NotYetFrozenException);
//! Get number of exogenous deterministic variables
inline int exo_det_nbr() const throw (NotYetFrozenException);
//! Get number of parameters
inline int param_nbr() const throw (NotYetFrozenException);
//! Returns the greatest symbol ID (the smallest is zero)
inline int maxID();
//! Get number of user-declared endogenous variables (without the auxiliary variables)
inline int orig_endo_nbr() const throw (NotYetFrozenException);
//! Write output of this class
void writeOutput(ostream &output) const throw (NotYetFrozenException);
//! Write JSON Output
void writeJsonOutput(ostream &output) const;
//! Write Julia output of this class
void writeJuliaOutput(ostream &output) const throw (NotYetFrozenException);
//! Write C output of this class
void writeCOutput(ostream &output) const throw (NotYetFrozenException);
//! Write CC output of this class
void writeCCOutput(ostream &output) const throw (NotYetFrozenException);
//! Mark a symbol as predetermined variable
void markPredetermined(int symb_id) throw (UnknownSymbolIDException, FrozenException);
//! Test if a given symbol is a predetermined variable
bool isPredetermined(int symb_id) const throw (UnknownSymbolIDException);
//! Return the number of predetermined variables
int predeterminedNbr() const;
//! Add an observed variable
void addObservedVariable(int symb_id) throw (UnknownSymbolIDException);
//! Return the number of observed variables
int observedVariablesNbr() const;
//! Is a given symbol in the set of observed variables
bool isObservedVariable(int symb_id) const;
//! Return the index of a given observed variable in the vector of all observed variables
int getObservedVariableIndex(int symb_id) const;
vector <int> getTrendVarIds() const;
//! Get list of exogenous variables
set <int> getExogenous() const;
//! Get list of endogenous variables
set <int> getEndogenous() const;
//! Is a given symbol an auxiliary variable
bool isAuxiliaryVariable(int symb_id) const;
//! Is a given symbol an auxiliary variable but not a Lagrange multiplier
bool isAuxiliaryVariableButNotMultiplier(int symb_id) const;
//! Get list of endogenous variables without aux vars
set <int> getOrigEndogenous() const;
};
inline void
SymbolTable::validateSymbID(int symb_id) const throw (UnknownSymbolIDException)
{
if (symb_id < 0 || symb_id > (int) symbol_table.size())
throw UnknownSymbolIDException(symb_id);
}
inline bool
SymbolTable::exists(const string &name) const
{
symbol_table_type::const_iterator iter = symbol_table.find(name);
return (iter != symbol_table.end());
}
inline string
SymbolTable::getName(int id) const throw (UnknownSymbolIDException)
{
validateSymbID(id);
return name_table[id];
}
inline string
SymbolTable::getTeXName(int id) const throw (UnknownSymbolIDException)
{
validateSymbID(id);
return tex_name_table[id];
}
inline string
SymbolTable::getLongName(int id) const throw (UnknownSymbolIDException)
{
validateSymbID(id);
return long_name_table[id];
}
inline SymbolType
SymbolTable::getType(int id) const throw (UnknownSymbolIDException)
{
validateSymbID(id);
return type_table[id];
}
inline SymbolType
SymbolTable::getType(const string &name) const throw (UnknownSymbolNameException)
{
return getType(getID(name));
}
inline int
SymbolTable::getID(const string &name) const throw (UnknownSymbolNameException)
{
symbol_table_type::const_iterator iter = symbol_table.find(name);
if (iter != symbol_table.end())
return iter->second;
else
throw UnknownSymbolNameException(name);
}
inline int
SymbolTable::getTypeSpecificID(int id) const throw (UnknownSymbolIDException, NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
validateSymbID(id);
return type_specific_ids[id];
}
inline int
SymbolTable::getTypeSpecificID(const string &name) const throw (UnknownSymbolNameException, NotYetFrozenException)
{
return getTypeSpecificID(getID(name));
}
inline int
SymbolTable::endo_nbr() const throw (NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
return endo_ids.size();
}
inline int
SymbolTable::exo_nbr() const throw (NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
return exo_ids.size();
}
inline int
SymbolTable::exo_det_nbr() const throw (NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
return exo_det_ids.size();
}
inline int
SymbolTable::param_nbr() const throw (NotYetFrozenException)
{
if (!frozen)
throw NotYetFrozenException();
return param_ids.size();
}
inline int
SymbolTable::maxID()
{
return symbol_table.size() - 1;
}
inline int
SymbolTable::orig_endo_nbr() const throw (NotYetFrozenException)
{
return (endo_nbr() - aux_vars.size());
}
#endif

View File

@ -1,109 +0,0 @@
/*
* Copyright (C) 2012-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WarningConsolidation.hh"
#include <ostream>
WarningConsolidation
&
operator<<(WarningConsolidation &wcc, const string &warning)
{
if (wcc.no_warn)
return wcc;
cerr << warning;
wcc.addWarning(warning);
return wcc;
};
WarningConsolidation &
operator<<(WarningConsolidation &wcc, const Dynare::location &loc)
{
if (wcc.no_warn)
return wcc;
stringstream ostr;
Dynare::position last = loc.end - 1;
ostr << loc.begin;
if (last.filename
&& (!loc.begin.filename
|| *loc.begin.filename != *last.filename))
ostr << '-' << last;
else if (loc.begin.line != last.line)
ostr << '-' << last.line << '.' << last.column;
else if (loc.begin.column != last.column)
ostr << '-' << last.column;
cerr << ostr.str();
wcc.addWarning(ostr.str());
return wcc;
};
WarningConsolidation &
operator<<(WarningConsolidation &wcc, ostream & (*pf)(ostream &))
{
if (wcc.no_warn)
return wcc;
cerr << pf;
wcc.addWarning(pf);
return wcc;
}
void
WarningConsolidation::writeOutput(ostream &output) const
{
if (warnings.str().empty())
return;
output << "disp([char(10) 'Dynare Preprocessor Warning(s) Encountered:']);" << endl;
bool writedisp = true;
string warningsstr = warnings.str();
for (size_t i = 0; i < warningsstr.length(); i++)
{
if (writedisp)
{
output << "disp(' ";
writedisp = false;
}
if (warningsstr[i] != '\n')
output << warningsstr[i];
else
{
output << "');" << endl;
if (i+1 < warningsstr.length())
writedisp = true;
}
}
}
int
WarningConsolidation::countWarnings() const
{
size_t p = 0;
int n = 0;
while ((p = warnings.str().find('\n', p)) != string::npos)
{
p++;
n++;
}
return n;
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (C) 2012-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WARNINGCONSOLIDATION_HH
#define _WARNINGCONSOLIDATION_HH
#include <sstream>
#include <string>
#include "location.hh"
using namespace std;
//! Stores Warnings issued by the Preprocessor
class WarningConsolidation
{
private:
stringstream warnings;
bool no_warn;
public:
WarningConsolidation(bool no_warn_arg) : no_warn(no_warn_arg)
{
};
~WarningConsolidation()
{
};
//! Add A Warning to the StringStream
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, const string &warning);
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, const Dynare::location &loc);
friend WarningConsolidation &operator<<(WarningConsolidation &wcc, ostream & (*pf)(ostream &));
inline void
addWarning(const string &w)
{
warnings << w;
};
inline void
addWarning(ostream & (*pf)(ostream &))
{
warnings << pf;
};
//! Write Warnings to m file
void writeOutput(ostream &output) const;
//! Count warnings
/*! This is done in a very lousy way, by counting newlines in the
stringstream... */
int countWarnings() const;
};
#endif

View File

@ -1,214 +0,0 @@
/*
* Copyright (C) 2008-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
%skeleton "lalr1.cc"
%require "2.5"
%defines
%code top {
class MacroDriver;
}
%name-prefix "Macro"
%parse-param { MacroDriver &driver }
%parse-param { ostream &out }
%lex-param { MacroDriver &driver }
%locations
%initial-action
{
// Initialize the location filenames
@$.begin.filename = @$.end.filename = &driver.file;
};
%debug
%error-verbose
%code requires {
#include "MacroValue.hh"
}
%union
{
string *string_val;
int int_val;
const MacroValue *mv;
};
%code {
#include <cstdlib> // Pour atoi()
#include "MacroDriver.hh"
/* this "connects" the bison parser in the driver to the flex scanner class
* object. it defines the yylex() function call to pull the next token from the
* current lexer object of the driver context. */
#undef yylex
#define yylex driver.lexer->lex
#define TYPERR_CATCH(statement, loc) try \
{ \
statement; \
} \
catch(MacroValue::TypeError &e) \
{ \
driver.error(loc, e.message); \
}
}
%token DEFINE LINE FOR IN IF ELSE ENDIF ECHO_DIR ERROR IFDEF IFNDEF
%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL LENGTH ECHOMACROVARS SAVE
%token <int_val> INTEGER
%token <string_val> NAME STRING
%left COMMA
%left LOGICAL_OR
%left LOGICAL_AND
%left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL
%nonassoc IN
%nonassoc COLON
%left PLUS MINUS
%left TIMES DIVIDE
%left UMINUS UPLUS EXCLAMATION
%left LBRACKET
%type <mv> expr array_expr
%%
%start statement_list_or_nothing;
statement_list_or_nothing : /* empty */
| statement_list
;
statement_list : statement EOL
| statement_list statement EOL
;
statement : expr
{ out << $1->toString(); }
| DEFINE NAME EQUAL expr
{ driver.set_variable(*$2, $4); delete $2; }
| FOR NAME IN expr
{ TYPERR_CATCH(driver.init_loop(*$2, $4), @$); delete $2; }
| IF expr
{ TYPERR_CATCH(driver.begin_if($2), @$); }
| IFDEF NAME
{ TYPERR_CATCH(driver.begin_ifdef(*$2), @$); delete $2; }
| IFNDEF NAME
{ TYPERR_CATCH(driver.begin_ifndef(*$2), @$); delete $2; }
| ECHO_DIR expr
{ TYPERR_CATCH(driver.echo(@$, $2), @$); }
| ERROR expr
{ TYPERR_CATCH(driver.error(@$, $2), @$); }
| LINE STRING INTEGER
/* Ignore @#line declarations */
| ECHOMACROVARS
{ driver.printvars(@$, true); }
| ECHOMACROVARS LPAREN SAVE RPAREN
{ out << driver.printvars(@$, false); }
;
expr : INTEGER
{ $$ = new IntMV(driver, $1); }
| STRING
{ $$ = new StringMV(driver, *$1); delete $1; }
| NAME
{
try
{
$$ = driver.get_variable(*$1);
}
catch(MacroDriver::UnknownVariable(&e))
{
error(@$, "Unknown variable: " + e.name);
}
delete $1;
}
| LENGTH LPAREN array_expr RPAREN
{ TYPERR_CATCH($$ = $3->length(), @$); }
| LPAREN expr RPAREN
{ $$ = $2; }
| expr PLUS expr
{ TYPERR_CATCH($$ = *$1 + *$3, @$); }
| expr MINUS expr
{ TYPERR_CATCH($$ = *$1 - *$3, @$); }
| expr TIMES expr
{ TYPERR_CATCH($$ = *$1 * *$3, @$); }
| expr DIVIDE expr
{
if (dynamic_cast<const IntMV *>($3) != NULL
&& ((IntMV *)$3)->get_int_value() == 0)
driver.error(@$, "Division by zero");
TYPERR_CATCH($$ = *$1 / *$3, @$);
}
| expr LESS expr
{ TYPERR_CATCH($$ = *$1 < *$3, @$); }
| expr GREATER expr
{ TYPERR_CATCH($$ = *$1 > *$3, @$); }
| expr LESS_EQUAL expr
{ TYPERR_CATCH($$ = *$1 <= *$3, @$); }
| expr GREATER_EQUAL expr
{ TYPERR_CATCH($$ = *$1 >= *$3, @$); }
| expr EQUAL_EQUAL expr
{ TYPERR_CATCH($$ = *$1 == *$3, @$); }
| expr EXCLAMATION_EQUAL expr
{ TYPERR_CATCH($$ = *$1 != *$3, @$); }
| expr LOGICAL_OR expr
{ TYPERR_CATCH($$ = *$1 || *$3, @$); }
| expr LOGICAL_AND expr
{ TYPERR_CATCH($$ = *$1 && *$3, @$); }
| MINUS expr %prec UMINUS
{ TYPERR_CATCH($$ = -*$2, @$); }
| PLUS expr %prec UPLUS
{ TYPERR_CATCH($$ = +(*$2), @$); }
| EXCLAMATION expr
{ TYPERR_CATCH($$ = !*$2, @$); }
| expr LBRACKET array_expr RBRACKET
{
TYPERR_CATCH($$ = (*$1)[*$3], @$)
catch(MacroValue::OutOfBoundsError)
{
error(@$, "Index out of bounds");
}
}
| LBRACKET array_expr RBRACKET
{ $$ = $2; }
| expr COLON expr
{ TYPERR_CATCH($$ = IntMV::new_range(driver, $1, $3), @$); }
| expr IN expr
{ TYPERR_CATCH($$ = $1->in($3), @$); }
;
array_expr : expr
{ $$ = $1->toArray(); }
| array_expr COMMA expr
{ TYPERR_CATCH($$ = $3->append($1), @$); }
;
%%
void
Macro::parser::error(const Macro::parser::location_type &l,
const string &m)
{
driver.error(l, m);
}

View File

@ -1,238 +0,0 @@
/*
* Copyright (C) 2008-2018 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <boost/lexical_cast.hpp>
#include "MacroDriver.hh"
MacroDriver::MacroDriver()
{
}
MacroDriver::~MacroDriver()
{
for (set<const MacroValue *>::iterator it = values.begin();
it != values.end(); it++)
delete *it;
}
void
MacroDriver::parse(const string &f, const string &fb, const string &modfiletxt,
ostream &out, bool debug, bool no_line_macro_arg, map<string, string> defines,
vector<string> path)
{
file = f;
basename = fb;
no_line_macro = no_line_macro_arg;
/*
Copy the file into a stringstream, and add an extra end-of-line. This is a
workaround for trac ticket #73: with this workaround, MOD files ending with
an @#endif or an @#endfor - but no newline - no longer trigger an error.
*/
stringstream file_with_endl;
for (map<string, string>::iterator it = defines.begin();
it != defines.end(); it++)
try
{
boost::lexical_cast<int>(it->second);
file_with_endl << "@#define " << it->first << " = " << it->second << endl;
}
catch (boost::bad_lexical_cast &)
{
if (!it->second.empty() && it->second.at(0) == '[' && it->second.at(it->second.length()-1) == ']')
// If the input is an array. Issue #1578
file_with_endl << "@#define " << it->first << " = " << it->second << endl;
else
file_with_endl << "@#define " << it->first << " = \"" << it->second << "\"" << endl;
}
file_with_endl << modfiletxt << endl;
lexer = new MacroFlex(&file_with_endl, &out, no_line_macro, path);
lexer->set_debug(debug);
Macro::parser parser(*this, out);
parser.set_debug_level(debug);
// Output first @#line statement
if (!no_line_macro)
out << "@#line \"" << file << "\" 1" << endl;
// Launch macro-processing
parser.parse();
delete lexer;
}
void
MacroDriver::error(const Macro::parser::location_type &l, const string &m) const
{
cerr << "ERROR in macro-processor: " << l << ": " << m << endl;
exit(EXIT_FAILURE);
}
void
MacroDriver::set_variable(const string &name, const MacroValue *value)
{
env[name] = value;
}
const MacroValue *
MacroDriver::get_variable(const string &name) const throw (UnknownVariable)
{
map<string, const MacroValue *>::const_iterator it = env.find(name);
if (it == env.end())
throw UnknownVariable(name);
return it->second;
}
void
MacroDriver::init_loop(const string &name, const MacroValue *value) throw (MacroValue::TypeError)
{
const ArrayMV<int> *mv1 = dynamic_cast<const ArrayMV<int> *>(value);
const ArrayMV<string> *mv2 = dynamic_cast<const ArrayMV<string> *>(value);
if (!mv1 && !mv2)
throw MacroValue::TypeError("Argument of @#for loop must be an array expression");
loop_stack.push(make_pair(name, make_pair(value, 0)));
}
bool
MacroDriver::iter_loop()
{
if (loop_stack.empty())
throw "No loop on which to iterate!";
int &i = loop_stack.top().second.second;
const MacroValue *mv = loop_stack.top().second.first;
string name = loop_stack.top().first;
const ArrayMV<int> *mv1 = dynamic_cast<const ArrayMV<int> *>(mv);
if (mv1)
{
if (i >= (int) mv1->values.size())
{
loop_stack.pop();
return false;
}
else
{
env[name] = new IntMV(*this, mv1->values[i++]);
return true;
}
}
else
{
const ArrayMV<string> *mv2 = dynamic_cast<const ArrayMV<string> *>(mv);
if (i >= (int) mv2->values.size())
{
loop_stack.pop();
return false;
}
else
{
env[name] = new StringMV(*this, mv2->values[i++]);
return true;
}
}
}
void
MacroDriver::begin_if(const MacroValue *value) throw (MacroValue::TypeError)
{
const IntMV *ival = dynamic_cast<const IntMV *>(value);
if (!ival)
throw MacroValue::TypeError("Argument of @#if must be an integer");
last_if = (bool) ival->value;
}
void
MacroDriver::begin_ifdef(const string &name)
{
try
{
get_variable(name);
begin_if(new IntMV(*this, 1));
}
catch (UnknownVariable &)
{
begin_if(new IntMV(*this, 0));
}
}
void
MacroDriver::begin_ifndef(const string &name)
{
try
{
get_variable(name);
begin_if(new IntMV(*this, 0));
}
catch (UnknownVariable &)
{
begin_if(new IntMV(*this, 1));
}
}
void
MacroDriver::echo(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError)
{
const StringMV *sval = dynamic_cast<const StringMV *>(value);
if (!sval)
throw MacroValue::TypeError("Argument of @#echo must be a string");
cerr << "ECHO in macro-processor: " << l << ": " << sval->value << endl;
}
void
MacroDriver::error(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError)
{
const StringMV *sval = dynamic_cast<const StringMV *>(value);
if (!sval)
throw MacroValue::TypeError("Argument of @#error must be a string");
error(l, sval->value);
}
string
MacroDriver::printvars(const Macro::parser::location_type &l, const bool tostdout) const
{
if (tostdout)
{
cout << "Macroprocessor: Printing macro variable values from " << file
<< " at line " << l.begin.line << endl;
for (map<string, const MacroValue *>::const_iterator it = env.begin();
it != env.end(); it++)
cout << " " << it->first << " = " << it->second->print() << endl;
cout << endl;
return "";
}
stringstream intomfile;
if (!no_line_macro)
intomfile << "@#line \"" << file << "\" " << l.begin.line << endl;
for (map<string, const MacroValue *>::const_iterator it = env.begin();
it != env.end(); it++)
intomfile<< "options_.macrovars_line_" << l.begin.line << "." << it->first << " = " << it->second->print() << ";" << endl;
return intomfile.str();
}

View File

@ -1,240 +0,0 @@
/*
* Copyright (C) 2008-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MACRO_DRIVER_HH
#define _MACRO_DRIVER_HH
#ifdef _PARSING_DRIVER_HH
# error Impossible to include both ParsingDriver.hh and MacroDriver.hh
#endif
#include <string>
#include <iostream>
#include <stack>
#include <map>
#include <set>
#include "MacroValue.hh"
#include "MacroBison.hh"
using namespace std;
// Declare MacroFlexLexer class
#ifndef __FLEX_LEXER_H
# define yyFlexLexer MacroFlexLexer
# include <FlexLexer.h>
# undef yyFlexLexer
#endif
//! The lexer class
/*! Actually it was necessary to subclass the MacroFlexLexer class generated by Flex,
since the prototype for MacroFlexLexer::yylex() was not convenient.
*/
class MacroFlex : public MacroFlexLexer
{
private:
//! Used to backup all the information related to a given scanning context
class ScanContext
{
public:
istream *input;
struct yy_buffer_state *buffer;
const Macro::parser::location_type yylloc;
const bool is_for_context;
const string for_body;
const Macro::parser::location_type for_body_loc;
ScanContext(istream *input_arg, struct yy_buffer_state *buffer_arg,
Macro::parser::location_type &yylloc_arg, bool is_for_context_arg,
const string &for_body_arg,
Macro::parser::location_type &for_body_loc_arg) :
input(input_arg), buffer(buffer_arg), yylloc(yylloc_arg), is_for_context(is_for_context_arg),
for_body(for_body_arg), for_body_loc(for_body_loc_arg)
{
}
};
//! The stack used to keep track of nested scanning contexts
stack<ScanContext> context_stack;
//! Input stream used for initialization of current scanning context
/*! Kept for deletion at end of current scanning buffer */
istream *input;
//! Should we omit the @#line statements ?
const bool no_line_macro;
//! The paths to search when looking for .mod files
vector<string> path;
//! True iff current context is the body of a loop
bool is_for_context;
//! If current context is the body of a loop, contains the string of the loop body
string for_body;
//! If current context is the body of a loop, contains the location of the beginning of the body
Macro::parser::location_type for_body_loc;
//! Temporary variable used in FOR_BODY mode
string for_body_tmp;
//! Temporary variable used in FOR_BODY mode
Macro::parser::location_type for_body_loc_tmp;
//! Temporary variable used in FOR_BODY mode. Keeps track of the location of the @#for statement, for reporting messages
Macro::parser::location_type for_stmt_loc_tmp;
//! Temporary variable used in FOR_BODY mode. Keeps track of number of nested @#for/@#endfor
int nested_for_nb;
//! Set to true while parsing a FOR statement (only the statement, not the loop body)
bool reading_for_statement;
//! Temporary variable used in THEN_BODY and ELSE_BODY modes. Keeps track of number of nested @#if
int nested_if_nb;
//! Temporary variable used in THEN_BODY mode
string then_body_tmp;
//! Temporary variable used in THEN_BODY mode
Macro::parser::location_type then_body_loc_tmp;
//! Temporary variable used in THEN_BODY mode. Keeps track of the location of the @#if statement, for reporting messages
Macro::parser::location_type if_stmt_loc_tmp;
//! Temporary variable used in ELSE_BODY mode
string else_body_tmp;
//! Temporary variable used in ELSE_BODY mode
Macro::parser::location_type else_body_loc_tmp;
//! Set to true while parsing an IF statement (only the statement, not the body)
bool reading_if_statement;
//! Output the @#line declaration
void output_line(Macro::parser::location_type *yylloc) const;
//! Save current scanning context
void save_context(Macro::parser::location_type *yylloc);
//! Restore last scanning context
void restore_context(Macro::parser::location_type *yylloc);
//! pushes the colon-separated paths passed to @#includepath onto the path vector
void push_path(string *includepath, Macro::parser::location_type *yylloc,
MacroDriver &driver);
//! Saves current scanning context and create a new context with content of filename
/*! Filename must be a newly allocated string which will be deleted by the lexer */
void create_include_context(string *filename, Macro::parser::location_type *yylloc,
MacroDriver &driver);
//! Saves current scanning context and create a new context based on the "then" body
void create_then_context(Macro::parser::location_type *yylloc);
//! Saves current scanning context and create a new context based on the "else" body
void create_else_context(Macro::parser::location_type *yylloc);
//! Initialise a new flex buffer with the loop body
void new_loop_body_buffer(Macro::parser::location_type *yylloc);
public:
MacroFlex(istream *in, ostream *out, bool no_line_macro_arg, vector<string> path_arg);
//! The main lexing function
Macro::parser::token_type lex(Macro::parser::semantic_type *yylval,
Macro::parser::location_type *yylloc,
MacroDriver &driver);
};
//! Implements the macro expansion using a Flex scanner and a Bison parser
class MacroDriver
{
friend class MacroValue;
private:
//! Stores all created macro values
set<const MacroValue *> values;
//! Environment: maps macro variables to their values
map<string, const MacroValue *> env;
//! Stack used to keep track of (possibly nested) loops
//! First element is loop variable name, second is the array over which iteration is done, and third is subscript to be used by next call of iter_loop() (beginning with 0) */
stack<pair<string, pair<const MacroValue *, int> > > loop_stack;
public:
//! Exception thrown when value of an unknown variable is requested
class UnknownVariable
{
public:
const string name;
UnknownVariable(const string &name_arg) : name(name_arg)
{
}
};
//! Constructor
MacroDriver();
//! Destructor
virtual
~MacroDriver();
//! Starts parsing a file, returns output in out
/*! \param no_line_macro should we omit the @#line statements ? */
void parse(const string &f, const string &fb, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro_arg,
map<string, string> defines, vector<string> path);
//! Name of main file being parsed
string file;
//! Basename of main file being parsed
string basename;
//! Whether or not to print @#line
bool no_line_macro;
//! Reference to the lexer
class MacroFlex *lexer;
//! Used to store the value of the last @#if condition
bool last_if;
//! Error handler
void error(const Macro::parser::location_type &l, const string &m) const;
//! Print variables
string printvars(const Macro::parser::location_type &l, const bool save) const;
//! Set a variable
void set_variable(const string &name, const MacroValue *value);
//! Get a variable
/*! Returns a newly allocated value (clone of the value stored in environment). */
const MacroValue *get_variable(const string &name) const throw (UnknownVariable);
//! Initiate a for loop
/*! Does not set name = value[1]. You must call iter_loop() for that. */
void init_loop(const string &name, const MacroValue *value) throw (MacroValue::TypeError);
//! Iterate innermost loop
/*! Returns false if iteration is no more possible (end of loop); in that case it destroys the pointer given to init_loop() */
bool iter_loop();
//! Begins an @#if statement
void begin_if(const MacroValue *value) throw (MacroValue::TypeError);
//! Begins an @#ifdef statement
void begin_ifdef(const string &name);
//! Begins an @#ifndef statement
void begin_ifndef(const string &name);
//! Executes @#echo directive
void echo(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError);
//! Executes @#error directive
void error(const Macro::parser::location_type &l, const MacroValue *value) const throw (MacroValue::TypeError);
};
#endif // ! MACRO_DRIVER_HH

View File

@ -1,567 +0,0 @@
/*
* Copyright (C) 2008-2018 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
%{
using namespace std;
#include <fstream>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/tokenizer.hpp>
#include "MacroDriver.hh"
// Announce to Flex the prototype we want for lexing function
#define YY_DECL \
Macro::parser::token_type \
MacroFlex::lex(Macro::parser::semantic_type *yylval, \
Macro::parser::location_type *yylloc, \
MacroDriver &driver)
// Shortcut to access tokens defined by Bison
typedef Macro::parser::token token;
/* By default yylex returns int, we use token_type.
Unfortunately yyterminate by default returns 0, which is
not of token_type. */
#define yyterminate() return Macro::parser::token_type (0);
%}
%option c++
%option prefix="Macro"
%option case-insensitive noyywrap nounput batch debug never-interactive
%x STMT
%x EXPR
%x FOR_BODY
%x THEN_BODY
%x ELSE_BODY
%{
// Increments location counter for every token read
#define YY_USER_ACTION yylloc->columns(yyleng);
%}
SPC [ \t]+
EOL (\r)?\n
CONT \\\\
%%
/* Code put at the beginning of yylex() */
%{
// Reset location before reading token
yylloc->step();
%}
<STMT,EXPR,FOR_BODY,THEN_BODY,ELSE_BODY>["/"]["/"].*
<INITIAL>^{SPC}*@#{SPC}*includepath{SPC}+\"([^\"\r\n:;|<>]*){1}(:[^\"\r\n:;|<>]*)*\"{SPC}*{EOL} {
yylloc->lines(1);
yylloc->step();
// Get path
string *includepath = new string(yytext);
int dblq_idx1 = includepath->find('"');
int dblq_idx2 = includepath->find('"', dblq_idx1 + 1);
includepath->erase(dblq_idx2);
includepath->erase(0, dblq_idx1 + 1);
push_path(includepath, yylloc, driver);
BEGIN(INITIAL);
}
<INITIAL>^{SPC}*@#{SPC}*includepath{SPC}+[^\"\r\n]*{SPC}*{EOL} {
yylloc->lines(1);
yylloc->step();
// Get variable name
string pathvar = string(yytext);
int dblq_idx1 = pathvar.find("includepath");
pathvar.erase(0, dblq_idx1 + 11);
pathvar.erase(0, pathvar.find_first_not_of(" \t"));
size_t p = pathvar.find_last_not_of(" \t\n\r");
if (string::npos != p)
pathvar.erase(p+1);
string *includepath = NULL;
try
{
includepath = new string(driver.get_variable(pathvar)->toString());
}
catch(MacroDriver::UnknownVariable(&e))
{
driver.error(*yylloc, "Unknown variable: " + pathvar);
}
push_path(includepath, yylloc, driver);
BEGIN(INITIAL);
}
<INITIAL>^{SPC}*@#{SPC}*include{SPC}+\"[^\"\r\n]*\"{SPC}*{EOL} {
yylloc->lines(1);
yylloc->step();
// Get filename
string *filename = new string(yytext);
int dblq_idx1 = filename->find('"');
int dblq_idx2 = filename->find('"', dblq_idx1 + 1);
filename->erase(dblq_idx2);
filename->erase(0, dblq_idx1 + 1);
create_include_context(filename, yylloc, driver);
BEGIN(INITIAL);
}
<INITIAL>^{SPC}*@#{SPC}*include{SPC}+[^\"\r\n]*{SPC}*{EOL} {
yylloc->lines(1);
yylloc->step();
// Get variable name
string modvarname = string(yytext);
int dblq_idx1 = modvarname.find("include");
modvarname.erase(0, dblq_idx1 + 7);
modvarname.erase(0, modvarname.find_first_not_of(" \t"));
size_t p = modvarname.find_last_not_of(" \t\n\r");
if (string::npos != p)
modvarname.erase(p+1);
string *filename = NULL;
try
{
filename = new string(driver.get_variable(modvarname)->toString());
}
catch(MacroDriver::UnknownVariable(&e))
{
driver.error(*yylloc, "Unknown variable: " + modvarname);
}
create_include_context(filename, yylloc, driver);
BEGIN(INITIAL);
}
<INITIAL>^{SPC}*@# { yylloc->step(); BEGIN(STMT); }
<INITIAL>@\{ { yylloc->step(); BEGIN(EXPR); }
<EXPR>\} { BEGIN(INITIAL); return token::EOL; }
<STMT>{CONT}{SPC}*{EOL} { yylloc->lines(1); yylloc->step(); }
<STMT>{EOL} {
/* If parsing a @#for or an @#if, keep the location
for reporting message in case of error */
if (reading_for_statement)
for_stmt_loc_tmp = *yylloc;
else if (reading_if_statement)
if_stmt_loc_tmp = *yylloc;
yylloc->lines(1);
yylloc->step();
if (reading_for_statement)
{
reading_for_statement = false;
for_body_tmp.erase();
for_body_loc_tmp = *yylloc;
nested_for_nb = 0;
BEGIN(FOR_BODY);
}
else if (reading_if_statement)
{
reading_if_statement = false;
then_body_tmp.erase();
then_body_loc_tmp = *yylloc;
nested_if_nb = 0;
BEGIN(THEN_BODY);
}
else
{
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
yyout << endl;
#else
*yyout << endl;
#endif
BEGIN(INITIAL);
}
return token::EOL;
}
<STMT,EXPR>{SPC}+ { yylloc->step(); }
<STMT,EXPR>[0-9]+ {
yylval->int_val = atoi(yytext);
return token::INTEGER;
}
<STMT,EXPR>\( { return token::LPAREN; }
<STMT,EXPR>\) { return token::RPAREN; }
<STMT,EXPR>\[ { return token::LBRACKET; }
<STMT,EXPR>\] { return token::RBRACKET; }
<STMT,EXPR>: { return token::COLON; }
<STMT,EXPR>, { return token::COMMA; }
<STMT,EXPR>= { return token::EQUAL; }
<STMT,EXPR>[!] { return token::EXCLAMATION; }
<STMT,EXPR>"||" { return token::LOGICAL_OR; }
<STMT,EXPR>&& { return token::LOGICAL_AND; }
<STMT,EXPR>"<=" { return token::LESS_EQUAL; }
<STMT,EXPR>">=" { return token::GREATER_EQUAL; }
<STMT,EXPR>"<" { return token::LESS; }
<STMT,EXPR>">" { return token::GREATER; }
<STMT,EXPR>"==" { return token::EQUAL_EQUAL; }
<STMT,EXPR>"!=" { return token::EXCLAMATION_EQUAL; }
<STMT,EXPR>[+] { return token::PLUS; }
<STMT,EXPR>[-] { return token::MINUS; }
<STMT,EXPR>[*] { return token::TIMES; }
<STMT,EXPR>[/] { return token::DIVIDE; }
<STMT,EXPR>in { return token::IN; }
<STMT,EXPR>length { return token::LENGTH; }
<STMT,EXPR>\"[^\"]*\" {
yylval->string_val = new string(yytext + 1);
yylval->string_val->resize(yylval->string_val->length() - 1);
return token::STRING;
}
<STMT>line { return token::LINE; }
<STMT>define { return token::DEFINE; }
<STMT>echomacrovars { return token::ECHOMACROVARS; }
<STMT>save { return token::SAVE; }
<STMT>for { reading_for_statement = true; return token::FOR; }
<STMT>endfor { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); }
<STMT>ifdef { reading_if_statement = true; return token::IFDEF; }
<STMT>ifndef { reading_if_statement = true; return token::IFNDEF; }
<STMT>if { reading_if_statement = true; return token::IF; }
<STMT>else { driver.error(*yylloc, "@#else is not matched by an @#if/@#ifdef/@#ifndef statement"); }
<STMT>endif { driver.error(*yylloc, "@#endif is not matched by an @#if/@#ifdef/@#ifndef statement"); }
<STMT>echo { return token::ECHO_DIR; }
<STMT>error { return token::ERROR; }
<STMT,EXPR>[A-Za-z_][A-Za-z0-9_]* {
yylval->string_val = new string(yytext);
return token::NAME;
}
<EXPR><<EOF>> { driver.error(*yylloc, "Unexpected end of file while parsing a macro expression"); }
<STMT><<EOF>> { driver.error(*yylloc, "Unexpected end of file while parsing a macro statement"); }
<FOR_BODY>{EOL} { yylloc->lines(1); yylloc->step(); for_body_tmp.append(yytext); }
<FOR_BODY>^{SPC}*@#{SPC}*for({SPC}|{CONT}) {
nested_for_nb++;
for_body_tmp.append(yytext);
yylloc->step();
}
<FOR_BODY>. { for_body_tmp.append(yytext); yylloc->step(); }
<FOR_BODY><<EOF>> { driver.error(for_stmt_loc_tmp, "@#for loop not matched by an @#endfor or file does not end with a new line (unexpected end of file)"); }
<FOR_BODY>^{SPC}*@#{SPC}*endfor{SPC}*(\/\/.*)?{EOL} {
yylloc->lines(1);
yylloc->step();
if (nested_for_nb)
{
/* This @#endfor is not the end of the loop body,
but only that of a nested @#for loop */
nested_for_nb--;
for_body_tmp.append(yytext);
}
else
{
// Switch to loop body context, except if iterating over an empty array
if (driver.iter_loop())
{
// Save old buffer state and location
save_context(yylloc);
is_for_context = true;
for_body = for_body_tmp;
for_body_loc = for_body_loc_tmp;
new_loop_body_buffer(yylloc);
}
BEGIN(INITIAL);
}
}
<THEN_BODY>{EOL} { yylloc->lines(1); yylloc->step(); then_body_tmp.append(yytext); }
<THEN_BODY>^{SPC}*@#{SPC}*if({SPC}|{CONT}) {
nested_if_nb++;
then_body_tmp.append(yytext);
yylloc->step();
}
<THEN_BODY>^{SPC}*@#{SPC}*ifdef({SPC}|{CONT}) {
nested_if_nb++;
then_body_tmp.append(yytext);
yylloc->step();
}
<THEN_BODY>^{SPC}*@#{SPC}*ifndef({SPC}|{CONT}) {
nested_if_nb++;
then_body_tmp.append(yytext);
yylloc->step();
}
<THEN_BODY>. { then_body_tmp.append(yytext); yylloc->step(); }
<THEN_BODY><<EOF>> { driver.error(if_stmt_loc_tmp, "@#if/@#ifdef/@#ifndef not matched by an @#endif or file does not end with a new line (unexpected end of file)"); }
<THEN_BODY>^{SPC}*@#{SPC}*else{SPC}*(\/\/.*)?{EOL} {
yylloc->lines(1);
yylloc->step();
if (nested_if_nb)
then_body_tmp.append(yytext);
else
{
else_body_tmp.erase();
else_body_loc_tmp = *yylloc;
BEGIN(ELSE_BODY);
}
}
<THEN_BODY>^{SPC}*@#{SPC}*endif{SPC}*(\/\/.*)?{EOL} {
yylloc->lines(1);
yylloc->step();
if (nested_if_nb)
{
/* This @#endif is not the end of the @#if we're parsing,
but only that of a nested @#if */
nested_if_nb--;
then_body_tmp.append(yytext);
}
else
{
if (driver.last_if)
create_then_context(yylloc);
else
output_line(yylloc);
BEGIN(INITIAL);
}
}
<ELSE_BODY>{EOL} { yylloc->lines(1); yylloc->step(); else_body_tmp.append(yytext); }
<ELSE_BODY>^{SPC}*@#{SPC}*if({SPC}|{CONT}) {
nested_if_nb++;
else_body_tmp.append(yytext);
yylloc->step();
}
<ELSE_BODY>. { else_body_tmp.append(yytext); yylloc->step(); }
<ELSE_BODY><<EOF>> { driver.error(if_stmt_loc_tmp, "@#if/@#ifdef/@#ifndef not matched by an @#endif or file does not end with a new line (unexpected end of file)"); }
<ELSE_BODY>^{SPC}*@#{SPC}*endif{SPC}*(\/\/.*)?{EOL} {
yylloc->lines(1);
yylloc->step();
if (nested_if_nb)
{
/* This @#endif is not the end of the @#if we're parsing,
but only that of a nested @#if */
nested_if_nb--;
else_body_tmp.append(yytext);
}
else
{
if (driver.last_if)
create_then_context(yylloc);
else
create_else_context(yylloc);
BEGIN(INITIAL);
}
}
<INITIAL><<EOF>> {
// Quit lexer if end of main file
if (context_stack.empty())
{
yyterminate();
}
// Else clean current scanning context
yy_delete_buffer(YY_CURRENT_BUFFER);
delete input;
delete yylloc->begin.filename;
/* If we are not in a loop body, or if the loop has terminated,
pop a context */
if (is_for_context && driver.iter_loop())
new_loop_body_buffer(yylloc);
else
restore_context(yylloc);
}
/* We don't use echo, because under Cygwin it will add an extra \r */
<INITIAL>{EOL} { yylloc->lines(1); yylloc->step();
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
yyout << endl;
#else
*yyout << endl;
#endif
}
/* Copy everything else to output */
<INITIAL>. { yylloc->step(); ECHO; }
<*>. { driver.error(*yylloc, "Macro lexer error: '" + string(yytext) + "'"); }
%%
MacroFlex::MacroFlex(istream* in, ostream* out, bool no_line_macro_arg, vector<string> path_arg)
: MacroFlexLexer(in, out), input(in), no_line_macro(no_line_macro_arg), path(path_arg),
reading_for_statement(false), reading_if_statement(false)
{
}
void
MacroFlex::output_line(Macro::parser::location_type *yylloc) const
{
if (!no_line_macro)
#if (YY_FLEX_MAJOR_VERSION > 2) || (YY_FLEX_MAJOR_VERSION == 2 && YY_FLEX_MINOR_VERSION >= 6)
const_cast<ostream&>(yyout)
#else
*yyout
#endif
<< endl << "@#line \"" << *yylloc->begin.filename << "\" "
<< yylloc->begin.line << endl;
}
void
MacroFlex::save_context(Macro::parser::location_type *yylloc)
{
context_stack.push(ScanContext(input, YY_CURRENT_BUFFER, *yylloc, is_for_context,
for_body, for_body_loc));
}
void
MacroFlex::restore_context(Macro::parser::location_type *yylloc)
{
input = context_stack.top().input;
yy_switch_to_buffer(context_stack.top().buffer);
*yylloc = context_stack.top().yylloc;
is_for_context = context_stack.top().is_for_context;
for_body = context_stack.top().for_body;
for_body_loc = context_stack.top().for_body_loc;
// Remove top of stack
context_stack.pop();
// Dump @#line instruction
output_line(yylloc);
}
void
MacroFlex::push_path(string *includepath, Macro::parser::location_type *yylloc,
MacroDriver &driver)
{
using namespace boost;
vector<string> tokenizedPath;
split(tokenizedPath, *includepath, is_any_of(":"), token_compress_on);
for (vector<string>::iterator it = tokenizedPath.begin();
it != tokenizedPath.end(); it++ )
if (!it->empty())
{
trim(*it);
path.push_back(*it);
}
}
void
MacroFlex::create_include_context(string *filename, Macro::parser::location_type *yylloc,
MacroDriver &driver)
{
#ifdef _WIN32
string FILESEP = "\\";
#else
string FILESEP = "/";
#endif
save_context(yylloc);
// Open new file
input = new ifstream(filename->c_str(), ios::binary);
if (input->fail())
{
ostringstream dirs;
dirs << "." << FILESEP << endl;
for (vector<string>::const_iterator it = path.begin(); it != path.end(); it++)
{
string testfile = *it + FILESEP + *filename;
input = new ifstream(testfile.c_str(), ios::binary);
if (input->good())
break;
dirs << *it << endl;
}
if (input->fail())
driver.error(*yylloc, "Could not open " + *filename +
". The following directories were searched:\n" + dirs.str());
}
// Reset location
yylloc->begin.filename = yylloc->end.filename = filename;
yylloc->begin.line = yylloc->end.line = 1;
yylloc->begin.column = yylloc->end.column = 0;
// We are not in a loop body
is_for_context = false;
for_body.clear();
// Output @#line information
output_line(yylloc);
// Switch to new buffer
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
}
void
MacroFlex::create_then_context(Macro::parser::location_type *yylloc)
{
save_context(yylloc);
input = new stringstream(then_body_tmp);
*yylloc = then_body_loc_tmp;
yylloc->begin.filename = yylloc->end.filename = new string(*then_body_loc_tmp.begin.filename);
is_for_context = false;
for_body.clear();
output_line(yylloc);
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
}
void
MacroFlex::create_else_context(Macro::parser::location_type *yylloc)
{
save_context(yylloc);
input = new stringstream(else_body_tmp);
*yylloc = else_body_loc_tmp;
yylloc->begin.filename = yylloc->end.filename = new string(*else_body_loc_tmp.begin.filename);
is_for_context = false;
for_body.clear();
output_line(yylloc);
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
}
void
MacroFlex::new_loop_body_buffer(Macro::parser::location_type *yylloc)
{
input = new stringstream(for_body);
*yylloc = for_body_loc;
yylloc->begin.filename = yylloc->end.filename = new string(*for_body_loc.begin.filename);
output_line(yylloc);
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
}
/* This implementation of MacroFlexLexer::yylex() is required to fill the
* vtable of the class MacroFlexLexer. We define the scanner's main yylex
* function via YY_DECL to reside in the MacroFlex class instead. */
#ifdef yylex
# undef yylex
#endif
int
MacroFlexLexer::yylex()
{
cerr << "MacroFlexLexer::yylex() has been called, that should never happen!" << endl;
exit(EXIT_FAILURE);
}

View File

@ -1,450 +0,0 @@
/*
* Copyright (C) 2008-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MacroDriver.hh"
MacroValue::MacroValue(MacroDriver &driver_arg) : driver(driver_arg)
{
driver.values.insert(this);
}
MacroValue::~MacroValue()
{
}
const MacroValue *
MacroValue::operator+() const throw (TypeError)
{
throw TypeError("Unary operator + does not exist for this type");
}
const MacroValue *
MacroValue::operator-(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator - does not exist for this type");
}
const MacroValue *
MacroValue::operator-() const throw (TypeError)
{
throw TypeError("Unary operator - does not exist for this type");
}
const MacroValue *
MacroValue::operator*(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator * does not exist for this type");
}
const MacroValue *
MacroValue::operator/(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator / does not exist for this type");
}
const MacroValue *
MacroValue::operator<(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator < does not exist for this type");
}
const MacroValue *
MacroValue::operator>(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator > does not exist for this type");
}
const MacroValue *
MacroValue::operator<=(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator <= does not exist for this type");
}
const MacroValue *
MacroValue::operator>=(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator >= does not exist for this type");
}
const MacroValue *
MacroValue::operator&&(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator && does not exist for this type");
}
const MacroValue *
MacroValue::operator||(const MacroValue &mv) const throw (TypeError)
{
throw TypeError("Operator || does not exist for this type");
}
const MacroValue *
MacroValue::operator!() const throw (TypeError)
{
throw TypeError("Operator ! does not exist for this type");
}
const MacroValue *
MacroValue::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
{
throw TypeError("Operator [] does not exist for this type");
}
const MacroValue *
MacroValue::length() const throw (TypeError)
{
throw TypeError("Length not supported for this type");
}
const MacroValue *
MacroValue::append(const MacroValue *mv) const throw (TypeError)
{
throw TypeError("Cannot append an array at the end of another one. Should use concatenation.");
}
const MacroValue *
MacroValue::in(const MacroValue *array) const throw (TypeError)
{
throw TypeError("First argument of 'in' operator cannot be an array");
}
const MacroValue *
MacroValue::new_base_value(MacroDriver &driver, int i)
{
return new IntMV(driver, i);
}
const MacroValue *
MacroValue::new_base_value(MacroDriver &driver, const string &s)
{
return new StringMV(driver, s);
}
IntMV::IntMV(MacroDriver &driver, int value_arg) : MacroValue(driver), value(value_arg)
{
}
IntMV::~IntMV()
{
}
const MacroValue *
IntMV::operator+(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of + operator");
return new IntMV(driver, value + mv2->value);
}
const MacroValue *
IntMV::operator+() const throw (TypeError)
{
return this;
}
const MacroValue *
IntMV::operator-(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of - operator");
return new IntMV(driver, value - mv2->value);
}
const MacroValue *
IntMV::operator-() const throw (TypeError)
{
return new IntMV(driver, -value);
}
const MacroValue *
IntMV::operator*(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of * operator");
return new IntMV(driver, value * mv2->value);
}
const MacroValue *
IntMV::operator/(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of / operator");
return new IntMV(driver, value / mv2->value);
}
const MacroValue *
IntMV::operator<(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of < operator");
return new IntMV(driver, value < mv2->value);
}
const MacroValue *
IntMV::operator>(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of > operator");
return new IntMV(driver, value > mv2->value);
}
const MacroValue *
IntMV::operator<=(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of <= operator");
return new IntMV(driver, value <= mv2->value);
}
const MacroValue *
IntMV::operator>=(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of >= operator");
return new IntMV(driver, value >= mv2->value);
}
const MacroValue *
IntMV::operator==(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
return new IntMV(driver, 0);
else
return new IntMV(driver, value == mv2->value);
}
const MacroValue *
IntMV::operator!=(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
return new IntMV(driver, 1);
else
return new IntMV(driver, value != mv2->value);
}
const MacroValue *
IntMV::operator&&(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of && operator");
return new IntMV(driver, value && mv2->value);
}
const MacroValue *
IntMV::operator||(const MacroValue &mv) const throw (TypeError)
{
const IntMV *mv2 = dynamic_cast<const IntMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of || operator");
return new IntMV(driver, value || mv2->value);
}
const MacroValue *
IntMV::operator!() const throw (TypeError)
{
return new IntMV(driver, !value);
}
string
IntMV::toString() const
{
ostringstream ss;
ss << value;
return ss.str();
}
string
IntMV::print() const
{
return toString();
}
const MacroValue *
IntMV::toArray() const
{
vector<int> v;
v.push_back(value);
return new ArrayMV<int>(driver, v);
}
const MacroValue *
IntMV::append(const MacroValue *array) const throw (TypeError)
{
const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(array);
if (array2 == NULL)
throw TypeError("Type mismatch for append operation");
vector<int> v(array2->values);
v.push_back(value);
return new ArrayMV<int>(driver, v);
}
const MacroValue *
IntMV::in(const MacroValue *array) const throw (TypeError)
{
const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(array);
if (array2 == NULL)
throw TypeError("Type mismatch for 'in' operator");
int result = 0;
for (vector<int>::const_iterator it = array2->values.begin();
it != array2->values.end(); it++)
if (*it == value)
{
result = 1;
break;
}
return new IntMV(driver, result);
}
const MacroValue *
IntMV::new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError)
{
const IntMV *mv1i = dynamic_cast<const IntMV *>(mv1);
const IntMV *mv2i = dynamic_cast<const IntMV *>(mv2);
if (mv1i == NULL || mv2i == NULL)
throw TypeError("Arguments of range operator (:) must be integers");
int v1 = mv1i->value;
int v2 = mv2i->value;
vector<int> result;
for (; v1 <= v2; v1++)
result.push_back(v1);
return new ArrayMV<int>(driver, result);
}
StringMV::StringMV(MacroDriver &driver, const string &value_arg) :
MacroValue(driver), value(value_arg)
{
}
StringMV::~StringMV()
{
}
const MacroValue *
StringMV::operator+(const MacroValue &mv) const throw (TypeError)
{
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of + operator");
return new StringMV(driver, value + mv2->value);
}
const MacroValue *
StringMV::operator==(const MacroValue &mv) const throw (TypeError)
{
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
if (mv2 == NULL)
return new IntMV(driver, 0);
else
return new IntMV(driver, value == mv2->value);
}
const MacroValue *
StringMV::operator!=(const MacroValue &mv) const throw (TypeError)
{
const StringMV *mv2 = dynamic_cast<const StringMV *>(&mv);
if (mv2 == NULL)
return new IntMV(driver, 1);
else
return new IntMV(driver, value != mv2->value);
}
const MacroValue *
StringMV::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
{
const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
if (mv2 == NULL)
throw TypeError("Expression inside [] must be an integer array");
string result;
for (vector<int>::const_iterator it = mv2->values.begin();
it != mv2->values.end(); it++)
{
if (*it < 1 || *it > (int) value.length())
throw OutOfBoundsError();
char c = value.at(*it - 1);
result.append(1, c);
}
return new StringMV(driver, result);
}
string
StringMV::toString() const
{
return value;
}
string
StringMV::print() const
{
return "'" + value + "'";
}
const MacroValue *
StringMV::toArray() const
{
vector<string> v;
v.push_back(value);
return new ArrayMV<string>(driver, v);
}
const MacroValue *
StringMV::append(const MacroValue *array) const throw (TypeError)
{
const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(array);
if (array2 == NULL)
throw TypeError("Type mismatch for append operation");
vector<string> v(array2->values);
v.push_back(value);
return new ArrayMV<string>(driver, v);
}
const MacroValue *
StringMV::in(const MacroValue *array) const throw (TypeError)
{
const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(array);
if (array2 == NULL)
throw TypeError("Type mismatch for 'in' operator");
int result = 0;
for (vector<string>::const_iterator it = array2->values.begin();
it != array2->values.end(); it++)
if (*it == value)
{
result = 1;
break;
}
return new IntMV(driver, result);
}

View File

@ -1,395 +0,0 @@
/*
* Copyright (C) 2008-2017 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,
* 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
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MACRO_VALUE_HH
#define _MACRO_VALUE_HH
#include <string>
#include <vector>
#include <sstream>
#include <boost/lexical_cast.hpp>
using namespace std;
class MacroDriver;
//! Base class for representing values in macro language
class MacroValue
{
protected:
//! Reference to enclosing MacroDriver
MacroDriver &driver;
public:
//! Exception thrown when type error occurs in macro language
class TypeError
{
public:
const string message;
TypeError(const string &message_arg) : message(message_arg)
{
};
};
//! Exception thrown when doing an out-of-bounds access through [] operator
class OutOfBoundsError
{
};
MacroValue(MacroDriver &driver_arg);
virtual
~MacroValue();
//! Applies + operator
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0;
//! Applies unary + operator
virtual const MacroValue *operator+() const throw (TypeError);
//! Applies - operator
virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
//! Applies unary - operator
virtual const MacroValue *operator-() const throw (TypeError);
//! Applies * operator
virtual const MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
//! Applies / operator
virtual const MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
//! Less comparison
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
//! Greater comparision
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
//! Less or equal comparison
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
//! Greater or equal comparison
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
//! Equal comparison
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError) = 0;
//! Not equal comparison
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError) = 0;
//! Applies && operator
virtual const MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
//! Applies || operator
virtual const MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
//! Applies unary ! operator
virtual const MacroValue *operator!() const throw (TypeError);
//! Applies [] operator
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
//! Converts value to string
virtual string toString() const = 0;
//! Converts value to be printed
virtual string print() const = 0;
//! Converts value to array form
virtual const MacroValue *toArray() const = 0;
//! Gets length
virtual const MacroValue *length() const throw (TypeError);
//! Appends value at the end of an array
/*! The argument must be an array. */
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
//! Applies "in" operator
/*! The argument must be an array. Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
//! Returns a new IntMV
/*! Necessary for ArrayMV::operator[] (template issue) */
static const MacroValue *new_base_value(MacroDriver &driver, int i);
//! Returns a new StringMV
/*! Necessary for ArrayMV::operator[] (template issue) */
static const MacroValue *new_base_value(MacroDriver &driver, const string &s);
};
//! Represents an integer value in macro language
class IntMV : public MacroValue
{
friend class StringMV;
friend class MacroDriver;
private:
//! Underlying integer value
const int value;
public:
IntMV(MacroDriver &driver, int value_arg);
virtual
~IntMV();
//! Computes arithmetic addition
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
//! Unary plus
/*! Returns itself */
virtual const MacroValue *operator+() const throw (TypeError);
//! Computes arithmetic substraction
virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
//! Computes opposite
virtual const MacroValue *operator-() const throw (TypeError);
//! Computes arithmetic multiplication
virtual const MacroValue *operator*(const MacroValue &mv) const throw (TypeError);
//! Computes arithmetic division
virtual const MacroValue *operator/(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator<(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator>(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator<=(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator>=(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
//! Computes logical and
virtual const MacroValue *operator&&(const MacroValue &mv) const throw (TypeError);
//! Computes logical or
virtual const MacroValue *operator||(const MacroValue &mv) const throw (TypeError);
//! Computes logical negation
virtual const MacroValue *operator!() const throw (TypeError);
virtual string toString() const;
virtual string print() const;
//! Converts value to array form
/*! Returns an integer array containing a single value */
virtual const MacroValue *toArray() const;
//! Appends value at the end of an array
/*! The first argument must be an integer array. */
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
//! Creates a integer range
/*! Arguments must be of type IntMV.
Returns an integer array containing all integers between mv1 and mv2.
If mv2 < mv1, returns an empty range (for consistency with MATLAB).
*/
static const MacroValue *new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError);
inline int
get_int_value() const
{
return value;
};
};
//! Represents a string value in macro language
class StringMV : public MacroValue
{
friend class MacroDriver;
private:
//! Underlying string value
const string value;
public:
StringMV(MacroDriver &driver, const string &value_arg);
virtual
~StringMV();
//! Computes string concatenation
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
//! Subscripting operator
/*! Argument must be an ArrayMV<int>. Indexes begin at 1. Returns a StringMV. */
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
//! Returns underlying string value
virtual string toString() const;
virtual string print() const;
//! Converts value to array form
/*! Returns a string array containing a single value */
virtual const MacroValue *toArray() const;
//! Appends value at the end of an array
/*! The first argument must be a string array. Returns a string array. */
virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
};
//! Represents an array in macro language
template<typename T>
class ArrayMV : public MacroValue
{
friend class IntMV;
friend class StringMV;
friend class ArrayMV<string>; // Necessary for operator[] to access values of integer array when subscripting a string array
friend class MacroDriver;
private:
//! Underlying vector
const vector<T> values;
public:
ArrayMV(MacroDriver &driver, const vector<T> &values_arg);
virtual
~ArrayMV();
//! Computes array concatenation
/*! Both array must be of same type */
virtual const MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
//! Returns an array in which the elements of the second array have been removed from the first
/*! It is close to a set difference operation, except that if an element appears two times in the first array, it will also be in the returned value (provided it is not in the second array) */
virtual const MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator==(const MacroValue &mv) const throw (TypeError);
virtual const MacroValue *operator!=(const MacroValue &mv) const throw (TypeError);
//! Subscripting operator
/*! Argument must be an ArrayMV<int>. Indexes begin at 1.
If argument is a one-element array, returns an IntMV or StringMV.
Otherwise returns an array. */
virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
//! Returns a string containing the concatenation of string representations of elements
virtual string toString() const;
virtual string print() const;
//! Returns itself
virtual const MacroValue *toArray() const;
//! Gets length
virtual const MacroValue *length() const throw (TypeError);
};
template<typename T>
ArrayMV<T>::ArrayMV(MacroDriver &driver, const vector<T> &values_arg) : MacroValue(driver), values(values_arg)
{
}
template<typename T>
ArrayMV<T>::~ArrayMV()
{
}
template<typename T>
const MacroValue *
ArrayMV<T>::operator+(const MacroValue &mv) const throw (TypeError)
{
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of + operator");
vector<T> values_copy(values);
values_copy.insert(values_copy.end(), mv2->values.begin(), mv2->values.end());
return new ArrayMV<T>(driver, values_copy);
}
template<typename T>
const MacroValue *
ArrayMV<T>::operator-(const MacroValue &mv) const throw (TypeError)
{
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
if (mv2 == NULL)
throw TypeError("Type mismatch for operands of - operator");
/* Highly inefficient algorithm for computing set difference
(but vector<T> is not suited for that...) */
vector<T> new_values;
for (typename vector<T>::const_iterator it = values.begin();
it != values.end(); it++)
{
typename vector<T>::const_iterator it2;
for (it2 = mv2->values.begin(); it2 != mv2->values.end(); it2++)
if (*it == *it2)
break;
if (it2 == mv2->values.end())
new_values.push_back(*it);
}
return new ArrayMV<T>(driver, new_values);
}
template<typename T>
const MacroValue *
ArrayMV<T>::operator==(const MacroValue &mv) const throw (TypeError)
{
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
if (mv2 == NULL)
return new IntMV(driver, 0);
else
return new IntMV(driver, values == mv2->values);
}
template<typename T>
const MacroValue *
ArrayMV<T>::operator!=(const MacroValue &mv) const throw (TypeError)
{
const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
if (mv2 == NULL)
return new IntMV(driver, 1);
else
return new IntMV(driver, values != mv2->values);
}
template<typename T>
const MacroValue *
ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError)
{
const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
if (mv2 == NULL)
throw TypeError("Expression inside [] must be an integer array");
vector<T> result;
for (vector<int>::const_iterator it = mv2->values.begin();
it != mv2->values.end(); it++)
{
if (*it < 1 || *it > (int) values.size())
throw OutOfBoundsError();
result.push_back(values[*it - 1]);
}
if (result.size() > 1 || result.size() == 0)
return new ArrayMV<T>(driver, result);
else
return MacroValue::new_base_value(driver, result[0]);
}
template<typename T>
string
ArrayMV<T>::toString() const
{
ostringstream ss;
for (typename vector<T>::const_iterator it = values.begin();
it != values.end(); it++)
ss << *it;
return ss.str();
}
template<typename T>
string
ArrayMV<T>::print() const
{
bool printStrArr = false;
try
{
typename vector<T>::const_iterator it = values.begin();
boost::lexical_cast<int>(*it);
}
catch (boost::bad_lexical_cast &)
{
printStrArr= true;
}
ostringstream ss;
if (printStrArr)
ss << "{";
else
ss << "[";
for (typename vector<T>::const_iterator it = values.begin();
it != values.end(); it++)
{
if (it != values.begin())
ss << ", ";
if (printStrArr)
ss << "'" << *it << "'";
else
ss << *it;
}
if (printStrArr)
ss << "}";
else
ss << "]";
return ss.str();
}
template<typename T>
const MacroValue *
ArrayMV<T>::toArray() const
{
return this;
}
template<typename T>
const MacroValue *
ArrayMV<T>::length() const throw (TypeError)
{
return new IntMV(driver, values.size());
}
#endif

View File

@ -1,23 +0,0 @@
noinst_LIBRARIES = libmacro.a
BUILT_SOURCES = MacroBison.hh stack.hh position.hh location.hh MacroBison.cc MacroFlex.cc
# We don't put BUILT_SOURCES in libmacro_a_SOURCES, otherwise MacroBison.o and MacroFlex.o will be linked two times (Automake translates MacroFlex.ll and MacroBison.yy into their respective .o); so BUILT_SOURCES is in EXTRA_DIST
libmacro_a_SOURCES = \
MacroFlex.ll \
MacroBison.yy \
MacroDriver.cc \
MacroDriver.hh \
MacroValue.cc \
MacroValue.hh
EXTRA_DIST = $(BUILT_SOURCES)
# The -I.. is for <FlexLexer.h>
libmacro_a_CPPFLAGS = $(BOOST_CPPFLAGS) -I..
MacroFlex.cc: MacroFlex.ll
$(LEX) -o MacroFlex.cc MacroFlex.ll
MacroBison.cc MacroBison.hh location.hh stack.hh position.hh: MacroBison.yy
$(YACC) -o MacroBison.cc MacroBison.yy