LCOV - code coverage report
Current view: top level - routines - locally_linear.hpp (source / functions) Hit Total Coverage
Test: clean.info Lines: 156 158 98.7 %
Date: 2013-05-24 Functions: 8 32 25.0 %
Branches: 143 690 20.7 %

           Branch data     Line data    Source code
       1                 :            : /* This software is distributed under BSD 3-clause license (see LICENSE file).
       2                 :            :  *
       3                 :            :  * Copyright (c) 2012-2013 Sergey Lisitsyn
       4                 :            :  */
       5                 :            : 
       6                 :            : #ifndef TAPKEE_LOCALLY_LINEAR_H_
       7                 :            : #define TAPKEE_LOCALLY_LINEAR_H_
       8                 :            : 
       9                 :            : /* Tapkee includes */
      10                 :            : #include <tapkee/routines/eigendecomposition.hpp>
      11                 :            : #include <tapkee/defines.hpp>
      12                 :            : #include <tapkee/utils/matrix.hpp>
      13                 :            : #include <tapkee/utils/time.hpp>
      14                 :            : #include <tapkee/utils/sparse.hpp>
      15                 :            : /* End of Tapkee includes */
      16                 :            : 
      17                 :            : namespace tapkee
      18                 :            : {
      19                 :            : namespace tapkee_internal
      20                 :            : {
      21                 :            : 
      22                 :            : 
      23                 :            : 
      24                 :            : template <class RandomAccessIterator, class PairwiseCallback>
      25                 :          1 : SparseWeightMatrix tangent_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, 
      26                 :            :                                          const Neighbors& neighbors, PairwiseCallback callback, 
      27                 :            :                                          const IndexType target_dimension, const ScalarType shift,
      28                 :            :                                          const bool partial_eigendecomposer=false)
      29                 :            : {
      30 [ +  - ][ +  - ]:          1 :         timed_context context("KLTSA weight matrix computation");
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      31                 :          1 :         const IndexType k = neighbors[0].size();
      32                 :            : 
      33   [ +  -  #  #  :          1 :         SparseTriplets sparse_triplets;
                   #  # ]
      34 [ +  - ][ #  # ]:          1 :         sparse_triplets.reserve((k*k+2*k+1)*(end-begin));
                 [ #  # ]
      35                 :            : 
      36                 :            : #pragma omp parallel shared(begin,end,neighbors,callback,sparse_triplets) default(none)
      37                 :            :         {
      38                 :            :                 IndexType index_iter;
      39                 :          3 :                 DenseMatrix gram_matrix = DenseMatrix::Zero(k,k);
      40                 :          4 :                 DenseVector rhs = DenseVector::Ones(k);
      41                 :          4 :                 DenseMatrix G = DenseMatrix::Zero(k,target_dimension+1);
      42                 :          4 :                 G.col(0).setConstant(1/sqrt(static_cast<ScalarType>(k)));
      43                 :          4 :                 DenseSelfAdjointEigenSolver solver;
      44                 :          4 :                 SparseTriplets local_triplets;
      45                 :          2 :                 local_triplets.reserve(k*k+2*k+1);
      46                 :            : 
      47 [ +  - ][ #  # ]:          3 : #pragma omp for nowait
                 [ #  # ]
      48                 :            :                 for (index_iter=0; index_iter<static_cast<IndexType>(end-begin); index_iter++)
      49                 :            :                 {
      50                 :         50 :                         const LocalNeighbors& current_neighbors = neighbors[index_iter];
      51                 :            :                 
      52 [ +  + ][ #  # ]:        544 :                         for (IndexType i=0; i<k; ++i)
                 [ #  # ]
      53                 :            :                         {
      54 [ +  + ][ #  # ]:       3190 :                                 for (IndexType j=i; j<k; ++j)
                 [ #  # ]
      55                 :            :                                 {
      56                 :       2690 :                                         ScalarType kij = callback.kernel(begin[current_neighbors[i]],begin[current_neighbors[j]]);
      57                 :       2636 :                                         gram_matrix(i,j) = kij;
      58                 :       2637 :                                         gram_matrix(j,i) = kij;
      59                 :            :                                 }
      60                 :            :                         }
      61                 :            :                         
      62                 :         50 :                         centerMatrix(gram_matrix);
      63                 :            : 
      64                 :            :                         //UNRESTRICT_ALLOC;
      65                 :            : #ifdef TAPKEE_WITH_ARPACK
      66   [ +  -  #  #  :         49 :                         if (partial_eigendecomposer)
                   #  # ]
      67                 :            :                         {
      68                 :          0 :                                 G.rightCols(target_dimension).noalias() =
      69                 :            :                                         eigendecomposition<DenseMatrix,DenseMatrixOperation>(Arpack,gram_matrix,target_dimension,0).first;
      70                 :            :                         }
      71                 :            :                         else
      72                 :            : #endif
      73                 :            :                         {
      74                 :         49 :                                 solver.compute(gram_matrix);
      75                 :         50 :                                 G.rightCols(target_dimension).noalias() = solver.eigenvectors().rightCols(target_dimension);
      76                 :            :                         }
      77                 :            :                         //RESTRICT_ALLOC;
      78                 :         50 :                         gram_matrix.noalias() = G * G.transpose();
      79                 :            :                         
      80                 :         50 :                         SparseTriplet diagonal_triplet(index_iter,index_iter,shift);
      81                 :         49 :                         local_triplets.push_back(diagonal_triplet);
      82 [ +  + ][ #  # ]:        549 :                         for (IndexType i=0; i<k; ++i)
                 [ #  # ]
      83                 :            :                         {
      84                 :        499 :                                 SparseTriplet neighborhood_diagonal_triplet(current_neighbors[i],current_neighbors[i],1.0);
      85                 :        500 :                                 local_triplets.push_back(neighborhood_diagonal_triplet);
      86                 :            : 
      87 [ +  + ][ #  # ]:       5494 :                                 for (IndexType j=0; j<k; ++j) 
                 [ #  # ]
      88                 :            :                                 {
      89                 :       4995 :                                         SparseTriplet tangent_triplet(current_neighbors[i],current_neighbors[j],-gram_matrix(i,j));
      90                 :       4994 :                                         local_triplets.push_back(tangent_triplet);
      91                 :            :                                 }
      92                 :            :                         }
      93                 :         50 : #pragma omp critical
      94                 :            :                         {
      95                 :         50 :                                 copy(local_triplets.begin(),local_triplets.end(),back_inserter(sparse_triplets));
      96                 :            :                         }
      97                 :            :                         
      98 [ +  + ][ #  # ]:         58 :                         local_triplets.clear();
                 [ #  # ]
      99                 :            :                 }
     100                 :            :         }
     101                 :            : 
     102 [ +  - ][ +  - ]:          1 :         return sparse_matrix_from_triplets(sparse_triplets, end-begin, end-begin);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     103                 :            : }
     104                 :            : 
     105                 :            : template <class RandomAccessIterator, class PairwiseCallback>
     106                 :          3 : SparseWeightMatrix linear_weight_matrix(const RandomAccessIterator& begin, const RandomAccessIterator& end, 
     107                 :            :                                         const Neighbors& neighbors, PairwiseCallback callback,
     108                 :            :                                         const ScalarType shift, const ScalarType trace_shift)
     109                 :            : {
     110 [ +  - ][ +  - ]:          3 :         timed_context context("KLLE weight computation");
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     111                 :          3 :         const IndexType k = neighbors[0].size();
     112                 :            : 
     113   [ +  -  #  #  :          3 :         SparseTriplets sparse_triplets;
                   #  # ]
     114 [ +  - ][ #  # ]:          3 :         sparse_triplets.reserve((k*k+2*k+1)*(end-begin));
                 [ #  # ]
     115                 :            : 
     116                 :            : #pragma omp parallel shared(begin,end,neighbors,callback,sparse_triplets) default(none)
     117                 :            :         {
     118                 :            :                 IndexType index_iter;
     119                 :         12 :                 DenseMatrix gram_matrix = DenseMatrix::Zero(k,k);
     120                 :         12 :                 DenseVector dots(k);
     121                 :         12 :                 DenseVector rhs = DenseVector::Ones(k);
     122                 :         11 :                 DenseVector weights;
     123                 :         10 :                 SparseTriplets local_triplets;
     124                 :         10 :                 local_triplets.reserve(k*k+2*k+1);
     125                 :            :                 
     126                 :            :                 //RESTRICT_ALLOC;
     127 [ +  + ][ #  # ]:         10 : #pragma omp for nowait
                 [ #  # ]
     128                 :            :                 for (index_iter=0; index_iter<static_cast<IndexType>(end-begin); index_iter++)
     129                 :            :                 {
     130                 :        150 :                         ScalarType kernel_value = callback.kernel(begin[index_iter],begin[index_iter]);
     131                 :        148 :                         const LocalNeighbors& current_neighbors = neighbors[index_iter];
     132                 :            :                         
     133 [ +  + ][ #  # ]:       1629 :                         for (IndexType i=0; i<k; ++i)
                 [ #  # ]
     134                 :       1461 :                                 dots[i] = callback.kernel(begin[index_iter], begin[current_neighbors[i]]);
     135                 :            : 
     136 [ +  + ][ #  # ]:       1628 :                         for (IndexType i=0; i<k; ++i)
                 [ #  # ]
     137                 :            :                         {
     138 [ +  + ][ #  # ]:       9171 :                                 for (IndexType j=i; j<k; ++j)
                 [ #  # ]
     139                 :       7699 :                                         gram_matrix(i,j) = kernel_value - dots(i) - dots(j) + 
     140                 :            :                                                            callback.kernel(begin[current_neighbors[i]],begin[current_neighbors[j]]);
     141                 :            :                         }
     142                 :            :                         
     143                 :        150 :                         ScalarType trace = gram_matrix.trace();
     144                 :        150 :                         gram_matrix.diagonal().array() += trace_shift*trace;
     145                 :        149 :                         weights = gram_matrix.selfadjointView<Eigen::Upper>().ldlt().solve(rhs);
     146                 :        148 :                         weights /= weights.sum();
     147                 :            : 
     148                 :        150 :                         SparseTriplet diagonal_triplet(index_iter,index_iter,1.0+shift);
     149                 :        149 :                         local_triplets.push_back(diagonal_triplet);
     150 [ +  + ][ #  # ]:       1639 :                         for (IndexType i=0; i<k; ++i)
                 [ #  # ]
     151                 :            :                         {
     152                 :       1489 :                                 SparseTriplet row_side_triplet(current_neighbors[i],index_iter,-weights[i]);
     153                 :       1492 :                                 SparseTriplet col_side_triplet(index_iter,current_neighbors[i],-weights[i]);
     154                 :       1491 :                                 local_triplets.push_back(row_side_triplet);
     155                 :       1491 :                                 local_triplets.push_back(col_side_triplet);
     156 [ +  + ][ #  # ]:      16237 :                                 for (IndexType j=0; j<k; ++j)
                 [ #  # ]
     157                 :            :                                 {
     158                 :      14747 :                                         SparseTriplet cross_triplet(current_neighbors[i],current_neighbors[j],weights(i)*weights(j));
     159                 :      14743 :                                         local_triplets.push_back(cross_triplet);
     160                 :            :                                 }
     161                 :            :                         }
     162                 :            : 
     163                 :        150 : #pragma omp critical
     164                 :            :                         {
     165                 :        150 :                                 copy(local_triplets.begin(),local_triplets.end(),back_inserter(sparse_triplets));
     166                 :            :                         }
     167                 :            :                         
     168 [ +  + ][ #  # ]:        177 :                         local_triplets.clear();
                 [ #  # ]
     169                 :            :                 }
     170                 :            :                 //UNRESTRICT_ALLOC;
     171                 :            :         }
     172                 :            : 
     173 [ +  - ][ +  - ]:          3 :         return sparse_matrix_from_triplets(sparse_triplets, end-begin, end-begin);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     174                 :            : }
     175                 :            : 
     176                 :            : template <class RandomAccessIterator, class PairwiseCallback>
     177                 :          1 : SparseWeightMatrix hessian_weight_matrix(RandomAccessIterator begin, RandomAccessIterator end, 
     178                 :            :                                          const Neighbors& neighbors, PairwiseCallback callback, 
     179                 :            :                                          const IndexType target_dimension)
     180                 :            : {
     181 [ +  - ][ +  - ]:          1 :         timed_context context("Hessian weight matrix computation");
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     182                 :          1 :         const IndexType k = neighbors[0].size();
     183                 :            : 
     184   [ +  -  #  #  :          1 :         SparseTriplets sparse_triplets;
                   #  # ]
     185 [ +  - ][ #  # ]:          1 :         sparse_triplets.reserve(k*k*(end-begin));
                 [ #  # ]
     186                 :            : 
     187                 :          1 :         const IndexType dp = target_dimension*(target_dimension+1)/2;
     188                 :            : 
     189                 :            : #pragma omp parallel shared(begin,end,neighbors,callback,sparse_triplets) default(none)
     190                 :            :         {
     191                 :            :                 IndexType index_iter;
     192                 :          4 :                 DenseMatrix gram_matrix = DenseMatrix::Zero(k,k);
     193                 :          4 :                 DenseMatrix Yi(k,1+target_dimension+dp);
     194                 :            : 
     195                 :          3 :                 SparseTriplets local_triplets;
     196                 :          3 :                 local_triplets.reserve(k*k+2*k+1);
     197                 :            : 
     198 [ +  - ][ #  # ]:          3 : #pragma omp for nowait
                 [ #  # ]
     199                 :            :                 for (index_iter=0; index_iter<static_cast<IndexType>(end-begin); index_iter++)
     200                 :            :                 {
     201                 :         50 :                         const LocalNeighbors& current_neighbors = neighbors[index_iter];
     202                 :            :                 
     203 [ +  + ][ #  # ]:        553 :                         for (IndexType i=0; i<k; ++i)
                 [ #  # ]
     204                 :            :                         {
     205 [ +  + ][ #  # ]:       3220 :                                 for (IndexType j=i; j<k; ++j)
                 [ #  # ]
     206                 :            :                                 {
     207                 :       2718 :                                         ScalarType kij = callback.kernel(begin[current_neighbors[i]],begin[current_neighbors[j]]);
     208                 :       2631 :                                         gram_matrix(i,j) = kij;
     209                 :       2659 :                                         gram_matrix(j,i) = kij;
     210                 :            :                                 }
     211                 :            :                         }
     212                 :            :                         
     213                 :         49 :                         centerMatrix(gram_matrix);
     214                 :            :                         
     215                 :         50 :                         DenseSelfAdjointEigenSolver sae_solver;
     216                 :         50 :                         sae_solver.compute(gram_matrix);
     217                 :            : 
     218                 :         50 :                         Yi.col(0).setConstant(1.0);
     219                 :         50 :                         Yi.block(0,1,k,target_dimension).noalias() = sae_solver.eigenvectors().rightCols(target_dimension);
     220                 :            : 
     221                 :         50 :                         IndexType ct = 0;
     222 [ +  + ][ #  # ]:        150 :                         for (IndexType j=0; j<target_dimension; ++j)
                 [ #  # ]
     223                 :            :                         {
     224 [ +  + ][ #  # ]:        250 :                                 for (IndexType p=0; p<target_dimension-j; ++p)
                 [ #  # ]
     225                 :            :                                 {
     226                 :        150 :                                         Yi.col(ct+p+1+target_dimension).noalias() = Yi.col(j+1).cwiseProduct(Yi.col(j+p+1));
     227                 :            :                                 }
     228                 :        100 :                                 ct += ct + target_dimension - j;
     229                 :            :                         }
     230                 :            :                         
     231 [ +  + ][ #  # ]:        349 :                         for (IndexType i=0; i<static_cast<IndexType>(Yi.cols()); i++)
                 [ #  # ]
     232                 :            :                         {
     233 [ +  + ][ #  # ]:       1039 :                                 for (IndexType j=0; j<i; j++)
                 [ #  # ]
     234                 :            :                                 {
     235                 :        741 :                                         ScalarType r = Yi.col(i).dot(Yi.col(j));
     236                 :        741 :                                         Yi.col(i) -= r*Yi.col(j);
     237                 :            :                                 }
     238                 :        298 :                                 ScalarType norm = Yi.col(i).norm();
     239                 :        300 :                                 Yi.col(i) *= (1.f / norm);
     240                 :            :                         }
     241 [ +  + ][ #  # ]:        199 :                         for (IndexType i=0; i<dp; i++)
                 [ #  # ]
     242                 :            :                         {
     243                 :        149 :                                 ScalarType colsum = Yi.col(1+target_dimension+i).sum();
     244   [ +  -  #  #  :        150 :                                 if (colsum > 1e-4)
                   #  # ]
     245                 :          0 :                                         Yi.col(1+target_dimension+i).array() /= colsum;
     246                 :            :                         }
     247                 :            : 
     248                 :            :                         // reuse gram matrix storage m'kay?
     249                 :         50 :                         gram_matrix.noalias() = Yi.rightCols(dp)*(Yi.rightCols(dp).transpose());
     250                 :            : 
     251 [ +  + ][ #  # ]:        551 :                         for (IndexType i=0; i<k; ++i)
                 [ #  # ]
     252                 :            :                         {
     253 [ +  + ][ #  # ]:       5489 :                                 for (IndexType j=0; j<k; ++j)
                 [ #  # ]
     254                 :            :                                 {
     255                 :       4990 :                                         SparseTriplet hessian_triplet(current_neighbors[i],current_neighbors[j],gram_matrix(i,j));
     256                 :       4988 :                                         local_triplets.push_back(hessian_triplet);
     257                 :            :                                 }
     258                 :            :                         }
     259                 :            : 
     260                 :         50 :                         #pragma omp critical
     261                 :            :                         {
     262                 :         50 :                                 copy(local_triplets.begin(),local_triplets.end(),back_inserter(sparse_triplets));
     263                 :            :                         }
     264                 :            : 
     265 [ +  + ][ #  # ]:         59 :                         local_triplets.clear();
                 [ #  # ]
     266                 :            :                 }
     267                 :            :         }
     268                 :            : 
     269 [ +  - ][ +  - ]:          1 :         return sparse_matrix_from_triplets(sparse_triplets, end-begin, end-begin);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     270                 :            : }
     271                 :            : 
     272                 :            : template<class RandomAccessIterator, class FeatureVectorCallback>
     273                 :          1 : DenseSymmetricMatrixPair construct_neighborhood_preserving_eigenproblem(SparseWeightMatrix W,
     274                 :            :                 RandomAccessIterator begin, RandomAccessIterator end, FeatureVectorCallback feature_vector_callback,
     275                 :            :                 IndexType dimension)
     276                 :            : {
     277 [ +  - ][ +  - ]:          1 :         timed_context context("NPE eigenproblem construction");
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     278                 :            :         
     279         [ +  - ]:          1 :         DenseSymmetricMatrix lhs = DenseSymmetricMatrix::Zero(dimension,dimension);
           [ +  -  #  # ]
           [ #  #  #  # ]
                 [ #  # ]
     280 [ +  - ][ +  - ]:          1 :         DenseSymmetricMatrix rhs = DenseSymmetricMatrix::Zero(dimension,dimension);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     281                 :            : 
     282 [ +  - ][ #  # ]:          1 :         DenseVector rank_update_vector_i(dimension);
                 [ #  # ]
     283 [ +  - ][ #  # ]:          1 :         DenseVector rank_update_vector_j(dimension);
                 [ #  # ]
     284                 :            : 
     285                 :            :         //RESTRICT_ALLOC;
     286 [ +  + ][ #  # ]:         51 :         for (RandomAccessIterator iter=begin; iter!=end; ++iter)
                 [ #  # ]
     287                 :            :         {
     288 [ +  - ][ #  # ]:         50 :                 feature_vector_callback.vector(*iter,rank_update_vector_i);
                 [ #  # ]
     289 [ +  - ][ +  - ]:         50 :                 rhs.selfadjointView<Eigen::Upper>().rankUpdate(rank_update_vector_i);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     290                 :            :         }
     291                 :            : 
     292 [ +  + ][ #  # ]:         51 :         for (int i=0; i<W.outerSize(); ++i)
                 [ #  # ]
     293                 :            :         {
     294 [ +  - ][ +  + ]:       1034 :                 for (SparseWeightMatrix::InnerIterator it(W,i); it; ++it)
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     295                 :            :                 {
     296 [ +  - ][ #  # ]:        984 :                         feature_vector_callback.vector(begin[it.row()],rank_update_vector_i);
                 [ #  # ]
     297 [ +  - ][ #  # ]:        984 :                         feature_vector_callback.vector(begin[it.col()],rank_update_vector_j);
                 [ #  # ]
     298 [ +  - ][ +  - ]:        984 :                         lhs.selfadjointView<Eigen::Upper>().rankUpdate(rank_update_vector_i, rank_update_vector_j, it.value());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     299                 :            :                 }
     300                 :            :         }
     301                 :            :         
     302 [ +  - ][ +  - ]:          1 :         rhs += rhs.transpose().eval();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     303 [ +  - ][ #  # ]:          1 :         rhs /= 2;
                 [ #  # ]
     304                 :            : 
     305                 :            :         //UNRESTRICT_ALLOC;
     306                 :            : 
     307 [ +  - ][ +  - ]:          1 :         return DenseSymmetricMatrixPair(lhs,rhs);
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     308                 :            : }
     309                 :            : 
     310                 :            : template<class RandomAccessIterator, class FeatureVectorCallback>
     311                 :          1 : DenseSymmetricMatrixPair construct_lltsa_eigenproblem(SparseWeightMatrix W,
     312                 :            :                 RandomAccessIterator begin, RandomAccessIterator end, FeatureVectorCallback feature_vector_callback,
     313                 :            :                 IndexType dimension)
     314                 :            : {
     315 [ +  - ][ +  - ]:          1 :         timed_context context("LLTSA eigenproblem construction");
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     316                 :            : 
     317         [ +  - ]:          1 :         DenseSymmetricMatrix lhs = DenseSymmetricMatrix::Zero(dimension,dimension);
           [ +  -  #  # ]
           [ #  #  #  # ]
                 [ #  # ]
     318 [ +  - ][ +  - ]:          1 :         DenseSymmetricMatrix rhs = DenseSymmetricMatrix::Zero(dimension,dimension);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     319                 :            : 
     320 [ +  - ][ #  # ]:          1 :         DenseVector rank_update_vector_i(dimension);
                 [ #  # ]
     321 [ +  - ][ #  # ]:          1 :         DenseVector rank_update_vector_j(dimension);
                 [ #  # ]
     322 [ +  - ][ +  - ]:          1 :         DenseVector sum = DenseVector::Zero(dimension);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     323                 :            :         
     324                 :            :         //RESTRICT_ALLOC;
     325 [ +  + ][ #  # ]:         51 :         for (RandomAccessIterator iter=begin; iter!=end; ++iter)
                 [ #  # ]
     326                 :            :         {
     327 [ +  - ][ #  # ]:         50 :                 feature_vector_callback.vector(*iter,rank_update_vector_i);
                 [ #  # ]
     328 [ +  - ][ #  # ]:         50 :                 sum += rank_update_vector_i;
                 [ #  # ]
     329 [ +  - ][ +  - ]:         50 :                 rhs.selfadjointView<Eigen::Upper>().rankUpdate(rank_update_vector_i);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     330                 :            :         }
     331 [ +  - ][ +  - ]:          1 :         rhs.selfadjointView<Eigen::Upper>().rankUpdate(sum,-1./(end-begin));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     332                 :            : 
     333 [ +  + ][ #  # ]:         51 :         for (int i=0; i<W.outerSize(); ++i)
                 [ #  # ]
     334                 :            :         {
     335 [ +  - ][ +  + ]:       1076 :                 for (SparseWeightMatrix::InnerIterator it(W,i); it; ++it)
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     336                 :            :                 {
     337 [ +  - ][ #  # ]:       1026 :                         feature_vector_callback.vector(begin[it.row()],rank_update_vector_i);
                 [ #  # ]
     338 [ +  - ][ #  # ]:       1026 :                         feature_vector_callback.vector(begin[it.col()],rank_update_vector_j);
                 [ #  # ]
     339 [ +  - ][ +  - ]:       1026 :                         lhs.selfadjointView<Eigen::Upper>().rankUpdate(rank_update_vector_i, rank_update_vector_j, it.value());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     340                 :            :                 }
     341                 :            :         }
     342 [ +  - ][ +  - ]:          1 :         lhs.selfadjointView<Eigen::Upper>().rankUpdate(sum,-1./(end-begin));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     343                 :            : 
     344 [ +  - ][ +  - ]:          1 :         rhs += rhs.transpose().eval();
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     345 [ +  - ][ #  # ]:          1 :         rhs /= 2;
                 [ #  # ]
     346                 :            : 
     347                 :            :         //UNRESTRICT_ALLOC;
     348                 :            : 
     349 [ +  - ][ +  - ]:          1 :         return DenseSymmetricMatrixPair(lhs,rhs);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     350                 :            : }
     351                 :            : 
     352                 :            : } // End of namespace tapkee_internal
     353                 :            : } // End of namespace tapkee
     354                 :            : 
     355                 :            : #endif

Generated by: LCOV version 1.9