Dynare++: finish to apply Dynare C++ coding style and extensions (.cc/.hh)

time-shift
Sébastien Villemot 2019-01-08 17:12:05 +01:00
parent b58e3d9f78
commit 188d6296d7
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
175 changed files with 13907 additions and 12482 deletions

View File

@ -1,37 +1,28 @@
RINTERNALS=/usr/share/R/include/
sylvcppsource := $(wildcard ../../sylv/cc/*.cpp)
sylvhsource := $(wildcard ../../sylv/cc/*.h)
sylvobjects := $(patsubst %.cpp, %.o, $(sylvcppsource))
sylvcppsource := $(wildcard ../../sylv/cc/*.cc)
sylvhsource := $(wildcard ../../sylv/cc/*.hh)
sylvobjects := $(patsubst %.cc, %.o, $(sylvcppsource))
tlcwebsource := $(wildcard ../../tl/cc/*.cweb)
tlcppsource := $(patsubst %.cweb,%.cpp,$(tlcwebsource))
tlhwebsource := $(wildcard ../../tl/cc/*.hweb)
tlhsource := $(patsubst %.hweb,%.h,$(tlhwebsource))
tlobjects := $(patsubst %.cweb,%.o,$(tlcwebsource))
tlcppsource := $(wildcard ../../tl/cc/*.cc)
tlhsource := $(wildcard ../../tl/cc/*.hh)
kordcwebsource := $(wildcard ../../kord/*.cweb)
kordcppsource := $(patsubst %.cweb,%.cpp,$(kordcwebsource))
kordhwebsource := $(wildcard ../../kord/*.hweb)
kordhsource := $(patsubst %.hweb,%.h,$(kordhwebsource))
kordobjects := $(patsubst %.cweb,%.o,$(kordcwebsource))
kordcppsource := $(wildcard ../../kord/*.cc)
kordhsource := $(wildcard ../../kord/*.hh)
integcwebsource := $(wildcard ../../integ/cc/*.cweb)
integcppsource := $(patsubst %.cweb,%.cpp,$(integcwebsource))
integhwebsource := $(wildcard ../../integ/cc/*.hweb)
integhsource := $(patsubst %.hweb,%.h,$(integhwebsource))
integobjects := $(patsubst %.cweb,%.o,$(integcwebsource))
integcppsource := $(wildcard ../../integ/cc/*.cc)
integhsource := $(wildcard ../../integ/cc/*.hh)
parserhsource := $(wildcard ../../parser/cc/*.h)
parsercppsource := $(wildcard ../parser/cc/*.cpp)
parserhsource := $(wildcard ../../parser/cc/*.hh)
parsercppsource := $(wildcard ../parser/cc/*.cc)
utilshsource := $(wildcard ../../utils/cc/*.h)
utilscppsource := $(wildcard ../utils/cc/*.cpp)
utilshsource := $(wildcard ../../utils/cc/*.hh)
utilscppsource := $(wildcard ../utils/cc/*.cc)
srccpp := dynare3.cpp dynare_model.cpp planner_builder.cpp dynare_atoms.cpp dynare_params.cpp nlsolve.cpp
objects := $(patsubst %.cpp,../../src/%.o,$(srccpp)) \
$(patsubst %.y,%_ll.o,$(wildcard ../../src/*.y)) \
$(patsubst %.lex,%_tab.o,$(wildcard ../../src/*.lex))
srccpp := dynare3.cc dynare_model.cc planner_builder.cc dynare_atoms.cc dynare_params.cc nlsolve.cc
objects := $(patsubst %.cc,../../src/%.o,$(srccpp)) \
$(patsubst %.yy,%_ll.o,$(wildcard ../../src/*.yy)) \
$(patsubst %.ll,%_tab.o,$(wildcard ../../src/*.ll))
PKG_CPPFLAGS= -I../../tl/cc -I../../sylv/cc -I../../kord -I../../src -I../.. -I$(RINTERNALS)
PKG_LIBS= ${LAPACK_LIBS} ${BLAS_LIBS} $(objects) $(kordobjects) $(integobjects) $(tlobjects) ../../parser/cc/parser.a ../../utils/cc/utils.a $(sylvobjects) -lpthread -llapack -lcblas -lf77blas -latlas -lg2c -lstdc++
@ -43,12 +34,12 @@ endif
dynareR.so: dynareR.o
g++ -shared -o dynareR.so dynareR.o -L/usr/lib/R/lib -lR $(PKG_LIBS)
dynareR.o: dynareR.cpp
dynareR.o: dynareR.cc
g++ -I/usr/share/R/include -I/usr/share/R/include $(PKG_CPPFLAGS) \
-fpic -g -O2 -c dynareR.cpp -o dynareR.o -DDEBUG
-fpic -g -O2 -c dynareR.cc -o dynareR.o -DDEBUG
test: test.cpp dynareR.cpp
g++ -O0 -g -o test test.cpp -DDEBUG $(PKG_LIBS) $(PKG_CPPFLAGS)
test: test.cc dynareR.cc
g++ -O0 -g -o test test.cc -DDEBUG $(PKG_LIBS) $(PKG_CPPFLAGS)
test-debug:
valgrind --leak-check=yes ./test

271
dynare++/extern/R/dynareR.cc vendored Normal file
View File

@ -0,0 +1,271 @@
// $Id: dynareR.cpp 862 2006-08-04 17:34:56Z tamas $
// Copyright 2006, Tamas K Papp
#include "dynare3.hh" // Dynare class
#include "approximation.hh" // Approximation class
// exceptions
#include "dynare_exception.hh"
#include "parser/cc/parser_exception.hh"
#include "utils/cc/exception.hh"
#include "SylvException.hh"
#include "tl_exception.hh"
#include "kord_exception.hh"
#include <algorithm>
#include <string.h>
#ifdef DEBUG
# include <stdio.h>
#endif
#include <R_ext/Memory.h>
/** This file containt the C glue functions for an R interface to
* Dynare++. Although written in standard C (except for the use of
* R_alloc), the indexing, calling and memory management conventions
* of the functions in this file were tailored for R.
*
* It is not recommended that you use this interface for anything else
* but R.
*/
/** Error codes: these error codes correspond to possible
* exceptions. */
#define DYNARER_SYLVEXCEPTION 1
#define DYNARER_DYNAREEXCEPTION 2
#define DYNARER_OGUEXCEPTION 3
#define DYNARER_TLEXCEPTION 4
#define DYNARER_KORDEXCEPTION 5
#define DYNARER_NAMESMATCHINGERROR 6
/** Copies the message into a buffer. The buffer is allocated and
* managed by R, ie it will be garbage collected after the .C call
* returns and the contents are duplicated.
*/
char *
passmessage(const char *errormessage)
{
long l = strlen(errormessage);
char *em = R_alloc(l, 1);
return strcpy(em, errormessage);
}
/** This function puts the mapping between the newtotal items after
* nl[offset] and the items in orig into the buffer perm, which has to
* be at least as long as newtotal. The function uses R indexing,
* that is to say, the first index is 1.
*/
int
matchnames(const char **orig, int origtotal,
const NameList &nl, int offset, int newtotal,
int *perm)
{
#ifdef DEBUG
printf("matching names (R indexing):\n");
#endif
for (int i = 0; i < newtotal; i++)
{
int j;
for (j = 0; j < origtotal; j++)
if (strcmp(nl.getName(offset+i), *(orig+j)) == 0)
{
*(perm+i) = j+1;
#ifdef DEBUG
printf("%d -> %d\n", i+1, j+1);
#endif
break;
}
if (j == origtotal)
return 1;
}
return 0;
}
/** dynareR is the interface function. The user provides:
* - a list of endogenous and exogenous variables, a list of
* parameters (and the length of each list)
* - the model equations (modeleq, pointer to a 0-terminated string)
* - the order of expansion (ord)
* - journal file name (jnlfile, can be "/dev/null" for no journal)
* - values for the parametes (parval)
* - variance-covariance matrix (vcov, stacked by columns, R does
* this)
* - initial values for finding the steady state (initval)
* - and the number of steps for the approximation algorithm
* (numsteps)
*
* If successful, the interface will write the results to these
* buffers:
* - tensorbuffer for the steady state and the flattened tensors
* - num_state for the number of endogenous variables that ended up in
* the state
* - mappings to variable names (ordering_state, ordering_endo,
* ordering_exo), indices start from 1
* - the deterministic steady state (newinitval)
*
* If dynare throws an exception, the interface tries to catch it and
* return an error code (error), and error message (errormessage), and
* if applicable, information on the stability of the model
* (kordcode). errormessage is allocated into R's memory, and will be
* collected after duplication.
*/
extern "C" {
void
dynareR(const char **endo, const int *num_endo,
const char **exo, const int *num_exo,
const char **par, const int *num_par,
const char **equations, const int *ord, const char *jnlfile,
const double *parval, const double *vcov,
const double *initval,
const int *num_steps,
double *tensorbuffer,
int *num_state, int *ordering_state,
int *ordering_endo, int *ordering_exo,
double *newinitval,
int *error, char **errormessage, int *kordcode)
{
// construct the model here
try
{
#ifdef DEBUG // will print only first var names etc.
printf("eq: %s\nendo: %d %s\nexo: %d %s\npar: %d %s\nord: %d\n",
*equations, *num_endo, *endo, *num_exo, *exo, *num_par, *par, *ord);
#endif
// create journal
Journal journal(jnlfile);
// create Dynare object
Dynare dynare(endo, *num_endo, exo, *num_exo,
par, *num_par, *equations, strlen(*equations),
*ord, journal);
// set Vcov and parameter values
copy(parval, parval+(*num_par), dynare.getParams().base());
#ifdef DEBUG
printf("parameter values (%d):\n", dynare.getParams().length());
dynare.getParams().print();
#endif
copy(vcov, vcov+(*num_exo)*(*num_exo), dynare.getVcov().base());
#ifdef DEBUG
printf("vcov matrix:\n");
dynare.getVcov().print();
#endif
// set initial values
Vector iv(initval, *num_endo);
#ifdef DEBUG
printf("initial values:\n");
iv.print();
#endif
dynare.setInitOuter(iv);
// construct approximation
tls.init(dynare.order(),
dynare.nstat()+2*dynare.npred()+3*dynare.nboth()
+2*dynare.nforw()+dynare.nexog());
Approximation approximation(dynare, journal, *num_steps);
approximation.walkStochSteady();
// write the steady state into the buffer
int ny = dynare.ny();
const Vector ss(dynare.getSteady());
// ss = ConstVector(approximation.getSS(), 0); // FIXME allow
// // for nonzero
int s = dynare.getStateNames().getNum();
int sm = s;
tensorbuffer = copy(ss.base(), ss.base()+ny, tensorbuffer);
// write the tensors into buffer
const UnfoldDecisionRule &udr
= approximation.getUnfoldDecisionRule();
for (int i = 1; i <= *ord; i++)
{
const UFSTensor *t = udr.get(Symmetry(i));
#ifdef DEBUG
printf("tensor %d:\n", i);
t->print();
#endif
tensorbuffer = copy(t->base(), t->base()+ny*sm, tensorbuffer);
sm *= s;
}
// save number of endogenous states
*num_state = s-(*num_exo);
// ordering
#ifdef DEBUG
printf("all endo names:\n");
dynare.getAllEndoNames().print();
printf("all state names:\n");
dynare.getStateNames().print();
#endif
if (matchnames(endo, *num_endo, dynare.getAllEndoNames(),
0, *num_endo, ordering_endo)
|| matchnames(endo, *num_endo, dynare.getStateNames(),
0, *num_state, ordering_state)
|| matchnames(exo, *num_exo, dynare.getStateNames(),
*num_state, *num_exo, ordering_exo))
{
*error = DYNARER_NAMESMATCHINGERROR;
*errormessage = "There was a problem when matching names. This is weird and should not happen.";
return;
}
// return new init values (first column of SS matrix)
ConstVector newinit((const GeneralMatrix &)approximation.getSS(), 0);
#ifdef DEBUG
printf("new initial values:\n");
newinit.print();
#endif
copy(newinit.base(), newinit.base()+(*num_endo), newinitval);
}
catch (const SylvException &e)
{
*error = DYNARER_SYLVEXCEPTION;
char errorbuffer[501];
e.printMessage(errorbuffer, 500);
*errormessage = passmessage(errorbuffer);
#ifdef DEBUG
printf("Caught Sylv exception: ");
e.printMessage();
#endif
return;
}
catch (const DynareException &e)
{
*error = DYNARER_DYNAREEXCEPTION;
*errormessage = passmessage(e.message());
#ifdef DEBUG
printf("Caught Dynare exception: %s\n", e.message());
#endif
return;
}
catch (const ogu::Exception &e)
{
*error = DYNARER_OGUEXCEPTION;
*errormessage = passmessage(e.message());
#ifdef DEBUG
printf("Caught ogu::Exception: ");
e.print();
#endif
return;
}
catch (const TLException &e)
{
*error = DYNARER_TLEXCEPTION;
*errormessage = passmessage(e.getmessage());
#ifdef DEBUG
printf("Caugth TL exception: ");
e.print();
#endif
return;
}
catch (const KordException &e)
{
*error = DYNARER_KORDEXCEPTION;
*errormessage = passmessage(e.getmessage());
*kordcode = e.code(); // Kord error code
#ifdef DEBUG
printf("Caugth Kord exception: ");
e.print();
#endif
return;
}
*error = 0;
return;
}
}

View File

@ -1,249 +0,0 @@
// $Id: dynareR.cpp 862 2006-08-04 17:34:56Z tamas $
// Copyright 2006, Tamas K Papp
#include "dynare3.h" // Dynare class
#include "approximation.h" // Approximation class
// exceptions
#include "dynare_exception.h"
#include "parser/cc/parser_exception.h"
#include "utils/cc/exception.h"
#include "SylvException.h"
#include "tl_exception.h"
#include "kord_exception.h"
#include <algorithm>
#include <string.h>
#ifdef DEBUG
#include <stdio.h>
#endif
#include <R_ext/Memory.h>
/** This file containt the C glue functions for an R interface to
* Dynare++. Although written in standard C (except for the use of
* R_alloc), the indexing, calling and memory management conventions
* of the functions in this file were tailored for R.
*
* It is not recommended that you use this interface for anything else
* but R.
*/
/** Error codes: these error codes correspond to possible
* exceptions. */
#define DYNARER_SYLVEXCEPTION 1
#define DYNARER_DYNAREEXCEPTION 2
#define DYNARER_OGUEXCEPTION 3
#define DYNARER_TLEXCEPTION 4
#define DYNARER_KORDEXCEPTION 5
#define DYNARER_NAMESMATCHINGERROR 6
/** Copies the message into a buffer. The buffer is allocated and
* managed by R, ie it will be garbage collected after the .C call
* returns and the contents are duplicated.
*/
char *passmessage(const char *errormessage) {
long l = strlen(errormessage);
char *em = R_alloc(l, 1);
return strcpy(em, errormessage);
}
/** This function puts the mapping between the newtotal items after
* nl[offset] and the items in orig into the buffer perm, which has to
* be at least as long as newtotal. The function uses R indexing,
* that is to say, the first index is 1.
*/
int matchnames(const char **orig, int origtotal,
const NameList &nl, int offset, int newtotal,
int *perm) {
#ifdef DEBUG
printf("matching names (R indexing):\n");
#endif
for (int i=0; i < newtotal; i++) {
int j;
for (j=0; j < origtotal; j++)
if (strcmp(nl.getName(offset+i), *(orig+j))==0) {
*(perm+i) = j+1;
#ifdef DEBUG
printf("%d -> %d\n",i+1,j+1);
#endif
break;
}
if (j==origtotal)
return 1;
}
return 0;
}
/** dynareR is the interface function. The user provides:
* - a list of endogenous and exogenous variables, a list of
* parameters (and the length of each list)
* - the model equations (modeleq, pointer to a 0-terminated string)
* - the order of expansion (ord)
* - journal file name (jnlfile, can be "/dev/null" for no journal)
* - values for the parametes (parval)
* - variance-covariance matrix (vcov, stacked by columns, R does
* this)
* - initial values for finding the steady state (initval)
* - and the number of steps for the approximation algorithm
* (numsteps)
*
* If successful, the interface will write the results to these
* buffers:
* - tensorbuffer for the steady state and the flattened tensors
* - num_state for the number of endogenous variables that ended up in
* the state
* - mappings to variable names (ordering_state, ordering_endo,
* ordering_exo), indices start from 1
* - the deterministic steady state (newinitval)
*
* If dynare throws an exception, the interface tries to catch it and
* return an error code (error), and error message (errormessage), and
* if applicable, information on the stability of the model
* (kordcode). errormessage is allocated into R's memory, and will be
* collected after duplication.
*/
extern "C" {
void dynareR(const char** endo, const int* num_endo,
const char** exo, const int* num_exo,
const char** par, const int* num_par,
const char** equations, const int* ord, const char* jnlfile,
const double *parval, const double *vcov,
const double *initval,
const int *num_steps,
double* tensorbuffer,
int *num_state, int *ordering_state,
int *ordering_endo, int *ordering_exo,
double *newinitval,
int* error, char **errormessage, int *kordcode) {
// construct the model here
try {
#ifdef DEBUG // will print only first var names etc.
printf("eq: %s\nendo: %d %s\nexo: %d %s\npar: %d %s\nord: %d\n",
*equations,*num_endo,*endo,*num_exo,*exo,*num_par,*par,*ord);
#endif
// create journal
Journal journal(jnlfile);
// create Dynare object
Dynare dynare(endo, *num_endo, exo, *num_exo,
par, *num_par, *equations, strlen(*equations),
*ord, journal);
// set Vcov and parameter values
copy(parval,parval+(*num_par),dynare.getParams().base());
#ifdef DEBUG
printf("parameter values (%d):\n",dynare.getParams().length());
dynare.getParams().print();
#endif
copy(vcov,vcov+(*num_exo)*(*num_exo),dynare.getVcov().base());
#ifdef DEBUG
printf("vcov matrix:\n");
dynare.getVcov().print();
#endif
// set initial values
Vector iv(initval,*num_endo);
#ifdef DEBUG
printf("initial values:\n");
iv.print();
#endif
dynare.setInitOuter(iv);
// construct approximation
tls.init(dynare.order(),
dynare.nstat()+2*dynare.npred()+3*dynare.nboth()+
2*dynare.nforw()+dynare.nexog());
Approximation approximation(dynare,journal,*num_steps);
approximation.walkStochSteady();
// write the steady state into the buffer
int ny = dynare.ny();
const Vector ss(dynare.getSteady());
// ss = ConstVector(approximation.getSS(), 0); // FIXME allow
// // for nonzero
int s = dynare.getStateNames().getNum();
int sm = s;
tensorbuffer = copy(ss.base(),ss.base()+ny,tensorbuffer);
// write the tensors into buffer
const UnfoldDecisionRule& udr =
approximation.getUnfoldDecisionRule();
for (int i=1; i <= *ord; i++) {
const UFSTensor* t = udr.get(Symmetry(i));
#ifdef DEBUG
printf("tensor %d:\n", i);
t->print();
#endif
tensorbuffer = copy(t->base(), t->base()+ny*sm, tensorbuffer);
sm *= s;
}
// save number of endogenous states
*num_state = s-(*num_exo);
// ordering
#ifdef DEBUG
printf("all endo names:\n");
dynare.getAllEndoNames().print();
printf("all state names:\n");
dynare.getStateNames().print();
#endif
if (matchnames(endo, *num_endo, dynare.getAllEndoNames(),
0, *num_endo, ordering_endo) ||
matchnames(endo, *num_endo, dynare.getStateNames(),
0, *num_state, ordering_state) ||
matchnames(exo, *num_exo, dynare.getStateNames(),
*num_state, *num_exo, ordering_exo)) {
*error = DYNARER_NAMESMATCHINGERROR;
*errormessage = "There was a problem when matching names. This is weird and should not happen.";
return;
}
// return new init values (first column of SS matrix)
ConstVector newinit((const GeneralMatrix&) approximation.getSS(), 0);
#ifdef DEBUG
printf("new initial values:\n");
newinit.print();
#endif
copy(newinit.base(),newinit.base()+(*num_endo),newinitval);
} catch (const SylvException &e) {
*error = DYNARER_SYLVEXCEPTION;
char errorbuffer[501];
e.printMessage(errorbuffer, 500);
*errormessage = passmessage(errorbuffer);
#ifdef DEBUG
printf("Caught Sylv exception: ");
e.printMessage();
#endif
return;
} catch (const DynareException &e) {
*error = DYNARER_DYNAREEXCEPTION;
*errormessage = passmessage(e.message());
#ifdef DEBUG
printf("Caught Dynare exception: %s\n", e.message());
#endif
return;
} catch (const ogu::Exception &e) {
*error = DYNARER_OGUEXCEPTION;
*errormessage = passmessage(e.message());
#ifdef DEBUG
printf("Caught ogu::Exception: ");
e.print();
#endif
return;
} catch (const TLException &e) {
*error = DYNARER_TLEXCEPTION;
*errormessage = passmessage(e.getmessage());
#ifdef DEBUG
printf("Caugth TL exception: ");
e.print();
#endif
return;
} catch (const KordException &e) {
*error = DYNARER_KORDEXCEPTION;
*errormessage = passmessage(e.getmessage());
*kordcode = e.code(); // Kord error code
#ifdef DEBUG
printf("Caugth Kord exception: ");
e.print();
#endif
return;
}
*error = 0;
return;}
}

34
dynare++/extern/R/test.cc vendored Normal file
View File

@ -0,0 +1,34 @@
#include "dynareR.cc"
int
main(void)
{
const char *parameters[] = {"beta", "gamma", "rho", "alpha", "delta"};
const char *varendo[] = {"k", "c", "a"};
const char *varexo[] = {"eps"};
const int numpar = 5;
const int numendo = 3;
const int numexo = 1;
const int ord = 2;
const int numsteps = 0;
const double parval[] = {.99, 2, .9, .3, .025};
const double vcov[] = {0.001};
const double initval[] = {0.066, 0.43, 0.01};
int e;
double tensorbuffer[100];
int num_state;
int ordering_state[] = {0, 0, 0};
int ordering_endo[] = {0, 0, 0};
int ordering_exo[] = {0};
double newinitval[] = {0, 0, 0};
const char *modeleq[] = {"(c/c(1))^gamma*beta*(alpha*exp(a(1))*k^(alpha-1)+1-delta)=1; a=rho*a(-1)+eps; k+c=exp(a)*k(-1)^alpha+(1-delta)*k(-1);"};
dynareR(varendo, &numendo, varexo, &numexo, parameters, &numpar, modeleq,
&ord, "journal", parval, vcov, initval,
&numsteps, tensorbuffer,
&num_state, ordering_state, ordering_endo, ordering_exo,
newinitval, &e);
printf("error code: %d\n", e);
}

View File

@ -1,32 +0,0 @@
#include "dynareR.cpp"
int main(void) {
const char *parameters[] = {"beta","gamma","rho","alpha","delta"};
const char *varendo[] = {"k","c","a"};
const char *varexo[] = {"eps"};
const int numpar = 5;
const int numendo = 3;
const int numexo = 1;
const int ord = 2;
const int numsteps = 0;
const double parval[] = {.99,2,.9,.3,.025};
const double vcov[] = {0.001};
const double initval[] = {0.066, 0.43, 0.01};
int e;
double tensorbuffer[100];
int num_state;
int ordering_state[] = {0,0,0};
int ordering_endo[] = {0,0,0};
int ordering_exo[] = {0};
double newinitval[] = {0,0,0};
const char *modeleq[] = {"(c/c(1))^gamma*beta*(alpha*exp(a(1))*k^(alpha-1)+1-delta)=1; a=rho*a(-1)+eps; k+c=exp(a)*k(-1)^alpha+(1-delta)*k(-1);"};
dynareR(varendo, &numendo, varexo, &numexo, parameters, &numpar, modeleq,
&ord, "journal", parval, vcov, initval,
&numsteps, tensorbuffer,
&num_state, ordering_state, ordering_endo, ordering_exo,
newinitval,&e);
printf("error code: %d\n", e);
}

140
dynare++/extern/matlab/dynare_simul.cc vendored Normal file
View File

@ -0,0 +1,140 @@
// Copyright (C) 2005-2011, Ondra Kamenik
// This is the mexFunction providing interface to
// DecisionRule<>::simulate(). It takes the following input
// parameters:
// order the order of approximation, needs order+1 derivatives
// nstat
// npred
// nboth
// nforw
// nexog
// ystart starting value (full vector of endogenous)
// shocks matrix of shocks (nexog x number of period)
// vcov covariance matrix of shocks (nexog x nexog)
// seed integer seed
// ysteady full vector of decision rule's steady
// ... order+1 matrices of derivatives
// output:
// res simulated results
#include "dynmex.h"
#include "mex.h"
#include "decision_rule.hh"
#include "fs_tensor.hh"
#include "SylvException.hh"
extern "C" {
void
mexFunction(int nlhs, mxArray *plhs[],
int nhrs, const mxArray *prhs[])
{
if (nhrs < 12 || nlhs != 2)
DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have at least 12 input parameters and exactly 2 output arguments.\n");
int order = (int) mxGetScalar(prhs[0]);
if (nhrs != 12 + order)
DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have exactly 11+order input parameters.\n");
int nstat = (int) mxGetScalar(prhs[1]);
int npred = (int) mxGetScalar(prhs[2]);
int nboth = (int) mxGetScalar(prhs[3]);
int nforw = (int) mxGetScalar(prhs[4]);
int nexog = (int) mxGetScalar(prhs[5]);
const mxArray *const ystart = prhs[6];
const mxArray *const shocks = prhs[7];
const mxArray *const vcov = prhs[8];
int seed = (int) mxGetScalar(prhs[9]);
const mxArray *const ysteady = prhs[10];
const mwSize *const ystart_dim = mxGetDimensions(ystart);
const mwSize *const shocks_dim = mxGetDimensions(shocks);
const mwSize *const vcov_dim = mxGetDimensions(vcov);
const mwSize *const ysteady_dim = mxGetDimensions(ysteady);
int ny = nstat + npred + nboth + nforw;
if (ny != (int) ystart_dim[0])
DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of rows.\n");
if (1 != ystart_dim[1])
DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of cols.\n");
int nper = shocks_dim[1];
if (nexog != (int) shocks_dim[0])
DYN_MEX_FUNC_ERR_MSG_TXT("shocks has a wrong number of rows.\n");
if (nexog != (int) vcov_dim[0])
DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of rows.\n");
if (nexog != (int) vcov_dim[1])
DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of cols.\n");
if (ny != (int) ysteady_dim[0])
DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of rows.\n");
if (1 != ysteady_dim[1])
DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of cols.\n");
mxArray *res = mxCreateDoubleMatrix(ny, nper, mxREAL);
try
{
// initialize tensor library
tls.init(order, npred+nboth+nexog);
// form the polynomial
UTensorPolynomial pol(ny, npred+nboth+nexog);
for (int dim = 0; dim <= order; dim++)
{
const mxArray *gk = prhs[11+dim];
const mwSize *const gk_dim = mxGetDimensions(gk);
FFSTensor ft(ny, npred+nboth+nexog, dim);
if (ft.ncols() != (int) gk_dim[1])
{
char buf[1000];
sprintf(buf, "Wrong number of columns for folded tensor: got %d but I want %d\n",
(int) gk_dim[1], ft.ncols());
DYN_MEX_FUNC_ERR_MSG_TXT(buf);
}
if (ft.nrows() != (int) gk_dim[0])
{
char buf[1000];
sprintf(buf, "Wrong number of rows for folded tensor: got %d but I want %d\n",
(int) gk_dim[0], ft.nrows());
DYN_MEX_FUNC_ERR_MSG_TXT(buf);
}
ft.zeros();
ConstTwoDMatrix gk_mat(ft.nrows(), ft.ncols(), mxGetPr(gk));
ft.add(1.0, gk_mat);
UFSTensor *ut = new UFSTensor(ft);
pol.insert(ut);
}
// form the decision rule
UnfoldDecisionRule
dr(pol, PartitionY(nstat, npred, nboth, nforw),
nexog, ConstVector(mxGetPr(ysteady), ny));
// form the shock realization
TwoDMatrix shocks_mat(nexog, nper, (const double *)mxGetPr(shocks));
TwoDMatrix vcov_mat(nexog, nexog, (const double *)mxGetPr(vcov));
GenShockRealization sr(vcov_mat, shocks_mat, seed);
// simulate and copy the results
Vector ystart_vec((const double *)mxGetPr(ystart), ny);
TwoDMatrix *res_mat
= dr.simulate(DecisionRule::horner, nper,
ystart_vec, sr);
TwoDMatrix res_tmp_mat(ny, nper, mxGetPr(res));
res_tmp_mat = (const TwoDMatrix &) (*res_mat);
delete res_mat;
plhs[1] = res;
}
catch (const KordException &e)
{
DYN_MEX_FUNC_ERR_MSG_TXT("Caugth Kord exception.");
}
catch (const TLException &e)
{
DYN_MEX_FUNC_ERR_MSG_TXT("Caugth TL exception.");
}
catch (SylvException &e)
{
DYN_MEX_FUNC_ERR_MSG_TXT("Caught Sylv exception.");
}
plhs[0] = mxCreateDoubleScalar(0);
}
};

View File

@ -1,129 +0,0 @@
// Copyright (C) 2005-2011, Ondra Kamenik
// This is the mexFunction providing interface to
// DecisionRule<>::simulate(). It takes the following input
// parameters:
// order the order of approximation, needs order+1 derivatives
// nstat
// npred
// nboth
// nforw
// nexog
// ystart starting value (full vector of endogenous)
// shocks matrix of shocks (nexog x number of period)
// vcov covariance matrix of shocks (nexog x nexog)
// seed integer seed
// ysteady full vector of decision rule's steady
// ... order+1 matrices of derivatives
// output:
// res simulated results
#include "dynmex.h"
#include "mex.h"
#include "decision_rule.hh"
#include "fs_tensor.hh"
#include "SylvException.h"
extern "C" {
void mexFunction(int nlhs, mxArray* plhs[],
int nhrs, const mxArray* prhs[])
{
if (nhrs < 12 || nlhs != 2)
DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have at least 12 input parameters and exactly 2 output arguments.\n");
int order = (int)mxGetScalar(prhs[0]);
if (nhrs != 12 + order)
DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have exactly 11+order input parameters.\n");
int nstat = (int)mxGetScalar(prhs[1]);
int npred = (int)mxGetScalar(prhs[2]);
int nboth = (int)mxGetScalar(prhs[3]);
int nforw = (int)mxGetScalar(prhs[4]);
int nexog = (int)mxGetScalar(prhs[5]);
const mxArray* const ystart = prhs[6];
const mxArray* const shocks = prhs[7];
const mxArray* const vcov = prhs[8];
int seed = (int)mxGetScalar(prhs[9]);
const mxArray* const ysteady = prhs[10];
const mwSize* const ystart_dim = mxGetDimensions(ystart);
const mwSize* const shocks_dim = mxGetDimensions(shocks);
const mwSize* const vcov_dim = mxGetDimensions(vcov);
const mwSize* const ysteady_dim = mxGetDimensions(ysteady);
int ny = nstat + npred + nboth + nforw;
if (ny != (int) ystart_dim[0])
DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of rows.\n");
if (1 != ystart_dim[1])
DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of cols.\n");
int nper = shocks_dim[1];
if (nexog != (int) shocks_dim[0])
DYN_MEX_FUNC_ERR_MSG_TXT("shocks has a wrong number of rows.\n");
if (nexog != (int) vcov_dim[0])
DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of rows.\n");
if (nexog != (int) vcov_dim[1])
DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of cols.\n");
if (ny != (int) ysteady_dim[0])
DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of rows.\n");
if (1 != ysteady_dim[1])
DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of cols.\n");
mxArray* res = mxCreateDoubleMatrix(ny, nper, mxREAL);
try {
// initialize tensor library
tls.init(order, npred+nboth+nexog);
// form the polynomial
UTensorPolynomial pol(ny, npred+nboth+nexog);
for (int dim = 0; dim <= order; dim++) {
const mxArray* gk = prhs[11+dim];
const mwSize* const gk_dim = mxGetDimensions(gk);
FFSTensor ft(ny, npred+nboth+nexog, dim);
if (ft.ncols() != (int) gk_dim[1]) {
char buf[1000];
sprintf(buf, "Wrong number of columns for folded tensor: got %d but I want %d\n",
(int) gk_dim[1], ft.ncols());
DYN_MEX_FUNC_ERR_MSG_TXT(buf);
}
if (ft.nrows() != (int) gk_dim[0]) {
char buf[1000];
sprintf(buf, "Wrong number of rows for folded tensor: got %d but I want %d\n",
(int) gk_dim[0], ft.nrows());
DYN_MEX_FUNC_ERR_MSG_TXT(buf);
}
ft.zeros();
ConstTwoDMatrix gk_mat(ft.nrows(), ft.ncols(), mxGetPr(gk));
ft.add(1.0, gk_mat);
UFSTensor* ut = new UFSTensor(ft);
pol.insert(ut);
}
// form the decision rule
UnfoldDecisionRule
dr(pol, PartitionY(nstat, npred, nboth, nforw),
nexog, ConstVector(mxGetPr(ysteady), ny));
// form the shock realization
TwoDMatrix shocks_mat(nexog, nper, (const double*)mxGetPr(shocks));
TwoDMatrix vcov_mat(nexog, nexog, (const double*)mxGetPr(vcov));
GenShockRealization sr(vcov_mat, shocks_mat, seed);
// simulate and copy the results
Vector ystart_vec((const double*)mxGetPr(ystart), ny);
TwoDMatrix* res_mat =
dr.simulate(DecisionRule::horner, nper,
ystart_vec, sr);
TwoDMatrix res_tmp_mat(ny, nper, mxGetPr(res));
res_tmp_mat = (const TwoDMatrix&)(*res_mat);
delete res_mat;
plhs[1] = res;
} catch (const KordException& e) {
DYN_MEX_FUNC_ERR_MSG_TXT("Caugth Kord exception.");
} catch (const TLException& e) {
DYN_MEX_FUNC_ERR_MSG_TXT("Caugth TL exception.");
} catch (SylvException& e) {
DYN_MEX_FUNC_ERR_MSG_TXT("Caught Sylv exception.");
}
plhs[0] = mxCreateDoubleScalar(0);
}
};

View File

@ -28,7 +28,7 @@
#include "int_sequence.hh"
#include "quadrature.hh"
#include "Vector.h"
#include "Vector.hh"
#include <vector>

View File

@ -16,8 +16,8 @@
#ifndef VECTOR_FUNCTION_H
#define VECTOR_FUNCTION_H
#include "Vector.h"
#include "GeneralMatrix.h"
#include "Vector.hh"
#include "GeneralMatrix.hh"
#include <vector>

View File

@ -1,12 +1,12 @@
// Copyright (C) 2008-2011, Ondra Kamenik
#include "parser/cc/matrix_parser.h"
#include "utils/cc/memory_file.h"
#include "utils/cc/exception.h"
#include "sylv/cc/GeneralMatrix.h"
#include "sylv/cc/Vector.h"
#include "sylv/cc/SymSchurDecomp.h"
#include "sylv/cc/SylvException.h"
#include "parser/cc/matrix_parser.hh"
#include "utils/cc/memory_file.hh"
#include "utils/cc/exception.hh"
#include "sylv/cc/GeneralMatrix.hh"
#include "sylv/cc/Vector.hh"
#include "sylv/cc/SymSchurDecomp.hh"
#include "sylv/cc/SylvException.hh"
#include "integ/cc/quadrature.hh"
#include "integ/cc/smolyak.hh"
#include "integ/cc/product.hh"

View File

@ -1,18 +1,18 @@
/* $Id: tests.cpp 431 2005-08-16 15:41:01Z kamenik $ */
/* Copyright 2005, Ondra Kamenik */
#include "GeneralMatrix.h"
#include "GeneralMatrix.hh"
#include <dynlapack.h>
#include "SylvException.h"
#include "SylvException.hh"
#include "rfs_tensor.h"
#include "normal_moments.h"
#include "rfs_tensor.hh"
#include "normal_moments.hh"
#include "vector_function.h"
#include "quadrature.h"
#include "smolyak.h"
#include "product.h"
#include "quasi_mcarlo.h"
#include "vector_function.hh"
#include "quadrature.hh"
#include "smolyak.hh"
#include "product.hh"
#include "quasi_mcarlo.hh"
#include <cstdio>
#include <cstring>

View File

@ -4,7 +4,7 @@
#include "decision_rule.hh"
#include "dynamic_model.hh"
#include "SymSchurDecomp.h"
#include "SymSchurDecomp.hh"
#include <dynlapack.h>

View File

@ -13,7 +13,7 @@
#include "t_container.hh"
#include "sparse_tensor.hh"
#include "Vector.h"
#include "Vector.hh"
/* The class is a virtual pure class which provides an access to names
of the variables. */

View File

@ -1,6 +1,6 @@
// Copyright 2005, Ondra Kamenik
#include "SymSchurDecomp.h"
#include "SymSchurDecomp.hh"
#include "global_check.hh"

View File

@ -36,7 +36,7 @@
#include "journal.hh"
#include "kord_exception.hh"
#include "GeneralSylvester.h"
#include "GeneralSylvester.hh"
#include <dynlapack.h>

View File

@ -3,7 +3,7 @@
#include <cstdlib>
#include "korder.hh"
#include "SylvException.h"
#include "SylvException.hh"
struct Rand
{

View File

@ -3,40 +3,40 @@ noinst_LIBRARIES = libparser.a
GENERATED_FILES = assign_tab.cc csv_tab.cc formula_tab.cc matrix_tab.cc namelist_tab.cc assign_tab.hh csv_tab.hh formula_tab.hh matrix_tab.hh namelist_tab.hh assign_ll.cc csv_ll.cc formula_ll.cc matrix_ll.cc namelist_ll.cc
libparser_a_SOURCES = \
location.h \
namelist.h \
atom_assignings.cpp \
atom_assignings.h \
atom_substitutions.cpp \
atom_substitutions.h \
csv_parser.cpp \
csv_parser.h \
dynamic_atoms.cpp \
dynamic_atoms.h \
fine_atoms.cpp \
fine_atoms.h \
formula_parser.cpp \
formula_parser.h \
matrix_parser.cpp \
matrix_parser.h \
parser_exception.cpp \
parser_exception.h \
static_atoms.cpp \
static_atoms.h \
static_fine_atoms.cpp \
static_fine_atoms.h \
tree.cpp \
tree.h \
location.hh \
namelist.hh \
atom_assignings.cc \
atom_assignings.hh \
atom_substitutions.cc \
atom_substitutions.hh \
csv_parser.cc \
csv_parser.hh \
dynamic_atoms.cc \
dynamic_atoms.hh \
fine_atoms.cc \
fine_atoms.hh \
formula_parser.cc \
formula_parser.hh \
matrix_parser.cc \
matrix_parser.hh \
parser_exception.cc \
parser_exception.hh \
static_atoms.cc \
static_atoms.hh \
static_fine_atoms.cc \
static_fine_atoms.hh \
tree.cc \
tree.hh \
$(GENERATED_FILES)
libparser_a_CPPFLAGS = -I../.. $(BOOST_CPPFLAGS)
BUILT_SOURCES = $(GENERATED_FILES)
EXTRA_DIST = assign.y csv.y formula.y matrix.y namelist.y assign.lex csv.lex formula.lex matrix.lex namelist.lex
EXTRA_DIST = assign.yy csv.yy formula.yy matrix.yy namelist.yy assign.ll csv.ll formula.ll matrix.ll namelist.ll
%_tab.cc %_tab.hh: %.y
%_tab.cc %_tab.hh: %.yy
$(YACC) -d -o$*_tab.cc $<
%_ll.cc: %.lex
%_ll.cc: %.ll
$(LEX) -i -o$@ $<

View File

@ -1,5 +1,5 @@
%{
#include "location.h"
#include "location.hh"
#include "assign_tab.hh"
extern YYLTYPE asgn_lloc;

View File

@ -1,8 +1,8 @@
%{
/* Copyright (C) 2006-2011, Ondra Kamenik */
#include "location.h"
#include "atom_assignings.h"
#include "location.hh"
#include "atom_assignings.hh"
#include "assign_tab.hh"
#include <stdio.h>

View File

@ -0,0 +1,252 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: atom_assignings.cpp 92 2007-04-19 11:38:21Z ondra $
#include "atom_assignings.hh"
#include "location.hh"
#include "parser_exception.hh"
#include "utils/cc/exception.hh"
#include <limits>
#include <iostream>
using namespace ogp;
AtomAssignings::AtomAssignings(const AtomAssignings &aa, ogp::StaticAtoms &a)
: atoms(a), expr(aa.expr, atoms), left_names(aa.left_names),
order(aa.order)
{
// fill the lname2expr
for (Tvarintmap::const_iterator it = aa.lname2expr.begin();
it != aa.lname2expr.end(); ++it)
lname2expr.insert(Tvarintmap::value_type(left_names.query((*it).first), (*it).second));
}
/** A global symbol for passing info to the AtomAssignings from
* asgn_parse(). */
AtomAssignings *aparser;
/** The declaration of functions defined in asgn_ll.cc and asgn_tab.cc
* generated from assign.lex assign.y */
void *asgn__scan_buffer(char *, size_t);
void asgn__destroy_buffer(void *);
void asgn_parse();
extern location_type asgn_lloc;
void
AtomAssignings::parse(int length, const char *stream)
{
char *buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
asgn_lloc.off = 0;
asgn_lloc.ll = 0;
void *p = asgn__scan_buffer(buffer, (unsigned int) length+2);
aparser = this;
asgn_parse();
delete [] buffer;
asgn__destroy_buffer(p);
}
void
AtomAssignings::error(const char *mes)
{
throw ParserException(mes, asgn_lloc.off);
}
void
AtomAssignings::add_assignment_to_double(const char *name, double val)
{
// if left hand side is a registered atom, insert it to tree
int t;
try
{
if (atoms.check(name))
t = expr.add_nulary(name);
else
t = -1;
}
catch (const ParserException &e)
{
t = -1;
}
// register left hand side in order
order.push_back(t);
// add the double to the tree
char tmp[100];
sprintf(tmp, "%30.25g", val);
try
{
expr.parse(strlen(tmp), tmp);
}
catch (const ParserException &e)
{
// should never happen
throw ParserException(string("Error parsing double ")+tmp+": "+e.message(), 0);
}
// register name of the left hand side and put to lname2expr
const char *ss = left_names.insert(name);
lname2expr.insert(Tvarintmap::value_type(ss, order.size()-1));
}
void
AtomAssignings::add_assignment(int asgn_off, const char *str, int name_len,
int right_off, int right_len)
{
// the order of doing things here is important: since the
// FormulaParser requires that all references from the i-th tree
// refere to trees with index lass than i, so to capture also a
// nulary term for the left hand side, it must be inserted to the
// expression tree before the expression is parsed.
// find the name in the atoms, make copy of name to be able to put
// '\0' at the end
char *buf = new char[name_len+1];
strncpy(buf, str, name_len);
buf[name_len] = '\0';
// if left hand side is a registered atom, insert it to tree
int t;
try
{
t = atoms.check(buf);
if (t == -1)
t = expr.add_nulary(buf);
}
catch (const ParserException &e)
{
atoms.register_name(buf);
t = expr.add_nulary(buf);
}
// register left hand side in order
order.push_back(t);
// parse expression on the right
try
{
expr.parse(right_len, str+right_off);
}
catch (const ParserException &e)
{
throw ParserException(e, asgn_off+right_off);
}
// register name of the left hand side and put to lname2expr
const char *ss = left_names.insert(buf);
if (lname2expr.find(ss) != lname2expr.end())
{
// Prevent the occurrence of #415
std::cerr << "Changing the value of " << ss << " is not supported. Aborting." << std::endl;
exit(EXIT_FAILURE);
}
lname2expr[ss] = order.size()-1;
// delete name
delete [] buf;
}
void
AtomAssignings::apply_subst(const AtomSubstitutions::Toldnamemap &mm)
{
// go through all old variables and see what are their derived new
// variables
for (AtomSubstitutions::Toldnamemap::const_iterator it = mm.begin();
it != mm.end(); ++it)
{
const char *oldname = (*it).first;
const AtomSubstitutions::Tshiftnameset &sset = (*it).second;
if (!sset.empty())
{
int told = atoms.index(oldname);
if (told < 0 && !atoms.get_name_storage().query(oldname))
atoms.register_name(oldname);
if (told == -1)
told = expr.add_nulary(oldname);
// at least one substitution here, so make an expression
expr.add_formula(told);
// say that this expression is not assigned to any atom
order.push_back(-1);
// now go through all new names derived from the old name and
// reference to the newly added formula
for (AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin();
itt != sset.end(); ++itt)
{
const char *newname = (*itt).first;
const char *nn = left_names.insert(newname);
lname2expr.insert(Tvarintmap::value_type(nn, expr.nformulas()-1));
}
}
}
}
void
AtomAssignings::print() const
{
printf("Atom Assignings\nExpressions:\n");
expr.print();
printf("Left names:\n");
for (Tvarintmap::const_iterator it = lname2expr.begin();
it != lname2expr.end(); ++it)
printf("%s ==> %d (t=%d)\n", (*it).first, expr.formula((*it).second), order[(*it).second]);
}
void
AtomAsgnEvaluator::setValues(EvalTree &et) const
{
// set values of constants
aa.atoms.setValues(et);
// set values of variables to NaN or to user set values
double nan = std::numeric_limits<double>::quiet_NaN();
for (int i = 0; i < aa.atoms.nvar(); i++)
{
const char *ss = aa.atoms.name(i);
int t = aa.atoms.index(ss);
if (t >= 0)
{
Tusrvalmap::const_iterator it = user_values.find(t);
if (it == user_values.end())
et.set_nulary(t, nan);
else
et.set_nulary(t, (*it).second);
}
}
}
void
AtomAsgnEvaluator::set_user_value(const char *name, double val)
{
int t = aa.atoms.index(name);
if (t >= 0)
{
Tusrvalmap::iterator it = user_values.find(t);
if (it == user_values.end())
user_values.insert(Tusrvalmap::value_type(t, val));
else
(*it).second = val;
}
}
void
AtomAsgnEvaluator::load(int i, double res)
{
// set the value
operator[](i) = res;
// if i-th expression is atom, set its value to this EvalTree
int t = aa.order[i];
if (t >= 0)
etree.set_nulary(t, res);
}
double
AtomAsgnEvaluator::get_value(const char *name) const
{
AtomAssignings::Tvarintmap::const_iterator it = aa.lname2expr.find(name);
if (it == aa.lname2expr.end())
return std::numeric_limits<double>::quiet_NaN();
else
return operator[]((*it).second);
}

View File

@ -1,225 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: atom_assignings.cpp 92 2007-04-19 11:38:21Z ondra $
#include "atom_assignings.h"
#include "location.h"
#include "parser_exception.h"
#include "utils/cc/exception.h"
#include <limits>
#include <iostream>
using namespace ogp;
AtomAssignings::AtomAssignings(const AtomAssignings& aa, ogp::StaticAtoms& a)
: atoms(a), expr(aa.expr, atoms), left_names(aa.left_names),
order(aa.order)
{
// fill the lname2expr
for (Tvarintmap::const_iterator it = aa.lname2expr.begin();
it != aa.lname2expr.end(); ++it)
lname2expr.insert(Tvarintmap::value_type(left_names.query((*it).first), (*it).second));
}
/** A global symbol for passing info to the AtomAssignings from
* asgn_parse(). */
AtomAssignings* aparser;
/** The declaration of functions defined in asgn_ll.cc and asgn_tab.cc
* generated from assign.lex assign.y */
void* asgn__scan_buffer(char*, size_t);
void asgn__destroy_buffer(void*);
void asgn_parse();
extern location_type asgn_lloc;
void AtomAssignings::parse(int length, const char* stream)
{
char* buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
asgn_lloc.off = 0;
asgn_lloc.ll = 0;
void* p = asgn__scan_buffer(buffer, (unsigned int)length+2);
aparser = this;
asgn_parse();
delete [] buffer;
asgn__destroy_buffer(p);
}
void AtomAssignings::error(const char* mes)
{
throw ParserException(mes, asgn_lloc.off);
}
void AtomAssignings::add_assignment_to_double(const char* name, double val)
{
// if left hand side is a registered atom, insert it to tree
int t;
try {
if (atoms.check(name))
t = expr.add_nulary(name);
else
t = -1;
} catch (const ParserException& e) {
t = -1;
}
// register left hand side in order
order.push_back(t);
// add the double to the tree
char tmp[100];
sprintf(tmp, "%30.25g", val);
try {
expr.parse(strlen(tmp), tmp);
} catch (const ParserException& e) {
// should never happen
throw ParserException(string("Error parsing double ")+tmp+": "+e.message(), 0);
}
// register name of the left hand side and put to lname2expr
const char* ss = left_names.insert(name);
lname2expr.insert(Tvarintmap::value_type(ss, order.size()-1));
}
void AtomAssignings::add_assignment(int asgn_off, const char* str, int name_len,
int right_off, int right_len)
{
// the order of doing things here is important: since the
// FormulaParser requires that all references from the i-th tree
// refere to trees with index lass than i, so to capture also a
// nulary term for the left hand side, it must be inserted to the
// expression tree before the expression is parsed.
// find the name in the atoms, make copy of name to be able to put
// '\0' at the end
char* buf = new char[name_len+1];
strncpy(buf, str, name_len);
buf[name_len] = '\0';
// if left hand side is a registered atom, insert it to tree
int t;
try {
t = atoms.check(buf);
if (t == -1)
t = expr.add_nulary(buf);
} catch (const ParserException& e) {
atoms.register_name(buf);
t = expr.add_nulary(buf);
}
// register left hand side in order
order.push_back(t);
// parse expression on the right
try {
expr.parse(right_len, str+right_off);
} catch (const ParserException& e) {
throw ParserException(e, asgn_off+right_off);
}
// register name of the left hand side and put to lname2expr
const char* ss = left_names.insert(buf);
if (lname2expr.find(ss) != lname2expr.end()) {
// Prevent the occurrence of #415
std::cerr << "Changing the value of " << ss << " is not supported. Aborting." << std::endl;
exit(EXIT_FAILURE);
}
lname2expr[ss] = order.size()-1;
// delete name
delete [] buf;
}
void AtomAssignings::apply_subst(const AtomSubstitutions::Toldnamemap& mm)
{
// go through all old variables and see what are their derived new
// variables
for (AtomSubstitutions::Toldnamemap::const_iterator it = mm.begin();
it != mm.end(); ++it) {
const char* oldname = (*it).first;
const AtomSubstitutions::Tshiftnameset& sset = (*it).second;
if (! sset.empty()) {
int told = atoms.index(oldname);
if (told < 0 && ! atoms.get_name_storage().query(oldname))
atoms.register_name(oldname);
if (told == -1)
told = expr.add_nulary(oldname);
// at least one substitution here, so make an expression
expr.add_formula(told);
// say that this expression is not assigned to any atom
order.push_back(-1);
// now go through all new names derived from the old name and
// reference to the newly added formula
for (AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin();
itt != sset.end(); ++itt) {
const char* newname = (*itt).first;
const char* nn = left_names.insert(newname);
lname2expr.insert(Tvarintmap::value_type(nn, expr.nformulas()-1));
}
}
}
}
void AtomAssignings::print() const
{
printf("Atom Assignings\nExpressions:\n");
expr.print();
printf("Left names:\n");
for (Tvarintmap::const_iterator it = lname2expr.begin();
it != lname2expr.end(); ++it)
printf("%s ==> %d (t=%d)\n", (*it).first, expr.formula((*it).second), order[(*it).second]);
}
void AtomAsgnEvaluator::setValues(EvalTree& et) const
{
// set values of constants
aa.atoms.setValues(et);
// set values of variables to NaN or to user set values
double nan = std::numeric_limits<double>::quiet_NaN();
for (int i = 0; i < aa.atoms.nvar(); i++) {
const char* ss = aa.atoms.name(i);
int t = aa.atoms.index(ss);
if (t >= 0) {
Tusrvalmap::const_iterator it = user_values.find(t);
if (it == user_values.end())
et.set_nulary(t, nan);
else
et.set_nulary(t, (*it).second);
}
}
}
void AtomAsgnEvaluator::set_user_value(const char* name, double val)
{
int t = aa.atoms.index(name);
if (t >= 0) {
Tusrvalmap::iterator it = user_values.find(t);
if (it == user_values.end())
user_values.insert(Tusrvalmap::value_type(t, val));
else
(*it).second = val;
}
}
void AtomAsgnEvaluator::load(int i, double res)
{
// set the value
operator[](i) = res;
// if i-th expression is atom, set its value to this EvalTree
int t = aa.order[i];
if (t >= 0)
etree.set_nulary(t, res);
}
double AtomAsgnEvaluator::get_value(const char* name) const
{
AtomAssignings::Tvarintmap::const_iterator it = aa.lname2expr.find(name);
if (it == aa.lname2expr.end())
return std::numeric_limits<double>::quiet_NaN();
else
return operator[]((*it).second);
}

View File

@ -5,9 +5,9 @@
#ifndef OGP_ATOM_ASSIGNINGS_H
#define OGP_ATOM_ASSIGNINGS_H
#include "static_atoms.h"
#include "formula_parser.h"
#include "atom_substitutions.h"
#include "static_atoms.hh"
#include "formula_parser.hh"
#include "atom_substitutions.hh"
#include <vector>
#include <map>

View File

@ -0,0 +1,300 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: atom_substitutions.cpp 42 2007-01-22 21:53:24Z ondra $
#include "atom_substitutions.hh"
#include "utils/cc/exception.hh"
using namespace ogp;
AtomSubstitutions::AtomSubstitutions(const AtomSubstitutions &as, const FineAtoms &oa,
FineAtoms &na)
: old_atoms(oa), new_atoms(na)
{
const NameStorage &ns = na.get_name_storage();
// fill new2old
for (Tshiftmap::const_iterator it = as.new2old.begin();
it != as.new2old.end(); ++it)
new2old.insert(Tshiftmap::value_type(ns.query((*it).first),
Tshiftname(ns.query((*it).second.first),
(*it).second.second)));
// fill old2new
for (Toldnamemap::const_iterator it = as.old2new.begin();
it != as.old2new.end(); ++it)
{
Tshiftnameset sset;
for (Tshiftnameset::const_iterator itt = (*it).second.begin();
itt != (*it).second.end(); ++itt)
sset.insert(Tshiftname(ns.query((*itt).first), (*itt).second));
old2new.insert(Toldnamemap::value_type(ns.query((*it).first), sset));
}
}
void
AtomSubstitutions::add_substitution(const char *newname, const char *oldname, int tshift)
{
// make sure the storage is from the new_atoms
newname = new_atoms.get_name_storage().query(newname);
oldname = new_atoms.get_name_storage().query(oldname);
if (newname == NULL || oldname == NULL)
throw ogu::Exception(__FILE__, __LINE__,
"Bad newname or oldname in AtomSubstitutions::add_substitution");
// insert to new2old map
new2old.insert(Tshiftmap::value_type(newname, Tshiftname(oldname, tshift)));
// insert to old2new map
Toldnamemap::iterator it = old2new.find(oldname);
if (it != old2new.end())
(*it).second.insert(Tshiftname(newname, -tshift));
else
{
Tshiftnameset snset;
snset.insert(Tshiftname(newname, -tshift));
old2new.insert(Toldnamemap::value_type(oldname, snset));
}
// put to info
info.num_substs++;
}
void
AtomSubstitutions::substitutions_finished(VarOrdering::ord_type ot)
{
// create an external ordering of new_atoms from old_atoms
const vector<const char *> &oa_ext = old_atoms.get_allvar();
vector<const char *> na_ext;
for (unsigned int i = 0; i < oa_ext.size(); i++)
{
const char *oname = oa_ext[i];
// add the old name itself
na_ext.push_back(oname);
// add all new names derived from the old name
Toldnamemap::const_iterator it = old2new.find(oname);
if (it != old2new.end())
for (Tshiftnameset::const_iterator itt = (*it).second.begin();
itt != (*it).second.end(); ++itt)
na_ext.push_back((*itt).first);
}
// call parsing finished for the new_atoms
new_atoms.parsing_finished(ot, na_ext);
}
const char *
AtomSubstitutions::get_new4old(const char *oldname, int tshift) const
{
Toldnamemap::const_iterator it = old2new.find(oldname);
if (it != old2new.end())
{
const Tshiftnameset &sset = (*it).second;
for (Tshiftnameset::const_iterator itt = sset.begin();
itt != sset.end(); ++itt)
if ((*itt).second == -tshift)
return (*itt).first;
}
return NULL;
}
void
AtomSubstitutions::print() const
{
printf("Atom Substitutions:\nOld ==> New:\n");
for (Toldnamemap::const_iterator it = old2new.begin(); it != old2new.end(); ++it)
for (Tshiftnameset::const_iterator itt = (*it).second.begin();
itt != (*it).second.end(); ++itt)
printf(" %s ==> [%s, %d]\n", (*it).first, (*itt).first, (*itt).second);
printf("Old <== New:\n");
for (Tshiftmap::const_iterator it = new2old.begin(); it != new2old.end(); ++it)
printf(" [%s, %d] <== %s\n", (*it).second.first, (*it).second.second, (*it).first);
}
void
SAtoms::substituteAllLagsAndLeads(FormulaParser &fp, AtomSubstitutions &as)
{
const char *name;
int mlead, mlag;
endovarspan(mlead, mlag);
// substitute all endo lagged more than 1
while (NULL != (name = findEndoWithLeadInInterval(mlag, -2)))
makeAuxVariables(name, -1, -2, mlag, fp, as);
// substitute all endo leaded more than 1
while (NULL != (name = findEndoWithLeadInInterval(2, mlead)))
makeAuxVariables(name, 1, 2, mlead, fp, as);
exovarspan(mlead, mlag);
// substitute all lagged exo
while (NULL != (name = findExoWithLeadInInterval(mlag, -1)))
makeAuxVariables(name, -1, -1, mlag, fp, as);
// substitute all leaded exo
while (NULL != (name = findExoWithLeadInInterval(1, mlead)))
makeAuxVariables(name, 1, 1, mlead, fp, as);
// notify that substitution have been finished
as.substitutions_finished(order_type);
}
void
SAtoms::substituteAllLagsAndExo1Leads(FormulaParser &fp, AtomSubstitutions &as)
{
const char *name;
int mlead, mlag;
endovarspan(mlead, mlag);
// substitute all endo lagged more than 1
while (NULL != (name = findEndoWithLeadInInterval(mlag, -2)))
makeAuxVariables(name, -1, -2, mlag, fp, as);
exovarspan(mlead, mlag);
// substitute all lagged exo
while (NULL != (name = findExoWithLeadInInterval(mlag, -1)))
makeAuxVariables(name, -1, -1, mlag, fp, as);
// substitute all leaded exo by 1
while (NULL != (name = findExoWithLeadInInterval(1, 1)))
makeAuxVariables(name, 1, 1, 1, fp, as);
// notify that substitution have been finished
as.substitutions_finished(order_type);
}
const char *
SAtoms::findNameWithLeadInInterval(const vector<const char *> &names,
int ll1, int ll2) const
{
for (unsigned int i = 0; i < names.size(); i++)
{
const char *name = names[i];
DynamicAtoms::Tvarmap::const_iterator it = vars.find(name);
if (it != vars.end())
{
const DynamicAtoms::Tlagmap &lmap = (*it).second;
for (DynamicAtoms::Tlagmap::const_iterator itt = lmap.begin();
itt != lmap.end(); ++itt)
if ((*itt).first >= ll1 && (*itt).first <= ll2)
return name;
}
}
// nothing found
return NULL;
}
void
SAtoms::attemptAuxName(const char *str, int ll, string &out) const
{
char c = (ll >= 0) ? ((ll == 0) ? 'e' : 'p') : 'm';
char absll[100];
sprintf(absll, "%d", std::abs(ll));
int iter = 1;
do
{
out = string(str) + '_';
for (int i = 0; i < iter; i++)
out += c;
if (ll != 0)
out += absll;
iter++;
}
while (varnames.query(out.c_str()));
}
void
SAtoms::makeAuxVariables(const char *name, int step, int start, int limit_lead,
FormulaParser &fp, AtomSubstitutions &as)
{
if (!(step == 1 || step == -1))
throw ogu::Exception(__FILE__, __LINE__,
"Wrong value of step in SAtoms::makeAuxVariables");
if (step*start > step*limit_lead)
throw ogu::Exception(__FILE__, __LINE__,
"Wrong value of start in SAtoms::makeAuxVariables");
// make sure that we do not go further than necessary, this is
// that the limit lead is not behind maxlead or minlag
int mlead, mlag;
varspan(name, mlead, mlag);
if (step == -1)
limit_lead = std::max(limit_lead, mlag);
else
limit_lead = std::min(limit_lead, mlead);
// Comment to comments: name="a"; start=-3; step=-1;
char tmp[500];
// recover tree index of a previous atom, i.e. set tprev to a tree
// index of atom "a(-2)"
int tprev = index(name, start-step);
if (tprev == -1)
{
sprintf(tmp, "%s(%d)", name, start-step);
tprev = fp.add_nulary(tmp);
}
int ll = start;
do
{
// either create atom "a_m2(0)" with tree index taux and add
// equation "a_m2(0)=a(-2)"
// or
// check if "a_m2(0)" has not been already created (with
// different step), in this case do not add equation "a_m2(0)
// = a(-2)"
const char *newname;
string newname_str;
int taux;
if (NULL == (newname = as.get_new4old(name, ll-step)))
{
attemptAuxName(name, ll-step, newname_str);
newname = newname_str.c_str();
register_uniq_endo(newname);
newname = varnames.query(newname);
sprintf(tmp, "%s(0)", newname);
taux = fp.add_nulary(tmp);
// add to substitutions
as.add_substitution(newname, name, ll-step);
// add equation "a_m2(0) = a(-2)", this is taux = tprev
fp.add_formula(fp.add_binary(MINUS, taux, tprev));
}
else
{
// example: exogenous EPS and occurrence at both EPS(-1)
// EPS(+1)
// first call makeAuxVariables("EPS",1,1,...) will make endo EPS_p0 = EPS
// second call makeAuxVariables("EPS",-1,-1,...) will use this EPS_p0
// to substitute for EPS(-1)
taux = index(newname, 0);
if (taux < 0)
throw ogu::Exception(__FILE__, __LINE__,
"Couldn't find tree index of previously substituted variable");
}
// create atom "a_m2(-1)" or turn "a(-3)" if any to "a_m2(-1)"; tree index t
int t = index(name, ll);
if (t == -1)
{
// no "a(-3)", make t <-> a_m2(-1)
sprintf(tmp, "%s(%d)", newname, step);
t = fp.add_nulary(tmp);
}
else
{
// turn a(-3) to a_m2(-1)
unassign_variable(name, ll, t);
assign_variable(newname, step, t);
}
// next iteration starts with tprev <-> "a_m2(-1)" (this will be made equal to "a_m3(0)")
tprev = t;
ll += step;
}
while (step*ll <= step*limit_lead);
}

View File

@ -1,275 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: atom_substitutions.cpp 42 2007-01-22 21:53:24Z ondra $
#include "atom_substitutions.h"
#include "utils/cc/exception.h"
using namespace ogp;
AtomSubstitutions::AtomSubstitutions(const AtomSubstitutions& as, const FineAtoms& oa,
FineAtoms& na)
: old_atoms(oa), new_atoms(na)
{
const NameStorage& ns = na.get_name_storage();
// fill new2old
for (Tshiftmap::const_iterator it = as.new2old.begin();
it != as.new2old.end(); ++it)
new2old.insert(Tshiftmap::value_type(ns.query((*it).first),
Tshiftname(ns.query((*it).second.first),
(*it).second.second)));
// fill old2new
for (Toldnamemap::const_iterator it = as.old2new.begin();
it != as.old2new.end(); ++it) {
Tshiftnameset sset;
for (Tshiftnameset::const_iterator itt = (*it).second.begin();
itt != (*it).second.end(); ++itt)
sset.insert(Tshiftname(ns.query((*itt).first), (*itt).second));
old2new.insert(Toldnamemap::value_type(ns.query((*it).first), sset));
}
}
void AtomSubstitutions::add_substitution(const char* newname, const char* oldname, int tshift)
{
// make sure the storage is from the new_atoms
newname = new_atoms.get_name_storage().query(newname);
oldname = new_atoms.get_name_storage().query(oldname);
if (newname == NULL || oldname == NULL)
throw ogu::Exception(__FILE__,__LINE__,
"Bad newname or oldname in AtomSubstitutions::add_substitution");
// insert to new2old map
new2old.insert(Tshiftmap::value_type(newname, Tshiftname(oldname, tshift)));
// insert to old2new map
Toldnamemap::iterator it = old2new.find(oldname);
if (it != old2new.end())
(*it).second.insert(Tshiftname(newname, -tshift));
else {
Tshiftnameset snset;
snset.insert(Tshiftname(newname, -tshift));
old2new.insert(Toldnamemap::value_type(oldname, snset));
}
// put to info
info.num_substs++;
}
void AtomSubstitutions::substitutions_finished(VarOrdering::ord_type ot)
{
// create an external ordering of new_atoms from old_atoms
const vector<const char*>& oa_ext = old_atoms.get_allvar();
vector<const char*> na_ext;
for (unsigned int i = 0; i < oa_ext.size(); i++) {
const char* oname = oa_ext[i];
// add the old name itself
na_ext.push_back(oname);
// add all new names derived from the old name
Toldnamemap::const_iterator it = old2new.find(oname);
if (it != old2new.end())
for (Tshiftnameset::const_iterator itt = (*it).second.begin();
itt != (*it).second.end(); ++itt)
na_ext.push_back((*itt).first);
}
// call parsing finished for the new_atoms
new_atoms.parsing_finished(ot, na_ext);
}
const char* AtomSubstitutions::get_new4old(const char* oldname, int tshift) const
{
Toldnamemap::const_iterator it = old2new.find(oldname);
if (it != old2new.end()) {
const Tshiftnameset& sset = (*it).second;
for (Tshiftnameset::const_iterator itt = sset.begin();
itt != sset.end(); ++itt)
if ((*itt).second == - tshift)
return (*itt).first;
}
return NULL;
}
void AtomSubstitutions::print() const
{
printf("Atom Substitutions:\nOld ==> New:\n");
for (Toldnamemap::const_iterator it = old2new.begin(); it != old2new.end(); ++it)
for (Tshiftnameset::const_iterator itt = (*it).second.begin();
itt != (*it).second.end(); ++itt)
printf(" %s ==> [%s, %d]\n", (*it).first, (*itt).first, (*itt).second);
printf("Old <== New:\n");
for (Tshiftmap::const_iterator it = new2old.begin(); it != new2old.end(); ++it)
printf(" [%s, %d] <== %s\n", (*it).second.first, (*it).second.second, (*it).first);
}
void SAtoms::substituteAllLagsAndLeads(FormulaParser& fp, AtomSubstitutions& as)
{
const char* name;
int mlead, mlag;
endovarspan(mlead, mlag);
// substitute all endo lagged more than 1
while (NULL != (name = findEndoWithLeadInInterval(mlag, -2)))
makeAuxVariables(name, -1, -2, mlag, fp, as);
// substitute all endo leaded more than 1
while (NULL != (name = findEndoWithLeadInInterval(2, mlead)))
makeAuxVariables(name, 1, 2, mlead, fp, as);
exovarspan(mlead, mlag);
// substitute all lagged exo
while (NULL != (name = findExoWithLeadInInterval(mlag, -1)))
makeAuxVariables(name, -1, -1, mlag, fp, as);
// substitute all leaded exo
while (NULL != (name = findExoWithLeadInInterval(1, mlead)))
makeAuxVariables(name, 1, 1, mlead, fp, as);
// notify that substitution have been finished
as.substitutions_finished(order_type);
}
void SAtoms::substituteAllLagsAndExo1Leads(FormulaParser& fp, AtomSubstitutions& as)
{
const char* name;
int mlead, mlag;
endovarspan(mlead, mlag);
// substitute all endo lagged more than 1
while (NULL != (name = findEndoWithLeadInInterval(mlag, -2)))
makeAuxVariables(name, -1, -2, mlag, fp, as);
exovarspan(mlead, mlag);
// substitute all lagged exo
while (NULL != (name = findExoWithLeadInInterval(mlag, -1)))
makeAuxVariables(name, -1, -1, mlag, fp, as);
// substitute all leaded exo by 1
while (NULL != (name = findExoWithLeadInInterval(1,1)))
makeAuxVariables(name, 1, 1, 1, fp, as);
// notify that substitution have been finished
as.substitutions_finished(order_type);
}
const char* SAtoms::findNameWithLeadInInterval(const vector<const char*>& names,
int ll1, int ll2) const
{
for (unsigned int i = 0; i < names.size(); i++) {
const char* name = names[i];
DynamicAtoms::Tvarmap::const_iterator it = vars.find(name);
if (it != vars.end()) {
const DynamicAtoms::Tlagmap& lmap = (*it).second;
for (DynamicAtoms::Tlagmap::const_iterator itt = lmap.begin();
itt != lmap.end(); ++itt)
if ((*itt).first >= ll1 && (*itt).first <= ll2)
return name;
}
}
// nothing found
return NULL;
}
void SAtoms::attemptAuxName(const char* str, int ll, string& out) const
{
char c = (ll >= 0)? ((ll == 0)? 'e' : 'p' ) : 'm';
char absll[100];
sprintf(absll, "%d", std::abs(ll));
int iter = 1;
do {
out = string(str) + '_';
for (int i = 0; i < iter; i++)
out += c;
if (ll != 0)
out += absll;
iter++;
} while (varnames.query(out.c_str()));
}
void SAtoms::makeAuxVariables(const char* name, int step, int start, int limit_lead,
FormulaParser& fp, AtomSubstitutions& as)
{
if (! (step == 1 || step == -1))
throw ogu::Exception(__FILE__,__LINE__,
"Wrong value of step in SAtoms::makeAuxVariables");
if (step*start > step*limit_lead)
throw ogu::Exception(__FILE__,__LINE__,
"Wrong value of start in SAtoms::makeAuxVariables");
// make sure that we do not go further than necessary, this is
// that the limit lead is not behind maxlead or minlag
int mlead, mlag;
varspan(name, mlead, mlag);
if (step == -1)
limit_lead = std::max(limit_lead, mlag);
else
limit_lead = std::min(limit_lead, mlead);
// Comment to comments: name="a"; start=-3; step=-1;
char tmp[500];
// recover tree index of a previous atom, i.e. set tprev to a tree
// index of atom "a(-2)"
int tprev = index(name, start-step);
if (tprev == -1) {
sprintf(tmp, "%s(%d)", name, start-step);
tprev = fp.add_nulary(tmp);
}
int ll = start;
do {
// either create atom "a_m2(0)" with tree index taux and add
// equation "a_m2(0)=a(-2)"
// or
// check if "a_m2(0)" has not been already created (with
// different step), in this case do not add equation "a_m2(0)
// = a(-2)"
const char* newname;
string newname_str;
int taux;
if (NULL == (newname=as.get_new4old(name, ll-step))) {
attemptAuxName(name, ll-step, newname_str);
newname = newname_str.c_str();
register_uniq_endo(newname);
newname = varnames.query(newname);
sprintf(tmp, "%s(0)", newname);
taux = fp.add_nulary(tmp);
// add to substitutions
as.add_substitution(newname, name, ll-step);
// add equation "a_m2(0) = a(-2)", this is taux = tprev
fp.add_formula(fp.add_binary(MINUS, taux, tprev));
} else {
// example: exogenous EPS and occurrence at both EPS(-1)
// EPS(+1)
// first call makeAuxVariables("EPS",1,1,...) will make endo EPS_p0 = EPS
// second call makeAuxVariables("EPS",-1,-1,...) will use this EPS_p0
// to substitute for EPS(-1)
taux = index(newname, 0);
if (taux < 0)
throw ogu::Exception(__FILE__,__LINE__,
"Couldn't find tree index of previously substituted variable");
}
// create atom "a_m2(-1)" or turn "a(-3)" if any to "a_m2(-1)"; tree index t
int t = index(name, ll);
if (t == -1) {
// no "a(-3)", make t <-> a_m2(-1)
sprintf(tmp, "%s(%d)", newname, step);
t = fp.add_nulary(tmp);
} else {
// turn a(-3) to a_m2(-1)
unassign_variable(name, ll, t);
assign_variable(newname, step, t);
}
// next iteration starts with tprev <-> "a_m2(-1)" (this will be made equal to "a_m3(0)")
tprev = t;
ll += step;
} while (step*ll <= step*limit_lead);
}

View File

@ -5,7 +5,7 @@
#ifndef OGP_ATOM_SUBSTITUTIONS_H
#define OGP_ATOM_SUBSTITUTIONS_H
#include "fine_atoms.h"
#include "fine_atoms.hh"
#include <string>

View File

@ -1,7 +1,7 @@
%{
// Copyright (C) 2007-2011, Ondra Kamenik
#include "location.h"
#include "location.hh"
#include "csv_tab.hh"
extern YYLTYPE csv_lloc;

View File

@ -1,6 +1,6 @@
%{
#include "location.h"
#include "csv_parser.h"
#include "location.hh"
#include "csv_parser.hh"
#include "csv_tab.hh"
void csv_error(const char*);

View File

@ -0,0 +1,44 @@
#include "csv_parser.hh"
#include "parser_exception.hh"
#include "location.hh"
#include "csv_tab.hh"
#include <cstring>
using namespace ogp;
/** A global symbol for passing info to the CSVParser from
* csv_parse(). */
CSVParser *csv_parser;
/** The declaration of functions defined in csv_ll.cc and
* csv_tab.cc generated from csv.lex and csv.y. */
void *csv__scan_buffer(char *, unsigned int);
void csv__destroy_buffer(void *);
int csv_parse();
extern ogp::location_type csv_lloc;
void
CSVParser::csv_error(const char *mes)
{
throw ParserException(mes, csv_lloc.off);
}
void
CSVParser::csv_parse(int length, const char *str)
{
// allocate temporary buffer and parse
char *buffer = new char[length+2];
strncpy(buffer, str, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
csv_lloc.off = 0;
csv_lloc.ll = 0;
parsed_string = buffer;
void *p = csv__scan_buffer(buffer, (unsigned int) length+2);
csv_parser = this;
::csv_parse();
delete [] buffer;
csv__destroy_buffer(p);
parsed_string = NULL;
}

View File

@ -1,42 +0,0 @@
#include "csv_parser.h"
#include "parser_exception.h"
#include "location.h"
#include "csv_tab.hh"
#include <cstring>
using namespace ogp;
/** A global symbol for passing info to the CSVParser from
* csv_parse(). */
CSVParser* csv_parser;
/** The declaration of functions defined in csv_ll.cc and
* csv_tab.cc generated from csv.lex and csv.y. */
void* csv__scan_buffer(char*, unsigned int);
void csv__destroy_buffer(void*);
int csv_parse();
extern ogp::location_type csv_lloc;
void CSVParser::csv_error(const char* mes)
{
throw ParserException(mes, csv_lloc.off);
}
void CSVParser::csv_parse(int length, const char* str)
{
// allocate temporary buffer and parse
char* buffer = new char[length+2];
strncpy(buffer, str, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
csv_lloc.off = 0;
csv_lloc.ll = 0;
parsed_string = buffer;
void* p = csv__scan_buffer(buffer, (unsigned int)length+2);
csv_parser = this;
::csv_parse();
delete [] buffer;
csv__destroy_buffer(p);
parsed_string = NULL;
}

View File

@ -0,0 +1,710 @@
// Copyright (C) 2005, Ondra Kamenik
// $Id: dynamic_atoms.cpp 1362 2007-07-10 11:50:18Z kamenik $
#include "utils/cc/exception.hh"
#include "dynamic_atoms.hh"
#include <cstring>
#include <climits>
using namespace ogp;
NameStorage::NameStorage(const NameStorage &stor)
{
for (unsigned int i = 0; i < stor.name_store.size(); i++)
{
char *str = new char[strlen(stor.name_store[i])+1];
strcpy(str, stor.name_store[i]);
name_store.push_back(str);
name_set.insert(str);
}
}
NameStorage::~NameStorage()
{
while (name_store.size() > 0)
{
delete [] name_store.back();
name_store.pop_back();
}
}
const char *
NameStorage::query(const char *name) const
{
set<const char *, ltstr>::const_iterator it = name_set.find(name);
if (it == name_set.end())
return NULL;
else
return (*it);
}
const char *
NameStorage::insert(const char *name)
{
set<const char *, ltstr>::const_iterator it = name_set.find(name);
if (it == name_set.end())
{
char *str = new char[strlen(name)+1];
strcpy(str, name);
name_store.push_back(str);
name_set.insert(str);
return str;
}
else
{
return (*it);
}
}
void
NameStorage::print() const
{
for (unsigned int i = 0; i < name_store.size(); i++)
printf("%s\n", name_store[i]);
}
void
Constants::import_constants(const Constants &c, OperationTree &otree, Tintintmap &tmap)
{
for (Tconstantmap::const_iterator it = c.cmap.begin();
it != c.cmap.end(); ++it)
{
int told = (*it).first;
int tnew = otree.add_nulary();
tmap.insert(Tintintmap::value_type(told, tnew));
add_constant(tnew, (*it).second);
}
}
void
Constants::setValues(EvalTree &et) const
{
Tconstantmap::const_iterator it;
for (it = cmap.begin(); it != cmap.end(); ++it)
et.set_nulary((*it).first, (*it).second);
}
void
Constants::add_constant(int t, double val)
{
cmap.insert(Tconstantmap::value_type(t, val));
cinvmap.insert(Tconstantinvmap::value_type(val, t));
}
bool
Constants::is_constant(int t) const
{
if (t < OperationTree::num_constants)
return true;
Tconstantmap::const_iterator it = cmap.find(t);
return (it != cmap.end());
}
double
Constants::get_constant_value(int t) const
{
Tconstantmap::const_iterator it = cmap.find(t);
if (it != cmap.end())
return (*it).second;
else
{
throw ogu::Exception(__FILE__, __LINE__,
"Tree index is not constant in Constants::get_constant_value");
return 0;
}
}
int
Constants::check(const char *str) const
{
double d;
sscanf(str, "%lf", &d);
Tconstantinvmap::const_iterator it = cinvmap.find(d);
if (it != cinvmap.end())
return (*it).second;
else
return -1;
}
void
Constants::print() const
{
Tconstantmap::const_iterator it;
for (it = cmap.begin(); it != cmap.end(); ++it)
printf("$%d: %8.4g\n", (*it).first, (*it).second);
}
DynamicAtoms::DynamicAtoms()
: nv(0), minlag(INT_MAX), maxlead(INT_MIN)
{
}
DynamicAtoms::DynamicAtoms(const DynamicAtoms &da)
: Constants(da),
varnames(da.varnames), vars(), indices(),
nv(da.nv), minlag(da.minlag), maxlead(da.maxlead)
{
// copy vars
for (Tvarmap::const_iterator it = da.vars.begin();
it != da.vars.end(); ++it)
vars.insert(Tvarmap::value_type(varnames.query((*it).first),
(*it).second));
// copy indices
for (Tindexmap::const_iterator it = da.indices.begin();
it != da.indices.end(); ++it)
indices.insert(Tindexmap::value_type((*it).first,
varnames.query((*it).second)));
}
int
DynamicAtoms::check(const char *name) const
{
if (is_string_constant(name))
return Constants::check(name);
return check_variable(name);
}
int
DynamicAtoms::check_variable(const char *name) const
{
string str;
int ll;
parse_variable(name, str, ll);
Tvarmap::const_iterator it = vars.find(str.c_str());
if (it != vars.end())
{
const Tlagmap &lmap = (*it).second;
Tlagmap::const_iterator itt = lmap.find(ll);
if (itt != lmap.end())
return (*itt).second;
}
return -1;
}
void
DynamicAtoms::assign(const char *name, int t)
{
if (is_string_constant(name))
assign_constant(name, t);
else
assign_variable(name, t);
}
void
DynamicAtoms::assign_constant(const char *name, int t)
{
double val;
sscanf(name, "%lf", &val);
add_constant(t, val);
}
// parse the name and then call assing_variable(varname, ll, t)
void
DynamicAtoms::assign_variable(const char *name, int t)
{
int ll;
string str;
parse_variable(name, str, ll);
// here str is just name without lead/lag
const char *ss = varnames.insert(str.c_str());
assign_variable(ss, ll, t);
}
void
DynamicAtoms::assign_variable(const char *varname, int ll, int t)
{
if (indices.end() != indices.find(t))
throw ogu::Exception(__FILE__, __LINE__,
"Attempt to assign already allocated tree index");
Tvarmap::iterator it = vars.find(varname);
if (it != vars.end())
{
Tlagmap &lmap = (*it).second;
if (lmap.end() != lmap.find(ll))
throw ogu::Exception(__FILE__, __LINE__,
"Attempt to assign already allocated variable");
lmap.insert(Tlagmap::value_type(ll, t));
}
else
{
Tlagmap lmap;
lmap.insert(Tlagmap::value_type(ll, t));
vars.insert(Tvarmap::value_type(varname, lmap));
}
indices.insert(Tindexmap::value_type(t, varname));
nv++;
if (ll < minlag)
minlag = ll;
if (ll > maxlead)
maxlead = ll;
}
void
DynamicAtoms::unassign_variable(const char *varname, int ll, int t)
{
Tvarmap::iterator it = vars.find(varname);
if (it != vars.end())
{
Tlagmap &lmap = (*it).second;
Tlagmap::iterator itt = lmap.find(ll);
if (itt != lmap.end())
{
if ((*itt).second == t)
{
// erase it from the lagmap; if it becomes empty,
// erase the lagmap from varmap
lmap.erase(itt);
if (lmap.size() == 0)
vars.erase(it);
// erase it from the indices
Tindexmap::iterator ittt = indices.find(t);
if (ittt != indices.end())
indices.erase(ittt);
nv--;
if (ll == minlag || ll == maxlead)
update_minmaxll();
}
else
throw ogu::Exception(__FILE__, __LINE__,
"Tree index inconsistent in DynamicAtoms::unassign_variable");
}
else
throw ogu::Exception(__FILE__, __LINE__,
"Lead/lag of the variable not found in DynamicAtoms::unassign_variable");
}
else
throw ogu::Exception(__FILE__, __LINE__,
"Variable not found in DynamicAtoms::unassign_variable");
}
void
DynamicAtoms::update_minmaxll()
{
minlag = INT_MAX;
maxlead = INT_MIN;
for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it)
{
const Tlagmap &lmap = (*it).second;
for (Tlagmap::const_iterator itt = lmap.begin(); itt != lmap.end(); ++itt)
{
int ll = (*itt).first;
if (ll < minlag)
minlag = ll;
if (ll > maxlead)
maxlead = ll;
}
}
}
vector<int>
DynamicAtoms::variables() const
{
vector<int> res;
for (Tvarmap::const_iterator it = vars.begin();
it != vars.end(); ++it)
{
const Tlagmap &lmap = (*it).second;
for (Tlagmap::const_iterator itt = lmap.begin();
itt != lmap.end(); ++itt)
res.push_back((*itt).second);
}
return res;
}
void
DynamicAtoms::varspan(int t, int &mlead, int &mlag) const
{
Tindexmap::const_iterator it = indices.find(t);
if (indices.end() == it)
{
mlead = INT_MIN;
mlag = INT_MAX;
return;
}
varspan((*it).second, mlead, mlag);
}
void
DynamicAtoms::varspan(const char *name, int &mlead, int &mlag) const
{
Tvarmap::const_iterator it = vars.find(name);
if (vars.end() == it)
{
mlead = INT_MIN;
mlag = INT_MAX;
return;
}
const Tlagmap &lmap = (*it).second;
Tlagmap::const_iterator beg = lmap.begin();
Tlagmap::const_reverse_iterator end = lmap.rbegin();
mlag = (*beg).first;
mlead = (*end).first;
}
void
DynamicAtoms::varspan(const vector<const char *> &names, int &mlead, int &mlag) const
{
mlead = INT_MIN;
mlag = INT_MAX;
for (unsigned int i = 0; i < names.size(); i++)
{
int lag, lead;
varspan(names[i], lead, lag);
if (lead > mlead)
mlead = lead;
if (lag < mlag)
mlag = lag;
}
}
bool
DynamicAtoms::is_named_atom(int t) const
{
return (indices.end() != indices.find(t));
}
int
DynamicAtoms::index(const char *name, int ll) const
{
Tvarmap::const_iterator it = vars.find(name);
if (vars.end() != it)
{
const Tlagmap &lmap = (*it).second;
Tlagmap::const_iterator itt = lmap.find(ll);
if (lmap.end() != itt)
return (*itt).second;
}
return -1;
}
bool
DynamicAtoms::is_referenced(const char *name) const
{
Tvarmap::const_iterator it = vars.find(name);
return it != vars.end();
}
const DynamicAtoms::Tlagmap &
DynamicAtoms::lagmap(const char *name) const
{
Tvarmap::const_iterator it = vars.find(name);
if (vars.end() == it)
throw ogu::Exception(__FILE__, __LINE__,
std::string("Couldn't find the name ")
+ name + " in DynamicAtoms::lagmap");
return (*it).second;
}
const char *
DynamicAtoms::name(int t) const
{
Tindexmap::const_iterator it = indices.find(t);
if (indices.end() == it)
throw ogu::Exception(__FILE__, __LINE__,
"Couldn't find tree index in DynamicAtoms::name");
return (*it).second;
}
int
DynamicAtoms::lead(int t) const
{
const char *nam = name(t);
const Tlagmap &lmap = lagmap(nam);
Tlagmap::const_iterator it = lmap.begin();
while (it != lmap.end() && (*it).second != t)
++it;
if (lmap.end() == it)
throw ogu::Exception(__FILE__, __LINE__,
"Couldn't find the three index in DynamicAtoms::lead");
return (*it).first;
}
void
DynamicAtoms::print() const
{
printf("names:\n");
varnames.print();
printf("constants:\n");
Constants::print();
printf("variables:\n");
for (Tvarmap::const_iterator it = vars.begin();
it != vars.end(); ++it)
{
const Tlagmap &lmap = (*it).second;
for (Tlagmap::const_iterator itt = lmap.begin();
itt != lmap.end(); ++itt)
printf("$%d: %s(%d)\n", (*itt).second, (*it).first, (*itt).first);
}
printf("indices:\n");
for (Tindexmap::const_iterator it = indices.begin();
it != indices.end(); ++it)
printf("t=%d ==> %s\n", (*it).first, (*it).second);
}
/** Note that the str has been parsed by the lexicographic
* analyzer. It can be either a variable or a double. So it is easy to
* recognize it by the first character. */
bool
DynamicAtoms::is_string_constant(const char *str)
{
return str[0] == '.' || str[0] == '-' || (str[0] >= '0' && str[0] <= '9');
}
VarOrdering::VarOrdering(const VarOrdering &vo, const vector<const char *> &vnames,
const DynamicAtoms &a)
: n_stat(vo.n_stat), n_pred(vo.n_pred), n_both(vo.n_both), n_forw(vo.n_forw),
der_atoms(vo.der_atoms), positions(vo.positions),
outer2y(vo.outer2y), y2outer(vo.y2outer), varnames(vnames), atoms(a)
{
}
bool
VarOrdering::check(int t) const
{
map<int, int>::const_iterator it = positions.find(t);
return it != positions.end();
}
int
VarOrdering::get_pos_of(int t) const
{
map<int, int>::const_iterator it = positions.find(t);
if (it != positions.end())
{
return (*it).second;
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"Couldn't find the tree index in VarOrdering::get_pos_of");
return -1;
}
}
void
VarOrdering::do_general(ord_type ordering)
{
// auxiliary vectors for setting der_atoms and map
vector<int> pred_minus;
vector<int> both_minus;
vector<int> stat;
vector<int> pred_pad;
vector<int> both_pad;
vector<int> forw_pad;
vector<int> both_plus;
vector<int> forw_plus;
// auxiliary vectors for setting y2outer and outer2y
vector<int> y2o_stat;
vector<int> y2o_pred;
vector<int> y2o_both;
vector<int> y2o_forw;
for (unsigned int i = 0; i < varnames.size(); i++)
{
const char *ss = varnames[i];
int lead;
int lag;
atoms.varspan(ss, lead, lag);
if (lag == 0 && lead == 0)
{
stat.push_back(atoms.index(ss, 0));
y2o_stat.push_back(i);
}
else if (lag == -1 && lead < 1)
{
pred_minus.push_back(atoms.index(ss, -1));
pred_pad.push_back(atoms.index(ss, 0));
y2o_pred.push_back(i);
}
else if (lag > -1 && lead == 1)
{
forw_pad.push_back(atoms.index(ss, 0));
forw_plus.push_back(atoms.index(ss, 1));
y2o_forw.push_back(i);
}
else if (lag == -1 && lead == 1)
{
both_minus.push_back(atoms.index(ss, -1));
both_pad.push_back(atoms.index(ss, 0));
both_plus.push_back(atoms.index(ss, 1));
y2o_both.push_back(i);
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"A wrong lag/lead of a variable in VarOrdering::do_pbspbfbf");
}
}
// here we fill ords according to ordering
vector<int> *ords[8];
if (ordering == pbspbfbf)
{
ords[0] = &pred_minus;
ords[1] = &both_minus;
ords[2] = &stat;
ords[3] = &pred_pad;
ords[4] = &both_pad;
ords[5] = &forw_pad;
ords[6] = &both_plus;
ords[7] = &forw_plus;
}
else if (ordering == bfspbfpb)
{
ords[0] = &both_plus;
ords[1] = &forw_plus;
ords[2] = &stat;
ords[3] = &pred_pad;
ords[4] = &both_pad;
ords[5] = &forw_pad;
ords[6] = &pred_minus;
ords[7] = &both_minus;
}
else // BEWARE: when implementing a new ordering, check also a
{// code below setting y2outer
throw ogu::Exception(__FILE__, __LINE__,
"Ordering not implemented in VarOrdering::do_general");
}
// make der_atoms and positions
int off = 0;
for (unsigned int i = 0; i < 8; i++)
for (unsigned int j = 0; j < (ords[i])->size(); j++, off++)
if ((*(ords[i]))[j] != -1)
{
der_atoms.push_back((*(ords[i]))[j]);
positions.insert(std::pair<int, int>((*(ords[i]))[j], off));
}
// set integer constants
n_stat = stat.size();
n_pred = pred_pad.size();
n_both = both_pad.size();
n_forw = forw_pad.size();
// make y2outer mapping
y2outer.insert(y2outer.end(), y2o_stat.begin(), y2o_stat.end());
y2outer.insert(y2outer.end(), y2o_pred.begin(), y2o_pred.end());
y2outer.insert(y2outer.end(), y2o_both.begin(), y2o_both.end());
y2outer.insert(y2outer.end(), y2o_forw.begin(), y2o_forw.end());
// make outer2y mapping
outer2y.resize(y2outer.size(), -1);
for (unsigned int i = 0; i < y2outer.size(); i++)
outer2y[y2outer[i]] = i;
}
void
VarOrdering::do_increasing_time()
{
// get maxlead and minlag of the variables
int mlag, mlead;
atoms.varspan(varnames, mlead, mlag);
// setup the matrix of tree indices, if there is no occurrence,
// the index is set to -1
vector<int> ll_init(varnames.size(), -1);
vector<vector<int> > tree_ind(mlead-mlag+1, ll_init);
for (unsigned int iv = 0; iv < varnames.size(); iv++)
{
try
{
const DynamicAtoms::Tlagmap &lmap = atoms.lagmap(varnames[iv]);
for (DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it)
{
int ll = (*it).first;
int t = (*it).second;
tree_ind[ll-mlag][iv] = t;
}
}
catch (const ogu::Exception &e)
{
// ignore the error of not found variable in the tree
}
}
// setup der_atoms and positions
for (int ll = mlag; ll <= mlead; ll++)
for (unsigned int iv = 0; iv < varnames.size(); iv++)
{
int t = tree_ind[ll-mlag][iv];
if (t != -1)
{
der_atoms.push_back(t);
int pos = (ll-mlag)*varnames.size() + iv;
positions.insert(map<int, int>::value_type(t, pos));
}
}
// set outer2y and y2outer to identities
for (unsigned int iv = 0; iv < varnames.size(); iv++)
{
outer2y.push_back(iv);
y2outer.push_back(iv);
}
// set n_stat, n_pred, n_both, and n_forw
for (unsigned int iv = 0; iv < varnames.size(); iv++)
{
int mmlag, mmlead;
atoms.varspan(varnames[iv], mmlead, mmlag);
if (mmlead == 0 && mmlag == 0)
{
n_stat++;
}
else if (mmlead <= 0 && mmlag < 0)
{
n_pred++;
}
else if (mmlead > 0 && mmlag >= 0)
{
n_forw++;
}
else if (mmlead > 0 && mmlag < 0)
{
n_both++;
}
else if (mmlead < mmlag)
{
// variable does not occur in the tree, cound as static
n_stat++;
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"A wrong lag/lead of a variable in VarOrdering::do_increasing_time");
}
}
}
void
VarOrdering::print() const
{
printf("nstat=%d, npred=%d, nboth=%d, nforw=%d\n", n_stat, n_pred, n_both, n_forw);
printf("der_atoms:\n");
for (unsigned int i = 0; i < der_atoms.size(); i++)
printf(" %d", der_atoms[i]);
printf("\nmap:\n");
for (map<int, int>::const_iterator it = positions.begin(); it != positions.end(); ++it)
printf(" [%d->%d]", (*it).first, (*it).second);
printf("\ny2outer:\n");
for (unsigned int i = 0; i < y2outer.size(); i++)
printf(" %d", y2outer[i]);
printf("\nouter2y:\n");
for (unsigned int i = 0; i < outer2y.size(); i++)
printf(" %d", outer2y[i]);
printf("\n");
}
// Local Variables:
// mode:C++
// End:

View File

@ -1,615 +0,0 @@
// Copyright (C) 2005, Ondra Kamenik
// $Id: dynamic_atoms.cpp 1362 2007-07-10 11:50:18Z kamenik $
#include "utils/cc/exception.h"
#include "dynamic_atoms.h"
#include <cstring>
#include <climits>
using namespace ogp;
NameStorage::NameStorage(const NameStorage& stor)
{
for (unsigned int i = 0; i < stor.name_store.size(); i++) {
char* str = new char[strlen(stor.name_store[i])+1];
strcpy(str, stor.name_store[i]);
name_store.push_back(str);
name_set.insert(str);
}
}
NameStorage::~NameStorage()
{
while (name_store.size() > 0) {
delete [] name_store.back();
name_store.pop_back();
}
}
const char* NameStorage::query(const char* name) const
{
set<const char*, ltstr>::const_iterator it = name_set.find(name);
if (it == name_set.end())
return NULL;
else
return (*it);
}
const char* NameStorage::insert(const char* name)
{
set<const char*, ltstr>::const_iterator it = name_set.find(name);
if (it == name_set.end()) {
char* str = new char[strlen(name)+1];
strcpy(str, name);
name_store.push_back(str);
name_set.insert(str);
return str;
} else {
return (*it);
}
}
void NameStorage::print() const
{
for (unsigned int i = 0; i < name_store.size(); i++)
printf("%s\n", name_store[i]);
}
void Constants::import_constants(const Constants& c, OperationTree& otree, Tintintmap& tmap)
{
for (Tconstantmap::const_iterator it = c.cmap.begin();
it != c.cmap.end(); ++it) {
int told = (*it).first;
int tnew = otree.add_nulary();
tmap.insert(Tintintmap::value_type(told, tnew));
add_constant(tnew, (*it).second);
}
}
void Constants::setValues(EvalTree& et) const
{
Tconstantmap::const_iterator it;
for (it = cmap.begin(); it != cmap.end(); ++it)
et.set_nulary((*it).first, (*it).second);
}
void Constants::add_constant(int t, double val)
{
cmap.insert(Tconstantmap::value_type(t, val));
cinvmap.insert(Tconstantinvmap::value_type(val, t));
}
bool Constants::is_constant(int t) const
{
if (t < OperationTree::num_constants)
return true;
Tconstantmap::const_iterator it = cmap.find(t);
return (it != cmap.end());
}
double Constants::get_constant_value(int t) const
{
Tconstantmap::const_iterator it = cmap.find(t);
if (it != cmap.end())
return (*it).second;
else {
throw ogu::Exception(__FILE__,__LINE__,
"Tree index is not constant in Constants::get_constant_value");
return 0;
}
}
int Constants::check(const char* str) const
{
double d;
sscanf(str, "%lf", &d);
Tconstantinvmap::const_iterator it = cinvmap.find(d);
if (it != cinvmap.end())
return (*it).second;
else
return -1;
}
void Constants::print() const
{
Tconstantmap::const_iterator it;
for (it = cmap.begin(); it != cmap.end(); ++it)
printf("$%d: %8.4g\n", (*it).first, (*it).second);
}
DynamicAtoms::DynamicAtoms()
: nv(0), minlag(INT_MAX), maxlead(INT_MIN)
{
}
DynamicAtoms::DynamicAtoms(const DynamicAtoms& da)
: Constants(da),
varnames(da.varnames), vars(), indices(),
nv(da.nv), minlag(da.minlag), maxlead(da.maxlead)
{
// copy vars
for (Tvarmap::const_iterator it = da.vars.begin();
it != da.vars.end(); ++it)
vars.insert(Tvarmap::value_type(varnames.query((*it).first),
(*it).second));
// copy indices
for (Tindexmap::const_iterator it = da.indices.begin();
it != da.indices.end(); ++it)
indices.insert(Tindexmap::value_type((*it).first,
varnames.query((*it).second)));
}
int DynamicAtoms::check(const char* name) const
{
if (is_string_constant(name))
return Constants::check(name);
return check_variable(name);
}
int DynamicAtoms::check_variable(const char* name) const
{
string str;
int ll;
parse_variable(name, str, ll);
Tvarmap::const_iterator it = vars.find(str.c_str());
if (it != vars.end()) {
const Tlagmap& lmap = (*it).second;
Tlagmap::const_iterator itt = lmap.find(ll);
if (itt != lmap.end())
return (*itt).second;
}
return -1;
}
void DynamicAtoms::assign(const char* name, int t)
{
if (is_string_constant(name))
assign_constant(name, t);
else
assign_variable(name, t);
}
void DynamicAtoms::assign_constant(const char* name, int t)
{
double val;
sscanf(name, "%lf", &val);
add_constant(t, val);
}
// parse the name and then call assing_variable(varname, ll, t)
void DynamicAtoms::assign_variable(const char* name, int t)
{
int ll;
string str;
parse_variable(name, str, ll);
// here str is just name without lead/lag
const char* ss = varnames.insert(str.c_str());
assign_variable(ss, ll, t);
}
void DynamicAtoms::assign_variable(const char* varname, int ll, int t)
{
if (indices.end() != indices.find(t))
throw ogu::Exception(__FILE__,__LINE__,
"Attempt to assign already allocated tree index");
Tvarmap::iterator it = vars.find(varname);
if (it != vars.end()) {
Tlagmap& lmap = (*it).second;
if (lmap.end() != lmap.find(ll))
throw ogu::Exception(__FILE__,__LINE__,
"Attempt to assign already allocated variable");
lmap.insert(Tlagmap::value_type(ll, t));
} else {
Tlagmap lmap;
lmap.insert(Tlagmap::value_type(ll, t));
vars.insert(Tvarmap::value_type(varname, lmap));
}
indices.insert(Tindexmap::value_type(t, varname));
nv++;
if (ll < minlag)
minlag = ll;
if (ll > maxlead)
maxlead = ll;
}
void DynamicAtoms::unassign_variable(const char* varname, int ll, int t)
{
Tvarmap::iterator it = vars.find(varname);
if (it != vars.end()) {
Tlagmap& lmap = (*it).second;
Tlagmap::iterator itt = lmap.find(ll);
if (itt != lmap.end()) {
if ((*itt).second == t) {
// erase it from the lagmap; if it becomes empty,
// erase the lagmap from varmap
lmap.erase(itt);
if (lmap.size() == 0)
vars.erase(it);
// erase it from the indices
Tindexmap::iterator ittt = indices.find(t);
if (ittt != indices.end())
indices.erase(ittt);
nv--;
if (ll == minlag || ll == maxlead)
update_minmaxll();
} else
throw ogu::Exception(__FILE__,__LINE__,
"Tree index inconsistent in DynamicAtoms::unassign_variable");
} else
throw ogu::Exception(__FILE__,__LINE__,
"Lead/lag of the variable not found in DynamicAtoms::unassign_variable");
} else
throw ogu::Exception(__FILE__,__LINE__,
"Variable not found in DynamicAtoms::unassign_variable");
}
void DynamicAtoms::update_minmaxll()
{
minlag = INT_MAX;
maxlead =INT_MIN;
for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it) {
const Tlagmap& lmap = (*it).second;
for (Tlagmap::const_iterator itt = lmap.begin(); itt != lmap.end(); ++itt) {
int ll = (*itt).first;
if (ll < minlag)
minlag = ll;
if (ll > maxlead)
maxlead = ll;
}
}
}
vector<int> DynamicAtoms::variables() const
{
vector<int> res;
for (Tvarmap::const_iterator it = vars.begin();
it != vars.end(); ++it) {
const Tlagmap& lmap = (*it).second;
for (Tlagmap::const_iterator itt = lmap.begin();
itt != lmap.end(); ++itt)
res.push_back((*itt).second);
}
return res;
}
void DynamicAtoms::varspan(int t, int& mlead, int& mlag) const
{
Tindexmap::const_iterator it = indices.find(t);
if (indices.end() == it) {
mlead = INT_MIN;
mlag = INT_MAX;
return;
}
varspan((*it).second, mlead, mlag);
}
void DynamicAtoms::varspan(const char* name, int& mlead, int& mlag) const
{
Tvarmap::const_iterator it = vars.find(name);
if (vars.end() == it) {
mlead = INT_MIN;
mlag = INT_MAX;
return;
}
const Tlagmap& lmap = (*it).second;
Tlagmap::const_iterator beg = lmap.begin();
Tlagmap::const_reverse_iterator end = lmap.rbegin();
mlag = (*beg).first;
mlead = (*end).first;
}
void DynamicAtoms::varspan(const vector<const char*>& names, int& mlead, int& mlag) const
{
mlead = INT_MIN;
mlag = INT_MAX;
for (unsigned int i = 0; i < names.size(); i++) {
int lag, lead;
varspan(names[i], lead, lag);
if (lead > mlead)
mlead = lead;
if (lag < mlag)
mlag = lag;
}
}
bool DynamicAtoms::is_named_atom(int t) const
{
return (indices.end() != indices.find(t));
}
int DynamicAtoms::index(const char* name, int ll) const
{
Tvarmap::const_iterator it = vars.find(name);
if (vars.end() != it) {
const Tlagmap& lmap = (*it).second;
Tlagmap::const_iterator itt = lmap.find(ll);
if (lmap.end() != itt)
return (*itt).second;
}
return -1;
}
bool DynamicAtoms::is_referenced(const char* name) const
{
Tvarmap::const_iterator it = vars.find(name);
return it != vars.end();
}
const DynamicAtoms::Tlagmap& DynamicAtoms::lagmap(const char* name) const
{
Tvarmap::const_iterator it = vars.find(name);
if (vars.end() == it)
throw ogu::Exception(__FILE__,__LINE__,
std::string("Couldn't find the name ")
+ name + " in DynamicAtoms::lagmap");
return (*it).second;
}
const char* DynamicAtoms::name(int t) const
{
Tindexmap::const_iterator it = indices.find(t);
if (indices.end() == it)
throw ogu::Exception(__FILE__,__LINE__,
"Couldn't find tree index in DynamicAtoms::name");
return (*it).second;
}
int DynamicAtoms::lead(int t) const
{
const char* nam = name(t);
const Tlagmap& lmap = lagmap(nam);
Tlagmap::const_iterator it = lmap.begin();
while (it != lmap.end() && (*it).second != t)
++it;
if (lmap.end() == it)
throw ogu::Exception(__FILE__,__LINE__,
"Couldn't find the three index in DynamicAtoms::lead");
return (*it).first;
}
void DynamicAtoms::print() const
{
printf("names:\n");
varnames.print();
printf("constants:\n");
Constants::print();
printf("variables:\n");
for (Tvarmap::const_iterator it = vars.begin();
it != vars.end(); ++it) {
const Tlagmap& lmap = (*it).second;
for (Tlagmap::const_iterator itt = lmap.begin();
itt != lmap.end(); ++itt)
printf("$%d: %s(%d)\n", (*itt).second, (*it).first, (*itt).first);
}
printf("indices:\n");
for (Tindexmap::const_iterator it = indices.begin();
it != indices.end(); ++it)
printf("t=%d ==> %s\n", (*it).first, (*it).second);
}
/** Note that the str has been parsed by the lexicographic
* analyzer. It can be either a variable or a double. So it is easy to
* recognize it by the first character. */
bool DynamicAtoms::is_string_constant(const char* str)
{
return str[0] == '.' || str[0] == '-' || (str[0] >= '0' && str[0] <= '9');
}
VarOrdering::VarOrdering(const VarOrdering& vo, const vector<const char*>& vnames,
const DynamicAtoms& a)
: n_stat(vo.n_stat), n_pred(vo.n_pred), n_both(vo.n_both), n_forw(vo.n_forw),
der_atoms(vo.der_atoms), positions(vo.positions),
outer2y(vo.outer2y), y2outer(vo.y2outer), varnames(vnames), atoms(a)
{
}
bool VarOrdering::check(int t) const
{
map<int,int>::const_iterator it = positions.find(t);
return it != positions.end();
}
int VarOrdering::get_pos_of(int t) const
{
map<int,int>::const_iterator it = positions.find(t);
if (it != positions.end()) {
return (*it).second;
} else {
throw ogu::Exception(__FILE__,__LINE__,
"Couldn't find the tree index in VarOrdering::get_pos_of");
return -1;
}
}
void VarOrdering::do_general(ord_type ordering)
{
// auxiliary vectors for setting der_atoms and map
vector<int> pred_minus;
vector<int> both_minus;
vector<int> stat;
vector<int> pred_pad;
vector<int> both_pad;
vector<int> forw_pad;
vector<int> both_plus;
vector<int> forw_plus;
// auxiliary vectors for setting y2outer and outer2y
vector<int> y2o_stat;
vector<int> y2o_pred;
vector<int> y2o_both;
vector<int> y2o_forw;
for (unsigned int i = 0; i < varnames.size(); i++) {
const char* ss = varnames[i];
int lead;
int lag;
atoms.varspan(ss, lead, lag);
if (lag == 0 && lead == 0) {
stat.push_back(atoms.index(ss, 0));
y2o_stat.push_back(i);
} else if (lag == -1 && lead < 1) {
pred_minus.push_back(atoms.index(ss, -1));
pred_pad.push_back(atoms.index(ss, 0));
y2o_pred.push_back(i);
} else if (lag > -1 && lead == 1) {
forw_pad.push_back(atoms.index(ss, 0));
forw_plus.push_back(atoms.index(ss, 1));
y2o_forw.push_back(i);
} else if (lag == -1 && lead == 1) {
both_minus.push_back(atoms.index(ss, -1));
both_pad.push_back(atoms.index(ss, 0));
both_plus.push_back(atoms.index(ss, 1));
y2o_both.push_back(i);
} else {
throw ogu::Exception(__FILE__,__LINE__,
"A wrong lag/lead of a variable in VarOrdering::do_pbspbfbf");
}
}
// here we fill ords according to ordering
vector<int>* ords[8];
if (ordering == pbspbfbf) {
ords[0] = &pred_minus;
ords[1] = &both_minus;
ords[2] = &stat;
ords[3] = &pred_pad;
ords[4] = &both_pad;
ords[5] = &forw_pad;
ords[6] = &both_plus;
ords[7] = &forw_plus;
} else if (ordering == bfspbfpb) {
ords[0] = &both_plus;
ords[1] = &forw_plus;
ords[2] = &stat;
ords[3] = &pred_pad;
ords[4] = &both_pad;
ords[5] = &forw_pad;
ords[6] = &pred_minus;
ords[7] = &both_minus;
} else { // BEWARE: when implementing a new ordering, check also a
// code below setting y2outer
throw ogu::Exception(__FILE__,__LINE__,
"Ordering not implemented in VarOrdering::do_general");
}
// make der_atoms and positions
int off = 0;
for (unsigned int i = 0; i < 8; i++)
for (unsigned int j = 0; j < (ords[i])->size(); j++, off++)
if ((*(ords[i]))[j] != -1) {
der_atoms.push_back((*(ords[i]))[j]);
positions.insert(std::pair<int,int>((*(ords[i]))[j], off));
}
// set integer constants
n_stat = stat.size();
n_pred = pred_pad.size();
n_both = both_pad.size();
n_forw = forw_pad.size();
// make y2outer mapping
y2outer.insert(y2outer.end(), y2o_stat.begin(), y2o_stat.end());
y2outer.insert(y2outer.end(), y2o_pred.begin(), y2o_pred.end());
y2outer.insert(y2outer.end(), y2o_both.begin(), y2o_both.end());
y2outer.insert(y2outer.end(), y2o_forw.begin(), y2o_forw.end());
// make outer2y mapping
outer2y.resize(y2outer.size(), -1);
for (unsigned int i = 0; i < y2outer.size(); i++)
outer2y[y2outer[i]] = i;
}
void VarOrdering::do_increasing_time()
{
// get maxlead and minlag of the variables
int mlag, mlead;
atoms.varspan(varnames, mlead, mlag);
// setup the matrix of tree indices, if there is no occurrence,
// the index is set to -1
vector<int> ll_init(varnames.size(), -1);
vector<vector<int> > tree_ind(mlead-mlag+1, ll_init);
for (unsigned int iv = 0; iv < varnames.size(); iv++) {
try {
const DynamicAtoms::Tlagmap& lmap = atoms.lagmap(varnames[iv]);
for (DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it) {
int ll = (*it).first;
int t = (*it).second;
tree_ind[ll-mlag][iv] = t;
}
} catch (const ogu::Exception& e) {
// ignore the error of not found variable in the tree
}
}
// setup der_atoms and positions
for (int ll = mlag; ll <= mlead; ll++)
for (unsigned int iv = 0; iv < varnames.size(); iv++) {
int t = tree_ind[ll-mlag][iv];
if (t != -1) {
der_atoms.push_back(t);
int pos = (ll-mlag)*varnames.size() + iv;
positions.insert(map<int,int>::value_type(t, pos));
}
}
// set outer2y and y2outer to identities
for (unsigned int iv = 0; iv < varnames.size(); iv++) {
outer2y.push_back(iv);
y2outer.push_back(iv);
}
// set n_stat, n_pred, n_both, and n_forw
for (unsigned int iv = 0; iv < varnames.size(); iv++) {
int mmlag, mmlead;
atoms.varspan(varnames[iv], mmlead, mmlag);
if (mmlead == 0 && mmlag == 0) {
n_stat++;
} else if (mmlead <= 0 && mmlag < 0) {
n_pred++;
} else if (mmlead > 0 && mmlag >=0) {
n_forw++;
} else if (mmlead > 0 && mmlag < 0) {
n_both++;
} else if (mmlead < mmlag) {
// variable does not occur in the tree, cound as static
n_stat++;
} else {
throw ogu::Exception(__FILE__,__LINE__,
"A wrong lag/lead of a variable in VarOrdering::do_increasing_time");
}
}
}
void VarOrdering::print() const
{
printf("nstat=%d, npred=%d, nboth=%d, nforw=%d\n", n_stat, n_pred, n_both, n_forw);
printf("der_atoms:\n");
for (unsigned int i = 0; i < der_atoms.size(); i++)
printf(" %d", der_atoms[i]);
printf("\nmap:\n");
for (map<int,int>::const_iterator it = positions.begin(); it != positions.end(); ++it)
printf(" [%d->%d]", (*it).first, (*it).second);
printf("\ny2outer:\n");
for (unsigned int i = 0; i < y2outer.size(); i++)
printf(" %d", y2outer[i]);
printf("\nouter2y:\n");
for (unsigned int i = 0; i < outer2y.size(); i++)
printf(" %d", outer2y[i]);
printf("\n");
}
// Local Variables:
// mode:C++
// End:

View File

@ -5,7 +5,7 @@
#ifndef OGP_DYNAMIC_ATOMS_H
#define OGP_DYNAMIC_ATOMS_H
#include "formula_parser.h"
#include "formula_parser.hh"
#include <vector>
#include <map>

View File

@ -0,0 +1,555 @@
// Copyright (C) 2005, Ondra Kamenik
// $Id: fine_atoms.cpp 1759 2008-03-31 14:25:20Z kamenik $
#include "utils/cc/exception.hh"
#include "parser_exception.hh"
#include "fine_atoms.hh"
using namespace ogp;
AllvarOuterOrdering::AllvarOuterOrdering(const vector<const char *> &allvar_outer,
const FineAtoms &a)
: atoms(a), allvar(),
endo2all(a.get_endovars().size(), -1),
exo2all(a.get_exovars().size(), -1)
{
// fill in the allvar from allvar_outer
for (unsigned int i = 0; i < allvar_outer.size(); i++)
{
const char *s = atoms.varnames.query(allvar_outer[i]);
if (s)
allvar.push_back(s);
else
throw ogu::Exception(__FILE__, __LINE__,
string("Variable ") + allvar_outer[i] + " is not a declared symbol in AllvarOuterOrdering constructor");
}
// fill in endo2all and exo2all
for (unsigned int i = 0; i < allvar.size(); i++)
{
Tvarintmap::const_iterator it = atoms.endo_outer_map.find(allvar[i]);
if (it != atoms.endo_outer_map.end())
endo2all[(*it).second] = i;
else
{
it = atoms.exo_outer_map.find(allvar[i]);
if (it != atoms.exo_outer_map.end())
exo2all[(*it).second] = i;
else
throw ogu::Exception(__FILE__, __LINE__,
string("Name ") + allvar[i] + " is neither endogenous nor exogenous variable in AllvarOuterOrdering constructor");
}
}
// check whether everything has been filled
unsigned int iendo = 0;
while (iendo < endo2all.size() && endo2all[iendo] != -1)
iendo++;
unsigned int iexo = 0;
while (iexo < exo2all.size() && exo2all[iexo] != -1)
iexo++;
if (iendo < endo2all.size())
throw ogu::Exception(__FILE__, __LINE__,
string("Endogenous variable ") + atoms.get_endovars()[iendo]
+" not found in outer all ordering in AllvarOuterOrdering constructor");
if (iexo < exo2all.size())
throw ogu::Exception(__FILE__, __LINE__,
string("Exogenous variable ") + atoms.get_exovars()[iexo]
+" not found in outer all ordering in AllvarOuterOrdering constructor");
}
AllvarOuterOrdering::AllvarOuterOrdering(const AllvarOuterOrdering &avo,
const FineAtoms &a)
: atoms(a), allvar(),
endo2all(avo.endo2all),
exo2all(avo.exo2all)
{
// fill in the allvar from avo.allvar
for (unsigned int i = 0; i < avo.allvar.size(); i++)
{
const char *s = atoms.varnames.query(avo.allvar[i]);
allvar.push_back(s);
}
}
FineAtoms::FineAtoms(const FineAtoms &fa)
: DynamicAtoms(fa), params(), endovars(), exovars(),
endo_order(NULL), exo_order(NULL), allvar_order(NULL),
der_atoms(fa.der_atoms),
endo_atoms_map(fa.endo_atoms_map),
exo_atoms_map(fa.exo_atoms_map)
{
// fill in params
for (unsigned int i = 0; i < fa.params.size(); i++)
{
const char *s = varnames.query(fa.params[i]);
if (!s)
throw ogu::Exception(__FILE__, __LINE__,
string("Parameter ") + fa.params[i] + " does not exist in FineAtoms copy cosntructor");
params.push_back(s);
param_outer_map.insert(Tvarintmap::value_type(s, params.size()-1));
}
// fill in endovars
for (unsigned int i = 0; i < fa.endovars.size(); i++)
{
const char *s = varnames.query(fa.endovars[i]);
if (!s)
throw ogu::Exception(__FILE__, __LINE__,
string("Endo variable ") + fa.endovars[i] + " does not exist in FineAtoms copy constructor");
endovars.push_back(s);
endo_outer_map.insert(Tvarintmap::value_type(s, endovars.size()-1));
}
// fill in exovars
for (unsigned int i = 0; i < fa.exovars.size(); i++)
{
const char *s = varnames.query(fa.exovars[i]);
if (!s)
throw ogu::Exception(__FILE__, __LINE__,
string("Exo variable ") + fa.exovars[i] + " does not exist in FineAtoms copy cosntructor");
exovars.push_back(s);
exo_outer_map.insert(Tvarintmap::value_type(s, exovars.size()-1));
}
if (fa.endo_order)
endo_order = fa.endo_order->clone(endovars, *this);
if (fa.exo_order)
exo_order = fa.exo_order->clone(exovars, *this);
if (fa.allvar_order)
allvar_order = new AllvarOuterOrdering(*(fa.allvar_order), *this);
}
int
FineAtoms::check_variable(const char *name) const
{
string str;
int ll;
parse_variable(name, str, ll);
if (varnames.query(str.c_str()))
return DynamicAtoms::check_variable(name);
else
{
throw ParserException(string("Variable <")+str+"> not declared.", 0);
return -1;
}
}
int
FineAtoms::num_exo_periods() const
{
int mlead, mlag;
exovarspan(mlead, mlag);
return mlead-mlag+1;
}
void
FineAtoms::parsing_finished(VarOrdering::ord_type ot)
{
make_internal_orderings(ot);
// by default, concatenate outer endo and outer exo and make it as
// allvar outer:
vector<const char *> allvar_tmp;
allvar_tmp.insert(allvar_tmp.end(), endovars.begin(), endovars.end());
allvar_tmp.insert(allvar_tmp.end(), exovars.begin(), exovars.end());
if (allvar_order)
delete allvar_order;
allvar_order = new AllvarOuterOrdering(allvar_tmp, *this);
}
void
FineAtoms::parsing_finished(VarOrdering::ord_type ot,
const vector<const char *> allvar)
{
make_internal_orderings(ot);
if (allvar_order)
delete allvar_order;
allvar_order = new AllvarOuterOrdering(allvar, *this);
}
const vector<const char *> &
FineAtoms::get_allvar() const
{
if (!allvar_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::get_allvars called before parsing_finished");
return allvar_order->get_allvar();
}
const vector<int> &
FineAtoms::outer_endo2all() const
{
if (!allvar_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::outer_endo2all called before parsing_finished");
return allvar_order->get_endo2all();
}
const vector<int> &
FineAtoms::outer_exo2all() const
{
if (!allvar_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::outer_exo2all called before parsing_finished");
return allvar_order->get_exo2all();
}
vector<int>
FineAtoms::variables() const
{
if (endo_order)
{
return der_atoms;
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::variables called before parsing_finished");
return vector<int>();
}
}
int
FineAtoms::nstat() const
{
if (endo_order)
{
return endo_order->nstat();
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::nstat called before parsing_finished");
return -1;
}
}
int
FineAtoms::npred() const
{
if (endo_order)
{
return endo_order->npred();
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::npred called before parsing_finished");
return -1;
}
}
int
FineAtoms::nboth() const
{
if (endo_order)
{
return endo_order->nboth();
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::nboth called before parsing_finished");
return -1;
}
}
int
FineAtoms::nforw() const
{
if (endo_order)
{
return endo_order->nforw();
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::nforw called before parsing_finished");
return -1;
}
}
int
FineAtoms::get_pos_of_endo(int t) const
{
if (endo_order)
{
return endo_order->get_pos_of(t);
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::get_pos_of_endo called before parsing_finished");
return -1;
}
}
int
FineAtoms::get_pos_of_exo(int t) const
{
if (exo_order)
{
return exo_order->get_pos_of(t);
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::get_pos_of_exo called before parsing_finished");
return -1;
}
}
int
FineAtoms::get_pos_of_all(int t) const
{
if (endo_order && exo_order)
{
if (endo_order->check(t))
return endo_order->get_pos_of(t);
else if (exo_order->check(t))
return endo_order->length() + exo_order->get_pos_of(t);
else
{
throw ogu::Exception(__FILE__, __LINE__,
"Atom is not endo nor exo in FineAtoms::get_pos_of_all");
return -1;
}
}
else
{
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::get_pos_of_exo called before parsing_finished");
return -1;
}
}
const vector<int> &
FineAtoms::y2outer_endo() const
{
if (!endo_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::y2outer_endo called before parsing_finished");
return endo_order->get_y2outer();
}
const vector<int> &
FineAtoms::outer2y_endo() const
{
if (!endo_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::outer2y_endo called before parsing_finished");
return endo_order->get_outer2y();
}
const vector<int> &
FineAtoms::y2outer_exo() const
{
if (!exo_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::y2outer_endo called before parsing_finished");
return exo_order->get_y2outer();
}
const vector<int> &
FineAtoms::outer2y_exo() const
{
if (!exo_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::outer2y_exo called before parsing_finished");
return exo_order->get_outer2y();
}
const vector<int> &
FineAtoms::get_endo_atoms_map() const
{
if (!endo_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::get_endo_atoms_map called before parsing_finished");
return endo_atoms_map;
}
const vector<int> &
FineAtoms::get_exo_atoms_map() const
{
if (!exo_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::get_exo_atoms_map called before parsing_finished");
return exo_atoms_map;
}
int
FineAtoms::name2outer_param(const char *name) const
{
Tvarintmap::const_iterator it = param_outer_map.find(name);
if (it == param_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not a parameter in FineAtoms::name2outer_param");
return (*it).second;
}
int
FineAtoms::name2outer_endo(const char *name) const
{
Tvarintmap::const_iterator it = endo_outer_map.find(name);
if (it == endo_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not an endogenous variable in FineAtoms::name2outer_endo");
return (*it).second;
}
int
FineAtoms::name2outer_exo(const char *name) const
{
Tvarintmap::const_iterator it = exo_outer_map.find(name);
if (it == exo_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not an exogenous variable in FineAtoms::name2outer_exo");
return (*it).second;
}
int
FineAtoms::name2outer_allvar(const char *name) const
{
if (!allvar_order)
throw ogu::Exception(__FILE__, __LINE__,
"FineAtoms::name2outer_allvar called beore parsing_finished");
Tvarintmap::const_iterator it = endo_outer_map.find(name);
if (it != endo_outer_map.end())
return allvar_order->get_endo2all()[(*it).second];
else
{
it = exo_outer_map.find(name);
if (it != exo_outer_map.end())
return allvar_order->get_exo2all()[(*it).second];
}
throw ogu::Exception(__FILE__, __LINE__,
string("Name ") + name + " is neither endo nor exo variable in FineAtoms::name2outer_allvar");
return -1;
}
void
FineAtoms::register_uniq_endo(const char *name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Endogenous variable <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
endovars.push_back(ss);
endo_outer_map.insert(Tvarintmap::value_type(ss, endovars.size()-1));
}
void
FineAtoms::register_uniq_exo(const char *name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Exogenous variable <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
exovars.push_back(ss);
exo_outer_map.insert(Tvarintmap::value_type(ss, exovars.size()-1));
}
void
FineAtoms::register_uniq_param(const char *name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Parameter <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
params.push_back(ss);
param_outer_map.insert(Tvarintmap::value_type(ss, params.size()-1));
}
void
FineAtoms::make_internal_orderings(VarOrdering::ord_type ot)
{
bool endo_ordering_done = false;
bool exo_ordering_done = false;
order_type = ot;
int mlead, mlag;
endovarspan(mlead, mlag);
if (mlag >= -1 && mlead <= 1)
{
// make endo ordering
if (endo_order)
delete endo_order;
if (ot == VarOrdering::pbspbfbf)
endo_order = new EndoVarOrdering1(endovars, *this);
else
endo_order = new EndoVarOrdering2(endovars, *this);
endo_order->do_ordering();
endo_ordering_done = true;
}
exovarspan(mlead, mlag);
if (mlag == 0 && mlead == 0)
{
// make exo ordering
if (exo_order)
delete exo_order;
exo_order = new ExoVarOrdering(exovars, *this);
exo_order->do_ordering();
exo_ordering_done = true;
}
if (endo_ordering_done && exo_ordering_done)
{
// concatenate der atoms from endo_order and exo_order
der_atoms.clear();
der_atoms.insert(der_atoms.end(),
endo_order->get_der_atoms().begin(),
endo_order->get_der_atoms().end());
der_atoms.insert(der_atoms.end(),
exo_order->get_der_atoms().begin(),
exo_order->get_der_atoms().end());
// create endo_atoms_map; der_atoms is a concatenation, so it is easy
int endo_atoms = endo_order->get_der_atoms().size();
endo_atoms_map.clear();
for (int i = 0; i < endo_atoms; i++)
endo_atoms_map.push_back(i);
// create exo_atoms_map
int exo_atoms = exo_order->get_der_atoms().size();
exo_atoms_map.clear();
for (int i = 0; i < exo_atoms; i++)
exo_atoms_map.push_back(endo_atoms + i);
}
}
void
FineAtoms::print() const
{
DynamicAtoms::print();
if (endo_order)
{
printf("Endo ordering:\n");
endo_order->print();
}
else
{
printf("Endo ordering not created.\n");
}
if (exo_order)
{
printf("Exo ordering:\n");
exo_order->print();
}
else
{
printf("Exo ordering not created.\n");
}
printf("endo atoms map:\n");
for (unsigned int i = 0; i < endo_atoms_map.size(); i++)
printf("%d --> %d\n", i, endo_atoms_map[i]);
printf("exo atoms map:\n");
for (unsigned int i = 0; i < exo_atoms_map.size(); i++)
printf("%d --> %d\n", i, exo_atoms_map[i]);
}

View File

@ -1,482 +0,0 @@
// Copyright (C) 2005, Ondra Kamenik
// $Id: fine_atoms.cpp 1759 2008-03-31 14:25:20Z kamenik $
#include "utils/cc/exception.h"
#include "parser_exception.h"
#include "fine_atoms.h"
using namespace ogp;
AllvarOuterOrdering::AllvarOuterOrdering(const vector<const char*>& allvar_outer,
const FineAtoms& a)
: atoms(a), allvar(),
endo2all(a.get_endovars().size(), -1),
exo2all(a.get_exovars().size(), -1)
{
// fill in the allvar from allvar_outer
for (unsigned int i = 0; i < allvar_outer.size(); i++) {
const char* s = atoms.varnames.query(allvar_outer[i]);
if (s)
allvar.push_back(s);
else
throw ogu::Exception(__FILE__, __LINE__,
string("Variable ") + allvar_outer[i] + " is not a declared symbol in AllvarOuterOrdering constructor");
}
// fill in endo2all and exo2all
for (unsigned int i = 0; i < allvar.size(); i++) {
Tvarintmap::const_iterator it = atoms.endo_outer_map.find(allvar[i]);
if (it != atoms.endo_outer_map.end())
endo2all[(*it).second] = i;
else {
it = atoms.exo_outer_map.find(allvar[i]);
if (it != atoms.exo_outer_map.end())
exo2all[(*it).second] = i;
else
throw ogu::Exception(__FILE__, __LINE__,
string("Name ") + allvar[i] + " is neither endogenous nor exogenous variable in AllvarOuterOrdering constructor");
}
}
// check whether everything has been filled
unsigned int iendo = 0;
while (iendo < endo2all.size() && endo2all[iendo] != -1) iendo++;
unsigned int iexo = 0;
while (iexo < exo2all.size() && exo2all[iexo] != -1) iexo++;
if (iendo < endo2all.size())
throw ogu::Exception(__FILE__, __LINE__,
string("Endogenous variable ") + atoms.get_endovars()[iendo] +
" not found in outer all ordering in AllvarOuterOrdering constructor");
if (iexo < exo2all.size())
throw ogu::Exception(__FILE__, __LINE__,
string("Exogenous variable ") + atoms.get_exovars()[iexo] +
" not found in outer all ordering in AllvarOuterOrdering constructor");
}
AllvarOuterOrdering::AllvarOuterOrdering(const AllvarOuterOrdering& avo,
const FineAtoms& a)
: atoms(a), allvar(),
endo2all(avo.endo2all),
exo2all(avo.exo2all)
{
// fill in the allvar from avo.allvar
for (unsigned int i = 0; i < avo.allvar.size(); i++) {
const char* s = atoms.varnames.query(avo.allvar[i]);
allvar.push_back(s);
}
}
FineAtoms::FineAtoms(const FineAtoms& fa)
: DynamicAtoms(fa), params(), endovars(), exovars(),
endo_order(NULL), exo_order(NULL), allvar_order(NULL),
der_atoms(fa.der_atoms),
endo_atoms_map(fa.endo_atoms_map),
exo_atoms_map(fa.exo_atoms_map)
{
// fill in params
for (unsigned int i = 0; i < fa.params.size(); i++) {
const char* s = varnames.query(fa.params[i]);
if (! s)
throw ogu::Exception(__FILE__, __LINE__,
string("Parameter ") + fa.params[i] + " does not exist in FineAtoms copy cosntructor");
params.push_back(s);
param_outer_map.insert(Tvarintmap::value_type(s, params.size()-1));
}
// fill in endovars
for (unsigned int i = 0; i < fa.endovars.size(); i++) {
const char* s = varnames.query(fa.endovars[i]);
if (! s)
throw ogu::Exception(__FILE__, __LINE__,
string("Endo variable ") + fa.endovars[i] + " does not exist in FineAtoms copy constructor");
endovars.push_back(s);
endo_outer_map.insert(Tvarintmap::value_type(s, endovars.size()-1));
}
// fill in exovars
for (unsigned int i = 0; i < fa.exovars.size(); i++) {
const char* s = varnames.query(fa.exovars[i]);
if (! s)
throw ogu::Exception(__FILE__, __LINE__,
string("Exo variable ") + fa.exovars[i] + " does not exist in FineAtoms copy cosntructor");
exovars.push_back(s);
exo_outer_map.insert(Tvarintmap::value_type(s, exovars.size()-1));
}
if (fa.endo_order)
endo_order = fa.endo_order->clone(endovars, *this);
if (fa.exo_order)
exo_order = fa.exo_order->clone(exovars, *this);
if (fa.allvar_order)
allvar_order = new AllvarOuterOrdering(*(fa.allvar_order), *this);
}
int FineAtoms::check_variable(const char* name) const
{
string str;
int ll;
parse_variable(name, str, ll);
if (varnames.query(str.c_str()))
return DynamicAtoms::check_variable(name);
else {
throw ParserException(string("Variable <")+str+"> not declared.",0);
return -1;
}
}
int FineAtoms::num_exo_periods() const
{
int mlead, mlag;
exovarspan(mlead, mlag);
return mlead-mlag+1;
}
void FineAtoms::parsing_finished(VarOrdering::ord_type ot)
{
make_internal_orderings(ot);
// by default, concatenate outer endo and outer exo and make it as
// allvar outer:
vector<const char*> allvar_tmp;
allvar_tmp.insert(allvar_tmp.end(), endovars.begin(), endovars.end());
allvar_tmp.insert(allvar_tmp.end(), exovars.begin(), exovars.end());
if (allvar_order)
delete allvar_order;
allvar_order = new AllvarOuterOrdering(allvar_tmp, *this);
}
void FineAtoms::parsing_finished(VarOrdering::ord_type ot,
const vector<const char*> allvar)
{
make_internal_orderings(ot);
if (allvar_order)
delete allvar_order;
allvar_order = new AllvarOuterOrdering(allvar, *this);
}
const vector<const char*>& FineAtoms::get_allvar() const
{
if (! allvar_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::get_allvars called before parsing_finished");
return allvar_order->get_allvar();
}
const vector<int>& FineAtoms::outer_endo2all() const
{
if (! allvar_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::outer_endo2all called before parsing_finished");
return allvar_order->get_endo2all();
}
const vector<int>& FineAtoms::outer_exo2all() const
{
if (! allvar_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::outer_exo2all called before parsing_finished");
return allvar_order->get_exo2all();
}
vector<int> FineAtoms::variables() const
{
if (endo_order) {
return der_atoms;
} else {
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::variables called before parsing_finished");
return vector<int>();
}
}
int FineAtoms::nstat() const
{
if (endo_order) {
return endo_order->nstat();
} else {
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::nstat called before parsing_finished");
return -1;
}
}
int FineAtoms::npred() const
{
if (endo_order) {
return endo_order->npred();
} else {
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::npred called before parsing_finished");
return -1;
}
}
int FineAtoms::nboth() const
{
if (endo_order) {
return endo_order->nboth();
} else {
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::nboth called before parsing_finished");
return -1;
}
}
int FineAtoms::nforw() const
{
if (endo_order) {
return endo_order->nforw();
} else {
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::nforw called before parsing_finished");
return -1;
}
}
int FineAtoms::get_pos_of_endo(int t) const
{
if (endo_order) {
return endo_order->get_pos_of(t);
} else {
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::get_pos_of_endo called before parsing_finished");
return -1;
}
}
int FineAtoms::get_pos_of_exo(int t) const
{
if (exo_order) {
return exo_order->get_pos_of(t);
} else {
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::get_pos_of_exo called before parsing_finished");
return -1;
}
}
int FineAtoms::get_pos_of_all(int t) const
{
if (endo_order && exo_order) {
if (endo_order->check(t))
return endo_order->get_pos_of(t);
else if (exo_order->check(t))
return endo_order->length() + exo_order->get_pos_of(t);
else {
throw ogu::Exception(__FILE__,__LINE__,
"Atom is not endo nor exo in FineAtoms::get_pos_of_all");
return -1;
}
} else {
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::get_pos_of_exo called before parsing_finished");
return -1;
}
}
const vector<int>& FineAtoms::y2outer_endo() const
{
if (! endo_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::y2outer_endo called before parsing_finished");
return endo_order->get_y2outer();
}
const vector<int>& FineAtoms::outer2y_endo() const
{
if (! endo_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::outer2y_endo called before parsing_finished");
return endo_order->get_outer2y();
}
const vector<int>& FineAtoms::y2outer_exo() const
{
if (! exo_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::y2outer_endo called before parsing_finished");
return exo_order->get_y2outer();
}
const vector<int>& FineAtoms::outer2y_exo() const
{
if (! exo_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::outer2y_exo called before parsing_finished");
return exo_order->get_outer2y();
}
const vector<int>& FineAtoms::get_endo_atoms_map() const
{
if (! endo_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::get_endo_atoms_map called before parsing_finished");
return endo_atoms_map;
}
const vector<int>& FineAtoms::get_exo_atoms_map() const
{
if (! exo_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::get_exo_atoms_map called before parsing_finished");
return exo_atoms_map;
}
int FineAtoms::name2outer_param(const char* name) const
{
Tvarintmap::const_iterator it = param_outer_map.find(name);
if (it == param_outer_map.end())
throw ogu::Exception(__FILE__,__LINE__,
"Name is not a parameter in FineAtoms::name2outer_param");
return (*it).second;
}
int FineAtoms::name2outer_endo(const char* name) const
{
Tvarintmap::const_iterator it = endo_outer_map.find(name);
if (it == endo_outer_map.end())
throw ogu::Exception(__FILE__,__LINE__,
"Name is not an endogenous variable in FineAtoms::name2outer_endo");
return (*it).second;
}
int FineAtoms::name2outer_exo(const char* name) const
{
Tvarintmap::const_iterator it = exo_outer_map.find(name);
if (it == exo_outer_map.end())
throw ogu::Exception(__FILE__,__LINE__,
"Name is not an exogenous variable in FineAtoms::name2outer_exo");
return (*it).second;
}
int FineAtoms::name2outer_allvar(const char* name) const
{
if (! allvar_order)
throw ogu::Exception(__FILE__,__LINE__,
"FineAtoms::name2outer_allvar called beore parsing_finished");
Tvarintmap::const_iterator it = endo_outer_map.find(name);
if (it != endo_outer_map.end())
return allvar_order->get_endo2all()[(*it).second];
else {
it = exo_outer_map.find(name);
if (it != exo_outer_map.end())
return allvar_order->get_exo2all()[(*it).second];
}
throw ogu::Exception(__FILE__,__LINE__,
string("Name ") + name + " is neither endo nor exo variable in FineAtoms::name2outer_allvar");
return -1;
}
void FineAtoms::register_uniq_endo(const char* name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Endogenous variable <")+name+"> is not unique.",0);
const char* ss = varnames.insert(name);
endovars.push_back(ss);
endo_outer_map.insert(Tvarintmap::value_type(ss, endovars.size()-1));
}
void FineAtoms::register_uniq_exo(const char* name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Exogenous variable <")+name+"> is not unique.",0);
const char* ss = varnames.insert(name);
exovars.push_back(ss);
exo_outer_map.insert(Tvarintmap::value_type(ss, exovars.size()-1));
}
void FineAtoms::register_uniq_param(const char* name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Parameter <")+name+"> is not unique.",0);
const char* ss = varnames.insert(name);
params.push_back(ss);
param_outer_map.insert(Tvarintmap::value_type(ss, params.size()-1));
}
void FineAtoms::make_internal_orderings(VarOrdering::ord_type ot)
{
bool endo_ordering_done = false;
bool exo_ordering_done = false;
order_type = ot;
int mlead, mlag;
endovarspan(mlead, mlag);
if (mlag >= -1 && mlead <= 1) {
// make endo ordering
if (endo_order)
delete endo_order;
if (ot == VarOrdering::pbspbfbf)
endo_order = new EndoVarOrdering1(endovars, *this);
else
endo_order = new EndoVarOrdering2(endovars, *this);
endo_order->do_ordering();
endo_ordering_done = true;
}
exovarspan(mlead, mlag);
if (mlag == 0 && mlead == 0) {
// make exo ordering
if (exo_order)
delete exo_order;
exo_order = new ExoVarOrdering(exovars, *this);
exo_order->do_ordering();
exo_ordering_done = true;
}
if (endo_ordering_done && exo_ordering_done) {
// concatenate der atoms from endo_order and exo_order
der_atoms.clear();
der_atoms.insert(der_atoms.end(),
endo_order->get_der_atoms().begin(),
endo_order->get_der_atoms().end());
der_atoms.insert(der_atoms.end(),
exo_order->get_der_atoms().begin(),
exo_order->get_der_atoms().end());
// create endo_atoms_map; der_atoms is a concatenation, so it is easy
int endo_atoms = endo_order->get_der_atoms().size();
endo_atoms_map.clear();
for (int i = 0; i < endo_atoms; i++)
endo_atoms_map.push_back(i);
// create exo_atoms_map
int exo_atoms = exo_order->get_der_atoms().size();
exo_atoms_map.clear();
for (int i = 0; i < exo_atoms; i++)
exo_atoms_map.push_back(endo_atoms + i);
}
}
void FineAtoms::print() const
{
DynamicAtoms::print();
if (endo_order) {
printf("Endo ordering:\n");
endo_order->print();
} else {
printf("Endo ordering not created.\n");
}
if (exo_order) {
printf("Exo ordering:\n");
exo_order->print();
} else {
printf("Exo ordering not created.\n");
}
printf("endo atoms map:\n");
for (unsigned int i = 0; i < endo_atoms_map.size(); i++)
printf("%d --> %d\n", i, endo_atoms_map[i]);
printf("exo atoms map:\n");
for (unsigned int i = 0; i < exo_atoms_map.size(); i++)
printf("%d --> %d\n", i, exo_atoms_map[i]);
}

View File

@ -5,7 +5,7 @@
#ifndef OGP_FINE_ATOMS_H
#define OGP_FINE_ATOMS_H
#include "dynamic_atoms.h"
#include "dynamic_atoms.hh"
#include <vector>
#include <string>

View File

@ -1,5 +1,5 @@
%{
#include "location.h"
#include "location.hh"
#include "formula_tab.hh"
extern YYLTYPE fmla_lloc;

View File

@ -3,8 +3,8 @@
#include <cstdio>
#include "location.h"
#include "formula_parser.h"
#include "location.hh"
#include "formula_parser.hh"
#include "formula_tab.hh"
void fmla_error(const char*);

View File

@ -0,0 +1,566 @@
// Copyright (C) 2005, Ondra Kamenik
// $Id: formula_parser.cpp 2268 2008-11-22 10:38:03Z michel $
#include "utils/cc/pascal_triangle.hh"
#include "utils/cc/exception.hh"
#include "parser_exception.hh"
#include "location.hh"
#include "formula_parser.hh"
#include "formula_tab.hh"
#include <cmath>
using namespace ogp;
extern location_type fmla_lloc;
FormulaParser::FormulaParser(const FormulaParser &fp, Atoms &a)
: otree(fp.otree), atoms(a), formulas(fp.formulas), ders()
{
// create derivatives
for (unsigned int i = 0; i < fp.ders.size(); i++)
ders.push_back(new FormulaDerivatives(*(fp.ders[i])));
}
FormulaParser::~FormulaParser()
{
destroy_derivatives();
}
void
FormulaParser::differentiate(int max_order)
{
destroy_derivatives();
vector<int> vars;
vars = atoms.variables();
for (unsigned int i = 0; i < formulas.size(); i++)
ders.push_back(new FormulaDerivatives(otree, vars, formulas[i], max_order));
}
const FormulaDerivatives &
FormulaParser::derivatives(int i) const
{
if (i < (int) ders.size())
return *(ders[i]);
else
throw ogu::Exception(__FILE__, __LINE__,
"Wrong formula index in FormulaParser::derivatives");
return *(ders[0]); // just because of compiler
}
void
FormulaParser::add_formula(int t)
{
formulas.push_back(t);
}
int
FormulaParser::add_binary(code_t code, int t1, int t2)
{
return otree.add_binary(code, t1, t2);
}
int
FormulaParser::add_unary(code_t code, int t)
{
return otree.add_unary(code, t);
}
int
FormulaParser::add_nulary(const char *str)
{
int t = -1;
try
{
t = atoms.check(str);
}
catch (const ParserException &e)
{
throw ParserException(e, fmla_lloc.off);
}
if (t == -1)
{
t = otree.add_nulary();
atoms.assign(str, t);
}
return t;
}
void
FormulaParser::add_subst_formulas(const map<int, int> &subst, const FormulaParser &fp)
{
for (int i = 0; i < fp.nformulas(); i++)
{
int f = add_substitution(fp.formula(i), subst, fp);
add_formula(f);
}
}
void
FormulaParser::substitute_formulas(const map<int, int> &smap)
{
for (int i = 0; i < nformulas(); i++)
{
// make substitution and replace the formula for it
int f = add_substitution(formulas[i], smap);
formulas[i] = f;
// update the derivatives if any
if (i < (int) ders.size() && ders[i])
{
int order = ders[i]->get_order();
delete ders[i];
ders[i] = new FormulaDerivatives(otree, atoms.variables(), formulas[i], order);
}
}
}
/** Global symbols for passing info to parser. */
FormulaParser *fparser;
/** The declarations of functions defined in formula_ll.cc and
* formula_tab.cc generated from formula.lex and formula.y */
void *fmla__scan_buffer(char *, size_t);
void fmla__destroy_buffer(void *);
int fmla_parse();
extern location_type fmla_lloc;
/** This makes own copy of provided data, sets the buffer for the
* parser with fmla_scan_buffer, and launches fmla_parse(). Note that
* the pointer returned from fmla_scan_buffer must be freed at the
* end. */
void
FormulaParser::parse(int length, const char *stream)
{
char *buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
fmla_lloc.off = 0;
fmla_lloc.ll = 0;
void *p = fmla__scan_buffer(buffer, (unsigned int) length+2);
fparser = this;
fmla_parse();
delete [] buffer;
fmla__destroy_buffer(p);
}
void
FormulaParser::error(const char *mes) const
{
throw ParserException(mes, fmla_lloc.off);
}
int
FormulaParser::last_formula() const
{
int res = -1;
for (unsigned int i = 0; i < formulas.size(); i++)
if (res < formulas[i])
res = formulas[i];
return std::max(res, otree.get_last_nulary());
}
int
FormulaParser::pop_last_formula()
{
if (formulas.size() == 0)
return -1;
int t = formulas.back();
if (formulas.size() == ders.size())
{
delete ders.back();
ders.pop_back();
}
formulas.pop_back();
return t;
}
void
FormulaParser::print() const
{
atoms.print();
for (unsigned int i = 0; i < formulas.size(); i++)
{
printf("formula %d:\n", formulas[i]);
otree.print_operation(formulas[i]);
}
for (unsigned int i = 0; i < ders.size(); i++)
{
printf("derivatives for the formula %d:\n", formulas[i]);
ders[i]->print(otree);
}
}
void
FormulaParser::destroy_derivatives()
{
while (ders.size() > 0)
{
delete ders.back();
ders.pop_back();
}
}
/** This constructor makes a vector of indices for formulas
* corresponding to derivatives of the given formula. The formula is
* supposed to belong to the provided tree, the created derivatives
* are added to the tree.
*
* The algorithm is as follows. todo: update description of the
* algorithm
*/
FormulaDerivatives::FormulaDerivatives(OperationTree &otree,
const vector<int> &vars, int f, int max_order)
: nvar(vars.size()), order(max_order)
{
FoldMultiIndex fmi_zero(nvar);
tder.push_back(f);
indices.push_back(fmi_zero);
unsigned int last_order_beg = 0;
unsigned int last_order_end = tder.size();
for (int k = 1; k <= order; k++)
{
// interval <last_order_beg,last_order_end) is guaranteed
// here to contain at least one item
for (unsigned int run = last_order_beg; run < last_order_end; run++)
{
// shift one order from the run
FoldMultiIndex fmi(indices[run], 1);
// set starting variable from the run, note that if k=1,
// the shift order ctor of fmi will set it to zero
int ivar_start = fmi[k-1];
for (int ivar = ivar_start; ivar < nvar; ivar++, fmi.increment())
{
int der = otree.add_derivative(tder[run], vars[ivar]);
if (der != OperationTree::zero)
{
tder.push_back(der);
indices.push_back(fmi);
}
}
}
// set new last_order_beg and last_order_end
last_order_beg = last_order_end;
last_order_end = tder.size();
// if there was no new derivative, break out from the loop
if (last_order_beg >= last_order_end)
break;
}
// build ind2der map
for (unsigned int i = 0; i < indices.size(); i++)
ind2der.insert(Tfmiintmap::value_type(indices[i], i));
}
FormulaDerivatives::FormulaDerivatives(const FormulaDerivatives &fd)
: tder(fd.tder), indices(fd.indices), ind2der(fd.ind2der),
nvar(fd.nvar), order(fd.order)
{
}
int
FormulaDerivatives::derivative(const FoldMultiIndex &mi) const
{
if (mi.order() > order)
throw ogu::Exception(__FILE__, __LINE__,
"Wrong order of multi-index in FormulaDerivatives::derivative");
if (mi.nv() != nvar)
throw ogu::Exception(__FILE__, __LINE__,
"Wrong multi-index variables in FormulaDerivatives::derivative");
Tfmiintmap::const_iterator it = ind2der.find(mi);
if (it == ind2der.end())
return OperationTree::zero;
else
return tder[(*it).second];
}
void
FormulaDerivatives::print(const OperationTree &otree) const
{
for (Tfmiintmap::const_iterator it = ind2der.begin();
it != ind2der.end(); ++it)
{
printf("derivative ");
(*it).first.print();
printf(" is formula %d\n", tder[(*it).second]);
otree.print_operation(tder[(*it).second]);
}
}
void
FormulaCustomEvaluator::eval(const AtomValues &av, FormulaEvalLoader &loader)
{
etree.reset_all();
av.setValues(etree);
for (unsigned int i = 0; i < terms.size(); i++)
{
double res = etree.eval(terms[i]);
loader.load((int) i, res);
}
}
FoldMultiIndex::FoldMultiIndex(int nv)
: nvar(nv), ord(0), data(new int[ord])
{
}
FoldMultiIndex::FoldMultiIndex(int nv, int ordd, int ii)
: nvar(nv), ord(ordd), data(new int[ord])
{
for (int i = 0; i < ord; i++)
data[i] = ii;
}
/** Note that a monotone sequence mapped by monotone mapping yields a
* monotone sequence. */
FoldMultiIndex::FoldMultiIndex(int nv, const FoldMultiIndex &mi, const vector<int> &mp)
: nvar(nv), ord(mi.ord), data(new int[ord])
{
for (int i = 0; i < ord; i++)
{
if (i < ord-1 && mp[i+1] < mp[i])
throw ogu::Exception(__FILE__, __LINE__,
"Mapping not monotone in FoldMultiIndex constructor");
if (mp[mi[i]] >= nv || mp[mi[i]] < 0)
throw ogu::Exception(__FILE__, __LINE__,
"Mapping out of bounds in FoldMultiIndex constructor");
data[i] = mp[mi[i]];
}
}
FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex &fmi, int new_orders)
: nvar(fmi.nvar),
ord(fmi.ord+new_orders),
data(new int[ord])
{
memcpy(data, fmi.data, fmi.ord*sizeof(int));
int new_item = (fmi.ord > 0) ? fmi.data[fmi.ord-1] : 0;
for (int i = fmi.ord; i < ord; i++)
{
data[i] = new_item;
}
}
FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex &fmi)
: nvar(fmi.nvar),
ord(fmi.ord),
data(new int[fmi.ord])
{
memcpy(data, fmi.data, ord*sizeof(int));
}
const FoldMultiIndex &
FoldMultiIndex::operator=(const FoldMultiIndex &fmi)
{
if (ord != fmi.ord)
{
delete [] data;
data = new int[fmi.ord];
}
ord = fmi.ord;
nvar = fmi.nvar;
memcpy(data, fmi.data, ord*sizeof(int));
return *this;
}
bool
FoldMultiIndex::operator<(const FoldMultiIndex &fmi) const
{
if (nvar != fmi.nvar)
ogu::Exception(__FILE__, __LINE__,
"Different nvar in FoldMultiIndex::operator<");
if (ord < fmi.ord)
return true;
if (ord > fmi.ord)
return false;
int i = 0;
while (i < ord && data[i] == fmi.data[i])
i++;
if (i == ord)
return false;
else
return data[i] < fmi.data[i];
}
bool
FoldMultiIndex::operator==(const FoldMultiIndex &fmi) const
{
bool res = true;
res = res && (nvar == fmi.nvar) && (ord == fmi.ord);
if (res)
for (int i = 0; i < ord; i++)
if (data[i] != fmi.data[i])
return false;
return res;
}
void
FoldMultiIndex::increment()
{
if (ord == 0)
return;
int k = ord-1;
data[k]++;
while (k > 0 && data[k] == nvar)
{
data[k] = 0;
data[--k]++;
}
for (int kk = 1; kk < ord; kk++)
if (data[kk-1] > data[kk])
data[kk] = data[kk-1];
}
// For description of an algorithm for calculation of folded offset,
// see Tensor Library Documentation, Ondra Kamenik, 2005, description
// of FTensor::getOffsetRecurse().
int
FoldMultiIndex::offset() const
{
// make copy for the recursions
int *tmp = new int[ord];
for (int i = 0; i < ord; i++)
tmp[i] = data[i];
// call the recursive algorithm
int res = offset_recurse(tmp, ord, nvar);
delete [] tmp;
return res;
}
void
FoldMultiIndex::print() const
{
printf("[");
for (int i = 0; i < ord; i++)
printf("%d ", data[i]);
printf("]");
}
int
FoldMultiIndex::offset_recurse(int *data, int len, int nv)
{
if (len == 0)
return 0;
// calculate length of initial constant indices
int prefix = 1;
while (prefix < len && data[0] == data[prefix])
prefix++;
int m = data[0];
int s1 = ptriang.noverk(nv+len-1, len) - ptriang.noverk(nv-m+len-1, len);
// cancel m from the rest of the sequence
for (int i = prefix; i < len; i++)
data[i] -= m;
// calculate offset of the remaining sequence
int s2 = offset_recurse(data+prefix, len-prefix, nv-m);
// return the sum
return s1+s2;
}
bool
ltfmi::operator()(const FoldMultiIndex &i1, const FoldMultiIndex &i2) const
{
return i1 < i2;
}
FormulaDerEvaluator::FormulaDerEvaluator(const FormulaParser &fp)
: etree(fp.otree, -1)
{
for (unsigned int i = 0; i < fp.ders.size(); i++)
ders.push_back((const FormulaDerivatives *) (fp.ders[i]));
der_atoms = fp.atoms.variables();
}
void
FormulaDerEvaluator::eval(const AtomValues &av, FormulaDerEvalLoader &loader, int order)
{
if (ders.size() == 0)
return;
int maxorder = ders[0]->order;
if (order > maxorder)
throw ogu::Exception(__FILE__, __LINE__,
"Wrong order in FormulaDerEvaluator::eval");
etree.reset_all();
av.setValues(etree);
int *vars = new int[order];
for (unsigned int i = 0; i < ders.size(); i++)
{
for (FormulaDerivatives::Tfmiintmap::const_iterator it = ders[i]->ind2der.begin();
it != ders[i]->ind2der.end(); ++it)
{
const FoldMultiIndex &mi = (*it).first;
if (mi.order() == order)
{
// set vars from multiindex mi and variables
for (int k = 0; k < order; k++)
vars[k] = der_atoms[mi[k]];
// evaluate
double res = etree.eval(ders[i]->tder[(*it).second]);
// load
loader.load(i, order, vars, res);
}
}
}
delete [] vars;
}
void
FormulaDerEvaluator::eval(const vector<int> &mp, const AtomValues &av,
FormulaDerEvalLoader &loader, int order)
{
etree.reset_all();
av.setValues(etree);
int nvar_glob = der_atoms.size();
int nvar = mp.size();
int *vars = new int[order];
for (unsigned int i = 0; i < ders.size(); i++)
{
FoldMultiIndex mi(nvar, order);
do
{
// find index of the derivative in the tensor
FoldMultiIndex mi_glob(nvar_glob, mi, mp);
int der = ders[i]->derivative(mi_glob);
if (der != OperationTree::zero)
{
// set vars from the global multiindex
for (int k = 0; k < order; k++)
vars[k] = der_atoms[mi_glob[k]];
// evaluate derivative
double res = etree.eval(der);
// load
loader.load(i, order, vars, res);
}
mi.increment();
}
while (!mi.past_the_end());
}
delete [] vars;
}
// Local Variables:
// mode:C++
// End:

View File

@ -1,517 +0,0 @@
// Copyright (C) 2005, Ondra Kamenik
// $Id: formula_parser.cpp 2268 2008-11-22 10:38:03Z michel $
#include "utils/cc/pascal_triangle.h"
#include "utils/cc/exception.h"
#include "parser_exception.h"
#include "location.h"
#include "formula_parser.h"
#include "formula_tab.hh"
#include <cmath>
using namespace ogp;
extern location_type fmla_lloc;
FormulaParser::FormulaParser(const FormulaParser& fp, Atoms& a)
: otree(fp.otree), atoms(a), formulas(fp.formulas), ders()
{
// create derivatives
for (unsigned int i = 0; i < fp.ders.size(); i++)
ders.push_back(new FormulaDerivatives(*(fp.ders[i])));
}
FormulaParser::~FormulaParser()
{
destroy_derivatives();
}
void FormulaParser::differentiate(int max_order)
{
destroy_derivatives();
vector<int> vars;
vars = atoms.variables();
for (unsigned int i = 0; i < formulas.size(); i++)
ders.push_back(new FormulaDerivatives(otree, vars, formulas[i], max_order));
}
const FormulaDerivatives& FormulaParser::derivatives(int i) const
{
if (i < (int)ders.size())
return *(ders[i]);
else
throw ogu::Exception(__FILE__,__LINE__,
"Wrong formula index in FormulaParser::derivatives");
return *(ders[0]); // just because of compiler
}
void FormulaParser::add_formula(int t)
{
formulas.push_back(t);
}
int FormulaParser::add_binary(code_t code, int t1, int t2)
{
return otree.add_binary(code, t1, t2);
}
int FormulaParser::add_unary(code_t code, int t)
{
return otree.add_unary(code, t);
}
int FormulaParser::add_nulary(const char* str)
{
int t = -1;
try {
t = atoms.check(str);
} catch (const ParserException& e) {
throw ParserException(e, fmla_lloc.off);
}
if (t == -1) {
t = otree.add_nulary();
atoms.assign(str, t);
}
return t;
}
void FormulaParser::add_subst_formulas(const map<int,int>& subst, const FormulaParser& fp)
{
for (int i = 0; i < fp.nformulas(); i++) {
int f = add_substitution(fp.formula(i), subst, fp);
add_formula(f);
}
}
void FormulaParser::substitute_formulas(const map<int,int>& smap)
{
for (int i = 0; i < nformulas(); i++) {
// make substitution and replace the formula for it
int f = add_substitution(formulas[i], smap);
formulas[i] = f;
// update the derivatives if any
if (i < (int)ders.size() && ders[i]) {
int order = ders[i]->get_order();
delete ders[i];
ders[i] = new FormulaDerivatives(otree, atoms.variables(), formulas[i], order);
}
}
}
/** Global symbols for passing info to parser. */
FormulaParser* fparser;
/** The declarations of functions defined in formula_ll.cc and
* formula_tab.cc generated from formula.lex and formula.y */
void* fmla__scan_buffer(char*, size_t);
void fmla__destroy_buffer(void*);
int fmla_parse();
extern location_type fmla_lloc;
/** This makes own copy of provided data, sets the buffer for the
* parser with fmla_scan_buffer, and launches fmla_parse(). Note that
* the pointer returned from fmla_scan_buffer must be freed at the
* end. */
void FormulaParser::parse(int length, const char* stream)
{
char* buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
fmla_lloc.off = 0;
fmla_lloc.ll = 0;
void* p = fmla__scan_buffer(buffer, (unsigned int)length+2);
fparser = this;
fmla_parse();
delete [] buffer;
fmla__destroy_buffer(p);
}
void FormulaParser::error(const char* mes) const
{
throw ParserException(mes, fmla_lloc.off);
}
int FormulaParser::last_formula() const
{
int res = -1;
for (unsigned int i = 0; i < formulas.size(); i++)
if (res < formulas[i])
res = formulas[i];
return std::max(res, otree.get_last_nulary());
}
int FormulaParser::pop_last_formula()
{
if (formulas.size() == 0)
return -1;
int t = formulas.back();
if (formulas.size() == ders.size()) {
delete ders.back();
ders.pop_back();
}
formulas.pop_back();
return t;
}
void FormulaParser::print() const
{
atoms.print();
for (unsigned int i = 0; i < formulas.size(); i++) {
printf("formula %d:\n", formulas[i]);
otree.print_operation(formulas[i]);
}
for (unsigned int i = 0; i < ders.size(); i++) {
printf("derivatives for the formula %d:\n", formulas[i]);
ders[i]->print(otree);
}
}
void FormulaParser::destroy_derivatives()
{
while (ders.size() > 0) {
delete ders.back();
ders.pop_back();
}
}
/** This constructor makes a vector of indices for formulas
* corresponding to derivatives of the given formula. The formula is
* supposed to belong to the provided tree, the created derivatives
* are added to the tree.
*
* The algorithm is as follows. todo: update description of the
* algorithm
*/
FormulaDerivatives::FormulaDerivatives(OperationTree& otree,
const vector<int>& vars, int f, int max_order)
: nvar(vars.size()), order(max_order)
{
FoldMultiIndex fmi_zero(nvar);
tder.push_back(f);
indices.push_back(fmi_zero);
unsigned int last_order_beg = 0;
unsigned int last_order_end = tder.size();
for (int k = 1; k <= order; k++) {
// interval <last_order_beg,last_order_end) is guaranteed
// here to contain at least one item
for (unsigned int run = last_order_beg; run < last_order_end; run++) {
// shift one order from the run
FoldMultiIndex fmi(indices[run], 1);
// set starting variable from the run, note that if k=1,
// the shift order ctor of fmi will set it to zero
int ivar_start = fmi[k-1];
for (int ivar = ivar_start; ivar < nvar; ivar++, fmi.increment()) {
int der = otree.add_derivative(tder[run], vars[ivar]);
if (der != OperationTree::zero) {
tder.push_back(der);
indices.push_back(fmi);
}
}
}
// set new last_order_beg and last_order_end
last_order_beg = last_order_end;
last_order_end = tder.size();
// if there was no new derivative, break out from the loop
if (last_order_beg >= last_order_end)
break;
}
// build ind2der map
for (unsigned int i = 0; i < indices.size(); i++)
ind2der.insert(Tfmiintmap::value_type(indices[i], i));
}
FormulaDerivatives::FormulaDerivatives(const FormulaDerivatives& fd)
: tder(fd.tder), indices(fd.indices), ind2der(fd.ind2der),
nvar(fd.nvar), order(fd.order)
{
}
int FormulaDerivatives::derivative(const FoldMultiIndex& mi) const
{
if (mi.order() > order)
throw ogu::Exception(__FILE__,__LINE__,
"Wrong order of multi-index in FormulaDerivatives::derivative");
if (mi.nv() != nvar)
throw ogu::Exception(__FILE__,__LINE__,
"Wrong multi-index variables in FormulaDerivatives::derivative");
Tfmiintmap::const_iterator it = ind2der.find(mi);
if (it == ind2der.end())
return OperationTree::zero;
else
return tder[(*it).second];
}
void FormulaDerivatives::print(const OperationTree& otree) const
{
for (Tfmiintmap::const_iterator it = ind2der.begin();
it != ind2der.end(); ++it) {
printf("derivative ");
(*it).first.print();
printf(" is formula %d\n", tder[(*it).second]);
otree.print_operation(tder[(*it).second]);
}
}
void FormulaCustomEvaluator::eval(const AtomValues& av, FormulaEvalLoader& loader)
{
etree.reset_all();
av.setValues(etree);
for (unsigned int i = 0; i < terms.size(); i++) {
double res = etree.eval(terms[i]);
loader.load((int)i, res);
}
}
FoldMultiIndex::FoldMultiIndex(int nv)
: nvar(nv), ord(0), data(new int[ord])
{
}
FoldMultiIndex::FoldMultiIndex(int nv, int ordd, int ii)
: nvar(nv), ord(ordd), data(new int[ord])
{
for (int i = 0; i < ord; i++)
data[i] = ii;
}
/** Note that a monotone sequence mapped by monotone mapping yields a
* monotone sequence. */
FoldMultiIndex::FoldMultiIndex(int nv, const FoldMultiIndex& mi, const vector<int>& mp)
: nvar(nv), ord(mi.ord), data(new int[ord])
{
for (int i = 0; i < ord; i++) {
if (i < ord-1 && mp[i+1] < mp[i])
throw ogu::Exception(__FILE__,__LINE__,
"Mapping not monotone in FoldMultiIndex constructor");
if (mp[mi[i]] >= nv || mp[mi[i]] < 0)
throw ogu::Exception(__FILE__,__LINE__,
"Mapping out of bounds in FoldMultiIndex constructor");
data[i] = mp[mi[i]];
}
}
FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex& fmi, int new_orders)
: nvar(fmi.nvar),
ord(fmi.ord+new_orders),
data(new int[ord])
{
memcpy(data, fmi.data, fmi.ord*sizeof(int));
int new_item = (fmi.ord > 0)? fmi.data[fmi.ord-1] : 0;
for (int i = fmi.ord; i < ord; i++) {
data[i] = new_item;
}
}
FoldMultiIndex::FoldMultiIndex(const FoldMultiIndex& fmi)
: nvar(fmi.nvar),
ord(fmi.ord),
data(new int[fmi.ord])
{
memcpy(data, fmi.data, ord*sizeof(int));
}
const FoldMultiIndex& FoldMultiIndex::operator=(const FoldMultiIndex& fmi)
{
if (ord != fmi.ord) {
delete [] data;
data = new int[fmi.ord];
}
ord = fmi.ord;
nvar = fmi.nvar;
memcpy(data, fmi.data, ord*sizeof(int));
return *this;
}
bool FoldMultiIndex::operator<(const FoldMultiIndex& fmi) const
{
if (nvar != fmi.nvar)
ogu::Exception(__FILE__,__LINE__,
"Different nvar in FoldMultiIndex::operator<");
if (ord < fmi.ord)
return true;
if (ord > fmi.ord)
return false;
int i = 0;
while (i < ord && data[i] == fmi.data[i])
i++;
if (i == ord)
return false;
else
return data[i] < fmi.data[i];
}
bool FoldMultiIndex::operator==(const FoldMultiIndex& fmi) const
{
bool res = true;
res = res && (nvar == fmi.nvar) && (ord == fmi.ord);
if (res)
for (int i = 0; i < ord; i++)
if (data[i] != fmi.data[i])
return false;
return res;
}
void FoldMultiIndex::increment()
{
if (ord == 0)
return;
int k = ord-1;
data[k]++;
while (k > 0 && data[k] == nvar) {
data[k] = 0;
data[--k]++;
}
for (int kk = 1; kk < ord; kk++)
if (data[kk-1] > data[kk])
data[kk] = data[kk-1];
}
// For description of an algorithm for calculation of folded offset,
// see Tensor Library Documentation, Ondra Kamenik, 2005, description
// of FTensor::getOffsetRecurse().
int FoldMultiIndex::offset() const
{
// make copy for the recursions
int* tmp = new int[ord];
for (int i = 0; i < ord; i++)
tmp[i] = data[i];
// call the recursive algorithm
int res = offset_recurse(tmp, ord, nvar);
delete [] tmp;
return res;
}
void FoldMultiIndex::print() const
{
printf("[");
for (int i = 0; i < ord; i++)
printf("%d ", data[i]);
printf("]");
}
int FoldMultiIndex::offset_recurse(int* data, int len, int nv)
{
if (len == 0)
return 0;
// calculate length of initial constant indices
int prefix = 1;
while (prefix < len && data[0] == data[prefix])
prefix++;
int m = data[0];
int s1 = ptriang.noverk(nv+len-1, len) - ptriang.noverk(nv-m+len-1,len);
// cancel m from the rest of the sequence
for (int i = prefix; i < len; i++)
data[i] -= m;
// calculate offset of the remaining sequence
int s2 = offset_recurse(data+prefix, len-prefix, nv-m);
// return the sum
return s1+s2;
}
bool ltfmi::operator()(const FoldMultiIndex& i1, const FoldMultiIndex& i2) const
{
return i1 < i2;
}
FormulaDerEvaluator::FormulaDerEvaluator(const FormulaParser& fp)
: etree(fp.otree, -1)
{
for (unsigned int i = 0; i < fp.ders.size(); i++)
ders.push_back((const FormulaDerivatives*)(fp.ders[i]));
der_atoms = fp.atoms.variables();
}
void FormulaDerEvaluator::eval(const AtomValues& av, FormulaDerEvalLoader& loader, int order)
{
if (ders.size() == 0)
return;
int maxorder = ders[0]->order;
if (order > maxorder)
throw ogu::Exception(__FILE__,__LINE__,
"Wrong order in FormulaDerEvaluator::eval");
etree.reset_all();
av.setValues(etree);
int* vars = new int[order];
for (unsigned int i = 0; i < ders.size(); i++) {
for (FormulaDerivatives::Tfmiintmap::const_iterator it = ders[i]->ind2der.begin();
it != ders[i]->ind2der.end(); ++it) {
const FoldMultiIndex& mi = (*it).first;
if (mi.order() == order) {
// set vars from multiindex mi and variables
for (int k = 0; k < order; k++)
vars[k] = der_atoms[mi[k]];
// evaluate
double res = etree.eval(ders[i]->tder[(*it).second]);
// load
loader.load(i, order, vars, res);
}
}
}
delete [] vars;
}
void FormulaDerEvaluator::eval(const vector<int>& mp, const AtomValues& av,
FormulaDerEvalLoader& loader, int order)
{
etree.reset_all();
av.setValues(etree);
int nvar_glob = der_atoms.size();
int nvar = mp.size();
int* vars = new int[order];
for (unsigned int i = 0; i < ders.size(); i++) {
FoldMultiIndex mi(nvar, order);
do {
// find index of the derivative in the tensor
FoldMultiIndex mi_glob(nvar_glob, mi, mp);
int der = ders[i]->derivative(mi_glob);
if (der != OperationTree::zero) {
// set vars from the global multiindex
for (int k = 0; k < order; k++)
vars[k] = der_atoms[mi_glob[k]];
// evaluate derivative
double res = etree.eval(der);
// load
loader.load(i, order, vars, res);
}
mi.increment();
} while (! mi.past_the_end());
}
delete [] vars;
}
// Local Variables:
// mode:C++
// End:

View File

@ -3,7 +3,7 @@
#ifndef OGP_FORMULA_PARSER_H
#define OGP_FORMULA_PARSER_H
#include "tree.h"
#include "tree.hh"
namespace ogp
{

View File

@ -1,7 +1,7 @@
%{
// Copyright (C) 2006-2011, Ondra Kamenik
#include "location.h"
#include "location.hh"
#include "matrix_tab.hh"
extern YYLTYPE matrix_lloc;

View File

@ -1,8 +1,8 @@
// Copyright (C) 2006-2011, Ondra Kamenik
%{
#include "location.h"
#include "matrix_parser.h"
#include "location.hh"
#include "matrix_parser.hh"
#include "matrix_tab.hh"
void matrix_error(const char*);

View File

@ -0,0 +1,112 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: matrix_parser.cpp 2269 2008-11-23 14:33:22Z michel $
#include "parser_exception.hh"
#include "matrix_parser.hh"
#include "location.hh"
#include "matrix_tab.hh"
#include <cstring>
using namespace ogp;
/** A global symbol for passing info to the MatrixParser from
* matrix_parse(). */
MatrixParser *mparser;
/** The declaration of functions defined in matrix_ll.cc and
* matrix_tab.cc generated from matrix.lex and matrix.y. */
void *matrix__scan_buffer(char *, size_t);
void matrix__destroy_buffer(void *);
int matrix_parse();
extern ogp::location_type matrix_lloc;
void
MatrixParser::parse(int length, const char *stream)
{
// reinitialize the object
data.clear();
row_lengths.clear();
nc = 0;
// allocate temporary buffer and parse
char *buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
matrix_lloc.off = 0;
matrix_lloc.ll = 0;
void *p = matrix__scan_buffer(buffer, (unsigned int) length+2);
mparser = this;
matrix_parse();
delete [] buffer;
matrix__destroy_buffer(p);
}
void
MatrixParser::add_item(double v)
{
data.push_back(v);
if (row_lengths.size() == 0)
row_lengths.push_back(0);
(row_lengths.back())++;
if (row_lengths.back() > nc)
nc = row_lengths.back();
}
void
MatrixParser::start_row()
{
row_lengths.push_back(0);
}
void
MatrixParser::error(const char *mes) const
{
throw ParserException(mes, matrix_lloc.off);
}
int
MatrixParser::find_first_non_empty_row(int start) const
{
int r = start;
while (r < (int) row_lengths.size() && row_lengths[r] == 0)
r++;
return r;
}
MPIterator
MatrixParser::begin() const
{
MPIterator it(*this);
return it;
}
MPIterator
MatrixParser::end() const
{
MPIterator it(*this, "end");
return it;
}
MPIterator::MPIterator(const MatrixParser &mp)
: p(&mp), i(0), c(0), r(mp.find_first_non_empty_row())
{
}
MPIterator::MPIterator(const MatrixParser &mp, const char *dummy)
: p(&mp), i(mp.data.size()), c(0), r(mp.row_lengths.size())
{
}
MPIterator &
MPIterator::operator++()
{
i++;
c++;
if (p->row_lengths[r] <= c)
{
c = 0;
r = p->find_first_non_empty_row(r+1);
}
return *this;
}

View File

@ -1,101 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: matrix_parser.cpp 2269 2008-11-23 14:33:22Z michel $
#include "parser_exception.h"
#include "matrix_parser.h"
#include "location.h"
#include "matrix_tab.hh"
#include <cstring>
using namespace ogp;
/** A global symbol for passing info to the MatrixParser from
* matrix_parse(). */
MatrixParser* mparser;
/** The declaration of functions defined in matrix_ll.cc and
* matrix_tab.cc generated from matrix.lex and matrix.y. */
void* matrix__scan_buffer(char*, size_t);
void matrix__destroy_buffer(void*);
int matrix_parse();
extern ogp::location_type matrix_lloc;
void MatrixParser::parse(int length, const char* stream)
{
// reinitialize the object
data.clear();
row_lengths.clear();
nc = 0;
// allocate temporary buffer and parse
char* buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
matrix_lloc.off = 0;
matrix_lloc.ll = 0;
void* p = matrix__scan_buffer(buffer, (unsigned int)length+2);
mparser = this;
matrix_parse();
delete [] buffer;
matrix__destroy_buffer(p);
}
void MatrixParser::add_item(double v)
{
data.push_back(v);
if (row_lengths.size() == 0)
row_lengths.push_back(0);
(row_lengths.back())++;
if (row_lengths.back() > nc)
nc = row_lengths.back();
}
void MatrixParser::start_row()
{
row_lengths.push_back(0);
}
void MatrixParser::error(const char* mes) const
{
throw ParserException(mes, matrix_lloc.off);
}
int MatrixParser::find_first_non_empty_row(int start) const
{
int r = start;
while (r < (int)row_lengths.size() && row_lengths[r] == 0)
r++;
return r;
}
MPIterator MatrixParser::begin() const
{
MPIterator it(*this);
return it;
}
MPIterator MatrixParser::end() const
{
MPIterator it(*this, "end");
return it;
}
MPIterator::MPIterator(const MatrixParser& mp)
: p(&mp), i(0), c(0), r(mp.find_first_non_empty_row())
{}
MPIterator::MPIterator(const MatrixParser& mp, const char* dummy)
: p(&mp), i(mp.data.size()), c(0), r(mp.row_lengths.size())
{}
MPIterator& MPIterator::operator++()
{
i++;
c++;
if (p->row_lengths[r] <= c) {
c = 0;
r = p->find_first_non_empty_row(r+1);
}
return *this;
}

View File

@ -0,0 +1,31 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: namelist.cpp 42 2007-01-22 21:53:24Z ondra $
#include "namelist.hh"
#include <cstring>
using namespace ogp;
/** A global symbol for passing info to NameListParser from its
* parser. */
NameListParser *name_list_parser;
void *namelist__scan_buffer(char *, unsigned int);
void namelist__destroy_buffer(void *);
void namelist_parse();
void
NameListParser::namelist_parse(int length, const char *stream)
{
char *buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
void *p = namelist__scan_buffer(buffer, (unsigned int) length+2);
name_list_parser = this;
::namelist_parse();
delete [] buffer;
namelist__destroy_buffer(p);
}

View File

@ -1,30 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: namelist.cpp 42 2007-01-22 21:53:24Z ondra $
#include "namelist.h"
#include <cstring>
using namespace ogp;
/** A global symbol for passing info to NameListParser from its
* parser. */
NameListParser* name_list_parser;
void* namelist__scan_buffer(char*, unsigned int);
void namelist__destroy_buffer(void*);
void namelist_parse();
void NameListParser::namelist_parse(int length, const char* stream)
{
char* buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
void* p = namelist__scan_buffer(buffer, (unsigned int)length+2);
name_list_parser = this;
::namelist_parse();
delete [] buffer;
namelist__destroy_buffer(p);
}

View File

@ -1,5 +1,5 @@
%{
#include "location.h"
#include "location.hh"
#include "namelist_tab.hh"
extern YYLTYPE namelist_lloc;

View File

@ -1,8 +1,8 @@
// Copyright (C) 2007-2011, Ondra Kamenik
%{
#include "location.h"
#include "namelist.h"
#include "location.hh"
#include "namelist.hh"
#include "namelist_tab.hh"
void namelist_error(const char*);

View File

@ -0,0 +1,118 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: parser_exception.cpp 2269 2008-11-23 14:33:22Z michel $
#include "parser_exception.hh"
#include <cstring>
#include <cstdio>
using namespace ogp;
ParserException::ParserException(const char *m, int offset)
: mes(new char[strlen(m)+1]), off(offset),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
strcpy(mes, m);
}
ParserException::ParserException(const string &m, int offset)
: mes(new char[m.size()+1]), off(offset),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string &m, const char *dum, int i1)
: mes(new char[m.size()+1]), off(0),
aux_i1(i1), aux_i2(-1), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string &m, const char *dum, int i1, int i2)
: mes(new char[m.size()+1]), off(0),
aux_i1(i1), aux_i2(i2), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string &m, const char *dum, int i1, int i2, int i3)
: mes(new char[m.size()+1]), off(0),
aux_i1(i1), aux_i2(i2), aux_i3(i3)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const ParserException &m, int plus_offset)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
off += plus_offset;
}
ParserException::ParserException(const ParserException &m, const char *dum, int i)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = m.aux_i2;
aux_i2 = m.aux_i1;
aux_i1 = i;
}
ParserException::ParserException(const ParserException &m, const char *dum, int i1, int i2)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = m.aux_i1;
aux_i2 = i2;
aux_i1 = i1;
}
ParserException::ParserException(const ParserException &m, const char *dum, int i1, int i2, int i3)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = i3;
aux_i2 = i2;
aux_i1 = i1;
}
ParserException::ParserException(const ParserException &e)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(e);
}
ParserException::~ParserException()
{
delete [] mes;
}
void
ParserException::copy(const ParserException &e)
{
if (mes)
delete [] mes;
mes = new char[strlen(e.mes)+1];
strcpy(mes, e.mes);
off = e.off;
aux_i1 = e.aux_i1;
aux_i2 = e.aux_i2;
aux_i3 = e.aux_i3;
}
void
ParserException::print(FILE *fd) const
{
// todo: to be refined
fprintf(fd, "%s: offset %d\n", mes, off);
}

View File

@ -1,117 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: parser_exception.cpp 2269 2008-11-23 14:33:22Z michel $
#include "parser_exception.h"
#include <cstring>
#include <cstdio>
using namespace ogp;
ParserException::ParserException(const char* m, int offset)
: mes(new char[strlen(m)+1]), off(offset),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
strcpy(mes, m);
}
ParserException::ParserException(const string& m, int offset)
: mes(new char[m.size()+1]), off(offset),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string& m, const char* dum, int i1)
: mes(new char[m.size()+1]), off(0),
aux_i1(i1), aux_i2(-1), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string& m, const char* dum, int i1, int i2)
: mes(new char[m.size()+1]), off(0),
aux_i1(i1), aux_i2(i2), aux_i3(-1)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const string& m, const char* dum, int i1, int i2, int i3)
: mes(new char[m.size()+1]), off(0),
aux_i1(i1), aux_i2(i2), aux_i3(i3)
{
strncpy(mes, m.c_str(), m.size());
mes[m.size()] = '\0';
}
ParserException::ParserException(const ParserException& m, int plus_offset)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
off += plus_offset;
}
ParserException::ParserException(const ParserException& m, const char* dum, int i)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = m.aux_i2;
aux_i2 = m.aux_i1;
aux_i1 = i;
}
ParserException::ParserException(const ParserException& m, const char* dum, int i1, int i2)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = m.aux_i1;
aux_i2 = i2;
aux_i1 = i1;
}
ParserException::ParserException(const ParserException& m, const char* dum, int i1, int i2, int i3)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(m);
aux_i3 = i3;
aux_i2 = i2;
aux_i1 = i1;
}
ParserException::ParserException(const ParserException& e)
: mes(NULL),
aux_i1(-1), aux_i2(-1), aux_i3(-1)
{
copy(e);
}
ParserException::~ParserException()
{
delete [] mes;
}
void ParserException::copy(const ParserException& e)
{
if (mes)
delete [] mes;
mes = new char[strlen(e.mes)+1];
strcpy(mes, e.mes);
off = e.off;
aux_i1 = e.aux_i1;
aux_i2 = e.aux_i2;
aux_i3 = e.aux_i3;
}
void ParserException::print(FILE* fd) const
{
// todo: to be refined
fprintf(fd, "%s: offset %d\n", mes, off);
}

View File

@ -0,0 +1,141 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: static_atoms.cpp 1360 2007-07-10 11:44:20Z kamenik $
#include "static_atoms.hh"
#include "utils/cc/exception.hh"
using namespace ogp;
StaticAtoms::StaticAtoms(const StaticAtoms &a)
: Atoms(), Constants(a), varnames(a.varnames),
varorder(), vars(), indices()
{
// fill varorder
for (unsigned int i = 0; i < a.varorder.size(); i++)
{
const char *s = varnames.query(a.varorder[i]);
varorder.push_back(s);
}
// fill vars
for (Tvarmap::const_iterator it = a.vars.begin();
it != a.vars.end(); ++it)
{
const char *s = varnames.query((*it).first);
vars.insert(Tvarmap::value_type(s, (*it).second));
}
// fill indices
for (Tinvmap::const_iterator it = a.indices.begin();
it != a.indices.end(); ++it)
{
const char *s = varnames.query((*it).second);
indices.insert(Tinvmap::value_type((*it).first, s));
}
}
void
StaticAtoms::import_atoms(const DynamicAtoms &da, OperationTree &otree, Tintintmap &tmap)
{
Constants::import_constants(da, otree, tmap);
for (int i = 0; i < da.get_name_storage().num(); i++)
{
const char *name = da.get_name_storage().get_name(i);
register_name(name);
int tnew = otree.add_nulary();
assign(name, tnew);
if (da.is_referenced(name))
{
const DynamicAtoms::Tlagmap &lmap = da.lagmap(name);
for (DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it)
{
int told = (*it).second;
tmap.insert(Tintintmap::value_type(told, tnew));
}
}
}
}
int
StaticAtoms::check(const char *name) const
{
if (DynamicAtoms::is_string_constant(name))
{
return Constants::check(name);
}
else
{
return check_variable(name);
}
}
int
StaticAtoms::index(const char *name) const
{
Tvarmap::const_iterator it = vars.find(name);
if (it == vars.end())
return -1;
else
return (*it).second;
}
const char *
StaticAtoms::inv_index(int t) const
{
Tinvmap::const_iterator it = indices.find(t);
if (it == indices.end())
return NULL;
else
return (*it).second;
}
void
StaticAtoms::assign(const char *name, int t)
{
if (DynamicAtoms::is_string_constant(name))
{
double val;
sscanf(name, "%lf", &val);
add_constant(t, val);
}
else
{
const char *ss = varnames.insert(name);
vars.insert(Tvarmap::value_type(ss, t));
indices.insert(Tinvmap::value_type(t, ss));
}
}
vector<int>
StaticAtoms::variables() const
{
vector<int> res;
for (Tvarmap::const_iterator it = vars.begin();
it != vars.end(); ++it)
{
res.push_back((*it).second);
}
return res;
}
void
StaticAtoms::register_name(const char *name)
{
const char *ss = varnames.insert(name);
varorder.push_back(ss);
}
void
StaticAtoms::print() const
{
printf("constants:\n");
Constants::print();
printf("variable names:\n");
varnames.print();
printf("map to tree indices:\n");
for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it)
printf("%s\t->\t%d\n", (*it).first, (*it).second);
}

View File

@ -1,121 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: static_atoms.cpp 1360 2007-07-10 11:44:20Z kamenik $
#include "static_atoms.h"
#include "utils/cc/exception.h"
using namespace ogp;
StaticAtoms::StaticAtoms(const StaticAtoms& a)
: Atoms(), Constants(a), varnames(a.varnames),
varorder(), vars(), indices()
{
// fill varorder
for (unsigned int i = 0; i < a.varorder.size(); i++) {
const char* s = varnames.query(a.varorder[i]);
varorder.push_back(s);
}
// fill vars
for (Tvarmap::const_iterator it = a.vars.begin();
it != a.vars.end(); ++it) {
const char* s = varnames.query((*it).first);
vars.insert(Tvarmap::value_type(s, (*it).second));
}
// fill indices
for (Tinvmap::const_iterator it = a.indices.begin();
it != a.indices.end(); ++it) {
const char* s = varnames.query((*it).second);
indices.insert(Tinvmap::value_type((*it).first, s));
}
}
void StaticAtoms::import_atoms(const DynamicAtoms& da, OperationTree& otree, Tintintmap& tmap)
{
Constants::import_constants(da, otree, tmap);
for (int i = 0; i < da.get_name_storage().num(); i++) {
const char* name = da.get_name_storage().get_name(i);
register_name(name);
int tnew = otree.add_nulary();
assign(name, tnew);
if (da.is_referenced(name)) {
const DynamicAtoms::Tlagmap& lmap = da.lagmap(name);
for (DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it) {
int told = (*it).second;
tmap.insert(Tintintmap::value_type(told, tnew));
}
}
}
}
int StaticAtoms::check(const char* name) const
{
if (DynamicAtoms::is_string_constant(name)) {
return Constants::check(name);
} else {
return check_variable(name);
}
}
int StaticAtoms::index(const char* name) const
{
Tvarmap::const_iterator it = vars.find(name);
if (it == vars.end())
return -1;
else
return (*it).second;
}
const char* StaticAtoms::inv_index(int t) const
{
Tinvmap::const_iterator it = indices.find(t);
if (it == indices.end())
return NULL;
else
return (*it).second;
}
void StaticAtoms::assign(const char* name, int t)
{
if (DynamicAtoms::is_string_constant(name)) {
double val;
sscanf(name, "%lf", &val);
add_constant(t, val);
} else {
const char* ss = varnames.insert(name);
vars.insert(Tvarmap::value_type(ss, t));
indices.insert(Tinvmap::value_type(t, ss));
}
}
vector<int> StaticAtoms::variables() const
{
vector<int> res;
for (Tvarmap::const_iterator it = vars.begin();
it != vars.end(); ++it) {
res.push_back((*it).second);
}
return res;
}
void StaticAtoms::register_name(const char* name)
{
const char* ss = varnames.insert(name);
varorder.push_back(ss);
}
void StaticAtoms::print() const
{
printf("constants:\n");
Constants::print();
printf("variable names:\n");
varnames.print();
printf("map to tree indices:\n");
for (Tvarmap::const_iterator it = vars.begin(); it != vars.end(); ++it)
printf("%s\t->\t%d\n", (*it).first, (*it).second);
}

View File

@ -5,7 +5,7 @@
#ifndef OGP_STATIC_ATOMS
#define OGP_STATIC_ATOMS
#include "dynamic_atoms.h"
#include "dynamic_atoms.hh"
namespace ogp
{

View File

@ -0,0 +1,237 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: static_fine_atoms.cpp 82 2007-04-19 11:33:30Z ondra $
#include "utils/cc/exception.hh"
#include "static_fine_atoms.hh"
#include "parser_exception.hh"
using namespace ogp;
StaticFineAtoms::StaticFineAtoms(const StaticFineAtoms &sfa)
: StaticAtoms(sfa),
params(), param_outer_map(),
endovars(), endo_outer_map(),
exovars(), exo_outer_map(),
der_atoms(sfa.der_atoms),
endo_atoms_map(sfa.endo_atoms_map),
exo_atoms_map(sfa.exo_atoms_map)
{
for (unsigned int i = 0; i < sfa.params.size(); i++)
{
const char *name = varnames.query(sfa.params[i]);
params.push_back(name);
param_outer_map.insert(Tvarintmap::value_type(name, i));
}
for (unsigned int i = 0; i < sfa.endovars.size(); i++)
{
const char *name = varnames.query(sfa.endovars[i]);
endovars.push_back(name);
endo_outer_map.insert(Tvarintmap::value_type(name, i));
}
for (unsigned int i = 0; i < sfa.exovars.size(); i++)
{
const char *name = varnames.query(sfa.exovars[i]);
exovars.push_back(name);
exo_outer_map.insert(Tvarintmap::value_type(name, i));
}
}
void
StaticFineAtoms::import_atoms(const FineAtoms &fa, OperationTree &otree, Tintintmap &tmap)
{
StaticAtoms::import_atoms(fa, otree, tmap);
// we just need to put parameters, endovars, and exovars to
// respective vectors, the names are already in the storage
// parameters
const vector<const char *> &fa_params = fa.get_params();
for (unsigned int i = 0; i < fa_params.size(); i++)
register_param(fa_params[i]);
// endogenous
const vector<const char *> &fa_endovars = fa.get_endovars();
for (unsigned int i = 0; i < fa_endovars.size(); i++)
register_endo(fa_endovars[i]);
// exogenous
const vector<const char *> &fa_exovars = fa.get_exovars();
for (unsigned int i = 0; i < fa_exovars.size(); i++)
register_exo(fa_exovars[i]);
parsing_finished();
}
void
StaticFineAtoms::import_atoms(const FineAtoms &fa, OperationTree &otree, Tintintmap &tmap,
const char *dummy)
{
StaticAtoms::import_atoms(fa, otree, tmap);
// we just need to put parameters, endovars, and exovars to
// respective vectors, the names are already in the storage
// parameters
const vector<const char *> &fa_params = fa.get_params();
for (unsigned int i = 0; i < fa_params.size(); i++)
register_param(fa_params[i]);
// endogenous
const vector<const char *> &fa_endovars = fa.get_endovars();
for (unsigned int i = 0; i < fa_endovars.size(); i++)
register_endo(fa_endovars[fa.y2outer_endo()[i]]);
// exogenous
const vector<const char *> &fa_exovars = fa.get_exovars();
for (unsigned int i = 0; i < fa_exovars.size(); i++)
register_exo(fa_exovars[fa.y2outer_exo()[i]]);
parsing_finished();
}
int
StaticFineAtoms::check_variable(const char *name) const
{
const char *ss = varnames.query(name);
if (ss == NULL)
throw ParserException(string("Variable <")+name+"> not declared.", 0);
return index(name);
}
void
StaticFineAtoms::parsing_finished()
{
// build der_atoms, and endo_atoms_map and exo_atoms_map
der_atoms.clear();
endo_atoms_map.clear();
exo_atoms_map.clear();
// go through all endo and exo insert tree indices, ignore names
// whose tree index is -1 (those which are not referenced)
for (unsigned int i = 0; i < endovars.size(); i++)
{
int t = index(endovars[i]);
if (t != -1)
{
endo_atoms_map.push_back(der_atoms.size());
der_atoms.push_back(t);
}
}
for (unsigned int i = 0; i < exovars.size(); i++)
{
int t = index(exovars[i]);
if (t != -1)
{
exo_atoms_map.push_back(der_atoms.size());
der_atoms.push_back(t);
}
}
}
int
StaticFineAtoms::name2outer_param(const char *name) const
{
Tvarintmap::const_iterator it = param_outer_map.find(name);
if (it == param_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not a parameter in StaticFineAtoms::name2outer_param");
return (*it).second;
}
int
StaticFineAtoms::name2outer_endo(const char *name) const
{
Tvarintmap::const_iterator it = endo_outer_map.find(name);
if (it == endo_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not an endogenous variable in StaticFineAtoms::name2outer_endo");
return (*it).second;
}
int
StaticFineAtoms::name2outer_exo(const char *name) const
{
Tvarintmap::const_iterator it = exo_outer_map.find(name);
if (it == exo_outer_map.end())
throw ogu::Exception(__FILE__, __LINE__,
"Name is not an exogenous variable in StaticFineAtoms::name2outer_exo");
return (*it).second;
}
void
StaticFineAtoms::register_uniq_endo(const char *name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Endogenous variable <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
register_endo(ss);
}
void
StaticFineAtoms::register_uniq_exo(const char *name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Exogenous variable <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
register_exo(ss);
}
void
StaticFineAtoms::register_uniq_param(const char *name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Parameter <")+name+"> is not unique.", 0);
const char *ss = varnames.insert(name);
register_param(ss);
}
void
StaticFineAtoms::print() const
{
StaticAtoms::print();
printf("endo atoms map:\n");
for (unsigned int i = 0; i < endo_atoms_map.size(); i++)
printf("%d --> %d\n", i, endo_atoms_map[i]);
printf("exo atoms map:\n");
for (unsigned int i = 0; i < exo_atoms_map.size(); i++)
printf("%d --> %d\n", i, exo_atoms_map[i]);
printf("der atoms:\n");
for (unsigned int i = 0; i < der_atoms.size(); i++)
printf("%d\t%d\n", i, der_atoms[i]);
}
void
StaticFineAtoms::register_endo(const char *name)
{
const char *ss = varnames.query(name);
if (ss == NULL)
throw ogp::ParserException(string("Endogenous variable <")
+name+"> not found in storage.", 0);
endovars.push_back(ss);
endo_outer_map.insert(Tvarintmap::value_type(ss, endovars.size()-1));
}
void
StaticFineAtoms::register_exo(const char *name)
{
const char *ss = varnames.query(name);
if (ss == NULL)
throw ogp::ParserException(string("Exogenous variable <")
+name+"> not found in storage.", 0);
exovars.push_back(ss);
exo_outer_map.insert(Tvarintmap::value_type(ss, exovars.size()-1));
}
void
StaticFineAtoms::register_param(const char *name)
{
const char *ss = varnames.query(name);
if (ss == NULL)
throw ogp::ParserException(string("Parameter <")+name+"> not found in storage.", 0);
params.push_back(ss);
param_outer_map.insert(Tvarintmap::value_type(ss, params.size()-1));
}

View File

@ -1,217 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: static_fine_atoms.cpp 82 2007-04-19 11:33:30Z ondra $
#include "utils/cc/exception.h"
#include "static_fine_atoms.h"
#include "parser_exception.h"
using namespace ogp;
StaticFineAtoms::StaticFineAtoms(const StaticFineAtoms& sfa)
: StaticAtoms(sfa),
params(), param_outer_map(),
endovars(), endo_outer_map(),
exovars(), exo_outer_map(),
der_atoms(sfa.der_atoms),
endo_atoms_map(sfa.endo_atoms_map),
exo_atoms_map(sfa.exo_atoms_map)
{
for (unsigned int i = 0; i < sfa.params.size(); i++) {
const char* name = varnames.query(sfa.params[i]);
params.push_back(name);
param_outer_map.insert(Tvarintmap::value_type(name, i));
}
for (unsigned int i = 0; i < sfa.endovars.size(); i++) {
const char* name = varnames.query(sfa.endovars[i]);
endovars.push_back(name);
endo_outer_map.insert(Tvarintmap::value_type(name, i));
}
for (unsigned int i = 0; i < sfa.exovars.size(); i++) {
const char* name = varnames.query(sfa.exovars[i]);
exovars.push_back(name);
exo_outer_map.insert(Tvarintmap::value_type(name, i));
}
}
void StaticFineAtoms::import_atoms(const FineAtoms& fa, OperationTree& otree, Tintintmap& tmap)
{
StaticAtoms::import_atoms(fa, otree, tmap);
// we just need to put parameters, endovars, and exovars to
// respective vectors, the names are already in the storage
// parameters
const vector<const char*>& fa_params = fa.get_params();
for (unsigned int i = 0; i < fa_params.size(); i++)
register_param(fa_params[i]);
// endogenous
const vector<const char*>& fa_endovars = fa.get_endovars();
for (unsigned int i = 0; i < fa_endovars.size(); i++)
register_endo(fa_endovars[i]);
// exogenous
const vector<const char*>& fa_exovars = fa.get_exovars();
for (unsigned int i = 0; i < fa_exovars.size(); i++)
register_exo(fa_exovars[i]);
parsing_finished();
}
void StaticFineAtoms::import_atoms(const FineAtoms& fa, OperationTree& otree, Tintintmap& tmap,
const char* dummy)
{
StaticAtoms::import_atoms(fa, otree, tmap);
// we just need to put parameters, endovars, and exovars to
// respective vectors, the names are already in the storage
// parameters
const vector<const char*>& fa_params = fa.get_params();
for (unsigned int i = 0; i < fa_params.size(); i++)
register_param(fa_params[i]);
// endogenous
const vector<const char*>& fa_endovars = fa.get_endovars();
for (unsigned int i = 0; i < fa_endovars.size(); i++)
register_endo(fa_endovars[fa.y2outer_endo()[i]]);
// exogenous
const vector<const char*>& fa_exovars = fa.get_exovars();
for (unsigned int i = 0; i < fa_exovars.size(); i++)
register_exo(fa_exovars[fa.y2outer_exo()[i]]);
parsing_finished();
}
int StaticFineAtoms::check_variable(const char* name) const
{
const char* ss = varnames.query(name);
if (ss == NULL)
throw ParserException(string("Variable <")+name+"> not declared.",0);
return index(name);
}
void StaticFineAtoms::parsing_finished()
{
// build der_atoms, and endo_atoms_map and exo_atoms_map
der_atoms.clear();
endo_atoms_map.clear();
exo_atoms_map.clear();
// go through all endo and exo insert tree indices, ignore names
// whose tree index is -1 (those which are not referenced)
for (unsigned int i = 0; i < endovars.size(); i++) {
int t = index(endovars[i]);
if (t != -1) {
endo_atoms_map.push_back(der_atoms.size());
der_atoms.push_back(t);
}
}
for (unsigned int i = 0; i < exovars.size(); i++) {
int t = index(exovars[i]);
if (t != -1) {
exo_atoms_map.push_back(der_atoms.size());
der_atoms.push_back(t);
}
}
}
int StaticFineAtoms::name2outer_param(const char* name) const
{
Tvarintmap::const_iterator it = param_outer_map.find(name);
if (it == param_outer_map.end())
throw ogu::Exception(__FILE__,__LINE__,
"Name is not a parameter in StaticFineAtoms::name2outer_param");
return (*it).second;
}
int StaticFineAtoms::name2outer_endo(const char* name) const
{
Tvarintmap::const_iterator it = endo_outer_map.find(name);
if (it == endo_outer_map.end())
throw ogu::Exception(__FILE__,__LINE__,
"Name is not an endogenous variable in StaticFineAtoms::name2outer_endo");
return (*it).second;
}
int StaticFineAtoms::name2outer_exo(const char* name) const
{
Tvarintmap::const_iterator it = exo_outer_map.find(name);
if (it == exo_outer_map.end())
throw ogu::Exception(__FILE__,__LINE__,
"Name is not an exogenous variable in StaticFineAtoms::name2outer_exo");
return (*it).second;
}
void StaticFineAtoms::register_uniq_endo(const char* name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Endogenous variable <")+name+"> is not unique.",0);
const char* ss = varnames.insert(name);
register_endo(ss);
}
void StaticFineAtoms::register_uniq_exo(const char* name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Exogenous variable <")+name+"> is not unique.",0);
const char* ss = varnames.insert(name);
register_exo(ss);
}
void StaticFineAtoms::register_uniq_param(const char* name)
{
if (varnames.query(name))
throw ogp::ParserException(string("Parameter <")+name+"> is not unique.",0);
const char* ss = varnames.insert(name);
register_param(ss);
}
void StaticFineAtoms::print() const
{
StaticAtoms::print();
printf("endo atoms map:\n");
for (unsigned int i = 0; i < endo_atoms_map.size(); i++)
printf("%d --> %d\n", i, endo_atoms_map[i]);
printf("exo atoms map:\n");
for (unsigned int i = 0; i < exo_atoms_map.size(); i++)
printf("%d --> %d\n", i, exo_atoms_map[i]);
printf("der atoms:\n");
for (unsigned int i = 0; i < der_atoms.size(); i++)
printf("%d\t%d\n",i, der_atoms[i]);
}
void StaticFineAtoms::register_endo(const char* name)
{
const char* ss = varnames.query(name);
if (ss == NULL)
throw ogp::ParserException(string("Endogenous variable <")
+name+"> not found in storage.",0);
endovars.push_back(ss);
endo_outer_map.insert(Tvarintmap::value_type(ss, endovars.size()-1));
}
void StaticFineAtoms::register_exo(const char* name)
{
const char* ss = varnames.query(name);
if (ss == NULL)
throw ogp::ParserException(string("Exogenous variable <")
+name+"> not found in storage.",0);
exovars.push_back(ss);
exo_outer_map.insert(Tvarintmap::value_type(ss, exovars.size()-1));
}
void StaticFineAtoms::register_param(const char* name)
{
const char* ss = varnames.query(name);
if (ss == NULL)
throw ogp::ParserException(string("Parameter <")+name+"> not found in storage.",0);
params.push_back(ss);
param_outer_map.insert(Tvarintmap::value_type(ss, params.size()-1));
}

View File

@ -5,8 +5,8 @@
#ifndef OGP_STATIC_FINE_ATOMS_H
#define OGP_STATIC_FINE_ATOMS_H
#include "static_atoms.h"
#include "fine_atoms.h"
#include "static_atoms.hh"
#include "fine_atoms.hh"
namespace ogp
{

1036
dynare++/parser/cc/tree.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,928 +0,0 @@
// Copyright (C) 2005-2011, Ondra Kamenik
#include "utils/cc/exception.h"
#include "tree.h"
#include <cstdlib>
#include <cmath>
#include <limits>
#ifdef __MINGW32__
#define __CROSS_COMPILATION__
#endif
#ifdef __MINGW64__
#define __CROSS_COMPILATION__
#endif
#ifdef __CROSS_COMPILATION__
#define M_PI 3.14159265358979323846
#endif
using namespace ogp;
/** Here we just implement complementary error function without
* declaring it for uses from outside this unit. The implementation is taken from "Numerical Recipes in C" 2nd ed. 1992 p. 221, */
double erffc(double x)
{
double z = std::abs(x);
double t = 1/(1+0.5*z);
double r = t*exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+t*(-0.82215223+t*0.17087277)))))))));
return x >= 0 ? r : 2-r;
}
/** Here we initialize OperationTree to contain only zero, one, nan
* and two_over_pi terms. */
OperationTree::OperationTree()
{
last_nulary = -1;
// allocate space for the constants
for (int i = 0; i < num_constants; i++)
add_nulary();
}
int OperationTree::add_nulary()
{
int op = terms.size();
Operation nulary;
terms.push_back(nulary);
_Tintset s;
s.insert(op);
nul_incidence.push_back(s);
_Tderivmap empty;
derivatives.push_back(empty);
last_nulary = op;
return op;
}
int OperationTree::add_unary(code_t code, int op)
{
if (op == zero &&
(code == UMINUS ||
code == SIN ||
code == TAN ||
code == SQRT ||
code == ERF))
return zero;
if ((op == zero && code == LOG) || op == nan)
return nan;
if (op == zero && (code == EXP ||
code == COS ||
code == ERFC))
return one;
Operation unary(code, op);
_Topmap::const_iterator i = ((const _Topmap&)opmap).find(unary);
if (i == opmap.end()) {
int newop = terms.size();
// add to the terms
terms.push_back(unary);
// copy incidence of the operand
nul_incidence.push_back(nul_incidence[op]);
// insert it to opmap
opmap.insert(_Topval(unary, newop));
// add empty map of derivatives
_Tderivmap empty;
derivatives.push_back(empty);
return newop;
}
return (*i).second;
}
int OperationTree::add_binary(code_t code, int op1, int op2)
{
// quick exits for special values
if (op1 == nan || op2 == nan)
return nan;
// for plus
if (code == PLUS) {
if (op1 == zero && op2 == zero)
return zero;
else if (op1 == zero)
return op2;
else if (op2 == zero)
return op1;
}
// for minus
if (code == MINUS) {
if (op1 == zero && op2 == zero)
return zero;
else if (op1 == zero)
return add_unary(UMINUS, op2);
else if (op2 == zero)
return op1;
}
// for times
if (code == TIMES) {
if (op1 == zero || op2 == zero)
return zero;
else if (op1 == one)
return op2;
else if (op2 == one)
return op1;
}
// for divide
if (code == DIVIDE) {
if (op1 == op2)
return one;
else if (op1 == zero)
return zero;
else if (op2 == zero)
return nan;
}
// for power
if (code == POWER) {
if (op1 == zero && op2 == zero)
return nan;
else if (op1 == zero)
return zero;
else if (op2 == zero)
return one;
else if (op1 == one)
return one;
else if (op2 == one)
return op1;
}
// order operands of commutative operations
if (code == TIMES || code == PLUS)
if (op1 > op2) {
int tmp = op1;
op1 = op2;
op2 = tmp;
}
// construct operation and check/add it
Operation binary(code, op1, op2);
_Topmap::const_iterator i = ((const _Topmap&)opmap).find(binary);
if (i == opmap.end()) {
int newop = terms.size();
terms.push_back(binary);
// sum both sets of incidenting nulary operations
nul_incidence.push_back(nul_incidence[op1]);
nul_incidence.back().insert(nul_incidence[op2].begin(), nul_incidence[op2].end());
// add to opmap
opmap.insert(_Topval(binary, newop));
// add empty map of derivatives
_Tderivmap empty;
derivatives.push_back(empty);
return newop;
}
return (*i).second;
}
int OperationTree::add_derivative(int t, int v)
{
if (t < 0 || t >= (int) terms.size())
throw ogu::Exception(__FILE__,__LINE__,
"Wrong value for tree index in OperationTree::add_derivative");
// quick returns for nulary terms or empty incidence
if (terms[t].nary() == 0 && t != v) {
return zero;
}
if (terms[t].nary() == 0 && t == v) {
return one;
}
if (nul_incidence[t].end() == nul_incidence[t].find(v)) {
return zero;
}
// quick return if the derivative has been registered
_Tderivmap::const_iterator i = derivatives[t].find(v);
if (i != derivatives[t].end())
return (*i).second;
int res = -1;
switch (terms[t].getCode()) {
case UMINUS:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_unary(UMINUS, tmp);
break;
}
case LOG:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_binary(DIVIDE, tmp, terms[t].getOp1());
break;
}
case EXP:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_binary(TIMES, t, tmp);
break;
}
case SIN:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_binary(TIMES, add_unary(COS, terms[t].getOp1()), tmp);
break;
}
case COS:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_unary(UMINUS, add_binary(TIMES, add_unary(SIN, terms[t].getOp1()), tmp));
break;
}
case TAN:
{
int tmp = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_unary(COS, terms[t].getOp1());
res = add_binary(DIVIDE, tmp, add_binary(TIMES, tmp2, tmp2));
break;
}
case SQRT:
{
int tmp = add_derivative(terms[t].getOp1(), v);
res = add_binary(DIVIDE, tmp,
add_binary(PLUS, t, t));
break;
}
case ERF:
{
int tmp = add_binary(TIMES, terms[t].getOp1(), terms[t].getOp1());
tmp = add_unary(UMINUS, tmp);
tmp = add_unary(EXP, tmp);
int der = add_derivative(terms[t].getOp1(), v);
tmp = add_binary(TIMES, tmp, der);
res = add_binary(TIMES, two_over_pi, tmp);
break;
}
case ERFC:
{
int tmp = add_binary(TIMES, terms[t].getOp1(), terms[t].getOp1());
tmp = add_unary(UMINUS, tmp);
tmp = add_unary(EXP, tmp);
int der = add_derivative(terms[t].getOp1(), v);
tmp = add_binary(TIMES, tmp, der);
tmp = add_binary(TIMES, two_over_pi, tmp);
res = add_unary(UMINUS, tmp);
break;
}
case PLUS:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
res = add_binary(PLUS, tmp1, tmp2);
break;
}
case MINUS:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
res = add_binary(MINUS, tmp1, tmp2);
break;
}
case TIMES:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
int res1 = add_binary(TIMES, terms[t].getOp1(), tmp2);
int res2 = add_binary(TIMES, tmp1, terms[t].getOp2());
res = add_binary(PLUS, res1, res2);
break;
}
case DIVIDE:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
if (tmp2 == zero)
res = add_binary(DIVIDE, tmp1, terms[t].getOp2());
else {
int nom = add_binary(MINUS,
add_binary(TIMES, tmp1, terms[t].getOp2()),
add_binary(TIMES, tmp2, terms[t].getOp1()));
int den = add_binary(TIMES, terms[t].getOp2(), terms[t].getOp2());
res = add_binary(DIVIDE, nom, den);
}
break;
}
case POWER:
{
int tmp1 = add_derivative(terms[t].getOp1(), v);
int tmp2 = add_derivative(terms[t].getOp2(), v);
int s1 = add_binary(TIMES, tmp2,
add_binary(TIMES, t,
add_unary(LOG, terms[t].getOp1())));
int s2 = add_binary(TIMES, tmp1,
add_binary(TIMES, terms[t].getOp2(),
add_binary(POWER, terms[t].getOp1(),
add_binary(MINUS, terms[t].getOp2(), one))));
res = add_binary(PLUS, s1, s2);
break;
}
case NONE:
break;
}
if (res == -1)
throw ogu::Exception(__FILE__,__LINE__,
"Unknown operation code.");
register_derivative(t, v, res);
return res;
}
int OperationTree::add_substitution(int t, const map<int,int>& subst)
{
return add_substitution(t, subst, *this);
}
int OperationTree::add_substitution(int t, const map<int,int>& subst,
const OperationTree& otree)
{
// return substitution of t if it is in the map
map<int,int>::const_iterator it = subst.find(t);
if (subst.end() != it)
return (*it).second;
int nary = otree.terms[t].nary();
if (nary == 2) {
// return the binary operation of the substituted terms
int t1 = add_substitution(otree.terms[t].getOp1(), subst, otree);
int t2 = add_substitution(otree.terms[t].getOp2(), subst, otree);
return add_binary(otree.terms[t].getCode(), t1, t2);
} else if (nary == 1) {
// return the unary operation of the substituted term
int t1 = add_substitution(otree.terms[t].getOp1(), subst, otree);
return add_unary(otree.terms[t].getCode(), t1);
} else {
// if t is not the first num_constants, and otree is not this
// tree, then raise and exception. Otherwise return t, since
// it is either a special term (having the same semantics in
// both trees), or the trees are the same, hence t has the
// same semantics
if (t < num_constants || this == &otree)
return t;
else {
throw ogu::Exception(__FILE__,__LINE__,
"Incomplete substitution map in OperationTree::add_substitution");
return -1;
}
}
}
void OperationTree::nularify(int t)
{
// remove the original operation from opmap
_Topmap::iterator it = opmap.find(terms[t]);
if (it != opmap.end())
opmap.erase(it);
// turn the operation to nulary
Operation nulary_op;
terms[t] = nulary_op;
// update last nulary
if (last_nulary < t)
last_nulary = t;
// update nul_incidence information for all terms including t
update_nul_incidence_after_nularify(t);
}
void OperationTree::register_derivative(int t, int v, int tder)
{
// todo: might check that the insert inserts a new pair
derivatives[t].insert(_Tderivmap::value_type(v, tder));
}
unordered_set<int> OperationTree::select_terms(int t, const opselector& sel) const
{
unordered_set<int> subterms;
select_terms(t, sel, subterms);
return subterms;
}
void OperationTree::select_terms(int t, const opselector& sel, unordered_set<int>& subterms) const
{
const Operation& op = terms[t];
if (sel(t))
subterms.insert(t);
else
if (op.nary() == 2) {
select_terms(op.getOp1(), sel, subterms);
select_terms(op.getOp2(), sel, subterms);
} else if (op.nary() == 1) {
select_terms(op.getOp1(), sel, subterms);
}
}
unordered_set<int> OperationTree::select_terms_inv(int t, const opselector& sel) const
{
unordered_set<int> subterms;
select_terms_inv(t, sel, subterms);
return subterms;
}
bool OperationTree::select_terms_inv(int t, const opselector& sel, unordered_set<int>& subterms) const
{
const Operation& op = terms[t];
if (op.nary() == 2) {
bool a1 = select_terms_inv(op.getOp1(), sel, subterms);
bool a2 = select_terms_inv(op.getOp2(), sel, subterms);
if (a1 && a2 && sel(t)) {
subterms.insert(t);
return true;
}
} else if (op.nary() == 1) {
bool a1 = select_terms_inv(op.getOp1(), sel, subterms);
if (a1 && sel(t)) {
subterms.insert(t);
return true;
}
} else {
if (sel(t)) {
subterms.insert(t);
return true;
}
}
return false;
}
void OperationTree::forget_derivative_maps()
{
for (unsigned int i = 0; i < derivatives.size(); i++)
derivatives[i].clear();
}
void OperationTree::print_operation_tree(int t, FILE* fd, OperationFormatter& f) const
{
f.format(terms[t], t, fd);
}
void OperationTree::print_operation(int t) const
{
DefaultOperationFormatter dof(*this);
print_operation_tree(t, stdout, dof);
}
void OperationTree::update_nul_incidence_after_nularify(int t)
{
unordered_set<int> updated;
for (int tnode = num_constants; tnode < (int)terms.size(); tnode++) {
const Operation& op = terms[tnode];
if (op.nary() == 2) {
int op1 = op.getOp1();
int op2 = op.getOp2();
if (op1 >= tnode || op2 >= tnode)
throw ogu::Exception(__FILE__,__LINE__,
"Tree disorder asserted");
bool updated1 = (updated.end() != updated.find(op1));
bool updated2 = (updated.end() != updated.find(op2));
if (updated1 || updated2) {
nul_incidence[tnode] = nul_incidence[op1];
nul_incidence[tnode].insert(nul_incidence[op2].begin(), nul_incidence[op2].end());
updated.insert(tnode);
}
} else if (op.nary() == 1) {
int op1 = op.getOp1();
if (op1 >= tnode)
throw ogu::Exception(__FILE__,__LINE__,
"Tree disorder asserted");
bool updated1 = (updated.end() != updated.find(op1));
if (updated1) {
nul_incidence[tnode] = nul_incidence[op1];
updated.insert(tnode);
}
} else if (op.nary() == 0) {
if (tnode == t) {
nul_incidence[tnode].clear();
nul_incidence[tnode].insert(tnode);
updated.insert(tnode);
}
}
}
}
EvalTree::EvalTree(const OperationTree& ot, int last)
: otree(ot),
values(new double[(last==-1)? ot.terms.size() : last+1]),
flags(new bool[(last==-1)? ot.terms.size() : last+1]),
last_operation((last==-1)? ot.terms.size()-1 : last)
{
if (last_operation < OperationTree::num_constants-1 ||
last_operation > (int)ot.terms.size()-1)
throw ogu::Exception(__FILE__,__LINE__,
"Wrong last in EvalTree constructor.");
values[0] = 0.0;
flags[0] = true;
values[1] = 1.0;
flags[1] = true;
values[2] = std::numeric_limits<double>::quiet_NaN();
flags[2] = true;
values[3] = 2.0/sqrt(M_PI);
flags[3] = true;
// this sets from num_constants on
reset_all();
}
void EvalTree::reset_all()
{
for (int i = OperationTree::num_constants; i <= last_operation; i++)
flags[i] = false;
}
void EvalTree::set_nulary(int t, double val)
{
if (t < 0 || t > last_operation)
throw ogu::Exception(__FILE__,__LINE__,
"The tree index out of bounds in EvalTree::set_nulary");
if (t < OperationTree::num_constants || otree.terms[t].nary() != 0)
throw ogu::Exception(__FILE__,__LINE__,
"The term is not nulary assignable in EvalTree::set_nulary");
values[t] = val;
flags[t] = true;
}
double EvalTree::eval(int t)
{
if (t < 0 || t > last_operation)
throw ogu::Exception(__FILE__,__LINE__,
"The tree index out of bounds in EvalTree::eval");
if (otree.terms[t].nary() == 0 && flags[t] == false)
throw ogu::Exception(__FILE__,__LINE__,
"Nulary term has not been assigned a value in EvalTree::eval");
if (! flags[t]) {
const Operation& op = otree.terms[t];
if (op.nary() == 1) {
double r1 = eval(op.getOp1());
double res;
if (op.getCode() == UMINUS)
res = -r1;
else if (op.getCode() == LOG)
res = log(r1);
else if (op.getCode() == EXP)
res = exp(r1);
else if (op.getCode() == SIN)
res = sin(r1);
else if (op.getCode() == COS)
res = cos(r1);
else if (op.getCode() == TAN)
res = tan(r1);
else if (op.getCode() == SQRT)
res = sqrt(r1);
else if (op.getCode() == ERF)
res = 1-erffc(r1);
else if (op.getCode() == ERFC)
res = erffc(r1);
else {
throw ogu::Exception(__FILE__,__LINE__,
"Unknown unary operation code in EvalTree::eval");
res = 0.0;
}
values[t] = res;
flags[t] = true;
} else if (op.nary() == 2) {
double res;
if (op.getCode() == PLUS) {
double r1 = eval(op.getOp1());
double r2 = eval(op.getOp2());
res = r1 + r2;
} else if (op.getCode() == MINUS) {
double r1 = eval(op.getOp1());
double r2 = eval(op.getOp2());
res = r1 - r2;
} else if (op.getCode() == TIMES) {
// pickup less complex formula first
unsigned int nul1 = otree.nulary_of_term(op.getOp1()).size();
unsigned int nul2 = otree.nulary_of_term(op.getOp2()).size();
if (nul1 < nul2) {
double r1 = eval(op.getOp1());
if (r1 == 0.0)
res = 0.0;
else {
double r2 = eval(op.getOp2());
res = r1 * r2;
}
} else {
double r2 = eval(op.getOp2());
if (r2 == 0)
res = 0.0;
else {
double r1 = eval(op.getOp1());
res = r1*r2;
}
}
} else if (op.getCode() == DIVIDE) {
double r1 = eval(op.getOp1());
if (r1 == 0)
res = 0.0;
else {
double r2 = eval(op.getOp2());
res = r1 / r2;
}
} else if (op.getCode() == POWER) {
// suppose that more complex is the first op in average
double r2 = eval(op.getOp2());
if (r2 == 0.0)
res = 1.0;
else {
double r1 = eval(op.getOp1());
res = pow(r1, r2);
}
} else {
throw ogu::Exception(__FILE__,__LINE__,
"Unknown binary operation code in EvalTree::eval");
res = 0.0;
}
values[t] = res;
flags[t] = true;
}
return values[t];
}
// if (! std::isfinite(values[t]))
// printf("Tree value t=%d is not finite = %f\n", t, values[t]);
return values[t];
}
void EvalTree::print() const
{
printf("last_op=%d\n", last_operation);
printf(" 0 1 2 3 4 5 6 7 8 9\n");
printf("----------------------------------------------------------------\n");
for (int i = 0; i <= (last_operation+1)/10; i++) {
printf("%-3d|", i);
int j = 0;
while (j < 10 && 10*i+j < last_operation+1) {
int k = 10*i+j;
if (flags[k])
printf(" %5.1g", values[k]);
else
printf(" -----");
j++;
}
printf("\n");
}
}
void DefaultOperationFormatter::format(const Operation& op, int t, FILE* fd)
{
// add to the stop_set
if (stop_set.end() == stop_set.find(t))
stop_set.insert(t);
else
return;
// call recursively non-nulary terms of the operation
if (op.nary() == 2) {
int t1 = op.getOp1();
const Operation& op1 = otree.terms[t1];
int t2 = op.getOp2();
const Operation& op2 = otree.terms[t2];
if (op1.nary() > 0)
format(op1, t1, fd);
if (op2.nary() > 0)
format(op2, t2, fd);
}
if (op.nary() == 1) {
int t1 = op.getOp1();
const Operation& op1 = otree.terms[t1];
if (op1.nary() > 0)
format(op1, t1, fd);
}
// print 'term ='
format_term(t, fd);
fprintf(fd, " = ");
if (op.nary() == 0) {
format_nulary(t, fd);
} else if (op.nary() == 1) {
int t1 = op.getOp1();
const Operation& op1 = otree.terms[t1];
const char* opname = "unknown";
switch (op.getCode()) {
case UMINUS:
opname = "-";
break;
case LOG:
opname = "log";
break;
case EXP:
opname = "exp";
break;
case SIN:
opname = "sin";
break;
case COS:
opname = "cos";
break;
case TAN:
opname = "tan";
break;
case SQRT:
opname = "sqrt";
break;
case ERF:
opname = "erf";
break;
case ERFC:
opname = "erfc";
break;
default:
break;
}
fprintf(fd, "%s(", opname);
if (op1.nary() == 0)
format_nulary(t1, fd);
else
format_term(t1, fd);
fprintf(fd, ")");
} else {
int t1 = op.getOp1();
const Operation& op1 = otree.terms[t1];
int t2 = op.getOp2();
const Operation& op2 = otree.terms[t2];
const char* opname = "unknown";
switch (op.getCode()) {
case PLUS:
opname = "+";
break;
case MINUS:
opname = "-";
break;
case TIMES:
opname = "*";
break;
case DIVIDE:
opname = "/";
break;
case POWER:
opname = "^";
break;
default:
break;
}
if (op1.nary() == 0)
format_nulary(t1, fd);
else
format_term(t1, fd);
fprintf(fd, " %s ", opname);
if (op2.nary() == 0)
format_nulary(t2, fd);
else
format_term(t2, fd);
}
print_delim(fd);
}
void DefaultOperationFormatter::format_term(int t, FILE* fd) const
{
fprintf(fd, "$%d", t);
}
void DefaultOperationFormatter::format_nulary(int t, FILE* fd) const
{
if (t == OperationTree::zero)
fprintf(fd, "0");
else if (t == OperationTree::one)
fprintf(fd, "1");
else if (t == OperationTree::nan)
fprintf(fd, "NaN");
else
fprintf(fd, "$%d", t);
}
void DefaultOperationFormatter::print_delim(FILE* fd) const
{
fprintf(fd, ";\n");
}
std::string OperationStringConvertor::convert(const Operation& op, int t) const
{
if (op.nary() == 0) {
if (t < OperationTree::num_constants)
if (t == OperationTree::zero)
return std::string("0");
else if (t == OperationTree::one)
return std::string("1");
else if (t == OperationTree::nan)
return std::string("NaN");
else if (t == OperationTree::two_over_pi) {
char buf[100];
sprintf(buf, "%20.16g", 2.0/std::sqrt(M_PI));
return std::string(buf);
} else {
return std::string("error!error");
}
else
return nulsc.convert(t);
} else if (op.nary() == 1) {
int t1 = op.getOp1();
const Operation& op1 = otree.operation(t1);
const char* opname = "unknown";
switch (op.getCode()) {
case UMINUS:
opname = "-";
break;
case LOG:
opname = "log";
break;
case EXP:
opname = "exp";
break;
case SIN:
opname = "sin";
break;
case COS:
opname = "cos";
break;
case TAN:
opname = "tan";
break;
case SQRT:
opname = "sqrt";
break;
case ERF:
opname = "erf";
break;
case ERFC:
opname = "erfc";
break;
default:
break;
}
std::string s1 = convert(op1, t1);
return std::string(opname) + "(" + s1 + ")";
} else {
int t1 = op.getOp1();
const Operation& op1 = otree.operation(t1);
int t2 = op.getOp2();
const Operation& op2 = otree.operation(t2);
const char* opname = "unknown";
switch (op.getCode()) {
case PLUS:
opname = "+";
break;
case MINUS:
opname = "-";
break;
case TIMES:
opname = "*";
break;
case DIVIDE:
opname = "/";
break;
case POWER:
opname = "^";
break;
default:
break;
}
// decide about parenthesis
bool op1_par = true;
bool op2_par = true;
if (op.getCode() == PLUS) {
op1_par = false;
op2_par = false;
} else if (op.getCode() == MINUS) {
op1_par = false;
if (op2.getCode() != MINUS && op2.getCode() != PLUS)
op2_par = false;
} else {
if (op1.nary() < 2)
op1_par = false;
if (op2.nary() < 2)
op2_par = false;
}
std::string res;
if (op1_par)
res += "(";
res += convert(op1, t1);
if (op1_par)
res += ")";
res += " ";
res += opname;
res += " ";
if (op2_par)
res += "(";
res += convert(op2, t2);
if (op2_par)
res += ")";
return res;
}
}
// Local Variables:
// mode:C++
// End:

View File

@ -3,22 +3,22 @@ bin_PROGRAMS = dynare++
GENERATED_FILES = dynglob_ll.cc dynglob_tab.cc dynglob_tab.hh
dynare___SOURCES = \
main.cpp \
dynare3.cpp \
dynare_atoms.h \
dynare_model.h \
forw_subst_builder.h \
planner_builder.cpp \
dynare3.h \
dynare_exception.h \
dynare_params.cpp \
planner_builder.h \
dynare_atoms.cpp \
dynare_model.cpp \
dynare_params.h \
forw_subst_builder.cpp \
nlsolve.cpp \
nlsolve.h \
main.cc \
dynare3.cc \
dynare_atoms.hh \
dynare_model.hh \
forw_subst_builder.hh \
planner_builder.cc \
dynare3.hh \
dynare_exception.hh \
dynare_params.cc \
planner_builder.hh \
dynare_atoms.cc \
dynare_model.cc \
dynare_params.hh \
forw_subst_builder.cc \
nlsolve.cc \
nlsolve.hh \
$(GENERATED_FILES)
dynare___CPPFLAGS = -I../sylv/cc -I../tl/cc -I../kord -I../integ/cc -I.. -I$(top_srcdir)/mex/sources -DDYNVERSION=\"$(PACKAGE_VERSION)\" $(BOOST_CPPFLAGS) $(CPPFLAGS_MATIO)
@ -27,10 +27,10 @@ dynare___LDADD = ../kord/libkord.a ../integ/cc/libinteg.a ../tl/cc/libtl.a ../pa
dynare___CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
BUILT_SOURCES = $(GENERATED_FILES)
EXTRA_DIST = dynglob.lex dynglob.y
EXTRA_DIST = dynglob.ll dynglob.yy
dynglob_tab.cc dynglob_tab.hh: dynglob.y
$(YACC) -d -odynglob_tab.cc dynglob.y
dynglob_tab.cc dynglob_tab.hh: dynglob.yy
$(YACC) -d -odynglob_tab.cc dynglob.yy
dynglob_ll.cc: dynglob.lex
$(LEX) -i -odynglob_ll.cc dynglob.lex
dynglob_ll.cc: dynglob.ll
$(LEX) -i -odynglob_ll.cc dynglob.ll

390
dynare++/src/dynare3.cc Normal file
View File

@ -0,0 +1,390 @@
#include "dynare3.hh"
#include "dynare_exception.hh"
#include "planner_builder.hh"
#include "forw_subst_builder.hh"
#include "utils/cc/memory_file.hh"
#include "utils/cc/exception.hh"
#include "parser/cc/parser_exception.hh"
#include "parser/cc/atom_substitutions.hh"
#include "../tl/cc/tl_exception.hh"
#include "../kord/kord_exception.hh"
#ifndef DYNVERSION
# define DYNVERSION "unknown"
#endif
/**************************************************************************************/
/* DynareNameList class */
/**************************************************************************************/
vector<int>
DynareNameList::selectIndices(const vector<const char *> &ns) const
{
vector<int> res;
for (unsigned int i = 0; i < ns.size(); i++)
{
int j = 0;
while (j < getNum() && strcmp(getName(j), ns[i]) != 0)
j++;
if (j == getNum())
throw DynareException(__FILE__, __LINE__,
string("Couldn't find name for ") + ns[i]
+" in DynareNameList::selectIndices");
res.push_back(j);
}
return res;
}
/**************************************************************************************/
/* Dynare class */
/**************************************************************************************/
Dynare::Dynare(const char *modname, int ord, double sstol, Journal &jr)
: journal(jr), model(NULL), ysteady(NULL), md(1), dnl(NULL), denl(NULL), dsnl(NULL),
fe(NULL), fde(NULL), ss_tol(sstol)
{
// make memory file
ogu::MemoryFile mf(modname);
if (mf.exists())
{
try
{
model = new ogdyn::DynareParser(mf.base(), mf.length(), ord);
}
catch (const ogp::ParserException &pe)
{
int line;
int col;
mf.line_and_col(pe.offset(), line, col);
throw DynareException(pe.message(), modname, line, col);
}
ysteady = new Vector(model->getAtoms().ny());
dnl = new DynareNameList(*this);
denl = new DynareExogNameList(*this);
dsnl = new DynareStateNameList(*this, *dnl, *denl);
fe = new ogp::FormulaEvaluator(model->getParser());
fde = new ogp::FormulaDerEvaluator(model->getParser());
writeModelInfo(journal);
}
else
{
throw DynareException(__FILE__, __LINE__, string("Could not open model file ")+modname);
}
}
Dynare::Dynare(const char **endo, int num_endo,
const char **exo, int num_exo,
const char **par, int num_par,
const char *equations, int len, int ord,
double sstol, Journal &jr)
: journal(jr), model(NULL), ysteady(NULL), md(1), dnl(NULL), denl(NULL), dsnl(NULL),
fe(NULL), fde(NULL), ss_tol(sstol)
{
try
{
model = new ogdyn::DynareSPModel(endo, num_endo, exo, num_exo, par, num_par,
equations, len, ord);
}
catch (const ogp::ParserException &pe)
{
throw DynareException(pe.message(), pe.offset());
}
ysteady = new Vector(model->getAtoms().ny());
dnl = new DynareNameList(*this);
denl = new DynareExogNameList(*this);
dsnl = new DynareStateNameList(*this, *dnl, *denl);
fe = new ogp::FormulaEvaluator(model->getParser());
fde = new ogp::FormulaDerEvaluator(model->getParser());
writeModelInfo(journal);
}
Dynare::Dynare(const Dynare &dynare)
: journal(dynare.journal), model(NULL),
ysteady(NULL), md(dynare.md),
dnl(NULL), denl(NULL), dsnl(NULL), fe(NULL), fde(NULL),
ss_tol(dynare.ss_tol)
{
model = dynare.model->clone();
ysteady = new Vector(*(dynare.ysteady));
dnl = new DynareNameList(*this);
denl = new DynareExogNameList(*this);
dsnl = new DynareStateNameList(*this, *dnl, *denl);
fe = new ogp::FormulaEvaluator(model->getParser());
fde = new ogp::FormulaDerEvaluator(model->getParser());
}
Dynare::~Dynare()
{
if (model)
delete model;
if (ysteady)
delete ysteady;
if (dnl)
delete dnl;
if (dsnl)
delete dsnl;
if (denl)
delete denl;
if (fe)
delete fe;
if (fde)
delete fde;
}
void
Dynare::writeMat(mat_t *fd, const char *prefix) const
{
char tmp[100];
sprintf(tmp, "%s_vars", prefix);
getAllEndoNames().writeMat(fd, tmp);
getAllEndoNames().writeMatIndices(fd, prefix);
sprintf(tmp, "%s_state_vars", prefix);
getStateNames().writeMat(fd, tmp);
sprintf(tmp, "%s_shocks", prefix);
getExogNames().writeMat(fd, tmp);
getExogNames().writeMatIndices(fd, prefix);
sprintf(tmp, "%s_vcov_exo", prefix);
model->getVcov().writeMat(fd, tmp);
TwoDMatrix aux(1, 1);
sprintf(tmp, "%s_nstat", prefix);
aux.get(0, 0) = nstat();
aux.writeMat(fd, tmp);
sprintf(tmp, "%s_npred", prefix);
aux.get(0, 0) = npred();
aux.writeMat(fd, tmp);
sprintf(tmp, "%s_nboth", prefix);
aux.get(0, 0) = nboth();
aux.writeMat(fd, tmp);
sprintf(tmp, "%s_nforw", prefix);
aux.get(0, 0) = nforw();
aux.writeMat(fd, tmp);
}
void
Dynare::writeDump(const std::string &basename) const
{
std::string fname(basename);
fname += ".dump";
std::ofstream out(fname.c_str());
model->dump_model(out);
out.close();
}
void
Dynare::solveDeterministicSteady(Vector &steady)
{
JournalRecordPair pa(journal);
pa << "Non-linear solver for deterministic steady state" << endrec;
steady = (const Vector &) model->getInit();
DynareVectorFunction dvf(*this);
DynareJacobian dj(*this);
ogu::NLSolver nls(dvf, dj, 500, ss_tol, journal);
int iter;
if (!nls.solve(steady, iter))
throw DynareException(__FILE__, __LINE__,
"Could not obtain convergence in non-linear solver");
}
// evaluate system at given y_t=y_{t+1}=y_{t-1}, and given shocks x_t
void
Dynare::evaluateSystem(Vector &out, const Vector &yy, const Vector &xx)
{
ConstVector yym(yy, nstat(), nys());
ConstVector yyp(yy, nstat()+npred(), nyss());
evaluateSystem(out, yym, yy, yyp, xx);
}
// evaluate system at given y^*_{t-1}, y_t, y^{**}_{t+1} and at
// exogenous x_t, all three vectors yym, yy, and yyp have the
// respective lengths of y^*_{t-1}, y_t, y^{**}_{t+1}
void
Dynare::evaluateSystem(Vector &out, const Vector &yym, const Vector &yy,
const Vector &yyp, const Vector &xx)
{
ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx);
DynareEvalLoader del(model->getAtoms(), out);
fe->eval(dav, del);
}
void
Dynare::calcDerivatives(const Vector &yy, const Vector &xx)
{
ConstVector yym(yy, nstat(), nys());
ConstVector yyp(yy, nstat()+npred(), nyss());
ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx);
DynareDerEvalLoader ddel(model->getAtoms(), md, model->getOrder());
for (int iord = 1; iord <= model->getOrder(); iord++)
fde->eval(dav, ddel, iord);
}
void
Dynare::calcDerivativesAtSteady()
{
Vector xx(nexog());
xx.zeros();
calcDerivatives(*ysteady, xx);
}
void
Dynare::writeModelInfo(Journal &jr) const
{
// write info on variables
{
JournalRecordPair rp(journal);
rp << "Information on variables" << endrec;
JournalRecord rec1(journal);
rec1 << "Number of endogenous: " << ny() << endrec;
JournalRecord rec2(journal);
rec2 << "Number of exogenous: " << nexog() << endrec;
JournalRecord rec3(journal);
rec3 << "Number of static: " << nstat() << endrec;
JournalRecord rec4(journal);
rec4 << "Number of predetermined: " << npred()+nboth() << endrec;
JournalRecord rec5(journal);
rec5 << "Number of forward looking: " << nforw()+nboth() << endrec;
JournalRecord rec6(journal);
rec6 << "Number of both: " << nboth() << endrec;
}
// write info on planner variables
const ogdyn::PlannerInfo *pinfo = model->get_planner_info();
if (pinfo)
{
JournalRecordPair rp(journal);
rp << "Information on planner variables" << endrec;
JournalRecord rec1(journal);
rec1 << "Number of Lagrange multipliers: " << pinfo->num_lagrange_mults << endrec;
JournalRecord rec2(journal);
rec2 << "Number of auxiliary variables: " << pinfo->num_aux_variables << endrec;
JournalRecord rec3(journal);
rec3 << "Number of new terms in the tree: " << pinfo->num_new_terms << endrec;
}
// write info on forward substitutions
const ogdyn::ForwSubstInfo *finfo = model->get_forw_subst_info();
if (finfo)
{
JournalRecordPair rp(journal);
rp << "Information on forward substitutions" << endrec;
JournalRecord rec1(journal);
rec1 << "Number of affected equations: " << finfo->num_affected_equations << endrec;
JournalRecord rec2(journal);
rec2 << "Number of substituted terms: " << finfo->num_subst_terms << endrec;
JournalRecord rec3(journal);
rec3 << "Number of auxiliary variables: " << finfo->num_aux_variables << endrec;
JournalRecord rec4(journal);
rec4 << "Number of new terms in the tree: " << finfo->num_new_terms << endrec;
}
// write info on substitutions
const ogp::SubstInfo *sinfo = model->get_subst_info();
if (sinfo)
{
JournalRecordPair rp(journal);
rp << "Information on substitutions" << endrec;
JournalRecord rec1(journal);
rec1 << "Number of substitutions: " << sinfo->num_substs << endrec;
}
}
DynareNameList::DynareNameList(const Dynare &dynare)
{
for (int i = 0; i < dynare.ny(); i++)
{
int j = dynare.model->getAtoms().y2outer_endo()[i];
const char *name = dynare.model->getAtoms().get_endovars()[j];
names.push_back(name);
}
}
DynareStateNameList::DynareStateNameList(const Dynare &dynare, const DynareNameList &dnl,
const DynareExogNameList &denl)
{
for (int i = 0; i < dynare.nys(); i++)
names.push_back(dnl.getName(i+dynare.nstat()));
for (int i = 0; i < dynare.nexog(); i++)
names.push_back(denl.getName(i));
}
DynareExogNameList::DynareExogNameList(const Dynare &dynare)
{
for (int i = 0; i < dynare.nexog(); i++)
{
int j = dynare.model->getAtoms().y2outer_exo()[i];
const char *name = dynare.model->getAtoms().get_exovars()[j];
names.push_back(name);
}
}
DynareEvalLoader::DynareEvalLoader(const ogp::FineAtoms &a, Vector &out)
: Vector(out)
{
if (a.ny() != out.length())
throw DynareException(__FILE__, __LINE__, "Wrong length of out vector in DynareEvalLoader constructor");
}
/** This clears the container of model derivatives and initializes it
* inserting empty sparse tensors up to the given order. */
DynareDerEvalLoader::DynareDerEvalLoader(const ogp::FineAtoms &a,
TensorContainer<FSSparseTensor> &mod_ders,
int order)
: atoms(a), md(mod_ders)
{
md.clear();
for (int iord = 1; iord <= order; iord++)
{
FSSparseTensor *t = new FSSparseTensor(iord, atoms.ny()+atoms.nys()+atoms.nyss()+atoms.nexo(), atoms.ny());
md.insert(t);
}
}
void
DynareDerEvalLoader::load(int i, int iord, const int *vars, double res)
{
FSSparseTensor *t = md.get(Symmetry(iord));
IntSequence s(iord, 0);
for (int j = 0; j < iord; j++)
s[j] = atoms.get_pos_of_all(vars[j]);
t->insert(s, i, res);
}
DynareJacobian::DynareJacobian(Dynare &dyn)
: Jacobian(dyn.ny()), d(dyn)
{
zeros();
}
void
DynareJacobian::eval(const Vector &yy)
{
ogdyn::DynareSteadyAtomValues
dav(d.getModel().getAtoms(), d.getModel().getParams(), yy);
zeros();
d.fde->eval(dav, *this, 1);
}
void
DynareJacobian::load(int i, int iord, const int *vars, double res)
{
if (iord != 1)
throw DynareException(__FILE__, __LINE__,
"Derivative order different from order=1 in DynareJacobian::load");
int t = vars[0];
int j = d.getModel().getAtoms().get_pos_of_all(t);
if (j < d.nyss())
get(i, j+d.nstat()+d.npred()) += res;
else if (j < d.nyss()+d.ny())
get(i, j-d.nyss()) += res;
else if (j < d.nyss()+d.ny()+d.nys())
get(i, j-d.nyss()-d.ny()+d.nstat()) += res;
}
void
DynareVectorFunction::eval(const ConstVector &in, Vector &out)
{
check_for_eval(in, out);
Vector xx(d.nexog());
xx.zeros();
d.evaluateSystem(out, in, xx);
}

View File

@ -1,364 +0,0 @@
#include "dynare3.h"
#include "dynare_exception.h"
#include "planner_builder.h"
#include "forw_subst_builder.h"
#include "utils/cc/memory_file.h"
#include "utils/cc/exception.h"
#include "parser/cc/parser_exception.h"
#include "parser/cc/atom_substitutions.h"
#include "../tl/cc/tl_exception.hh"
#include "../kord/kord_exception.hh"
#ifndef DYNVERSION
#define DYNVERSION "unknown"
#endif
/**************************************************************************************/
/* DynareNameList class */
/**************************************************************************************/
vector<int> DynareNameList::selectIndices(const vector<const char*>& ns) const
{
vector<int> res;
for (unsigned int i = 0; i < ns.size(); i++) {
int j = 0;
while (j < getNum() && strcmp(getName(j), ns[i]) != 0)
j++;
if (j == getNum())
throw DynareException(__FILE__, __LINE__,
string("Couldn't find name for ") + ns[i] +
" in DynareNameList::selectIndices");
res.push_back(j);
}
return res;
}
/**************************************************************************************/
/* Dynare class */
/**************************************************************************************/
Dynare::Dynare(const char* modname, int ord, double sstol, Journal& jr)
: journal(jr), model(NULL), ysteady(NULL), md(1), dnl(NULL), denl(NULL), dsnl(NULL),
fe(NULL), fde(NULL), ss_tol(sstol)
{
// make memory file
ogu::MemoryFile mf(modname);
if (mf.exists()) {
try {
model = new ogdyn::DynareParser(mf.base(), mf.length(), ord);
} catch (const ogp::ParserException& pe) {
int line;
int col;
mf.line_and_col(pe.offset(), line, col);
throw DynareException(pe.message(), modname, line, col);
}
ysteady = new Vector(model->getAtoms().ny());
dnl = new DynareNameList(*this);
denl = new DynareExogNameList(*this);
dsnl = new DynareStateNameList(*this, *dnl, *denl);
fe = new ogp::FormulaEvaluator(model->getParser());
fde = new ogp::FormulaDerEvaluator(model->getParser());
writeModelInfo(journal);
} else {
throw DynareException(__FILE__, __LINE__, string("Could not open model file ")+modname);
}
}
Dynare::Dynare(const char** endo, int num_endo,
const char** exo, int num_exo,
const char** par, int num_par,
const char* equations, int len, int ord,
double sstol, Journal& jr)
: journal(jr), model(NULL), ysteady(NULL), md(1), dnl(NULL), denl(NULL), dsnl(NULL),
fe(NULL), fde(NULL), ss_tol(sstol)
{
try {
model = new ogdyn::DynareSPModel(endo, num_endo, exo, num_exo, par, num_par,
equations, len, ord);
} catch (const ogp::ParserException& pe) {
throw DynareException(pe.message(), pe.offset());
}
ysteady = new Vector(model->getAtoms().ny());
dnl = new DynareNameList(*this);
denl = new DynareExogNameList(*this);
dsnl = new DynareStateNameList(*this, *dnl, *denl);
fe = new ogp::FormulaEvaluator(model->getParser());
fde = new ogp::FormulaDerEvaluator(model->getParser());
writeModelInfo(journal);
}
Dynare::Dynare(const Dynare& dynare)
: journal(dynare.journal), model(NULL),
ysteady(NULL), md(dynare.md),
dnl(NULL), denl(NULL), dsnl(NULL), fe(NULL), fde(NULL),
ss_tol(dynare.ss_tol)
{
model = dynare.model->clone();
ysteady = new Vector(*(dynare.ysteady));
dnl = new DynareNameList(*this);
denl = new DynareExogNameList(*this);
dsnl = new DynareStateNameList(*this, *dnl, *denl);
fe = new ogp::FormulaEvaluator(model->getParser());
fde = new ogp::FormulaDerEvaluator(model->getParser());
}
Dynare::~Dynare()
{
if (model)
delete model;
if (ysteady)
delete ysteady;
if (dnl)
delete dnl;
if (dsnl)
delete dsnl;
if (denl)
delete denl;
if (fe)
delete fe;
if (fde)
delete fde;
}
void Dynare::writeMat(mat_t* fd, const char* prefix) const
{
char tmp[100];
sprintf(tmp, "%s_vars", prefix);
getAllEndoNames().writeMat(fd, tmp);
getAllEndoNames().writeMatIndices(fd, prefix);
sprintf(tmp, "%s_state_vars", prefix);
getStateNames().writeMat(fd, tmp);
sprintf(tmp, "%s_shocks", prefix);
getExogNames().writeMat(fd, tmp);
getExogNames().writeMatIndices(fd, prefix);
sprintf(tmp, "%s_vcov_exo", prefix);
model->getVcov().writeMat(fd, tmp);
TwoDMatrix aux(1,1);
sprintf(tmp, "%s_nstat", prefix);
aux.get(0,0) = nstat();
aux.writeMat(fd, tmp);
sprintf(tmp, "%s_npred", prefix);
aux.get(0,0) = npred();
aux.writeMat(fd, tmp);
sprintf(tmp, "%s_nboth", prefix);
aux.get(0,0) = nboth();
aux.writeMat(fd, tmp);
sprintf(tmp, "%s_nforw", prefix);
aux.get(0,0) = nforw();
aux.writeMat(fd, tmp);
}
void Dynare::writeDump(const std::string& basename) const
{
std::string fname(basename);
fname += ".dump";
std::ofstream out(fname.c_str());
model->dump_model(out);
out.close();
}
void Dynare::solveDeterministicSteady(Vector& steady)
{
JournalRecordPair pa(journal);
pa << "Non-linear solver for deterministic steady state" << endrec;
steady = (const Vector&) model->getInit();
DynareVectorFunction dvf(*this);
DynareJacobian dj(*this);
ogu::NLSolver nls(dvf, dj, 500, ss_tol, journal);
int iter;
if (! nls.solve(steady, iter))
throw DynareException(__FILE__, __LINE__,
"Could not obtain convergence in non-linear solver");
}
// evaluate system at given y_t=y_{t+1}=y_{t-1}, and given shocks x_t
void Dynare::evaluateSystem(Vector& out, const Vector& yy, const Vector& xx)
{
ConstVector yym(yy, nstat(), nys());
ConstVector yyp(yy, nstat()+npred(), nyss());
evaluateSystem(out, yym, yy, yyp, xx);
}
// evaluate system at given y^*_{t-1}, y_t, y^{**}_{t+1} and at
// exogenous x_t, all three vectors yym, yy, and yyp have the
// respective lengths of y^*_{t-1}, y_t, y^{**}_{t+1}
void Dynare::evaluateSystem(Vector& out, const Vector& yym, const Vector& yy,
const Vector& yyp, const Vector& xx)
{
ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx);
DynareEvalLoader del(model->getAtoms(), out);
fe->eval(dav, del);
}
void Dynare::calcDerivatives(const Vector& yy, const Vector& xx)
{
ConstVector yym(yy, nstat(), nys());
ConstVector yyp(yy, nstat()+npred(), nyss());
ogdyn::DynareAtomValues dav(model->getAtoms(), model->getParams(), yym, yy, yyp, xx);
DynareDerEvalLoader ddel(model->getAtoms(), md, model->getOrder());
for (int iord = 1; iord <= model->getOrder(); iord++)
fde->eval(dav, ddel, iord);
}
void Dynare::calcDerivativesAtSteady()
{
Vector xx(nexog());
xx.zeros();
calcDerivatives(*ysteady, xx);
}
void Dynare::writeModelInfo(Journal& jr) const
{
// write info on variables
{
JournalRecordPair rp(journal);
rp << "Information on variables" << endrec;
JournalRecord rec1(journal);
rec1 << "Number of endogenous: " << ny() << endrec;
JournalRecord rec2(journal);
rec2 << "Number of exogenous: " << nexog() << endrec;
JournalRecord rec3(journal);
rec3 << "Number of static: " << nstat() << endrec;
JournalRecord rec4(journal);
rec4 << "Number of predetermined: " << npred()+nboth() << endrec;
JournalRecord rec5(journal);
rec5 << "Number of forward looking: " << nforw()+nboth() << endrec;
JournalRecord rec6(journal);
rec6 << "Number of both: " << nboth() << endrec;
}
// write info on planner variables
const ogdyn::PlannerInfo* pinfo = model->get_planner_info();
if (pinfo) {
JournalRecordPair rp(journal);
rp << "Information on planner variables" << endrec;
JournalRecord rec1(journal);
rec1 << "Number of Lagrange multipliers: " << pinfo->num_lagrange_mults << endrec;
JournalRecord rec2(journal);
rec2 << "Number of auxiliary variables: " << pinfo->num_aux_variables << endrec;
JournalRecord rec3(journal);
rec3 << "Number of new terms in the tree: " << pinfo->num_new_terms << endrec;
}
// write info on forward substitutions
const ogdyn::ForwSubstInfo* finfo = model->get_forw_subst_info();
if (finfo) {
JournalRecordPair rp(journal);
rp << "Information on forward substitutions" << endrec;
JournalRecord rec1(journal);
rec1 << "Number of affected equations: " << finfo->num_affected_equations << endrec;
JournalRecord rec2(journal);
rec2 << "Number of substituted terms: " << finfo->num_subst_terms << endrec;
JournalRecord rec3(journal);
rec3 << "Number of auxiliary variables: " << finfo->num_aux_variables << endrec;
JournalRecord rec4(journal);
rec4 << "Number of new terms in the tree: " << finfo->num_new_terms << endrec;
}
// write info on substitutions
const ogp::SubstInfo* sinfo = model->get_subst_info();
if (sinfo) {
JournalRecordPair rp(journal);
rp << "Information on substitutions" << endrec;
JournalRecord rec1(journal);
rec1 << "Number of substitutions: " << sinfo->num_substs << endrec;
}
}
DynareNameList::DynareNameList(const Dynare& dynare)
{
for (int i = 0; i < dynare.ny(); i++) {
int j = dynare.model->getAtoms().y2outer_endo()[i];
const char* name = dynare.model->getAtoms().get_endovars()[j];
names.push_back(name);
}
}
DynareStateNameList::DynareStateNameList(const Dynare& dynare, const DynareNameList& dnl,
const DynareExogNameList& denl)
{
for (int i = 0; i < dynare.nys(); i++)
names.push_back(dnl.getName(i+dynare.nstat()));
for (int i = 0; i < dynare.nexog(); i++)
names.push_back(denl.getName(i));
}
DynareExogNameList::DynareExogNameList(const Dynare& dynare)
{
for (int i = 0; i < dynare.nexog(); i++) {
int j = dynare.model->getAtoms().y2outer_exo()[i];
const char* name = dynare.model->getAtoms().get_exovars()[j];
names.push_back(name);
}
}
DynareEvalLoader::DynareEvalLoader(const ogp::FineAtoms& a, Vector& out)
: Vector(out)
{
if (a.ny() != out.length())
throw DynareException(__FILE__, __LINE__, "Wrong length of out vector in DynareEvalLoader constructor");
}
/** This clears the container of model derivatives and initializes it
* inserting empty sparse tensors up to the given order. */
DynareDerEvalLoader::DynareDerEvalLoader(const ogp::FineAtoms& a,
TensorContainer<FSSparseTensor>& mod_ders,
int order)
: atoms(a), md(mod_ders)
{
md.clear();
for (int iord = 1; iord <= order; iord++) {
FSSparseTensor* t = new FSSparseTensor(iord, atoms.ny()+atoms.nys()+atoms.nyss()+atoms.nexo(), atoms.ny());
md.insert(t);
}
}
void DynareDerEvalLoader::load(int i, int iord, const int* vars, double res)
{
FSSparseTensor* t = md.get(Symmetry(iord));
IntSequence s(iord, 0);
for (int j = 0; j < iord; j++)
s[j] = atoms.get_pos_of_all(vars[j]);
t->insert(s, i, res);
}
DynareJacobian::DynareJacobian(Dynare& dyn)
: Jacobian(dyn.ny()), d(dyn)
{
zeros();
}
void DynareJacobian::eval(const Vector& yy)
{
ogdyn::DynareSteadyAtomValues
dav(d.getModel().getAtoms(), d.getModel().getParams(), yy);
zeros();
d.fde->eval(dav, *this, 1);
}
void DynareJacobian::load(int i, int iord, const int* vars, double res)
{
if (iord != 1)
throw DynareException(__FILE__, __LINE__,
"Derivative order different from order=1 in DynareJacobian::load");
int t = vars[0];
int j = d.getModel().getAtoms().get_pos_of_all(t);
if (j < d.nyss())
get(i, j+d.nstat()+d.npred()) += res;
else if (j < d.nyss()+d.ny())
get(i, j-d.nyss()) += res;
else if (j < d.nyss()+d.ny()+d.nys())
get(i, j-d.nyss()-d.ny()+d.nstat()) += res;
}
void DynareVectorFunction::eval(const ConstVector& in, Vector& out)
{
check_for_eval(in, out);
Vector xx(d.nexog());
xx.zeros();
d.evaluateSystem(out, in, xx);
}

View File

@ -9,8 +9,8 @@
#include "../kord/decision_rule.hh"
#include "../kord/dynamic_model.hh"
#include "dynare_model.h"
#include "nlsolve.h"
#include "dynare_model.hh"
#include "nlsolve.hh"
#include <vector>

View File

@ -0,0 +1,310 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: dynare_atoms.cpp 1765 2008-03-31 14:32:08Z kamenik $
#include "parser/cc/parser_exception.hh"
#include "utils/cc/exception.hh"
#include "dynare_atoms.hh"
#include <string>
#include <cmath>
using namespace ogdyn;
using std::string;
void
DynareStaticAtoms::register_name(const char *name)
{
if (varnames.query(name))
throw ogp::ParserException(string("The name ")+name+" is not unique.", 0);
StaticAtoms::register_name(name);
}
int
DynareStaticAtoms::check_variable(const char *name) const
{
if (0 == varnames.query(name))
throw ogp::ParserException(std::string("Unknown name <")+name+">", 0);
Tvarmap::const_iterator it = vars.find(name);
if (it == vars.end())
return -1;
else
return (*it).second;
}
DynareDynamicAtoms::DynareDynamicAtoms(const DynareDynamicAtoms &dda)
: SAtoms(dda)
{
// fill atom_type
for (Tatypemap::const_iterator it = dda.atom_type.begin();
it != dda.atom_type.end(); ++it)
atom_type.insert(Tatypemap::value_type(varnames.query((*it).first), (*it).second));
}
void
DynareDynamicAtoms::parse_variable(const char *in, std::string &out, int &ll) const
{
ll = 0;
std::string str = in;
int left = str.find_first_of("({");
if (left != -1)
{
out = str.substr(0, left);
left++;
int right = str.find_first_of(")}", left);
if ((int) string::npos == right)
throw ogp::ParserException(
string("Syntax error when parsing Dynare atom <")+in+">.", 0);
std::string tmp(str, left, right-left);
sscanf(tmp.c_str(), "%d", &ll);
}
else
{
out = in;
}
}
void
DynareDynamicAtoms::register_uniq_endo(const char *name)
{
FineAtoms::register_uniq_endo(name);
atom_type.insert(Tatypemap::value_type(varnames.query(name), endovar));
}
void
DynareDynamicAtoms::register_uniq_exo(const char *name)
{
FineAtoms::register_uniq_exo(name);
atom_type.insert(Tatypemap::value_type(varnames.query(name), exovar));
}
void
DynareDynamicAtoms::register_uniq_param(const char *name)
{
FineAtoms::register_uniq_param(name);
atom_type.insert(Tatypemap::value_type(varnames.query(name), param));
}
bool
DynareDynamicAtoms::is_type(const char *name, atype tp) const
{
Tatypemap::const_iterator it = atom_type.find(name);
if (it != atom_type.end() && (*it).second == tp)
return true;
else
return false;
}
void
DynareDynamicAtoms::print() const
{
SAtoms::print();
printf("Name types:\n");
for (Tatypemap::const_iterator it = atom_type.begin();
it != atom_type.end(); ++it)
printf("name=%s type=%s\n", (*it).first,
((*it).second == endovar) ? "endovar" : (((*it).second == exovar) ? "exovar" : "param"));
}
std::string
DynareDynamicAtoms::convert(int t) const
{
if (t < ogp::OperationTree::num_constants)
{
throw ogu::Exception(__FILE__, __LINE__,
"Tree index is a built-in constant in DynareDynamicAtoms::convert");
return std::string();
}
if (is_constant(t))
{
double v = get_constant_value(t);
char buf[100];
sprintf(buf, "%20.16g", v);
const char *s = buf;
while (*s == ' ')
++s;
return std::string(s);
}
const char *s = name(t);
if (is_type(s, endovar))
{
int ll = lead(t);
char buf[100];
if (ll)
sprintf(buf, "%s(%d)", s, ll);
else
sprintf(buf, "%s", s);
return std::string(buf);
}
return std::string(s);
}
void
DynareAtomValues::setValues(ogp::EvalTree &et) const
{
// set constants
atoms.setValues(et);
// set parameteres
for (unsigned int i = 0; i < atoms.get_params().size(); i++)
{
if (atoms.is_referenced(atoms.get_params()[i]))
{
const ogp::DynamicAtoms::Tlagmap &lmap = atoms.lagmap(atoms.get_params()[i]);
for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it)
{
int t = (*it).second;
et.set_nulary(t, paramvals[i]);
}
}
}
// set endogenous
for (unsigned int outer_i = 0; outer_i < atoms.get_endovars().size(); outer_i++)
{
if (atoms.is_referenced(atoms.get_endovars()[outer_i]))
{
const ogp::DynamicAtoms::Tlagmap &lmap = atoms.lagmap(atoms.get_endovars()[outer_i]);
for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it)
{
int ll = (*it).first;
int t = (*it).second;
int i = atoms.outer2y_endo()[outer_i];
if (ll == -1)
{
et.set_nulary(t, yym[i-atoms.nstat()]);
}
else if (ll == 0)
et.set_nulary(t, yy[i]);
else
et.set_nulary(t, yyp[i-atoms.nstat()-atoms.npred()]);
}
}
}
// set exogenous
for (unsigned int outer_i = 0; outer_i < atoms.get_exovars().size(); outer_i++)
{
if (atoms.is_referenced(atoms.get_exovars()[outer_i]))
{
const ogp::DynamicAtoms::Tlagmap &lmap = atoms.lagmap(atoms.get_exovars()[outer_i]);
for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it)
{
int ll = (*it).first;
if (ll == 0) // this is always true because of checks
{
int t = (*it).second;
int i = atoms.outer2y_exo()[outer_i];
et.set_nulary(t, xx[i]);
}
}
}
}
}
void
DynareStaticSteadyAtomValues::setValues(ogp::EvalTree &et) const
{
// set constants
atoms_static.setValues(et);
// set parameters
for (unsigned int i = 0; i < atoms_static.get_params().size(); i++)
{
const char *name = atoms_static.get_params()[i];
int t = atoms_static.index(name);
if (t != -1)
{
int idyn = atoms.name2outer_param(name);
et.set_nulary(t, paramvals[idyn]);
}
}
// set endogenous
for (unsigned int i = 0; i < atoms_static.get_endovars().size(); i++)
{
const char *name = atoms_static.get_endovars()[i];
int t = atoms_static.index(name);
if (t != -1)
{
int idyn = atoms.outer2y_endo()[atoms.name2outer_endo(name)];
et.set_nulary(t, yy[idyn]);
}
}
// set exogenous
for (unsigned int i = 0; i < atoms_static.get_exovars().size(); i++)
{
const char *name = atoms_static.get_exovars()[i];
int t = atoms_static.index(name);
if (t != -1)
et.set_nulary(t, 0.0);
}
}
DynareSteadySubstitutions::DynareSteadySubstitutions(const ogp::FineAtoms &a,
const ogp::OperationTree &tree,
const Tsubstmap &subst,
const Vector &pvals, Vector &yy)
: atoms(a), y(yy)
{
// fill the vector of left and right hand sides
for (Tsubstmap::const_iterator it = subst.begin();
it != subst.end(); ++it)
{
left_hand_sides.push_back((*it).first);
right_hand_sides.push_back((*it).second);
}
// evaluate right hand sides
DynareSteadyAtomValues dsav(atoms, pvals, y);
ogp::FormulaCustomEvaluator fe(tree, right_hand_sides);
fe.eval(dsav, *this);
}
void
DynareSteadySubstitutions::load(int i, double res)
{
const char *name = left_hand_sides[i];
int iouter = atoms.name2outer_endo(name);
int iy = atoms.outer2y_endo()[iouter];
if (!std::isfinite(y[iy]))
y[iy] = res;
}
DynareStaticSteadySubstitutions::
DynareStaticSteadySubstitutions(const ogp::FineAtoms &a, const ogp::StaticFineAtoms &sa,
const ogp::OperationTree &tree,
const Tsubstmap &subst,
const Vector &pvals, Vector &yy)
: atoms(a), atoms_static(sa), y(yy)
{
// fill the vector of left and right hand sides
for (Tsubstmap::const_iterator it = subst.begin();
it != subst.end(); ++it)
{
left_hand_sides.push_back((*it).first);
right_hand_sides.push_back((*it).second);
}
// evaluate right hand sides
DynareStaticSteadyAtomValues dsav(atoms, atoms_static, pvals, y);
ogp::FormulaCustomEvaluator fe(tree, right_hand_sides);
fe.eval(dsav, *this);
}
void
DynareStaticSteadySubstitutions::load(int i, double res)
{
const char *name = left_hand_sides[i];
int iouter = atoms.name2outer_endo(name);
int iy = atoms.outer2y_endo()[iouter];
if (!std::isfinite(y[iy]))
y[iy] = res;
}

View File

@ -1,274 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: dynare_atoms.cpp 1765 2008-03-31 14:32:08Z kamenik $
#include "parser/cc/parser_exception.h"
#include "utils/cc/exception.h"
#include "dynare_atoms.h"
#include <string>
#include <cmath>
using namespace ogdyn;
using std::string;
void DynareStaticAtoms::register_name(const char* name)
{
if (varnames.query(name))
throw ogp::ParserException(string("The name ")+name+" is not unique.", 0);
StaticAtoms::register_name(name);
}
int DynareStaticAtoms::check_variable(const char* name) const
{
if (0 == varnames.query(name))
throw ogp::ParserException(std::string("Unknown name <")+name+">", 0);
Tvarmap::const_iterator it = vars.find(name);
if (it == vars.end())
return -1;
else
return (*it).second;
}
DynareDynamicAtoms::DynareDynamicAtoms(const DynareDynamicAtoms& dda)
: SAtoms(dda)
{
// fill atom_type
for (Tatypemap::const_iterator it = dda.atom_type.begin();
it != dda.atom_type.end(); ++it)
atom_type.insert(Tatypemap::value_type(varnames.query((*it).first), (*it).second));
}
void DynareDynamicAtoms::parse_variable(const char* in, std::string& out, int& ll) const
{
ll = 0;
std::string str = in;
int left = str.find_first_of("({");
if (left != -1) {
out = str.substr(0, left);
left++;
int right = str.find_first_of(")}", left);
if ((int)string::npos == right)
throw ogp::ParserException(
string("Syntax error when parsing Dynare atom <")+in+">.", 0);
std::string tmp(str, left, right-left);
sscanf(tmp.c_str(), "%d", &ll);
} else {
out = in;
}
}
void DynareDynamicAtoms::register_uniq_endo(const char* name)
{
FineAtoms::register_uniq_endo(name);
atom_type.insert(Tatypemap::value_type(varnames.query(name), endovar));
}
void DynareDynamicAtoms::register_uniq_exo(const char* name)
{
FineAtoms::register_uniq_exo(name);
atom_type.insert(Tatypemap::value_type(varnames.query(name), exovar));
}
void DynareDynamicAtoms::register_uniq_param(const char* name)
{
FineAtoms::register_uniq_param(name);
atom_type.insert(Tatypemap::value_type(varnames.query(name), param));
}
bool DynareDynamicAtoms::is_type(const char* name, atype tp) const
{
Tatypemap::const_iterator it = atom_type.find(name);
if (it != atom_type.end() && (*it).second == tp)
return true;
else
return false;
}
void DynareDynamicAtoms::print() const
{
SAtoms::print();
printf("Name types:\n");
for (Tatypemap::const_iterator it = atom_type.begin();
it != atom_type.end(); ++it)
printf("name=%s type=%s\n", (*it).first,
((*it).second == endovar) ? "endovar" : (((*it).second == exovar)? "exovar" : "param"));
}
std::string DynareDynamicAtoms::convert(int t) const
{
if (t < ogp::OperationTree::num_constants) {
throw ogu::Exception(__FILE__,__LINE__,
"Tree index is a built-in constant in DynareDynamicAtoms::convert");
return std::string();
}
if (is_constant(t)) {
double v = get_constant_value(t);
char buf[100];
sprintf(buf, "%20.16g", v);
const char* s = buf;
while (*s == ' ')
++s;
return std::string(s);
}
const char* s = name(t);
if (is_type(s, endovar)) {
int ll = lead(t);
char buf[100];
if (ll)
sprintf(buf, "%s(%d)", s, ll);
else
sprintf(buf, "%s", s);
return std::string(buf);
}
return std::string(s);
}
void DynareAtomValues::setValues(ogp::EvalTree& et) const
{
// set constants
atoms.setValues(et);
// set parameteres
for (unsigned int i = 0; i < atoms.get_params().size(); i++) {
if (atoms.is_referenced(atoms.get_params()[i])) {
const ogp::DynamicAtoms::Tlagmap& lmap = atoms.lagmap(atoms.get_params()[i]);
for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it) {
int t = (*it).second;
et.set_nulary(t, paramvals[i]);
}
}
}
// set endogenous
for (unsigned int outer_i = 0; outer_i < atoms.get_endovars().size(); outer_i++) {
if (atoms.is_referenced(atoms.get_endovars()[outer_i])) {
const ogp::DynamicAtoms::Tlagmap& lmap = atoms.lagmap(atoms.get_endovars()[outer_i]);
for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it) {
int ll = (*it).first;
int t = (*it).second;
int i = atoms.outer2y_endo()[outer_i];
if (ll == -1) {
et.set_nulary(t, yym[i-atoms.nstat()]);
}
else if (ll == 0)
et.set_nulary(t, yy[i]);
else
et.set_nulary(t, yyp[i-atoms.nstat()-atoms.npred()]);
}
}
}
// set exogenous
for (unsigned int outer_i = 0; outer_i < atoms.get_exovars().size(); outer_i++) {
if (atoms.is_referenced(atoms.get_exovars()[outer_i])) {
const ogp::DynamicAtoms::Tlagmap& lmap = atoms.lagmap(atoms.get_exovars()[outer_i]);
for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it) {
int ll = (*it).first;
if (ll == 0) { // this is always true because of checks
int t = (*it).second;
int i = atoms.outer2y_exo()[outer_i];
et.set_nulary(t, xx[i]);
}
}
}
}
}
void DynareStaticSteadyAtomValues::setValues(ogp::EvalTree& et) const
{
// set constants
atoms_static.setValues(et);
// set parameters
for (unsigned int i = 0; i < atoms_static.get_params().size(); i++) {
const char* name = atoms_static.get_params()[i];
int t = atoms_static.index(name);
if (t != -1) {
int idyn = atoms.name2outer_param(name);
et.set_nulary(t, paramvals[idyn]);
}
}
// set endogenous
for (unsigned int i = 0; i < atoms_static.get_endovars().size(); i++) {
const char* name = atoms_static.get_endovars()[i];
int t = atoms_static.index(name);
if (t != -1) {
int idyn = atoms.outer2y_endo()[atoms.name2outer_endo(name)];
et.set_nulary(t, yy[idyn]);
}
}
// set exogenous
for (unsigned int i = 0; i < atoms_static.get_exovars().size(); i++) {
const char* name = atoms_static.get_exovars()[i];
int t = atoms_static.index(name);
if (t != -1)
et.set_nulary(t, 0.0);
}
}
DynareSteadySubstitutions::DynareSteadySubstitutions(const ogp::FineAtoms& a,
const ogp::OperationTree& tree,
const Tsubstmap& subst,
const Vector& pvals, Vector& yy)
: atoms(a), y(yy)
{
// fill the vector of left and right hand sides
for (Tsubstmap::const_iterator it = subst.begin();
it != subst.end(); ++it) {
left_hand_sides.push_back((*it).first);
right_hand_sides.push_back((*it).second);
}
// evaluate right hand sides
DynareSteadyAtomValues dsav(atoms, pvals, y);
ogp::FormulaCustomEvaluator fe(tree, right_hand_sides);
fe.eval(dsav, *this);
}
void DynareSteadySubstitutions::load(int i, double res)
{
const char* name = left_hand_sides[i];
int iouter = atoms.name2outer_endo(name);
int iy = atoms.outer2y_endo()[iouter];
if (! std::isfinite(y[iy]))
y[iy] = res;
}
DynareStaticSteadySubstitutions::
DynareStaticSteadySubstitutions(const ogp::FineAtoms& a, const ogp::StaticFineAtoms& sa,
const ogp::OperationTree& tree,
const Tsubstmap& subst,
const Vector& pvals, Vector& yy)
: atoms(a), atoms_static(sa), y(yy)
{
// fill the vector of left and right hand sides
for (Tsubstmap::const_iterator it = subst.begin();
it != subst.end(); ++it) {
left_hand_sides.push_back((*it).first);
right_hand_sides.push_back((*it).second);
}
// evaluate right hand sides
DynareStaticSteadyAtomValues dsav(atoms, atoms_static, pvals, y);
ogp::FormulaCustomEvaluator fe(tree, right_hand_sides);
fe.eval(dsav, *this);
}
void DynareStaticSteadySubstitutions::load(int i, double res)
{
const char* name = left_hand_sides[i];
int iouter = atoms.name2outer_endo(name);
int iy = atoms.outer2y_endo()[iouter];
if (! std::isfinite(y[iy]))
y[iy] = res;
}

View File

@ -5,12 +5,12 @@
#ifndef OGDYN_DYNARE_ATOMS_H
#define OGDYN_DYNARE_ATOMS_H
#include "sylv/cc/Vector.h"
#include "sylv/cc/Vector.hh"
#include "parser/cc/static_atoms.h"
#include "parser/cc/static_fine_atoms.h"
#include "parser/cc/atom_substitutions.h"
#include "parser/cc/tree.h"
#include "parser/cc/static_atoms.hh"
#include "parser/cc/static_fine_atoms.hh"
#include "parser/cc/atom_substitutions.hh"
#include "parser/cc/tree.hh"
#include <map>
#include <vector>

1075
dynare++/src/dynare_model.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,957 +0,0 @@
// Copyright (C) 2006-2011, Ondra Kamenik
#include "parser/cc/parser_exception.h"
#include "parser/cc/location.h"
#include "utils/cc/exception.h"
#include "dynare_model.h"
#include "dynare_exception.h"
#include "planner_builder.h"
#include "forw_subst_builder.h"
#include <cstdlib>
#include <string>
#include <cmath>
#include <climits>
using namespace ogdyn;
ParsedMatrix::ParsedMatrix(const ogp::MatrixParser& mp)
: TwoDMatrix(mp.nrows(), mp.ncols())
{
zeros();
for (ogp::MPIterator it = mp.begin(); it != mp.end(); ++it)
get(it.row(), it.col()) = *it;
}
DynareModel::DynareModel()
: atoms(), eqs(atoms), order(-1),
param_vals(0), init_vals(0), vcov_mat(0),
t_plobjective(-1), t_pldiscount(-1),
pbuilder(NULL), fbuilder(NULL),
atom_substs(NULL), old_atoms(NULL)
{}
DynareModel::DynareModel(const DynareModel& dm)
: atoms(dm.atoms), eqs(dm.eqs, atoms), order(dm.order),
param_vals(0), init_vals(0), vcov_mat(0),
t_plobjective(dm.t_plobjective),
t_pldiscount(dm.t_pldiscount),
pbuilder(NULL), fbuilder(NULL),
atom_substs(NULL), old_atoms(NULL)
{
if (dm.param_vals)
param_vals = new Vector((const Vector&)*(dm.param_vals));
if (dm.init_vals)
init_vals = new Vector((const Vector&)*(dm.init_vals));
if (dm.vcov_mat)
vcov_mat = new TwoDMatrix((const TwoDMatrix&)*(dm.vcov_mat));
if (dm.old_atoms)
old_atoms = new DynareDynamicAtoms((const DynareDynamicAtoms&)*(dm.old_atoms));
if (dm.atom_substs)
atom_substs = new ogp::AtomSubstitutions((*dm.atom_substs), *old_atoms, atoms);
if (dm.pbuilder)
pbuilder = new PlannerBuilder(*(dm.pbuilder), *this);
if (dm.fbuilder)
fbuilder = new ForwSubstBuilder(*(dm.fbuilder), *this);
}
DynareModel::~DynareModel()
{
if (param_vals)
delete param_vals;
if (init_vals)
delete init_vals;
if (vcov_mat)
delete vcov_mat;
if (old_atoms)
delete old_atoms;
if (atom_substs)
delete atom_substs;
if (pbuilder)
delete pbuilder;
if (fbuilder)
delete fbuilder;
}
const PlannerInfo* DynareModel::get_planner_info() const
{
if (pbuilder)
return &(pbuilder->get_info());
return NULL;
}
const ForwSubstInfo* DynareModel::get_forw_subst_info() const
{
if (fbuilder)
return &(fbuilder->get_info());
return NULL;
}
const ogp::SubstInfo* DynareModel::get_subst_info() const
{
if (atom_substs)
return &(atom_substs->get_info());
return NULL;
}
void DynareModel::setInitOuter(const Vector& x)
{
if (x.length() != atoms.ny())
throw DynareException(__FILE__, __LINE__,
"Wrong length of vector in DynareModel::setInitOuter");
for (int i = 0; i < atoms.ny(); i++)
(*init_vals)[i] = x[atoms.y2outer_endo()[i]];
}
void DynareModel::print() const
{
printf("all atoms:\n");
atoms.print();
printf("formulas:\n");
DebugOperationFormatter dof(*this);
for (int i = 0; i < eqs.nformulas(); i++) {
int tf = eqs.formula(i);
printf("formula %d:\n", tf);
eqs.getTree().print_operation_tree(tf, stdout, dof);
}
}
void DynareModel::dump_model(std::ostream& os) const
{
// endogenous variable declaration
os << "var";
for (int i = 0; i < (int)atoms.get_endovars().size(); i++)
os << " " << atoms.get_endovars()[i];
os << ";\n\n";
// exogenous variables
os << "varexo";
for (int i = 0; i < (int)atoms.get_exovars().size(); i++)
os << " " << atoms.get_exovars()[i];
os << ";\n\n";
// parameters
os << "parameters";
for (int i = 0; i < (int)atoms.get_params().size(); i++)
os << " " << atoms.get_params()[i];
os << ";\n\n";
// parameter values
os.precision(16);
for (int i = 0; i < (int)atoms.get_params().size(); i++)
os << atoms.get_params()[i] << "=" << getParams()[i] << ";\n";
os << "\n\n";
// model section
ogp::OperationStringConvertor osc(atoms, getParser().getTree());
os << "model;\n";
for (int i = 0; i < getParser().nformulas(); i++) {
os << "// Equation " << i << "\n0 = ";
int t = getParser().formula(i);
os << osc.convert(getParser().getTree().operation(t), t);
os << ";\n";
}
os << "end;\n";
// initval as steady state
os << "initval;\n";
for (int i = 0; i < (int)atoms.get_endovars().size(); i++)
os << atoms.get_endovars()[atoms.y2outer_endo()[i]] << "=" << getInit()[i] << ";\n";
os << "end;\n";
}
void DynareModel::add_name(const char* name, int flag)
{
if (flag == 1) {
// endogenous
atoms.register_uniq_endo(name);
} else if (flag == 2) {
// exogenous
atoms.register_uniq_exo(name);
} else if (flag == 3) {
// parameter
atoms.register_uniq_param(name);
} else {
throw DynareException(__FILE__, __LINE__,
"Unrecognized flag value.");
}
}
void DynareModel::check_model() const
{
if (order == -1)
throw DynareException(__FILE__,__LINE__,
"Order of approximation not set in DynareModel::check_model");
if (atoms.ny() != eqs.nformulas()) {
char mes[1000];
sprintf(mes, "Model has %d equations for %d endogenous variables", eqs.nformulas(), atoms.ny());
throw DynareException(__FILE__, __LINE__, mes);
}
// check whether all nulary terms of all formulas in eqs are
// either constant or assigned to a name
for (int i = 0; i < eqs.nformulas(); i++) {
int ft = eqs.formula(i);
const unordered_set<int>& nuls = eqs.nulary_of_term(ft);
for (unordered_set<int>::const_iterator it = nuls.begin();
it != nuls.end(); ++it)
if (! atoms.is_constant(*it) && ! atoms.is_named_atom(*it))
throw DynareException(__FILE__,__LINE__,
"Dangling nulary term found, internal error.");
}
int mlag, mlead;
atoms.exovarspan(mlead, mlag);
if (atoms.nexo() > 0 && (mlead != 0 || mlag != 0))
throw DynareException(__FILE__,__LINE__,
"The model contains occurrences of lagged/leaded exogenous variables");
atoms.endovarspan(mlead, mlag);
if (mlead > 1 || mlag < -1)
throw DynareException(__FILE__,__LINE__,
"The model contains occurrences of too lagged/leaded endogenous variables");
// check the dimension of vcov matrix
if (getAtoms().nexo() != getVcov().nrows())
throw DynareException(__FILE__,__LINE__,
"Dimension of VCOV matrix does not correspond to the shocks");
}
int DynareModel::variable_shift(int t, int tshift)
{
const char* name = atoms.name(t);
if (atoms.is_type(name, DynareDynamicAtoms::param) ||
atoms.is_constant(t))
throw DynareException(__FILE__, __LINE__,
"The tree index is not a variable in DynareModel::variable_shift");
int ll = atoms.lead(t) + tshift;
int res = atoms.index(name, ll);
if (res == -1) {
std::string str(name);
str += '(';
char tmp[50];
sprintf(tmp,"%d",ll);
str += tmp;
str += ')';
res = eqs.add_nulary(str.c_str());
}
return res;
}
void DynareModel::variable_shift_map(const unordered_set<int>& a_set, int tshift,
map<int,int>& s_map)
{
s_map.clear();
for (unordered_set<int>::const_iterator it = a_set.begin();
it != a_set.end(); ++it) {
int t = *it;
// make shift map only for non-constants and non-parameters
if (! atoms.is_constant(t)) {
const char* name = atoms.name(t);
if (atoms.is_type(name, DynareDynamicAtoms::endovar) ||
atoms.is_type(name, DynareDynamicAtoms::exovar)) {
int tt = variable_shift(t, tshift);
s_map.insert(map<int,int>::value_type(t,tt));
}
}
}
}
void DynareModel::termspan(int t, int& mlead, int& mlag) const
{
mlead = INT_MIN;
mlag = INT_MAX;
const unordered_set<int>& nul_terms = eqs.nulary_of_term(t);
for (unordered_set<int>::const_iterator ni = nul_terms.begin();
ni != nul_terms.end(); ++ni) {
if (!atoms.is_constant(*ni) &&
(atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::endovar) ||
atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::exovar))) {
int ll = atoms.lead(*ni);
if (ll < mlag)
mlag = ll;
if (ll > mlead)
mlead = ll;
}
}
}
bool DynareModel::is_constant_term(int t) const
{
const unordered_set<int>& nul_terms = eqs.nulary_of_term(t);
for (unordered_set<int>::const_iterator ni = nul_terms.begin();
ni != nul_terms.end(); ++ni)
if (! atoms.is_constant(*ni) &&
! atoms.is_type(atoms.name(*ni), DynareDynamicAtoms::param))
return false;
return true;
}
unordered_set<int> DynareModel::get_nonlinear_subterms(int t) const
{
NLSelector nls(*this);
return eqs.getTree().select_terms(t, nls);
}
void DynareModel::substitute_atom_for_term(const char* name, int ll, int t)
{
// if the term t is itself a named atom (parameter, exo, endo),
// then we have to unassign it first
if (atoms.is_named_atom(t))
atoms.unassign_variable(atoms.name(t), atoms.lead(t), t);
// assign allocated tree index
// for the term now to name(ll)
atoms.assign_variable(name, ll, t);
// make operation t nulary in operation tree
eqs.nularify(t);
}
void DynareModel::final_job()
{
if (t_plobjective != -1 && t_pldiscount != -1) {
// at this moment include all equations and all variables; in
// future we will exclude purely exogenous processes; todo:
PlannerBuilder::Tvarset vset;
for (int i = 0; i < atoms.ny(); i++)
vset.insert(atoms.get_endovars()[i]);
PlannerBuilder::Teqset eset;
for (int i = 0; i < eqs.nformulas(); i++)
eset.push_back(i);
// construct the planner builder, this adds a lot of stuff to
// the model
if (pbuilder)
delete pbuilder;
pbuilder = new PlannerBuilder(*this, vset, eset);
}
// construct ForwSubstBuilder
if (fbuilder)
delete fbuilder;
fbuilder = new ForwSubstBuilder(*this);
// call parsing_finished (this will define an outer ordering of all variables)
atoms.parsing_finished(ogp::VarOrdering::bfspbfpb);
// make a copy of atoms and name it old_atoms
if (old_atoms)
delete old_atoms;
old_atoms = new DynareDynamicAtoms(atoms);
// construct empty substitutions from old_atoms to atoms
if (atom_substs)
delete atom_substs;
atom_substs = new ogp::AtomSubstitutions(*old_atoms, atoms);
// do the actual substitution, it will also call
// parsing_finished for atoms which creates internal orderings
atoms.substituteAllLagsAndExo1Leads(eqs, *atom_substs);
}
extern ogp::location_type dynglob_lloc;
DynareParser::DynareParser(const char* stream, int len, int ord)
: DynareModel(),
pa_atoms(), paramset(pa_atoms),
ia_atoms(), initval(ia_atoms), vcov(),
model_beg(0), model_end(-1),
paramset_beg(0), paramset_end(-1),
initval_beg(0), initval_end(-1),
vcov_beg(0), vcov_end(-1),
order_beg(0), order_end(-1),
plobjective_beg(0), plobjective_end(-1),
pldiscount_beg(0), pldiscount_end(-1)
{
// global parse
try {
parse_glob(len, stream);
} catch (const ogp::ParserException& e) {
throw ogp::ParserException(e, dynglob_lloc.off);
}
// setting parameters parse
try {
if (paramset_end > paramset_beg)
paramset.parse(paramset_end-paramset_beg, stream+paramset_beg);
} catch (const ogp::ParserException& e) {
throw ogp::ParserException(e, paramset_beg);
}
// model parse
try {
if (model_end > model_beg)
eqs.parse(model_end-model_beg, stream+model_beg);
else
throw ogp::ParserException("Model section not found.", 0);
} catch (const ogp::ParserException& e) {
throw ogp::ParserException(e, model_beg);
}
// initval setting parse
try {
if (initval_end > initval_beg)
initval.parse(initval_end-initval_beg, stream+initval_beg);
} catch (const ogp::ParserException& e) {
throw ogp::ParserException(e, initval_beg);
}
// vcov parse
try {
if (vcov_end > vcov_beg) {
vcov.parse(vcov_end-vcov_beg, stream+vcov_beg);
}
} catch (const ogp::ParserException& e) {
throw ogp::ParserException(e, vcov_beg);
}
// planner objective parse
try {
if (plobjective_end > plobjective_beg) {
eqs.parse(plobjective_end-plobjective_beg, stream+plobjective_beg);
t_plobjective = eqs.pop_last_formula();
}
} catch (const ogp::ParserException& e) {
throw ogp::ParserException(e, plobjective_beg);
}
// planner discount parse
try {
if (pldiscount_end > pldiscount_beg) {
t_pldiscount = parse_pldiscount(pldiscount_end - pldiscount_beg,
stream + pldiscount_beg);
}
} catch (const ogp::ParserException& e) {
throw ogp::ParserException(e, pldiscount_beg);
}
// order parse
try {
if (order_end > order_beg) {
order = parse_order(order_end > order_beg, stream + order_beg);
}
} catch (const ogp::ParserException& e) {
throw ogp::ParserException(e, order_beg);
}
// check the overridden order
if (ord != -1)
order = ord;
// end parsing job, add planner's FOCs, make substitutions
DynareModel::final_job();
// calculate parameters
calc_params();
// calculate initial values
calc_init();
if (vcov_end > vcov_beg)
vcov_mat = new ParsedMatrix(vcov);
else {
// vcov has not been asserted, set it to unit matrix
vcov_mat = new TwoDMatrix(atoms.nexo(), atoms.nexo());
vcov_mat->unit();
}
// check the model
check_model();
// differentiate
if (order >= 1)
eqs.differentiate(order);
}
DynareParser::DynareParser(const DynareParser& dp)
: DynareModel(dp),
pa_atoms(dp.pa_atoms), paramset(dp.paramset, pa_atoms),
ia_atoms(dp.ia_atoms), initval(dp.initval, ia_atoms), vcov(dp.vcov),
model_beg(dp.model_beg), model_end(dp.model_end),
paramset_beg(dp.paramset_beg), paramset_end(dp.paramset_end),
initval_beg(dp.initval_beg), initval_end(dp.initval_end),
vcov_beg(dp.vcov_beg), vcov_end(dp.vcov_end),
order_beg(dp.order_beg), order_end(dp.order_end),
plobjective_beg(dp.plobjective_beg), plobjective_end(dp.plobjective_end),
pldiscount_beg(dp.pldiscount_beg), pldiscount_end(dp.pldiscount_end)
{
}
DynareParser::~DynareParser()
{
}
void DynareParser::add_name(const char* name, int flag)
{
DynareModel::add_name(name, flag);
// register with static atoms used for atom assignements
if (flag == 1) {
// endogenous
ia_atoms.register_name(name);
} else if (flag == 2) {
// exogenous
ia_atoms.register_name(name);
} else if (flag == 3) {
// parameter
pa_atoms.register_name(name);
ia_atoms.register_name(name);
} else {
throw DynareException(__FILE__, __LINE__,
"Unrecognized flag value.");
}
}
void DynareParser::error(const char* mes)
{
// throwing zero offset since this exception will be caugth at
// constructor
throw ogp::ParserException(mes, 0);
}
void DynareParser::print() const
{
DynareModel::print();
printf("parameter atoms:\n");
paramset.print();
printf("initval atoms:\n");
initval.print();
printf("model position: %d %d\n", model_beg, model_end);
printf("paramset position: %d %d\n", paramset_beg, paramset_end);
printf("initval position: %d %d\n", initval_beg, initval_end);
}
/** A global symbol for passing info to the DynareParser from
* parser. */
DynareParser* dynare_parser;
/** The declarations of functions defined in dynglob_ll.cc and
* dynglob_tab.cc generated from dynglob.lex and dynglob.y */
void* dynglob__scan_buffer(char*, size_t);
void dynglob__destroy_buffer(void*);
void dynglob_parse();
extern ogp::location_type dynglob_lloc;
void DynareParser::parse_glob(int length, const char* stream)
{
char* buffer = new char[length+2];
strncpy(buffer, stream, length);
buffer[length] = '\0';
buffer[length+1] = '\0';
void* p = dynglob__scan_buffer(buffer, (unsigned int)length+2);
dynare_parser = this;
dynglob_parse();
delete [] buffer;
dynglob__destroy_buffer(p);
}
int DynareParser::parse_order(int len, const char* str)
{
char* buf = new char[len+1];
strncpy(buf, str, len);
buf[len] = '\0';
int res;
sscanf(buf, "%d", &res);
delete [] buf;
return res;
}
int DynareParser::parse_pldiscount(int len, const char* str)
{
char* buf = new char[len+1];
strncpy(buf, str, len);
buf[len] = '\0';
if (! atoms.is_type(buf, DynareDynamicAtoms::param))
throw ogp::ParserException(std::string("Name ") + buf + " is not a parameter", 0);
int t = atoms.index(buf, 0);
if (t == -1)
t = eqs.add_nulary(buf);
delete [] buf;
return t;
}
void DynareParser::calc_params()
{
if (param_vals)
delete param_vals;
param_vals = new Vector(atoms.np());
ogp::AtomAsgnEvaluator aae(paramset);
aae.eval();
for (int i = 0; i < atoms.np(); i++)
(*param_vals)[i] = aae.get_value(atoms.get_params()[i]);
for (unsigned int i = 0; i < atoms.get_params().size(); i++)
if (! std::isfinite((*param_vals)[i]))
printf("dynare++: warning: value for parameter %s is not finite\n",
atoms.get_params()[i]);
}
void DynareParser::calc_init()
{
// update initval atoms assignings according to substitutions
if (atom_substs)
initval.apply_subst(atom_substs->get_old2new());
// calculate the vector of initial values
if (init_vals)
delete init_vals;
init_vals = new Vector(atoms.ny());
ogp::AtomAsgnEvaluator aae(initval);
// set parameters
for (int ip = 0; ip < atoms.np(); ip++)
aae.set_user_value(atoms.get_params()[ip], (*param_vals)[ip]);
// set exogenous to zeros
for (int ie = 0; ie < atoms.nexo(); ie++)
aae.set_user_value(atoms.get_exovars()[ie], 0.0);
// evaluate
aae.eval();
// set results to internally ordered vector init_vals
for (int outer = 0; outer < atoms.ny(); outer++) {
int i = atoms.outer2y_endo()[outer];
(*init_vals)[i] = aae.get_value(atoms.get_endovars()[outer]);
}
// if the planner's FOCs have been added, then add estimate of
// Lagrange multipliers to the vector
if (pbuilder) {
MultInitSS mis(*pbuilder, *param_vals, *init_vals);
}
// if forward substitution builder has been created, we have to
// its substitutions and evaluate them
if (fbuilder)
ogdyn::DynareSteadySubstitutions dss(atoms, eqs.getTree(),
fbuilder->get_aux_map(), *param_vals, *init_vals);
for (unsigned int i = 0; i < atoms.get_endovars().size(); i++)
if (! std::isfinite((*init_vals)[i]))
printf("dynare++: warning: initval for <%s> is not finite\n",
atoms.get_endovars()[atoms.y2outer_endo()[i]]);
}
// this returns false for linear functions
bool NLSelector::operator()(int t) const
{
const ogp::Operation& op = model.getParser().getTree().operation(t);
const DynareDynamicAtoms& atoms = model.getAtoms();
// if the term is constant, return false
if (model.is_constant_term(t))
return false;
int nary = op.nary();
if (nary == 0) {
if (atoms.is_type(atoms.name(t), DynareDynamicAtoms::endovar) ||
atoms.is_type(atoms.name(t), DynareDynamicAtoms::exovar))
return true;
else
return false;
} else if (nary == 1) {
if (op.getCode() == ogp::UMINUS)
return false;
else
return true;
} else {
if (op.getCode() == ogp::TIMES)
// if at least one operand is constant, than the TIMES is linear
if (model.is_constant_term(op.getOp1()) ||
model.is_constant_term(op.getOp2()))
return false;
else
return true;
// both PLUS and MINUS are linear
if (op.getCode() == ogp::PLUS ||
op.getCode() == ogp::MINUS)
return false;
// POWER is linear if exponent or base is 0 or one
if (op.getCode() == ogp::POWER &&
(op.getOp1() == ogp::OperationTree::zero ||
op.getOp1() == ogp::OperationTree::one ||
op.getOp2() == ogp::OperationTree::zero ||
op.getOp2() == ogp::OperationTree::one))
return false;
else
return true;
// DIVIDE is linear if the denominator is constant, or if
// the nominator is zero
if (op.getCode() == ogp::DIVIDE &&
(op.getOp1() == ogp::OperationTree::zero ||
model.is_constant_term(op.getOp2())))
return false;
else
return true;
}
throw DynareException(__FILE__, __LINE__,
"Wrong operation in operation tree");
return false;
}
DynareSPModel::DynareSPModel(const char** endo, int num_endo,
const char** exo, int num_exo,
const char** par, int num_par,
const char* equations, int len,
int ord)
: DynareModel()
{
// set the order
order = ord;
// add names
for (int i = 0; i < num_endo; i++)
add_name(endo[i], 1);
for (int i = 0; i < num_exo; i++)
add_name(exo[i], 2);
for (int i = 0; i < num_par; i++)
add_name(par[i], 3);
// parse the equations
eqs.parse(len, equations);
// parsing finished
atoms.parsing_finished(ogp::VarOrdering::bfspbfpb);
// create what has to be created from DynareModel
param_vals = new Vector(atoms.np());
init_vals = new Vector(atoms.ny());
vcov_mat = new TwoDMatrix(atoms.nexo(), atoms.nexo());
// check the model
check_model();
// differentiate
if (order >= 1)
eqs.differentiate(order);
}
void ModelSSWriter::write_der0(FILE* fd)
{
write_der0_preamble(fd);
write_atom_assignment(fd);
stop_set.clear();
for (int fi = 0; fi < model.eqs.nformulas(); fi++)
otree.print_operation_tree(model.eqs.formula(fi), fd, *this);
write_der0_assignment(fd);
}
void ModelSSWriter::write_der1(FILE* fd)
{
write_der1_preamble(fd);
write_atom_assignment(fd);
stop_set.clear();
const vector<int>& variables = model.getAtoms().variables();
const vector<int>& eam = model.getAtoms().get_endo_atoms_map();
for (int i = 0; i < model.getParser().nformulas(); i++) {
const ogp::FormulaDerivatives& fder = model.getParser().derivatives(i);
for (unsigned int j = 0; j < eam.size(); j++) {
int t = fder.derivative(ogp::FoldMultiIndex(variables.size(), 1, eam[j]));
if (t > 0)
otree.print_operation_tree(t, fd, *this);
}
}
write_der1_assignment(fd);
}
MatlabSSWriter::MatlabSSWriter(const DynareModel& dm, const char* idd)
: ModelSSWriter(dm), id(new char[strlen(idd)+1])
{
strcpy(id, idd);
}
void MatlabSSWriter::write_der0_preamble(FILE* fd) const
{
fprintf(fd,
"%% Usage:\n"
"%% out = %s_f(params, y)\n"
"%% where\n"
"%% out is a (%d,1) column vector of the residuals\n"
"%% of the static system\n",
id, model.getAtoms().ny());
write_common1_preamble(fd);
fprintf(fd,
"function out = %s_f(params, y)\n", id);
write_common2_preamble(fd);
}
void MatlabSSWriter::write_der1_preamble(FILE* fd) const
{
fprintf(fd,
"%% Usage:\n"
"%% out = %s_ff(params, y)\n"
"%% where\n"
"%% out is a (%d,%d) matrix of the first order\n"
"%% derivatives of the static system residuals\n"
"%% columns correspond to endo variables in\n"
"%% the ordering as declared\n",
id, model.getAtoms().ny(), model.getAtoms().ny());
write_common1_preamble(fd);
fprintf(fd,
"function out = %s_ff(params, y)\n", id);
write_common2_preamble(fd);
}
void MatlabSSWriter::write_common1_preamble(FILE* fd) const
{
fprintf(fd,
"%% params is a (%d,1) vector of parameter values\n"
"%% in the ordering as declared\n"
"%% y is a (%d,1) vector of endogenous variables\n"
"%% in the ordering as declared\n"
"%%\n"
"%% Created by Dynare++ v. %s\n", model.getAtoms().np(),
model.getAtoms().ny(), DYNVERSION);
// write ordering of parameters
fprintf(fd, "\n%% params ordering\n%% =====================\n");
for (unsigned int ip = 0; ip < model.getAtoms().get_params().size(); ip++) {
const char* parname = model.getAtoms().get_params()[ip];
fprintf(fd, "%% %s\n", parname);
}
// write endogenous variables
fprintf(fd, "%%\n%% y ordering\n%% =====================\n");
for (unsigned int ie = 0; ie < model.getAtoms().get_endovars().size(); ie++) {
const char* endoname = model.getAtoms().get_endovars()[ie];
fprintf(fd, "%% %s\n", endoname);
}
fprintf(fd,"\n");
}
void MatlabSSWriter::write_common2_preamble(FILE* fd) const
{
fprintf(fd, "if size(y) ~= [%d,1]\n\terror('Wrong size of y, must be [%d,1]');\nend\n",
model.getAtoms().ny(), model.getAtoms().ny());
fprintf(fd, "if size(params) ~= [%d,1]\n\terror('Wrong size of params, must be [%d,1]');\nend\n\n",
model.getAtoms().np(), model.getAtoms().np());
}
void MatlabSSWriter::write_atom_assignment(FILE* fd) const
{
// write OperationTree::num_constants
fprintf(fd, "%% hardwired constants\n");
ogp::EvalTree etree(model.getParser().getTree(), ogp::OperationTree::num_constants-1);
for (int i = 0; i < ogp::OperationTree::num_constants; i++) {
format_nulary(i, fd);
double g = etree.eval(i);
if (std::isnan(g))
fprintf(fd, " = NaN;\n");
else
fprintf(fd, " = %12.8g;\n", etree.eval(i));
}
// write numerical constants
fprintf(fd, "%% numerical constants\n");
const ogp::Constants::Tconstantmap& cmap = model.getAtoms().get_constantmap();
for (ogp::Constants::Tconstantmap::const_iterator it = cmap.begin();
it != cmap.end(); ++it) {
format_nulary((*it).first, fd);
fprintf(fd, " = %12.8g;\n", (*it).second);
}
// write parameters
fprintf(fd, "%% parameter values\n");
for (unsigned int ip = 0; ip < model.getAtoms().get_params().size(); ip++) {
const char* parname = model.getAtoms().get_params()[ip];
int t = model.getAtoms().index(parname, 0);
if (t == -1) {
fprintf(fd, "%% %s not used in the model\n", parname);
} else {
format_nulary(t, fd);
fprintf(fd, " = params(%d); %% %s\n", ip+1, parname);
}
}
// write exogenous variables
fprintf(fd, "%% exogenous variables to zeros\n");
for (unsigned int ie = 0; ie < model.getAtoms().get_exovars().size(); ie++) {
const char* exoname = model.getAtoms().get_exovars()[ie];
try {
const ogp::DynamicAtoms::Tlagmap& lmap = model.getAtoms().lagmap(exoname);
for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it) {
format_nulary((*it).second, fd);
fprintf(fd, " = 0.0; %% %s\n", exoname);
}
} catch (const ogu::Exception& e) {
// ignore the error of not found variable in the tree
}
}
// write endogenous variables
fprintf(fd, "%% endogenous variables to y\n");
for (unsigned int ie = 0; ie < model.getAtoms().get_endovars().size(); ie++) {
const char* endoname = model.getAtoms().get_endovars()[ie];
const ogp::DynamicAtoms::Tlagmap& lmap = model.getAtoms().lagmap(endoname);
for (ogp::DynamicAtoms::Tlagmap::const_iterator it = lmap.begin();
it != lmap.end(); ++it) {
format_nulary((*it).second, fd);
fprintf(fd, " = y(%d); %% %s\n", ie+1, endoname);
}
}
fprintf(fd,"\n");
}
void MatlabSSWriter::write_der0_assignment(FILE* fd) const
{
// initialize out variable
fprintf(fd, "%% setting the output variable\n");
fprintf(fd, "out = zeros(%d, 1);\n", model.getParser().nformulas());
// fill out with the terms
for (int i = 0; i < model.getParser().nformulas(); i++) {
fprintf(fd, "out(%d) = ", i+1);
format_term(model.getParser().formula(i), fd);
fprintf(fd, ";\n");
}
}
void MatlabSSWriter::write_der1_assignment(FILE* fd) const
{
// initialize out variable
fprintf(fd, "%% setting the output variable\n");
fprintf(fd, "out = zeros(%d, %d);\n", model.getParser().nformulas(), model.getAtoms().ny());
// fill out with the terms
const vector<int>& variables = model.getAtoms().variables();
const vector<int>& eam = model.getAtoms().get_endo_atoms_map();
for (int i = 0; i < model.getParser().nformulas(); i++) {
const ogp::FormulaDerivatives& fder = model.getParser().derivatives(i);
for (unsigned int j = 0; j < eam.size(); j++) {
int tvar = variables[eam[j]];
const char* name = model.getAtoms().name(tvar);
int yi = model.getAtoms().name2outer_endo(name);
int t = fder.derivative(ogp::FoldMultiIndex(variables.size(), 1, eam[j]));
if (t != ogp::OperationTree::zero) {
fprintf(fd, "out(%d,%d) = out(%d,%d) + ", i+1, yi+1, i+1, yi+1);
format_term(t, fd);
fprintf(fd, "; %% %s(%d)\n", name, model.getAtoms().lead(tvar));
}
}
}
}
void MatlabSSWriter::format_term(int t, FILE* fd) const
{
fprintf(fd, "t%d", t);
}
void MatlabSSWriter::format_nulary(int t, FILE* fd) const
{
fprintf(fd, "a%d", t);
}
void DebugOperationFormatter::format_nulary(int t, FILE* fd) const
{
const DynareDynamicAtoms& a = model.getAtoms();
if (t == ogp::OperationTree::zero)
fprintf(fd, "0");
else if (t == ogp::OperationTree::one)
fprintf(fd, "1");
else if (t == ogp::OperationTree::nan)
fprintf(fd, "NaN");
else if (t == ogp::OperationTree::two_over_pi)
fprintf(fd, "2/sqrt(PI)");
else if (a.is_constant(t))
fprintf(fd, "%g", a.get_constant_value(t));
else {
int ll = a.lead(t);
const char* name = a.name(t);
if (ll == 0)
fprintf(fd, "%s", name);
else
fprintf(fd, "%s(%d)", name, ll);
}
}

View File

@ -3,14 +3,14 @@
#ifndef OGDYN_DYNARE_MODEL
#define OGDYN_DYNARE_MODEL
#include "parser/cc/matrix_parser.h"
#include "parser/cc/atom_assignings.h"
#include "parser/cc/matrix_parser.hh"
#include "parser/cc/atom_assignings.hh"
#include "dynare_atoms.h"
#include "dynare_atoms.hh"
#include "twod_matrix.hh"
#include "Vector.h"
#include "GeneralMatrix.h"
#include "Vector.hh"
#include "GeneralMatrix.hh"
#include <map>
#include <boost/unordered_set.hpp>

View File

@ -0,0 +1,278 @@
// Copyright (C) 2004-2011, Ondra Kamenik
#include "dynare_params.hh"
#include <getopt.h>
#include <cstdio>
#include <cstring>
const char *help_str
= "usage: dynare++ [--help] [--version] [options] <model file>\n"
"\n"
" --help print this message and return\n"
" --version print version and return\n"
"\n"
"options:\n"
" --per <num> number of periods simulated after burnt [100]\n"
" --burn <num> number of periods burnt [0]\n"
" --sim <num> number of simulations [80]\n"
" --rtper <num> number of RT periods simulated after burnt [0]\n"
" --rtsim <num> number of RT simulations [0]\n"
" --condper <num> number of periods in cond. simulations [0]\n"
" --condsim <num> number of conditional simulations [0]\n"
" --steps <num> steps towards stoch. SS [0=deter.]\n"
" --centralize centralize the rule [do centralize]\n"
" --no-centralize do not centralize the rule [do centralize]\n"
" --prefix <string> prefix of variables in Mat-4 file [\"dyn\"]\n"
" --seed <num> random number generator seed [934098]\n"
" --order <num> order of approximation [no default]\n"
" --threads <num> number of max parallel threads [2]\n"
" --ss-tol <num> steady state calcs tolerance [1.e-13]\n"
" --check pesPES check model residuals [no checks]\n"
" lower/upper case switches off/on\n"
" pP checking along simulation path\n"
" eE checking on ellipse\n"
" sS checking along shocks\n"
" --check-evals <num> max number of evals per residual [1000]\n"
" --check-num <num> number of checked points [10]\n"
" --check-scale <num> scaling of checked points [2.0]\n"
" --no-irfs shuts down IRF simulations [do IRFs]\n"
" --irfs performs IRF simulations [do IRFs]\n"
" --qz-criterium <num> threshold for stable eigenvalues [1.000001]\n"
"\n\n";
// returns the pointer to the first character after the last slash or
// backslash in the string
const char *dyn_basename(const char *str);
DynareParams::DynareParams(int argc, char **argv)
: modname(NULL), num_per(100), num_burn(0), num_sim(80),
num_rtper(0), num_rtsim(0),
num_condper(0), num_condsim(0),
num_threads(2), num_steps(0),
prefix("dyn"), seed(934098), order(-1), ss_tol(1.e-13),
check_along_path(false), check_along_shocks(false),
check_on_ellipse(false), check_evals(1000), check_num(10), check_scale(2.0),
do_irfs_all(true), do_centralize(true), qz_criterium(1.0+1e-6),
help(false), version(false)
{
if (argc == 1 || !strcmp(argv[1], "--help"))
{
help = true;
return;
}
if (argc == 1 || !strcmp(argv[1], "--version"))
{
version = true;
return;
}
modname = argv[argc-1];
argc--;
struct option const opts [] = {
{"periods", required_argument, NULL, opt_per},
{"per", required_argument, NULL, opt_per},
{"burn", required_argument, NULL, opt_burn},
{"simulations", required_argument, NULL, opt_sim},
{"sim", required_argument, NULL, opt_sim},
{"rtperiods", required_argument, NULL, opt_rtper},
{"rtper", required_argument, NULL, opt_rtper},
{"rtsimulations", required_argument, NULL, opt_rtsim},
{"rtsim", required_argument, NULL, opt_rtsim},
{"condperiods", required_argument, NULL, opt_condper},
{"condper", required_argument, NULL, opt_condper},
{"condsimulations", required_argument, NULL, opt_condsim},
{"condsim", required_argument, NULL, opt_condsim},
{"prefix", required_argument, NULL, opt_prefix},
{"threads", required_argument, NULL, opt_threads},
{"steps", required_argument, NULL, opt_steps},
{"seed", required_argument, NULL, opt_seed},
{"order", required_argument, NULL, opt_order},
{"ss-tol", required_argument, NULL, opt_ss_tol},
{"check", required_argument, NULL, opt_check},
{"check-scale", required_argument, NULL, opt_check_scale},
{"check-evals", required_argument, NULL, opt_check_evals},
{"check-num", required_argument, NULL, opt_check_num},
{"qz-criterium", required_argument, NULL, opt_qz_criterium},
{"no-irfs", no_argument, NULL, opt_noirfs},
{"irfs", no_argument, NULL, opt_irfs},
{"centralize", no_argument, NULL, opt_centralize},
{"no-centralize", no_argument, NULL, opt_no_centralize},
{"help", no_argument, NULL, opt_help},
{"version", no_argument, NULL, opt_version},
{NULL, 0, NULL, 0}
};
int ret;
int index;
while (-1 != (ret = getopt_long(argc, argv, "", opts, &index)))
{
switch (ret)
{
case opt_per:
if (1 != sscanf(optarg, "%d", &num_per))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_burn:
if (1 != sscanf(optarg, "%d", &num_burn))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_sim:
if (1 != sscanf(optarg, "%d", &num_sim))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_rtper:
if (1 != sscanf(optarg, "%d", &num_rtper))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_rtsim:
if (1 != sscanf(optarg, "%d", &num_rtsim))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_condper:
if (1 != sscanf(optarg, "%d", &num_condper))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_condsim:
if (1 != sscanf(optarg, "%d", &num_condsim))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_prefix:
prefix = optarg;
break;
case opt_threads:
if (1 != sscanf(optarg, "%d", &num_threads))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_steps:
if (1 != sscanf(optarg, "%d", &num_steps))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_seed:
if (1 != sscanf(optarg, "%d", &seed))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_order:
if (1 != sscanf(optarg, "%d", &order))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_ss_tol:
if (1 != sscanf(optarg, "%lf", &ss_tol))
fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg);
break;
case opt_check:
processCheckFlags(optarg);
break;
case opt_check_scale:
if (1 != sscanf(optarg, "%lf", &check_scale))
fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg);
break;
case opt_check_evals:
if (1 != sscanf(optarg, "%d", &check_evals))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_check_num:
if (1 != sscanf(optarg, "%d", &check_num))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_noirfs:
irf_list.clear();
do_irfs_all = false;
break;
case opt_irfs:
processIRFList(argc, argv);
if (irf_list.empty())
do_irfs_all = true;
else
do_irfs_all = false;
break;
case opt_centralize:
do_centralize = true;
break;
case opt_no_centralize:
do_centralize = false;
break;
case opt_qz_criterium:
if (1 != sscanf(optarg, "%lf", &qz_criterium))
fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg);
break;
case opt_help:
help = true;
break;
case opt_version:
version = true;
break;
case '?':
fprintf(stderr, "Unknown option, ignored\n");
break;
}
}
// make basename (get rid of the extension)
basename = dyn_basename(modname);
std::string::size_type i = basename.rfind('.');
if (i != std::string::npos)
basename.erase(i);
}
void
DynareParams::printHelp() const
{
printf("%s", help_str);
}
void
DynareParams::processCheckFlags(const char *flags)
{
for (unsigned int i = 0; i < strlen(flags); i++)
{
switch (flags[i])
{
case 'p':
check_along_path = false;
break;
case 'P':
check_along_path = true;
break;
case 'e':
check_on_ellipse = false;
break;
case 'E':
check_on_ellipse = true;
break;
case 's':
check_along_shocks = false;
break;
case 'S':
check_along_shocks = true;
break;
default:
fprintf(stderr, "Unknown check type selection character <%c>, ignored.\n", flags[i]);
}
}
}
void
DynareParams::processIRFList(int argc, char **argv)
{
irf_list.clear();
while (optind < argc && *(argv[optind]) != '-')
{
irf_list.push_back(argv[optind]);
optind++;
}
}
const char *
dyn_basename(const char *str)
{
int i = strlen(str);
while (i > 0 && str[i-1] != '/' && str[i-1] != '\\')
i--;
return str+i;
}
// Local Variables:
// mode:C++
// End:

View File

@ -1,267 +0,0 @@
// Copyright (C) 2004-2011, Ondra Kamenik
#include "dynare_params.h"
#include <getopt.h>
#include <cstdio>
#include <cstring>
const char* help_str =
"usage: dynare++ [--help] [--version] [options] <model file>\n"
"\n"
" --help print this message and return\n"
" --version print version and return\n"
"\n"
"options:\n"
" --per <num> number of periods simulated after burnt [100]\n"
" --burn <num> number of periods burnt [0]\n"
" --sim <num> number of simulations [80]\n"
" --rtper <num> number of RT periods simulated after burnt [0]\n"
" --rtsim <num> number of RT simulations [0]\n"
" --condper <num> number of periods in cond. simulations [0]\n"
" --condsim <num> number of conditional simulations [0]\n"
" --steps <num> steps towards stoch. SS [0=deter.]\n"
" --centralize centralize the rule [do centralize]\n"
" --no-centralize do not centralize the rule [do centralize]\n"
" --prefix <string> prefix of variables in Mat-4 file [\"dyn\"]\n"
" --seed <num> random number generator seed [934098]\n"
" --order <num> order of approximation [no default]\n"
" --threads <num> number of max parallel threads [2]\n"
" --ss-tol <num> steady state calcs tolerance [1.e-13]\n"
" --check pesPES check model residuals [no checks]\n"
" lower/upper case switches off/on\n"
" pP checking along simulation path\n"
" eE checking on ellipse\n"
" sS checking along shocks\n"
" --check-evals <num> max number of evals per residual [1000]\n"
" --check-num <num> number of checked points [10]\n"
" --check-scale <num> scaling of checked points [2.0]\n"
" --no-irfs shuts down IRF simulations [do IRFs]\n"
" --irfs performs IRF simulations [do IRFs]\n"
" --qz-criterium <num> threshold for stable eigenvalues [1.000001]\n"
"\n\n";
// returns the pointer to the first character after the last slash or
// backslash in the string
const char* dyn_basename(const char* str);
DynareParams::DynareParams(int argc, char** argv)
: modname(NULL), num_per(100), num_burn(0), num_sim(80),
num_rtper(0), num_rtsim(0),
num_condper(0), num_condsim(0),
num_threads(2), num_steps(0),
prefix("dyn"), seed(934098), order(-1), ss_tol(1.e-13),
check_along_path(false), check_along_shocks(false),
check_on_ellipse(false), check_evals(1000), check_num(10), check_scale(2.0),
do_irfs_all(true), do_centralize(true), qz_criterium(1.0+1e-6),
help(false), version(false)
{
if (argc == 1 || !strcmp(argv[1],"--help")) {
help = true;
return;
}
if (argc == 1 || !strcmp(argv[1],"--version")) {
version = true;
return;
}
modname = argv[argc-1];
argc--;
struct option const opts [] = {
{"periods", required_argument, NULL, opt_per},
{"per", required_argument, NULL, opt_per},
{"burn", required_argument, NULL, opt_burn},
{"simulations", required_argument, NULL, opt_sim},
{"sim", required_argument, NULL, opt_sim},
{"rtperiods", required_argument, NULL, opt_rtper},
{"rtper", required_argument, NULL, opt_rtper},
{"rtsimulations", required_argument, NULL, opt_rtsim},
{"rtsim", required_argument, NULL, opt_rtsim},
{"condperiods", required_argument, NULL, opt_condper},
{"condper", required_argument, NULL, opt_condper},
{"condsimulations", required_argument, NULL, opt_condsim},
{"condsim", required_argument, NULL, opt_condsim},
{"prefix", required_argument, NULL, opt_prefix},
{"threads", required_argument, NULL, opt_threads},
{"steps", required_argument, NULL, opt_steps},
{"seed", required_argument, NULL, opt_seed},
{"order", required_argument, NULL, opt_order},
{"ss-tol", required_argument, NULL, opt_ss_tol},
{"check", required_argument, NULL, opt_check},
{"check-scale", required_argument, NULL, opt_check_scale},
{"check-evals", required_argument, NULL, opt_check_evals},
{"check-num", required_argument, NULL, opt_check_num},
{"qz-criterium",required_argument, NULL, opt_qz_criterium},
{"no-irfs", no_argument, NULL, opt_noirfs},
{"irfs", no_argument, NULL, opt_irfs},
{"centralize", no_argument, NULL, opt_centralize},
{"no-centralize", no_argument, NULL, opt_no_centralize},
{"help", no_argument, NULL, opt_help},
{"version", no_argument, NULL, opt_version},
{NULL, 0, NULL, 0}
};
int ret;
int index;
while (-1 != (ret = getopt_long(argc, argv, "", opts, &index))) {
switch (ret) {
case opt_per:
if (1 != sscanf(optarg, "%d", &num_per))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_burn:
if (1 != sscanf(optarg, "%d", &num_burn))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_sim:
if (1 != sscanf(optarg, "%d", &num_sim))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_rtper:
if (1 != sscanf(optarg, "%d", &num_rtper))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_rtsim:
if (1 != sscanf(optarg, "%d", &num_rtsim))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_condper:
if (1 != sscanf(optarg, "%d", &num_condper))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_condsim:
if (1 != sscanf(optarg, "%d", &num_condsim))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_prefix:
prefix = optarg;
break;
case opt_threads:
if (1 != sscanf(optarg, "%d", &num_threads))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_steps:
if (1 != sscanf(optarg, "%d", &num_steps))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_seed:
if (1 != sscanf(optarg, "%d", &seed))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_order:
if (1 != sscanf(optarg, "%d", &order))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_ss_tol:
if (1 != sscanf(optarg, "%lf", &ss_tol))
fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg);
break;
case opt_check:
processCheckFlags(optarg);
break;
case opt_check_scale:
if (1 != sscanf(optarg, "%lf", &check_scale))
fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg);
break;
case opt_check_evals:
if (1 != sscanf(optarg, "%d", &check_evals))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_check_num:
if (1 != sscanf(optarg, "%d", &check_num))
fprintf(stderr, "Couldn't parse integer %s, ignored\n", optarg);
break;
case opt_noirfs:
irf_list.clear();
do_irfs_all = false;
break;
case opt_irfs:
processIRFList(argc, argv);
if (irf_list.empty())
do_irfs_all = true;
else
do_irfs_all = false;
break;
case opt_centralize:
do_centralize = true;
break;
case opt_no_centralize:
do_centralize = false;
break;
case opt_qz_criterium:
if (1 != sscanf(optarg, "%lf", &qz_criterium))
fprintf(stderr, "Couldn't parse float %s, ignored\n", optarg);
break;
case opt_help:
help = true;
break;
case opt_version:
version = true;
break;
case '?':
fprintf(stderr, "Unknown option, ignored\n");
break;
}
}
// make basename (get rid of the extension)
basename = dyn_basename(modname);
std::string::size_type i = basename.rfind('.');
if (i != std::string::npos)
basename.erase(i);
}
void DynareParams::printHelp() const
{
printf("%s", help_str);
}
void DynareParams::processCheckFlags(const char* flags)
{
for (unsigned int i = 0; i < strlen(flags); i++) {
switch (flags[i]) {
case 'p':
check_along_path = false;
break;
case 'P':
check_along_path = true;
break;
case 'e':
check_on_ellipse = false;
break;
case 'E':
check_on_ellipse = true;
break;
case 's':
check_along_shocks = false;
break;
case 'S':
check_along_shocks = true;
break;
default:
fprintf(stderr, "Unknown check type selection character <%c>, ignored.\n", flags[i]);
}
}
}
void DynareParams::processIRFList(int argc, char** argv)
{
irf_list.clear();
while (optind < argc && *(argv[optind]) != '-') {
irf_list.push_back(argv[optind]);
optind++;
}
}
const char* dyn_basename(const char* str)
{
int i = strlen(str);
while (i > 0 && str[i-1] != '/' && str[i-1] != '\\')
i--;
return str+i;
}
// Local Variables:
// mode:C++
// End:

View File

@ -1,5 +1,5 @@
%{
#include "parser/cc/location.h"
#include "parser/cc/location.hh"
#include "dynglob_tab.hh"
extern YYLTYPE dynglob_lloc;

View File

@ -1,8 +1,8 @@
%{
// Copyright (C) 2006-2011, Ondra Kamenik
#include "parser/cc/location.h"
#include "dynare_model.h"
#include "parser/cc/location.hh"
#include "dynare_model.hh"
#include "dynglob_tab.hh"
#include <stdio.h>

View File

@ -0,0 +1,133 @@
// Copyright (C) 2006-2011, Ondra Kamenik
#include "forw_subst_builder.hh"
using namespace ogdyn;
ForwSubstBuilder::ForwSubstBuilder(DynareModel &m)
: model(m)
{
info.num_new_terms -= model.getParser().getTree().get_num_op();
// go through all equations
int neq = model.eqs.nformulas();
for (int i = 0; i < neq; i++)
{
int ft = model.eqs.formula(i);
int mlead, mlag;
model.termspan(ft, mlead, mlag);
// if equation is too forward looking
if (mlead > 1)
{
info.num_affected_equations++;
// break it to non-linear terms
unordered_set<int> nlt = model.get_nonlinear_subterms(ft);
int j = 0; // indexes subterms
// and make substitutions for all these non-linear subterms
for (unordered_set<int>::const_iterator it = nlt.begin();
it != nlt.end(); ++it, ++j)
substitute_for_term(*it, i, j);
}
}
// unassign all variables with lead greater than 1
unassign_gt_1_leads();
// forget the derivatives in the tree because some variables could
// have been unassigned
model.eqs.getTree().forget_derivative_maps();
info.num_new_terms += model.getParser().getTree().get_num_op();
}
void
ForwSubstBuilder::substitute_for_term(int t, int i, int j)
{
int mlead, mlag;
model.termspan(t, mlead, mlag);
if (mlead > 1)
{
info.num_subst_terms++;
// Example for comments: let t = f(x(+4))
// first make lagsubst be substitution setting f(x(+4)) to f(x(+1))
// this is lag = -3 (1-mlead)
map<int, int> lagsubst;
unordered_set<int> nult = model.eqs.nulary_of_term(t);// make copy of nult!
model.variable_shift_map(nult, 1-mlead, lagsubst);
int lagt = model.eqs.add_substitution(t, lagsubst);
// now maxlead of lagt is +1
// add AUXLD_*_*_1 = f(x(+1)) to the model
char name[100];
sprintf(name, "AUXLD_%d_%d_%d", i, j, 1);
model.atoms.register_uniq_endo(name);
info.num_aux_variables++;
const char *ss = model.atoms.get_name_storage().query(name);
int auxt = model.eqs.add_nulary(name);
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, auxt, lagt));
aux_map.insert(Tsubstmap::value_type(ss, lagt));
// now add variables and equations
// AUXLD_*_*_2 = AUXLD_*_*_1(+1) through
// AUXLD_*_*_{mlead-1} = AUXLD_*_*_{mlead-2}(+1)
for (int ll = 1; ll <= mlead-2; ll++)
{
// create AUXLD_*_*_{ll}(+1)
sprintf(name, "AUXLD_%d_%d_%d(+1)", i, j, ll);
int lastauxt_lead = model.eqs.add_nulary(name);
// create AUXLD_*_*{ll+1}
sprintf(name, "AUXLD_%d_%d_%d", i, j, ll+1);
model.atoms.register_uniq_endo(name);
info.num_aux_variables++;
ss = model.atoms.get_name_storage().query(name);
auxt = model.eqs.add_nulary(name);
// add AUXLD_*_*_{ll+1} = AUXLD_*_*_{ll}(+1)
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, auxt, lastauxt_lead));
// add substitution to the map; todo: this
// works well because in the context where
// aux_map is used the timing doesn't matter,
// however, it is misleading, needs to be
// changed
aux_map.insert(Tsubstmap::value_type(ss, lagt));
}
// now we have to substitute AUXLD_*_*{mlead-1}(+1) for t
sprintf(name, "AUXLD_%d_%d_%d", i, j, mlead-1);
ss = model.atoms.get_name_storage().query(name);
model.substitute_atom_for_term(ss, +1, t);
}
}
void
ForwSubstBuilder::unassign_gt_1_leads(const char *name)
{
const char *ss = model.atoms.get_name_storage().query(name);
int mlead, mlag;
model.atoms.varspan(name, mlead, mlag);
for (int ll = 2; ll <= mlead; ll++)
{
int t = model.atoms.index(ss, ll);
if (t != -1)
model.atoms.unassign_variable(ss, ll, t);
}
}
void
ForwSubstBuilder::unassign_gt_1_leads()
{
const vector<const char *> &endovars = model.atoms.get_endovars();
for (unsigned int i = 0; i < endovars.size(); i++)
unassign_gt_1_leads(endovars[i]);
const vector<const char *> &exovars = model.atoms.get_exovars();
for (unsigned int i = 0; i < exovars.size(); i++)
unassign_gt_1_leads(exovars[i]);
}
ForwSubstBuilder::ForwSubstBuilder(const ForwSubstBuilder &b, DynareModel &m)
: model(m)
{
for (Tsubstmap::const_iterator it = b.aux_map.begin();
it != b.aux_map.end(); ++it)
{
const char *ss = m.atoms.get_name_storage().query((*it).first);
aux_map.insert(Tsubstmap::value_type(ss, (*it).second));
}
}

View File

@ -1,125 +0,0 @@
// Copyright (C) 2006-2011, Ondra Kamenik
#include "forw_subst_builder.h"
using namespace ogdyn;
ForwSubstBuilder::ForwSubstBuilder(DynareModel& m)
: model(m)
{
info.num_new_terms -= model.getParser().getTree().get_num_op();
// go through all equations
int neq = model.eqs.nformulas();
for (int i = 0; i < neq; i++) {
int ft = model.eqs.formula(i);
int mlead, mlag;
model.termspan(ft, mlead, mlag);
// if equation is too forward looking
if (mlead > 1) {
info.num_affected_equations++;
// break it to non-linear terms
unordered_set<int> nlt = model.get_nonlinear_subterms(ft);
int j = 0; // indexes subterms
// and make substitutions for all these non-linear subterms
for (unordered_set<int>::const_iterator it = nlt.begin();
it != nlt.end(); ++it, ++j)
substitute_for_term(*it, i, j);
}
}
// unassign all variables with lead greater than 1
unassign_gt_1_leads();
// forget the derivatives in the tree because some variables could
// have been unassigned
model.eqs.getTree().forget_derivative_maps();
info.num_new_terms += model.getParser().getTree().get_num_op();
}
void ForwSubstBuilder::substitute_for_term(int t, int i, int j)
{
int mlead, mlag;
model.termspan(t, mlead, mlag);
if (mlead > 1) {
info.num_subst_terms++;
// Example for comments: let t = f(x(+4))
// first make lagsubst be substitution setting f(x(+4)) to f(x(+1))
// this is lag = -3 (1-mlead)
map<int,int> lagsubst;
unordered_set<int> nult = model.eqs.nulary_of_term(t);// make copy of nult!
model.variable_shift_map(nult, 1-mlead, lagsubst);
int lagt = model.eqs.add_substitution(t, lagsubst);
// now maxlead of lagt is +1
// add AUXLD_*_*_1 = f(x(+1)) to the model
char name[100];
sprintf(name, "AUXLD_%d_%d_%d", i, j, 1);
model.atoms.register_uniq_endo(name);
info.num_aux_variables++;
const char* ss = model.atoms.get_name_storage().query(name);
int auxt = model.eqs.add_nulary(name);
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, auxt, lagt));
aux_map.insert(Tsubstmap::value_type(ss, lagt));
// now add variables and equations
// AUXLD_*_*_2 = AUXLD_*_*_1(+1) through
// AUXLD_*_*_{mlead-1} = AUXLD_*_*_{mlead-2}(+1)
for (int ll = 1; ll <= mlead-2; ll++) {
// create AUXLD_*_*_{ll}(+1)
sprintf(name, "AUXLD_%d_%d_%d(+1)", i, j, ll);
int lastauxt_lead = model.eqs.add_nulary(name);
// create AUXLD_*_*{ll+1}
sprintf(name, "AUXLD_%d_%d_%d", i, j, ll+1);
model.atoms.register_uniq_endo(name);
info.num_aux_variables++;
ss = model.atoms.get_name_storage().query(name);
auxt = model.eqs.add_nulary(name);
// add AUXLD_*_*_{ll+1} = AUXLD_*_*_{ll}(+1)
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, auxt, lastauxt_lead));
// add substitution to the map; todo: this
// works well because in the context where
// aux_map is used the timing doesn't matter,
// however, it is misleading, needs to be
// changed
aux_map.insert(Tsubstmap::value_type(ss, lagt));
}
// now we have to substitute AUXLD_*_*{mlead-1}(+1) for t
sprintf(name, "AUXLD_%d_%d_%d", i, j, mlead-1);
ss = model.atoms.get_name_storage().query(name);
model.substitute_atom_for_term(ss, +1, t);
}
}
void ForwSubstBuilder::unassign_gt_1_leads(const char* name)
{
const char* ss = model.atoms.get_name_storage().query(name);
int mlead, mlag;
model.atoms.varspan(name, mlead, mlag);
for (int ll = 2; ll <= mlead; ll++) {
int t = model.atoms.index(ss, ll);
if (t != -1)
model.atoms.unassign_variable(ss, ll, t);
}
}
void ForwSubstBuilder::unassign_gt_1_leads()
{
const vector<const char*>& endovars = model.atoms.get_endovars();
for (unsigned int i = 0; i < endovars.size(); i++)
unassign_gt_1_leads(endovars[i]);
const vector<const char*>& exovars = model.atoms.get_exovars();
for (unsigned int i = 0; i < exovars.size(); i++)
unassign_gt_1_leads(exovars[i]);
}
ForwSubstBuilder::ForwSubstBuilder(const ForwSubstBuilder& b, DynareModel& m)
: model(m)
{
for (Tsubstmap::const_iterator it = b.aux_map.begin();
it != b.aux_map.end(); ++it) {
const char* ss = m.atoms.get_name_storage().query((*it).first);
aux_map.insert(Tsubstmap::value_type(ss, (*it).second));
}
}

View File

@ -5,7 +5,7 @@
#ifndef FORW_SUBST_BUILDER_H
#define FORW_SUBST_BUILDER_H
#include "dynare_model.h"
#include "dynare_model.hh"
namespace ogdyn
{

214
dynare++/src/main.cc Normal file
View File

@ -0,0 +1,214 @@
// Copyright (C) 2004-2011, Ondra Kamenik
#include "dynare3.hh"
#include "dynare_exception.hh"
#include "dynare_params.hh"
#include "utils/cc/exception.hh"
#include "parser/cc/parser_exception.hh"
#include "../sylv/cc/SylvException.hh"
#include "../kord/random.hh"
#include "../kord/global_check.hh"
#include "../kord/approximation.hh"
int
main(int argc, char **argv)
{
DynareParams params(argc, argv);
if (params.help)
{
params.printHelp();
return 0;
}
if (params.version)
{
printf("Dynare++ v. %s. Copyright (C) 2004-2011, Ondra Kamenik\n",
DYNVERSION);
printf("Dynare++ comes with ABSOLUTELY NO WARRANTY and is distributed under\n");
printf("GPL: modules integ, tl, kord, sylv, src, extern and documentation\n");
printf("LGPL: modules parser, utils\n");
printf(" for GPL see http://www.gnu.org/licenses/gpl.html\n");
printf(" for LGPL see http://www.gnu.org/licenses/lgpl.html\n");
return 0;
}
THREAD_GROUP::max_parallel_threads = params.num_threads;
try
{
// make journal name and journal
std::string jname(params.basename);
jname += ".jnl";
Journal journal(jname.c_str());
// make dynare object
Dynare dynare(params.modname, params.order, params.ss_tol, journal);
// make list of shocks for which we will do IRFs
vector<int> irf_list_ind;
if (params.do_irfs_all)
for (int i = 0; i < dynare.nexog(); i++)
irf_list_ind.push_back(i);
else
irf_list_ind = ((const DynareNameList &) dynare.getExogNames()).selectIndices(params.irf_list);
// write matlab files
FILE *mfd;
std::string mfile1(params.basename);
mfile1 += "_f.m";
if (NULL == (mfd = fopen(mfile1.c_str(), "w")))
{
fprintf(stderr, "Couldn't open %s for writing.\n", mfile1.c_str());
exit(1);
}
ogdyn::MatlabSSWriter writer0(dynare.getModel(), params.basename.c_str());
writer0.write_der0(mfd);
fclose(mfd);
std::string mfile2(params.basename);
mfile2 += "_ff.m";
if (NULL == (mfd = fopen(mfile2.c_str(), "w")))
{
fprintf(stderr, "Couldn't open %s for writing.\n", mfile2.c_str());
exit(1);
}
ogdyn::MatlabSSWriter writer1(dynare.getModel(), params.basename.c_str());
writer1.write_der1(mfd);
fclose(mfd);
// open mat file
std::string matfile(params.basename);
matfile += ".mat";
mat_t *matfd = Mat_Create(matfile.c_str(), NULL);
if (matfd == NULL)
{
fprintf(stderr, "Couldn't open %s for writing.\n", matfile.c_str());
exit(1);
}
// write info about the model (dimensions and variables)
dynare.writeMat(matfd, params.prefix);
// write the dump file corresponding to the input
dynare.writeDump(params.basename);
system_random_generator.initSeed(params.seed);
tls.init(dynare.order(),
dynare.nstat()+2*dynare.npred()+3*dynare.nboth()
+2*dynare.nforw()+dynare.nexog());
Approximation app(dynare, journal, params.num_steps, params.do_centralize, params.qz_criterium);
try
{
app.walkStochSteady();
}
catch (const KordException &e)
{
// tell about the exception and continue
printf("Caught (not yet fatal) Kord exception: ");
e.print();
JournalRecord rec(journal);
rec << "Solution routine not finished (" << e.get_message()
<< "), see what happens" << endrec;
}
std::string ss_matrix_name(params.prefix);
ss_matrix_name += "_steady_states";
ConstTwoDMatrix(app.getSS()).writeMat(matfd, ss_matrix_name.c_str());
// check the approximation
if (params.check_along_path || params.check_along_shocks
|| params.check_on_ellipse)
{
GlobalChecker gcheck(app, THREAD_GROUP::max_parallel_threads, journal);
if (params.check_along_shocks)
gcheck.checkAlongShocksAndSave(matfd, params.prefix,
params.getCheckShockPoints(),
params.getCheckShockScale(),
params.check_evals);
if (params.check_on_ellipse)
gcheck.checkOnEllipseAndSave(matfd, params.prefix,
params.getCheckEllipsePoints(),
params.getCheckEllipseScale(),
params.check_evals);
if (params.check_along_path)
gcheck.checkAlongSimulationAndSave(matfd, params.prefix,
params.getCheckPathPoints(),
params.check_evals);
}
// write the folded decision rule to the Mat-4 file
app.getFoldDecisionRule().writeMat(matfd, params.prefix);
// simulate conditional
if (params.num_condper > 0 && params.num_condsim > 0)
{
SimResultsDynamicStats rescond(dynare.numeq(), params.num_condper, 0);
ConstVector det_ss(app.getSS(), 0);
rescond.simulate(params.num_condsim, app.getFoldDecisionRule(), det_ss, dynare.getVcov(), journal);
rescond.writeMat(matfd, params.prefix);
}
// simulate unconditional
//const DecisionRule& dr = app.getUnfoldDecisionRule();
const DecisionRule &dr = app.getFoldDecisionRule();
if (params.num_per > 0 && params.num_sim > 0)
{
SimResultsStats res(dynare.numeq(), params.num_per, params.num_burn);
res.simulate(params.num_sim, dr, dynare.getSteady(), dynare.getVcov(), journal);
res.writeMat(matfd, params.prefix);
// impulse response functions
if (!irf_list_ind.empty())
{
IRFResults irf(dynare, dr, res, irf_list_ind, journal);
irf.writeMat(matfd, params.prefix);
}
}
// simulate with real-time statistics
if (params.num_rtper > 0 && params.num_rtsim > 0)
{
RTSimResultsStats rtres(dynare.numeq(), params.num_rtper, params.num_burn);
rtres.simulate(params.num_rtsim, dr, dynare.getSteady(), dynare.getVcov(), journal);
rtres.writeMat(matfd, params.prefix);
}
Mat_Close(matfd);
}
catch (const KordException &e)
{
printf("Caugth Kord exception: ");
e.print();
return e.code();
}
catch (const TLException &e)
{
printf("Caugth TL exception: ");
e.print();
return 255;
}
catch (SylvException &e)
{
printf("Caught Sylv exception: ");
e.printMessage();
return 255;
}
catch (const DynareException &e)
{
printf("Caught Dynare exception: %s\n", e.message());
return 255;
}
catch (const ogu::Exception &e)
{
printf("Caught ogu::Exception: ");
e.print();
return 255;
}
catch (const ogp::ParserException &e)
{
printf("Caught parser exception: %s\n", e.message());
return 255;
}
return 0;
}

View File

@ -1,188 +0,0 @@
// Copyright (C) 2004-2011, Ondra Kamenik
#include "dynare3.h"
#include "dynare_exception.h"
#include "dynare_params.h"
#include "utils/cc/exception.h"
#include "parser/cc/parser_exception.h"
#include "../sylv/cc/SylvException.h"
#include "../kord/random.hh"
#include "../kord/global_check.hh"
#include "../kord/approximation.hh"
int main(int argc, char** argv)
{
DynareParams params(argc, argv);
if (params.help) {
params.printHelp();
return 0;
}
if (params.version) {
printf("Dynare++ v. %s. Copyright (C) 2004-2011, Ondra Kamenik\n",
DYNVERSION);
printf("Dynare++ comes with ABSOLUTELY NO WARRANTY and is distributed under\n");
printf("GPL: modules integ, tl, kord, sylv, src, extern and documentation\n");
printf("LGPL: modules parser, utils\n");
printf(" for GPL see http://www.gnu.org/licenses/gpl.html\n");
printf(" for LGPL see http://www.gnu.org/licenses/lgpl.html\n");
return 0;
}
THREAD_GROUP::max_parallel_threads = params.num_threads;
try {
// make journal name and journal
std::string jname(params.basename);
jname += ".jnl";
Journal journal(jname.c_str());
// make dynare object
Dynare dynare(params.modname, params.order, params.ss_tol, journal);
// make list of shocks for which we will do IRFs
vector<int> irf_list_ind;
if (params.do_irfs_all)
for (int i = 0; i < dynare.nexog(); i++)
irf_list_ind.push_back(i);
else
irf_list_ind = ((const DynareNameList&)dynare.getExogNames()).selectIndices(params.irf_list);
// write matlab files
FILE* mfd;
std::string mfile1(params.basename);
mfile1 += "_f.m";
if (NULL == (mfd=fopen(mfile1.c_str(), "w"))) {
fprintf(stderr, "Couldn't open %s for writing.\n", mfile1.c_str());
exit(1);
}
ogdyn::MatlabSSWriter writer0(dynare.getModel(), params.basename.c_str());
writer0.write_der0(mfd);
fclose(mfd);
std::string mfile2(params.basename);
mfile2 += "_ff.m";
if (NULL == (mfd=fopen(mfile2.c_str(), "w"))) {
fprintf(stderr, "Couldn't open %s for writing.\n", mfile2.c_str());
exit(1);
}
ogdyn::MatlabSSWriter writer1(dynare.getModel(), params.basename.c_str());
writer1.write_der1(mfd);
fclose(mfd);
// open mat file
std::string matfile(params.basename);
matfile += ".mat";
mat_t* matfd = Mat_Create(matfile.c_str(), NULL);
if (matfd == NULL) {
fprintf(stderr, "Couldn't open %s for writing.\n", matfile.c_str());
exit(1);
}
// write info about the model (dimensions and variables)
dynare.writeMat(matfd, params.prefix);
// write the dump file corresponding to the input
dynare.writeDump(params.basename);
system_random_generator.initSeed(params.seed);
tls.init(dynare.order(),
dynare.nstat()+2*dynare.npred()+3*dynare.nboth()+
2*dynare.nforw()+dynare.nexog());
Approximation app(dynare, journal, params.num_steps, params.do_centralize, params.qz_criterium);
try {
app.walkStochSteady();
} catch (const KordException& e) {
// tell about the exception and continue
printf("Caught (not yet fatal) Kord exception: ");
e.print();
JournalRecord rec(journal);
rec << "Solution routine not finished (" << e.get_message()
<< "), see what happens" << endrec;
}
std::string ss_matrix_name(params.prefix);
ss_matrix_name += "_steady_states";
ConstTwoDMatrix(app.getSS()).writeMat(matfd, ss_matrix_name.c_str());
// check the approximation
if (params.check_along_path || params.check_along_shocks
|| params.check_on_ellipse) {
GlobalChecker gcheck(app, THREAD_GROUP::max_parallel_threads, journal);
if (params.check_along_shocks)
gcheck.checkAlongShocksAndSave(matfd, params.prefix,
params.getCheckShockPoints(),
params.getCheckShockScale(),
params.check_evals);
if (params.check_on_ellipse)
gcheck.checkOnEllipseAndSave(matfd, params.prefix,
params.getCheckEllipsePoints(),
params.getCheckEllipseScale(),
params.check_evals);
if (params.check_along_path)
gcheck.checkAlongSimulationAndSave(matfd, params.prefix,
params.getCheckPathPoints(),
params.check_evals);
}
// write the folded decision rule to the Mat-4 file
app.getFoldDecisionRule().writeMat(matfd, params.prefix);
// simulate conditional
if (params.num_condper > 0 && params.num_condsim > 0) {
SimResultsDynamicStats rescond(dynare.numeq(), params.num_condper, 0);
ConstVector det_ss(app.getSS(),0);
rescond.simulate(params.num_condsim, app.getFoldDecisionRule(), det_ss, dynare.getVcov(), journal);
rescond.writeMat(matfd, params.prefix);
}
// simulate unconditional
//const DecisionRule& dr = app.getUnfoldDecisionRule();
const DecisionRule& dr = app.getFoldDecisionRule();
if (params.num_per > 0 && params.num_sim > 0) {
SimResultsStats res(dynare.numeq(), params.num_per, params.num_burn);
res.simulate(params.num_sim, dr, dynare.getSteady(), dynare.getVcov(), journal);
res.writeMat(matfd, params.prefix);
// impulse response functions
if (! irf_list_ind.empty()) {
IRFResults irf(dynare, dr, res, irf_list_ind, journal);
irf.writeMat(matfd, params.prefix);
}
}
// simulate with real-time statistics
if (params.num_rtper > 0 && params.num_rtsim > 0) {
RTSimResultsStats rtres(dynare.numeq(), params.num_rtper, params.num_burn);
rtres.simulate(params.num_rtsim, dr, dynare.getSteady(), dynare.getVcov(), journal);
rtres.writeMat(matfd, params.prefix);
}
Mat_Close(matfd);
} catch (const KordException& e) {
printf("Caugth Kord exception: ");
e.print();
return e.code();
} catch (const TLException& e) {
printf("Caugth TL exception: ");
e.print();
return 255;
} catch (SylvException& e) {
printf("Caught Sylv exception: ");
e.printMessage();
return 255;
} catch (const DynareException& e) {
printf("Caught Dynare exception: %s\n", e.message());
return 255;
} catch (const ogu::Exception& e) {
printf("Caught ogu::Exception: ");
e.print();
return 255;
} catch (const ogp::ParserException& e) {
printf("Caught parser exception: %s\n", e.message());
return 255;
}
return 0;
}

265
dynare++/src/nlsolve.cc Normal file
View File

@ -0,0 +1,265 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: nlsolve.cpp 762 2006-05-22 13:00:07Z kamenik $
#include "nlsolve.hh"
#include "dynare_exception.hh"
#include <cmath>
using namespace ogu;
/** This should not be greater than DBL_EPSILON^(1/2). */
double GoldenSectionSearch::tol = 1.e-4;
/** This is equal to the golden section ratio. */
double GoldenSectionSearch::golden = (3.-std::sqrt(5.))/2;
double
GoldenSectionSearch::search(OneDFunction &f, double x1, double x2)
{
double b;
if (init_bracket(f, x1, x2, b))
{
double fb = f.eval(b);
double f1 = f.eval(x1);
f.eval(x2);
double dx;
do
{
double w = (b-x1)/(x2-x1);
dx = std::abs((1-2*w)*(x2-x1));
double x;
if (b-x1 > x2-b)
x = b - dx;
else
x = b + dx;
double fx = f.eval(x);
if (!std::isfinite(fx))
return x1;
if (b-x1 > x2-b)
{
// x is on the left from b
if (f1 > fx && fx < fb)
{
// pickup bracket [f1,fx,fb]
x2 = b;
fb = fx;
b = x;
}
else
{
// pickup bracket [fx,fb,fx2]
f1 = fx;
x1 = x;
}
}
else
{
// x is on the right from b
if (f1 > fb && fb < fx)
{
// pickup bracket [f1,fb,fx]
x2 = x;
}
else
{
// pickup bracket [fb,fx,f2]
f1 = fb;
x1 = b;
fb = fx;
b = x;
}
}
}
while (dx > tol);
}
return b;
}
bool
GoldenSectionSearch::init_bracket(OneDFunction &f, double x1, double &x2, double &b)
{
double f1 = f.eval(x1);
if (!std::isfinite(f1))
throw DynareException(__FILE__, __LINE__,
"Safer point not finite in GoldenSectionSearch::init_bracket");
int cnt = 0;
bool bracket_found = false;
do
{
bool finite_found = search_for_finite(f, x1, x2, b);
if (!finite_found)
{
b = x1;
return false;
}
double f2 = f.eval(x2);
double fb = f.eval(b);
double bsym = 2*x2 - b;
double fbsym = f.eval(bsym);
// now we know that f1, f2, and fb are finite
if (std::isfinite(fbsym))
{
// we have four numbers f1, fb, f2, fbsym, we test for the
// following combinations to find the bracket:
// [f1,f2,fbsym], [f1,fb,fbsym] and [f1,fb,fbsym]
if (f1 > f2 && f2 < fbsym)
{
bracket_found = true;
b = x2;
x2 = bsym;
}
else if (f1 > fb && fb < fbsym)
{
bracket_found = true;
x2 = bsym;
}
else if (f1 > fb && fb < f2)
{
bracket_found = true;
}
else
{
double newx2 = b;
// choose the smallest value in case we end
if (f1 > fbsym)
{
// the smallest value is on the other end, we do
// not want to continue
b = bsym;
return false;
}
else
b = x1;
// move x2 to b in case we continue
x2 = newx2;
}
}
else
{
// we have only three numbers, we test for the bracket,
// and if not found, we set b as potential result and
// shorten x2 as potential init value for next cycle
if (f1 > fb && fb < f2)
bracket_found = true;
else
{
double newx2 = b;
// choose the smaller value in case we end
if (f1 > f2)
b = x2;
else
b = x1;
// move x2 to b in case we continue
x2 = newx2;
}
}
cnt++;
}
while (!bracket_found && cnt < 5);
return bracket_found;
}
/** This moves x2 toward to x1 until the function at x2 is finite and
* b as a golden section between x1 and x2 yields also finite f. */
bool
GoldenSectionSearch::search_for_finite(OneDFunction &f, double x1, double &x2, double &b)
{
int cnt = 0;
bool found = false;
do
{
double f2 = f.eval(x2);
b = (1-golden)*x1 + golden*x2;
double fb = f.eval(b);
found = std::isfinite(f2) && std::isfinite(fb);
if (!found)
x2 = b;
cnt++;
}
while (!found && cnt < 5);
return found;
}
void
VectorFunction::check_for_eval(const ConstVector &in, Vector &out) const
{
if (inDim() != in.length() || outDim() != out.length())
throw DynareException(__FILE__, __LINE__,
"Wrong dimensions in VectorFunction::check_for_eval");
}
double
NLSolver::eval(double lambda)
{
Vector xx((const Vector &)x);
xx.add(1-lambda, xcauchy);
xx.add(lambda, xnewton);
Vector ff(func.outDim());
func.eval(xx, ff);
return ff.dot(ff);
}
bool
NLSolver::solve(Vector &xx, int &iter)
{
JournalRecord rec(journal);
rec << "Iter lambda residual" << endrec;
JournalRecord rec1(journal);
rec1 << "---------------------------" << endrec;
char tmpbuf[14];
x = (const Vector &) xx;
iter = 0;
// setup fx
Vector fx(func.outDim());
func.eval(x, fx);
if (!fx.isFinite())
throw DynareException(__FILE__, __LINE__,
"Initial guess does not yield finite residual in NLSolver::solve");
bool converged = fx.getMax() < tol;
JournalRecord rec2(journal);
sprintf(tmpbuf, "%10.6g", fx.getMax());
rec2 << iter << " N/A " << tmpbuf << endrec;
while (!converged && iter < max_iter)
{
// setup Jacobian
jacob.eval(x);
// calculate cauchy step
Vector g(func.inDim());
g.zeros();
ConstTwoDMatrix(jacob).multaVecTrans(g, fx);
Vector Jg(func.inDim());
Jg.zeros();
ConstTwoDMatrix(jacob).multaVec(Jg, g);
double m = -g.dot(g)/Jg.dot(Jg);
xcauchy = (const Vector &) g;
xcauchy.mult(m);
// calculate newton step
xnewton = (const Vector &) fx;
ConstTwoDMatrix(jacob).multInvLeft(xnewton);
xnewton.mult(-1);
// line search
double lambda = GoldenSectionSearch::search(*this, 0, 1);
x.add(1-lambda, xcauchy);
x.add(lambda, xnewton);
// evaluate func
func.eval(x, fx);
converged = fx.getMax() < tol;
// iter
iter++;
JournalRecord rec3(journal);
sprintf(tmpbuf, "%10.6g", fx.getMax());
rec3 << iter << " " << lambda << " " << tmpbuf << endrec;
}
xx = (const Vector &) x;
return converged;
}

View File

@ -1,228 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id: nlsolve.cpp 762 2006-05-22 13:00:07Z kamenik $
#include "nlsolve.h"
#include "dynare_exception.h"
#include <cmath>
using namespace ogu;
/** This should not be greater than DBL_EPSILON^(1/2). */
double GoldenSectionSearch::tol = 1.e-4;
/** This is equal to the golden section ratio. */
double GoldenSectionSearch::golden = (3.-std::sqrt(5.))/2;
double GoldenSectionSearch::search(OneDFunction& f, double x1, double x2)
{
double b;
if (init_bracket(f, x1, x2, b)) {
double fb = f.eval(b);
double f1 = f.eval(x1);
f.eval(x2);
double dx;
do {
double w = (b-x1)/(x2-x1);
dx = std::abs((1-2*w)*(x2-x1));
double x;
if (b-x1 > x2-b)
x = b - dx;
else
x = b + dx;
double fx = f.eval(x);
if (! std::isfinite(fx))
return x1;
if (b-x1 > x2-b) {
// x is on the left from b
if (f1 > fx && fx < fb) {
// pickup bracket [f1,fx,fb]
x2 = b;
fb = fx;
b = x;
} else {
// pickup bracket [fx,fb,fx2]
f1 = fx;
x1 = x;
}
} else {
// x is on the right from b
if (f1 > fb && fb < fx) {
// pickup bracket [f1,fb,fx]
x2 = x;
} else {
// pickup bracket [fb,fx,f2]
f1 = fb;
x1 = b;
fb = fx;
b = x;
}
}
} while(dx > tol);
}
return b;
}
bool GoldenSectionSearch::init_bracket(OneDFunction& f, double x1, double& x2, double& b)
{
double f1 = f.eval(x1);
if (! std::isfinite(f1))
throw DynareException(__FILE__, __LINE__,
"Safer point not finite in GoldenSectionSearch::init_bracket");
int cnt = 0;
bool bracket_found = false;
do {
bool finite_found = search_for_finite(f, x1, x2, b);
if (! finite_found) {
b = x1;
return false;
}
double f2 = f.eval(x2);
double fb = f.eval(b);
double bsym = 2*x2 - b;
double fbsym = f.eval(bsym);
// now we know that f1, f2, and fb are finite
if (std::isfinite(fbsym)) {
// we have four numbers f1, fb, f2, fbsym, we test for the
// following combinations to find the bracket:
// [f1,f2,fbsym], [f1,fb,fbsym] and [f1,fb,fbsym]
if (f1 > f2 && f2 < fbsym) {
bracket_found = true;
b = x2;
x2 = bsym;
} else if (f1 > fb && fb < fbsym) {
bracket_found = true;
x2 = bsym;
} else if (f1 > fb && fb < f2) {
bracket_found = true;
} else {
double newx2 = b;
// choose the smallest value in case we end
if (f1 > fbsym) {
// the smallest value is on the other end, we do
// not want to continue
b = bsym;
return false;
} else
b = x1;
// move x2 to b in case we continue
x2 = newx2;
}
} else {
// we have only three numbers, we test for the bracket,
// and if not found, we set b as potential result and
// shorten x2 as potential init value for next cycle
if (f1 > fb && fb < f2)
bracket_found = true;
else {
double newx2 = b;
// choose the smaller value in case we end
if (f1 > f2)
b = x2;
else
b = x1;
// move x2 to b in case we continue
x2 = newx2;
}
}
cnt++;
} while (! bracket_found && cnt < 5);
return bracket_found;
}
/** This moves x2 toward to x1 until the function at x2 is finite and
* b as a golden section between x1 and x2 yields also finite f. */
bool GoldenSectionSearch::search_for_finite(OneDFunction& f, double x1, double& x2, double&b)
{
int cnt = 0;
bool found = false;
do {
double f2 = f.eval(x2);
b = (1-golden)*x1 + golden*x2;
double fb = f.eval(b);
found = std::isfinite(f2) && std::isfinite(fb);
if (! found)
x2 = b;
cnt++;
} while (! found && cnt < 5);
return found;
}
void VectorFunction::check_for_eval(const ConstVector& in, Vector& out) const
{
if (inDim() != in.length() || outDim() != out.length())
throw DynareException(__FILE__, __LINE__,
"Wrong dimensions in VectorFunction::check_for_eval");
}
double NLSolver::eval(double lambda)
{
Vector xx((const Vector&)x);
xx.add(1-lambda, xcauchy);
xx.add(lambda, xnewton);
Vector ff(func.outDim());
func.eval(xx, ff);
return ff.dot(ff);
}
bool NLSolver::solve(Vector& xx, int& iter)
{
JournalRecord rec(journal);
rec << "Iter lambda residual" << endrec;
JournalRecord rec1(journal);
rec1 << "---------------------------" << endrec;
char tmpbuf[14];
x = (const Vector&)xx;
iter = 0;
// setup fx
Vector fx(func.outDim());
func.eval(x, fx);
if (!fx.isFinite())
throw DynareException(__FILE__,__LINE__,
"Initial guess does not yield finite residual in NLSolver::solve");
bool converged = fx.getMax() < tol;
JournalRecord rec2(journal);
sprintf(tmpbuf, "%10.6g", fx.getMax());
rec2 << iter << " N/A " << tmpbuf << endrec;
while (! converged && iter < max_iter) {
// setup Jacobian
jacob.eval(x);
// calculate cauchy step
Vector g(func.inDim());
g.zeros();
ConstTwoDMatrix(jacob).multaVecTrans(g, fx);
Vector Jg(func.inDim());
Jg.zeros();
ConstTwoDMatrix(jacob).multaVec(Jg, g);
double m = -g.dot(g)/Jg.dot(Jg);
xcauchy = (const Vector&) g;
xcauchy.mult(m);
// calculate newton step
xnewton = (const Vector&) fx;
ConstTwoDMatrix(jacob).multInvLeft(xnewton);
xnewton.mult(-1);
// line search
double lambda = GoldenSectionSearch::search(*this, 0, 1);
x.add(1-lambda, xcauchy);
x.add(lambda, xnewton);
// evaluate func
func.eval(x, fx);
converged = fx.getMax() < tol;
// iter
iter++;
JournalRecord rec3(journal);
sprintf(tmpbuf, "%10.6g", fx.getMax());
rec3 << iter << " " << lambda << " " << tmpbuf << endrec;
}
xx = (const Vector&)x;
return converged;
}

View File

@ -0,0 +1,419 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id$
#include "planner_builder.hh"
#include "dynare_exception.hh"
#include <cmath>
using namespace ogdyn;
const IntegerMatrix &
IntegerMatrix::operator=(const IntegerMatrix &im)
{
if (nr != im.nr || nc != im.nc)
throw DynareException(__FILE__, __LINE__,
"Matrices have different dimensions in IntegerMatrix::operator=");
memcpy(data, im.data, nr*nc*sizeof(int));
return *this;
}
const IntegerArray3 &
IntegerArray3::operator=(const IntegerArray3 &ia3)
{
if (n1 != ia3.n1 || n2 != ia3.n2 || n3 != ia3.n3)
throw DynareException(__FILE__, __LINE__,
"Arrays have different dimensions in IntegerArray3::operator=");
memcpy(data, ia3.data, n1*n2*n3*sizeof(int));
return *this;
}
PlannerBuilder::PlannerBuilder(DynareModel &m, const Tvarset &yyset,
const Teqset &ffset)
: yset(), fset(ffset), model(m),
tb(model.t_plobjective), tbeta(model.t_pldiscount),
maxlead(model.atoms.get_maxlead()),
minlag(model.atoms.get_minlag()),
diff_b(yyset.size(), 1-minlag),
diff_f(yyset.size(), fset.size(), 1+maxlead-minlag),
static_atoms(),
static_tree(),
diff_b_static(yyset.size(), 1-minlag),
diff_f_static(yyset.size(), fset.size(), 1+maxlead-minlag)
{
info.num_new_terms -= model.getParser().getTree().get_num_op();
fill_yset(m.atoms.get_name_storage(), yyset);
add_derivatives_of_b();
add_derivatives_of_f();
shift_derivatives_of_b();
shift_derivatives_of_f();
beta_multiply_b();
beta_multiply_f();
make_static_version();
lagrange_mult_f();
form_equations();
info.num_new_terms += model.getParser().getTree().get_num_op();
}
PlannerBuilder::PlannerBuilder(const PlannerBuilder &pb, ogdyn::DynareModel &m)
: yset(), fset(pb.fset), model(m),
tb(pb.tb), tbeta(pb.tbeta),
maxlead(pb.maxlead), minlag(pb.minlag),
diff_b(pb.diff_b), diff_f(pb.diff_f),
static_atoms(pb.static_atoms),
static_tree(pb.static_tree),
diff_b_static(pb.diff_b_static),
diff_f_static(pb.diff_f_static),
aux_map(), static_aux_map()
{
fill_yset(m.atoms.get_name_storage(), pb.yset);
fill_aux_map(m.atoms.get_name_storage(), pb.aux_map, pb.static_aux_map);
}
void
PlannerBuilder::add_derivatives_of_b()
{
int yi = 0;
for (Tvarset::const_iterator yname = yset.begin();
yname != yset.end(); ++yname, yi++)
for (int ll = minlag; ll <= 0; ll++)
{
int yt = model.atoms.index(*yname, ll);
if (yt != -1)
diff_b(yi, ll-minlag) = model.eqs.add_derivative(tb, yt);
else
diff_b(yi, ll-minlag) = ogp::OperationTree::zero;
}
}
void
PlannerBuilder::add_derivatives_of_f()
{
int yi = 0;
for (Tvarset::const_iterator yname = yset.begin();
yname != yset.end(); ++yname, yi++)
for (unsigned int fi = 0; fi < fset.size(); fi++)
for (int ll = minlag; ll <= maxlead; ll++)
{
int yt = model.atoms.index(*yname, ll);
if (yt != -1)
diff_f(yi, fi, ll-minlag)
= model.eqs.add_derivative(model.eqs.formula(fset[fi]), yt);
else
diff_f(yi, fi, ll-minlag) = ogp::OperationTree::zero;
}
}
void
PlannerBuilder::shift_derivatives_of_b()
{
map<int, int> subst;
for (int yi = 0; yi < diff_b.nrows(); yi++)
for (int ll = minlag; ll < 0; ll++)
if (diff_b(yi, ll-minlag) != ogp::OperationTree::zero)
{
model.variable_shift_map(model.eqs.nulary_of_term(diff_b(yi, ll-minlag)),
-ll, subst);
diff_b(yi, ll-minlag) = model.eqs.add_substitution(diff_b(yi, ll-minlag), subst);
}
}
void
PlannerBuilder::shift_derivatives_of_f()
{
map<int, int> subst;
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
{
// first do it leads which are put under expectation before t: no problem
for (int ll = 0; ll <= maxlead; ll++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero)
{
model.variable_shift_map(model.eqs.nulary_of_term(diff_f(yi, fi, ll-minlag)),
-ll, subst);
diff_f(yi, fi, ll-minlag)
= model.eqs.add_substitution(diff_f(yi, fi, ll-minlag), subst);
}
// now do it for lags, these are put as leads under
// expectations after time t, so we have to introduce
// auxiliary variables at time t, and make leads of them here
for (int ll = minlag; ll < 0; ll++)
{
int ft = diff_f(yi, fi, ll-minlag);
if (ft != ogp::OperationTree::zero)
{
// if the ft term has a lead, than we need to
// introduce an auxiliary variable z_t, define it
// as E_t[ft] and put z_{t-ll} to the
// equation. Otherwise, we just put leaded ft to
// the equation directly.
int ft_maxlead, ft_minlag;
model.termspan(ft, ft_maxlead, ft_minlag);
if (ft_maxlead > 0)
{
// make an auxiliary variable
char name[100];
sprintf(name, "AUX_%d_%d_%d", yi, fset[fi], -ll);
model.atoms.register_uniq_endo(name);
info.num_aux_variables++;
int taux = model.eqs.add_nulary(name);
sprintf(name, "AUX_%d_%d_%d(%d)", yi, fset[fi], -ll, -ll);
int taux_leaded = model.eqs.add_nulary(name);
// put aux_leaded to the equation
diff_f(yi, fi, ll-minlag) = taux_leaded;
// save auxiliary variable and the term
aux_map.insert(Tsubstmap::value_type(model.atoms.name(taux), ft));
}
else
{
// no auxiliary variable is needed and the
// term ft can be leaded in place
model.variable_shift_map(model.eqs.nulary_of_term(ft), -ll, subst);
diff_f(yi, fi, ll-minlag)
= model.eqs.add_substitution(ft, subst);
}
}
}
}
}
void
PlannerBuilder::beta_multiply_b()
{
int beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll >= minlag; ll--,
beta_pow = model.eqs.add_binary(ogp::TIMES, beta_pow, tbeta))
for (int yi = 0; yi < diff_b.nrows(); yi++)
if (diff_b(yi, ll-minlag) != ogp::OperationTree::zero)
diff_b(yi, ll-minlag)
= model.eqs.add_binary(ogp::TIMES, beta_pow, diff_b(yi, ll-minlag));
}
void
PlannerBuilder::beta_multiply_f()
{
int beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll <= maxlead; ll++,
beta_pow = model.eqs.add_binary(ogp::DIVIDE, beta_pow, tbeta))
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero)
diff_f(yi, fi, ll-minlag)
= model.eqs.add_binary(ogp::TIMES, beta_pow, diff_f(yi, fi, ll-minlag));
beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll >= minlag; ll--,
beta_pow = model.eqs.add_binary(ogp::TIMES, beta_pow, tbeta))
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero)
diff_f(yi, fi, ll-minlag)
= model.eqs.add_binary(ogp::TIMES, beta_pow, diff_f(yi, fi, ll-minlag));
}
void
PlannerBuilder::make_static_version()
{
// map holding substitutions from dynamic to static
ogp::StaticFineAtoms::Tintintmap tmap;
// fill static atoms with outer ordering
static_atoms.import_atoms(model.atoms, static_tree, tmap);
// go through diff_b and fill diff_b_static
for (int ll = minlag; ll <= 0; ll++)
for (int yi = 0; yi < diff_b.nrows(); yi++)
diff_b_static(yi, ll-minlag)
= static_tree.add_substitution(diff_b(yi, ll-minlag),
tmap, model.eqs.getTree());
// go through diff_f and fill diff_f_static
for (int ll = minlag; ll <= maxlead; ll++)
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
diff_f_static(yi, fi, ll-minlag)
= static_tree.add_substitution(diff_f(yi, fi, ll-minlag),
tmap, model.eqs.getTree());
// go through aux_map and fill static_aux_map
for (Tsubstmap::const_iterator it = aux_map.begin();
it != aux_map.end(); ++it)
{
int tstatic = static_tree.add_substitution((*it).second, tmap, model.eqs.getTree());
const char *name = static_atoms.get_name_storage().query((*it).first);
static_aux_map.insert(Tsubstmap::value_type(name, tstatic));
}
}
void
PlannerBuilder::lagrange_mult_f()
{
// register multipliers
char mult_name[100];
for (int fi = 0; fi < diff_f.dim2(); fi++)
{
sprintf(mult_name, "MULT%d", fset[fi]);
model.atoms.register_uniq_endo(mult_name);
info.num_lagrange_mults++;
}
// multiply with the multipliers
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
for (int ll = minlag; ll <= maxlead; ll++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero)
{
sprintf(mult_name, "MULT%d(%d)", fset[fi], -ll);
int tm = model.eqs.add_nulary(mult_name);
diff_f(yi, fi, ll-minlag)
= model.eqs.add_binary(ogp::TIMES, tm, diff_f(yi, fi, ll-minlag));
}
}
void
PlannerBuilder::form_equations()
{
// add planner's FOCs
for (int yi = 0; yi < diff_f.dim1(); yi++)
{
int eq = ogp::OperationTree::zero;
for (int ll = minlag; ll <= 0; ll++)
eq = model.eqs.add_binary(ogp::PLUS, eq, diff_b(yi, ll-minlag));
for (int fi = 0; fi < diff_f.dim2(); fi++)
for (int ll = minlag; ll <= maxlead; ll++)
eq = model.eqs.add_binary(ogp::PLUS, eq, diff_f(yi, fi, ll-minlag));
model.eqs.add_formula(eq);
}
// add equations for auxiliary variables
for (Tsubstmap::const_iterator it = aux_map.begin();
it != aux_map.end(); ++it)
{
int t = model.atoms.index((*it).first, 0);
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, t, (*it).second));
}
}
void
PlannerBuilder::fill_yset(const ogp::NameStorage &ns,
const PlannerBuilder::Tvarset &yyset)
{
for (Tvarset::const_iterator it = yyset.begin(); it != yyset.end(); ++it)
yset.insert(ns.query(*it));
}
void
PlannerBuilder::fill_aux_map(const ogp::NameStorage &ns, const Tsubstmap &aaux_map,
const Tsubstmap &astatic_aux_map)
{
// fill aux_map
for (Tsubstmap::const_iterator it = aaux_map.begin();
it != aaux_map.end(); ++it)
aux_map.insert(Tsubstmap::value_type(ns.query((*it).first), (*it).second));
// fill static_aux_map
for (Tsubstmap::const_iterator it = astatic_aux_map.begin();
it != astatic_aux_map.end(); ++it)
static_aux_map.insert(Tsubstmap::value_type(static_atoms.get_name_storage().query((*it).first),
(*it).second));
}
MultInitSS::MultInitSS(const PlannerBuilder &pb, const Vector &pvals, Vector &yy)
: builder(pb), b(builder.diff_b_static.nrows()),
F(builder.diff_f_static.dim1(), builder.diff_f_static.dim2())
{
b.zeros();
F.zeros();
// first evaluate substitutions (auxiliary variables) from the builder
ogdyn::DynareStaticSteadySubstitutions dss(builder.model.atoms, builder.static_atoms,
builder.static_tree,
builder.static_aux_map, pvals, yy);
// gather all the terms from builder.diff_b_static and
// builder.diff_f_static to the vector, the ordering is important,
// since the index of this vector will have to be decoded to the
// position in b and F.
vector<int> terms;
for (int yi = 0; yi < builder.diff_b_static.nrows(); yi++)
for (int l = 0; l < builder.diff_b_static.ncols(); l++)
terms.push_back(builder.diff_b_static(yi, l));
for (int yi = 0; yi < builder.diff_f_static.dim1(); yi++)
for (int fi = 0; fi < builder.diff_f_static.dim2(); fi++)
for (int l = 0; l < builder.diff_f_static.dim3(); l++)
terms.push_back(builder.diff_f_static(yi, fi, l));
// evaluate the terms, it will call a series of load(i,res), which
// sum the results through lags/leads to b and F
DynareStaticSteadyAtomValues dssav(builder.model.atoms, builder.static_atoms, pvals, yy);
ogp::FormulaCustomEvaluator fe(builder.static_tree, terms);
fe.eval(dssav, *this);
// solve overdetermined system b+F*lambda=0 using SVD decomposition
SVDDecomp decomp(F);
Vector lambda(builder.diff_f_static.dim2());
decomp.solve(b, lambda);
lambda.mult(-1);
// take values of lambda and put it to yy
for (int fi = 0; fi < builder.diff_f_static.dim2(); fi++)
{
char mult_name[100];
sprintf(mult_name, "MULT%d", builder.fset[fi]);
int iouter = builder.model.atoms.name2outer_endo(mult_name);
int iy = builder.model.atoms.outer2y_endo()[iouter];
if (!std::isfinite(yy[iy]))
yy[iy] = lambda[fi];
// go through all substitutions of the multiplier and set them
// as well
if (builder.model.atom_substs)
{
const ogp::AtomSubstitutions::Toldnamemap &old2new
= builder.model.atom_substs->get_old2new();
const ogp::AtomSubstitutions::Toldnamemap::const_iterator it
= old2new.find(mult_name);
if (it != old2new.end())
{
const ogp::AtomSubstitutions::Tshiftnameset &sset = (*it).second;
for (ogp::AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin();
itt != sset.end(); ++itt)
{
const char *newname = (*itt).first;
int iouter = builder.model.atoms.name2outer_endo(newname);
int iy = builder.model.atoms.outer2y_endo()[iouter];
if (!std::isfinite(yy[iy]))
yy[iy] = lambda[fi];
}
}
}
}
}
void
MultInitSS::load(int i, double res)
{
// we can afford it, since the evaluator sets res to exact zero if
// the term is zero
if (res == 0)
return;
// decode i and add to either b or F
if (i < builder.diff_b_static.nrows()*builder.diff_b_static.ncols())
{
// add to b
b[i / builder.diff_b_static.ncols()] += res;
}
else
{
// add to F
i -= builder.diff_b_static.nrows()*builder.diff_b_static.ncols();
int yifi = i / builder.diff_f_static.dim3();
int yi = yifi / builder.diff_f_static.dim2();
int fi = yifi % builder.diff_f_static.dim2();
F.get(yi, fi) += res;
}
}

View File

@ -1,385 +0,0 @@
// Copyright (C) 2006, Ondra Kamenik
// $Id$
#include "planner_builder.h"
#include "dynare_exception.h"
#include <cmath>
using namespace ogdyn;
const IntegerMatrix& IntegerMatrix::operator=(const IntegerMatrix& im)
{
if (nr != im.nr || nc != im.nc)
throw DynareException(__FILE__,__LINE__,
"Matrices have different dimensions in IntegerMatrix::operator=");
memcpy(data, im.data, nr*nc*sizeof(int));
return *this;
}
const IntegerArray3& IntegerArray3::operator=(const IntegerArray3& ia3)
{
if (n1 != ia3.n1 || n2 != ia3.n2 || n3 != ia3.n3)
throw DynareException(__FILE__,__LINE__,
"Arrays have different dimensions in IntegerArray3::operator=");
memcpy(data, ia3.data, n1*n2*n3*sizeof(int));
return *this;
}
PlannerBuilder::PlannerBuilder(DynareModel& m, const Tvarset& yyset,
const Teqset& ffset)
: yset(), fset(ffset), model(m),
tb(model.t_plobjective), tbeta(model.t_pldiscount),
maxlead(model.atoms.get_maxlead()),
minlag(model.atoms.get_minlag()),
diff_b(yyset.size(), 1-minlag),
diff_f(yyset.size(), fset.size(), 1+maxlead-minlag),
static_atoms(),
static_tree(),
diff_b_static(yyset.size(), 1-minlag),
diff_f_static(yyset.size(), fset.size(), 1+maxlead-minlag)
{
info.num_new_terms -= model.getParser().getTree().get_num_op();
fill_yset(m.atoms.get_name_storage(), yyset);
add_derivatives_of_b();
add_derivatives_of_f();
shift_derivatives_of_b();
shift_derivatives_of_f();
beta_multiply_b();
beta_multiply_f();
make_static_version();
lagrange_mult_f();
form_equations();
info.num_new_terms += model.getParser().getTree().get_num_op();
}
PlannerBuilder::PlannerBuilder(const PlannerBuilder& pb, ogdyn::DynareModel& m)
: yset(), fset(pb.fset), model(m),
tb(pb.tb), tbeta(pb.tbeta),
maxlead(pb.maxlead), minlag(pb.minlag),
diff_b(pb.diff_b), diff_f(pb.diff_f),
static_atoms(pb.static_atoms),
static_tree(pb.static_tree),
diff_b_static(pb.diff_b_static),
diff_f_static(pb.diff_f_static),
aux_map(), static_aux_map()
{
fill_yset(m.atoms.get_name_storage(), pb.yset);
fill_aux_map(m.atoms.get_name_storage(), pb.aux_map, pb.static_aux_map);
}
void PlannerBuilder::add_derivatives_of_b()
{
int yi = 0;
for (Tvarset::const_iterator yname = yset.begin();
yname != yset.end(); ++yname, yi++)
for (int ll = minlag; ll <= 0; ll++) {
int yt = model.atoms.index(*yname, ll);
if (yt != -1)
diff_b(yi, ll-minlag) = model.eqs.add_derivative(tb, yt);
else
diff_b(yi, ll-minlag) = ogp::OperationTree::zero;
}
}
void PlannerBuilder::add_derivatives_of_f()
{
int yi = 0;
for (Tvarset::const_iterator yname = yset.begin();
yname != yset.end(); ++yname, yi++)
for (unsigned int fi = 0; fi < fset.size(); fi++)
for (int ll = minlag; ll <= maxlead; ll++) {
int yt = model.atoms.index(*yname, ll);
if (yt != -1)
diff_f(yi, fi, ll-minlag) =
model.eqs.add_derivative(model.eqs.formula(fset[fi]), yt);
else
diff_f(yi, fi, ll-minlag) = ogp::OperationTree::zero;
}
}
void PlannerBuilder::shift_derivatives_of_b()
{
map<int,int> subst;
for (int yi = 0; yi < diff_b.nrows(); yi++)
for (int ll = minlag; ll < 0; ll++)
if (diff_b(yi, ll-minlag) != ogp::OperationTree::zero) {
model.variable_shift_map(model.eqs.nulary_of_term(diff_b(yi, ll-minlag)),
-ll, subst);
diff_b(yi, ll-minlag) = model.eqs.add_substitution(diff_b(yi, ll-minlag), subst);
}
}
void PlannerBuilder::shift_derivatives_of_f()
{
map<int,int> subst;
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++) {
// first do it leads which are put under expectation before t: no problem
for (int ll = 0; ll <= maxlead; ll++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero) {
model.variable_shift_map(model.eqs.nulary_of_term(diff_f(yi, fi, ll-minlag)),
-ll, subst);
diff_f(yi, fi, ll-minlag) =
model.eqs.add_substitution(diff_f(yi, fi, ll-minlag), subst);
}
// now do it for lags, these are put as leads under
// expectations after time t, so we have to introduce
// auxiliary variables at time t, and make leads of them here
for (int ll = minlag; ll < 0; ll++) {
int ft = diff_f(yi, fi, ll-minlag);
if (ft != ogp::OperationTree::zero) {
// if the ft term has a lead, than we need to
// introduce an auxiliary variable z_t, define it
// as E_t[ft] and put z_{t-ll} to the
// equation. Otherwise, we just put leaded ft to
// the equation directly.
int ft_maxlead, ft_minlag;
model.termspan(ft, ft_maxlead, ft_minlag);
if (ft_maxlead > 0) {
// make an auxiliary variable
char name[100];
sprintf(name, "AUX_%d_%d_%d", yi, fset[fi], -ll);
model.atoms.register_uniq_endo(name);
info.num_aux_variables++;
int taux = model.eqs.add_nulary(name);
sprintf(name, "AUX_%d_%d_%d(%d)", yi, fset[fi], -ll, -ll);
int taux_leaded = model.eqs.add_nulary(name);
// put aux_leaded to the equation
diff_f(yi, fi, ll-minlag) = taux_leaded;
// save auxiliary variable and the term
aux_map.insert(Tsubstmap::value_type(model.atoms.name(taux), ft));
} else {
// no auxiliary variable is needed and the
// term ft can be leaded in place
model.variable_shift_map(model.eqs.nulary_of_term(ft), -ll, subst);
diff_f(yi, fi, ll-minlag) =
model.eqs.add_substitution(ft, subst);
}
}
}
}
}
void PlannerBuilder::beta_multiply_b()
{
int beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll >= minlag; ll--,
beta_pow = model.eqs.add_binary(ogp::TIMES, beta_pow, tbeta))
for (int yi = 0; yi < diff_b.nrows(); yi++)
if (diff_b(yi, ll-minlag) != ogp::OperationTree::zero)
diff_b(yi, ll-minlag) =
model.eqs.add_binary(ogp::TIMES, beta_pow, diff_b(yi, ll-minlag));
}
void PlannerBuilder::beta_multiply_f()
{
int beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll <= maxlead; ll++,
beta_pow = model.eqs.add_binary(ogp::DIVIDE, beta_pow, tbeta))
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero)
diff_f(yi, fi, ll-minlag) =
model.eqs.add_binary(ogp::TIMES, beta_pow, diff_f(yi, fi, ll-minlag));
beta_pow = ogp::OperationTree::one;
for (int ll = 0; ll >= minlag; ll--,
beta_pow = model.eqs.add_binary(ogp::TIMES, beta_pow, tbeta))
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero)
diff_f(yi, fi, ll-minlag) =
model.eqs.add_binary(ogp::TIMES, beta_pow, diff_f(yi, fi, ll-minlag));
}
void PlannerBuilder::make_static_version()
{
// map holding substitutions from dynamic to static
ogp::StaticFineAtoms::Tintintmap tmap;
// fill static atoms with outer ordering
static_atoms.import_atoms(model.atoms, static_tree, tmap);
// go through diff_b and fill diff_b_static
for (int ll = minlag; ll <= 0; ll++)
for (int yi = 0; yi < diff_b.nrows(); yi++)
diff_b_static(yi, ll-minlag) =
static_tree.add_substitution(diff_b(yi, ll-minlag),
tmap, model.eqs.getTree());
// go through diff_f and fill diff_f_static
for (int ll = minlag; ll <= maxlead; ll++)
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
diff_f_static(yi, fi, ll-minlag) =
static_tree.add_substitution(diff_f(yi, fi, ll-minlag),
tmap, model.eqs.getTree());
// go through aux_map and fill static_aux_map
for (Tsubstmap::const_iterator it = aux_map.begin();
it != aux_map.end(); ++it) {
int tstatic = static_tree.add_substitution((*it).second, tmap, model.eqs.getTree());
const char* name = static_atoms.get_name_storage().query((*it).first);
static_aux_map.insert(Tsubstmap::value_type(name, tstatic));
}
}
void PlannerBuilder::lagrange_mult_f()
{
// register multipliers
char mult_name[100];
for (int fi = 0; fi < diff_f.dim2(); fi++) {
sprintf(mult_name, "MULT%d", fset[fi]);
model.atoms.register_uniq_endo(mult_name);
info.num_lagrange_mults++;
}
// multiply with the multipliers
for (int yi = 0; yi < diff_f.dim1(); yi++)
for (int fi = 0; fi < diff_f.dim2(); fi++)
for (int ll = minlag; ll <= maxlead; ll++)
if (diff_f(yi, fi, ll-minlag) != ogp::OperationTree::zero) {
sprintf(mult_name, "MULT%d(%d)", fset[fi], -ll);
int tm = model.eqs.add_nulary(mult_name);
diff_f(yi, fi, ll-minlag) =
model.eqs.add_binary(ogp::TIMES, tm, diff_f(yi, fi, ll-minlag));
}
}
void PlannerBuilder::form_equations()
{
// add planner's FOCs
for (int yi = 0; yi < diff_f.dim1(); yi++) {
int eq = ogp::OperationTree::zero;
for (int ll = minlag; ll <= 0; ll++)
eq = model.eqs.add_binary(ogp::PLUS, eq, diff_b(yi, ll-minlag));
for (int fi = 0; fi < diff_f.dim2(); fi++)
for (int ll = minlag; ll <= maxlead; ll++)
eq = model.eqs.add_binary(ogp::PLUS, eq, diff_f(yi, fi, ll-minlag));
model.eqs.add_formula(eq);
}
// add equations for auxiliary variables
for (Tsubstmap::const_iterator it = aux_map.begin();
it != aux_map.end(); ++it) {
int t = model.atoms.index((*it).first, 0);
model.eqs.add_formula(model.eqs.add_binary(ogp::MINUS, t, (*it).second));
}
}
void PlannerBuilder::fill_yset(const ogp::NameStorage& ns,
const PlannerBuilder::Tvarset& yyset)
{
for (Tvarset::const_iterator it = yyset.begin(); it != yyset.end(); ++it)
yset.insert(ns.query(*it));
}
void PlannerBuilder::fill_aux_map(const ogp::NameStorage& ns, const Tsubstmap& aaux_map,
const Tsubstmap& astatic_aux_map)
{
// fill aux_map
for (Tsubstmap::const_iterator it = aaux_map.begin();
it != aaux_map.end(); ++it)
aux_map.insert(Tsubstmap::value_type(ns.query((*it).first), (*it).second));
// fill static_aux_map
for (Tsubstmap::const_iterator it = astatic_aux_map.begin();
it != astatic_aux_map.end(); ++it)
static_aux_map.insert(Tsubstmap::value_type(static_atoms.get_name_storage().query((*it).first),
(*it).second));
}
MultInitSS::MultInitSS(const PlannerBuilder& pb, const Vector& pvals, Vector& yy)
: builder(pb), b(builder.diff_b_static.nrows()),
F(builder.diff_f_static.dim1(), builder.diff_f_static.dim2())
{
b.zeros();
F.zeros();
// first evaluate substitutions (auxiliary variables) from the builder
ogdyn::DynareStaticSteadySubstitutions dss(builder.model.atoms, builder.static_atoms,
builder.static_tree,
builder.static_aux_map, pvals, yy);
// gather all the terms from builder.diff_b_static and
// builder.diff_f_static to the vector, the ordering is important,
// since the index of this vector will have to be decoded to the
// position in b and F.
vector<int> terms;
for (int yi = 0; yi < builder.diff_b_static.nrows(); yi++)
for (int l = 0; l < builder.diff_b_static.ncols(); l++)
terms.push_back(builder.diff_b_static(yi, l));
for (int yi = 0; yi < builder.diff_f_static.dim1(); yi++)
for (int fi = 0; fi < builder.diff_f_static.dim2(); fi++)
for (int l = 0; l < builder.diff_f_static.dim3(); l++)
terms.push_back(builder.diff_f_static(yi, fi, l));
// evaluate the terms, it will call a series of load(i,res), which
// sum the results through lags/leads to b and F
DynareStaticSteadyAtomValues dssav(builder.model.atoms, builder.static_atoms, pvals, yy);
ogp::FormulaCustomEvaluator fe(builder.static_tree, terms);
fe.eval(dssav, *this);
// solve overdetermined system b+F*lambda=0 using SVD decomposition
SVDDecomp decomp(F);
Vector lambda(builder.diff_f_static.dim2());
decomp.solve(b, lambda);
lambda.mult(-1);
// take values of lambda and put it to yy
for (int fi = 0; fi < builder.diff_f_static.dim2(); fi++) {
char mult_name[100];
sprintf(mult_name, "MULT%d", builder.fset[fi]);
int iouter = builder.model.atoms.name2outer_endo(mult_name);
int iy = builder.model.atoms.outer2y_endo()[iouter];
if (! std::isfinite(yy[iy]))
yy[iy] = lambda[fi];
// go through all substitutions of the multiplier and set them
// as well
if (builder.model.atom_substs) {
const ogp::AtomSubstitutions::Toldnamemap& old2new =
builder.model.atom_substs->get_old2new();
const ogp::AtomSubstitutions::Toldnamemap::const_iterator it =
old2new.find(mult_name);
if (it != old2new.end()) {
const ogp::AtomSubstitutions::Tshiftnameset& sset = (*it).second;
for (ogp::AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin();
itt != sset.end(); ++itt) {
const char* newname = (*itt).first;
int iouter = builder.model.atoms.name2outer_endo(newname);
int iy = builder.model.atoms.outer2y_endo()[iouter];
if (! std::isfinite(yy[iy]))
yy[iy] = lambda[fi];
}
}
}
}
}
void MultInitSS::load(int i, double res)
{
// we can afford it, since the evaluator sets res to exact zero if
// the term is zero
if (res == 0)
return;
// decode i and add to either b or F
if (i < builder.diff_b_static.nrows()*builder.diff_b_static.ncols()) {
// add to b
b[i / builder.diff_b_static.ncols()] += res;
} else {
// add to F
i -= builder.diff_b_static.nrows()*builder.diff_b_static.ncols();
int yifi = i / builder.diff_f_static.dim3();
int yi = yifi / builder.diff_f_static.dim2();
int fi = yifi % builder.diff_f_static.dim2();
F.get(yi, fi) += res;
}
}

View File

@ -3,7 +3,7 @@
#ifndef PLANNER_BUILDER_H
#define PLANNER_BUILDER_H
#include "dynare_model.h"
#include "dynare_model.hh"
namespace ogdyn
{

View File

@ -0,0 +1,355 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/BlockDiagonal.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */
/* Tag $Name: $ */
#include "BlockDiagonal.hh"
#include <cstdio>
#include <cstring>
BlockDiagonal::BlockDiagonal(const double *d, int d_size)
: QuasiTriangular(d, d_size),
row_len(new int[d_size]), col_len(new int[d_size])
{
for (int i = 0; i < d_size; i++)
{
row_len[i] = d_size;
col_len[i] = 0;
}
}
BlockDiagonal::BlockDiagonal(const QuasiTriangular &t)
: QuasiTriangular(t),
row_len(new int[t.numRows()]), col_len(new int[t.numRows()])
{
for (int i = 0; i < t.numRows(); i++)
{
row_len[i] = t.numRows();
col_len[i] = 0;
}
}
BlockDiagonal::BlockDiagonal(int p, const BlockDiagonal &b)
: QuasiTriangular(p, b),
row_len(new int[b.numRows()]), col_len(new int[b.numRows()])
{
memcpy(row_len, b.row_len, b.numRows()*sizeof(int));
memcpy(col_len, b.col_len, b.numRows()*sizeof(int));
}
BlockDiagonal::BlockDiagonal(const BlockDiagonal &b)
: QuasiTriangular(b),
row_len(new int[b.numRows()]), col_len(new int[b.numRows()])
{
memcpy(row_len, b.row_len, b.numRows()*sizeof(int));
memcpy(col_len, b.col_len, b.numRows()*sizeof(int));
}
/* put zeroes to right upper submatrix whose first column is defined
* by 'edge' */
void
BlockDiagonal::setZerosToRU(diag_iter edge)
{
int iedge = (*edge).getIndex();
for (int i = 0; i < iedge; i++)
for (int j = iedge; j < numCols(); j++)
get(i, j) = 0.0;
}
/* Updates row_len and col_len so that there are zeroes in upper right part, this
* |T1 0 |
* |0 T2|. The first column of T2 is given by diagonal iterator 'edge'.
* Note the semantics of row_len and col_len. row_len[i] is distance
* of the right-most non-zero element of i-th row from the left, and
* col_len[j] is distance of top-most non-zero element of j-th column
* to the top. (First element has distance 1).
*/
void
BlockDiagonal::setZeroBlockEdge(diag_iter edge)
{
setZerosToRU(edge);
int iedge = (*edge).getIndex();
for (diag_iter run = diag_begin(); run != edge; ++run)
{
int ind = (*run).getIndex();
if (row_len[ind] > iedge)
{
row_len[ind] = iedge;
if (!(*run).isReal())
row_len[ind+1] = iedge;
}
}
for (diag_iter run = edge; run != diag_end(); ++run)
{
int ind = (*run).getIndex();
if (col_len[ind] < iedge)
{
col_len[ind] = iedge;
if (!(*run).isReal())
col_len[ind+1] = iedge;
}
}
}
BlockDiagonal::const_col_iter
BlockDiagonal::col_begin(const DiagonalBlock &b) const
{
int jbar = b.getIndex();
int d_size = diagonal.getSize();
return const_col_iter(&getData()[jbar*d_size + col_len[jbar]], d_size,
b.isReal(), col_len[jbar]);
}
BlockDiagonal::col_iter
BlockDiagonal::col_begin(const DiagonalBlock &b)
{
int jbar = b.getIndex();
int d_size = diagonal.getSize();
return col_iter(&getData()[jbar*d_size + col_len[jbar]], d_size,
b.isReal(), col_len[jbar]);
}
BlockDiagonal::const_row_iter
BlockDiagonal::row_end(const DiagonalBlock &b) const
{
int jbar = b.getIndex();
int d_size = diagonal.getSize();
return const_row_iter(&getData()[d_size*row_len[jbar]+jbar], d_size,
b.isReal(), row_len[jbar]);
}
BlockDiagonal::row_iter
BlockDiagonal::row_end(const DiagonalBlock &b)
{
int jbar = b.getIndex();
int d_size = diagonal.getSize();
return row_iter(&getData()[d_size*row_len[jbar]+jbar], d_size,
b.isReal(), row_len[jbar]);
}
int
BlockDiagonal::getNumZeros() const
{
int sum = 0;
for (int i = 0; i < diagonal.getSize(); i++)
{
sum += diagonal.getSize() - row_len[i];
}
return sum;
}
QuasiTriangular::const_diag_iter
BlockDiagonal::findBlockStart(const_diag_iter from) const
{
if (from != diag_end())
{
++from;
while (from != diag_end()
&& col_len[(*from).getIndex()] != (*from).getIndex())
++from;
}
return from;
}
int
BlockDiagonal::getLargestBlock() const
{
int largest = 0;
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end())
{
int si = (*start).getIndex();
int ei = diagonal.getSize();
if (end != diag_end())
ei = (*end).getIndex();
if (largest < ei-si)
largest = ei-si;
start = end;
end = findBlockStart(start);
}
return largest;
}
void
BlockDiagonal::savePartOfX(int si, int ei, const KronVector &x, Vector &work)
{
for (int i = si; i < ei; i++)
{
ConstKronVector xi(x, i);
Vector target(work, (i-si)*xi.length(), xi.length());
target = xi;
}
}
void
BlockDiagonal::multKronBlock(const_diag_iter start, const_diag_iter end,
KronVector &x, Vector &work) const
{
int si = (*start).getIndex();
int ei = diagonal.getSize();
if (end != diag_end())
ei = (*end).getIndex();
savePartOfX(si, ei, x, work);
for (const_diag_iter di = start; di != end; ++di)
{
int jbar = (*di).getIndex();
if ((*di).isReal())
{
KronVector xi(x, jbar);
xi.zeros();
Vector wi(work, (jbar-si)*xi.length(), xi.length());
xi.add(*((*di).getAlpha()), wi);
for (const_row_iter ri = row_begin(*di); ri != row_end(*di); ++ri)
{
int col = ri.getCol();
Vector wj(work, (col-si)*xi.length(), xi.length());
xi.add(*ri, wj);
}
}
else
{
KronVector xi(x, jbar);
KronVector xii(x, jbar+1);
xi.zeros();
xii.zeros();
Vector wi(work, (jbar-si)*xi.length(), xi.length());
Vector wii(work, (jbar+1-si)*xi.length(), xi.length());
xi.add(*((*di).getAlpha()), wi);
xi.add((*di).getBeta1(), wii);
xii.add((*di).getBeta2(), wi);
xii.add(*((*di).getAlpha()), wii);
for (const_row_iter ri = row_begin(*di); ri != row_end(*di); ++ri)
{
int col = ri.getCol();
Vector wj(work, (col-si)*xi.length(), xi.length());
xi.add(ri.a(), wj);
xii.add(ri.b(), wj);
}
}
}
}
void
BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end,
KronVector &x, Vector &work) const
{
int si = (*start).getIndex();
int ei = diagonal.getSize();
if (end != diag_end())
ei = (*end).getIndex();
savePartOfX(si, ei, x, work);
for (const_diag_iter di = start; di != end; ++di)
{
int jbar = (*di).getIndex();
if ((*di).isReal())
{
KronVector xi(x, jbar);
xi.zeros();
Vector wi(work, (jbar-si)*xi.length(), xi.length());
xi.add(*((*di).getAlpha()), wi);
for (const_col_iter ci = col_begin(*di); ci != col_end(*di); ++ci)
{
int row = ci.getRow();
Vector wj(work, (row-si)*xi.length(), xi.length());
xi.add(*ci, wj);
}
}
else
{
KronVector xi(x, jbar);
KronVector xii(x, jbar+1);
xi.zeros();
xii.zeros();
Vector wi(work, (jbar-si)*xi.length(), xi.length());
Vector wii(work, (jbar+1-si)*xi.length(), xi.length());
xi.add(*((*di).getAlpha()), wi);
xi.add((*di).getBeta2(), wii);
xii.add((*di).getBeta1(), wi);
xii.add(*((*di).getAlpha()), wii);
for (const_col_iter ci = col_begin(*di); ci != col_end(*di); ++ci)
{
int row = ci.getRow();
Vector wj(work, (row-si)*xi.length(), xi.length());
xi.add(ci.a(), wj);
xii.add(ci.b(), wj);
}
}
}
}
void
BlockDiagonal::multKron(KronVector &x) const
{
int largest = getLargestBlock();
Vector work(largest *x.getN()*power(x.getM(), x.getDepth()-1));
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end())
{
multKronBlock(start, end, x, work);
start = end;
end = findBlockStart(start);
}
}
void
BlockDiagonal::multKronTrans(KronVector &x) const
{
int largest = getLargestBlock();
Vector work(largest *x.getN()*power(x.getM(), x.getDepth()-1));
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end())
{
multKronBlockTrans(start, end, x, work);
start = end;
end = findBlockStart(start);
}
}
void
BlockDiagonal::printInfo() const
{
printf("Block sizes:");
int num_blocks = 0;
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end())
{
int si = (*start).getIndex();
int ei = diagonal.getSize();
if (end != diag_end())
ei = (*end).getIndex();
printf(" %d", ei-si);
num_blocks++;
start = end;
end = findBlockStart(start);
}
printf("\nNum blocks: %d\n", num_blocks);
printf("There are %d zeros out of %d\n",
getNumZeros(), getNumOffdiagonal());
}
int
BlockDiagonal::getNumBlocks() const
{
int num_blocks = 0;
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end())
{
num_blocks++;
start = end;
end = findBlockStart(start);
}
return num_blocks;
}
// Local Variables:
// mode:C++
// End:

View File

@ -1,321 +0,0 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/BlockDiagonal.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */
/* Tag $Name: $ */
#include "BlockDiagonal.h"
#include <cstdio>
#include <cstring>
BlockDiagonal::BlockDiagonal(const double* d, int d_size)
: QuasiTriangular(d, d_size),
row_len(new int[d_size]), col_len(new int[d_size])
{
for (int i = 0; i < d_size; i++) {
row_len[i] = d_size;
col_len[i] = 0;
}
}
BlockDiagonal::BlockDiagonal(const QuasiTriangular& t)
: QuasiTriangular(t),
row_len(new int[t.numRows()]), col_len(new int[t.numRows()])
{
for (int i = 0; i < t.numRows(); i++) {
row_len[i] = t.numRows();
col_len[i] = 0;
}
}
BlockDiagonal::BlockDiagonal(int p, const BlockDiagonal& b)
: QuasiTriangular(p, b),
row_len(new int[b.numRows()]), col_len(new int[b.numRows()])
{
memcpy(row_len, b.row_len, b.numRows()*sizeof(int));
memcpy(col_len, b.col_len, b.numRows()*sizeof(int));
}
BlockDiagonal::BlockDiagonal(const BlockDiagonal& b)
: QuasiTriangular(b),
row_len(new int[b.numRows()]), col_len(new int[b.numRows()])
{
memcpy(row_len, b.row_len, b.numRows()*sizeof(int));
memcpy(col_len, b.col_len, b.numRows()*sizeof(int));
}
/* put zeroes to right upper submatrix whose first column is defined
* by 'edge' */
void BlockDiagonal::setZerosToRU(diag_iter edge)
{
int iedge = (*edge).getIndex();
for (int i = 0; i < iedge; i++)
for (int j = iedge; j < numCols(); j++)
get(i,j) = 0.0;
}
/* Updates row_len and col_len so that there are zeroes in upper right part, this
* |T1 0 |
* |0 T2|. The first column of T2 is given by diagonal iterator 'edge'.
* Note the semantics of row_len and col_len. row_len[i] is distance
* of the right-most non-zero element of i-th row from the left, and
* col_len[j] is distance of top-most non-zero element of j-th column
* to the top. (First element has distance 1).
*/
void BlockDiagonal::setZeroBlockEdge(diag_iter edge)
{
setZerosToRU(edge);
int iedge = (*edge).getIndex();
for (diag_iter run = diag_begin(); run != edge; ++run) {
int ind = (*run).getIndex();
if (row_len[ind] > iedge) {
row_len[ind] = iedge;
if (!(*run).isReal())
row_len[ind+1] = iedge;
}
}
for (diag_iter run = edge; run != diag_end(); ++run) {
int ind = (*run).getIndex();
if (col_len[ind] < iedge) {
col_len[ind] = iedge;
if (!(*run).isReal())
col_len[ind+1] = iedge;
}
}
}
BlockDiagonal::const_col_iter
BlockDiagonal::col_begin(const DiagonalBlock& b) const
{
int jbar = b.getIndex();
int d_size = diagonal.getSize();
return const_col_iter(&getData()[jbar*d_size + col_len[jbar]], d_size,
b.isReal(), col_len[jbar]);
}
BlockDiagonal::col_iter
BlockDiagonal::col_begin(const DiagonalBlock& b)
{
int jbar = b.getIndex();
int d_size = diagonal.getSize();
return col_iter(&getData()[jbar*d_size + col_len[jbar]], d_size,
b.isReal(), col_len[jbar]);
}
BlockDiagonal::const_row_iter
BlockDiagonal::row_end(const DiagonalBlock& b) const
{
int jbar = b.getIndex();
int d_size = diagonal.getSize();
return const_row_iter(&getData()[d_size*row_len[jbar]+jbar], d_size,
b.isReal(), row_len[jbar]);
}
BlockDiagonal::row_iter
BlockDiagonal::row_end(const DiagonalBlock& b)
{
int jbar = b.getIndex();
int d_size = diagonal.getSize();
return row_iter(&getData()[d_size*row_len[jbar]+jbar], d_size,
b.isReal(), row_len[jbar]);
}
int BlockDiagonal::getNumZeros() const
{
int sum = 0;
for (int i = 0; i < diagonal.getSize(); i++) {
sum += diagonal.getSize() - row_len[i];
}
return sum;
}
QuasiTriangular::const_diag_iter
BlockDiagonal::findBlockStart(const_diag_iter from) const
{
if (from != diag_end()) {
++from;
while (from != diag_end() &&
col_len[(*from).getIndex()] != (*from).getIndex())
++from;
}
return from;
}
int BlockDiagonal::getLargestBlock() const
{
int largest = 0;
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end()) {
int si = (*start).getIndex();
int ei = diagonal.getSize();
if (end != diag_end())
ei = (*end).getIndex();
if (largest < ei-si)
largest = ei-si;
start = end;
end = findBlockStart(start);
}
return largest;
}
void BlockDiagonal::savePartOfX(int si, int ei, const KronVector& x, Vector& work)
{
for (int i = si; i < ei; i++) {
ConstKronVector xi(x, i);
Vector target(work, (i-si)*xi.length(), xi.length());
target = xi;
}
}
void BlockDiagonal::multKronBlock(const_diag_iter start, const_diag_iter end,
KronVector& x, Vector& work) const
{
int si = (*start).getIndex();
int ei = diagonal.getSize();
if (end != diag_end())
ei = (*end).getIndex();
savePartOfX(si, ei, x, work);
for (const_diag_iter di = start; di != end; ++di) {
int jbar = (*di).getIndex();
if ((*di).isReal()) {
KronVector xi(x, jbar);
xi.zeros();
Vector wi(work, (jbar-si)*xi.length(), xi.length());
xi.add(*((*di).getAlpha()), wi);
for (const_row_iter ri = row_begin(*di); ri != row_end(*di); ++ri) {
int col = ri.getCol();
Vector wj(work, (col-si)*xi.length(), xi.length());
xi.add(*ri, wj);
}
} else {
KronVector xi(x, jbar);
KronVector xii(x, jbar+1);
xi.zeros();
xii.zeros();
Vector wi(work, (jbar-si)*xi.length(), xi.length());
Vector wii(work, (jbar+1-si)*xi.length(), xi.length());
xi.add(*((*di).getAlpha()), wi);
xi.add((*di).getBeta1(), wii);
xii.add((*di).getBeta2(), wi);
xii.add(*((*di).getAlpha()), wii);
for (const_row_iter ri = row_begin(*di); ri != row_end(*di); ++ri) {
int col = ri.getCol();
Vector wj(work, (col-si)*xi.length(), xi.length());
xi.add(ri.a(), wj);
xii.add(ri.b(), wj);
}
}
}
}
void BlockDiagonal::multKronBlockTrans(const_diag_iter start, const_diag_iter end,
KronVector& x, Vector& work) const
{
int si = (*start).getIndex();
int ei = diagonal.getSize();
if (end != diag_end())
ei = (*end).getIndex();
savePartOfX(si, ei, x, work);
for (const_diag_iter di = start; di != end; ++di) {
int jbar = (*di).getIndex();
if ((*di).isReal()) {
KronVector xi(x, jbar);
xi.zeros();
Vector wi(work, (jbar-si)*xi.length(), xi.length());
xi.add(*((*di).getAlpha()), wi);
for (const_col_iter ci = col_begin(*di); ci != col_end(*di); ++ci) {
int row = ci.getRow();
Vector wj(work, (row-si)*xi.length(), xi.length());
xi.add(*ci, wj);
}
} else {
KronVector xi(x, jbar);
KronVector xii(x, jbar+1);
xi.zeros();
xii.zeros();
Vector wi(work, (jbar-si)*xi.length(), xi.length());
Vector wii(work, (jbar+1-si)*xi.length(), xi.length());
xi.add(*((*di).getAlpha()), wi);
xi.add((*di).getBeta2(), wii);
xii.add((*di).getBeta1(), wi);
xii.add(*((*di).getAlpha()), wii);
for (const_col_iter ci = col_begin(*di); ci != col_end(*di); ++ci) {
int row = ci.getRow();
Vector wj(work, (row-si)*xi.length(), xi.length());
xi.add(ci.a(), wj);
xii.add(ci.b(), wj);
}
}
}
}
void BlockDiagonal::multKron(KronVector& x) const
{
int largest = getLargestBlock();
Vector work(largest*x.getN()*power(x.getM(),x.getDepth()-1));
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end()) {
multKronBlock(start, end, x, work);
start = end;
end = findBlockStart(start);
}
}
void BlockDiagonal::multKronTrans(KronVector& x) const
{
int largest = getLargestBlock();
Vector work(largest*x.getN()*power(x.getM(),x.getDepth()-1));
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end()) {
multKronBlockTrans(start, end, x, work);
start = end;
end = findBlockStart(start);
}
}
void BlockDiagonal::printInfo() const
{
printf("Block sizes:");
int num_blocks = 0;
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end()) {
int si = (*start).getIndex();
int ei = diagonal.getSize();
if (end != diag_end())
ei = (*end).getIndex();
printf(" %d", ei-si);
num_blocks++;
start = end;
end = findBlockStart(start);
}
printf("\nNum blocks: %d\n", num_blocks);
printf("There are %d zeros out of %d\n",
getNumZeros(), getNumOffdiagonal());
}
int BlockDiagonal::getNumBlocks() const
{
int num_blocks = 0;
const_diag_iter start = diag_begin();
const_diag_iter end = findBlockStart(start);
while (start != diag_end()) {
num_blocks++;
start = end;
end = findBlockStart(start);
}
return num_blocks;
}
// Local Variables:
// mode:C++
// End:

View File

@ -5,7 +5,7 @@
#ifndef BLOCK_DIAGONAL_H
#define BLOCK_DIAGONAL_H
#include "QuasiTriangular.h"
#include "QuasiTriangular.hh"
class BlockDiagonal : public QuasiTriangular
{

View File

@ -0,0 +1,613 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralMatrix.cpp,v 1.4 2004/11/24 20:41:59 kamenik Exp $ */
/* Tag $Name: $ */
#include "SylvException.hh"
#include "GeneralMatrix.hh"
#include <dynblas.h>
#include <dynlapack.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <limits>
int GeneralMatrix::md_length = 32;
GeneralMatrix::GeneralMatrix(const GeneralMatrix &m)
: data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows)
{
copy(m);
}
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &m)
: data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows)
{
copy(m);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix &m, const char *dummy)
: data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols)
{
for (int i = 0; i < m.rows; i++)
for (int j = 0; j < m.cols; j++)
get(j, i) = m.get(i, j);
}
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix &m, const char *dummy)
: data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols)
{
for (int i = 0; i < m.rows; i++)
for (int j = 0; j < m.cols; j++)
get(j, i) = m.get(i, j);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols)
: data(nrows*ncols), rows(nrows), cols(ncols), ld(nrows)
{
copy(m, i, j);
}
GeneralMatrix::GeneralMatrix(GeneralMatrix &m, int i, int j, int nrows, int ncols)
: data(m.base()+m.ld*j+i, m.ld*(ncols-1)+nrows), rows(nrows), cols(ncols), ld(m.ld)
{
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const GeneralMatrix &b)
: data(a.rows*b.cols), rows(a.rows), cols(b.cols), ld(a.rows)
{
gemm("N", a, "N", b, 1.0, 0.0);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const GeneralMatrix &b, const char *dum)
: data(a.rows*b.rows), rows(a.rows), cols(b.rows), ld(a.rows)
{
gemm("N", a, "T", b, 1.0, 0.0);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const char *dum, const GeneralMatrix &b)
: data(a.cols*b.cols), rows(a.cols), cols(b.cols), ld(a.cols)
{
gemm("T", a, "N", b, 1.0, 0.0);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix &a, const char *dum1,
const GeneralMatrix &b, const char *dum2)
: data(a.cols*b.rows), rows(a.cols), cols(b.rows), ld(a.cols)
{
gemm("T", a, "T", b, 1.0, 0.0);
}
GeneralMatrix::~GeneralMatrix()
{
}
void
GeneralMatrix::place(const ConstGeneralMatrix &m, int i, int j)
{
if (i + m.numRows() > numRows()
|| j + m.numCols() > numCols())
throw SYLV_MES_EXCEPTION("Bad submatrix placement, matrix dimensions exceeded.");
GeneralMatrix tmpsub(*this, i, j, m.numRows(), m.numCols());
tmpsub.copy(m);
}
void
GeneralMatrix::mult(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b)
{
gemm("N", a, "N", b, 1.0, 0.0);
}
void
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b,
double mult)
{
gemm("N", a, "N", b, mult, 1.0);
}
void
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const ConstGeneralMatrix &b,
const char *dum, double mult)
{
gemm("N", a, "T", b, mult, 1.0);
}
void
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const char *dum,
const ConstGeneralMatrix &b, double mult)
{
gemm("T", a, "N", b, mult, 1.0);
}
void
GeneralMatrix::multAndAdd(const ConstGeneralMatrix &a, const char *dum1,
const ConstGeneralMatrix &b, const char *dum2, double mult)
{
gemm("T", a, "T", b, mult, 1.0);
}
void
GeneralMatrix::addOuter(const ConstVector &a, double mult)
{
if (numRows() != numCols())
throw SYLV_MES_EXCEPTION("Matrix is not square in GeneralMatrix::addOuter.");
if (numRows() != a.length())
throw SYLV_MES_EXCEPTION("Wrong length of a vector in GeneralMatrix::addOuter.");
// since BLAS dsyr (symmetric rank 1 update) assumes symmetricity, we do this manually
for (int i = 0; i < numRows(); i++)
for (int j = i; j < numRows(); j++)
{
double s = mult*a[i]*a[j];
get(i, j) = get(i, j) + s;
if (i != j)
get(j, i) = get(j, i) + s;
}
}
void
GeneralMatrix::multRight(const ConstGeneralMatrix &m)
{
gemm_partial_right("N", m, 1.0, 0.0);
}
void
GeneralMatrix::multLeft(const ConstGeneralMatrix &m)
{
gemm_partial_left("N", m, 1.0, 0.0);
}
void
GeneralMatrix::multRightTrans(const ConstGeneralMatrix &m)
{
gemm_partial_right("T", m, 1.0, 0.0);
}
void
GeneralMatrix::multLeftTrans(const ConstGeneralMatrix &m)
{
gemm_partial_left("T", m, 1.0, 0.0);
}
// here we must be careful for ld
void
GeneralMatrix::zeros()
{
if (ld == rows)
data.zeros();
else
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i, j) = 0;
}
}
void
GeneralMatrix::unit()
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if (i == j)
get(i, j) = 1.0;
else
get(i, j) = 0.0;
}
void
GeneralMatrix::nans()
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i, j) = std::numeric_limits<double>::quiet_NaN();
}
void
GeneralMatrix::infs()
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i, j) = std::numeric_limits<double>::infinity();
}
// here we must be careful for ld
void
GeneralMatrix::mult(double a)
{
if (ld == rows)
data.mult(a);
else
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i, j) *= a;
}
}
// here we must be careful for ld
void
GeneralMatrix::add(double a, const ConstGeneralMatrix &m)
{
if (m.numRows() != rows || m.numCols() != cols)
throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add.");
if (ld == rows && m.ld == m.rows)
data.add(a, m.data);
else
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i, j) += a*m.get(i, j);
}
}
void
GeneralMatrix::add(double a, const ConstGeneralMatrix &m, const char *dum)
{
if (m.numRows() != cols || m.numCols() != rows)
throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add.");
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i, j) += a*m.get(j, i);
}
void
GeneralMatrix::copy(const ConstGeneralMatrix &m, int ioff, int joff)
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i, j) = m.get(i+ioff, j+joff);
}
void
GeneralMatrix::gemm(const char *transa, const ConstGeneralMatrix &a,
const char *transb, const ConstGeneralMatrix &b,
double alpha, double beta)
{
int opa_rows = a.numRows();
int opa_cols = a.numCols();
if (!strcmp(transa, "T"))
{
opa_rows = a.numCols();
opa_cols = a.numRows();
}
int opb_rows = b.numRows();
int opb_cols = b.numCols();
if (!strcmp(transb, "T"))
{
opb_rows = b.numCols();
opb_cols = b.numRows();
}
if (opa_rows != numRows()
|| opb_cols != numCols()
|| opa_cols != opb_rows)
{
throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix multiplication.");
}
blas_int m = opa_rows;
blas_int n = opb_cols;
blas_int k = opa_cols;
blas_int lda = a.ld;
blas_int ldb = b.ld;
blas_int ldc = ld;
if (lda > 0 && ldb > 0 && ldc > 0)
{
dgemm(transa, transb, &m, &n, &k, &alpha, a.data.base(), &lda,
b.data.base(), &ldb, &beta, data.base(), &ldc);
}
else if (numRows()*numCols() > 0)
{
if (beta == 0.0)
zeros();
else
mult(beta);
}
}
void
GeneralMatrix::gemm_partial_left(const char *trans, const ConstGeneralMatrix &m,
double alpha, double beta)
{
int icol;
for (icol = 0; icol + md_length < cols; icol += md_length)
{
GeneralMatrix incopy((const GeneralMatrix &)*this, 0, icol, rows, md_length);
GeneralMatrix inplace((GeneralMatrix&)*this, 0, icol, rows, md_length);
inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta);
}
if (cols > icol)
{
GeneralMatrix incopy((const GeneralMatrix &)*this, 0, icol, rows, cols - icol);
GeneralMatrix inplace((GeneralMatrix&)*this, 0, icol, rows, cols - icol);
inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta);
}
}
void
GeneralMatrix::gemm_partial_right(const char *trans, const ConstGeneralMatrix &m,
double alpha, double beta)
{
int irow;
for (irow = 0; irow + md_length < rows; irow += md_length)
{
GeneralMatrix incopy((const GeneralMatrix &)*this, irow, 0, md_length, cols);
GeneralMatrix inplace((GeneralMatrix&)*this, irow, 0, md_length, cols);
inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta);
}
if (rows > irow)
{
GeneralMatrix incopy((const GeneralMatrix &)*this, irow, 0, rows - irow, cols);
GeneralMatrix inplace((GeneralMatrix&)*this, irow, 0, rows - irow, cols);
inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta);
}
}
ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix &m, int i, int j, int nrows, int ncols)
: data(m.getData(), j*m.getLD()+i, (ncols-1)*m.getLD()+nrows), rows(nrows), cols(ncols), ld(m.getLD())
{
// can check that the submatirx is fully in the matrix
}
ConstGeneralMatrix::ConstGeneralMatrix(const ConstGeneralMatrix &m, int i, int j, int nrows, int ncols)
: data(m.getData(), j*m.getLD()+i, (ncols-1)*m.getLD()+nrows), rows(nrows), cols(ncols), ld(m.getLD())
{
// can check that the submatirx is fully in the matrix
}
ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix &m)
: data(m.data), rows(m.rows), cols(m.cols), ld(m.ld)
{
}
double
ConstGeneralMatrix::getNormInf() const
{
double norm = 0.0;
for (int i = 0; i < numRows(); i++)
{
ConstVector rowi(data.base()+i, ld, cols);
double normi = rowi.getNorm1();
if (norm < normi)
norm = normi;
}
return norm;
}
double
ConstGeneralMatrix::getNorm1() const
{
double norm = 0.0;
for (int j = 0; j < numCols(); j++)
{
ConstVector colj(data.base()+ld *j, 1, rows);
double normj = colj.getNorm1();
if (norm < normj)
norm = normj;
}
return norm;
}
void
ConstGeneralMatrix::multVec(double a, Vector &x, double b, const ConstVector &d) const
{
if (x.length() != rows || cols != d.length())
{
throw SYLV_MES_EXCEPTION("Wrong dimensions for vector multiply.");
}
if (rows > 0)
{
blas_int mm = rows;
blas_int nn = cols;
double alpha = b;
blas_int lda = ld;
blas_int incx = d.skip();
double beta = a;
blas_int incy = x.skip();
dgemv("N", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx,
&beta, x.base(), &incy);
}
}
void
ConstGeneralMatrix::multVecTrans(double a, Vector &x, double b,
const ConstVector &d) const
{
if (x.length() != cols || rows != d.length())
{
throw SYLV_MES_EXCEPTION("Wrong dimensions for vector multiply.");
}
if (rows > 0)
{
blas_int mm = rows;
blas_int nn = cols;
double alpha = b;
blas_int lda = rows;
blas_int incx = d.skip();
double beta = a;
blas_int incy = x.skip();
dgemv("T", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx,
&beta, x.base(), &incy);
}
}
/* m = inv(this)*m */
void
ConstGeneralMatrix::multInvLeft(const char *trans, int mrows, int mcols, int mld, double *d) const
{
if (rows != cols)
{
throw SYLV_MES_EXCEPTION("The matrix is not square for inversion.");
}
if (cols != mrows)
{
throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix inverse mutliply.");
}
if (rows > 0)
{
GeneralMatrix inv(*this);
lapack_int *ipiv = new lapack_int[rows];
lapack_int info;
lapack_int rows2 = rows, mcols2 = mcols, mld2 = mld;
dgetrf(&rows2, &rows2, inv.getData().base(), &rows2, ipiv, &info);
dgetrs(trans, &rows2, &mcols2, inv.base(), &rows2, ipiv, d,
&mld2, &info);
delete [] ipiv;
}
}
/* m = inv(this)*m */
void
ConstGeneralMatrix::multInvLeft(GeneralMatrix &m) const
{
multInvLeft("N", m.numRows(), m.numCols(), m.getLD(), m.getData().base());
}
/* m = inv(this')*m */
void
ConstGeneralMatrix::multInvLeftTrans(GeneralMatrix &m) const
{
multInvLeft("T", m.numRows(), m.numCols(), m.getLD(), m.getData().base());
}
/* d = inv(this)*d */
void
ConstGeneralMatrix::multInvLeft(Vector &d) const
{
if (d.skip() != 1)
{
throw SYLV_MES_EXCEPTION("Skip!=1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)");
}
multInvLeft("N", d.length(), 1, d.length(), d.base());
}
/* d = inv(this')*d */
void
ConstGeneralMatrix::multInvLeftTrans(Vector &d) const
{
if (d.skip() != 1)
{
throw SYLV_MES_EXCEPTION("Skip!=1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)");
}
multInvLeft("T", d.length(), 1, d.length(), d.base());
}
bool
ConstGeneralMatrix::isFinite() const
{
for (int i = 0; i < numRows(); i++)
for (int j = 0; j < numCols(); j++)
if (!std::isfinite(get(i, j)))
return false;
return true;
}
bool
ConstGeneralMatrix::isZero() const
{
for (int i = 0; i < numRows(); i++)
for (int j = 0; j < numCols(); j++)
if (get(i, j) != 0.0)
return false;
return true;
}
void
ConstGeneralMatrix::print() const
{
printf("rows=%d, cols=%d\n", rows, cols);
for (int i = 0; i < rows; i++)
{
printf("row %d:\n", i);
for (int j = 0; j < cols; j++)
{
printf("%6.3g ", get(i, j));
}
printf("\n");
}
}
void
SVDDecomp::construct(const GeneralMatrix &A)
{
// quick exit if empty matrix
if (minmn == 0)
{
U.unit();
VT.unit();
conv = true;
return;
}
// make copy of the matrix
GeneralMatrix AA(A);
lapack_int m = AA.numRows();
lapack_int n = AA.numCols();
double *a = AA.base();
lapack_int lda = AA.getLD();
double *s = sigma.base();
double *u = U.base();
lapack_int ldu = U.getLD();
double *vt = VT.base();
lapack_int ldvt = VT.getLD();
double tmpwork;
lapack_int lwork = -1;
lapack_int info;
lapack_int *iwork = new lapack_int[8*minmn];
// query for optimal lwork
dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &tmpwork,
&lwork, iwork, &info);
lwork = (lapack_int) tmpwork;
Vector work(lwork);
// do the decomposition
dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work.base(),
&lwork, iwork, &info);
delete [] iwork;
if (info < 0)
throw SYLV_MES_EXCEPTION("Internal error in SVDDecomp constructor");
if (info == 0)
conv = true;
}
void
SVDDecomp::solve(const GeneralMatrix &B, GeneralMatrix &X) const
{
if (B.numRows() != U.numRows())
throw SYLV_MES_EXCEPTION("Incompatible number of rows ");
// reciprocal condition number for determination of zeros in the
// end of sigma
double rcond = 1e-13;
// solve U: B = U^T*B
GeneralMatrix UTB(U, "trans", B);
// determine nz=number of zeros in the end of sigma
int nz = 0;
while (nz < minmn && sigma[minmn-1-nz] < rcond*sigma[0])
nz++;
// take relevant B for sigma inversion
int m = U.numRows();
int n = VT.numCols();
GeneralMatrix Bprime(UTB, m-minmn, 0, minmn-nz, B.numCols());
// solve sigma
for (int i = 0; i < minmn-nz; i++)
Vector(i, Bprime).mult(1.0/sigma[i]);
// solve VT
X.zeros();
//- copy Bprime to right place of X
for (int i = 0; i < minmn-nz; i++)
Vector(n-minmn+i, X) = ConstVector(i, Bprime);
//- multiply with VT
X.multLeftTrans(VT);
}

View File

@ -1,556 +0,0 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralMatrix.cpp,v 1.4 2004/11/24 20:41:59 kamenik Exp $ */
/* Tag $Name: $ */
#include "SylvException.h"
#include "GeneralMatrix.h"
#include <dynblas.h>
#include <dynlapack.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <limits>
int GeneralMatrix::md_length = 32;
GeneralMatrix::GeneralMatrix(const GeneralMatrix& m)
: data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows)
{
copy(m);
}
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix& m)
: data(m.rows*m.cols), rows(m.rows), cols(m.cols), ld(m.rows)
{
copy(m);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix& m, const char* dummy)
: data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols)
{
for (int i = 0; i < m.rows; i++)
for (int j = 0; j < m.cols; j++)
get(j,i) = m.get(i,j);
}
GeneralMatrix::GeneralMatrix(const ConstGeneralMatrix& m, const char* dummy)
: data(m.rows*m.cols), rows(m.cols), cols(m.rows), ld(m.cols)
{
for (int i = 0; i < m.rows; i++)
for (int j = 0; j < m.cols; j++)
get(j,i) = m.get(i,j);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols)
: data(nrows*ncols), rows(nrows), cols(ncols), ld(nrows)
{
copy(m, i, j);
}
GeneralMatrix::GeneralMatrix(GeneralMatrix& m, int i, int j, int nrows, int ncols)
: data(m.base()+m.ld*j+i, m.ld*(ncols-1)+nrows), rows(nrows), cols(ncols), ld(m.ld)
{}
GeneralMatrix::GeneralMatrix(const GeneralMatrix& a, const GeneralMatrix& b)
: data(a.rows*b.cols), rows(a.rows), cols(b.cols), ld(a.rows)
{
gemm("N", a, "N", b, 1.0, 0.0);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix& a, const GeneralMatrix& b, const char* dum)
: data(a.rows*b.rows), rows(a.rows), cols(b.rows), ld(a.rows)
{
gemm("N", a, "T", b, 1.0, 0.0);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix& a, const char* dum, const GeneralMatrix& b)
: data(a.cols*b.cols), rows(a.cols), cols(b.cols), ld(a.cols)
{
gemm("T", a, "N", b, 1.0, 0.0);
}
GeneralMatrix::GeneralMatrix(const GeneralMatrix& a, const char* dum1,
const GeneralMatrix& b, const char* dum2)
: data(a.cols*b.rows), rows(a.cols), cols(b.rows), ld(a.cols)
{
gemm("T", a, "T", b, 1.0, 0.0);
}
GeneralMatrix::~GeneralMatrix()
{
}
void GeneralMatrix::place(const ConstGeneralMatrix& m, int i, int j)
{
if (i + m.numRows() > numRows() ||
j + m.numCols() > numCols())
throw SYLV_MES_EXCEPTION("Bad submatrix placement, matrix dimensions exceeded.");
GeneralMatrix tmpsub(*this, i, j, m.numRows(), m.numCols());
tmpsub.copy(m);
}
void GeneralMatrix::mult(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b)
{
gemm("N", a, "N", b, 1.0, 0.0);
}
void GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b,
double mult)
{
gemm("N", a, "N", b, mult, 1.0);
}
void GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const ConstGeneralMatrix& b,
const char* dum, double mult)
{
gemm("N", a, "T", b, mult, 1.0);
}
void GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const char* dum,
const ConstGeneralMatrix& b, double mult)
{
gemm("T", a, "N", b, mult, 1.0);
}
void GeneralMatrix::multAndAdd(const ConstGeneralMatrix& a, const char* dum1,
const ConstGeneralMatrix& b, const char* dum2, double mult)
{
gemm("T", a, "T", b, mult, 1.0);
}
void GeneralMatrix::addOuter(const ConstVector& a, double mult)
{
if (numRows() != numCols())
throw SYLV_MES_EXCEPTION("Matrix is not square in GeneralMatrix::addOuter.");
if (numRows() != a.length())
throw SYLV_MES_EXCEPTION("Wrong length of a vector in GeneralMatrix::addOuter.");
// since BLAS dsyr (symmetric rank 1 update) assumes symmetricity, we do this manually
for (int i = 0; i < numRows(); i++)
for (int j = i; j < numRows(); j++) {
double s = mult*a[i]*a[j];
get(i,j) = get(i,j) + s;
if (i != j)
get(j,i) = get(j,i) + s;
}
}
void GeneralMatrix::multRight(const ConstGeneralMatrix& m)
{
gemm_partial_right("N", m, 1.0, 0.0);
}
void GeneralMatrix::multLeft(const ConstGeneralMatrix& m)
{
gemm_partial_left("N", m, 1.0, 0.0);
}
void GeneralMatrix::multRightTrans(const ConstGeneralMatrix& m)
{
gemm_partial_right("T", m, 1.0, 0.0);
}
void GeneralMatrix::multLeftTrans(const ConstGeneralMatrix& m)
{
gemm_partial_left("T", m, 1.0, 0.0);
}
// here we must be careful for ld
void GeneralMatrix::zeros()
{
if (ld == rows)
data.zeros();
else {
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i,j) = 0;
}
}
void GeneralMatrix::unit()
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if (i == j)
get(i,j) = 1.0;
else
get(i,j) = 0.0;
}
void GeneralMatrix::nans()
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i,j) = std::numeric_limits<double>::quiet_NaN();
}
void GeneralMatrix::infs()
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i,j) = std::numeric_limits<double>::infinity();
}
// here we must be careful for ld
void GeneralMatrix::mult(double a)
{
if (ld == rows)
data.mult(a);
else {
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i,j) *= a;
}
}
// here we must be careful for ld
void GeneralMatrix::add(double a, const ConstGeneralMatrix& m)
{
if (m.numRows() != rows || m.numCols() != cols)
throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add.");
if (ld == rows && m.ld == m.rows)
data.add(a, m.data);
else {
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i,j) += a*m.get(i,j);
}
}
void GeneralMatrix::add(double a, const ConstGeneralMatrix& m, const char* dum)
{
if (m.numRows() != cols || m.numCols() != rows)
throw SYLV_MES_EXCEPTION("Matrix has different size in GeneralMatrix::add.");
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i,j) += a*m.get(j,i);
}
void GeneralMatrix::copy(const ConstGeneralMatrix& m, int ioff, int joff)
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
get(i,j) = m.get(i+ioff,j+joff);
}
void GeneralMatrix::gemm(const char* transa, const ConstGeneralMatrix& a,
const char* transb, const ConstGeneralMatrix& b,
double alpha, double beta)
{
int opa_rows = a.numRows();
int opa_cols = a.numCols();
if (!strcmp(transa, "T")) {
opa_rows = a.numCols();
opa_cols = a.numRows();
}
int opb_rows = b.numRows();
int opb_cols = b.numCols();
if (!strcmp(transb, "T")) {
opb_rows = b.numCols();
opb_cols = b.numRows();
}
if (opa_rows != numRows() ||
opb_cols != numCols() ||
opa_cols != opb_rows) {
throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix multiplication.");
}
blas_int m = opa_rows;
blas_int n = opb_cols;
blas_int k = opa_cols;
blas_int lda = a.ld;
blas_int ldb = b.ld;
blas_int ldc = ld;
if (lda > 0 && ldb > 0 && ldc > 0) {
dgemm(transa, transb, &m, &n, &k, &alpha, a.data.base(), &lda,
b.data.base(), &ldb, &beta, data.base(), &ldc);
} else if (numRows()*numCols() > 0) {
if (beta == 0.0)
zeros();
else
mult(beta);
}
}
void GeneralMatrix::gemm_partial_left(const char* trans, const ConstGeneralMatrix& m,
double alpha, double beta)
{
int icol;
for (icol = 0; icol + md_length < cols; icol += md_length) {
GeneralMatrix incopy((const GeneralMatrix&)*this, 0, icol, rows, md_length);
GeneralMatrix inplace((GeneralMatrix&)*this, 0, icol, rows, md_length);
inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta);
}
if (cols > icol) {
GeneralMatrix incopy((const GeneralMatrix&)*this, 0, icol, rows, cols - icol);
GeneralMatrix inplace((GeneralMatrix&)*this, 0, icol, rows, cols - icol);
inplace.gemm(trans, m, "N", ConstGeneralMatrix(incopy), alpha, beta);
}
}
void GeneralMatrix::gemm_partial_right(const char* trans, const ConstGeneralMatrix& m,
double alpha, double beta)
{
int irow;
for (irow = 0; irow + md_length < rows; irow += md_length) {
GeneralMatrix incopy((const GeneralMatrix&)*this, irow, 0, md_length, cols);
GeneralMatrix inplace((GeneralMatrix&)*this, irow, 0, md_length, cols);
inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta);
}
if (rows > irow) {
GeneralMatrix incopy((const GeneralMatrix&)*this, irow, 0, rows - irow, cols);
GeneralMatrix inplace((GeneralMatrix&)*this, irow, 0, rows - irow, cols);
inplace.gemm("N", ConstGeneralMatrix(incopy), trans, m, alpha, beta);
}
}
ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix& m, int i, int j, int nrows, int ncols)
: data(m.getData(), j*m.getLD()+i, (ncols-1)*m.getLD()+nrows), rows(nrows), cols(ncols), ld(m.getLD())
{
// can check that the submatirx is fully in the matrix
}
ConstGeneralMatrix::ConstGeneralMatrix(const ConstGeneralMatrix& m, int i, int j, int nrows, int ncols)
: data(m.getData(), j*m.getLD()+i, (ncols-1)*m.getLD()+nrows), rows(nrows), cols(ncols), ld(m.getLD())
{
// can check that the submatirx is fully in the matrix
}
ConstGeneralMatrix::ConstGeneralMatrix(const GeneralMatrix& m)
: data(m.data), rows(m.rows), cols(m.cols), ld(m.ld) {}
double ConstGeneralMatrix::getNormInf() const
{
double norm = 0.0;
for (int i = 0; i < numRows(); i++) {
ConstVector rowi(data.base()+i, ld, cols);
double normi = rowi.getNorm1();
if (norm < normi)
norm = normi;
}
return norm;
}
double ConstGeneralMatrix::getNorm1() const
{
double norm = 0.0;
for (int j = 0; j < numCols(); j++) {
ConstVector colj(data.base()+ld*j, 1, rows);
double normj = colj.getNorm1();
if (norm < normj)
norm = normj;
}
return norm;
}
void ConstGeneralMatrix::multVec(double a, Vector& x, double b, const ConstVector& d) const
{
if (x.length() != rows || cols != d.length()) {
throw SYLV_MES_EXCEPTION("Wrong dimensions for vector multiply.");
}
if (rows > 0) {
blas_int mm = rows;
blas_int nn = cols;
double alpha = b;
blas_int lda = ld;
blas_int incx = d.skip();
double beta = a;
blas_int incy = x.skip();
dgemv("N", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx,
&beta, x.base(), &incy);
}
}
void ConstGeneralMatrix::multVecTrans(double a, Vector& x, double b,
const ConstVector& d) const
{
if (x.length() != cols || rows != d.length()) {
throw SYLV_MES_EXCEPTION("Wrong dimensions for vector multiply.");
}
if (rows > 0) {
blas_int mm = rows;
blas_int nn = cols;
double alpha = b;
blas_int lda = rows;
blas_int incx = d.skip();
double beta = a;
blas_int incy = x.skip();
dgemv("T", &mm, &nn, &alpha, data.base(), &lda, d.base(), &incx,
&beta, x.base(), &incy);
}
}
/* m = inv(this)*m */
void ConstGeneralMatrix::multInvLeft(const char* trans, int mrows, int mcols, int mld, double* d) const
{
if (rows != cols) {
throw SYLV_MES_EXCEPTION("The matrix is not square for inversion.");
}
if (cols != mrows) {
throw SYLV_MES_EXCEPTION("Wrong dimensions for matrix inverse mutliply.");
}
if (rows > 0) {
GeneralMatrix inv(*this);
lapack_int* ipiv = new lapack_int[rows];
lapack_int info;
lapack_int rows2 = rows, mcols2 = mcols, mld2 = mld;
dgetrf(&rows2, &rows2, inv.getData().base(), &rows2, ipiv, &info);
dgetrs(trans, &rows2, &mcols2, inv.base(), &rows2, ipiv, d,
&mld2, &info);
delete [] ipiv;
}
}
/* m = inv(this)*m */
void ConstGeneralMatrix::multInvLeft(GeneralMatrix& m) const
{
multInvLeft("N", m.numRows(), m.numCols(), m.getLD(), m.getData().base());
}
/* m = inv(this')*m */
void ConstGeneralMatrix::multInvLeftTrans(GeneralMatrix& m) const
{
multInvLeft("T", m.numRows(), m.numCols(), m.getLD(), m.getData().base());
}
/* d = inv(this)*d */
void ConstGeneralMatrix::multInvLeft(Vector& d) const
{
if (d.skip() != 1) {
throw SYLV_MES_EXCEPTION("Skip!=1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)");
}
multInvLeft("N", d.length(), 1, d.length(), d.base());
}
/* d = inv(this')*d */
void ConstGeneralMatrix::multInvLeftTrans(Vector& d) const
{
if (d.skip() != 1) {
throw SYLV_MES_EXCEPTION("Skip!=1 not implemented in ConstGeneralMatrix::multInvLeft(Vector&)");
}
multInvLeft("T", d.length(), 1, d.length(), d.base());
}
bool ConstGeneralMatrix::isFinite() const
{
for (int i = 0; i < numRows(); i++)
for (int j = 0; j < numCols(); j++)
if (! std::isfinite(get(i,j)))
return false;
return true;
}
bool ConstGeneralMatrix::isZero() const
{
for (int i = 0; i < numRows(); i++)
for (int j = 0; j < numCols(); j++)
if (get(i,j) != 0.0)
return false;
return true;
}
void ConstGeneralMatrix::print() const
{
printf("rows=%d, cols=%d\n",rows, cols);
for (int i = 0; i < rows; i++) {
printf("row %d:\n",i);
for (int j = 0; j < cols; j++) {
printf("%6.3g ",get(i,j));
}
printf("\n");
}
}
void SVDDecomp::construct(const GeneralMatrix& A)
{
// quick exit if empty matrix
if (minmn == 0) {
U.unit();
VT.unit();
conv = true;
return;
}
// make copy of the matrix
GeneralMatrix AA(A);
lapack_int m = AA.numRows();
lapack_int n = AA.numCols();
double* a = AA.base();
lapack_int lda = AA.getLD();
double* s = sigma.base();
double* u = U.base();
lapack_int ldu = U.getLD();
double* vt = VT.base();
lapack_int ldvt = VT.getLD();
double tmpwork;
lapack_int lwork = -1;
lapack_int info;
lapack_int* iwork = new lapack_int[8*minmn];
// query for optimal lwork
dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, &tmpwork,
&lwork, iwork, &info);
lwork = (lapack_int)tmpwork;
Vector work(lwork);
// do the decomposition
dgesdd("A", &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work.base(),
&lwork, iwork, &info);
delete [] iwork;
if (info < 0)
throw SYLV_MES_EXCEPTION("Internal error in SVDDecomp constructor");
if (info == 0)
conv = true;
}
void SVDDecomp::solve(const GeneralMatrix& B, GeneralMatrix& X) const
{
if (B.numRows() != U.numRows())
throw SYLV_MES_EXCEPTION("Incompatible number of rows ");
// reciprocal condition number for determination of zeros in the
// end of sigma
double rcond = 1e-13;
// solve U: B = U^T*B
GeneralMatrix UTB(U, "trans", B);
// determine nz=number of zeros in the end of sigma
int nz = 0;
while (nz < minmn && sigma[minmn-1-nz] < rcond*sigma[0])
nz++;
// take relevant B for sigma inversion
int m = U.numRows();
int n = VT.numCols();
GeneralMatrix Bprime(UTB, m-minmn, 0, minmn-nz, B.numCols());
// solve sigma
for (int i = 0; i < minmn-nz; i++)
Vector(i, Bprime).mult(1.0/sigma[i]);
// solve VT
X.zeros();
//- copy Bprime to right place of X
for (int i = 0; i < minmn-nz; i++)
Vector(n-minmn+i, X) = ConstVector(i, Bprime);
//- multiply with VT
X.multLeftTrans(VT);
}

View File

@ -5,7 +5,7 @@
#ifndef GENERAL_MATRIX_H
#define GENERAL_MATRIX_H
#include "Vector.h"
#include "Vector.hh"
#include <algorithm>

View File

@ -0,0 +1,141 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralSylvester.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */
/* Tag $Name: $ */
#include "GeneralSylvester.hh"
#include "SchurDecomp.hh"
#include "SylvException.hh"
#include "TriangularSylvester.hh"
#include "IterativeSylvester.hh"
#include <ctime>
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, const double *dd,
const SylvParams &ps)
: pars(ps),
mem_driver(pars, 1, m, n, ord), order(ord), a(da, n),
b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)),
solved(false)
{
init();
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, double *dd,
const SylvParams &ps)
: pars(ps),
mem_driver(pars, 0, m, n, ord), order(ord), a(da, n),
b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)),
solved(false)
{
init();
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, const double *dd,
bool alloc_for_check)
: pars(alloc_for_check),
mem_driver(pars, 1, m, n, ord), order(ord), a(da, n),
b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)),
solved(false)
{
init();
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double *da, const double *db,
const double *dc, double *dd,
bool alloc_for_check)
: pars(alloc_for_check),
mem_driver(pars, 0, m, n, ord), order(ord), a(da, n),
b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)),
solved(false)
{
init();
}
void
GeneralSylvester::init()
{
GeneralMatrix ainvb(b);
double rcond1;
double rcondinf;
a.multInvLeft2(ainvb, d, rcond1, rcondinf);
pars.rcondA1 = rcond1;
pars.rcondAI = rcondinf;
bdecomp = new SchurDecompZero(ainvb);
cdecomp = new SimilarityDecomp(c.getData().base(), c.numRows(), *(pars.bs_norm));
cdecomp->check(pars, c);
cdecomp->infoToPars(pars);
if (*(pars.method) == SylvParams::recurse)
sylv = new TriangularSylvester(*bdecomp, *cdecomp);
else
sylv = new IterativeSylvester(*bdecomp, *cdecomp);
}
void
GeneralSylvester::solve()
{
if (solved)
throw SYLV_MES_EXCEPTION("Attempt to run solve() more than once.");
mem_driver.setStackMode(true);
clock_t start = clock();
// multiply d
d.multLeftITrans(bdecomp->getQ());
d.multRightKron(cdecomp->getQ(), order);
// convert to KronVector
KronVector dkron(d.getData(), getM(), getN(), order);
// solve
sylv->solve(pars, dkron);
// multiply d back
d.multLeftI(bdecomp->getQ());
d.multRightKron(cdecomp->getInvQ(), order);
clock_t end = clock();
pars.cpu_time = ((double) (end-start))/CLOCKS_PER_SEC;
mem_driver.setStackMode(false);
solved = true;
}
void
GeneralSylvester::check(const double *ds)
{
if (!solved)
throw SYLV_MES_EXCEPTION("Cannot run check on system, which is not solved yet.");
mem_driver.setStackMode(true);
// calculate xcheck = AX+BXC^i-D
SylvMatrix dcheck(d.numRows(), d.numCols());
dcheck.multLeft(b.numRows()-b.numCols(), b, d);
dcheck.multRightKron(c, order);
dcheck.multAndAdd(a, d);
ConstVector dv(ds, d.numRows()*d.numCols());
dcheck.getData().add(-1.0, dv);
// calculate relative norms
pars.mat_err1 = dcheck.getNorm1()/d.getNorm1();
pars.mat_errI = dcheck.getNormInf()/d.getNormInf();
pars.mat_errF = dcheck.getData().getNorm()/d.getData().getNorm();
pars.vec_err1 = dcheck.getData().getNorm1()/d.getData().getNorm1();
pars.vec_errI = dcheck.getData().getMax()/d.getData().getMax();
mem_driver.setStackMode(false);
}
GeneralSylvester::~GeneralSylvester()
{
delete bdecomp;
delete cdecomp;
delete sylv;
}
// Local Variables:
// mode:C++
// End:

View File

@ -1,138 +0,0 @@
/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/GeneralSylvester.cpp,v 1.1.1.1 2004/06/04 13:00:20 kamenik Exp $ */
/* Tag $Name: $ */
#include "GeneralSylvester.h"
#include "SchurDecomp.h"
#include "SylvException.h"
#include "TriangularSylvester.h"
#include "IterativeSylvester.h"
#include <ctime>
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double* da, const double* db,
const double* dc, const double* dd,
const SylvParams& ps)
: pars(ps),
mem_driver(pars, 1, m, n, ord), order(ord), a(da, n),
b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)),
solved(false)
{
init();
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double* da, const double* db,
const double* dc, double* dd,
const SylvParams& ps)
: pars(ps),
mem_driver(pars, 0, m, n, ord), order(ord), a(da, n),
b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)),
solved(false)
{
init();
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double* da, const double* db,
const double* dc, const double* dd,
bool alloc_for_check)
: pars(alloc_for_check),
mem_driver(pars, 1, m, n, ord), order(ord), a(da, n),
b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)),
solved(false)
{
init();
}
GeneralSylvester::GeneralSylvester(int ord, int n, int m, int zero_cols,
const double* da, const double* db,
const double* dc, double* dd,
bool alloc_for_check)
: pars(alloc_for_check),
mem_driver(pars, 0, m, n, ord), order(ord), a(da, n),
b(db, n, n-zero_cols), c(dc, m), d(dd, n, power(m, order)),
solved(false)
{
init();
}
void GeneralSylvester::init()
{
GeneralMatrix ainvb(b);
double rcond1;
double rcondinf;
a.multInvLeft2(ainvb, d, rcond1, rcondinf);
pars.rcondA1 = rcond1;
pars.rcondAI = rcondinf;
bdecomp = new SchurDecompZero(ainvb);
cdecomp = new SimilarityDecomp(c.getData().base(), c.numRows(), *(pars.bs_norm));
cdecomp->check(pars, c);
cdecomp->infoToPars(pars);
if (*(pars.method) == SylvParams::recurse)
sylv = new TriangularSylvester(*bdecomp, *cdecomp);
else
sylv = new IterativeSylvester(*bdecomp, *cdecomp);
}
void GeneralSylvester::solve()
{
if (solved)
throw SYLV_MES_EXCEPTION("Attempt to run solve() more than once.");
mem_driver.setStackMode(true);
clock_t start = clock();
// multiply d
d.multLeftITrans(bdecomp->getQ());
d.multRightKron(cdecomp->getQ(), order);
// convert to KronVector
KronVector dkron(d.getData(), getM(), getN(), order);
// solve
sylv->solve(pars, dkron);
// multiply d back
d.multLeftI(bdecomp->getQ());
d.multRightKron(cdecomp->getInvQ(), order);
clock_t end = clock();
pars.cpu_time = ((double)(end-start))/CLOCKS_PER_SEC;
mem_driver.setStackMode(false);
solved = true;
}
void GeneralSylvester::check(const double* ds)
{
if (!solved)
throw SYLV_MES_EXCEPTION("Cannot run check on system, which is not solved yet.");
mem_driver.setStackMode(true);
// calculate xcheck = AX+BXC^i-D
SylvMatrix dcheck(d.numRows(), d.numCols());
dcheck.multLeft(b.numRows()-b.numCols(), b, d);
dcheck.multRightKron(c, order);
dcheck.multAndAdd(a,d);
ConstVector dv(ds, d.numRows()*d.numCols());
dcheck.getData().add(-1.0, dv);
// calculate relative norms
pars.mat_err1 = dcheck.getNorm1()/d.getNorm1();
pars.mat_errI = dcheck.getNormInf()/d.getNormInf();
pars.mat_errF = dcheck.getData().getNorm()/d.getData().getNorm();
pars.vec_err1 = dcheck.getData().getNorm1()/d.getData().getNorm1();
pars.vec_errI = dcheck.getData().getMax()/d.getData().getMax();
mem_driver.setStackMode(false);
}
GeneralSylvester::~GeneralSylvester()
{
delete bdecomp;
delete cdecomp;
delete sylv;
}
// Local Variables:
// mode:C++
// End:

View File

@ -5,10 +5,10 @@
#ifndef GENERAL_SYLVESTER_H
#define GENERAL_SYLVESTER_H
#include "SylvMatrix.h"
#include "SylvMemory.h"
#include "SimilarityDecomp.h"
#include "SylvesterSolver.h"
#include "SylvMatrix.hh"
#include "SylvMemory.hh"
#include "SimilarityDecomp.hh"
#include "SylvesterSolver.hh"
class GeneralSylvester
{

Some files were not shown because too many files have changed in this diff Show More