我有一个问题,乍一看很简单。我有一个图表和一条路径。我必须找到最小化节点之间路径差异的最佳路径。例如,具有路径P1-> P2 - > P3 - > P4,我需要输出另一条路径G1 - > G2 - > G3 - > G4,其中路径和图形节点之间的距离$ d(P1,G1)$被最小化。
现在我用boost::astar_search
来看看A *,但我尝试使其工作失败:它说它找到了解决方案,但检索路径总是只给我第一个节点。 / p>
你能建议我解决这个问题吗?
谢谢!
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <utility>
#include <algorithm>
#include <numeric>
#include <deque>
#include <unordered_set>
#include <vector>
#include <fstream>
#include <list>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/compressed_sparse_row_graph.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/depth_first_search.hpp>
#include <boost/pending/indirect_cmp.hpp>
#include <boost/range/irange.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/astar_search.hpp>
// Properties: weights are int
typedef boost::property<boost::edge_weight_t, int> edge_weight;
// The graph itself as a compressed sparse row matrix
typedef boost::compressed_sparse_row_graph<boost::bidirectionalS, boost::no_property, edge_weight> boost_graph;
// Vertex iterator
typedef boost::graph_traits<boost_graph>::vertex_iterator vertex_iterator;
// Edge iterator
typedef boost::graph_traits<boost_graph>::edge_iterator edge_iterator;
// Adjacent nodes iterator
typedef boost::graph_traits<boost_graph>::adjacency_iterator adjacency_iterator;
typedef boost::graph_traits<boost_graph>::out_edge_iterator outward_iterator;
typedef boost::graph_traits<boost_graph>::in_edge_iterator inward_iterator;
// Property maps
typedef boost::property_map<boost_graph, boost::vertex_index_t>::type index_map;
//typedef boost::property_map<boost_graph, boost::vertex_name_t> name_map;
// Property iterators
typedef boost::iterator_property_map<std::size_t*, index_map, std::size_t, std::size_t&> predecessor_map;
typedef boost::iterator_property_map<std::size_t*, index_map, std::size_t, std::size_t&> distance_map;
// A* heuristics
template <class graph_type>
class astar_heuristic : public boost::astar_heuristic<graph_type, int>
{
public:
typedef typename boost::graph_traits<graph_type>::vertex_descriptor vertex_type;
astar_heuristic(vertex_type goal) : goal_(goal)
{
// NOP
};
int operator()(vertex_type u)
{
std::cout << "> CALLED HEUR @ " << u << std::endl;
return (u - 3) * (u - 3);
}
private:
vertex_type goal_;
};
// Class to be used to terminate the A* algorithm
class exit_astar
{
public:
exit_astar() { };
};
// A* visitor that terminates when we find the goal
template <class vertex_type>
class astar_visitor : public boost::default_astar_visitor
{
public:
astar_visitor(vertex_type goal, const std::vector<std::size_t> &target, int &index) : goal_(goal), target_(target), index_(index)
{
//index = 0;
};
template <class graph>
void initialize_vertex(vertex_type u, graph& g)
{
//std::cout << "INIT: " << u << std::endl;
}
template <class graph>
void discover_vertex(vertex_type u, graph& g)
{
std::cout << "DISC: " << u << std::endl;
}
template <class graph>
void examine_vertex(vertex_type u, graph& g)
{
std::cout << "EXAM: " << u << " (in/out " <<
boost::in_degree(boost::vertex(u, g), g) << "/" <<
boost::out_degree(boost::vertex(u, g), g) << ")" << std::endl;
if (u == goal_)
{
std::cout << "GOAL" << std::endl;
throw exit_astar();
}
}
template <class graph>
void finish_vertex(vertex_type u, graph& g)
{
std::cout << "STOP: " << u << std::endl;
}
template <class graph>
void examine_edge(typename graph::edge_descriptor e, graph& g)
{
std::cout << "EDGE: " << boost::get(boost::edge_index, g, e) << " " << boost::source(e, g) << "-" << boost::target(e, g) << std::endl;
std::cout << "> ++ " << ++index_ << std::endl;
}
template <class graph>
void edge_relaxed(typename graph::edge_descriptor e, graph& g)
{
std::cout << "RELX: " << boost::get(boost::edge_index, g, e) << " " << boost::source(e, g) << "-" << boost::target(e, g) << std::endl;
}
template <class graph>
void edge_not_relaxed(typename graph::edge_descriptor e, graph& g)
{
std::cout << "NRLX: " << boost::get(boost::edge_index, g, e) << " " << boost::source(e, g) << "-" << boost::target(e, g) << std::endl;
std::cout << "> -- " << --index_ << std::endl;
}
private:
vertex_type goal_;
const std::vector<std::size_t> &target_;
int &index_;
};
// ****************************************************************************
int main(int argc, const char * argv[])
{
std::vector<std::pair<std::size_t, std::size_t>> graph_edges;
std::vector<int> edge_weight;
int n_nodes;
graph_edges.push_back(std::make_pair( 0, 1)); edge_weight.push_back(1);
graph_edges.push_back(std::make_pair( 0, 3)); edge_weight.push_back(2);
graph_edges.push_back(std::make_pair( 1, 4)); edge_weight.push_back(2);
graph_edges.push_back(std::make_pair( 2, 4)); edge_weight.push_back(3);
graph_edges.push_back(std::make_pair( 3, 4)); edge_weight.push_back(1);
graph_edges.push_back(std::make_pair( 4, 5)); edge_weight.push_back(1);
graph_edges.push_back(std::make_pair( 4, 6)); edge_weight.push_back(5);
graph_edges.push_back(std::make_pair( 5, 7)); edge_weight.push_back(4);
graph_edges.push_back(std::make_pair( 7, 8)); edge_weight.push_back(1);
graph_edges.push_back(std::make_pair( 8, 9)); edge_weight.push_back(3);
graph_edges.push_back(std::make_pair( 8, 11)); edge_weight.push_back(2);
graph_edges.push_back(std::make_pair( 8, 12)); edge_weight.push_back(3);
graph_edges.push_back(std::make_pair( 9, 10)); edge_weight.push_back(2);
graph_edges.push_back(std::make_pair(12, 10)); edge_weight.push_back(4);
n_nodes = 13;
// Create the graph
boost_graph graph(boost::edges_are_unsorted_multi_pass, graph_edges.begin(), graph_edges.end(), edge_weight.data(), n_nodes);
std::cout << "Graph statistics: " << std::endl;
std::cout << "Nodes: " << boost::num_vertices(graph) << std::endl;
std::cout << "Edges: " << graph_edges.size() << std::endl;
edge_iterator ei, ee;
std::size_t source_node = std::stoul(argv[1]);
std::size_t destination_node = std::stoul(argv[2]);
std::cout << ">> SOURCE NODE " << source_node << std::endl;
std::cout << "Degrees in/out: " << source_node << std::endl;
std::cout << boost::in_degree(boost::vertex(source_node, graph), graph) << std::endl;
std::cout << boost::out_degree(boost::vertex(source_node, graph), graph) << std::endl;
std::cout << "Degrees in/out: " << destination_node << std::endl;
std::cout << boost::in_degree(boost::vertex(destination_node, graph), graph) << std::endl;
std::cout << boost::out_degree(boost::vertex(destination_node, graph), graph) << std::endl;
std::cout << ">> SOURCE NODE " << source_node << std::endl;
std::cout << ">> DESTINATION NODE " << destination_node << std::endl;
// Target path: right now UNUSED
std::vector<std::size_t> t { 1, 40, 56, 97, 164};
std::cout << "Target: ";
for(auto &i : t) std::cout << i << " ";
std::cout << ". " << std::endl;
int visitor_index = 0;
// A* search path and cost
std::vector<std::size_t> p(boost::num_vertices(graph));
std::vector<std::size_t> d(boost::num_vertices(graph));
try
{
// A* parameter interface
boost::astar_search(
graph,
source_node,
astar_heuristic<boost_graph>(destination_node),
//boost::predecessor_map(&p[0]).distance_map(&d[0]).visitor(astar_visitor<std::size_t>(destination_node)));
boost::predecessor_map(boost::make_iterator_property_map(p.begin(), boost::get(boost::vertex_index, graph))).
distance_map(boost::make_iterator_property_map(d.begin(), boost::get(boost::vertex_index, graph))).
visitor(astar_visitor<std::size_t>(destination_node, t, visitor_index)));
/* FROM THE EXAMPLE:
astar_search_tree
(g,
start,
distance_heuristic<mygraph_t, cost, location*>(locations, goal),
predecessor_map(make_iterator_property_map(p.begin(), get(vertex_index, g))).
distance_map(make_iterator_property_map(d.begin(), get(vertex_index, g))).
visitor(astar_goal_visitor<vertex>(goal)));
*/
}
catch(exit_astar fg)
{
std::cout << "p # " << p.size() << " / d # " << d.size() << std::endl;
std::list<std::size_t> shortest_path;
for(std::size_t v = source_node; ; v = p[v])
{
shortest_path.push_front(v);
if(p[v] == v)
break;
}
auto spi = shortest_path.begin();
std::cout << source_node << std::endl;
for(++spi; spi != shortest_path.end(); ++spi)
std::cout << *spi << std::endl;
std::cout << "Shortest A* path from " << source_node << " to " << destination_node << " cost " << d[destination_node] << std::endl;
//return 0;
}
std::cout << "Didn't find a path from " << source_node << "to" << destination_node << "!" << std::endl;
return 0;
}
输出
Graph statistics:
Nodes: 13
Edges: 14
>> SOURCE NODE 0
Degrees in/out: 0
0
2
Degrees in/out: 12
1
1
>> SOURCE NODE 0
>> DESTINATION NODE 12
Target: 1 40 56 97 164 .
> CALLED HEUR @ 0
DISC: 0
EXAM: 0 (in/out 0/2)
EDGE: 0 0-1
> ++ 1
RELX: 0 0-1
> CALLED HEUR @ 1
DISC: 1
EDGE: 1 0-3
> ++ 2
RELX: 1 0-3
> CALLED HEUR @ 3
DISC: 3
STOP: 0
EXAM: 3 (in/out 1/1)
EDGE: 4 3-4
> ++ 3
RELX: 4 3-4
> CALLED HEUR @ 4
DISC: 4
STOP: 3
EXAM: 4 (in/out 3/2)
EDGE: 5 4-5
> ++ 4
RELX: 5 4-5
> CALLED HEUR @ 5
DISC: 5
EDGE: 6 4-6
> ++ 5
RELX: 6 4-6
> CALLED HEUR @ 6
DISC: 6
STOP: 4
EXAM: 1 (in/out 1/1)
EDGE: 2 1-4
> ++ 6
NRLX: 2 1-4
> -- 5
STOP: 1
EXAM: 5 (in/out 1/1)
EDGE: 7 5-7
> ++ 6
RELX: 7 5-7
> CALLED HEUR @ 7
DISC: 7
STOP: 5
EXAM: 6 (in/out 1/0)
STOP: 6
EXAM: 7 (in/out 1/1)
EDGE: 8 7-8
> ++ 7
RELX: 8 7-8
> CALLED HEUR @ 8
DISC: 8
STOP: 7
EXAM: 8 (in/out 1/3)
EDGE: 9 8-9
> ++ 8
RELX: 9 8-9
> CALLED HEUR @ 9
DISC: 9
EDGE: 10 8-11
> ++ 9
RELX: 10 8-11
> CALLED HEUR @ 11
DISC: 11
EDGE: 11 8-12
> ++ 10
RELX: 11 8-12
> CALLED HEUR @ 12
DISC: 12
STOP: 8
EXAM: 9 (in/out 1/1)
EDGE: 12 9-10
> ++ 11
RELX: 12 9-10
> CALLED HEUR @ 10
DISC: 10
STOP: 9
EXAM: 10 (in/out 2/0)
STOP: 10
EXAM: 11 (in/out 1/0)
STOP: 11
EXAM: 12 (in/out 1/1)
GOAL
p # 13 / d # 13
0
Shortest A* path from 0 to 12 cost 0