Установка цвета вершины во время поиска по ширине_first_search

Я хотел бы сделать регион, растущий на графике BGL. Идея роста региона состоит в том, чтобы посетить вершины, начиная с указанной корневой вершины, а также собрать и вернуть подграф или список вершин, которые прошли некоторую критериальную функцию по сравнению с их родителем. Например, скажем, у нас есть простой график, который выглядит так:

A-B-C-D

а веса ребер равны:

AB = 4, BC = 10, CD = 3

Теперь мы хотим увеличить регион, начиная с A. Мы хотим сделать следующее:

  • Откройте A и добавьте его в подключенный регион
  • Discover B, and decide if B is "similar enough" to A. For this example, lets say the criterion is a threshold on the edge weight: if the edge weight is > 5, then we should not continue traversing to B. So here, AB = 4 so we should grow to B, but since BC=10, we should never reach C.
    • If so, add B to the connected region and continue by discovering C and checking if C is similar enough to B, etc.
    • Если нет, остановитесь и верните текущую подключенную область

Я могу проверить эту функцию критерия в функции tree_edge посетителя. Если A и B слишком различны, я попытался «остановить» BFS от продолжения (добавив B в очередь, а затем обработав его позже и т. д.), установив целевую вершину ребра, переданного tree_edge, в черный цвет. Однако это, похоже, не останавливает обход:

#include <iostream>

#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/breadth_first_search.hpp>

using EdgeWeightProperty = boost::property<boost::edge_weight_t, float>;

using ColorPropertyType = boost::property<boost::vertex_color_t, boost::default_color_type>;

using GraphType =  boost::adjacency_list<boost::setS, // out edge container
                                         boost::vecS, // vertex container
                                         boost::undirectedS, // directed or undirected
                                         ColorPropertyType, // vertex properites
                                         EdgeWeightProperty> // edge properties
                                         ;

template <typename TGraph>
void printColors(const TGraph& g)
{
    const auto& colorMapGraph = get(boost::vertex_color_t(), g);

    std::cout << "colors: ";
    for(unsigned int i = 0; i < num_vertices(g); ++i) {
        std::cout << get(colorMapGraph, vertex(i, g)) << " ";
    }

    std::cout << std::endl;
}

class BreadthFirstSearchVisitor : public boost::default_bfs_visitor
{
public:

    // We must provide a mutable version of the graph to the visitor since we want to change properties
    BreadthFirstSearchVisitor(GraphType& graph) : mGraph(graph) {}

    template < typename TEdge, typename TGraph>
    void tree_edge(TEdge e, const TGraph& g) const
    {
        std::cout << std::endl << "tree_edge: " << e << std::endl;
        printColors(g);
        const auto& colors = get(boost::vertex_color_t(), mGraph); // Though this is const&, you can still call put()

        const auto& edgeWeights = get(boost::edge_weight_t(), mGraph);

        boost::graph_traits<GraphType>::vertex_descriptor targetVertex = boost::target(e, g);
        std::cout << "targetVertex: " << targetVertex << std::endl;

        float edgeWeight = get(edgeWeights, e);
        std::cout << "edgeWeight: " << edgeWeight << std::endl;

        if(edgeWeight > 5.f) {
            std::cout << "Next vertex does not belong to the region!" << std::endl;
            put(colors, vertex(targetVertex, mGraph), boost::color_traits<GraphType>::black());
            printColors(g);
        }

    }

    // A very strange pattern, but this is (officially) recommended here: http://stackoverflow.com/a/2608616/284529
    GraphType& mGraph;
};

int main(int,char*[])
{
    // Create a graph object
    GraphType g(4);

    EdgeWeightProperty e0 = 4.f;
    add_edge(0, 1, e0, g);

    EdgeWeightProperty e1 = 10.f;
    add_edge(1, 2, e1, g);

    EdgeWeightProperty e2 = 3.f;
    add_edge(2, 3, e2, g);

    BreadthFirstSearchVisitor breadthFirstSearchVisitor(g);

    unsigned int startVertex = 0;

    // named argument signature
    breadth_first_search(g, vertex(startVertex, g), visitor(breadthFirstSearchVisitor).color_map(get(boost::vertex_color_t(), g)));

    return 0;
}

Результат:

tree_edge: (0,1)
colors: 1 0 0 0 
targetVertex: 1
edgeWeight: 4

tree_edge: (1,2)
colors: 4 1 0 0 
targetVertex: 2
edgeWeight: 10
Next vertex does not belong to the region!
colors: 4 1 4 0 

tree_edge: (2,3)
colors: 4 4 1 0 
targetVertex: 3
edgeWeight: 3

но я ожидал, что он никогда не вызовет tree_edge с ребром (2,3), потому что мы пометили вершину 2 как черную.

Может ли кто-нибудь объяснить, почему это не работает, как я ожидал?


person David Doria    schedule 09.11.2016    source источник


Ответы (1)


Похоже, что ответ заключается в том, чтобы вместо этого просто изменить обработку tree_edge в посетителе на examine_edge. Я предполагаю, что целевая вершина уже была добавлена ​​в очередь после вызова tree_edge, поэтому ее цвет больше не имеет значения (поскольку цвет используется для определения того, следует ли добавлять вершину в очередь).

person David Doria    schedule 09.11.2016