2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2004-2011 Ondra Kamenik
|
|
|
|
|
* Copyright © 2019 Dynare Team
|
|
|
|
|
*
|
|
|
|
|
* This file is part of Dynare.
|
|
|
|
|
*
|
|
|
|
|
* Dynare is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* Dynare is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
#ifndef TRIANGULAR_SYLVESTER_H
|
|
|
|
|
#define TRIANGULAR_SYLVESTER_H
|
|
|
|
|
|
2019-01-08 17:12:05 +01:00
|
|
|
|
#include "SylvesterSolver.hh"
|
|
|
|
|
#include "KronVector.hh"
|
|
|
|
|
#include "QuasiTriangular.hh"
|
|
|
|
|
#include "QuasiTriangularZero.hh"
|
|
|
|
|
#include "SimilarityDecomp.hh"
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2019-01-15 18:55:09 +01:00
|
|
|
|
#include <memory>
|
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class TriangularSylvester : public SylvesterSolver
|
|
|
|
|
{
|
2019-01-15 18:55:09 +01:00
|
|
|
|
const std::unique_ptr<const QuasiTriangular> matrixKK;
|
|
|
|
|
const std::unique_ptr<const QuasiTriangular> matrixFF;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
public:
|
2017-05-16 16:30:27 +02:00
|
|
|
|
TriangularSylvester(const QuasiTriangular &k, const QuasiTriangular &f);
|
|
|
|
|
TriangularSylvester(const SchurDecompZero &kdecomp, const SchurDecomp &fdecomp);
|
|
|
|
|
TriangularSylvester(const SchurDecompZero &kdecomp, const SimilarityDecomp &fdecomp);
|
2019-12-20 14:36:20 +01:00
|
|
|
|
|
2019-01-15 18:55:09 +01:00
|
|
|
|
~TriangularSylvester() override = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void print() const;
|
2019-01-09 16:26:42 +01:00
|
|
|
|
void solve(SylvParams &pars, KronVector &d) const override;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void solvi(double r, KronVector &d, double &eig_min) const;
|
|
|
|
|
void solvii(double alpha, double beta1, double beta2,
|
|
|
|
|
KronVector &d1, KronVector &d2,
|
|
|
|
|
double &eig_min) const;
|
|
|
|
|
void solviip(double alpha, double betas,
|
|
|
|
|
KronVector &d, double &eig_min) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* Computes:
|
|
|
|
|
⎛x₁⎞ ⎛d₁⎞ ⎛ α −β₁⎞ ⎛d₁⎞
|
|
|
|
|
⎢ ⎥=⎢ ⎥+⎢ ⎥⊗Fᵀ⊗Fᵀ⊗…⊗K·⎢ ⎥
|
|
|
|
|
⎝x₂⎠ ⎝d₂⎠ ⎝−β₂ α ⎠ ⎝d₂⎠
|
2017-05-16 16:30:27 +02:00
|
|
|
|
*/
|
|
|
|
|
void linEval(double alpha, double beta1, double beta2,
|
|
|
|
|
KronVector &x1, KronVector &x2,
|
|
|
|
|
const ConstKronVector &d1, const ConstKronVector &d2) const;
|
|
|
|
|
void
|
|
|
|
|
linEval(double alpha, double beta1, double beta2,
|
|
|
|
|
KronVector &x1, KronVector &x2,
|
|
|
|
|
const KronVector &d1, const KronVector &d2) const
|
|
|
|
|
{
|
|
|
|
|
linEval(alpha, beta1, beta2, x1, x2,
|
|
|
|
|
ConstKronVector(d1), ConstKronVector(d2));
|
|
|
|
|
}
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* Computes:
|
|
|
|
|
⎛x₁⎞ ⎛d₁⎞ ⎛γ −δ₁⎞ ⎛d₁⎞ ⎛γ −δ₁⎞² ⎛d₁⎞
|
|
|
|
|
⎢ ⎥=⎢ ⎥+2α⎢ ⎥⊗Fᵀ⊗Fᵀ⊗…⊗K·⎢ ⎥+(α²+β)⎢ ⎥ ⊗Fᵀ²⊗Fᵀ²⊗…⊗K²·⎢ ⎥
|
|
|
|
|
⎝x₂⎠ ⎝d₂⎠ ⎝δ₂ γ ⎠ ⎝d₂⎠ ⎝δ₂ γ ⎠ ⎝d₂⎠
|
2017-05-16 16:30:27 +02:00
|
|
|
|
*/
|
|
|
|
|
void quaEval(double alpha, double betas,
|
|
|
|
|
double gamma, double delta1, double delta2,
|
|
|
|
|
KronVector &x1, KronVector &x2,
|
|
|
|
|
const ConstKronVector &d1, const ConstKronVector &d2) const;
|
|
|
|
|
void
|
|
|
|
|
quaEval(double alpha, double betas,
|
|
|
|
|
double gamma, double delta1, double delta2,
|
|
|
|
|
KronVector &x1, KronVector &x2,
|
|
|
|
|
const KronVector &d1, const KronVector &d2) const
|
|
|
|
|
{
|
|
|
|
|
quaEval(alpha, betas, gamma, delta1, delta2, x1, x2,
|
|
|
|
|
ConstKronVector(d1), ConstKronVector(d2));
|
|
|
|
|
}
|
2009-09-08 15:55:19 +02:00
|
|
|
|
private:
|
2019-03-28 18:56:46 +01:00
|
|
|
|
/* Returns square of size of minimal eigenvalue of the system solved,
|
2017-05-16 16:30:27 +02:00
|
|
|
|
now obsolete */
|
|
|
|
|
double getEigSep(int depth) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Recursively calculates kronecker product of complex vectors (used in getEigSep)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
static void multEigVector(KronVector &eig, const Vector &feig, const Vector &keig);
|
2019-03-28 18:56:46 +01:00
|
|
|
|
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using const_diag_iter = QuasiTriangular::const_diag_iter;
|
|
|
|
|
using const_row_iter = QuasiTriangular::const_row_iter;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
|
|
|
|
|
// Called from solvi
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void solviRealAndEliminate(double r, const_diag_iter di,
|
|
|
|
|
KronVector &d, double &eig_min) const;
|
|
|
|
|
void solviComplexAndEliminate(double r, const_diag_iter di,
|
|
|
|
|
KronVector &d, double &eig_min) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Called from solviip
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void solviipRealAndEliminate(double alpha, double betas,
|
|
|
|
|
const_diag_iter di, const_diag_iter dsi,
|
|
|
|
|
KronVector &d, double &eig_min) const;
|
|
|
|
|
void solviipComplexAndEliminate(double alpha, double betas,
|
|
|
|
|
const_diag_iter di, const_diag_iter dsi,
|
|
|
|
|
KronVector &d, double &eig_min) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Eliminations
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void solviEliminateReal(const_diag_iter di, KronVector &d,
|
|
|
|
|
const KronVector &y, double divisor) const;
|
|
|
|
|
void solviEliminateComplex(const_diag_iter di, KronVector &d,
|
|
|
|
|
const KronVector &y1, const KronVector &y2,
|
|
|
|
|
double divisor) const;
|
|
|
|
|
void solviipEliminateReal(const_diag_iter di, const_diag_iter dsi,
|
|
|
|
|
KronVector &d,
|
|
|
|
|
const KronVector &y1, const KronVector &y2,
|
|
|
|
|
double divisor, double divisor2) const;
|
|
|
|
|
void solviipEliminateComplex(const_diag_iter di, const_diag_iter dsi,
|
|
|
|
|
KronVector &d,
|
|
|
|
|
const KronVector &y1, const KronVector &y11,
|
|
|
|
|
const KronVector &y2, const KronVector &y22,
|
|
|
|
|
double divisor) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Lemma 2
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void solviipComplex(double alpha, double betas, double gamma,
|
|
|
|
|
double delta1, double delta2,
|
|
|
|
|
KronVector &d1, KronVector &d2,
|
|
|
|
|
double &eig_min) const;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
// Norms for what we consider zero on diagonal of F
|
2019-01-16 17:52:16 +01:00
|
|
|
|
static constexpr double diag_zero = 1.e-15;
|
2019-03-28 18:56:46 +01:00
|
|
|
|
static constexpr double diag_zero_sq = diag_zero*diag_zero;
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif /* TRIANGULAR_SYLVESTER_H */
|