修改 Boost::Graph 中的顶点属性

发布于 2024-07-15 07:03:31 字数 143 浏览 6 评论 0原文

我试图弄清楚如何使用 boost::graph 来存储一些信息。 但是,我想将一些信息与每个顶点相关联。 盯着该库的文档会发现(a)文档写得很糟糕,或者(b),我显然没有我想象的那么擅长 C++。 选择两个。

我正在寻找一个简单的使用示例。

I am trying to figure out how to use boost::graph to store some information. However, there is information I want tied to each vertex. Staring at the documentation for the library reveals either(a)badly written documentation, or (b), I'm obviously not as good at C++ as I thought. Pick two.

I am looking for a simple example use.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

红墙和绿瓦 2024-07-22 07:03:31

捆绑属性易于使用:

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 并将它们用作属性。

Bundled properties are straightforward to use:

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";

[...]

and so on.

Please also refer to the docs.

The other type of vertex property that are very useful are external properties. You can declare std::vectors of the appropriate size and use them as properties.

忆沫 2024-07-22 07:03:31

我不喜欢 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;

当然,您可能对图形结构有其他需求,但修改上面的代码应该非常容易。

I don't like the nested-template property approach of boost::graph, so I wrote a small wrapper around everything, that basically allows to put any struct/class as a vertex/edge property. One can access properties accessing the struct members.

To keep it flexible these structs are defined as template parameter.

Here the Code:

/* 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;
};

Using this you can access properties like this:

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;

Of course you may have other needs for your graph's structure, but modification of the code above should be pretty easy.

狠疯拽 2024-07-22 07:03:31

下面是我用来将一些属性附加到顶点、边和图的代码。 请注意,顶点名称和图形名称是预定义的属性(完整列表请参阅 boost/properties.hpp),因此 vertex_name_tgraph_name_t 已定义。 但是,vertex_location_tedge_length_tgraph_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;

Below is code I used to attach some properties to vertices, edges, and graphs. Note that vertex name and graph name are predefined properties (see boost/properties.hpp for a complete list) so that vertex_name_t and graph_name_t are already defined. However, vertex_location_t, edge_length_t, and graph_notes_t are my own properties and hence need definition. I cobbled together this code from various examples and documentation, and I'm not sure exactly what BOOST_INSTALL_PROPERTY does, but the code seems to work fine.

// 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;
在梵高的星空下 2024-07-22 07:03:31

我认为 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;
}

I consider Boost.Graph to have a very good documentation, but not truly for beginners on the matter. So here goes an example that i hope is simple enough !

//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;
}
爱要勇敢去追 2024-07-22 07:03:31

我发现这些例子非常有用。 在 Windows 上,它将位于 \Program Files\boost\boost_1_38\libs\graph\example 目录中。

kevin_bacon2.cpp 使用顶点属性来存储参与者的名称。

您的顶点和边属性可以存储在常规结构或类中。

I found the examples pretty useful. On windows it will be in your \Program Files\boost\boost_1_38\libs\graph\example directory.

kevin_bacon2.cpp uses vertex properties to store the names of actors.

Your vertex and edge properties can be stored in regular structs or classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文