Изменение свойств вершины в Boost :: Graph

Я пытаюсь понять, как использовать boost :: graph для хранения некоторой информации. Однако есть информация, которую я хочу привязать к каждой вершине. Изучая документацию к библиотеке, можно обнаружить либо (а) плохо написанную документацию, либо (б), я явно не так хорош в C ++, как я думал. Выбери два.

Я ищу простой пример использования.


person Paul Nathan    schedule 22.03.2009    source источник
comment
После просмотра документации по ускорению в 17-м году я получил те же два откровения.   -  person dev_nut    schedule 01.04.2017


Ответы (5)


Объединенные свойства просто использовать:

using namespace boost;

struct vertex_info { 
    std::string whatever; 
    int othervalue; 
    std::vector<int> some_values; 
};

typedef adjacency_list<vecS, vecS, undirectedS, vertex_info> graph_t;

graph_t g(n);

g[0].whatever = "Vertex 0";

[...]

и так далее.

См. Также документы.

Другой очень полезный тип свойства вершины - это внешние свойства. Вы можете объявить std::vectors подходящего размера и использовать их как свойства.

person baol    schedule 16.03.2010
comment
Это должен быть принятый ответ. Тем более, что конкурирующий ответ, получивший наибольшее количество голосов, является повторной реализацией этой функции, которую вы показали, уже есть в библиотеке! Ваш примерный код также является самым простым примером, который я нашел в сети, как настроить использование библиотеки простого графа ускорения. Спасибо. - person Dennis; 06.06.2010
comment
+1; извините, я опаздываю на вечеринку :) Небольшое примечание: вы можете объявить std :: vectors - это верно, только если вы используете vecS, и то только для вершин (не ребер) IIRC. - person phooji; 20.04.2011
comment
Вы также можете использовать несколько свойств с помощью магии TMP: здесь - ›informit .com / article / article.aspx? p = 25756 & seqNum = 7. - person Ramadheer Singh; 20.07.2011
comment

Мне не нравится подход boost :: graph к свойствам вложенных шаблонов, поэтому я написал небольшую оболочку для всего, что в основном позволяет помещать любую структуру / класс как свойство вершины / края. Можно получить доступ к свойствам, обращаясь к членам структуры.

Чтобы сохранить гибкость, эти структуры определены как параметр шаблона.

Вот Код:

/* definition of basic boost::graph properties */
enum vertex_properties_t { vertex_properties };
enum edge_properties_t { edge_properties };
namespace boost {
    BOOST_INSTALL_PROPERTY(vertex, properties);
    BOOST_INSTALL_PROPERTY(edge, properties);
}


/* the graph base class template */
template < typename VERTEXPROPERTIES, typename EDGEPROPERTIES >
class Graph
{
public:

    /* an adjacency_list like we need it */
    typedef adjacency_list<
        setS, // disallow parallel edges
        listS, // vertex container
        bidirectionalS, // directed graph
        property<vertex_properties_t, VERTEXPROPERTIES>,
        property<edge_properties_t, EDGEPROPERTIES>
    > GraphContainer;


    /* a bunch of graph-specific typedefs */
    typedef typename graph_traits<GraphContainer>::vertex_descriptor Vertex;
    typedef typename graph_traits<GraphContainer>::edge_descriptor Edge;
    typedef std::pair<Edge, Edge> EdgePair;

    typedef typename graph_traits<GraphContainer>::vertex_iterator vertex_iter;
    typedef typename graph_traits<GraphContainer>::edge_iterator edge_iter;
    typedef typename graph_traits<GraphContainer>::adjacency_iterator adjacency_iter;
    typedef typename graph_traits<GraphContainer>::out_edge_iterator out_edge_iter;

    typedef typename graph_traits<GraphContainer>::degree_size_type degree_t;

    typedef std::pair<adjacency_iter, adjacency_iter> adjacency_vertex_range_t;
    typedef std::pair<out_edge_iter, out_edge_iter> out_edge_range_t;
    typedef std::pair<vertex_iter, vertex_iter> vertex_range_t;
    typedef std::pair<edge_iter, edge_iter> edge_range_t;


    /* constructors etc. */
    Graph()
    {}

    Graph(const Graph& g) :
        graph(g.graph)
    {}

    virtual ~Graph()
    {}


    /* structure modification methods */
    void Clear()
    {
        graph.clear();
    }

    Vertex AddVertex(const VERTEXPROPERTIES& prop)
    {
        Vertex v = add_vertex(graph);
        properties(v) = prop;
        return v;
    }

    void RemoveVertex(const Vertex& v)
    {
        clear_vertex(v, graph);
        remove_vertex(v, graph);
    }

    EdgePair AddEdge(const Vertex& v1, const Vertex& v2, const EDGEPROPERTIES& prop_12, const EDGEPROPERTIES& prop_21)
    {
        /* TODO: maybe one wants to check if this edge could be inserted */
        Edge addedEdge1 = add_edge(v1, v2, graph).first;
        Edge addedEdge2 = add_edge(v2, v1, graph).first;

        properties(addedEdge1) = prop_12;
        properties(addedEdge2) = prop_21;

        return EdgePair(addedEdge1, addedEdge2);
    }


    /* property access */
    VERTEXPROPERTIES& properties(const Vertex& v)
    {
        typename property_map<GraphContainer, vertex_properties_t>::type param = get(vertex_properties, graph);
        return param[v];
    }

    const VERTEXPROPERTIES& properties(const Vertex& v) const
    {
        typename property_map<GraphContainer, vertex_properties_t>::const_type param = get(vertex_properties, graph);
        return param[v];
    }

    EDGEPROPERTIES& properties(const Edge& v)
    {
        typename property_map<GraphContainer, edge_properties_t>::type param = get(edge_properties, graph);
        return param[v];
    }

    const EDGEPROPERTIES& properties(const Edge& v) const
    {
        typename property_map<GraphContainer, edge_properties_t>::const_type param = get(edge_properties, graph);
        return param[v];
    }


    /* selectors and properties */
    const GraphContainer& getGraph() const
    {
        return graph;
    }

    vertex_range_t getVertices() const
    {
        return vertices(graph);
    }

    adjacency_vertex_range_t getAdjacentVertices(const Vertex& v) const
    {
        return adjacent_vertices(v, graph);
    }

    int getVertexCount() const
    {
        return num_vertices(graph);
    }

    int getVertexDegree(const Vertex& v) const
    {
        return out_degree(v, graph);
    }


    /* operators */
    Graph& operator=(const Graph &rhs)
    {
        graph = rhs.graph;
        return *this;
    }

protected:
    GraphContainer graph;
};

Используя это, вы можете получить доступ к следующим свойствам:

struct VertexProperties {
    int i;
};

struct EdgeProperties {
};

typedef Graph<VertexProperties, EdgeProperties> MyGraph;

MyGraph g;

VertexProperties vp;
vp.i = 42;

MyGraph::Vertex v = g.AddVertex(vp);

g.properties(v).i = 23;

Конечно, у вас могут быть другие потребности в структуре вашего графа, но модификация приведенного выше кода должна быть довольно простой.

person grefab    schedule 04.06.2009
comment
Здорово! Именно этот код сделал Boost Graph полезным для меня. Еще я не люблю работать с вложенными шаблонами. - person conradlee; 16.03.2010
comment
Просто во избежание проблем с такими новичками, как я. В начале кода необходимо добавить: #include ‹boost / config.hpp› #include ‹boost / version.hpp› #include ‹boost / graph / graph_utility.hpp› #include ‹boost / graph / adjacency_list.hpp ›#Include‹ boost / property_map / property_map.hpp ›#include‹ boost / static_assert.hpp ›using namespace boost; (Прошу прощения за этот ужасный комментарий) - person Manuel; 16.02.2012
comment
УДИВИТЕЛЬНОЕ решение! Это спасло мне день =) Я просто застрял на итераторах ... Я не могу найти способ получить доступ к корневому узлу моего графика, любая идея? - person Tex; 22.02.2012
comment
Извините за задержку с ответом. Приведенный выше код просто определяет структуру графа (V, E) и не хранит метаинформацию, такую ​​как наличие корневой вершины. Однако AddVertex () возвращает созданную вершину, так что вы можете позаботиться об этом самостоятельно. - person grefab; 05.07.2012
comment
Какой вложенный шаблон? Если вы имеете в виду протокол свойств графа, они практически не нужны. BGL имеет объединенные свойства (который мог существовать или не существовать в 2009 году). Я думаю, что у этого класса-оболочки больше недостатков, чем достоинств в современном BGL / C ++. Я продемонстрировал это бок о бок в это новое сообщение - person sehe; 10.11.2017
comment
Не уверен, существовали ли они тогда. Приведенный выше код был предназначен для использования BGL, поскольку тогда это было проще, поэтому нет необходимости писать шаблонные типы везде, где требуются вершины, ребра или их диапазоны. Но это было более восьми лет назад. Более современное решение, использующее C ++ 1x и диапазоны, будет выглядеть иначе, как вы объяснили в своем сообщении. - person grefab; 10.11.2017

Ниже приведен код, который я использовал для добавления некоторых свойств к вершинам, ребрам и графам. Обратите внимание, что имя вершины и имя графа являются предопределенными свойствами (полный список см. В boost / properties.hpp), так что vertex_name_t и graph_name_t уже определены. Однако vertex_location_t, edge_length_t и graph_notes_t являются моими собственными свойствами и, следовательно, нуждаются в определении. Я собрал этот код из различных примеров и документации, и я не совсем уверен, что делает BOOST_INSTALL_PROPERTY, но код, похоже, работает нормально.

// Define custom properties
enum vertex_location_t { vertex_location };
enum edge_length_t     { edge_length     };
enum graph_notes_t     { graph_notes     };

namespace boost
{
    BOOST_INSTALL_PROPERTY(vertex, location);
    BOOST_INSTALL_PROPERTY(edge,   length  );
    BOOST_INSTALL_PROPERTY(graph,  notes   );
}

// Define vertex properties:  vertex name and location
typedef property<vertex_name_t,     string,
        property<vertex_location_t, Point3> >
VertexProperties;

// Define edge properties:  length
typedef property<edge_length_t, double> EdgeProperties;

// Define graph properties:  graph name and notes
typedef property<graph_name_t,  string,
        property<graph_notes_t, string> >
GraphProperties;

// Define a graph type
typedef adjacency_list
<
    vecS,       // edge container type
    vecS,       // vertex container type
    undirectedS,
    VertexProperties,
    EdgeProperties,
    GraphProperties
> Graph;
person Community    schedule 12.05.2009

Я считаю, что Boost.Graph имеет очень хорошую документацию, но не для новичков в этом вопросе. Итак, вот пример, который, я надеюсь, достаточно прост!

//includes

// Create a name for your information
struct VertexInformation
{
  typedef boost::vertex_property_type type;
};

// Graph type, customize it to your needs
// This is when you decide what information will be attached to vertices and/or edges
// of MyGraph objects
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
  boost::property<VertexInformation, double> > MyGraph;

int main()
{
  MyGraph graph;

  // Create accessor for information
  typedef boost::property_map<MyGraph, VertexInformation>::type  InformationAccessor;
  InformationAccessor information( get( VertexInformation(), graph ) );

  // Create a vertex (for example purpose)
  typedef boost::graph_traits<MyGraph>::vertex_descriptor MyVertex;
  MyVertex vertex = add_vertex( graph );

  // Now you can access your information
  put( information, vertex, 1. );

  // returns 1 !
  get( information, vertex );
  return 0;
}
person Benoît    schedule 23.03.2009
comment
Итак, когда вы устанавливаете аргумент шаблона свойств вершины равным boost::property<VertexInformation, double>, вы фактически называете double свойство вершины VertexInformation? То есть, почему бы вам не поместить double value; ВНУТРИ структуры VertexInformation? - person David Doria; 09.11.2016

Я нашел эти примеры очень полезными. В Windows он будет в вашем каталоге \ Program Files \ boost \ boost_1_38 \ libs \ graph \ example.

kevin_bacon2.cpp использует свойства вершин для хранения имен актеров.

Свойства вершин и ребер можно хранить в обычных структурах или классах.

person eodonohoe    schedule 02.06.2009