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/
|
RINTERNALS=/usr/share/R/include/
|
||||||
|
|
||||||
sylvcppsource := $(wildcard ../../sylv/cc/*.cpp)
|
sylvcppsource := $(wildcard ../../sylv/cc/*.cc)
|
||||||
sylvhsource := $(wildcard ../../sylv/cc/*.h)
|
sylvhsource := $(wildcard ../../sylv/cc/*.hh)
|
||||||
sylvobjects := $(patsubst %.cpp, %.o, $(sylvcppsource))
|
sylvobjects := $(patsubst %.cc, %.o, $(sylvcppsource))
|
||||||
|
|
||||||
tlcwebsource := $(wildcard ../../tl/cc/*.cweb)
|
tlcppsource := $(wildcard ../../tl/cc/*.cc)
|
||||||
tlcppsource := $(patsubst %.cweb,%.cpp,$(tlcwebsource))
|
tlhsource := $(wildcard ../../tl/cc/*.hh)
|
||||||
tlhwebsource := $(wildcard ../../tl/cc/*.hweb)
|
|
||||||
tlhsource := $(patsubst %.hweb,%.h,$(tlhwebsource))
|
|
||||||
tlobjects := $(patsubst %.cweb,%.o,$(tlcwebsource))
|
|
||||||
|
|
||||||
kordcwebsource := $(wildcard ../../kord/*.cweb)
|
kordcppsource := $(wildcard ../../kord/*.cc)
|
||||||
kordcppsource := $(patsubst %.cweb,%.cpp,$(kordcwebsource))
|
kordhsource := $(wildcard ../../kord/*.hh)
|
||||||
kordhwebsource := $(wildcard ../../kord/*.hweb)
|
|
||||||
kordhsource := $(patsubst %.hweb,%.h,$(kordhwebsource))
|
|
||||||
kordobjects := $(patsubst %.cweb,%.o,$(kordcwebsource))
|
|
||||||
|
|
||||||
integcwebsource := $(wildcard ../../integ/cc/*.cweb)
|
integcppsource := $(wildcard ../../integ/cc/*.cc)
|
||||||
integcppsource := $(patsubst %.cweb,%.cpp,$(integcwebsource))
|
integhsource := $(wildcard ../../integ/cc/*.hh)
|
||||||
integhwebsource := $(wildcard ../../integ/cc/*.hweb)
|
|
||||||
integhsource := $(patsubst %.hweb,%.h,$(integhwebsource))
|
|
||||||
integobjects := $(patsubst %.cweb,%.o,$(integcwebsource))
|
|
||||||
|
|
||||||
parserhsource := $(wildcard ../../parser/cc/*.h)
|
parserhsource := $(wildcard ../../parser/cc/*.hh)
|
||||||
parsercppsource := $(wildcard ../parser/cc/*.cpp)
|
parsercppsource := $(wildcard ../parser/cc/*.cc)
|
||||||
|
|
||||||
utilshsource := $(wildcard ../../utils/cc/*.h)
|
utilshsource := $(wildcard ../../utils/cc/*.hh)
|
||||||
utilscppsource := $(wildcard ../utils/cc/*.cpp)
|
utilscppsource := $(wildcard ../utils/cc/*.cc)
|
||||||
|
|
||||||
srccpp := dynare3.cpp dynare_model.cpp planner_builder.cpp dynare_atoms.cpp dynare_params.cpp nlsolve.cpp
|
srccpp := dynare3.cc dynare_model.cc planner_builder.cc dynare_atoms.cc dynare_params.cc nlsolve.cc
|
||||||
objects := $(patsubst %.cpp,../../src/%.o,$(srccpp)) \
|
objects := $(patsubst %.cc,../../src/%.o,$(srccpp)) \
|
||||||
$(patsubst %.y,%_ll.o,$(wildcard ../../src/*.y)) \
|
$(patsubst %.yy,%_ll.o,$(wildcard ../../src/*.yy)) \
|
||||||
$(patsubst %.lex,%_tab.o,$(wildcard ../../src/*.lex))
|
$(patsubst %.ll,%_tab.o,$(wildcard ../../src/*.ll))
|
||||||
|
|
||||||
PKG_CPPFLAGS= -I../../tl/cc -I../../sylv/cc -I../../kord -I../../src -I../.. -I$(RINTERNALS)
|
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++
|
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
|
dynareR.so: dynareR.o
|
||||||
g++ -shared -o dynareR.so dynareR.o -L/usr/lib/R/lib -lR $(PKG_LIBS)
|
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) \
|
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
|
test: test.cc dynareR.cc
|
||||||
g++ -O0 -g -o test test.cpp -DDEBUG $(PKG_LIBS) $(PKG_CPPFLAGS)
|
g++ -O0 -g -o test test.cc -DDEBUG $(PKG_LIBS) $(PKG_CPPFLAGS)
|
||||||
|
|
||||||
test-debug:
|
test-debug:
|
||||||
valgrind --leak-check=yes ./test
|
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 "int_sequence.hh"
|
||||||
#include "quadrature.hh"
|
#include "quadrature.hh"
|
||||||
|
|
||||||
#include "Vector.h"
|
#include "Vector.hh"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
#ifndef VECTOR_FUNCTION_H
|
#ifndef VECTOR_FUNCTION_H
|
||||||
#define VECTOR_FUNCTION_H
|
#define VECTOR_FUNCTION_H
|
||||||
|
|
||||||
#include "Vector.h"
|
#include "Vector.hh"
|
||||||
#include "GeneralMatrix.h"
|
#include "GeneralMatrix.hh"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// Copyright (C) 2008-2011, Ondra Kamenik
|
// Copyright (C) 2008-2011, Ondra Kamenik
|
||||||
|
|
||||||
#include "parser/cc/matrix_parser.h"
|
#include "parser/cc/matrix_parser.hh"
|
||||||
#include "utils/cc/memory_file.h"
|
#include "utils/cc/memory_file.hh"
|
||||||
#include "utils/cc/exception.h"
|
#include "utils/cc/exception.hh"
|
||||||
#include "sylv/cc/GeneralMatrix.h"
|
#include "sylv/cc/GeneralMatrix.hh"
|
||||||
#include "sylv/cc/Vector.h"
|
#include "sylv/cc/Vector.hh"
|
||||||
#include "sylv/cc/SymSchurDecomp.h"
|
#include "sylv/cc/SymSchurDecomp.hh"
|
||||||
#include "sylv/cc/SylvException.h"
|
#include "sylv/cc/SylvException.hh"
|
||||||
#include "integ/cc/quadrature.hh"
|
#include "integ/cc/quadrature.hh"
|
||||||
#include "integ/cc/smolyak.hh"
|
#include "integ/cc/smolyak.hh"
|
||||||
#include "integ/cc/product.hh"
|
#include "integ/cc/product.hh"
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
/* $Id: tests.cpp 431 2005-08-16 15:41:01Z kamenik $ */
|
/* $Id: tests.cpp 431 2005-08-16 15:41:01Z kamenik $ */
|
||||||
/* Copyright 2005, Ondra Kamenik */
|
/* Copyright 2005, Ondra Kamenik */
|
||||||
|
|
||||||
#include "GeneralMatrix.h"
|
#include "GeneralMatrix.hh"
|
||||||
#include <dynlapack.h>
|
#include <dynlapack.h>
|
||||||
#include "SylvException.h"
|
#include "SylvException.hh"
|
||||||
|
|
||||||
#include "rfs_tensor.h"
|
#include "rfs_tensor.hh"
|
||||||
#include "normal_moments.h"
|
#include "normal_moments.hh"
|
||||||
|
|
||||||
#include "vector_function.h"
|
#include "vector_function.hh"
|
||||||
#include "quadrature.h"
|
#include "quadrature.hh"
|
||||||
#include "smolyak.h"
|
#include "smolyak.hh"
|
||||||
#include "product.h"
|
#include "product.hh"
|
||||||
#include "quasi_mcarlo.h"
|
#include "quasi_mcarlo.hh"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "decision_rule.hh"
|
#include "decision_rule.hh"
|
||||||
#include "dynamic_model.hh"
|
#include "dynamic_model.hh"
|
||||||
|
|
||||||
#include "SymSchurDecomp.h"
|
#include "SymSchurDecomp.hh"
|
||||||
|
|
||||||
#include <dynlapack.h>
|
#include <dynlapack.h>
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "t_container.hh"
|
#include "t_container.hh"
|
||||||
#include "sparse_tensor.hh"
|
#include "sparse_tensor.hh"
|
||||||
|
|
||||||
#include "Vector.h"
|
#include "Vector.hh"
|
||||||
|
|
||||||
/* The class is a virtual pure class which provides an access to names
|
/* The class is a virtual pure class which provides an access to names
|
||||||
of the variables. */
|
of the variables. */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Copyright 2005, Ondra Kamenik
|
// Copyright 2005, Ondra Kamenik
|
||||||
|
|
||||||
#include "SymSchurDecomp.h"
|
#include "SymSchurDecomp.hh"
|
||||||
|
|
||||||
#include "global_check.hh"
|
#include "global_check.hh"
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "journal.hh"
|
#include "journal.hh"
|
||||||
|
|
||||||
#include "kord_exception.hh"
|
#include "kord_exception.hh"
|
||||||
#include "GeneralSylvester.h"
|
#include "GeneralSylvester.hh"
|
||||||
|
|
||||||
#include <dynlapack.h>
|
#include <dynlapack.h>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "korder.hh"
|
#include "korder.hh"
|
||||||
#include "SylvException.h"
|
#include "SylvException.hh"
|
||||||
|
|
||||||
struct Rand
|
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
|
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 = \
|
libparser_a_SOURCES = \
|
||||||
location.h \
|
location.hh \
|
||||||
namelist.h \
|
namelist.hh \
|
||||||
atom_assignings.cpp \
|
atom_assignings.cc \
|
||||||
atom_assignings.h \
|
atom_assignings.hh \
|
||||||
atom_substitutions.cpp \
|
atom_substitutions.cc \
|
||||||
atom_substitutions.h \
|
atom_substitutions.hh \
|
||||||
csv_parser.cpp \
|
csv_parser.cc \
|
||||||
csv_parser.h \
|
csv_parser.hh \
|
||||||
dynamic_atoms.cpp \
|
dynamic_atoms.cc \
|
||||||
dynamic_atoms.h \
|
dynamic_atoms.hh \
|
||||||
fine_atoms.cpp \
|
fine_atoms.cc \
|
||||||
fine_atoms.h \
|
fine_atoms.hh \
|
||||||
formula_parser.cpp \
|
formula_parser.cc \
|
||||||
formula_parser.h \
|
formula_parser.hh \
|
||||||
matrix_parser.cpp \
|
matrix_parser.cc \
|
||||||
matrix_parser.h \
|
matrix_parser.hh \
|
||||||
parser_exception.cpp \
|
parser_exception.cc \
|
||||||
parser_exception.h \
|
parser_exception.hh \
|
||||||
static_atoms.cpp \
|
static_atoms.cc \
|
||||||
static_atoms.h \
|
static_atoms.hh \
|
||||||
static_fine_atoms.cpp \
|
static_fine_atoms.cc \
|
||||||
static_fine_atoms.h \
|
static_fine_atoms.hh \
|
||||||
tree.cpp \
|
tree.cc \
|
||||||
tree.h \
|
tree.hh \
|
||||||
$(GENERATED_FILES)
|
$(GENERATED_FILES)
|
||||||
|
|
||||||
libparser_a_CPPFLAGS = -I../.. $(BOOST_CPPFLAGS)
|
libparser_a_CPPFLAGS = -I../.. $(BOOST_CPPFLAGS)
|
||||||
|
|
||||||
BUILT_SOURCES = $(GENERATED_FILES)
|
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 $<
|
$(YACC) -d -o$*_tab.cc $<
|
||||||
|
|
||||||
%_ll.cc: %.lex
|
%_ll.cc: %.ll
|
||||||
$(LEX) -i -o$@ $<
|
$(LEX) -i -o$@ $<
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
%{
|
%{
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "assign_tab.hh"
|
#include "assign_tab.hh"
|
||||||
|
|
||||||
extern YYLTYPE asgn_lloc;
|
extern YYLTYPE asgn_lloc;
|
|
@ -1,8 +1,8 @@
|
||||||
%{
|
%{
|
||||||
/* Copyright (C) 2006-2011, Ondra Kamenik */
|
/* Copyright (C) 2006-2011, Ondra Kamenik */
|
||||||
|
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "atom_assignings.h"
|
#include "atom_assignings.hh"
|
||||||
#include "assign_tab.hh"
|
#include "assign_tab.hh"
|
||||||
|
|
||||||
#include <stdio.h>
|
#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
|
#ifndef OGP_ATOM_ASSIGNINGS_H
|
||||||
#define OGP_ATOM_ASSIGNINGS_H
|
#define OGP_ATOM_ASSIGNINGS_H
|
||||||
|
|
||||||
#include "static_atoms.h"
|
#include "static_atoms.hh"
|
||||||
#include "formula_parser.h"
|
#include "formula_parser.hh"
|
||||||
#include "atom_substitutions.h"
|
#include "atom_substitutions.hh"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#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
|
#ifndef OGP_ATOM_SUBSTITUTIONS_H
|
||||||
#define OGP_ATOM_SUBSTITUTIONS_H
|
#define OGP_ATOM_SUBSTITUTIONS_H
|
||||||
|
|
||||||
#include "fine_atoms.h"
|
#include "fine_atoms.hh"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
%{
|
%{
|
||||||
// Copyright (C) 2007-2011, Ondra Kamenik
|
// Copyright (C) 2007-2011, Ondra Kamenik
|
||||||
|
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "csv_tab.hh"
|
#include "csv_tab.hh"
|
||||||
|
|
||||||
extern YYLTYPE csv_lloc;
|
extern YYLTYPE csv_lloc;
|
|
@ -1,6 +1,6 @@
|
||||||
%{
|
%{
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "csv_parser.h"
|
#include "csv_parser.hh"
|
||||||
#include "csv_tab.hh"
|
#include "csv_tab.hh"
|
||||||
|
|
||||||
void csv_error(const char*);
|
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
|
#ifndef OGP_DYNAMIC_ATOMS_H
|
||||||
#define OGP_DYNAMIC_ATOMS_H
|
#define OGP_DYNAMIC_ATOMS_H
|
||||||
|
|
||||||
#include "formula_parser.h"
|
#include "formula_parser.hh"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#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
|
#ifndef OGP_FINE_ATOMS_H
|
||||||
#define OGP_FINE_ATOMS_H
|
#define OGP_FINE_ATOMS_H
|
||||||
|
|
||||||
#include "dynamic_atoms.h"
|
#include "dynamic_atoms.hh"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
|
@ -1,5 +1,5 @@
|
||||||
%{
|
%{
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "formula_tab.hh"
|
#include "formula_tab.hh"
|
||||||
|
|
||||||
extern YYLTYPE fmla_lloc;
|
extern YYLTYPE fmla_lloc;
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "formula_parser.h"
|
#include "formula_parser.hh"
|
||||||
#include "formula_tab.hh"
|
#include "formula_tab.hh"
|
||||||
|
|
||||||
void fmla_error(const char*);
|
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
|
#ifndef OGP_FORMULA_PARSER_H
|
||||||
#define OGP_FORMULA_PARSER_H
|
#define OGP_FORMULA_PARSER_H
|
||||||
|
|
||||||
#include "tree.h"
|
#include "tree.hh"
|
||||||
|
|
||||||
namespace ogp
|
namespace ogp
|
||||||
{
|
{
|
|
@ -1,7 +1,7 @@
|
||||||
%{
|
%{
|
||||||
// Copyright (C) 2006-2011, Ondra Kamenik
|
// Copyright (C) 2006-2011, Ondra Kamenik
|
||||||
|
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "matrix_tab.hh"
|
#include "matrix_tab.hh"
|
||||||
|
|
||||||
extern YYLTYPE matrix_lloc;
|
extern YYLTYPE matrix_lloc;
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright (C) 2006-2011, Ondra Kamenik
|
// Copyright (C) 2006-2011, Ondra Kamenik
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "matrix_parser.h"
|
#include "matrix_parser.hh"
|
||||||
#include "matrix_tab.hh"
|
#include "matrix_tab.hh"
|
||||||
|
|
||||||
void matrix_error(const char*);
|
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"
|
#include "namelist_tab.hh"
|
||||||
|
|
||||||
extern YYLTYPE namelist_lloc;
|
extern YYLTYPE namelist_lloc;
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright (C) 2007-2011, Ondra Kamenik
|
// Copyright (C) 2007-2011, Ondra Kamenik
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include "location.h"
|
#include "location.hh"
|
||||||
#include "namelist.h"
|
#include "namelist.hh"
|
||||||
#include "namelist_tab.hh"
|
#include "namelist_tab.hh"
|
||||||
|
|
||||||
void namelist_error(const char*);
|
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
|
#ifndef OGP_STATIC_ATOMS
|
||||||
#define OGP_STATIC_ATOMS
|
#define OGP_STATIC_ATOMS
|
||||||
|
|
||||||
#include "dynamic_atoms.h"
|
#include "dynamic_atoms.hh"
|
||||||
|
|
||||||
namespace ogp
|
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
|
#ifndef OGP_STATIC_FINE_ATOMS_H
|
||||||
#define OGP_STATIC_FINE_ATOMS_H
|
#define OGP_STATIC_FINE_ATOMS_H
|
||||||
|
|
||||||
#include "static_atoms.h"
|
#include "static_atoms.hh"
|
||||||
#include "fine_atoms.h"
|
#include "fine_atoms.hh"
|
||||||
|
|
||||||
namespace ogp
|
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
|
GENERATED_FILES = dynglob_ll.cc dynglob_tab.cc dynglob_tab.hh
|
||||||
|
|
||||||
dynare___SOURCES = \
|
dynare___SOURCES = \
|
||||||
main.cpp \
|
main.cc \
|
||||||
dynare3.cpp \
|
dynare3.cc \
|
||||||
dynare_atoms.h \
|
dynare_atoms.hh \
|
||||||
dynare_model.h \
|
dynare_model.hh \
|
||||||
forw_subst_builder.h \
|
forw_subst_builder.hh \
|
||||||
planner_builder.cpp \
|
planner_builder.cc \
|
||||||
dynare3.h \
|
dynare3.hh \
|
||||||
dynare_exception.h \
|
dynare_exception.hh \
|
||||||
dynare_params.cpp \
|
dynare_params.cc \
|
||||||
planner_builder.h \
|
planner_builder.hh \
|
||||||
dynare_atoms.cpp \
|
dynare_atoms.cc \
|
||||||
dynare_model.cpp \
|
dynare_model.cc \
|
||||||
dynare_params.h \
|
dynare_params.hh \
|
||||||
forw_subst_builder.cpp \
|
forw_subst_builder.cc \
|
||||||
nlsolve.cpp \
|
nlsolve.cc \
|
||||||
nlsolve.h \
|
nlsolve.hh \
|
||||||
$(GENERATED_FILES)
|
$(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)
|
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)
|
dynare___CXXFLAGS = $(AM_CXXFLAGS) $(PTHREAD_CFLAGS)
|
||||||
|
|
||||||
BUILT_SOURCES = $(GENERATED_FILES)
|
BUILT_SOURCES = $(GENERATED_FILES)
|
||||||
EXTRA_DIST = dynglob.lex dynglob.y
|
EXTRA_DIST = dynglob.ll dynglob.yy
|
||||||
|
|
||||||
dynglob_tab.cc dynglob_tab.hh: dynglob.y
|
dynglob_tab.cc dynglob_tab.hh: dynglob.yy
|
||||||
$(YACC) -d -odynglob_tab.cc dynglob.y
|
$(YACC) -d -odynglob_tab.cc dynglob.yy
|
||||||
|
|
||||||
dynglob_ll.cc: dynglob.lex
|
dynglob_ll.cc: dynglob.ll
|
||||||
$(LEX) -i -odynglob_ll.cc dynglob.lex
|
$(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/decision_rule.hh"
|
||||||
#include "../kord/dynamic_model.hh"
|
#include "../kord/dynamic_model.hh"
|
||||||
|
|
||||||
#include "dynare_model.h"
|
#include "dynare_model.hh"
|
||||||
#include "nlsolve.h"
|
#include "nlsolve.hh"
|
||||||
|
|
||||||
#include <vector>
|
#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
|
#ifndef OGDYN_DYNARE_ATOMS_H
|
||||||
#define 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_atoms.hh"
|
||||||
#include "parser/cc/static_fine_atoms.h"
|
#include "parser/cc/static_fine_atoms.hh"
|
||||||
#include "parser/cc/atom_substitutions.h"
|
#include "parser/cc/atom_substitutions.hh"
|
||||||
#include "parser/cc/tree.h"
|
#include "parser/cc/tree.hh"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#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
|
#ifndef OGDYN_DYNARE_MODEL
|
||||||
#define OGDYN_DYNARE_MODEL
|
#define OGDYN_DYNARE_MODEL
|
||||||
|
|
||||||
#include "parser/cc/matrix_parser.h"
|
#include "parser/cc/matrix_parser.hh"
|
||||||
#include "parser/cc/atom_assignings.h"
|
#include "parser/cc/atom_assignings.hh"
|
||||||
|
|
||||||
#include "dynare_atoms.h"
|
#include "dynare_atoms.hh"
|
||||||
#include "twod_matrix.hh"
|
#include "twod_matrix.hh"
|
||||||
|
|
||||||
#include "Vector.h"
|
#include "Vector.hh"
|
||||||
#include "GeneralMatrix.h"
|
#include "GeneralMatrix.hh"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <boost/unordered_set.hpp>
|
#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"
|
#include "dynglob_tab.hh"
|
||||||
|
|
||||||
extern YYLTYPE dynglob_lloc;
|
extern YYLTYPE dynglob_lloc;
|
|
@ -1,8 +1,8 @@
|
||||||
%{
|
%{
|
||||||
// Copyright (C) 2006-2011, Ondra Kamenik
|
// Copyright (C) 2006-2011, Ondra Kamenik
|
||||||
|
|
||||||
#include "parser/cc/location.h"
|
#include "parser/cc/location.hh"
|
||||||
#include "dynare_model.h"
|
#include "dynare_model.hh"
|
||||||
#include "dynglob_tab.hh"
|
#include "dynglob_tab.hh"
|
||||||
|
|
||||||
#include <stdio.h>
|
#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
|
#ifndef FORW_SUBST_BUILDER_H
|
||||||
#define FORW_SUBST_BUILDER_H
|
#define FORW_SUBST_BUILDER_H
|
||||||
|
|
||||||
#include "dynare_model.h"
|
#include "dynare_model.hh"
|
||||||
|
|
||||||
namespace ogdyn
|
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
|
#ifndef PLANNER_BUILDER_H
|
||||||
#define PLANNER_BUILDER_H
|
#define PLANNER_BUILDER_H
|
||||||
|
|
||||||
#include "dynare_model.h"
|
#include "dynare_model.hh"
|
||||||
|
|
||||||
namespace ogdyn
|
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
|
#ifndef BLOCK_DIAGONAL_H
|
||||||
#define BLOCK_DIAGONAL_H
|
#define BLOCK_DIAGONAL_H
|
||||||
|
|
||||||
#include "QuasiTriangular.h"
|
#include "QuasiTriangular.hh"
|
||||||
|
|
||||||
class BlockDiagonal : public QuasiTriangular
|
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
|
#ifndef GENERAL_MATRIX_H
|
||||||
#define GENERAL_MATRIX_H
|
#define GENERAL_MATRIX_H
|
||||||
|
|
||||||
#include "Vector.h"
|
#include "Vector.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#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
|
#ifndef GENERAL_SYLVESTER_H
|
||||||
#define GENERAL_SYLVESTER_H
|
#define GENERAL_SYLVESTER_H
|
||||||
|
|
||||||
#include "SylvMatrix.h"
|
#include "SylvMatrix.hh"
|
||||||
#include "SylvMemory.h"
|
#include "SylvMemory.hh"
|
||||||
#include "SimilarityDecomp.h"
|
#include "SimilarityDecomp.hh"
|
||||||
#include "SylvesterSolver.h"
|
#include "SylvesterSolver.hh"
|
||||||
|
|
||||||
class GeneralSylvester
|
class GeneralSylvester
|
||||||
{
|
{
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue