| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file    Conditional.h | 
					
						
							|  |  |  |  * @brief   Base class for conditional densities | 
					
						
							|  |  |  |  * @author  Frank Dellaert | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // \callgraph
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #include <iostream>
 | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | #include <boost/utility.hpp> // for noncopyable
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #include <boost/foreach.hpp>
 | 
					
						
							|  |  |  | #include <boost/range/iterator_range.hpp>
 | 
					
						
							|  |  |  | #include <boost/serialization/nvp.hpp>
 | 
					
						
							|  |  |  | #include <gtsam/base/types.h>
 | 
					
						
							| 
									
										
										
										
											2010-08-20 01:23:19 +08:00
										 |  |  | #include <gtsam/base/Testable.h>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #include <gtsam/inference/Factor.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/Permutation.h>
 | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 22:44:53 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Base class for conditional densities | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * We make it noncopyable so we enforce the fact that factors are | 
					
						
							|  |  |  |  * kept in pointer containers. To be safe, you should make them | 
					
						
							|  |  |  |  * immutable, i.e., practicing functional programming. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class Conditional: boost::noncopyable, public Testable<Conditional> { | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | protected: | 
					
						
							|  |  |  |   /** Conditional just uses an internal Factor for storage (a conditional is
 | 
					
						
							|  |  |  |    * really just a special factor anyway, but we do this instead of inherit | 
					
						
							|  |  |  |    * to prevent "diamond" inheritance with GaussianFactor and | 
					
						
							|  |  |  |    * GaussianConditional. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   Factor factor_; | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   /** The first nFrontal variables are frontal and the rest are parents. */ | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   size_t nrFrontals_; | 
					
						
							| 
									
										
										
										
											2009-11-10 22:55:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   ValueWithDefault<bool, true> permuted_; | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   /** convenience typename for a shared pointer to this class */ | 
					
						
							|  |  |  |   typedef gtsam::Factor FactorType; | 
					
						
							|  |  |  |   typedef boost::shared_ptr<Conditional> shared_ptr; | 
					
						
							|  |  |  |   typedef Factor::iterator iterator; | 
					
						
							|  |  |  |   typedef Factor::const_iterator const_iterator; | 
					
						
							|  |  |  |   typedef boost::iterator_range<const_iterator> Frontals; | 
					
						
							|  |  |  |   typedef boost::iterator_range<const_iterator> Parents; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** Empty Constructor to make serialization possible */ | 
					
						
							|  |  |  |   Conditional(){} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** No parents */ | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   Conditional(Index key) : factor_(key), nrFrontals_(1) {} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** Single parent */ | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   Conditional(Index key, Index parent) : factor_(key, parent), nrFrontals_(1) {} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** Two parents */ | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   Conditional(Index key, Index parent1, Index parent2) : factor_(key, parent1, parent2), nrFrontals_(1) {} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** Three parents */ | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   Conditional(Index key, Index parent1, Index parent2, Index parent3) : factor_(key, parent1, parent2, parent3), nrFrontals_(1) {} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** Constructor from a frontal variable and a vector of parents */ | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   Conditional(Index key, const std::vector<Index>& parents) : nrFrontals_(1) { | 
					
						
							|  |  |  | 			factor_.keys_.resize(1 + parents.size()); | 
					
						
							|  |  |  | 			*(beginFrontals()) = key; | 
					
						
							|  |  |  | 			std::copy(parents.begin(), parents.end(), beginParents()); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   /** Named constructor from any number of frontal variables and parents */ | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   template<typename Iterator> | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   static shared_ptr fromRange(Iterator firstKey, Iterator lastKey, size_t nrFrontals) { | 
					
						
							|  |  |  |   	shared_ptr conditional(new Conditional); | 
					
						
							|  |  |  |   	conditional->nrFrontals_ = nrFrontals; | 
					
						
							|  |  |  | 		std::copy(firstKey, lastKey, back_inserter(conditional->factor_.keys_)); | 
					
						
							|  |  |  | 		return conditional; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   /** check equality */ | 
					
						
							|  |  |  |   bool equals(const Conditional& c, double tol = 1e-9) const { | 
					
						
							|  |  |  |     return nrFrontals_ == c.nrFrontals_ && factor_.equals(c.factor_, tol); } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  | 	/** return the number of frontals */ | 
					
						
							|  |  |  | 	size_t nrFrontals() const { return nrFrontals_; } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  | 	/** return the number of parents */ | 
					
						
							|  |  |  | 	size_t nrParents() const { return factor_.keys_.size() - nrFrontals_; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** Special accessor when there is only one frontal variable. */ | 
					
						
							|  |  |  | 	Index key() const { assert(nrFrontals_==1); return factor_.keys_[0]; } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** return a const reference to all keys */ | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |   const std::vector<Index>& keys() const { return factor_.keys(); } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   /** Iterators over frontal and parent variables. */ | 
					
						
							|  |  |  |   const_iterator beginFrontals() const { return factor_.keys_.begin(); } | 
					
						
							|  |  |  |   const_iterator endFrontals() const { return factor_.keys_.begin()+nrFrontals_; } | 
					
						
							|  |  |  |   const_iterator beginParents() const { return factor_.keys_.begin()+nrFrontals_; } | 
					
						
							|  |  |  |   const_iterator endParents() const { return factor_.keys_.end(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** Mutable iterators and accessors */ | 
					
						
							|  |  |  |   iterator beginFrontals() { return factor_.keys_.begin(); } | 
					
						
							|  |  |  |   iterator endFrontals() { return factor_.keys_.begin()+nrFrontals_; } | 
					
						
							|  |  |  |   iterator beginParents() { return factor_.keys_.begin()+nrFrontals_; } | 
					
						
							|  |  |  |   iterator endParents() { return factor_.keys_.end(); } | 
					
						
							|  |  |  |   boost::iterator_range<iterator> frontals() { return boost::make_iterator_range(beginFrontals(), endFrontals()); } | 
					
						
							|  |  |  |   boost::iterator_range<iterator> parents() { return boost::make_iterator_range(beginParents(), endParents()); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   /** return a view of the frontal keys */ | 
					
						
							|  |  |  |   Frontals frontals() const { | 
					
						
							|  |  |  |     return boost::make_iterator_range(beginFrontals(), endFrontals()); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** return a view of the parent keys */ | 
					
						
							|  |  |  | 	Parents parents() const { | 
					
						
							|  |  |  | 	  return boost::make_iterator_range(beginParents(), endParents()); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** print */ | 
					
						
							|  |  |  |   void print(const std::string& s = "Conditional") const { | 
					
						
							|  |  |  |     std::cout << s << " P("; | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |     BOOST_FOREACH(Index key, frontals()) std::cout << " " << key; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     if (nrParents()>0) std::cout << " |"; | 
					
						
							| 
									
										
										
										
											2010-10-12 05:14:35 +08:00
										 |  |  |     BOOST_FOREACH(Index parent, parents()) std::cout << " " << parent; | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |     std::cout << ")" << std::endl; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   /** Permute the variables when only separator variables need to be permuted.
 | 
					
						
							|  |  |  |    * Returns true if any reordered variables appeared in the separator and | 
					
						
							|  |  |  |    * false if not. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   bool permuteSeparatorWithInverse(const Permutation& inversePermutation) { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |     BOOST_FOREACH(Index key, frontals()) { assert(key == inversePermutation[key]); } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     bool parentChanged = false; | 
					
						
							|  |  |  |     BOOST_FOREACH(Index& parent, parents()) { | 
					
						
							|  |  |  |       Index newParent = inversePermutation[parent]; | 
					
						
							|  |  |  |       if(parent != newParent) { | 
					
						
							|  |  |  |         parentChanged = true; | 
					
						
							|  |  |  |         parent = newParent; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return parentChanged; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |   /**
 | 
					
						
							|  |  |  |    * Permutes the Conditional, but for efficiency requires the permutation | 
					
						
							|  |  |  |    * to already be inverted. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   void permuteWithInverse(const Permutation& inversePermutation) { | 
					
						
							|  |  |  |     factor_.permuteWithInverse(inversePermutation); } | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | protected: | 
					
						
							|  |  |  |   /** Debugging invariant that the keys should be in order, including that the
 | 
					
						
							|  |  |  |    * conditioned variable is numbered lower than the parents. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   void checkSorted() const; | 
					
						
							| 
									
										
										
										
											2009-11-08 03:31:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  |   friend class Factor; | 
					
						
							| 
									
										
										
										
											2009-11-08 03:31:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 22:44:53 +08:00
										 |  |  | private: | 
					
						
							|  |  |  | 	/** Serialization function */ | 
					
						
							|  |  |  | 	friend class boost::serialization::access; | 
					
						
							|  |  |  | 	template<class Archive> | 
					
						
							|  |  |  | 	void serialize(Archive & ar, const unsigned int version) { | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | 		ar & BOOST_SERIALIZATION_NVP(factor_); | 
					
						
							| 
									
										
										
										
											2010-10-12 08:14:50 +08:00
										 |  |  |     ar & BOOST_SERIALIZATION_NVP(nrFrontals_); | 
					
						
							| 
									
										
										
										
											2009-11-10 22:44:53 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-11-08 03:31:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 11:50:30 +08:00
										 |  |  | } |