Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
LeastSquares.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include "LeastSquares.hh"
26 #include "Lapack.hh"
27 #include <Base/Common/BIASpragma.hh>
28 
29 using namespace BIAS;
30 using namespace std;
31 
32 /////////////////////////////////////////////////////////////////////////
33 /// LeastSquaresBase
34 /////////////////////////////////////////////////////////////////////////
35 
36 int LeastSquaresBase::Init(unsigned SolutionSize, bool ReduceToATA)
37 {
38  _ReduceToATA=ReduceToATA;
39  _SolutionSize=SolutionSize;
40  _ATA.newsize(_SolutionSize, _SolutionSize);
41  _Weight.newsize(_SolutionSize, _SolutionSize);
42  _ATb.newsize(_SolutionSize);
43  return 0;
44 }
45 
47  Vector<double> &x)
48 {
49  BIASERR("only the overloaded function in the derived class can be used");
50  return -1;
51 }
52 
54 {
55  BIASERR("only the overloaded function in the derived class can be used");
56  return -1;
57 }
58 
60  Vector<double> &weights, Vector<double> &x)
61 {
62  BIASERR("only the overloaded function in the derived class can be used");
63  return -1;
64 }
65 
67  Vector<double> &x)
68 {
69  BIASERR("only the overloaded function in the derived class can be used");
70  return -1;
71 }
72 
73 
74 ////////////////////////////////////////////////////////////////////////////
75 /// LeastSquaresLapack
76 ///////////////////////////////////////////////////////////////////////////
77 
78 
80  Vector<double> &x)
81 {
82  BIASDOUT(D_LS_MATRIXES, "A: "<<A<<"\nb: "<<b);
83  int res=0;
84  if (_ReduceToATA){
85  _AT=A.Transpose();
86  _AT.Mult(A, _ATA);
87  _AT.Mult(b, _ATb);
88  BIASDOUT(D_LS_RED_MATRIXES, "_ATA: "<<_ATA<<"\n_ATb: "<<_ATb);
89  x=Lapack_LLS_QR_linear_solve(_ATA, _ATb, res);
90  } else {
91  x=Lapack_LLS_QR_linear_solve(A, b, res);
92  }
93 
94  return res;
95 }
96 
98 {
99  BIASERR("unfinished");
100  return -1;
101 }
102 
104  Vector<double> &weights,
105  Vector<double> &x)
106 {
107  BIASDOUT(D_LS_MATRIXES, "A: "<<A<<"\nb: "<<b);
108  int res=0;
109  if (_ReduceToATA){
110  Matrix<double> wA(A);
111  Vector<double> wb(b);
112  for (unsigned i=0; i<_SolutionSize; i++){
113  wA.ScaleRow(i, weights[i]);
114  wb[i]*=weights[i];
115  }
116  _AT=wA.Transpose();
117  _AT.Mult(wA, _ATA);
118  _AT.Mult(wb, _ATb);
119  BIASDOUT(D_LS_RED_MATRIXES, "_ATA: "<<_ATA<<"\n_ATb: "<<_ATb);
120  x=Lapack_LLS_QR_linear_solve(_ATA, _ATb, res);
121  } else {
122  _Weight.newsize(A.num_rows(), A.num_rows());
123  for (int i=0; i<A.num_rows(); i++){
124  _Weight[i][i]=1.0/weights[i];
125  }
126  x=Lapack_WLLS_solve(A, b, _Weight, res);
127  }
128  return res;
129 }
130 
132  Vector<double> &weights,
133  Vector<double> &x)
134 {
135  BIASERR("unfinished");
136  return -1;
137 }
138 
139 
140 ////////////////////////////////////////////////////////////////////////////
141 /// LeastSquaresSVD
142 ///////////////////////////////////////////////////////////////////////////
143 
144 
145 /** solve |Ax-b|=min using svd with mxn Matrix A
146 
147  |r|^2 = |Ax-b|^2 = (Ax-b)^T(Ax-b)
148  = x^T A^T A x - x^T A^T b - b^T A x + b^T b =
149  use x^T A^T b = b^T A x (both are real)
150  = x^T A^T A x - 2 x^T A^T b + b^T b =
151  use SVD(A^T A) := W S W^T since A^T A is symmetric
152  = x^T W S W^T x - 2 x^T A^T b + b^T b =
153  set z:=W^T x -> x=Wz or x^T = z^T W^T
154  = z^T S z - 2 z^T W^T A^T b + b^T b =
155  set d:= W^T A^T b
156  = z^T S z - 2 z^T d + b^T b =
157  = sum_i(S_i*z_i^2 - 2 z_i d_i + b_i^2)
158 
159  d |r|^2 / dx = d|r|^2/dz * dz/dx == 0
160  -> d|r|^2/dz=0
161  -> z_i = d_i / S_i
162 
163  x = W z
164 
165  solve least squares using svd:
166  1. calculate SVD(A^T A) = W S W^T
167  2. calculate d = W^T A^T b
168  3. calculate z: z_i = d_i/S_i
169  4. calculate x = W z
170 
171  @author woelk 04 2003 */
173  Vector<double> &x)
174 {
175  BIASDOUT(D_LS_MATRIXES, "A: "<<A<<"\nb: "<<b);
176  _AT=A.Transpose();
177  _AT.Mult(A, _ATA);
178  _AT.Mult(b, _ATb);
179  BIASDOUT(D_LS_RED_MATRIXES, "_ATA: "<<_ATA<<"\n_ATb: "<<_ATb);
180  if (_svd.Compute(_ATA)!=0){
181  return -2;
182  }
183  Vector<double> d(A.num_rows()), z(A.num_cols());
184  Vector<double> S=_svd.GetS();
185  d=_svd.GetVT() * _ATb;
186  BIASDOUT(D_LS_SVD, "_ATA: "<<_ATA<<"\nd: "<<d<<"\nS: "<<S);
187  for (int i=0; i<A.num_cols(); i++)
188  z[i]=(fabs(S[i])>DEFAULT_DOUBLE_ZERO_THRESHOLD)?d[i]/S[i]:0.0;
189 
190  x = _svd.GetU() * z;
191  return 0;
192 }
193 
194 
196 {
197  BIASDOUT(D_LS_MATRIXES, "A: "<<A);
198  if (x.size()!=(int)_SolutionSize)
199  x.newsize(_SolutionSize);
200 
201  if (_ReduceToATA){
202  _AT=A.Transpose();
203  _AT.Mult(A, _ATA);
204  BIASDOUT(D_LS_RED_MATRIXES, "_ATA: "<<_ATA);
205  if (General_singular_value_decomposition(_ATA, _S, _VT)!=0){
206  BIASERR("error in svd");
207  return -2;
208  }
209  for (unsigned i=0; i<_SolutionSize; i++){
210  x[i]=_VT[_SolutionSize-1][i];
211  }
212  } else {
213  if (General_singular_value_decomposition(A, _S, _VT)!=0){
214  BIASERR("error in svd");
215  return -2;
216  }
217  for (unsigned i=0; i<_SolutionSize; i++){
218  x[i]=_VT[_SolutionSize-1][i];
219  }
220  }
221  return 0;
222 }
223 
224 
226  Vector<double> &weights, Vector<double> &x)
227 {
228  BIASERR("unfinished");
229  return -1;
230 }
231 
233  Vector<double> &x)
234 {
235  BIASDOUT(D_LS_MATRIXES, "A: "<<A<<"\nweights: "<<weights);
236  if (x.size()!=(int)_SolutionSize)
237  x.newsize(_SolutionSize);
238 
239  Matrix<double> wA(A);
240  for (unsigned i=0; i<_SolutionSize; i++){
241  wA.ScaleRow(i, weights[i]);
242  }
243 
244  if (_ReduceToATA){
245  _AT=wA.Transpose();
246  _AT.Mult(wA, _ATA);
247  BIASDOUT(D_LS_RED_MATRIXES, "_ATA: "<<_ATA);
248  if (General_singular_value_decomposition(_ATA, _S, _VT)!=0){
249  BIASERR("error in svd");
250  return -2;
251  }
252  for (unsigned i=0; i<_SolutionSize; i++){
253  x[i]=_VT[_SolutionSize-1][i];
254  }
255  } else {
256  if (General_singular_value_decomposition(wA, _S, _VT)!=0){
257  BIASERR("error in svd");
258  return -2;
259  }
260  for (unsigned i=0; i<_SolutionSize; i++){
261  x[i]=_VT[_SolutionSize-1][i];
262  }
263  }
264  return 0;
265 }
266 
BIAS::Vector< double > Lapack_LLS_QR_linear_solve(const BIAS::Matrix< double > &A, const BIAS::Vector< double > &b, int &res)
linear least squares solves |Ax-b|=min res=0 on success, anything else rudimentary tested (woelk) ...
Definition: Lapack.cpp:311
virtual int Solve(Matrix< double > &A, Vector< double > &b, Vector< double > &x)
Solve linear equation system A*x = b using linear least squares, i.e.
virtual int WeightedSolve(Matrix< double > &A, Vector< double > &b, Vector< double > &weights, Vector< double > &x)
Solve linear equation system A*x = b using weighted linear least squares, i.e.
Subscript num_cols() const
Definition: cmat.h:320
Matrix< T > Transpose() const
transpose function, storing data destination matrix
Definition: Matrix.hh:823
virtual int WeightedSolve(Matrix< double > &A, Vector< double > &b, Vector< double > &weights, Vector< double > &x)
Solve linear equation system A*x = b using weighted linear least squares, i.e.
BIAS::Vector< double > Lapack_WLLS_solve(const BIAS::Matrix< double > &A, const BIAS::Vector< double > &b, const BIAS::Matrix< double > &B, int &res)
weighted linear least squares solves |B^-1(b-Ax)|=min res=0 on success, anything else rudimentary tes...
Definition: Lapack.cpp:376
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
virtual int WeightedSolve(Matrix< double > &A, Vector< double > &b, Vector< double > &weights, Vector< double > &x)
Solve linear equation system A*x = b using weighted linear least squares, i.e.
virtual int Solve(Matrix< double > &A, Vector< double > &b, Vector< double > &x)
LeastSquaresSVD.
int General_singular_value_decomposition(char jobu, char jobvt, const BIAS::Matrix< double > &A, BIAS::Vector< double > &ret_S, BIAS::Matrix< double > &ret_U, BIAS::Matrix< double > &ret_VT)
solve general eigenproblem.
Definition: Lapack.cpp:688
void Mult(const Matrix< T > &arg, Matrix< T > &result) const
matrix multiplication, result is not allocated
Definition: Matrix.hh:913
Subscript num_rows() const
Definition: cmat.h:319
virtual int Solve(Matrix< double > &A, Vector< double > &b, Vector< double > &x)
LeastSquaresLapack.
int Init(unsigned SolutionSize, bool ReduceToATA=true)
Initialize least squares solver.
void ScaleRow(int NoRow, T scale)
Scales row NoRow with scale.
Definition: Matrix.cpp:215
Subscript size() const
Definition: vec.h:262