需要使用boost ::图形从一个大图中找到子图
Need to find sub graphs from one big graph using boost::graph
PH -> PH1
PH -> PH2
PH1 -> N1
PH1 -> N2
PH2 -> N3
PH2 -> N4
需要输出为:
sub graph 1 :
PH1 -> N1
PH1 -> N2
sub graph 2 :
PH2 -> N3
PH2 -> N3
这是几乎使用 connected_components
。
复杂的事情是忽略PH
节点。您没有说该节点是给出的还是应检测到。我写了一些代码来检测它。
让我们开始
#include <boost/graph/adjacency_list.hpp>
using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
boost::property<boost::vertex_name_t, std::string> >;
我们要大致实现以下步骤:
using ComponentId = int;
using Mappings = std::vector<ComponentId>;
using Graphs = std::vector<Graph>;
Graph build();
Mappings map_components(Graph const&);
Graphs split(Graph const&, Mappings const&);
,主程序看起来像
#include <boost/graph/graph_utility.hpp>
int main() {
Graph g = build();
Mappings components = map_components(g);
for (auto& sub : split(g, components)) {
std::cout << "n========================n";
print_graph(sub, get(boost::vertex_name, sub));
}
}
样本数据
这很简单,因为我们使用了vertex_name
属性:
using Vertex = Graph::vertex_descriptor;
Graph build() {
Graph g;
Vertex PH = add_vertex({"PH"}, g);
Vertex PH1 = add_vertex({"PH1"}, g);
Vertex PH2 = add_vertex({"PH2"}, g);
Vertex N1 = add_vertex({"N1"}, g);
Vertex N2 = add_vertex({"N2"}, g);
Vertex N3 = add_vertex({"N3"}, g);
Vertex N4 = add_vertex({"N4"}, g);
add_edge(PH, PH1, g);
add_edge(PH, PH2, g);
add_edge(PH1, N1, g);
add_edge(PH1, N2, g);
add_edge(PH2, N3, g);
add_edge(PH2, N4, g);
return g;
}
映射组件
这还不错:
#include <boost/graph/connected_components.hpp> // connected_components
Mappings naive_components(Graph const& g) {
Mappings mappings(num_vertices(g));
int num = boost::connected_components(g, mappings.data());
return mappings;
}
除了连接所有内容,所以我们得到1个包含所有顶点的组件...让我们使用articulation_points
首先"忽略"顶点:
#include <boost/graph/biconnected_components.hpp> // articulation_points
#include <boost/graph/connected_components.hpp> // connected_components
#include <boost/graph/filtered_graph.hpp>
#include <boost/function.hpp>
using Filtered = boost::filtered_graph<Graph, boost::keep_all, boost::function<bool(Vertex)> >;
Mappings map_components(Graph const& g) {
Mappings mappings(num_vertices(g));
std::vector<Vertex> ap;
articulation_points(g, back_inserter(ap));
if (!ap.empty()) {
// get the articulation point with the lowest degree
nth_element(ap.begin(), ap.begin()+1, ap.end(), [&](Vertex a, Vertex b) { return degree(a, g) < degree(b, g); });
Vertex ignored = ap.front();
std::cout << "Igoring articulation point " << get(boost::vertex_name, g, ignored) << " from graphn";
Filtered fg(g, {}, [&](Vertex v) { return ignored != v; });
int num = boost::connected_components(fg, mappings.data());
mappings[ignored] = num; // make sure the ignored vertex is in its own component
}
return mappings;
}
基本上是在做同样的事情,但它忽略了PH
节点。请注意,我们尝试确保剪切尽可能少的边缘(通过degree
进行排序)。
拆分
将单独的图分解成几乎是一种形式(重复使用相同的Filtered
图表):
#include <boost/graph/copy.hpp>
Graphs split(Graph const& g, Mappings const& components) {
if (components.empty())
return {};
Graphs results;
auto highest = *std::max_element(components.begin(), components.end());
for (int c = 0; c <= highest; ++c) {
results.emplace_back();
boost::copy_graph(Filtered(g, {}, [c, &components](Vertex v) { return components.at(v) == c; }), results.back());
}
return results;
}
完整列表
活在coliru
#include <boost/graph/adjacency_list.hpp>
using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, boost::property<boost::vertex_name_t, std::string> >;
using ComponentId = int;
using Mappings = std::vector<ComponentId>;
using Graphs = std::vector<Graph>;
Graph build();
Mappings map_components(Graph const&);
Graphs split(Graph const&, Mappings const&);
#include <boost/graph/graph_utility.hpp>
int main() {
Graph g = build();
Mappings components = map_components(g);
for (auto& sub : split(g, components)) {
std::cout << "n========================n";
print_graph(sub, get(boost::vertex_name, sub));
}
}
using Vertex = Graph::vertex_descriptor;
Graph build() {
Graph g;
Vertex PH = add_vertex({"PH"}, g);
Vertex PH1 = add_vertex({"PH1"}, g);
Vertex PH2 = add_vertex({"PH2"}, g);
Vertex N1 = add_vertex({"N1"}, g);
Vertex N2 = add_vertex({"N2"}, g);
Vertex N3 = add_vertex({"N3"}, g);
Vertex N4 = add_vertex({"N4"}, g);
add_edge(PH, PH1, g);
add_edge(PH, PH2, g);
add_edge(PH1, N1, g);
add_edge(PH1, N2, g);
add_edge(PH2, N3, g);
add_edge(PH2, N4, g);
return g;
}
#include <boost/graph/biconnected_components.hpp> // articulation_points
#include <boost/graph/connected_components.hpp> // connected_components
#include <boost/graph/filtered_graph.hpp>
#include <boost/function.hpp>
using Filtered = boost::filtered_graph<Graph, boost::keep_all, boost::function<bool(Vertex)> >;
Mappings map_components(Graph const& g) {
Mappings mappings(num_vertices(g));
std::vector<Vertex> ap;
articulation_points(g, back_inserter(ap));
if (!ap.empty()) {
// get the articulation point with the lowest degree
nth_element(ap.begin(), ap.begin()+1, ap.end(), [&](Vertex a, Vertex b) { return degree(a, g) < degree(b, g); });
Vertex ignored = ap.front();
std::cout << "Igoring articulation point " << get(boost::vertex_name, g, ignored) << " from graphn";
Filtered fg(g, {}, [&](Vertex v) { return ignored != v; });
int num = boost::connected_components(fg, mappings.data());
mappings[ignored] = num; // make sure the ignored vertex is in its own component
}
return mappings;
}
#include <boost/graph/copy.hpp>
Graphs split(Graph const& g, Mappings const& components) {
if (components.empty())
return {};
Graphs results;
auto highest = *std::max_element(components.begin(), components.end());
for (int c = 0; c <= highest; ++c) {
results.emplace_back();
boost::copy_graph(Filtered(g, {}, [c, &components](Vertex v) { return components.at(v) == c; }), results.back());
}
return results;
}
打印
Igoring articulation point PH from graph
========================
PH1 --> N1 N2
N1 -->
N2 -->
========================
PH2 --> N3 N4
N3 -->
N4 -->
========================
PH -->
相关文章:
- 如何在 boost 中访问现有图的子图
- 以编程方式连接子图
- 使用C Visual Studio创建一个绘图图
- 需要使用boost ::图形从一个大图中找到子图
- 子图的图形特征
- 提升图相等性和子图
- 如何删除提升图的子图
- 子图和图连接在提升
- Boost子图复制构造函数不适用于Qt 5.0.2和MinGW
- 如何访问提升子图'graph'属性?
- 使用write_graphviz()打印组成的子图
- Boost子图实现和使用Graphml导出
- 是否有任何方法可以使用c++ libgraph为子图设置默认节点属性?
- 我应该用过滤图还是子图,还是别的什么
- 为什么Boost VF2子图同构给出一个不正确的答案
- 图的子图求值问题
- Boost子图和捆绑属性
- 查找子图中的边
- 如何有效地实现具有大量大完整子图的图
- 如何在一个完整图的每条边上迭代一次