ReFRACtor
linear_algebra.cc
Go to the documentation of this file.
1 #include "linear_algebra.h"
2 #include "fp_gsl_matrix.h"
3 #include "fp_exception.h"
4 #include "gsl/gsl_linalg.h"
5 #include "gsl/gsl_multifit_nlin.h"
6 
7 using namespace FullPhysics;
8 using namespace blitz;
9 
12 
13 //-----------------------------------------------------------------------
24 //-----------------------------------------------------------------------
25 
26 Array<double, 1>
27 FullPhysics::solve_least_squares(const blitz::Array<double, 2>& A,
28  const blitz::Array<double, 1>& B,
29  double Rcond)
30 {
31  int n = A.cols();
32  Array<double, 1> s;
33  Array<double, 2> u;
34  Array<double, 2> v;
35  svd(A, s, u, v);
36  v.transposeSelf(secondDim, firstDim);
37  // Set very small values to zero.
38  for(int i = 0; i < s.rows(); ++i)
39  if(s(i) <= s(0) * Rcond)
40  s(i) = 0.0;
41  GslVector sgsl(s);
42  GslMatrix ugsl(u);
43  GslMatrix vgsl(v);
44  GslVector bgsl(const_cast<Array<double, 1>&>(B));
45  Array<double, 1> x(n);
46  GslVector xgsl(x);
47  int status = gsl_linalg_SV_solve(ugsl.gsl(), vgsl.gsl(), sgsl.gsl(),
48  bgsl.gsl(), xgsl.gsl());
49  gsl_check(status);
50  return xgsl.blitz_array();
51 }
52 
53 //-----------------------------------------------------------------------
63 //-----------------------------------------------------------------------
64 
65 Array<double, 1>
66 FullPhysics::solve_least_squares_qr(const blitz::Array<double, 2>& A,
67  const blitz::Array<double, 1>& B)
68 {
69  GslMatrix Agsl(const_cast<Array<double, 2>&>(A));
70  GslVector Bgsl(const_cast<Array<double, 1>&>(B));
71 
72  // tau must be the min(M, N)
73  Array<double, 1> tau;
74  tau.resize(min(A.rows(), A.cols()));
75  GslVector taugsl(tau);
76 
77  int status = gsl_linalg_QR_decomp (Agsl.gsl(), taugsl.gsl());
78  gsl_check(status);
79 
80  Array<double, 1> X(A.cols());
81  GslVector Xgsl(X);
82 
83  Array<double, 1> residual(A.rows());
84  GslVector residualgsl(residual);
85 
86  status = gsl_linalg_QR_lssolve (Agsl.gsl(), taugsl.gsl(), Bgsl.gsl(), Xgsl.gsl(), residualgsl.gsl());
87  gsl_check(status);
88 
89  return Xgsl.blitz_array();
90 }
91 
92 //-----------------------------------------------------------------------
101 //-----------------------------------------------------------------------
102 
103 void FullPhysics::svd(const blitz::Array<double, 2>& A,
104  blitz::Array<double, 1>& S,
105  blitz::Array<double, 2>& U,
106  blitz::Array<double, 2>& VT)
107 {
108  int m = A.rows();
109  int n = A.cols();
110  range_min_check(m, n);
111  S.resize(n);
112  U.reference(Array<double,2>(A.shape()));
113  U = A; // This is calculated in place.
114  VT.reference(Array<double,2>(shape(n,n)));
115  Array<double, 1> work(n);
116  GslMatrix ugsl(U);
117  GslVector sgsl(S);
118  GslMatrix vtgsl(VT);
119  GslVector workgsl(work);
120  int status = gsl_linalg_SV_decomp(ugsl.gsl(), vtgsl.gsl(), sgsl.gsl(),
121  workgsl.gsl());
122  gsl_check(status);
123  VT.transposeSelf(secondDim, firstDim);
124 }
125 
126 //-----------------------------------------------------------------------
134 //-----------------------------------------------------------------------
135 
136 Array<double, 2> FullPhysics::generalized_inverse(const
137  blitz::Array<double, 2>& A, double Rcond)
138 {
139  firstIndex i1; secondIndex i2; thirdIndex i3;
140  blitz::Array<double, 1> s;
141  blitz::Array<double, 2> u, vt;
142  svd(A, s, u, vt);
143  Array<double, 2> res(vt.cols(), u.rows());
144  res = sum(where(s(i3) > s(0) * Rcond, vt(i3, i1) * u(i2, i3) / s(i3), 0),
145  i3);
146  return res;
147 }
148 
149 //-----------------------------------------------------------------------
162 //-----------------------------------------------------------------------
163 
164 Array<double, 2> FullPhysics::generalized_inverse(const
165  blitz::Array<double, 2>& A, const blitz::Array<bool, 1>& Zero_unused,
166  double Rcond)
167 {
168  firstIndex i1; secondIndex i2; thirdIndex i3;
169  if(A.rows() != A.cols())
170  throw Exception("This version of generalized_inverse can only be used with square matrix");
171  blitz::Array<double, 1> s;
172  blitz::Array<double, 2> u, vt;
173  int num_zero = count(Zero_unused);
174  blitz::Array<double, 2> asub(A.rows() - num_zero, A.cols() - num_zero);
175  int isub = 0;
176  for(int i = 0; i < A.rows(); ++i)
177  if(!Zero_unused(i)) {
178  int jsub = 0;
179  for(int j = 0; j < A.cols(); ++j)
180  if(!Zero_unused(j)) {
181  asub(isub, jsub) = A(i, j);
182  ++jsub;
183  }
184  ++isub;
185  }
186  svd(asub, s, u, vt);
187  Array<double, 2> ressub(vt.cols(), u.rows());
188  ressub = sum(where(s(i3) > s(0) * Rcond, vt(i3, i1) * u(i2, i3) / s(i3), 0),
189  i3);
190  Array<double, 2> res(A.shape());
191  res = 0;
192  isub = 0;
193  for(int i = 0; i < A.rows(); ++i)
194  if(!Zero_unused(i)) {
195  int jsub = 0;
196  for(int j = 0; j < A.cols(); ++j)
197  if(!Zero_unused(j)) {
198  res(i,j) = ressub(isub, jsub);
199  ++jsub;
200  }
201  ++isub;
202  }
203  return res;
204 }
205 
206 
207 //-----------------------------------------------------------------------
210 //-----------------------------------------------------------------------
211 
212 blitz::Array<double, 2> FullPhysics::cholesky_decomposition(const blitz::Array<double, 2>& A)
213 {
214  Array<double, 2> t(A.shape());
215  GslMatrix rgsl(t);
216  Array<double, 2> res(rgsl.blitz_array());
217  res = A;
218  int status = gsl_linalg_cholesky_decomp(rgsl.gsl());
219  gsl_check(status);
220  for(int i = 0; i < res.rows(); ++i)
221  for(int j = i + 1; j < res.cols(); ++j)
222  res(i, j) = 0;
223  return res;
224 }
225 
226 blitz::Array<double, 2> FullPhysics::multifit_covar(const blitz::Array<double, 2>& J, double Eps_rel)
227 {
228  Array<double, 2> covar(J.cols(), J.cols());
229  int status = gsl_multifit_covar(GslMatrix(const_cast< Array<double, 2>& >(J)).gsl(), Eps_rel, GslMatrix(covar).gsl());
230  gsl_check(status);
231  return covar;
232 }
233 
234 bool FullPhysics::multifit_test_gradient(const blitz::Array<double, 1>& g, double Eps_abs)
235 {
236  return gsl_multifit_test_gradient(GslVector(const_cast< Array<double, 1>& >(g)).gsl(), Eps_abs) == GSL_SUCCESS;
237 }
238 
240  const blitz::Array<double, 1>& dx, const blitz::Array<double, 1>& x, double Eps_abs, double Eps_rel)
241 {
242  return gsl_multifit_test_delta( GslVector(const_cast< Array<double, 1>& >(dx)).gsl(),
243  GslVector(const_cast< Array<double, 1>& >(x)).gsl(),
244  Eps_abs, Eps_rel) == GSL_SUCCESS;
245 }
246 
const Unit s("s", 1.0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0)
void svd(const blitz::Array< double, 2 > &A, blitz::Array< double, 1 > &S, blitz::Array< double, 2 > &U, blitz::Array< double, 2 > &VT)
Compute the SVD decomposition of a matrix A = U * SIGMA * V^T.
blitz::Array< double, 1 > solve_least_squares(const blitz::Array< double, 2 > &A, const blitz::Array< double, 1 > &B, double Rcond=1e-12)
This solves the least squares system A*x = b, returning the minimum norm solution.
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
blitz::Array< double, 2 > cholesky_decomposition(const blitz::Array< double, 2 > &A)
This calculates the Cholesky Decompostion of A so that A = L L^T.
const Unit J("J", N *m)
This provides thin wrapper around the GNU Scientific Library gsl_matrix.
Definition: fp_gsl_matrix.h:20
Apply value function to a blitz array.
const Unit A("A", 1.0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0)
blitz::Array< double, 1 > solve_least_squares_qr(const blitz::Array< double, 2 > &A, const blitz::Array< double, 1 > &B)
This finds the least squares solution to the overdetermined system A x = b where the matrix A has mor...
blitz::Array< double, 2 > multifit_covar(const blitz::Array< double, 2 > &J, double Eps_rel=std::numeric_limits< double >::epsilon())
bool multifit_test_gradient(const blitz::Array< double, 1 > &g, double Eps_abs=std::numeric_limits< double >::epsilon())
blitz::Array< double, 2 > generalized_inverse(const blitz::Array< double, 2 > &A, double Rcond=std::numeric_limits< double >::epsilon())
This returns the generalized inverse of the given matrix.
#define gsl_check(status)
GSL check.
Definition: fp_exception.h:228
const Unit m("m", 1.0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
const blitz::Array< double, 1 > & blitz_array() const
Return blitz::Array look at data.
bool multifit_test_delta(const blitz::Array< double, 1 > &dx, const blitz::Array< double, 1 > &x, double Eps_abs=std::numeric_limits< double >::epsilon(), double Eps_rel=std::numeric_limits< double >::epsilon())
const Unit g("g", 1e-3 *kg)
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
const gsl_matrix * gsl() const
Return gsl_matrix look at data.
Definition: fp_gsl_matrix.h:58
#define range_min_check(V, Min)
Range check.
Definition: fp_exception.h:167
const gsl_vector * gsl() const
Return gsl_vector look at data.
This provides thin wrapper around the GNU Scientific Library gsl_vector.
Definition: fp_gsl_matrix.h:96

Copyright © 2017, California Institute of Technology.
ALL RIGHTS RESERVED.
U.S. Government Sponsorship acknowledged.
Generated Fri Aug 24 2018 15:44:11