xia*_*o 啸 5 boost breadth-first-search boost-graph
我是BGL(boost图库)的新手.我正在学习breadth_first_search接口,它看起来很方便.但是,在我的应用程序中,我需要在遇到其他一些终止条件时剪切breadth_first_search,例如搜索空间节点数满足最大值.
我可以在BFSVisitors中添加新的终止条件,还是有其他技巧?
谢谢!
在 @yuyoyuppe 评论之后(有点晚),您可以创建一个代理访问者,它将包装实际访问者并在满足给定谓词时抛出。discover_vertex
我选择解决的实现为您提供了在和上运行谓词的能力examine_edge
。首先我们定义一个总是返回 false 的默认谓词:
namespace details {
struct no_halting {
template <typename GraphElement, typename Graph>
bool operator()(GraphElement const&, Graph const&) {
return false;
}
};
} // namespace details
Run Code Online (Sandbox Code Playgroud)
然后是模板本身。
template <typename VertexPredicate = details::no_halting,
typename EdgePredicate = details::no_halting,
typename BFSVisitor = boost::default_bfs_visitor>
struct bfs_halting_visitor : public BFSVisitor {
// ... Actual implementation ...
private:
VertexPredicate vpred;
EdgePredicate epred;
};
Run Code Online (Sandbox Code Playgroud)
它将需要 3 个模板参数:
discover_vertex
(每个顶点最多一次)examine_edge
(每个边缘最多一次)为了构建它,我们只需初始化基本访问者和两个谓词:
template <typename VPred, typename EPred, typename ... VisArgs>
bfs_halting_visitor(VPred&& vpred, EPred&& epred, VisArgs&&... args) :
BFSVisitor(std::forward<VisArgs>(args)...),
vpred(vpred), epred(epred) {}
Run Code Online (Sandbox Code Playgroud)
然后,我们必须创建一个(私有)代理函数来对基本实现执行适当的调用并检查谓词:
template <typename Pred, typename R, typename ... FArgs, typename ... Args>
void throw_on_predicate(R (BFSVisitor::*base_fct)(FArgs...), Pred&& pred, Args&&... args) {
bool result = pred(args...);
(this->*base_fct)(std::forward<Args>(args)...);
if (result) {
throw std::runtime_error("A predicate returned true");
}
}
Run Code Online (Sandbox Code Playgroud)
当然,我懒惰地使用了,std::runtime_error
但您应该定义自己的异常类型,派生自std::exception
或您使用的任何基本异常类。
现在我们可以轻松定义两个回调:
template <typename Edge, typename Graph>
void examine_edge(Edge&& e, Graph&& g) {
throw_on_predicate(&BFSVisitor::template examine_edge<Edge, Graph>, epred,
std::forward<Edge>(e), std::forward<Graph>(g));
}
template <typename Vertex, typename Graph>
void discover_vertex(Vertex&& v, Graph&& g) {
throw_on_predicate(&BFSVisitor::template discover_vertex<Vertex, Graph>, vpred,
std::forward<Vertex>(v), std::forward<Graph>(g));
}
Run Code Online (Sandbox Code Playgroud)
我们将在自定义顶点谓词上测试我们的设施,该谓词在发现第 N 个顶点时返回 true。
struct VertexCounter {
VertexCounter(std::size_t limit) : count(0), limit(limit) {}
VertexCounter() : VertexCounter(0) {}
template <typename V, typename G>
bool operator()(V&&, G&&) {
return ((++count) > limit);
}
private:
std::size_t count;
std::size_t const limit;
};
Run Code Online (Sandbox Code Playgroud)
要在给定图上执行 bfs,很容易:
Graph graph = get_graph();
Vertex start_vertex;
bfs_halting_visitor<VertexCounter> vis(VertexCounter(2), details::no_halting());
try {
boost::breadth_first_search(graph, start_vertex, boost::visitor(vis));
} catch (std::runtime_error& e) {
std::cout << e.what() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
Coliru 上的现场演示可帮助您了解所有功能的实际情况。
归档时间: |
|
查看次数: |
497 次 |
最近记录: |