BayesNet is now list-based for fast bi-directional access
SLOW O(n) random access operator[key] provided (should maybe be called [at] as it does bounds checking) I also fixed a bug in equals.release/4.3a0
							parent
							
								
									eab038651e
								
							
						
					
					
						commit
						e9d942f81e
					
				| 
						 | 
				
			
			@ -490,9 +490,10 @@
 | 
			
		|||
<useDefaultCommand>false</useDefaultCommand>
 | 
			
		||||
<runAllBuilders>true</runAllBuilders>
 | 
			
		||||
</target>
 | 
			
		||||
<target name="testSymbolicBayesChain.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
 | 
			
		||||
<target name="testSymbolicBayesNet.run" path="cpp" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
 | 
			
		||||
<buildCommand>make</buildCommand>
 | 
			
		||||
<buildTarget>testSymbolicBayesChain.run</buildTarget>
 | 
			
		||||
<buildArguments/>
 | 
			
		||||
<buildTarget>testSymbolicBayesNet.run</buildTarget>
 | 
			
		||||
<stopOnError>true</stopOnError>
 | 
			
		||||
<useDefaultCommand>false</useDefaultCommand>
 | 
			
		||||
<runAllBuilders>true</runAllBuilders>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,29 +30,8 @@ namespace gtsam {
 | 
			
		|||
	/* ************************************************************************* */
 | 
			
		||||
	template<class Conditional>
 | 
			
		||||
	bool BayesNet<Conditional>::equals(const BayesNet& cbn, double tol) const {
 | 
			
		||||
		if(indices_ != cbn.indices_) return false;
 | 
			
		||||
		if(size() != cbn.size()) return false;
 | 
			
		||||
		return equal(conditionals_.begin(),conditionals_.begin(),conditionals_.begin(),equals_star<Conditional>);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
	template<class Conditional>
 | 
			
		||||
	void BayesNet<Conditional>::push_back
 | 
			
		||||
		(const boost::shared_ptr<Conditional>& conditional) {
 | 
			
		||||
		indices_.insert(make_pair(conditional->key(),conditionals_.size()));
 | 
			
		||||
		conditionals_.push_back(conditional);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* *
 | 
			
		||||
	template<class Conditional>
 | 
			
		||||
	void BayesNet<Conditional>::erase(const string& key) {
 | 
			
		||||
		list<string>::iterator it;
 | 
			
		||||
		for (it=keys_.begin(); it != keys_.end(); ++it){
 | 
			
		||||
		  if( strcmp(key.c_str(), (*it).c_str()) == 0 )
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		keys_.erase(it);
 | 
			
		||||
		conditionals_.erase(key);
 | 
			
		||||
		return equal(conditionals_.begin(),conditionals_.end(),cbn.conditionals_.begin(),equals_star<Conditional>(tol));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			@ -65,5 +44,24 @@ namespace gtsam {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
	// predicate to check whether a conditional has the sought key
 | 
			
		||||
	template<class Conditional>
 | 
			
		||||
	class HasKey {
 | 
			
		||||
		const string& key_;
 | 
			
		||||
	public:
 | 
			
		||||
		HasKey(const std::string& key):key_(key) {}
 | 
			
		||||
		bool operator()(const boost::shared_ptr<Conditional>& conditional) {
 | 
			
		||||
			return (conditional->key()==key_);
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	template<class Conditional>
 | 
			
		||||
	boost::shared_ptr<Conditional> BayesNet<Conditional>::operator[](const std::string& key) const {
 | 
			
		||||
		const_iterator it = find_if(conditionals_.begin(),conditionals_.end(),HasKey<Conditional>(key));
 | 
			
		||||
		if (it == conditionals_.end()) throw(invalid_argument(
 | 
			
		||||
						"BayesNet::operator['"+key+"']: not found"));
 | 
			
		||||
		return *it;
 | 
			
		||||
	}
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
 | 
			
		||||
} // namespace gtsam
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,10 +8,9 @@
 | 
			
		|||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <boost/shared_ptr.hpp>
 | 
			
		||||
#include <boost/serialization/map.hpp>
 | 
			
		||||
#include <boost/serialization/vector.hpp>
 | 
			
		||||
#include <boost/serialization/list.hpp>
 | 
			
		||||
#include <boost/serialization/shared_ptr.hpp>
 | 
			
		||||
 | 
			
		||||
#include "Testable.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +32,8 @@ namespace gtsam {
 | 
			
		|||
 | 
			
		||||
		/** We store shared pointers to Conditional densities */
 | 
			
		||||
		typedef typename boost::shared_ptr<Conditional> conditional_ptr;
 | 
			
		||||
		typedef typename std::vector<conditional_ptr> Conditionals;
 | 
			
		||||
		typedef typename std::list<conditional_ptr> Conditionals;
 | 
			
		||||
 | 
			
		||||
		typedef typename Conditionals::const_iterator const_iterator;
 | 
			
		||||
		typedef typename Conditionals::const_reverse_iterator const_reverse_iterator;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -46,19 +46,6 @@ namespace gtsam {
 | 
			
		|||
		 */
 | 
			
		||||
		Conditionals conditionals_;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 *   O(log n) random access on keys will provided by a map from keys to vector index.
 | 
			
		||||
		 */
 | 
			
		||||
		typedef std::map<std::string, int> Indices;
 | 
			
		||||
		Indices indices_;
 | 
			
		||||
 | 
			
		||||
		/** O(log n) lookup from key to node index */
 | 
			
		||||
		inline int index(const std::string& key) const {
 | 
			
		||||
			Indices::const_iterator it = indices_.find(key); // get node index
 | 
			
		||||
			assert( it != indices_.end() );
 | 
			
		||||
			return it->second;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	public:
 | 
			
		||||
 | 
			
		||||
		/** print */
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +55,14 @@ namespace gtsam {
 | 
			
		|||
		bool equals(const BayesNet& other, double tol = 1e-9) const;
 | 
			
		||||
 | 
			
		||||
		/** push_back: use reverse topological sort (i.e. parents last / elimination order) */
 | 
			
		||||
		void push_back(const boost::shared_ptr<Conditional>& conditional);
 | 
			
		||||
		inline void push_back(const boost::shared_ptr<Conditional>& conditional) {
 | 
			
		||||
			conditionals_.push_back(conditional);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/** push_front: use topological sort (i.e. parents first / reverse elimination order) */
 | 
			
		||||
		inline void push_front(const boost::shared_ptr<Conditional>& conditional) {
 | 
			
		||||
			conditionals_.push_front(conditional);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/** size is the number of nodes */
 | 
			
		||||
		inline size_t size() const {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,11 +72,8 @@ namespace gtsam {
 | 
			
		|||
		/** return keys in reverse topological sort order, i.e., elimination order */
 | 
			
		||||
		Ordering ordering() const;
 | 
			
		||||
 | 
			
		||||
		/** O(log n) random access to Conditional by key */
 | 
			
		||||
		inline conditional_ptr operator[](const std::string& key) const {
 | 
			
		||||
			int i = index(key);
 | 
			
		||||
			return conditionals_[i];
 | 
			
		||||
		}
 | 
			
		||||
		/** SLOW O(n) random access to Conditional by key */
 | 
			
		||||
		conditional_ptr operator[](const std::string& key) const;
 | 
			
		||||
 | 
			
		||||
		/** return iterators. FD: breaks encapsulation? */
 | 
			
		||||
		const_iterator const begin() const {return conditionals_.begin();}
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +87,6 @@ namespace gtsam {
 | 
			
		|||
		template<class Archive>
 | 
			
		||||
		void serialize(Archive & ar, const unsigned int version) {
 | 
			
		||||
			ar & BOOST_SERIALIZATION_NVP(conditionals_);
 | 
			
		||||
			ar & BOOST_SERIALIZATION_NVP(indices_);
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,9 +50,8 @@ namespace gtsam {
 | 
			
		|||
	template<class Conditional>
 | 
			
		||||
	BayesTree<Conditional>::BayesTree(const BayesNet<Conditional>& bayesNet, bool verbose) {
 | 
			
		||||
		typename BayesNet<Conditional>::const_reverse_iterator rit;
 | 
			
		||||
		for ( rit=bayesNet.rbegin(); rit < bayesNet.rend(); ++rit ) {
 | 
			
		||||
		for ( rit=bayesNet.rbegin(); rit != bayesNet.rend(); ++rit )
 | 
			
		||||
			insert(*rit,verbose);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +68,7 @@ namespace gtsam {
 | 
			
		|||
			double tol) const {
 | 
			
		||||
		return size()==other.size() &&
 | 
			
		||||
		equal(nodeMap_.begin(),nodeMap_.end(),other.nodeMap_.begin()) &&
 | 
			
		||||
		equal(nodes_.begin(),nodes_.end(),other.nodes_.begin(),equals_star<Node>);
 | 
			
		||||
		equal(nodes_.begin(),nodes_.end(),other.nodes_.begin(),equals_star<Node>(tol));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			@ -106,7 +105,7 @@ namespace gtsam {
 | 
			
		|||
		if (parent_clique->size() == parents.size()) {
 | 
			
		||||
			if (verbose) cout << "Adding to clique " << index << endl;
 | 
			
		||||
			nodeMap_.insert(make_pair(key, index));
 | 
			
		||||
			parent_clique->push_back(conditional);
 | 
			
		||||
			parent_clique->push_front(conditional);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ using namespace gtsam;
 | 
			
		|||
typedef pair<const string, Matrix>& mypair;
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
LinearFactor::LinearFactor(const boost::shared_ptr<ConditionalGaussian> cg) :
 | 
			
		||||
LinearFactor::LinearFactor(const boost::shared_ptr<ConditionalGaussian>& cg) :
 | 
			
		||||
	b(cg->get_d()) {
 | 
			
		||||
	As.insert(make_pair(cg->key(), cg->get_R()));
 | 
			
		||||
	std::map<std::string, Matrix>::const_iterator it = cg->parentsBegin();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ public:
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/** Construct from Conditional Gaussian */
 | 
			
		||||
	LinearFactor(const boost::shared_ptr<ConditionalGaussian> cg);
 | 
			
		||||
	LinearFactor(const boost::shared_ptr<ConditionalGaussian>& cg);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Constructor that combines a set of factors
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,7 +65,8 @@ namespace gtsam {
 | 
			
		|||
 | 
			
		||||
		/** print */
 | 
			
		||||
		void print(const std::string& s = "SymbolicConditional") const {
 | 
			
		||||
			std::cout << s << " P(" << key_ << " |";
 | 
			
		||||
			std::cout << s << " P(" << key_;
 | 
			
		||||
			if (parents_.size()>0) std::cout << " |";
 | 
			
		||||
			BOOST_FOREACH(std::string parent, parents_) std::cout << " " << parent;
 | 
			
		||||
			std::cout << ")" << std::endl;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,17 +55,24 @@ namespace gtsam {
 | 
			
		|||
	 * Template to create a binary predicate
 | 
			
		||||
	 */
 | 
			
		||||
	template<class V>
 | 
			
		||||
	bool equals(const V& expected, const V& actual, double tol = 1e-9) {
 | 
			
		||||
		return (actual.equals(expected, tol));
 | 
			
		||||
	}
 | 
			
		||||
	struct equals : public std::binary_function<const V&, const V&, bool> {
 | 
			
		||||
		double tol_;
 | 
			
		||||
		equals(double tol = 1e-9) : tol_(tol) {}
 | 
			
		||||
		bool operator()(const V& expected, const V& actual) {
 | 
			
		||||
			return (actual.equals(expected, tol_));
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Binary predicate on shared pointers
 | 
			
		||||
	 */
 | 
			
		||||
	template<class V>
 | 
			
		||||
	bool equals_star(const boost::shared_ptr<V>& expected,
 | 
			
		||||
			const boost::shared_ptr<V>& actual, double tol = 1e-9) {
 | 
			
		||||
		return (actual->equals(*expected, tol));
 | 
			
		||||
	}
 | 
			
		||||
	struct equals_star : public std::binary_function<const boost::shared_ptr<V>&, const boost::shared_ptr<V>&, bool> {
 | 
			
		||||
		double tol_;
 | 
			
		||||
		equals_star(double tol = 1e-9) : tol_(tol) {}
 | 
			
		||||
		bool operator()(const boost::shared_ptr<V>& expected, const boost::shared_ptr<V>& actual) {
 | 
			
		||||
			return (actual->equals(*expected, tol_));
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
} // gtsam
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,9 +54,9 @@ TEST( BayesTree, constructor )
 | 
			
		|||
 | 
			
		||||
	// Check root
 | 
			
		||||
	BayesNet<SymbolicConditional> expected_root;
 | 
			
		||||
	expected_root.push_back(B);
 | 
			
		||||
	expected_root.push_back(L);
 | 
			
		||||
	expected_root.push_back(E);
 | 
			
		||||
	expected_root.push_back(L);
 | 
			
		||||
	expected_root.push_back(B);
 | 
			
		||||
	BayesNet<SymbolicConditional> actual_root = bayesTree.root();
 | 
			
		||||
	CHECK(assert_equal(expected_root,actual_root));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ TEST( BayesTree, constructor )
 | 
			
		|||
	ASIA.push_back(E);
 | 
			
		||||
	ASIA.push_back(L);
 | 
			
		||||
	ASIA.push_back(B);
 | 
			
		||||
	bool verbose = true;
 | 
			
		||||
	bool verbose = false;
 | 
			
		||||
	BayesTree<SymbolicConditional> bayesTree2(ASIA,verbose);
 | 
			
		||||
	if (verbose) bayesTree2.print("bayesTree2");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue