28 std::tuple<gsl::matrix,double>
31 static double constexpr
32 eps4 { std::sqrt( std::sqrt( std::numeric_limits<double>::epsilon() ) ) };
33 static double constexpr eps2 { std::sqrt( std::numeric_limits<double>::epsilon() ) };
35 auto D = matrix.const_diagonal();
36 maxoffl = std::sqrt( std::accumulate( D.begin(), D.end(),
38 [](
double const x,
double const y ){
39 return x > y ? x : y; } ) );
41 double const minL2 { eps2 * maxoffl };
44 static std::vector<double> D;
46 size_t const N = matrix.size1();
47 if( matrix.size2() != N )
throw exception(
"gsl::modifiedCholeskyDecomp():"
48 "matrix must be square.", __FILE__,
49 __LINE__, exception::GSL_EBADLEN );
52 throw exception(
"gsl::modifiedCholeskyDecomp():"
53 "maxoffl must be nonzero.", __FILE__,
54 __LINE__, exception::GSL_ESANITY );
56 gsl::matrix L( N, N );
59 double const minL { eps4 * maxoffl };
62 for(
size_t j { 0 }; j < N; ++j ){
65 for(
size_t i { 0 }; i < j; ++i ){
66 double const entry { L.get( j, i ) };
67 sumL2 += entry * entry;
69 L.set( j, j, matrix.get( j, j ) - sumL2 );
72 for(
size_t i { j + 1 }; i < N; ++i ){
74 for(
size_t k { 0 }; k < j; ++k )
75 sumLL += L.get( i, k ) * L.get( j, k );
76 double const d { matrix.get( j, i ) - sumLL };
78 minLjj = std::max( minLjj, d );
80 minLjj = std::max( minLjj / maxoffl, minL );
82 if( L.get( j, j ) > minLjj * minLjj ){
84 L.set( j, j, std::sqrt( L.get( j, j ) ) );
87 minLjj = std::max( minLjj, minL2 );
88 maxAdd = std::max( maxAdd, minLjj * minLjj - L.get( j, j ) );
89 L.set( j, j, minLjj );
93 for(
size_t i { j + 1 }; i < N; ++i )
94 L.set( i, j, L.get( i, j ) / L.get( j, j ) );
98 return std::make_tuple( L, maxAdd );
104 static double constexpr eps2 { std::sqrt( std::numeric_limits<double>::epsilon() )};
107 size_t const N { matrix.size1() };
108 if( matrix.size2() != N )
throw exception(
"gsl::modelHessian():"
109 "matrix must be square.", __FILE__,
110 __LINE__, exception::GSL_EBADLEN );
112 double maxDiag { -INF };
113 double minDiag { INF };
114 for(
double const& d : matrix.const_diagonal() ){
115 maxDiag = std::max( maxDiag, d );
116 minDiag = std::min( minDiag, d );
118 double const maxPosDiag { std::max( 0.0, maxDiag ) };
121 if( minDiag <= eps2 * maxPosDiag ){
122 mu = 2 * (maxPosDiag - minDiag) * eps2 - minDiag;
127 for(
size_t i { 0 }; i < N; ++i )
128 for(
size_t j { i + 1 }; j < N; ++j )
129 maxoff = std::max( maxoff, matrix.get( i, j ) );
130 if( maxoff * (1 + 2 * eps2) > maxDiag ){
131 mu += (maxoff - maxDiag) + 2 * eps2 * maxoff;
132 maxDiag = maxoff * (1 + 2 * eps2);
140 if( mu > 0 ) matrix.diagonal().add_constant( mu );
142 double const maxoffl { std::sqrt( std::max( maxDiag, maxoff / N ) ) };
145 gsl::matrix L { std::get<0>( cholDecomp ) };
146 double const maxAdd { std::get<1>( cholDecomp ) };
149 double maxev { matrix.get( 0, 0 ) };
150 double minev { maxev };
151 for(
size_t i { 0 }; i < N; ++i ){
153 for(
size_t j { 0 }; j + 1 < i; ++j )
154 offrow += std::fabs( matrix.get( j, i ) );
155 for(
size_t j { i + 1 }; j < N; ++j )
156 offrow += std::fabs( matrix.get( i, j ) );
157 double const hii { matrix.get( i, i ) };
158 maxev = std::max( maxev, hii + offrow );
159 minev = std::min( minev, hii - offrow );
161 double const sdd { std::max( 0.0, (maxev - minev) *eps2 - minev ) };
162 mu = std::min( maxAdd, sdd );
163 matrix.diagonal().add_constant( mu );
166 L = std::get<0>( cholDecomp );
168 for(
size_t j { 0 }; j < N; ++j )
169 for(
size_t i { 0 }; i < j; ++i )
170 L.set( i, j, L.get( j, i ) );
gsl::matrix modelHessian(gsl::matrix &matrix)
Find a Cholesky decomposition (both upper and lower triangles returned in matrix) of a matrix + mu * ...
std::tuple< gsl::matrix, double > modifiedCholeskyDecomp(gsl::matrix const &matrix, double maxoffl)
Modified in-place Cholesky decomposition using the method of Gill, Murray and Wright (1981) to deal w...