File: normalEquation.h

package info (click to toggle)
groops 0%2Bgit20250907%2Bds-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 11,140 kB
  • sloc: cpp: 135,607; fortran: 1,603; makefile: 20
file content (223 lines) | stat: -rw-r--r-- 8,754 bytes parent folder | download | duplicates (2)
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__ */