1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
/***********************************************/
/**
* @file normalEquation.h
*
* @brief Systems of normal equations.
* Creation, combination and solving of systems of normal equations.
*
* @author Torsten Mayer-Guerr
* @date 2004-12-10
*
*/
/***********************************************/
#ifndef __GROOPS_NORMALEQUATION__
#define __GROOPS_NORMALEQUATION__
// Latex documentation
#ifdef DOCSTRING_NormalEquation
static const char *docstringNormalEquation = R"(
\section{NormalEquation}\label{normalEquationType}
This class provides a system of normal equations.
This total system is the weighted sum of individual normals.
\begin{equation}
\M N_{total} = \sum_{k=1} \frac{1}{\sigma_k^2}\M N_k
\qquad\text{and}\qquad
\M n_{total} = \sum_{k=1} \frac{1}{\sigma_k^2} \M n_k.
\end{equation}
The normals do not need to have the same dimension. The dimension
of the total combined system is chosen to cover all individual systems.
For each normal a \config{startIndex} is required which indicates
the position of the first unknown of the individual normal within the
combined parameter vector.
The $\sigma_k$ of the relative weights are defined by \config{aprioriSigma}
in a first step. If an apriori solution \configFile{inputfileApproxSolution}{matrix} is
given or the normals are solved iteratively the weights are determined by means
of variance compoment estimation (VCE), see \program{NormalsSolverVCE}:
\begin{equation}
\sigma_k^2 =
\frac{\M e_k^T\M P\M e_k}
{n_k-\frac{1}{\sigma_k^2}\text{trace}\left(\M N_k\M N_{total}^{-1}\right)},
\end{equation}
where $n_k$ is the number of observations. The square sum of the residuals
is calculated by
\begin{equation}
\M e_k^T\M P\M e_k = \M x^T\M N_k\M x - 2\M n_k^T\M x + \M l_k^T\M P_k\M l_k.
\end{equation}
The system of normal equations can be solved with several right hand sides at once. But
only one right hand side, which can be selected with the index \config{rightHandSide}
(counting from zero), can be used to compute the variance factors.
The combined normal $\M N_{total}$ and the solution $\M x$ are taken from the previous
iteration step. In case of \configClass{DesignVCE}{normalEquationType:designVCE} the algorithm
is a little bit different as described below.
)";
#endif
/***********************************************/
#include "base/import.h"
#include "base/parameterName.h"
#include "inputOutput/fileName.h"
#include "config/config.h"
#include "parallel/matrixDistributed.h"
/**
* @defgroup normalEquationGroup NormalEquation
* @brief Systems of normal equations.
* @ingroup classesGroup
* The interface is given by @ref NormalEquation. */
/// @{
/***** TYPES ***********************************/
class NormalEquation;
class NormalEquationBase;
typedef std::shared_ptr<NormalEquation> NormalEquationPtr;
/***** CLASS ***********************************/
/** @brief Systems of normal equations.
* Creation, combination and solving of systems of normal equations.
* An Instance of this class can be created by @ref readConfig. */
class NormalEquation
{
private:
enum Status {UNKNOWN, INIT, NORMAL, CHOLESKY, INVERSECHOLESKY, INVERSE};
Status status;
UInt rhsNo;
MatrixDistributed normals;
Matrix n; // right hand sides (at master)
Vector lPl; // Norm of the observations
UInt obsCount;
Matrix Wz; // Monte-Carlo-vector
Matrix x; // current solution
std::vector<NormalEquationBase*> normalsComponent;
public:
/// Constructor.
NormalEquation(Config &config, const std::string &name);
/// Destructor.
virtual ~NormalEquation();
/** @brief Init systems of normal equations.
* @param blockSize normal matrix is divided into blocks, (0: only one block).
* @param comm normal matrix is distributed over processes. */
void init(UInt blockSize, Parallel::CommunicatorPtr comm);
/** @brief Number of unknown parameters.
* Dimension of the normal matrix N. */
UInt parameterCount() const {return normals.parameterCount();}
/** @brief Count of the observation vectors on the right hand side.
* Columns of the right hand side n. */
UInt rightHandSideCount() const {return n.columns();}
/** @brief Total count of observations.
* This includes pseudo observations by the regularization. */
UInt observationCount() const {return obsCount;}
/** @brief Names of the unknown parameters. */
std::vector<ParameterName> parameterNames() const;
/** @brief Variance factors of the different normal equations systems.
* Estimated with Variance Component Estimation (VCE). */
Vector varianceComponentFactors() const;
/** @brief Set approximate solution.
* To speed up the iterative Variance Component Estimation (VCE). */
void setApproximateSolution(const const_MatrixSlice &x0);
/** @name Status
* @brief The following functions changes the state of this class.
* Optimal performance is only given if the functions are called in a specific state.
* The expected state and the state after the call are given in brackets.
* (expected state -> state after call). */
//@{
/** @brief Accumulate normal equations.
* The weight of the different normal equation systems are computed
* in terms of Variance Component Estimation (VCE).
* This is an iterative process as it depends on residuals which depend on the solution.
* If convergence is reached TRUE is returned.
* Change of state of this class: (->NORMAL). */
Bool build(UInt rightHandSide=0);
/** @brief Write systems of normal equations to file.
* Change of state of this class: (NORMAL -> NORMAL). */
void write(const FileName &name);
/** @brief Solve the system of normal equations.
* Change of state of this class: (NORMAL -> CHOLESKY).
* @return Solution vector as columns of the matrix. */
Matrix solve();
/** @brief A posteriori sigma.
* Change of state of this class: (CHOLESKY -> CHOLESKY). */
Double aposterioriSigma();
/** @brief Inverse of the combined normal matrix.
* The posteriori sigma is applied if possible.
* Change of state of this class: (CHOLESKY -> CHOLESKYINVERSE).
* @return Accuracy of the solution (Square root of the diagonals of the inverse). */
Vector sigmaParameter();
/** @brief Write variance/covariance matrix.
* Change of state of this class: (CHOLESKYINVERSE -> INVERSE). */
void writeCovariance(const FileName &name);
/** @brief Contribution of normal equation components.
* Each column of the returned matrix contains the contribution
* of the normal equation component to the solution.
* The sum of the elements in each row is one.
* Change of state of this class: (INVERSE -> INVERSE).
* @return contribution vectors as coulumns of a matrix */
Matrix contribution();
//@}
/** @brief creates an derived instance of this class. */
static NormalEquationPtr create(Config &config, const std::string &name) {return NormalEquationPtr(new NormalEquation(config, name));}
};
/***** FUNCTIONS *******************************/
/** @brief Creates an instance of the class NormalEquation.
* Search for a node with @a name in the Config node.
* if @a name is not found the function returns FALSE and class with empty normals is created.
* @param config The config node which includes the node with the options for this class
* @param name Tag name in the config.
* @param[out] normalEquation Created class.
* @param mustSet If is MUSTSET and @a name is not found, this function throws an exception instead of returning with FALSE.
* @param defaultValue Ignored at the moment.
* @param annotation Description of the function of this class.
* @relates NormalEquation */
template<> Bool readConfig(Config &config, const std::string &name, NormalEquationPtr &normalEquation, Config::Appearance mustSet, const std::string &defaultValue, const std::string &annotation);
/// @}
/***** CLASS ***********************************/
// Internal class
class NormalEquationBase
{
public:
virtual ~NormalEquationBase() {}
protected:
virtual UInt rightHandSideCount() const = 0;
virtual UInt parameterCount() const = 0;
virtual void parameterNames(std::vector<ParameterName> &name) const = 0;
virtual void init(MatrixDistributed &normals, UInt rhsCount) = 0;
virtual Bool addNormalEquation(UInt rightHandSide, const const_MatrixSlice &x, const const_MatrixSlice &Wz,
MatrixDistributed &normals, Matrix &n, Vector &lPl, UInt &obsCount) = 0;
virtual Vector contribution(MatrixDistributed &Cov) = 0;
virtual std::vector<Double> varianceComponentFactors() const = 0;
friend class NormalEquation;
};
/***********************************************/
#endif /* __GROOPS_NORMALEQUATION__ */
|