I am writing a program which uses the boost graph library to solve the Travelling Salesman problem using A* search with a minimum spanning tree heuristic. I am rather new to boost::graph
In my heuristic class, I calculate the minimum spanning tree of all the vertices yet unvisited. I keep track of which vertices have been visited by maintaining a
copy of the original graph from which I remove the current vertex and all its edges on each call to the heuristic. However, when I go to call boost::clear_vertex(u, subGraph)
where u
is a vertex_descriptor
and subGraph
is the copy of the original graph from which I am subtracting vertices, I get a debug assertion failure stating:
list erase iterator outside range.
After doing some debugging, I found that ultimately the error is generated on line 1383 of STL <list>
where for some reason the following condition is false:
_Where._Getcont() != _STD addressof(this->_Get_data())
.
Here is my Heuristic class:
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;
};
Here are some relevant typedefs:
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
I would really appreciate someone clearing up for me why this is happening. Also, it could be that my idea for a heuristic class is totally stupid, so if you think I should just try some other approach for a Minimum Spanning Tree heuristic rather than keep messing with this, I am certainly open to the prospect. If my heuristic is idiotic, I would really appreciate some suggestion as to what else to do. My boost version is boost_1_67_0 and I am using MS Visual Studio 2017.