Files
easy-graph--easy-graph/cpp_easygraph/functions/community/subgraph.cpp
T
2026-07-13 12:36:30 +08:00

180 lines
6.9 KiB
C++

#include "subgraph.h"
#include "../../classes/graph.h"
#include "../../classes/directed_graph.h"
#include "../../common/utils.h"
static node_t _add_one_node_for_subgraph(Graph& self, py::object one_node_for_adding, py::object node_attr = py::dict()) {
node_t id;
if (self.node_to_id.contains(one_node_for_adding)) {
id = self.node_to_id[one_node_for_adding].cast<node_t>();
} else {
id = ++(self.id);
self.id_to_node[py::cast(id)] = one_node_for_adding;
self.node_to_id[one_node_for_adding] = id;
}
py::list items = py::list(node_attr.attr("items")());
self.node[id] = node_attr_dict_factory();
for (int i = 0; i < len(items); i++) {
py::tuple kv = items[i].cast<py::tuple>();
py::object pkey = kv[0];
std::string weight_key = weight_to_string(pkey);
weight_t value = kv[1].cast<weight_t>();
self.node[id].insert(std::make_pair(weight_key, value));
}
return id;
}
static void _add_one_edge_for_subgraph(Graph& self, node_t u, node_t v, py::object edge_attr) {
py::list items = py::list(edge_attr.attr("items")());
self.adj[u][v] = node_attr_dict_factory();
self.adj[v][u] = node_attr_dict_factory();
for (int i = 0; i < len(items); i++) {
py::tuple kv = items[i].cast<py::tuple>();
py::object pkey = kv[0];
std::string weight_key = weight_to_string(pkey);
weight_t value = kv[1].cast<weight_t>();
self.adj[u][v].insert(std::make_pair(weight_key, value));
self.adj[v][u].insert(std::make_pair(weight_key, value));
}
}
static py::object _nodes_subgraph_cpp_graph(py::object self, std::vector<node_t>& node_ids) {
Graph& self_ = self.cast<Graph&>();
py::object G = self.attr("__class__")();
Graph& G_ = G.cast<Graph&>();
G_.graph.attr("update")(self_.graph);
py::object nodes = self.attr("nodes");
py::object adj = self.attr("adj");
// 修复:维护原图内部索引到新图内部索引的映射
std::unordered_map<node_t, node_t> old_id_to_new_id;
// 第一遍:添加所有节点并建立映射
for (node_t node_id : node_ids) {
py::object node = self_.id_to_node[py::cast(node_id)];
py::object node_attr = nodes[node];
node_t new_id = _add_one_node_for_subgraph(G_, node, node_attr);
old_id_to_new_id[node_id] = new_id;
}
// 第二遍:添加边(使用映射后的索引)
for (node_t node_id : node_ids) {
py::object node = self_.id_to_node[py::cast(node_id)];
py::object out_edges = adj[node];
py::list edge_items = py::list(out_edges.attr("items")());
// 获取当前节点的新索引
node_t new_u = old_id_to_new_id[node_id];
for (int j = 0; j < py::len(edge_items); j++) {
py::tuple item = edge_items[j].cast<py::tuple>();
py::object v = item[0];
py::object edge_attr = item[1];
if (self_.node_to_id.contains(v)) {
node_t v_id = self_.node_to_id[v].cast<node_t>();
bool v_in_subgraph = std::find(node_ids.begin(), node_ids.end(), v_id) != node_ids.end();
if (v_in_subgraph) {
// 使用映射后的索引
node_t new_v = old_id_to_new_id[v_id];
_add_one_edge_for_subgraph(G_, new_u, new_v, edge_attr);
}
}
}
}
return G;
}
static node_t DiGraph_add_one_node_for_subgraph(DiGraph& self, py::object one_node_for_adding, py::object node_attr = py::dict()) {
node_t id;
if (self.node_to_id.contains(one_node_for_adding)) {
id = self.node_to_id[one_node_for_adding].cast<node_t>();
} else {
id = ++(self.id);
self.id_to_node[py::cast(id)] = one_node_for_adding;
self.node_to_id[one_node_for_adding] = id;
}
py::list items = py::list(node_attr.attr("items")());
self.node[id] = node_attr_dict_factory();
for (int i = 0; i < len(items); i++) {
py::tuple kv = items[i].cast<py::tuple>();
py::object pkey = kv[0];
std::string weight_key = weight_to_string(pkey);
weight_t value = kv[1].cast<weight_t>();
self.node[id].insert(std::make_pair(weight_key, value));
}
return id;
}
static void DiGraph_add_one_edge_for_subgraph(DiGraph& self, node_t u, node_t v, py::object edge_attr) {
py::list items = py::list(edge_attr.attr("items")());
self.adj[u][v] = node_attr_dict_factory();
for (int i = 0; i < len(items); i++) {
py::tuple kv = items[i].cast<py::tuple>();
py::object pkey = kv[0];
std::string weight_key = weight_to_string(pkey);
weight_t value = kv[1].cast<weight_t>();
self.adj[u][v].insert(std::make_pair(weight_key, value));
}
}
static py::object _nodes_subgraph_cpp_digraph(py::object self, std::vector<node_t>& node_ids) {
DiGraph& self_ = self.cast<DiGraph&>();
py::object G = self.attr("__class__")();
DiGraph& G_ = G.cast<DiGraph&>();
G_.graph.attr("update")(self_.graph);
py::object nodes = self.attr("nodes");
py::object adj = self.attr("adj");
// 修复:维护原图内部索引到新图内部索引的映射
std::unordered_map<node_t, node_t> old_id_to_new_id;
// 第一遍:添加所有节点并建立映射
for (node_t node_id : node_ids) {
py::object node = self_.id_to_node[py::cast(node_id)];
py::object node_attr = nodes[node];
node_t new_id = DiGraph_add_one_node_for_subgraph(G_, node, node_attr);
old_id_to_new_id[node_id] = new_id;
}
// 第二遍:添加边(使用映射后的索引)
for (node_t node_id : node_ids) {
py::object node = self_.id_to_node[py::cast(node_id)];
py::object out_edges = adj[node];
py::list edge_items = py::list(out_edges.attr("items")());
// 获取当前节点的新索引
node_t new_u = old_id_to_new_id[node_id];
for (int j = 0; j < py::len(edge_items); j++) {
py::tuple item = edge_items[j].cast<py::tuple>();
py::object v = item[0];
py::object edge_attr = item[1];
if (self_.node_to_id.contains(v)) {
node_t v_id = self_.node_to_id[v].cast<node_t>();
bool v_in_subgraph = std::find(node_ids.begin(), node_ids.end(), v_id) != node_ids.end();
if (v_in_subgraph) {
// 使用映射后的索引
node_t new_v = old_id_to_new_id[v_id];
DiGraph_add_one_edge_for_subgraph(G_, new_u, new_v, edge_attr);
}
}
}
}
return G;
}
py::object nodes_subgraph_cpp(py::object self, std::vector<node_t>& node_ids) {
bool is_directed = self.attr("is_directed")().cast<bool>();
if (is_directed) {
return _nodes_subgraph_cpp_digraph(self, node_ids);
} else {
return _nodes_subgraph_cpp_graph(self, node_ids);
}
}