简体   繁体   English

在过滤后的图形上的boost :: astar_search

[英]boost::astar_search on filtered graph

I need to run A* on a graph with some of the edges removed. 我需要在删除了一些边的图形上运行A *。 To do so I construct a filtered graph with blacklisted edges and I want to run A* on the filtered graph. 为此,我构造了一个具有列入黑名单的边缘的过滤图,并且我想在过滤图上运行A *。 The blacklisted edges are embedded in the class BlackListEdgeConstraint , that I initialize by passing to its constructor the list of the forbidden edges. 被列入黑名单的边缘嵌入在类BlackListEdgeConstraint ,我通过将其禁用边缘列表传递给其构造函数来对其进行初始化。 This BlackListEdgeConstraint is correctly constructed, and I construct the filtered graph with these constrain. BlackListEdgeConstraint的构造正确,我使用这些约束构造了filtered图形。 The problem is that when I run A* on the filtered graph, another BlackListEdgeConstraint object is mysteriously constructed with an empty constructor, and no edge is in effect blacklisted. 问题是,当我在过滤后的图形上运行A *时,另一个BlackListEdgeConstraint对象是使用空的构造函数神秘地构造的,并且实际上没有边缘被列入黑名单。 Why is it happening? 为什么会这样呢?

This is my complete code: 这是我完整的代码:

#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/astar_search.hpp>
using namespace std;

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;
typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_descriptor;


struct BlackListEdgeConstraint
{
private:
    std::set<Edge> blackList;
    graph_t* g;

public:

    BlackListEdgeConstraint():blackList(std::set<Edge>() ),g(NULL){throw std::runtime_error("This should not be called");};

    BlackListEdgeConstraint(std::set<Edge>& list, graph_t* g_) : blackList(list), g(g_)
    {
        Edge edge = *blackList.begin();
        std::cout<<"The black list contains "<< edge.first<<"-"<<edge.second<<std::endl;
    }

    /**
     * This is the "predicate function" used by boost::filtered_graph (
     *  see http://www.boost.org/doc/libs/1_64_0/libs/graph/doc/filtered_graph.html )
     *  It it returns true, the edge is included in the filtered graph, otherwise it is excluded.
     */
    bool operator()(const boost::graph_traits<graph_t>::edge_descriptor& e) const
    {
        Edge edge(source(e,*g), target(e,*g) );
        std::cout<<"Should we include edge "<<source(e,*g)<<" ->"<< target(e,*g)<<" represented by a descriptor "<<e<<"? ";
        //Include the edge if it's not in the blacklist.
        bool include = (blackList.find( edge ) == blackList.end() );
        std::cout<<include<<std::endl;
        return include;
    }
};

template<class GraphType>
class MyHeuristic : public boost::astar_heuristic<GraphType, double>
{
    private:
        const GraphType* g;

    public:
        MyHeuristic(const GraphType* g_): g(g_) {};

        double operator()(vertex_descriptor  v)
        {
            return 0;
        }
};

 //Used to terminate our search
struct GoalsReached{};

class MyVisitor : public boost::default_astar_visitor
{
    private:
        vertex_descriptor goal;

    public:
        MyVisitor(vertex_descriptor goal_): goal(goal_){};

        template<class GraphType>
        void examine_vertex(vertex_descriptor u, const GraphType& g)
        {   if (u==goal) throw GoalsReached(); }
};


int main()
{
    Edge edge_array[] = {Edge(0,1), Edge(1,2), Edge(2,3), Edge(3,0), Edge(1,3) };
    int weights[] = {1,1,1,1,1};
    int num_arcs = sizeof(edge_array) / sizeof(Edge);
    int num_nodes = 4;

    // Graph created from the list of edges
    graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes);

    // Create descriptor for the source node
    vertex_descriptor s = vertex(0, g);
    vertex_descriptor goal = vertex(3,g) ;
    std::set<Edge> blacklist; blacklist.insert( Edge(1,3)  );

    BlackListEdgeConstraint filter(blacklist, &g);
    boost::filtered_graph<graph_t, BlackListEdgeConstraint> filtered(g, filter);

    cout<<"filtered constructed"<<endl;

    // Create vectors to store the predecessors (p) and the distances from the root (d)
    std::vector<vertex_descriptor> p(num_vertices(filtered));
    std::vector<int> d(num_vertices(filtered));

    try{
        cout<<"Launching astar_search"<<endl;
        boost::astar_search(filtered, s, 
                MyHeuristic<boost::filtered_graph<graph_t, BlackListEdgeConstraint>>(&filtered),
                boost::predecessor_map(&p[0]).
                distance_map(&d[0]).
                visitor(MyVisitor(goal) )
        );
        cout<<"astar_search launched"<<endl;
    }catch(const GoalsReached& )
    {   // Print the path
        std::vector<boost::graph_traits<graph_t>::vertex_descriptor > path;
        boost::graph_traits<graph_t>::vertex_descriptor current = goal;

        while(current!=s)
        {
            path.push_back(current);
            current = p[current];
        }
        path.push_back(s);

        // Prints the path obtained in reverse
        std::vector<boost::graph_traits<graph_t>::vertex_descriptor >::reverse_iterator it;

        for (it = path.rbegin(); it != path.rend(); ++it) {
            std::cout << *it << " ";
        }
        std::cout << std::endl;
    }


    return EXIT_SUCCESS;

}

And this is the output: 这是输出:

The black list contains 1-3
filtered constructed
Launching astar_search
terminate called after throwing an instance of 'std::runtime_error'
  what():  This should not be called

My boost version is 1.54 我的增强版是1.54

The problem is that, when boost::astar_search(..) is invoked, the empty constructor BlackListEdgeConstraint() is called. 问题在于,当调用boost :: astar_search(..)时,将调用空的构造函数BlackListEdgeConstraint()。

I don't know how you reach the conclusion. 我不知道你怎么得出结论。 I cannot reproduce that: 我无法重现:

Live On Coliru 生活在Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/astar_search.hpp>

struct VertexProperties {
};

struct EdgeProperties {
    double weight = 1;
};

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProperties, EdgeProperties> MyGraph;
struct StreetDirectory {
    using Graph = MyGraph;
    using Edge = Graph::edge_descriptor;
    using Vertex = Graph::vertex_descriptor;
};

struct BlackListEdgeConstraint : StreetDirectory
{
    private:
        std::set<StreetDirectory::Edge> blackList;

   public:
        BlackListEdgeConstraint(const std::set<Edge>& list) : blackList(list) {};

        BlackListEdgeConstraint()
        {
           throw std::runtime_error("This should not be called");
        };


        bool operator()(const Edge& e) const
        {
           //Include the edge if it's not in the blacklist.
           return blackList.find(e) == blackList.end();
        }
};


int main() {
    MyGraph graph;

    const std::set<StreetDirectory::Edge> blacklistEdges { 
        add_edge(1,2,graph).first,
        add_edge(1,3,graph).first, 
        add_edge(2,4,graph).first, 
    };
    add_edge(4,2,graph);

    BlackListEdgeConstraint filter(blacklistEdges);
    boost::filtered_graph<MyGraph, BlackListEdgeConstraint> filtered(graph, filter);
    std::vector<StreetDirectory::Vertex> p(boost::num_vertices(filtered)); //Output variable
    std::vector<double>                  d(boost::num_vertices(filtered)); //Output variable

    boost::default_astar_visitor vis;

    boost::astar_search(
            filtered,
            1,
            [](auto /*vd*/) { return 1; },
            boost::predecessor_map(&p[0]).
                weight_map(boost::get(&EdgeProperties::weight, filtered)).
                distance_map(&d[0]).
                visitor(vis)
        );
}

Notes 笔记

  • in general functors are passed by value in (standard) library algorithms. 通常,函子通过(标准)库算法中的值传递。 So you'd use std::reference_wrapper<BlackListEdgeConstraint> if you wanted to use the same instance. 因此,如果要使用同一实例,则可以使用std::reference_wrapper<BlackListEdgeConstraint> But like I said, I don't see it happening, so it's not a problem AFAICT 但是就像我说的那样,我看不到它的发生,所以这不是问题

  • in your sample there seemed to be no edge-weight map indicated. 在您的样本中似乎没有显示边缘权重图。 I don't see how that should have compiled 我不知道应该怎么编译

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM