2009-03-22 2 views
29

나는 boost :: graph를 사용하여 정보를 저장하는 방법을 알아 내려고하고있다. 그러나 각 꼭지점에 묶어두기를 원하는 정보가 있습니다. 라이브러리에 대한 문서를 보니 (a) 나쁘게 작성된 문서 또는 (b) 필자가 생각한 것처럼 분명히 C++이 좋지 않다는 것을 알 수 있습니다. 둘을 골라.부스트 :: 그래프에서 버텍스 속성 수정하기

간단한 예제 사용을 찾고 있습니다.

+3

'17 년에 부스트 문서를보고 나서 두 가지 계시가 있습니다. –

답변

1

나는 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; 
} 
+0

그래서 버텍스 프로퍼티 템플릿 인수를'boost :: property '으로 설정하면 사실상 double이라는 버텍스 프로퍼티 인 "VertexInformation"을 "명명하는"것입니까? 즉, 왜 'double value'를 넣지 않을까요? 'VertexInformation' 구조체 안에? –

4

다음은 일부 속성을 정점, 가장자리 및 그래프에 첨부하는 데 사용되는 코드입니다. 버텍스 이름과 그래프 이름은 vertex_name_tgraph_name_t이 이미 정의 된 미리 정의 된 속성입니다 (전체 목록은 boost/properties.hpp를 참조하십시오). 그러나 vertex_location_t, edge_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; 
1

매우 유용한 예를 발견했습니다. 창에서 \ Program Files \ boost \ boost_1_38 \ libs \ graph \ example 디렉토리에 있습니다.

kevin_bacon2.cpp는 꼭지점 속성을 사용하여 액터 이름을 저장합니다.

정점 및 가장자리 속성은 일반 구조체 또는 클래스에 저장할 수 있습니다.

13

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; 

하지만, 코드의 수정은 위해야 꽤 쉬워.

+0

좋습니다! 이 코드는 Boost Graph를 나를 위해 사용할 수있게 한 것입니다. 또한 중첩 된 템플릿으로 작업하는 것을 좋아하지 않습니다. – conradlee

+0

도와 줘서 기쁩니다. :) – grefab

+3

나 같은 초보자에게 문제가 발생하지 않도록하십시오. 코드 시작 부분에 다음을 추가해야합니다 : #include #include #include #include #include #include using namespace boost; (이 끔찍한 코멘트는 유감입니다.) – Manuel

65

번들 속성 사용은 어떻게됩니까?

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

[...] 

등등.

BGL을 많이 사용하며 번들 속성을 사용하는 작업은 매우 간단합니다 (see the docs).

자주 사용하는 다른 유형의 정점 속성은 외부 속성입니다. 적절한 크기의 std::vectors을 선언하고이를 대부분의 알고리즘과 대부분의 속성으로 속성으로 사용할 수 있습니다.

+14

이 대답이 받아 들여질 필요가 있습니다. 특히 경쟁자가 답을 얻었으므로 현재 투표에서이 기능에 대한 재 구현이 이미 라이브러리에 있습니다! 예제 코드는 간단한 부스트 그래프 라이브러리 사용법을 설정하는 방법에 대해 웹에서 찾은 가장 간단한 예제이기도합니다. 감사. – Dennis

+0

+1; 미안 해요, 파티에 늦었습니다. 단지 사이드 노트에 "std :: vectors 선언 할 수 있습니다."- vecS를 사용하고 vertex (가장자리가 아님) IIRC 만 사용하는 경우에만 해당됩니다. – phooji

+1

TMP의 마법을 통해 여러 속성을 사용할 수도 있습니다. 여기 -> http://www.informit.com/articles/article.aspx?p=25756&seqNum=7 –

관련 문제