| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file summarization.cpp | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @date Jun 22, 2012 | 
					
						
							|  |  |  |  * @author Alex Cunningham | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gtsam_unstable/linear/conditioning.h>
 | 
					
						
							|  |  |  | #include <gtsam_unstable/linear/bayesTreeOperations.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  | GaussianConditionalOrdered::shared_ptr conditionDensity(const GaussianConditionalOrdered::shared_ptr& initConditional, | 
					
						
							|  |  |  |     const std::set<Index>& saved_indices, const VectorValuesOrdered& solution) { | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  |   const bool verbose = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!initConditional) | 
					
						
							|  |  |  |     return initConditional; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (verbose) { | 
					
						
							|  |  |  |     cout << "backsubSummarize() Starting" << endl; | 
					
						
							|  |  |  |     initConditional->print("Full initial conditional"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Check for presence of variables to remove
 | 
					
						
							|  |  |  |   std::set<Index> frontalsToRemove, parentsToRemove; | 
					
						
							|  |  |  |   BOOST_FOREACH(const Index& frontal, initConditional->frontals()) | 
					
						
							|  |  |  |     if (!saved_indices.count(frontal)) | 
					
						
							|  |  |  |       frontalsToRemove.insert(frontal); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BOOST_FOREACH(const Index& parent, initConditional->parents()) | 
					
						
							|  |  |  |     if (!saved_indices.count(parent)) | 
					
						
							|  |  |  |       parentsToRemove.insert(parent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // If all variables in this conditional are to be saved, just return initial conditional
 | 
					
						
							|  |  |  |   if (frontalsToRemove.empty() && parentsToRemove.empty()) | 
					
						
							|  |  |  |     return initConditional; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // If none of the frontal variables are to be saved, return empty pointer
 | 
					
						
							|  |  |  |   if (frontalsToRemove.size() == initConditional->nrFrontals()) | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |     return GaussianConditionalOrdered::shared_ptr(); | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Collect dimensions of the new conditional
 | 
					
						
							|  |  |  |   if (verbose) cout << "  Collecting dimensions" << endl; | 
					
						
							|  |  |  |   size_t newTotalRows = 0, newTotalCols = 1; // Need spacing for RHS
 | 
					
						
							|  |  |  |   size_t newNrFrontals = 0; | 
					
						
							|  |  |  |   size_t oldOffset = 0; | 
					
						
							|  |  |  |   vector<size_t> newDims, oldDims; | 
					
						
							|  |  |  |   vector<size_t> oldColOffsets; | 
					
						
							|  |  |  |   vector<Index> newIndices; | 
					
						
							|  |  |  |   vector<size_t> newIdxToOldIdx; // Access to arrays, maps from new var to old var
 | 
					
						
							|  |  |  |   const vector<Index>& oldIndices = initConditional->keys(); | 
					
						
							|  |  |  |   const size_t oldNrFrontals = initConditional->nrFrontals(); | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |   GaussianConditionalOrdered::const_iterator varIt = initConditional->beginFrontals(); | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  |   size_t oldIdx = 0; | 
					
						
							|  |  |  |   for (; varIt != initConditional->endFrontals(); ++varIt) { | 
					
						
							|  |  |  |     size_t varDim = initConditional->dim(varIt); | 
					
						
							|  |  |  |     oldDims += varDim; | 
					
						
							|  |  |  |     if (!frontalsToRemove.count(*varIt)) { | 
					
						
							|  |  |  |       newTotalCols += varDim; | 
					
						
							|  |  |  |       newTotalRows += varDim; | 
					
						
							|  |  |  |       newDims += varDim; | 
					
						
							|  |  |  |       newIndices += *varIt; | 
					
						
							|  |  |  |       ++newNrFrontals; | 
					
						
							|  |  |  |       newIdxToOldIdx += oldIdx; | 
					
						
							|  |  |  |       oldColOffsets += oldOffset; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     oldOffset += varDim; | 
					
						
							|  |  |  |     ++oldIdx; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   varIt = initConditional->beginParents(); | 
					
						
							|  |  |  |   for (; varIt != initConditional->endParents(); ++varIt) { | 
					
						
							|  |  |  |     size_t varDim = initConditional->dim(varIt); | 
					
						
							|  |  |  |     oldDims += varDim; | 
					
						
							|  |  |  |     if (!parentsToRemove.count(*varIt)) { | 
					
						
							|  |  |  |       newTotalCols += varDim; | 
					
						
							|  |  |  |       newDims += varDim; | 
					
						
							|  |  |  |       newIndices += *varIt; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   newDims += 1; // For the RHS
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Initialize new conditional
 | 
					
						
							|  |  |  |   Matrix full_matrix = Matrix::Zero(newTotalRows, newTotalCols); | 
					
						
							|  |  |  |   Vector sigmas = zero(newTotalRows); | 
					
						
							|  |  |  |   if (verbose) cout << "  Initializing new conditional\nfull_matrix:\n" << full_matrix << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Fill in full matrix - iterate over rows for each sub-conditional
 | 
					
						
							|  |  |  |   const size_t oldRNrCols = initConditional->get_R().cols(); | 
					
						
							|  |  |  |   size_t newColOffset = 0; | 
					
						
							|  |  |  |   for (size_t newfrontalIdx=0; newfrontalIdx<newNrFrontals; ++newfrontalIdx) { | 
					
						
							|  |  |  |     const size_t& dim = newDims.at(newfrontalIdx); | 
					
						
							|  |  |  |     if (verbose) cout << "     Filling in Matrix: newfrontalIdx " << newfrontalIdx | 
					
						
							|  |  |  |         << " frontalKey: " << newIndices[newfrontalIdx] << " dim: " << dim << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     size_t oldColOffset = oldColOffsets.at(newfrontalIdx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // get R block, sliced by row
 | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |     Eigen::Block<GaussianConditionalOrdered::rsd_type::constBlock> rblock = | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  |         initConditional->get_R().block(oldColOffset, oldColOffset, dim, oldRNrCols-oldColOffset); | 
					
						
							|  |  |  |     if (verbose) cout << "   rblock\n" << rblock << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // set the R matrix for this var
 | 
					
						
							|  |  |  |     full_matrix.block(newColOffset, newColOffset, dim, dim) = rblock.leftCols(dim); | 
					
						
							|  |  |  |     if (verbose) cout << "   full_matrix: set R\n" << full_matrix << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // set RHS
 | 
					
						
							|  |  |  |     full_matrix.block(newColOffset, newTotalCols-1, dim, 1) = initConditional->get_d().segment(oldColOffset, dim); | 
					
						
							|  |  |  |     if (verbose) cout << "   full_matrix: set rhs\n" << full_matrix << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // set sigmas
 | 
					
						
							|  |  |  |     sigmas.segment(newColOffset, dim) = initConditional->get_sigmas().segment(oldColOffset, dim); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // add parents in R block, while updating rhs
 | 
					
						
							|  |  |  |     // Loop through old variable list
 | 
					
						
							|  |  |  |     size_t newParentStartCol = newColOffset + dim; | 
					
						
							|  |  |  |     size_t oldParentStartCol = dim; // Copying from Rblock - offset already accounted for
 | 
					
						
							|  |  |  |     for (size_t oldIdx = newIdxToOldIdx[newfrontalIdx]+1; oldIdx<oldNrFrontals; ++oldIdx) { | 
					
						
							|  |  |  |       Index parentKey = oldIndices[oldIdx]; | 
					
						
							|  |  |  |       size_t parentDim = oldDims[oldIdx]; | 
					
						
							|  |  |  |       if (verbose) cout << "   Adding parents from R: parentKey: " << parentKey << " parentDim: " << parentDim << endl; | 
					
						
							|  |  |  |       if (!frontalsToRemove.count(parentKey)) { | 
					
						
							|  |  |  |         if (verbose) { | 
					
						
							|  |  |  |           cout << "         Copying block (from): oldParentStartCol " << oldParentStartCol << endl; | 
					
						
							|  |  |  |           cout << "         Copying block   (to): newColOffset " << newColOffset << ", newParentStartCol " << newParentStartCol << endl; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         full_matrix.block(newColOffset, newParentStartCol, dim, parentDim) | 
					
						
							|  |  |  |             = rblock.middleCols(oldParentStartCol, parentDim); | 
					
						
							|  |  |  |         newParentStartCol += parentDim; | 
					
						
							|  |  |  |         if (verbose) cout << "      full_matrix: add parent from R\n" << full_matrix << endl; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         const Vector& parentSol = solution.at(parentKey); | 
					
						
							|  |  |  |         full_matrix.block(newColOffset, newTotalCols-1, dim, 1) -= | 
					
						
							|  |  |  |             rblock.middleCols(oldParentStartCol, parentDim) * parentSol; | 
					
						
							|  |  |  |         if (verbose) cout << "      full_matrix: update rhs from parent in R\n" << full_matrix << endl; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       oldParentStartCol += parentDim; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // add parents (looping over original block structure), while updating rhs
 | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |     GaussianConditionalOrdered::const_iterator oldParent = initConditional->beginParents(); | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  |     for (; oldParent != initConditional->endParents(); ++oldParent) { | 
					
						
							|  |  |  |       Index parentKey = *oldParent; | 
					
						
							|  |  |  |       size_t parentDim = initConditional->dim(oldParent); | 
					
						
							|  |  |  |       if (verbose) cout << "   Adding parents from S: parentKey: " << parentKey << " parentDim: " << parentDim << endl; | 
					
						
							|  |  |  |       if (parentsToRemove.count(parentKey)) { | 
					
						
							|  |  |  |         // Solve out the variable
 | 
					
						
							|  |  |  |         const Vector& parentSol = solution.at(parentKey); | 
					
						
							|  |  |  |         assert((size_t)parentSol.size() == parentDim); | 
					
						
							|  |  |  |         full_matrix.block(newColOffset, newTotalCols-1, dim, 1) -= | 
					
						
							|  |  |  |           initConditional->get_S(oldParent).middleRows(oldColOffset, dim) * parentSol; | 
					
						
							|  |  |  |         if (verbose) cout << "      full_matrix: update rhs from parent in S\n" << full_matrix << endl; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         // Copy the matrix block
 | 
					
						
							|  |  |  |         full_matrix.block(newColOffset, newParentStartCol, dim, parentDim) = | 
					
						
							|  |  |  |             initConditional->get_S(oldParent).middleRows(oldColOffset, dim); | 
					
						
							|  |  |  |         if (verbose) cout << "      full_matrix: add parent from S\n" << full_matrix << endl; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Increment the rows
 | 
					
						
							|  |  |  |     newColOffset += dim; | 
					
						
							|  |  |  |     oldColOffset += dim; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Construct a new conditional
 | 
					
						
							|  |  |  |   if (verbose) cout << "backsubSummarize() Complete!" << endl; | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |   GaussianConditionalOrdered::rsd_type matrices(full_matrix, newDims.begin(), newDims.end()); | 
					
						
							|  |  |  |   return GaussianConditionalOrdered::shared_ptr(new | 
					
						
							|  |  |  |       GaussianConditionalOrdered(newIndices.begin(), newIndices.end(), newNrFrontals, matrices, sigmas)); | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  | GaussianFactorGraphOrdered conditionDensity(const GaussianBayesTreeOrdered& bayesTree, | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  |     const std::set<Index>& saved_indices) { | 
					
						
							|  |  |  |   const bool verbose = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |   VectorValuesOrdered solution = optimize(bayesTree); | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // FIXME: set of conditionals does not manage possibility of solving out whole separators
 | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |   std::set<GaussianConditionalOrdered::shared_ptr> affected_cliques = findAffectedCliqueConditionals(bayesTree, saved_indices); | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Summarize conditionals separately
 | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |   GaussianFactorGraphOrdered summarized_graph; | 
					
						
							|  |  |  |   BOOST_FOREACH(const GaussianConditionalOrdered::shared_ptr& conditional, affected_cliques) { | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  |     if (verbose) conditional->print("Initial conditional"); | 
					
						
							| 
									
										
										
										
											2013-07-30 07:55:40 +08:00
										 |  |  |     GaussianConditionalOrdered::shared_ptr reducedConditional = conditionDensity(conditional, saved_indices, solution); | 
					
						
							| 
									
										
										
										
											2013-03-24 04:19:36 +08:00
										 |  |  |     if (reducedConditional) { | 
					
						
							|  |  |  |       if (verbose) reducedConditional->print("Final conditional"); | 
					
						
							|  |  |  |       summarized_graph.push_back(reducedConditional->toFactor()); | 
					
						
							|  |  |  |     } else if (verbose) { | 
					
						
							|  |  |  |       cout << "Conditional removed after summarization!" << endl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return summarized_graph; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // \namespace gtsam
 | 
					
						
							|  |  |  | 
 |