easykf-2.04
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Pages
ukf_math.h
Go to the documentation of this file.
1 /* ukf_math.h
2  *
3  * Copyright (C) 2011-2014 Jeremy Fix
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or (at
8  * your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #ifndef UKF_MATH_H
21 #define UKF_MATH_H
22 
23 #include <gsl/gsl_vector.h>
24 #include <gsl/gsl_matrix.h>
25 
26 #include <iostream>
27 #include <cassert>
28 #include <cmath>
29 
30 namespace ukf
31 {
32  namespace math
33  {
34 
35  inline double min(double a, double b)
36  {
37  return a < b ? a : b;
38  }
39 
40  inline double max(double a, double b)
41  {
42  return a < b ? b : a;
43  }
44 
45  inline double signof(double x)
46  {
47  return x <= 0.0 ? -1.0 : 1.0;
48  }
49 
50  inline bool cmp_equal(double x, double y)
51  {
52  return fabs(x - y) <= 1e-10;
53  }
54  inline bool cmp_diff(double x, double y)
55  {
56  return fabs(x - y) >= 1e-10;
57  }
58 
64  void choleskyUpdate(gsl_matrix * sigmaTheta, double alpha, gsl_vector *x) {
65 
66  /*
67  This function performs a cholesky update of the
68  cholesky factorization sigmaTheta, that is it replaces
69  the Cholesky factorization sigmaTheta by the cholesky factorization of
70 
71  sigmaTheta*sigmaTheta^T + alpha * x * x^T
72 
73  The algorithm is an adaptation of a LU factorization rank one update.
74 
75  Reference is :
76 
77  Peter Strange, Andreas Griewank and Matthias Bollhöfer.
78  On the Efficient Update of Rectangular LU Factorizations subject to Low Rank Modifications.
79  Electronic Transactions on Numerical Analysis, 26:161-177, 2007.
80  alg. is given in left part of fig.2.1.
81 
82  Perhaps a more efficient algorithm exists, however it should do the work for now. And the code is probably not optimal...
83  */
84 
85  if (sigmaTheta->size1 != sigmaTheta->size2)
86  std::cout<<"ERROR ukf::math::choleskyUpdate Cannot use CholeskyUpdate on non-squared matrices"<<std::endl ;
87 
88  int i,j,n= sigmaTheta->size1 ;
89  double tmp ;
90  gsl_matrix *U = gsl_matrix_alloc(n,n) ;
91  gsl_vector *D = gsl_vector_alloc(n) ;
92  gsl_vector *y = gsl_vector_alloc(n) ;
93 
94  // A first thing is to set SS' (chol factor) in a LU form, L being unitriangular
95  // Compute U = L^T and D = diag(L)
96  gsl_matrix_set_zero(U) ;
97  for (i=0; i<n; i++){
98  gsl_vector_set(D,i,gsl_matrix_get(sigmaTheta,i,i));
99  for (j=0; j<=i; j++){
100  gsl_matrix_set(U,j,i,gsl_matrix_get(sigmaTheta,i,j));
101  }
102  }
103  // Replace L by L*D^{-1} and U by D*U
104  for (i=0; i<n; i++){
105  for (j=0; j<=i; j++){
106  tmp = gsl_matrix_get(sigmaTheta,i,j);
107  tmp /= gsl_vector_get(D,j);
108  gsl_matrix_set(sigmaTheta,i,j,tmp);
109  tmp = gsl_matrix_get(U,j,i);
110  tmp *= gsl_vector_get(D,j);
111  gsl_matrix_set(U,j,i,tmp);
112  }
113  }
114 
115  // compute the y = alpha x vector
116  gsl_vector_memcpy(y,x) ;
117  gsl_vector_scale(y,alpha) ;
118 
119  // perform the rank 1 LU modification
120  for (i=0; i<n; i++){
121 
122  // diagonal update
123  tmp = gsl_matrix_get(U,i,i) +
124  gsl_vector_get(x,i)*gsl_vector_get(y,i);
125  gsl_matrix_set(U,i,i,tmp);
126  tmp = gsl_vector_get(y,i);
127  tmp /= gsl_matrix_get(U,i,i);
128  gsl_vector_set(y,i,tmp);
129 
130  for (j=i+1; j<n; j++){
131  // L (that is sigmaTheta) update
132  tmp = gsl_vector_get(x,j) -
133  gsl_vector_get(x,i)*gsl_matrix_get(sigmaTheta,j,i);
134  gsl_vector_set(x,j,tmp) ;
135  tmp = gsl_matrix_get(sigmaTheta,j,i) + gsl_vector_get(y,i) * gsl_vector_get(x,j);
136  gsl_matrix_set(sigmaTheta,j,i,tmp);
137  }
138 
139  for (j=i+1; j<n; j++) {
140  // U update
141  tmp = gsl_matrix_get(U,i,j) +
142  gsl_vector_get(x,i)*gsl_vector_get(y,j);
143  gsl_matrix_set(U,i,j,tmp) ;
144  tmp = gsl_vector_get(y,j) -
145  gsl_vector_get(y,i) * gsl_matrix_get(U,i,j);
146  gsl_vector_set(y,j,tmp) ;
147  }
148  }
149 
150  // Now we want the chol decomposition
151  // first D = sqrt(diag(U)) ;
152  for (i=0; i<n; i++){
153  tmp = gsl_matrix_get(U,i,i) ;
154 
155  if (tmp<=0){std::cout<< "WARNING ukf::math::choleskyUpdate::matrix not positive definite : " << tmp << std::endl;}
156  gsl_vector_set(D,i,sqrt(tmp)) ;
157  }
158  // then L = L*D ;
159  for (i=0; i<n; i++) {
160  for (j=0; j<n; j++) {
161  tmp = gsl_matrix_get(sigmaTheta,i,j) * gsl_vector_get(D,j);
162  gsl_matrix_set(sigmaTheta,i,j,tmp);
163  }
164  }
165  // that's all folks !
166 
167  //free memory
168  gsl_matrix_free(U);
169  gsl_vector_free(y);
170  gsl_vector_free(D);
171  }
172  } // math
173 } // ukf
174 
175 
176 #endif // UKF_MATH_H
double min(double a, double b)
Definition: ukf_math.h:35
bool cmp_diff(double x, double y)
Definition: ukf_math.h:54
void choleskyUpdate(gsl_matrix *sigmaTheta, double alpha, gsl_vector *x)
This function performs a cholesky update according to Strange et al.(2007)
Definition: ukf_math.h:64
double max(double a, double b)
Definition: ukf_math.h:40
double signof(double x)
Definition: ukf_math.h:45
bool cmp_equal(double x, double y)
Definition: ukf_math.h:50