12 namespace mrpt {
namespace srba {
16 template <
class HESS_Ap,
class HESS_f,
class HESS_Apf>
25 SchurComplement(HESS_Ap &_HAp, HESS_f & _Hf, HESS_Apf & _HApf,
double * _minus_grad_Ap,
double * _minus_grad_f)
45 const typename HESS_f::col_t & col_i =
Hf.getCol(i);
46 ASSERT_(!col_i.empty() && col_i.rbegin()->first==i)
58 typename HESS_Ap::col_t & HAp_col_i =
HAp.getCol(i);
64 for (
size_t j=0;j<=i;j++)
71 THApSymbolicEntry sym_ij;
78 typename HESS_Apf::col_t & row_i =
HApf.getCol(i);
79 typename HESS_Apf::col_t & row_j =
HApf.getCol(j);
87 while (it_i!=it_i_end && it_j!=it_j_end)
89 if ( it_i->first < it_j->first ) ++it_i;
90 else if ( it_j->first < it_i->first ) ++it_j;
100 const size_t idx_feat = it_j->first;
104 typename HESS_Apf::matrix_t *out_temporary_result = NULL;
107 grad_entries->lst_terms_to_subtract.resize( grad_entries->lst_terms_to_subtract.size()+1 );
108 typename TGradApSymbolicEntry::TEntry &ent = *grad_entries->lst_terms_to_subtract.rbegin();
109 ent.feat_idx = idx_feat;
110 out_temporary_result = &ent.Hpi_lk_times_inv_Hf_lk;
115 std::cout <<
"SymSchur.HAp("<<i<<
","<<j<<
"): HApf_" << it_i->first <<
" * HApf_" << it_j->first << std::endl;
117 sym_ij.lst_terms_to_add.push_back(
typename THApSymbolicEntry::TEntry(
121 out_temporary_result ) );
129 if (!sym_ij.lst_terms_to_add.empty())
135 if ( ((i==j) || (i!=j && HAp_col_i.size()!=1))
137 (itExistingRowEntry=HAp_col_i.find(j))!= HAp_col_i.end())
140 sym_ij.HAp_ij = & itExistingRowEntry ->second.num;
146 sym_ij.HAp_ij = & HAp_col_i[j].num;
148 sym_ij.HAp_ij->setZero();
197 for (
int k=0;k<Hfi.cols();k++)
198 Hfi.coeffRef(k,k)+=lambda;
200 const Eigen::FullPivLU<typename HESS_f::matrix_t> lu( Hfi );
203 if (
true== (
m_Hf_blocks_info[i].num_Hf_diag_blocks_invertible = lu.isInvertible() ))
212 typename HESS_Apf::matrix_t aux_Hpi_lk_times_inv_Hf_lk;
215 const THApSymbolicEntry &sym_entry = *it;
217 typename HESS_Ap::matrix_t & HAp_ij = *sym_entry.HAp_ij;
219 const size_t N = sym_entry.lst_terms_to_add.size();
222 for (
size_t i=0;i<N;i++)
224 const typename THApSymbolicEntry::TEntry &entry = sym_entry.lst_terms_to_add[i];
226 if (entry.inv_Hf_lk->num_Hf_diag_blocks_invertible)
232 typename HESS_Apf::matrix_t * Hpi_lk_times_inv_Hf_lk =
233 entry.out_Hpi_lk_times_inv_Hf_lk!=NULL
235 entry.out_Hpi_lk_times_inv_Hf_lk : &aux_Hpi_lk_times_inv_Hf_lk;
237 Hpi_lk_times_inv_Hf_lk->noalias() = (*entry.Hpi_lk) * entry.inv_Hf_lk->num_Hf_diag_blocks_inverses;
240 HAp_ij.noalias() -= (*Hpi_lk_times_inv_Hf_lk) * (*entry.Hpj_lk).transpose();
256 double *grad_df = this->
minus_grad_f + it->feat_idx * HESS_f::matrix_t::RowsAtCompileTime;
259 grad_Ap.noalias() -= it->Hpi_lk_times_inv_Hf_lk *
vector_f_t(grad_df);
264 modified_grad_Ap+= HESS_Ap::matrix_t::RowsAtCompileTime;
272 double *in_deltas_Ap,
273 double *out_deltas_feats
281 typename HESS_Apf::col_t & row_i =
HApf.getCol(idx_Ap);
283 const vector_Ap_t delta_idx_Ap =
vector_Ap_t(in_deltas_Ap + idx_Ap * HESS_Ap::matrix_t::RowsAtCompileTime );
287 const size_t idx_feat = itCol->first;
291 double *grad_df = this->
minus_grad_f + idx_feat * HESS_f::matrix_t::RowsAtCompileTime;
294 vector_f_t(grad_df).noalias() -= itCol->second.num.transpose() * delta_idx_Ap;
299 for (
size_t idx_feat=0;idx_feat<
nUnknowns_f;idx_feat++)
304 vector_f_t delta_feat =
vector_f_t( out_deltas_feats + idx_feat * HESS_f::matrix_t::RowsAtCompileTime );
308 delta_feat = (
m_Hf_blocks_info[idx_feat].num_Hf_diag_blocks_inverses * grad_df);
329 typedef typename Eigen::Map<Eigen::Matrix<double,HESS_Ap::matrix_t::RowsAtCompileTime,1> >
vector_Ap_t;
330 typedef typename Eigen::Map<Eigen::Matrix<double,HESS_f::matrix_t::RowsAtCompileTime,1> >
vector_f_t;
339 TInfoPerHfBlock() : sym_Hf_diag_blocks(NULL), num_Hf_diag_blocks_invertible(false) { }
354 const typename HESS_Apf::matrix_t * _Hpi_lk,
356 const typename HESS_Apf::matrix_t * _Hpj_lk,
357 typename HESS_Apf::matrix_t * _out_Hpi_lk_times_inv_Hf_lk
367 const typename HESS_Apf::matrix_t *
Hpi_lk;
369 const typename HESS_Apf::matrix_t *
Hpj_lk;
378 std::swap(HAp_ij,o.
HAp_ij);
400 #if defined(_MSC_VER) && (_MSC_VER < 1600) // if we use MSVC older than 2010:
Eigen::Map< Eigen::Matrix< double, HESS_f::matrix_t::RowsAtCompileTime, 1 > > vector_f_t
std::deque< THApSymbolicEntry > m_sym_HAp_reduce
All the required operations needed to update HAp into its reduced system.
mrpt::aligned_containers< TEntry >::deque_t lst_terms_t
std::deque< TEntry > lst_terms_to_add
#define MRPT_MAKE_ALIGNED_OPERATOR_NEW
std::vector< TGradApSymbolicEntry > m_sym_GradAp_reduce
All the required operations needed to update Gradient of Ap into its reduced system.
Eigen::Map< Eigen::Matrix< double, typename hessian_traits_t::TSparseBlocksHessian_Ap::matrix_t::RowsAtCompileTime, 1 > > vector_Ap_t
const size_t nUnknowns_Ap
const Scalar * const_iterator
std::deque< TYPE1, Eigen::aligned_allocator< TYPE1 > > deque_t
bool num_Hf_diag_blocks_invertible
Whether num_Hf_diag_blocks_inverses could be generated.
size_t getNumFeatures() const
After calling numeric_build_reduced_system() one can get the stats on how many features are actually ...
size_t getNumFeaturesFullRank() const
HESS_Ap::matrix_t * HAp_ij
const HESS_Apf::matrix_t * Hpi_lk
SchurComplement(HESS_Ap &_HAp, HESS_f &_Hf, HESS_Apf &_HApf, double *_minus_grad_Ap, double *_minus_grad_f)
Constructor: builds the symbolic representations Note: HApf must be in row-compressed form; HAp & Hf ...
HESS_f::matrix_t num_Hf_diag_blocks_inverses
EIGEN_STRONG_INLINE size_t getColCount() const
Get number of columns.
void numeric_build_reduced_system(const double lambda)
Replace the HAp matrix with its Schur reduced version.
bool was_ith_feature_invertible(const size_t i) const
TEntry(const typename HESS_Apf::matrix_t *_Hpi_lk, const TInfoPerHfBlock *_inv_Hf_lk, const typename HESS_Apf::matrix_t *_Hpj_lk, typename HESS_Apf::matrix_t *_out_Hpi_lk_times_inv_Hf_lk)
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
TInfoPerHfBlock_vector_t m_Hf_blocks_info
const TInfoPerHfBlock * inv_Hf_lk
void numeric_solve_for_features(double *in_deltas_Ap, double *out_deltas_feats)
HESS_Apf::matrix_t * out_Hpi_lk_times_inv_Hf_lk
If NULL=use local storage.
void swap(THApSymbolicEntry &o)
A generic symbolic and numeric Schur-complement handler for builing reduced systems of equations...
const HESS_Apf::matrix_t * Hpj_lk
const HESS_f::matrix_t * sym_Hf_diag_blocks
lst_terms_t lst_terms_to_subtract
Info for each block in HAp.
void realize_HAp_changed()
Must be called after the numerical values of the Hessian HAp change, typically after an optimization ...
std::vector< TYPE1, Eigen::aligned_allocator< TYPE1 > > vector_t
HESS_Apf::matrix_t Hpi_lk_times_inv_Hf_lk
mrpt::aligned_containers< TInfoPerHfBlock >::vector_t TInfoPerHfBlock_vector_t
std::list< TYPE1, Eigen::aligned_allocator< TYPE1 > > list_t
size_t nHf_invertible_blocks
for stats, the number of Hf diagonal blocks which are not rank-deficient.