- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我主要使用自己的网络流算法。但是,我最近才开始使用 boost,但在定义图形时遇到了困难。更具体地说,我自己的代码中的顶点编号为 0 到 n-1。边从 0 到 m-1 编号。我正在尝试构建一个非常简单的 4 边网络。
所有四个边的容量都是 4 个单元。我正在寻找 boost 以找到从 s = 0 到 t = 3 的最大流量。(答案是 8。)
为了让它运行,我有以下代码,但尽管它编译和构建没有错误,但代码没有按照我的预期进行。有关我的具体问题,请参阅代码中的注释。有两个问题(Q1)和(Q2)。
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
#include <boost/graph/push_relabel_max_flow.hpp>
#include <boost/graph/edmonds_karp_max_flow.hpp>
using namespace boost;
typedef adjacency_list_traits < vecS, vecS, directedS > Traits;
typedef adjacency_list < vecS, vecS, directedS,
property < vertex_name_t, std::string,
property < vertex_index_t, int,
property < vertex_color_t, boost::default_color_type,
property < vertex_distance_t, double,
property < vertex_predecessor_t, Traits::edge_descriptor > > > > >,
property < edge_index_t, int,
property < edge_capacity_t, double,
property < edge_weight_t, double,
property < edge_residual_capacity_t, double,
property < edge_reverse_t, Traits::edge_descriptor > > > > > > Graph;
int main()
{
Graph g;
property_map<Graph, vertex_index_t>::type v = get(vertex_index, g);
property_map<Graph, edge_index_t>::type e = get(edge_index, g);
property_map<Graph, edge_capacity_t>::type cap = get(edge_capacity, g);
property_map<Graph, edge_weight_t>::type cost = get(edge_weight, g);
property_map<Graph, edge_residual_capacity_t>::type rescap = get(edge_residual_capacity, g);
property_map < Graph, edge_reverse_t >::type rev = get(edge_reverse, g);
int nonodes = 4;
for (int i = 0; i < nonodes; i++) {
Traits::vertex_descriptor vd;
vd = add_vertex(g);
assert(v[vd] == i);//(Q1)Here, v[vd] = i; produces an error. Is there any other way to assign integer indices to vertices?
}
Graph::vertex_iterator vertexIt, vertexEnd;
tie(vertexIt, vertexEnd) = vertices(g);
//Create edges
Traits::edge_descriptor edf, edb;//Max flow algorithms seem to want both forward and backward edges. edf is for forward, edb is for backward
//Q2. All of the add_edge() functions below do not seem to add any edges to the graph, leading to a run time error when boykov_kolmogorov_max_flow() is finally called.
edf = (add_edge(*(vertexIt+0), *(vertexIt + 1), g)).first;
edb = (add_edge(*(vertexIt + 1), *(vertexIt + 0), g)).first;
e[edf] = 0;
e[edb] = 1;
cap[edf] = 4;
cap[edb] = 4;
edf = (add_edge(*(vertexIt + 0), *(vertexIt + 2), g)).first;
edb = (add_edge(*(vertexIt + 2), *(vertexIt + 0), g)).first;
e[edf] = 2;
e[edb] = 3;
cap[edf] = 4;
cap[edb] = 4;
edf = (add_edge(*(vertexIt + 1), *(vertexIt + 3), g)).first;
edb = (add_edge(*(vertexIt + 3), *(vertexIt + 1), g)).first;
e[edf] = 4;
e[edb] = 5;
cap[edf] = 4;
cap[edb] = 4;
edf = (add_edge(*(vertexIt + 2), *(vertexIt + 3), g)).first;
edb = (add_edge(*(vertexIt + 3), *(vertexIt + 2), g)).first;
e[edf] = 6;
e[edb] = 7;
cap[edf] = 4;
cap[edb] = 4;
double flow = boykov_kolmogorov_max_flow(g, *(vertexIt + 0), *(vertexIt + 3));
return 0;
}
关于问题 1)我查找了提供的解决方案 On C++ Boost Graph Creation and the vertex_index Property. .但是,我不清楚为什么 v[vd] = i;
会导致编译时错误,但 e[edf] = 0;
之后不会导致编译时间错误。
关于问题 2)我真正想要的是一种访问顶点以传递给 add_edge()
函数的方法。更一般地说,有没有一种方法可以通过诸如 vertex[2]
之类的某种机制访问第二条边(从 0 开始计数),或者通过诸如 edge[3]
等?
最佳答案
i); //(Q1)Here, v[vd] = i; produces an error. Is there any other way to assign integer indices to vertices?
当您使用 vecS
时,顶点索引是隐式 并且是顶点 vector 的整数索引。因此,如果不对周围的顶点进行物理洗牌,就无法分配它。
但是,您可以在没有内置隐式顶点索引的情况下自由操作,方法是选择一个非随机访问的顶点容器,例如listS
.
但是:如果这样做,您(显然)可以不再使用 ID 作为顶点描述符,使所有代码都像
edf = (add_edge(*(vertexIt + 0), *(vertexIt + 1), g)).first;
edb = (add_edge(*(vertexIt + 1), *(vertexIt + 0), g)).first;
很笨拙,更像是
auto find_vertex_by_id = [&g](size_t id) {
for(auto vd : boost::make_iterator_range(boost::vertices(g)))
if (id == g[vd])
return vd;
throw std::range_error("vertex id " + std::to_string(id));
};
edf = (add_edge(find_vertex_by_id(g[*vertexIt].id + 0), find_vertex_by_id(g[*vertexIt].id + 1), g)).first;
edb = (add_edge(find_vertex_by_id(g[*vertexIt].id + 1), find_vertex_by_id(g[*vertexIt].id + 0), u)).first;
查看 Live On Coliru ,我希望你同意这会加重病情。
Note it also crashes. Don't worry, that's a minor issue (mainly because the reverse edge map is not built up correctly). Fixing that, quickly, gives you the elusive
Flow: 8
! Sneak Preview
我建议走另一条路!拥抱隐式顶点索引,它与描述符类型一致。然后,不要为迭代器的迂回方式而烦恼,只需绝对地址:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
#include <boost/graph/edmonds_karp_max_flow.hpp>
#include <boost/graph/push_relabel_max_flow.hpp>
#include <iostream>
using namespace boost;
typedef adjacency_list_traits<vecS, vecS, directedS> Traits;
typedef adjacency_list<
vecS, vecS, directedS,
property<
vertex_name_t, std::string,
property<vertex_index_t, int,
property<vertex_color_t, boost::default_color_type,
property<vertex_distance_t, double,
property<vertex_predecessor_t, Traits::edge_descriptor>
> > > >,
property<
edge_index_t, int,
property<edge_capacity_t, double,
property<edge_weight_t, double,
property<edge_residual_capacity_t, double,
property<edge_reverse_t, Traits::edge_descriptor>
> > > > >
Graph;
int main() {
Graph g;
property_map<Graph, edge_index_t>::type e = get(edge_index, g);
property_map<Graph, edge_capacity_t>::type cap = get(edge_capacity, g);
//property_map<Graph, edge_weight_t>::type cost = get(edge_weight, g);
//property_map<Graph, edge_residual_capacity_t>::type rescap = get(edge_residual_capacity, g);
property_map<Graph, edge_reverse_t>::type rev = get(edge_reverse, g);
int nonodes = 4;
for (int i = 0; i < nonodes; i++) {
Traits::vertex_descriptor vd;
vd = add_vertex(g);
assert(vd == i);
}
// Create edges
Traits::edge_descriptor edf, edb; // Max flow algorithms seem to want both forward and backward edges. edf is for
// forward, edb is for backward
// Q2. All of the add_edge() functions below do not seem to add any edges to the graph, leading to a run time error
// when boykov_kolmogorov_max_flow() is finally called.
edf = (add_edge(0, 1, g)).first;
edb = (add_edge(1, 0, g)).first;
e[edf] = 0;
e[edb] = 1;
cap[edf] = 4;
cap[edb] = 4;
rev[edf] = edb;
rev[edb] = edf;
edf = (add_edge(0, 2, g)).first;
edb = (add_edge(2, 0, g)).first;
e[edf] = 2;
e[edb] = 3;
cap[edf] = 4;
cap[edb] = 4;
rev[edf] = edb;
rev[edb] = edf;
edf = (add_edge(1, 3, g)).first;
edb = (add_edge(3, 1, g)).first;
e[edf] = 4;
e[edb] = 5;
cap[edf] = 4;
cap[edb] = 4;
rev[edf] = edb;
rev[edb] = edf;
edf = (add_edge(2, 3, g)).first;
edb = (add_edge(3, 2, g)).first;
e[edf] = 6;
e[edb] = 7;
cap[edf] = 4;
cap[edb] = 4;
rev[edf] = edb;
rev[edb] = edf;
double flow = boykov_kolmogorov_max_flow(g, 0, 3);
std::cout << "Flow: " << flow << "\n";
}
打印
Flow: 8
那不是更好吗?现在,让我们继续改进那些仍然丑陋/烦人的东西
add_vertex
循环现在看起来相当无能:
for (int i = 0; i < nonodes; i++) {
Traits::vertex_descriptor vd;
vd = add_vertex(g);
assert(vd == i);
}
确实,让我们写:
Graph g(nonodes);
以必须将属性映射传递给算法为代价,您可以使用 Bundled Properties 使构建图形更容易接受。 :
等等 - 什么?那不是改进,是吗?好吧,等你看到这个:
struct { int from,to; } edges[] = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, };
int edge_id = 0;
for (auto& edge : edges) {
auto edf = add_edge(edge.from, edge.to, EdgeProperty{edge_id++, 4}, g).first,
edb = add_edge(edge.to, edge.from, EdgeProperty{edge_id++, 4}, g).first;
rev[edf] = edb;
rev[edb] = edf;
}
耶!
那些特定于流算法的属性并不真正属于图中,那么为什么要包含它们呢?让我们做一些花哨的步法并使用外部 map 。这开始变得更先进了,但真正让我们明白了属性映射的要点:它们就像C++ 的镜头。
未发表评论:
#include <boost/graph/adjacency_list.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
#include <functional>
#include <iostream>
using namespace boost;
struct VertexProperty { std::string name; };
struct EdgeProperty {
int id;
double capacity, residual_capacity;
EdgeProperty(int id, double cap, double res = 0)
: id(id), capacity(cap), residual_capacity(res)
{ }
};
typedef adjacency_list<vecS, vecS, directedS, VertexProperty, EdgeProperty> Graph;
int main() {
int nonodes = 4;
Graph g(nonodes);
// reverse edge map
auto e = get(&EdgeProperty::id, g);
auto rev = make_vector_property_map<Graph::edge_descriptor>(e);
// Create edges
struct { int from,to; } edges[] = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 }, };
int edge_id = 0;
for (auto& pair : edges) {
auto a = add_edge(pair.from, pair.to, EdgeProperty { edge_id++, 4 }, g).first;
auto b = add_edge(pair.to, pair.from, EdgeProperty { edge_id++, 4 }, g).first;
rev[a] = b;
rev[b] = a;
}
// property maps
struct VertexEx {
default_color_type color;
double distance;
Graph::edge_descriptor pred;
};
auto idx = get(vertex_index, g);
auto vex = make_vector_property_map<VertexEx>(idx);
auto pred = make_transform_value_property_map(std::mem_fn(&VertexEx::pred), vex);
auto color = make_transform_value_property_map(std::mem_fn(&VertexEx::color), vex);
auto dist = make_transform_value_property_map(std::mem_fn(&VertexEx::distance), vex);
auto cap = get(&EdgeProperty::capacity, g);
auto rescap = get(&EdgeProperty::residual_capacity, g);
// algorithm
double flow = boykov_kolmogorov_max_flow(g, cap, rescap, rev, pred, color, dist, idx, 0, 3);
std::cout << "Flow: " << flow << "\n";
}
Live On Coliru ,评论更少。
关于c++ - 访问 boost::graph 中的特定顶点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45925625/
我想使用图中所示的迷宫,使用迭代深度优先搜索找到从起始节点到目标的路径。它是一个仅包含一对数字的文本文件,例如成对连接,又称边/弧。像这样: 11 3 2 3 0 3 1 4 5 4 5 7 6 7
问题:您有一个无向图 G = (V, E)(V = 顶点,E = 边),您必须访问每个顶点并在两个方向上通过每个边。 我所知道的图算法只有 DFS、BFS 和一些 MST(Kruskal 等)不幸的是
枚举任意图中两个顶点之间的所有简单路径通常需要指数时间,因为顶点之间可能存在指数数量的简单路径。但是,如果我们只对位于两个末端顶点之间的至少一条简单路径上的顶点怎么办? 即:给定一个无向图和两个不同的
我正在开发一个简单的 opengl 游戏以了解更多相关信息。但是由于某种原因,当我尝试随时间旋转我的立方体时,它会被拉伸(stretch)。你可以在照片中看到它: 我认为这与我的模型矩阵有关,但我不确
我已经在谷歌上搜索了很长一段时间,但我找不到任何东西。如何使用 Graphviz 绘制没有连接顶点的图形? 最佳答案 像这样: digraph g { SingleNode; } 简单地不定义
我目前正在使用 R 中的“igraph”包进行一些社交网络分析,我想知道是否有一种方法可以个性化社交网络中节点的放置。 例如,使用以下玩具代码: library(igraph) edg
我在 Box2D 中有一个多边形形状。形状是一个三角形,我希望有 3 个顶点。事实上,我创建的所有形状都会输出 8 个顶点。为什么是这样?如果我输出顶点数,那总是正确的数量。我不想渲染不必要的线条,但
来自user manual CGAL Surface_mesh 类: the data structure uses integer indices as descriptors for vertic
我正在尝试找到引用 ARFaceGeometry 网格索引的方法为了使用 ARKit 将图形放置在面部的特定部位。 我见过很多例子,其中功能与一些索引号,但我找不到对此列表的任何引用。它似乎有超过12
Apache TomCat(版本未知) 业务对象 4.1 顶点 4.4.3 在一台服务器上,我们拥有 TomCat 和 Business Objects。 APEX 也使用 TomCat。 在对我们的
我正在使用 MX Graph 进行一些工作,以帮助识别网站中的关键内容路径。我将其设置为每个顶点代表网站上的一个页面,每条边代表一组从页面 A 访问页面 B 的访问者。 一切都运行良好,除了边太多,我
我正在尝试使用三角形 strip 绘制一个平面。我了解如何手动执行此操作,但我真的很难使用 for 循环来执行此操作。到目前为止,下面的代码绘制了两个三角形。 //vertices for trian
如果我想通过 id 顶点获取名称,我可以使用这个函数:VAS(g, "name",id)但是如果我想要相反的方式,通过名称获取 id,我该怎么做呢? 最佳答案 igraph 本身不提供按名称查找顶点的
我有一个三角形,其任意顶点位于 3D 空间中。 我知道通过以下操作很容易找到这种三角形的质心: float centroid[3] = { 0, 0, 0 }; for (int i = 0; i =
我有一个点数组。每个点都有位置(x, y, z) 和法 vector (xn, yn, zn) ,一共6个 double 。考虑到浮点容差,我需要在此数组中找到唯一元素并删除重复条目。 实现它的简单有
我有一个相互连接的边列表 (E),如何找到从一个顶点连接到另一个顶点的最短路径? 我正在考虑使用 lowest common ancestors ,但边缘没有明确定义的根,所以我认为该解决方案不起作用
我现在正在使用计算着色器开发粒子系统。我将所有粒子都放在着色器存储缓冲区中。一个粒子包含两个顶点,当前位置和先前位置。 struct Particle{ glm::vec4 _currPo
我将我的顶点剪裁在边缘上,如这张专辑所示: http://imgur.com/a/VkCrJ 当我的地形大小为 400 x 400 时,我得到裁剪,但在 40x40 或更小时,我没有得到任何裁剪。这是
总是在顶点着色器中而不是在片段着色器中更好地进行硬计算吗?即使是具有超过 100.000 个多边形的高网格模型(假设有一堆独特的顶点)? 最佳答案 不,它并不总是更好。 选择合适的计算位置的最佳方法是
我想编辑一个立方体上的 1 个顶点,但我不知道该怎么做。我试过到处寻找此功能,但找不到解决方案。 这是我想要实现的目标的图像: 最佳答案 http://answers.unity3d.com/ques
我是一名优秀的程序员,十分优秀!