2013-03-21 9 views
6

Stosując bodźcem wykres biblioteki szukam sposób ekstraktu matrycy przylegania z bazowego wykresu przedstawionego obu boost::adjacency_list lub boost::adjacency_matrix. Chciałbym użyć tej macierzy w połączeniu z boost::numeric::ublas, aby rozwiązać system równoczesnych równań liniowych.Ekstrakt matrycy przylegania z wykresu BGL

Oto minimalne przykład aby można było tam:

#include <boost/graph/adjacency_list.hpp> 
#include <boost/graph/adjacency_matrix.hpp> 

using namespace boost; 

typedef boost::adjacency_list< listS, vecS, directedS > ListGraph; 
typedef boost::adjacency_matrix<directedS> MatrixGraph; 

int main(){ 

    ListGraph lg; 
    add_edge (0, 1, lg); 
    add_edge (0, 3, lg); 
    add_edge (1, 2, lg); 
    add_edge (2, 3, lg); 

    //How do I get the adjacency matrix underlying lg? 

    MatrixGraph mg(3); 
    add_edge (0, 1, mg); 
    add_edge (0, 3, mg); 
    add_edge (1, 2, mg); 
    add_edge (2, 3, mg); 

    //How do I get the adjacency matrix underlying mg? 

} 

Jeśli ktoś mógł wymyślić skuteczny sposób, aby uzyskać macierz sąsiedztwa byłbym bardzo zobowiązany. Idealnie rozwiązanie jest kompatybilne z uBLAS. Zastanawiam się, czy istnieje sposób na uniknięcie iteracji na całym wykresie.

+1

Nie jestem pewien, ale nie sądzę, istnieje sposób, aby osiągnąć to, że nie wiąże się iteracja wykresie. Mam nadzieję, że ktoś mnie oszuka, ale w międzyczasie można zobaczyć [tutaj] (http://liveworkspace.org/code/1M7a0s$1), że jest to naprawdę łatwe dzięki iteracji. –

Odpowiedz

1

Najprostszym sposobem konwersji adjacency_list do adjacency_matrix jest użycie boost::copy_graph

Kod dla MatrixGraph mg powinno zostać zmienione w następujący sposób

#include <boost/graph/copy.hpp> 
#include <cassert> 

using namespace boost; 

typedef boost::adjacency_list< listS, vecS, directedS > ListGraph; 
typedef boost::adjacency_matrix<directedS> MatrixGraph; 

int main(){ 

    ListGraph lg; 
    add_edge(0, 1, lg); 
    add_edge(0, 3, lg); 
    add_edge(1, 2, lg); 
    add_edge(2, 3, lg); 

    //How do I get the adjacency matrix underlying lg? 

    //How do I get the adjacency matrix underlying mg? 
    MatrixGraph mg(num_vertices(lg)); 
    boost::copy_graph(lg, mg); 
} 

Teraz, aby korzystać macierz sąsiedztwa z ublas lub podobna, można napisać prosta klasa "dostęp", aby składnia była bardziej zgodna z ublas. Kontynuując poprzedni fragment otrzymujemy:

template <class Graph> 
class MatrixAccessor 
{ 
public: 
    typedef typename Graph::Matrix Matrix; //actually a vector< 
    typedef typename Matrix::const_reference const_reference; 


    MatrixAccessor(const Graph* g) 
     : m_g(g) 
    { 
     static_assert(boost::is_same<size_t, typename Graph::vertex_descriptor>::value, "Vertex descriptor should be of integer type"); 
    } 

    const_reference operator()(size_t u, size_t v) const 
    { 
     return m_g->get_edge(u, v); 
    } 

    const Graph* m_g; 
}; 

void use_matrix(const MatrixGraph & mg) 
{ 
    MatrixAccessor<MatrixGraph> matr(&mg); 
    assert(matr(0, 1) == 1); 
    assert(matr(0, 2) == 0); 
} 

W przypadku, gdy adjacency_matrix ma pewne właściwości meblowe zestawie, może trzeba zmodyfikować operator() w MatrixAccessor.

W zależności od tego, ile używasz urządzenia uBLAS, możesz udoskonalić MatrixAccessor. Na przykład out_edge_iterator dla danego wierzchołka MatrixGraph jest w istocie iteratorem nad kolumną macierzy; vertex_iterator może być traktowany jako iterator przez rzędy macierzy, itp.

Oczywiście matryca graficzna jest niezmienna i jako taka powinna być używana z ostrożnością.

0

Użytkownik current revision z adjacency_matrix ma nieudokumentowanego członka publicznego m_matrix (patrz wiersz 640). Jednak jest to płaski wektor krotek <bool, bundled_properties> (wiersz 512). Ponieważ podstawowa pamięć wygląda tak inaczej niż matryca ublas, najprawdopodobniej nie jest możliwa konwersja wykresu do macierzy poza iteracją po krawędziach.

0

tak samo łatwo i nie wiem, ile jest skuteczna. Oto, co wymyśliłem:

Użyłem małego wykresu świata i wydrukowałem matrycę dopasowania.

#include <boost/graph/adjacency_list.hpp> 
#include <boost/graph/small_world_generator.hpp> 
#include <boost/random/linear_congruential.hpp> 

using namespace std; 
using namespace boost; 

typedef adjacency_list<vecS, vecS, undirectedS> Graph; 
typedef small_world_iterator<boost::minstd_rand, Graph> SWGen; 

int main() 
{ 

    boost::minstd_rand gen; 
    int N = 20; 
    int degree = 4; 
    double rewiring = 0.; 

    Graph g(SWGen(gen, N, degree, rewiring), SWGen(), 20); 

    cout << num_edges(g)<< '\n'; 

    typedef graph_traits<Graph>::edge_iterator edge_iterator; 
    pair<edge_iterator, edge_iterator> ei = edges(g); 

    for(edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) { 
     cout << "(" << source(*edge_iter, g) << ", " << target(*edge_iter, g) << ")\n"; 
    } 
    vector<vector<int> > mat(N,vector<int>(N)); 

    for (edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter){ 
     int a = source(*edge_iter, g); 
     int b = target(*edge_iter, g); 
     mat[a][b] = 1; 
     mat[b][a] = 1; 
    } 


    for (int i=0; i<N; i++){ 
     for (int j=0; j<N; j++){ 
      cout << mat[i][j]<<" "; 
     } 
     cout <<endl; 
    } 

    return 0; 
} 

wyjściowa:

0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 
1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 
1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 
Powiązane problemy