gpt4 book ai didi

c++ - 使用 boost::copy_graph 从 grid_graph 复制到 adjacency_list

转载 作者:可可西里 更新时间:2023-11-01 18:27:35 29 4
gpt4 key购买 nike

我正在使用 boost 图形库并尝试初始化 MutableGraph以网格的形式开始生活。边缘会在以后的生活中添加和删除,所以我认为 adjacency_list<vecS,listS,undirectedS>是正确的选择。

我对 BGL 的阅读表明,用这些边缘初始化它的明智方法是利用 boost::grid_graph通过使用 boost::copy_graphboost::grid_graph 复制可以免费为我制作所有初始边缘。我认为这是有道理的 - copy_graph来自 VertexListGraph 模型的拷贝到一个模型 MutableGraph ,这正是我所拥有的。

我最初尝试使用 copy_graph 的双参数版本, 带着模糊的希望,其余部分的默认值会发生一些明智的事情。事实并非如此,grid_graph (出于我不太清楚的原因)似乎没有使用 PropertyMap 的工具s 有边或顶点,所以默认 vertex_copyedge_copy复制属性失败(编译器错误)。

由于 2 参数版本显然不合适,我继续并尝试实现我自己的二元运算符来复制顶点和边。即使使用“无操作”拷贝,它也无法像我希望的那样工作(即无法编译)。

我整理了一个最小的工作示例来说明问题:

#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));
}

这个例子不能编译:

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> >&)

我对该错误的分析是,它似乎试图默认构造 grid_graph 的部分内部结构。 ,由于某些我不太清楚的原因,它不能被默认构造。(clang 并没有真正告诉我任何我在这里从 g++ 中看不到的信息)。

问题:

  1. 这是将可变图初始化为常规网格的正确方法吗?我最初认为这样做比自己编写一个函数要容易得多,但现在我不太确定了!
  2. 为什么默认值为orig_to_copy和/或 vertex_index在这里不合适?我假设这两个是错误的原因。 (如果有的话,哪一个实际上是导致问题的原因?我无法破译当前错误的根本原因是什么)。
  3. 解决此问题的“正确”方法是什么?

最佳答案

您的方向是正确的,但是您的代码中有两处需要更改。首先是有一种定义自定义顶点属性的特殊方法。第二个是 BGL 命名参数有不同的语法(更受欢迎,可能是唯一正确的语法)。

关于第一项,请引用the section of the documentation titled Custom Vertex Properties .本质上,为了定义自定义顶点属性,您需要首先定义一个“标记类型”(一个名称以 _t 结尾的 struct):

struct vertex_position_t {
typedef boost::vertex_property_tag kind;
};

然后您在定义内部存储的顶点属性的 boost::property 模板中的某处包含标记类型:

typedef boost::property<boost::vertex_index_t, std::size_t,
boost::property<vertex_position_t, Position> > VertexProperties;

上面的 typedef 定义了两个内部存储的属性:索引和自定义“位置”。

关于第二项,the preferred way使用命名参数是一种“类似方法链接”的语法。例如,如果一个函数接受两个命名参数,named_pa​​ram1named_pa​​ram2,则在 boost 命名空间中有两个函数名为 named_pa​​ram1named_pa​​ram2,恭敬地。 boost::named_pa​​ram1 函数接受 named_pa​​ram1 参数的值并返回一个具有 named_pa​​ram2 方法 的对象(类似地,boost::named_pa​​ram2 函数接受 named_pa​​ram2 参数的值并返回一个具有 named_pa​​ram1 方法).您调用该方法来设置该命名参数的值(这又会返回另一个对象,该对象具有其他支持的命名参数的方法)。

为了传递命名参数 named_pa​​ram1named_pa​​ram2 的值 val1val2,您可以使用:

boost::named_parameter1(val1).named_param2(val2)

或:

boost::named_parameter2(val2).named_param1(val1)

作为引用,这里有一个完整的程序,可以将网格复制到 Graph 类型的对象中:

#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/copy.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/grid_graph.hpp>
#include <boost/property_map/property_map.hpp>

struct vertex_position_t {
typedef boost::vertex_property_tag kind;
};

struct Position {
std::size_t x, y;

Position()
: x(0), y(0)
{
}
};

typedef boost::property<boost::vertex_index_t, std::size_t, boost::property<vertex_position_t, Position> > VertexProperties;
typedef boost::adjacency_list<boost::vecS, boost::listS, boost::undirectedS, VertexProperties> Graph;
typedef boost::graph_traits<Graph> GraphTraits;

namespace detail {
typedef boost::grid_graph<2> Grid;
typedef boost::graph_traits<Grid> GridTraits;

struct grid_to_graph_vertex_copier {
typedef boost::property_map< Grid, boost::vertex_index_t>::type grid_vertex_index_map;
typedef boost::property_map< ::Graph, boost::vertex_index_t>::type graph_vertex_index_map;
typedef boost::property_map< ::Graph, ::vertex_position_t>::type graph_vertex_position_map;

const Grid& grid;
grid_vertex_index_map grid_vertex_index;
graph_vertex_index_map graph_vertex_index;
graph_vertex_position_map graph_vertex_position;

grid_to_graph_vertex_copier(const Grid& grid_, Graph& graph)
: grid(grid_), grid_vertex_index(get(boost::vertex_index_t(), grid_)),
graph_vertex_index(get(boost::vertex_index_t(), graph)),
graph_vertex_position(get(::vertex_position_t(), graph))
{
}

private:
Position grid_vertex_index_to_position(std::size_t idx) const {
unsigned num_dims = grid.dimensions();
assert(grid.dimensions() == 2);

idx %= grid.length(0) * grid.length(1);

Position ret;
ret.x = idx % grid.length(0);
ret.y = idx / grid.length(0);

return ret;
}

public:
void operator()(GridTraits::vertex_descriptor grid_vertex, ::GraphTraits::vertex_descriptor graph_vertex) const {
std::size_t idx = get(grid_vertex_index, grid_vertex);
put(graph_vertex_index, graph_vertex, idx);
Position pos = grid_vertex_index_to_position(idx);
std::cout << "grid_vertex = " << idx << ", pos.x = " << pos.x << ", pos.y = " << pos.y << std::endl;
put(graph_vertex_position, graph_vertex, pos);
}
};

struct grid_to_graph_edge_copier {
void operator()(GridTraits::edge_descriptor grid_edge, ::GraphTraits::edge_descriptor graph_edge) const {
}
};
}

int main()
{
boost::array<std::size_t, 2> lengths = { { 3, 5 } };
detail::Grid grid(lengths);

Graph graph;

boost::copy_graph(grid, graph, boost::vertex_copy(detail::grid_to_graph_vertex_copier(grid, graph))
.edge_copy(detail::grid_to_graph_edge_copier()));

std::cout << std::endl;
boost::write_graphviz(std::cout, graph);

return EXIT_SUCCESS;
}

当我运行它时,我收到了以下输出:

grid_vertex = 0, pos.x = 0, pos.y = 0grid_vertex = 1, pos.x = 1, pos.y = 0grid_vertex = 2, pos.x = 2, pos.y = 0grid_vertex = 3, pos.x = 0, pos.y = 1grid_vertex = 4, pos.x = 1, pos.y = 1grid_vertex = 5, pos.x = 2, pos.y = 1grid_vertex = 6, pos.x = 0, pos.y = 2grid_vertex = 7, pos.x = 1, pos.y = 2grid_vertex = 8, pos.x = 2, pos.y = 2grid_vertex = 9, pos.x = 0, pos.y = 3grid_vertex = 10, pos.x = 1, pos.y = 3grid_vertex = 11, pos.x = 2, pos.y = 3grid_vertex = 12, pos.x = 0, pos.y = 4grid_vertex = 13, pos.x = 1, pos.y = 4grid_vertex = 14, pos.x = 2, pos.y = 4graph G {0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;0--1 ;1--2 ;3--4 ;4--5 ;6--7 ;7--8 ;9--10 ;10--11 ;12--13 ;13--14 ;1--0 ;2--1 ;4--3 ;5--4 ;7--6 ;8--7 ;10--9 ;11--10 ;13--12 ;14--13 ;0--3 ;1--4 ;2--5 ;3--6 ;4--7 ;5--8 ;6--9 ;7--10 ;8--11 ;9--12 ;10--13 ;11--14 ;3--0 ;4--1 ;5--2 ;6--3 ;7--4 ;8--5 ;9--6 ;10--7 ;11--8 ;12--9 ;13--10 ;14--11 ;}

关于c++ - 使用 boost::copy_graph 从 grid_graph 复制到 adjacency_list,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7532675/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com