Formatting
parent
e2d49922d2
commit
22b7d8276a
|
@ -1,19 +1,19 @@
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||||
* Atlanta, Georgia 30332-0415
|
* Atlanta, Georgia 30332-0415
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||||
|
|
||||||
* See LICENSE for the license information
|
* See LICENSE for the license information
|
||||||
|
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file treeTraversal-inst.h
|
* @file treeTraversal-inst.h
|
||||||
* @author Richard Roberts
|
* @author Richard Roberts
|
||||||
* @date April 9, 2013
|
* @date April 9, 2013
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gtsam/base/treeTraversal/parallelTraversalTasks.h>
|
#include <gtsam/base/treeTraversal/parallelTraversalTasks.h>
|
||||||
|
@ -33,31 +33,33 @@
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
/** Internal functions used for traversing trees */
|
/** Internal functions used for traversing trees */
|
||||||
namespace treeTraversal {
|
namespace treeTraversal {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
namespace {
|
namespace {
|
||||||
// Internal node used in DFS preorder stack
|
// Internal node used in DFS preorder stack
|
||||||
template<typename NODE, typename DATA>
|
template<typename NODE, typename DATA>
|
||||||
struct TraversalNode {
|
struct TraversalNode {
|
||||||
bool expanded;
|
bool expanded;
|
||||||
const boost::shared_ptr<NODE>& treeNode;
|
const boost::shared_ptr<NODE>& treeNode;
|
||||||
DATA& parentData;
|
DATA& parentData;
|
||||||
typename FastList<DATA>::iterator dataPointer;
|
typename FastList<DATA>::iterator dataPointer;
|
||||||
TraversalNode(const boost::shared_ptr<NODE>& _treeNode, DATA& _parentData) :
|
TraversalNode(const boost::shared_ptr<NODE>& _treeNode, DATA& _parentData) :
|
||||||
expanded(false), treeNode(_treeNode), parentData(_parentData) {}
|
expanded(false), treeNode(_treeNode), parentData(_parentData) {
|
||||||
};
|
|
||||||
|
|
||||||
// Do nothing - default argument for post-visitor for tree traversal
|
|
||||||
struct no_op {
|
|
||||||
template<typename NODE, typename DATA>
|
|
||||||
void operator()(const boost::shared_ptr<NODE>& node, const DATA& data) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** Traverse a forest depth-first with pre-order and post-order visits.
|
// Do nothing - default argument for post-visitor for tree traversal
|
||||||
|
struct no_op {
|
||||||
|
template<typename NODE, typename DATA>
|
||||||
|
void operator()(const boost::shared_ptr<NODE>& node, const DATA& data) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Traverse a forest depth-first with pre-order and post-order visits.
|
||||||
* @param forest The forest of trees to traverse. The method \c forest.roots() should exist
|
* @param forest The forest of trees to traverse. The method \c forest.roots() should exist
|
||||||
* and return a collection of (shared) pointers to \c FOREST::Node.
|
* and return a collection of (shared) pointers to \c FOREST::Node.
|
||||||
* @param visitorPre \c visitorPre(node, parentData) will be called at every node, before
|
* @param visitorPre \c visitorPre(node, parentData) will be called at every node, before
|
||||||
|
@ -71,9 +73,10 @@ namespace gtsam {
|
||||||
* call to \c visitorPre (the \c DATA object may be modified by visiting the children).
|
* call to \c visitorPre (the \c DATA object may be modified by visiting the children).
|
||||||
* @param rootData The data to pass by reference to \c visitorPre when it is called on each
|
* @param rootData The data to pass by reference to \c visitorPre when it is called on each
|
||||||
* root node. */
|
* root node. */
|
||||||
template<class FOREST, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
|
template<class FOREST, typename DATA, typename VISITOR_PRE,
|
||||||
void DepthFirstForest(FOREST& forest, DATA& rootData, VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost)
|
typename VISITOR_POST>
|
||||||
{
|
void DepthFirstForest(FOREST& forest, DATA& rootData, VISITOR_PRE& visitorPre,
|
||||||
|
VISITOR_POST& visitorPost) {
|
||||||
// Typedefs
|
// Typedefs
|
||||||
typedef typename FOREST::Node Node;
|
typedef typename FOREST::Node Node;
|
||||||
typedef boost::shared_ptr<Node> sharedNode;
|
typedef boost::shared_ptr<Node> sharedNode;
|
||||||
|
@ -92,12 +95,11 @@ namespace gtsam {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Traverse
|
// Traverse
|
||||||
while(!stack.empty())
|
while (!stack.empty()) {
|
||||||
{
|
|
||||||
// Get next node
|
// Get next node
|
||||||
TraversalNode& node = stack.front();
|
TraversalNode& node = stack.front();
|
||||||
|
|
||||||
if(node.expanded) {
|
if (node.expanded) {
|
||||||
// If already expanded, then the data stored in the node is no longer needed, so visit
|
// If already expanded, then the data stored in the node is no longer needed, so visit
|
||||||
// then delete it.
|
// then delete it.
|
||||||
(void) visitorPost(node.treeNode, *node.dataPointer);
|
(void) visitorPost(node.treeNode, *node.dataPointer);
|
||||||
|
@ -106,7 +108,8 @@ namespace gtsam {
|
||||||
} else {
|
} else {
|
||||||
// If not already visited, visit the node and add its children (use reverse iterators so
|
// If not already visited, visit the node and add its children (use reverse iterators so
|
||||||
// children are processed in the order they appear)
|
// children are processed in the order they appear)
|
||||||
node.dataPointer = dataList.insert(dataList.end(), visitorPre(node.treeNode, node.parentData));
|
node.dataPointer = dataList.insert(dataList.end(),
|
||||||
|
visitorPre(node.treeNode, node.parentData));
|
||||||
typename Stack::iterator insertLocation = stack.begin();
|
typename Stack::iterator insertLocation = stack.begin();
|
||||||
BOOST_FOREACH(const sharedNode& child, node.treeNode->children)
|
BOOST_FOREACH(const sharedNode& child, node.treeNode->children)
|
||||||
stack.insert(insertLocation, TraversalNode(child, *node.dataPointer));
|
stack.insert(insertLocation, TraversalNode(child, *node.dataPointer));
|
||||||
|
@ -114,9 +117,9 @@ namespace gtsam {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(dataList.empty());
|
assert(dataList.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Traverse a forest depth-first, with a pre-order visit but no post-order visit.
|
/** Traverse a forest depth-first, with a pre-order visit but no post-order visit.
|
||||||
* @param forest The forest of trees to traverse. The method \c forest.roots() should exist
|
* @param forest The forest of trees to traverse. The method \c forest.roots() should exist
|
||||||
* and return a collection of (shared) pointers to \c FOREST::Node.
|
* and return a collection of (shared) pointers to \c FOREST::Node.
|
||||||
* @param visitorPre \c visitorPre(node, parentData) will be called at every node, before
|
* @param visitorPre \c visitorPre(node, parentData) will be called at every node, before
|
||||||
|
@ -127,14 +130,13 @@ namespace gtsam {
|
||||||
* Regarding efficiency, this copy-on-return is usually optimized out by the compiler.
|
* Regarding efficiency, this copy-on-return is usually optimized out by the compiler.
|
||||||
* @param rootData The data to pass by reference to \c visitorPre when it is called on each
|
* @param rootData The data to pass by reference to \c visitorPre when it is called on each
|
||||||
* root node. */
|
* root node. */
|
||||||
template<class FOREST, typename DATA, typename VISITOR_PRE>
|
template<class FOREST, typename DATA, typename VISITOR_PRE>
|
||||||
void DepthFirstForest(FOREST& forest, DATA& rootData, VISITOR_PRE& visitorPre)
|
void DepthFirstForest(FOREST& forest, DATA& rootData, VISITOR_PRE& visitorPre) {
|
||||||
{
|
|
||||||
no_op visitorPost;
|
no_op visitorPost;
|
||||||
DepthFirstForest(forest, rootData, visitorPre, visitorPost);
|
DepthFirstForest(forest, rootData, visitorPre, visitorPost);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Traverse a forest depth-first with pre-order and post-order visits.
|
/** Traverse a forest depth-first with pre-order and post-order visits.
|
||||||
* @param forest The forest of trees to traverse. The method \c forest.roots() should exist
|
* @param forest The forest of trees to traverse. The method \c forest.roots() should exist
|
||||||
* and return a collection of (shared) pointers to \c FOREST::Node.
|
* and return a collection of (shared) pointers to \c FOREST::Node.
|
||||||
* @param visitorPre \c visitorPre(node, parentData) will be called at every node, before
|
* @param visitorPre \c visitorPre(node, parentData) will be called at every node, before
|
||||||
|
@ -148,77 +150,80 @@ namespace gtsam {
|
||||||
* call to \c visitorPre (the \c DATA object may be modified by visiting the children).
|
* call to \c visitorPre (the \c DATA object may be modified by visiting the children).
|
||||||
* @param rootData The data to pass by reference to \c visitorPre when it is called on each
|
* @param rootData The data to pass by reference to \c visitorPre when it is called on each
|
||||||
* root node. */
|
* root node. */
|
||||||
template<class FOREST, typename DATA, typename VISITOR_PRE, typename VISITOR_POST>
|
template<class FOREST, typename DATA, typename VISITOR_PRE,
|
||||||
void DepthFirstForestParallel(FOREST& forest, DATA& rootData, VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost,
|
typename VISITOR_POST>
|
||||||
int problemSizeThreshold = 10)
|
void DepthFirstForestParallel(FOREST& forest, DATA& rootData,
|
||||||
{
|
VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost,
|
||||||
|
int problemSizeThreshold = 10) {
|
||||||
#ifdef GTSAM_USE_TBB
|
#ifdef GTSAM_USE_TBB
|
||||||
// Typedefs
|
// Typedefs
|
||||||
typedef typename FOREST::Node Node;
|
typedef typename FOREST::Node Node;
|
||||||
typedef boost::shared_ptr<Node> sharedNode;
|
typedef boost::shared_ptr<Node> sharedNode;
|
||||||
|
|
||||||
tbb::task::spawn_root_and_wait(internal::CreateRootTask<Node>(
|
tbb::task::spawn_root_and_wait(
|
||||||
forest.roots(), rootData, visitorPre, visitorPost, problemSizeThreshold));
|
internal::CreateRootTask<Node>(forest.roots(), rootData, visitorPre,
|
||||||
|
visitorPost, problemSizeThreshold));
|
||||||
#else
|
#else
|
||||||
DepthFirstForest(forest, rootData, visitorPre, visitorPost);
|
DepthFirstForest(forest, rootData, visitorPre, visitorPost);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
/* ************************************************************************* */
|
/** Traversal function for CloneForest */
|
||||||
/** Traversal function for CloneForest */
|
namespace {
|
||||||
namespace {
|
template<typename NODE>
|
||||||
template<typename NODE>
|
boost::shared_ptr<NODE> CloneForestVisitorPre(
|
||||||
boost::shared_ptr<NODE>
|
const boost::shared_ptr<NODE>& node,
|
||||||
CloneForestVisitorPre(const boost::shared_ptr<NODE>& node, const boost::shared_ptr<NODE>& parentPointer)
|
const boost::shared_ptr<NODE>& parentPointer) {
|
||||||
{
|
|
||||||
// Clone the current node and add it to its cloned parent
|
// Clone the current node and add it to its cloned parent
|
||||||
boost::shared_ptr<NODE> clone = boost::make_shared<NODE>(*node);
|
boost::shared_ptr<NODE> clone = boost::make_shared<NODE>(*node);
|
||||||
clone->children.clear();
|
clone->children.clear();
|
||||||
parentPointer->children.push_back(clone);
|
parentPointer->children.push_back(clone);
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clone a tree, copy-constructing new nodes (calling boost::make_shared) and setting up child
|
/** Clone a tree, copy-constructing new nodes (calling boost::make_shared) and setting up child
|
||||||
* pointers for a clone of the original tree.
|
* pointers for a clone of the original tree.
|
||||||
* @param forest The forest of trees to clone. The method \c forest.roots() should exist and
|
* @param forest The forest of trees to clone. The method \c forest.roots() should exist and
|
||||||
* return a collection of shared pointers to \c FOREST::Node.
|
* return a collection of shared pointers to \c FOREST::Node.
|
||||||
* @return The new collection of roots. */
|
* @return The new collection of roots. */
|
||||||
template<class FOREST>
|
template<class FOREST>
|
||||||
FastVector<boost::shared_ptr<typename FOREST::Node> > CloneForest(const FOREST& forest)
|
FastVector<boost::shared_ptr<typename FOREST::Node> > CloneForest(
|
||||||
{
|
const FOREST& forest) {
|
||||||
typedef typename FOREST::Node Node;
|
typedef typename FOREST::Node Node;
|
||||||
boost::shared_ptr<Node> rootContainer = boost::make_shared<Node>();
|
boost::shared_ptr<Node> rootContainer = boost::make_shared<Node>();
|
||||||
DepthFirstForest(forest, rootContainer, CloneForestVisitorPre<Node>);
|
DepthFirstForest(forest, rootContainer, CloneForestVisitorPre<Node>);
|
||||||
return FastVector<boost::shared_ptr<Node> >(rootContainer->children.begin(), rootContainer->children.end());
|
return FastVector<boost::shared_ptr<Node> >(rootContainer->children.begin(),
|
||||||
}
|
rootContainer->children.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
/* ************************************************************************* */
|
/** Traversal function for PrintForest */
|
||||||
/** Traversal function for PrintForest */
|
namespace {
|
||||||
namespace {
|
struct PrintForestVisitorPre {
|
||||||
struct PrintForestVisitorPre
|
|
||||||
{
|
|
||||||
const KeyFormatter& formatter;
|
const KeyFormatter& formatter;
|
||||||
PrintForestVisitorPre(const KeyFormatter& formatter) : formatter(formatter) {}
|
PrintForestVisitorPre(const KeyFormatter& formatter) :
|
||||||
template<typename NODE> std::string operator()(const boost::shared_ptr<NODE>& node, const std::string& parentString)
|
formatter(formatter) {
|
||||||
{
|
}
|
||||||
|
template<typename NODE> std::string operator()(
|
||||||
|
const boost::shared_ptr<NODE>& node, const std::string& parentString) {
|
||||||
// Print the current node
|
// Print the current node
|
||||||
node->print(parentString + "-", formatter);
|
node->print(parentString + "-", formatter);
|
||||||
// Increment the indentation
|
// Increment the indentation
|
||||||
return parentString + "| ";
|
return parentString + "| ";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Print a tree, prefixing each line with \c str, and formatting keys using \c keyFormatter.
|
/** Print a tree, prefixing each line with \c str, and formatting keys using \c keyFormatter.
|
||||||
* To print each node, this function calls the \c print function of the tree nodes. */
|
* To print each node, this function calls the \c print function of the tree nodes. */
|
||||||
template<class FOREST>
|
template<class FOREST>
|
||||||
void PrintForest(const FOREST& forest, std::string str, const KeyFormatter& keyFormatter) {
|
void PrintForest(const FOREST& forest, std::string str,
|
||||||
|
const KeyFormatter& keyFormatter) {
|
||||||
PrintForestVisitorPre visitor(keyFormatter);
|
PrintForestVisitorPre visitor(keyFormatter);
|
||||||
DepthFirstForest(forest, str, visitor);
|
DepthFirstForest(forest, str, visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue