Używam biblioteki wykresów boost i próbuję zainicjować MutableGraph
, aby rozpocząć życie jako siatka. Krawędzie zostaną dodane i usunięte w późniejszym okresie życia, więc myślę, że adjacency_list<vecS,listS,undirectedS>
jest właściwym wyborem.Kopiowanie z grid_graph do adjacency_list z boost :: copy_graph
Moje czytanie o BGL wskazano, że rozsądny sposób initalise go z tych krawędzi byłoby wykorzystać boost::grid_graph
za pomocą boost::copy_graph
skopiować z boost::grid_graph
że można dokonać wszystkich początkowych krawędzie dla mnie za darmo. Myślałem, że ma to sens - copy_graph
egzemplarzy z modelu VertexListGraph
do modelu MutableGraph
, który jest dokładnie tym, co mam.
Początkowo próbowałem użyć 2-argumentowej wersji copy_graph
, z niejasną nadzieją, że stanie się coś sensownego z domyślnymi ustawieniami dla reszty. Tak się nie stało, grid_graph
(z powodów, których nie mogłem dokładnie wymyślić) nie wydaje się mieć możliwości używania PropertyMap
s z żadną krawędzią lub wierzchołkiem, więc domyślne vertex_copy
i edge_copy
zawiodły (z kompilatorem błąd) kopiowanie właściwości.
Ponieważ wersja 2-argumentowa najwyraźniej nie wydawała się odpowiednia, przechodzę dalej i próbuję zaimplementować własnego operatora binarnego do kopiowania wierzchołków i krawędzi. Nawet z kopią "no-op" nie działa tak dobrze, jak mam nadzieję (to znaczy, że się nie kompiluje).
Mam ułożyła minimalnej pracy przykład, który ilustruje problem:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/grid_graph.hpp>
#include <boost/graph/copy.hpp>
struct Position {
int x, y;
};
struct VertexProperties {
Position pos;
};
typedef boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS,
VertexProperties> Graph;
struct MyCopy {
template <typename S, typename D>
void operator()(const S& /*src*/, D& /*dest*/) {
// Nothing for now, deduced types to try and just make it compile
// TODO: set values for pos to reflect position on grid.
}
};
int main() {
boost::array<std::size_t, 2> lengths = { { 3, 3 } };
boost::grid_graph<2> grid(lengths);
Graph graph;
MyCopy copier;
// Using 3-Arg version of copy_graph so we can specify a custom way of copying to create the properties
boost::copy_graph(grid,graph,boost::bgl_named_params<MyCopy,boost::vertex_copy_t,
boost::bgl_named_params<MyCopy,boost::edge_copy_t> >(copier));
}
Ten przykład nie kompiluje:
g++ -Wextra -Wall -O2 -g -o copytest.o -c copytest.cc
In file included from /usr/include/boost/graph/grid_graph.hpp:24:0,
from copytest.cc:2:
/usr/include/boost/iterator/transform_iterator.hpp: In constructor ‘boost::transform_iterator<UnaryFunction, Iterator, Reference, Value>::transform_iterator() [with UnaryFunc = boost::detail::grid_graph_vertex_at<boost::grid_graph<2u> >, Iterator = boost::counting_iterator<unsigned int, boost::use_default, boost::use_default>, Reference = boost::use_default, Value = boost::use_default]’:
/usr/include/boost/graph/copy.hpp:115:55: instantiated from ‘static void boost::detail::copy_graph_impl<0>::apply(const Graph&, MutableGraph&, CopyVertex, CopyEdge, Orig2CopyVertexIndexMap, IndexMap) [with Graph = boost::grid_graph<2u>, MutableGraph = boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, VertexProperties>, CopyVertex = MyCopy, CopyEdge = MyCopy, IndexMap = boost::grid_graph_index_map<boost::grid_graph<2u>, boost::array<unsigned int, 2u>, unsigned int>, Orig2CopyVertexIndexMap = boost::iterator_property_map<__gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >, boost::grid_graph_index_map<boost::grid_graph<2u>, boost::array<unsigned int, 2u>, unsigned int>, void*, void*&>]’
/usr/include/boost/graph/copy.hpp:327:5: instantiated from ‘void boost::copy_graph(const VertexListGraph&, MutableGraph&, const boost::bgl_named_params<P, T, R>&) [with VertexListGraph = boost::grid_graph<2u>, MutableGraph = boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, VertexProperties>, P = MyCopy, T = boost::vertex_copy_t, R = boost::bgl_named_params<MyCopy, boost::edge_copy_t>]’
/mnt/home/ajw/code/hpcwales/copytest.cc:31:66: instantiated from here
/usr/include/boost/iterator/transform_iterator.hpp:100:26: error: no matching function for call to ‘boost::detail::grid_graph_vertex_at<boost::grid_graph<2u> >::grid_graph_vertex_at()’
/usr/include/boost/graph/grid_graph.hpp:104:7: note: candidates are: boost::detail::grid_graph_vertex_at<Graph>::grid_graph_vertex_at(const Graph*) [with Graph = boost::grid_graph<2u>]
/usr/include/boost/graph/grid_graph.hpp:100:33: note: boost::detail::grid_graph_vertex_at<boost::grid_graph<2u> >::grid_graph_vertex_at(const boost::detail::grid_graph_vertex_at<boost::grid_graph<2u> >&)
Moja analiza tego błędu jest to, że wydaje się być próba domyślnego skonstruowania części wewnętrznych z grid_graph
, które nie mogą być domyślnie skonstruowane, z jakiegoś powodu, który nie jest dla mnie strasznie jasny. (clang tak naprawdę nie mówi mi nic, czego nie mogę zobaczyć z g ++ tutaj).
Pytania:
- Czy to jest właściwa droga o initalising jest zmienny wykres, aby uruchomić jako zwykły siatki? Początkowo myślałem, że to dużo łatwiejsze niż pisanie funkcji, aby to zrobić sam, ale teraz nie jestem tego taki pewien!
- Dlaczego domyślna wartość
orig_to_copy
i/lubvertex_index
nie jest tutaj odpowiednia? Zakładam, że te dwa są przyczyną błędu. (Które, jeśli jakiekolwiek, faktycznie powodują problem? Nie mogę odczytać przyczyny głównej błędu). - Co to jest "poprawny" sposób naprawy?
Szybkie check: gdy mówimy o nazwanych parametrów ty o niej jako 'named_param1' i' named_param2' całą drogę tekst aż do przykładów, gdzie nagle stał się 'boost :: named_parameter1' i' boost :: named_parameter2' dla pierwszej części łańcucha - czy to literówka? – Flexo
@awoodland: Nie jest to literówka, ponieważ pierwszą jest funkcja * w przestrzeni nazw 'boost', która zwraca obiekt posiadający * metody * dla innych nazwanych parametrów. 'boost :: named_parameter1 (val1) .named_param2 (val2)' najpierw konfiguruje parametr 'named_parameter1', wywołując funkcję' boost :: named_parameter1' *. Następnie konfiguruje parametr 'named_parameter2', wywołując metodę' named_parameter2' * * na obiekcie zwróconym przez 'boost :: named_parameter1()'. –
Okazuje się, że komputer, na którym próbowałem tej odpowiedzi, był oryginalnie uruchomiony 1.46. Na komputerze z wersją 1.42 nie udało się skompilować dokładnie tego samego błędu, który widziałem. Zgaduję, że to błąd w 1.42? Ta odpowiedź wciąż rozwiązuje wszystkie inne problemy, które miałem w mojej próbie, za co jestem bardzo wdzięczny. – Flexo