提升图:找到覆盖路径

时间:2014-05-29 10:11:00

标签: c++ boost graph a-star

我有一个问题,乍一看很简单。我有一个图表和一条路径。我必须找到最小化节点之间路径差异的最佳路径。例如,具有路径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

0 个答案:

没有答案