Dynare++: finish to apply Dynare C++ coding style and extensions (.cc/.hh)
parent
b58e3d9f78
commit
188d6296d7
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
};
|
|
@ -28,7 +28,7 @@
|
|||
#include "int_sequence.hh"
|
||||
#include "quadrature.hh"
|
||||
|
||||
#include "Vector.h"
|
||||
#include "Vector.hh"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "decision_rule.hh"
|
||||
#include "dynamic_model.hh"
|
||||
|
||||
#include "SymSchurDecomp.h"
|
||||
#include "SymSchurDecomp.hh"
|
||||
|
||||
#include <dynlapack.h>
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright 2005, Ondra Kamenik
|
||||
|
||||
#include "SymSchurDecomp.h"
|
||||
#include "SymSchurDecomp.hh"
|
||||
|
||||
#include "global_check.hh"
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "journal.hh"
|
||||
|
||||
#include "kord_exception.hh"
|
||||
#include "GeneralSylvester.h"
|
||||
#include "GeneralSylvester.hh"
|
||||
|
||||
#include <dynlapack.h>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <cstdlib>
|
||||
#include "korder.hh"
|
||||
#include "SylvException.h"
|
||||
#include "SylvException.hh"
|
||||
|
||||
struct Rand
|
||||
{
|
||||
|
|
|
@ -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$@ $<
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%{
|
||||
#include "location.h"
|
||||
#include "location.hh"
|
||||
#include "assign_tab.hh"
|
||||
|
||||
extern YYLTYPE asgn_lloc;
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef OGP_ATOM_SUBSTITUTIONS_H
|
||||
#define OGP_ATOM_SUBSTITUTIONS_H
|
||||
|
||||
#include "fine_atoms.h"
|
||||
#include "fine_atoms.hh"
|
||||
|
||||
#include <string>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
%{
|
||||
// Copyright (C) 2007-2011, Ondra Kamenik
|
||||
|
||||
#include "location.h"
|
||||
#include "location.hh"
|
||||
#include "csv_tab.hh"
|
||||
|
||||
extern YYLTYPE csv_lloc;
|
|
@ -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*);
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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:
|
|
@ -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:
|
|
@ -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>
|
|
@ -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]);
|
||||
}
|
|
@ -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]);
|
||||
}
|
|
@ -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>
|
|
@ -1,5 +1,5 @@
|
|||
%{
|
||||
#include "location.h"
|
||||
#include "location.hh"
|
||||
#include "formula_tab.hh"
|
||||
|
||||
extern YYLTYPE fmla_lloc;
|
|
@ -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*);
|
|
@ -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:
|
|
@ -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:
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef OGP_FORMULA_PARSER_H
|
||||
#define OGP_FORMULA_PARSER_H
|
||||
|
||||
#include "tree.h"
|
||||
#include "tree.hh"
|
||||
|
||||
namespace ogp
|
||||
{
|
|
@ -1,7 +1,7 @@
|
|||
%{
|
||||
// Copyright (C) 2006-2011, Ondra Kamenik
|
||||
|
||||
#include "location.h"
|
||||
#include "location.hh"
|
||||
#include "matrix_tab.hh"
|
||||
|
||||
extern YYLTYPE matrix_lloc;
|
|
@ -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*);
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
%{
|
||||
#include "location.h"
|
||||
#include "location.hh"
|
||||
#include "namelist_tab.hh"
|
||||
|
||||
extern YYLTYPE namelist_lloc;
|
|
@ -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*);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef OGP_STATIC_ATOMS
|
||||
#define OGP_STATIC_ATOMS
|
||||
|
||||
#include "dynamic_atoms.h"
|
||||
#include "dynamic_atoms.hh"
|
||||
|
||||
namespace ogp
|
||||
{
|
|
@ -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));
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
File diff suppressed because it is too large
Load Diff
|
@ -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:
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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:
|
|
@ -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:
|
|
@ -1,5 +1,5 @@
|
|||
%{
|
||||
#include "parser/cc/location.h"
|
||||
#include "parser/cc/location.hh"
|
||||
#include "dynglob_tab.hh"
|
||||
|
||||
extern YYLTYPE dynglob_lloc;
|
|
@ -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>
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef FORW_SUBST_BUILDER_H
|
||||
#define FORW_SUBST_BUILDER_H
|
||||
|
||||
#include "dynare_model.h"
|
||||
#include "dynare_model.hh"
|
||||
|
||||
namespace ogdyn
|
||||
{
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef PLANNER_BUILDER_H
|
||||
#define PLANNER_BUILDER_H
|
||||
|
||||
#include "dynare_model.h"
|
||||
#include "dynare_model.hh"
|
||||
|
||||
namespace ogdyn
|
||||
{
|
|
@ -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:
|
|
@ -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:
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef BLOCK_DIAGONAL_H
|
||||
#define BLOCK_DIAGONAL_H
|
||||
|
||||
#include "QuasiTriangular.h"
|
||||
#include "QuasiTriangular.hh"
|
||||
|
||||
class BlockDiagonal : public QuasiTriangular
|
||||
{
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef GENERAL_MATRIX_H
|
||||
#define GENERAL_MATRIX_H
|
||||
|
||||
#include "Vector.h"
|
||||
#include "Vector.hh"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -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:
|
|
@ -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:
|
|
@ -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
Loading…
Reference in New Issue