C++ 具有黑名单边的Boost过滤图
我想在有黑名单边的图上运行Dijkstra,也就是说,我想计算不使用这些链接的最短路径。 目前,我首先定义过滤器:C++ 具有黑名单边的Boost过滤图,c++,performance,boost-graph,C++,Performance,Boost Graph,我想在有黑名单边的图上运行Dijkstra,也就是说,我想计算不使用这些链接的最短路径。 目前,我首先定义过滤器: typedef std::pair<int, int> Edge; typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, boost::no_property, boost::property<boost::edge_weight_t, int> >
typedef std::pair<int, int> Edge;
typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, boost::no_property, boost::property<boost::edge_weight_t, int> > graph_t;
现在,我所做的很有效,但很奇怪。实际上,我首先在顶点0和1之间创建一条边。然后,在操作符()(…)
中,我有一个边描述符,而不是边(
)(如果我把边作为参数,编译器会像解释的那样抱怨,所以我猜boost
在某处执行一些转换,原因我不知道)。然后,我再次检索操作符()(…)
内的顶点0和1,并重建边。您知道,我要花很长的时间来做一些事情,只要操作符()(..)
直接接受边缘
您认为我可以以更优雅、更高效的方式执行相同的操作吗?您基本上要求的与boost graph无关。您希望能够高效地查找一对顶点描述符
决定因素将是黑名单数据结构的选择
作为旁注,您不在图形中插入Edge
对象。您选择的图形模型是一个邻接列表,因此它存储每个顶点的相邻顶点列表
对
只是一种方便的类型,用于轻松初始化图形。你完全可以不用它
在考虑了可能的选择之后,我认为没有更快的方法
- 在某些大范围内,您可能会获得更高的有效性能
- 使用本身表示为邻接列表的黑名单(例如
std::map
)或
- 要使用
无序集
李>
这两种优化不太可能产生显著的差异,除非是大规模的
- 通过使用
boost::container::flat\u集,您可能会受益于引用的局部性
成本是真实的吗?
如果您认为“构造边缘
”是一种资源浪费,那么请忘记这一点:它是一种POD类型(std::pair
),因此只有微不足道的构造函数/析构函数。鉴于set
是一个模板类,它上的大多数操作都可以内联。编译器将内联方法调用、注册参数、删除冗余加载/存储周期并有效生成最佳代码:
#include <set>
#include <utility>
using Edge = std::pair<int, int>;
using Blacklist = std::set<Edge>;
struct Pred {
Blacklist blacklist { {
{ 92, 29 },
{ 74, 92 },
{ 86, 6 },
{ 67, 35 },
{ 59, 4 },
{ 66, 13 },
{ 82, 37 },
{ 51, 94 },
{ 32, 6 }
} };
bool operator()(int source, int target) const {
return blacklist.end() != blacklist.find(Edge {source, target});
}
};
#包括
#包括
使用Edge=std::pair;
使用黑名单=std::set;
结构预测{
黑名单黑名单{
{ 92, 29 },
{ 74, 92 },
{ 86, 6 },
{ 67, 35 },
{ 59, 4 },
{ 66, 13 },
{ 82, 37 },
{ 51, 94 },
{ 32, 6 }
} };
布尔运算符()(int源,int目标)常量{
返回blacklist.end()!=blacklist.find(边{source,target});
}
};
专业提示:单击叮当声反汇编上的#
按钮查看优化器注释
摘要边缘
类型的成本不存在。任何实际成本都将取决于在edge\u描述符上使用boost::source()
和boost::target()
看到您的边缘容器选择器是列表
,您的边缘容器是基于节点的,这意味着边缘描述符是稳定的,基本上是对边缘对象的类型擦除引用。调用boost::source(e,g)
只不过是转换描述符和取消引用。根据它的使用方式,编译器甚至可以看穿这些间接指令
如果这一成本不符合您的喜好,请调整图形类型:)(您的用例可能需要使用EdgeList概念,或者使用基于节点的边缘容器等
... I fill the graph g ...
std::set<Edge> blacklist; blacklist.insert( Edge(0,1) );
BlackListEdgeConstraint filter(blacklist, &g);
boost::filtered_graph<graph_t, BlackListEdgeConstraint> filtered(g, filter);
... I run Dikjstra on the filtered graph ...
#include <set>
#include <utility>
using Edge = std::pair<int, int>;
using Blacklist = std::set<Edge>;
struct Pred {
Blacklist blacklist { {
{ 92, 29 },
{ 74, 92 },
{ 86, 6 },
{ 67, 35 },
{ 59, 4 },
{ 66, 13 },
{ 82, 37 },
{ 51, 94 },
{ 32, 6 }
} };
bool operator()(int source, int target) const {
return blacklist.end() != blacklist.find(Edge {source, target});
}
};