【发布时间】:2018-12-13 21:38:02
【问题描述】:
我正在编写一个程序,该程序使用 boost 图形库来解决旅行商问题,该问题使用 A* 搜索和最小生成树启发式算法。我对 boost::graph 很陌生
在我的启发式课程中,我计算了所有尚未访问的顶点的最小生成树。我通过维护一个来跟踪访问了哪些顶点
原始图的副本,我在每次调用启发式时从中删除当前顶点及其所有边。但是,当我调用 boost::clear_vertex(u, subGraph) 时,u 是 vertex_descriptor 和 subGraph 是我从中减去顶点的原始图的副本,我得到一个调试断言失败说明:
列出擦除迭代器超出范围。
经过一些调试,我发现最终在 STL <list> 的第 1383 行产生了错误,由于某种原因,以下条件为 false:
_Where._Getcont() != _STD addressof(this->_Get_data()).
这是我的启发式课程:
class MST_Heuristic : public astar_heuristic<MyGraphType, double>
{
public:
MST_Heuristic(vertex_descriptor goal, MyGraphType g)
: m_goal(goal), subGraph(g), firstRun(true) {}
double operator () (vertex_descriptor u)
{
double MSTDist = 0.0;
double startDist = numeric_limits<double>::infinity();
int minEdgeWeight = subGraph[*out_edges(u, subGraph).first].weight; // initialize minEdgeWeight to weight of first out edge
if (firstRun)
{
IndexMap mapIndex;
associative_property_map<IndexMap> vertexIndices(mapIndex);
int j = 0;
for (auto v = vertices(subGraph).first; v != vertices(subGraph).second; v++)
{
put(vertexIndices, *v, j++);
}
dijkstra_shortest_paths(subGraph, u, get(&VertexData::pred, subGraph), // calculate the shortest path from the start for each vertex
get(&VertexData::dist2, subGraph), get(&EdgeData::weight, subGraph),
vertexIndices, less<double>(), plus<double>(),
numeric_limits<double>::infinity(), 0, do_nothing_dijkstra_visitor(),
get(&VertexData::color, subGraph));
}
for (auto ed : make_iterator_range(out_edges(u, subGraph)))
{
minEdgeWeight = min(subGraph[ed].weight, minEdgeWeight); // find distance from nearest unvisited vertex to the current vertex
}
clear_vertex(u, subGraph);
remove_vertex(u, subGraph);
// Problem here; The problem has to do with removing vertices/edges and destabilizing the graph, thereby making it impossible to iterate through the graph
IndexMap mapIndex;
associative_property_map<IndexMap> vertexIndices(mapIndex);
int j = 0;
for (auto v = vertices(subGraph).first; v != vertices(subGraph).second; v++)
{
put(vertexIndices, *v, j++);
}
prim_minimum_spanning_tree(subGraph, *vertices(subGraph).first, // calculate the minimum spanning tree
get(&VertexData::pred, subGraph), get(&VertexData::dist, subGraph),
get(&EdgeData::weight, subGraph), vertexIndices,
do_nothing_dijkstra_visitor());
for (auto vd : make_iterator_range(vertices(subGraph))) // estimate distance to travel all the unvisited vertices
{
MSTDist += subGraph[vd].dist;
startDist = min(startDist, subGraph[vd].dist2);
}
firstRun = false;
return static_cast<double>(minEdgeWeight) + MSTDist + startDist; // return the result of the heuristic function
}
private:
vertex_descriptor m_goal;
MyGraphType subGraph;
bool firstRun;
};
以下是一些相关的 typedef:
typedef adjacency_list_traits<listS, listS, undirectedS> GraphTraits; // to simplify the next definition
typedef GraphTraits::vertex_descriptor vertex_descriptor; // vertex descriptor for the graph
typedef GraphTraits::edge_descriptor edge_descriptor; // edge descriptor for the graph
typedef std::map<vertex_descriptor, size_t>IndexMap; // type used for the vertex index property map
typedef adjacency_list<listS, listS, undirectedS,VertexData, EdgeData> MyGraphType; // graph type
我非常感谢有人为我澄清为什么会发生这种情况。此外,我对启发式类的想法可能是完全愚蠢的,所以如果你认为我应该尝试一些其他方法来实现最小生成树启发式而不是继续搞乱这个,我当然愿意接受这个前景。如果我的启发式是愚蠢的,我真的很感激一些关于还能做什么的建议。我的 boost 版本是 boost_1_67_0,我使用的是 MS Visual Studio 2017。
【问题讨论】:
-
好的。所以,我从 Sehe 的答案中实现了建议/修订,对于任何未来的读者来说,答案都有效,但这对 A* 来说不是一个好的启发式方法,因为在每个顶点都调用了一次启发式函数之后,子图已完全销毁,无法再用于算法。
-
也许您可以通过引用获取“子图” - 假设修改正在搜索的图是合法的
-
@sehe 感谢您的建议。我决定改为尝试使子图成为一个指针,并根据原始图中顶点的颜色在子图中的哪些顶点和边为每个启发式调用动态创建子图。这样就可以了,所以我不必从子图中删除东西,所以希望这会更好。
标签: c++ boost a-star boost-graph