@q $Id: approximation.cweb 2344 2009-02-09 20:36:08Z michel $ @>
@q Copyright 2005, Ondra Kamenik @>

@ Start of {\tt approximation.cpp} file.

@c
#include "kord_exception.h"
#include "approximation.h"
#include "first_order.h"
#include "korder_stoch.h"

@<|ZAuxContainer| constructor code@>;
@<|ZAuxContainer::getType| code@>;
@<|Approximation| constructor code@>;
@<|Approximation| destructor code@>;
@<|Approximation::getFoldDecisionRule| code@>;
@<|Approximation::getUnfoldDecisionRule| code@>;
@<|Approximation::approxAtSteady| code@>;
@<|Approximation::walkStochSteady| code@>;
@<|Approximation::saveRuleDerivs| code@>;
@<|Approximation::calcStochShift| code@>;
@<|Approximation::check| code@>;
@<|Approximation::calcYCov| code@>;

@ 
@<|ZAuxContainer| constructor code@>=
ZAuxContainer::ZAuxContainer(const _Ctype* gss, int ngss, int ng, int ny, int nu)
	: StackContainer<FGSTensor>(4,1)
{
	stack_sizes[0] = ngss; stack_sizes[1] = ng;
	stack_sizes[2] = ny; stack_sizes[3] = nu;
	conts[0] = gss;
	calculateOffsets();
}


@ The |getType| method corresponds to
$f(g^{**}(y^*,u',\sigma),0,0,0)$. For the first argument we return
|matrix|, for other three we return |zero|.

@<|ZAuxContainer::getType| code@>=
ZAuxContainer::itype ZAuxContainer::getType(int i, const Symmetry& s) const
{
	if (i == 0)
		if (s[2] > 0)
			return zero;
		else
			return matrix;
	return zero;
}


@ 
@<|Approximation| constructor code@>=
Approximation::Approximation(DynamicModel& m, Journal& j, int ns, bool dr_centr, double qz_crit)
	: model(m), journal(j), rule_ders(NULL), rule_ders_ss(NULL), fdr(NULL), udr(NULL),
	  ypart(model.nstat(), model.npred(), model.nboth(), model.nforw()),
	  mom(UNormalMoments(model.order(), model.getVcov())), nvs(4), steps(ns),
	  dr_centralize(dr_centr), qz_criterium(qz_crit), ss(ypart.ny(), steps+1)
{
	nvs[0] = ypart.nys(); nvs[1] = model.nexog();
	nvs[2] = model.nexog(); nvs[3] = 1;

	ss.nans();
}

@ 
@<|Approximation| destructor code@>=
Approximation::~Approximation()
{
	if (rule_ders_ss) delete rule_ders_ss;
	if (rule_ders) delete rule_ders;
	if (fdr) delete fdr;
	if (udr) delete udr;
}

@ This just returns |fdr| with a check that it is created.
@<|Approximation::getFoldDecisionRule| code@>=
const FoldDecisionRule& Approximation::getFoldDecisionRule() const
{
	KORD_RAISE_IF(fdr == NULL,
				  "Folded decision rule has not been created in Approximation::getFoldDecisionRule");
	return *fdr;
}


@ This just returns |udr| with a check that it is created.
@<|Approximation::getUnfoldDecisionRule| code@>=
const UnfoldDecisionRule& Approximation::getUnfoldDecisionRule() const
{
	KORD_RAISE_IF(udr == NULL,
				  "Unfolded decision rule has not been created in Approximation::getUnfoldDecisionRule");
	return *udr;
}


@ This methods assumes that the deterministic steady state is
|model.getSteady()|. It makes an approximation about it and stores the
derivatives to |rule_ders| and |rule_ders_ss|. Also it runs a |check|
for $\sigma=0$.

@<|Approximation::approxAtSteady| code@>=
void Approximation::approxAtSteady()
{
	model.calcDerivativesAtSteady();
	FirstOrder fo(model.nstat(), model.npred(), model.nboth(), model.nforw(),
				  model.nexog(), *(model.getModelDerivatives().get(Symmetry(1))),
				  journal, qz_criterium);
	KORD_RAISE_IF_X(! fo.isStable(),
					"The model is not Blanchard-Kahn stable",
					KORD_MD_NOT_STABLE);

	if (model.order() >= 2) {
		KOrder korder(model.nstat(), model.npred(), model.nboth(), model.nforw(),
					  model.getModelDerivatives(), fo.getGy(), fo.getGu(),
					  model.getVcov(), journal);
		korder.switchToFolded();
		for (int k = 2; k <= model.order(); k++)
			korder.performStep<KOrder::fold>(k);
		
		saveRuleDerivs(korder.getFoldDers());
	} else {
		FirstOrderDerivs<KOrder::fold> fo_ders(fo);
		saveRuleDerivs(fo_ders);
	}
	check(0.0);
}

@ This is the core routine of |Approximation| class.

First we solve for the approximation about the deterministic steady
state. Then we perform |steps| cycles toward the stochastic steady
state. Each cycle moves the size of shocks by |dsigma=1.0/steps|. At
the end of a cycle, we have |rule_ders| being the derivatives at
stochastic steady state for $\sigma=sigma\_so\_far+dsigma$ and
|model.getSteady()| being the steady state.

If the number of |steps| is zero, the decision rule |dr| at the bottom
is created from derivatives about deterministic steady state, with
size of $\sigma=1$. Otherwise, the |dr| is created from the
approximation about stochastic steady state with $\sigma=0$.

Within each cycle, we first make a backup of the last steady (from
initialization or from a previous cycle), then we calculate the fix
point of the last rule with $\sigma=dsigma$. This becomes a new steady
state at the $\sigma=sigma\_so\_far+dsigma$. We calculate expectations
of $g^{**}(y,\sigma\eta_{t+1},\sigma$ expressed as a Taylor expansion
around the new $\sigma$ and the new steady state. Then we solve for
the decision rule with explicit $g^{**}$ at $t+1$ and save the rule.

After we reached $\sigma=1$, the decision rule is formed.

The biproduct of this method is the matrix |ss|, whose columns are
steady states for subsequent $\sigma$s. The first column is the
deterministic steady state, the last column is the stochastic steady
state for a full size of shocks ($\sigma=1$). There are |steps+1|
columns.

@<|Approximation::walkStochSteady| code@>=
void Approximation::walkStochSteady()
{
	@<initial approximation at deterministic steady@>;
	double sigma_so_far = 0.0;
	double dsigma = (steps == 0)? 0.0 : 1.0/steps;
	for (int i = 1; i <= steps; i++) {
		JournalRecordPair pa(journal);
		pa << "Approximation about stochastic steady for sigma=" << sigma_so_far+dsigma << endrec;

		Vector last_steady((const Vector&)model.getSteady());

		@<calculate fix-point of the last rule for |dsigma|@>;
		@<calculate |hh| as expectations of the last $g^{**}$@>;
		@<form |KOrderStoch|, solve and save@>;

		check(sigma_so_far+dsigma);
		sigma_so_far += dsigma;
	}

	@<construct the resulting decision rules@>;
}

@ Here we solve for the deterministic steady state, calculate
approximation at the deterministic steady and save the steady state
to |ss|.

@<initial approximation at deterministic steady@>=
	model.solveDeterministicSteady();
	approxAtSteady();
	Vector steady0(ss, 0);
	steady0 = (const Vector&)model.getSteady();

@ We form the |DRFixPoint| object from the last rule with
$\sigma=dsigma$. Then we save the steady state to |ss|. The new steady
is also put to |model.getSteady()|.

@<calculate fix-point of the last rule for |dsigma|@>=
	DRFixPoint<KOrder::fold> fp(*rule_ders, ypart, model.getSteady(), dsigma);
	bool converged = fp.calcFixPoint(DecisionRule::horner, model.getSteady());
	JournalRecord rec(journal);
	rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
		<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
	if (converged)
		rec << " Converged." << endrec;
	else {
		rec << " Not converged!!" << endrec;
		KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
	}
	Vector steadyi(ss, i);
	steadyi = (const Vector&)model.getSteady();

@ We form the steady state shift |dy|, which is the new steady state
minus the old steady state. Then we create |StochForwardDerivs|
object, which calculates the derivatives of $g^{**}$ expectations at
new sigma and new steady.

@<calculate |hh| as expectations of the last $g^{**}$@>=
	Vector dy((const Vector&)model.getSteady());
	dy.add(-1.0, last_steady);

	StochForwardDerivs<KOrder::fold> hh(ypart, model.nexog(), *rule_ders_ss, mom, dy,
										dsigma, sigma_so_far);
	JournalRecord rec1(journal);
	rec1 << "Calculation of g** expectations done" << endrec;


@ We calculate derivatives of the model at the new steady, form
|KOrderStoch| object and solve, and save the rule.

@<form |KOrderStoch|, solve and save@>=
	model.calcDerivativesAtSteady();
	KOrderStoch korder_stoch(ypart, model.nexog(), model.getModelDerivatives(),
							 hh, journal);
	for (int d = 1; d <= model.order(); d++) {
		korder_stoch.performStep<KOrder::fold>(d);
	}
	saveRuleDerivs(korder_stoch.getFoldDers());


@ 
@<construct the resulting decision rules@>=
	if (fdr) {
		delete fdr;
		fdr = NULL;
	}
	if (udr) {
		delete udr;
		udr = NULL;
	}

	fdr = new FoldDecisionRule(*rule_ders, ypart, model.nexog(),
							   model.getSteady(), 1.0-sigma_so_far);
	if (steps == 0 && dr_centralize) {
		@<centralize decision rule for zero steps@>;
	}


@ 
@<centralize decision rule for zero steps@>=
	DRFixPoint<KOrder::fold> fp(*rule_ders, ypart, model.getSteady(), 1.0);
	bool converged = fp.calcFixPoint(DecisionRule::horner, model.getSteady());
	JournalRecord rec(journal);
	rec << "Fix point calcs: iter=" << fp.getNumIter() << ", newton_iter="
		<< fp.getNewtonTotalIter() << ", last_newton_iter=" << fp.getNewtonLastIter() << ".";
	if (converged)
		rec << " Converged." << endrec;
	else {
		rec << " Not converged!!" << endrec;
		KORD_RAISE_X("Fix point calculation not converged", KORD_FP_NOT_CONV);
	}

	{
		JournalRecordPair recp(journal);
		recp << "Centralizing about fix-point." << endrec;
		FoldDecisionRule* dr_backup = fdr;
		fdr = new FoldDecisionRule(*dr_backup, model.getSteady());
		delete dr_backup;
	}


@ Here we simply make a new hardcopy of the given rule |rule_ders|,
and make a new container of in-place subtensors of the derivatives
corresponding to forward looking variables. The given container comes
from a temporary object and will be destroyed.
 
@<|Approximation::saveRuleDerivs| code@>=
void Approximation::saveRuleDerivs(const FGSContainer& g)
{
	if (rule_ders) {
		delete rule_ders;
		delete rule_ders_ss;
	}
	rule_ders = new FGSContainer(g);
	rule_ders_ss = new FGSContainer(4);
	for (FGSContainer::iterator run = (*rule_ders).begin(); run != (*rule_ders).end(); ++run) {
		FGSTensor* ten = new FGSTensor(ypart.nstat+ypart.npred, ypart.nyss(), *((*run).second));
		rule_ders_ss->insert(ten);
	}
}

@ This method calculates a shift of the system equations due to
integrating shocks at a given $\sigma$ and current steady state. More precisely, if
$$F(y,u,u',\sigma)=f(g^{**}(g^*(y,u,\sigma),u',\sigma),g(y,u,\sigma),y,u)$$
then the method returns a vector
$$\sum_{d=1}{1\over d!}\sigma^d\left[F_{u'^d}\right]_{\alpha_1\ldots\alpha_d}
\Sigma^{\alpha_1\ldots\alpha_d}$$

For a calculation of $\left[F_{u'^d}\right]$ we use |@<|ZAuxContainer|
class declaration@>|, so we create its object. In each cycle we
calculate $\left[F_{u'^d}\right]$@q'@>, and then multiply with the shocks,
and add the ${\sigma^d\over d!}$ multiple to the result.

@<|Approximation::calcStochShift| code@>=
void Approximation::calcStochShift(Vector& out, double at_sigma) const
{
	KORD_RAISE_IF(out.length() != ypart.ny(),
				  "Wrong length of output vector for Approximation::calcStochShift");
	out.zeros();

	ZAuxContainer zaux(rule_ders_ss, ypart.nyss(), ypart.ny(),
					   ypart.nys(), model.nexog());

	int dfac = 1;
	for (int d = 1; d <= rule_ders->getMaxDim(); d++, dfac*=d) {
		if ( KOrder::is_even(d)) {
			Symmetry sym(0,d,0,0);
			@<calculate $F_{u'^d}$ via |ZAuxContainer|@>;@q'@>
			@<multiply with shocks and add to result@>;
		}
	}
}

@ 
@<calculate $F_{u'^d}$ via |ZAuxContainer|@>=
	FGSTensor* ten = new FGSTensor(ypart.ny(), TensorDimens(sym, nvs));
	ten->zeros();
	for (int l = 1; l <= d; l++) {
		const FSSparseTensor* f = model.getModelDerivatives().get(Symmetry(l));
		zaux.multAndAdd(*f, *ten);
	}

@
@<multiply with shocks and add to result@>=
	FGSTensor* tmp = new FGSTensor(ypart.ny(), TensorDimens(Symmetry(0,0,0,0), nvs));
	tmp->zeros();
	ten->contractAndAdd(1, *tmp, *(mom.get(Symmetry(d))));

	out.add(pow(at_sigma,d)/dfac, tmp->getData());
	delete ten;
	delete tmp;


@ This method calculates and reports
$$f(\bar y)+\sum_{d=1}{1\over d!}\sigma^d\left[F_{u'^d}\right]_{\alpha_1\ldots\alpha_d}
\Sigma^{\alpha_1\ldots\alpha_d}$$
at $\bar y$, zero shocks and $\sigma$. This number should be zero.

We evaluate the error both at a given $\sigma$ and $\sigma=1.0$.

@<|Approximation::check| code@>=
void Approximation::check(double at_sigma) const
{
	Vector stoch_shift(ypart.ny());
	Vector system_resid(ypart.ny());
	Vector xx(model.nexog());
	xx.zeros();
	model.evaluateSystem(system_resid, model.getSteady(), xx);
	calcStochShift(stoch_shift, at_sigma);
	stoch_shift.add(1.0, system_resid);
	JournalRecord rec1(journal);
	rec1 << "Error of current approximation for shocks at sigma " << at_sigma
		 << " is " << stoch_shift.getMax() << endrec;
	calcStochShift(stoch_shift, 1.0);
	stoch_shift.add(1.0, system_resid);
	JournalRecord rec2(journal);
	rec2 << "Error of current approximation for full shocks is " << stoch_shift.getMax() << endrec;
}

@ The method returns unconditional variance of endogenous variables
based on the first order. The first order approximation looks like
$$\hat y_t=g_{y^*}\hat y^*_{t-1}+g_uu_t$$
where $\hat y$ denotes a deviation from the steady state. It can be written as
$$\hat y_t=\left[0\, g_{y^*}\, 0\right]\hat y_{t-1}+g_uu_t$$
which yields unconditional covariance $V$ for which
$$V=GVG^T + g_u\Sigma g_u^T,$$
where $G=[0\, g_{y^*}\, 0]$ and $\Sigma$ is the covariance of the shocks. 

For solving this Lyapunov equation we use the Sylvester module, which
solves equation of the type
$$AX+BX(C\otimes\cdots\otimes C)=D$$
So we invoke the Sylvester solver for the first dimension with $A=I$,
$B=-G$, $C=G^T$ and $D=g_u\Sigma g_u^T$.


@<|Approximation::calcYCov| code@>=
TwoDMatrix* Approximation::calcYCov() const
{
	const TwoDMatrix& gy = *(rule_ders->get(Symmetry(1,0,0,0)));
	const TwoDMatrix& gu = *(rule_ders->get(Symmetry(0,1,0,0)));
	TwoDMatrix G(model.numeq(), model.numeq());
	G.zeros();
	G.place(gy, 0, model.nstat());
	TwoDMatrix B((const TwoDMatrix&)G);
	B.mult(-1.0);
	TwoDMatrix C(G, "transpose");
	TwoDMatrix A(model.numeq(), model.numeq());
	A.zeros();
	for (int i = 0; i < model.numeq(); i++)
		A.get( i,i)	= 1.0;

	TwoDMatrix guSigma(gu, model.getVcov());
	TwoDMatrix guTrans(gu, "transpose");
	TwoDMatrix* X = new TwoDMatrix(guSigma, guTrans);
	
	GeneralSylvester gs(1, model.numeq(), model.numeq(), 0,
						A.base(), B.base(), C.base(), X->base());
	gs.solve();

	return X;
}

@ End of {\tt approximation.cpp} file.
