如何在AGE源码中创建GRAPH_global_context实现Barabási-Albert图生成
在AGE中使用
GRAPH_global_context实现Barabási-Albert图生成 GRAPH_global_context是AGE中管理图全局状态的核心结构,它维护了顶点表、边表、哈希索引等元数据,所有需要访问顶点/边详细信息的操作(比如你提到的get_vertex_entry、get_vertex_entry_edges_out)都依赖它。以下是在图生成逻辑中正确创建和使用该结构的步骤:
1. 初始化GRAPH_global_context
首先需要调用AGE提供的初始化函数创建实例,这个函数会完成内部哈希表、锁资源的初始化:
#include "age_graph.h" GRAPH_global_context *ggctx = init_graph_global_context(); if (!ggctx) { // 处理初始化失败(比如内存分配错误) return NULL; }
2. 结合Barabási-Albert生成流程使用
Barabási-Albert图的核心是偏好依附规则,需要频繁获取现有顶点的边数,这正好依赖GRAPH_global_context提供的接口。以下是简化的生成逻辑框架:
步骤1:生成初始顶点集
先创建初始的m0个顶点,并将它们连接成完全图:
// 示例:初始3个顶点 graphid initial_vids[3]; for (int i = 0; i < 3; i++) { // create_vertex会自动将顶点注册到ggctx的顶点表中 initial_vids[i] = create_vertex(ggctx, "BA_Vertex", NULL); } // 连接初始顶点为完全图 for (int i = 0; i < 3; i++) { for (int j = i + 1; j < 3; j++) { create_edge(ggctx, initial_vids[i], initial_vids[j], "Connects", NULL); } }
步骤2:新增顶点并按偏好依附规则连接
对每个新增顶点,遍历现有顶点,通过get_vertex_entry和get_vertex_entry_edges_out获取顶点度数,计算连接概率:
const int total_nodes = 100; // 目标总顶点数 const int m = 2; // 每个新顶点连接2个现有顶点 // 维护现有顶点ID列表(也可通过ggctx遍历顶点表实现) ListGraphId *existing_vids = list_graphid_create(); for (int i = 0; i < 3; i++) { list_graphid_append(existing_vids, initial_vids[i]); } for (int i = 3; i < total_nodes; i++) { graphid new_vid = create_vertex(ggctx, "BA_Vertex", NULL); list_graphid_append(existing_vids, new_vid); // 计算所有现有顶点的总度数 int total_degree = 0; for (int k = 0; k < existing_vids->length - 1; k++) { vertex_entry *ve = get_vertex_entry(ggctx, existing_vids->elements[k]); ListGraphId *out_edges = get_vertex_entry_edges_out(ve); total_degree += out_edges->length; free_list_graphid(out_edges); // 释放临时列表 } // 按偏好依附选择m个顶点连接 int connected = 0; while (connected < m) { int rand_idx = rand() % (existing_vids->length - 1); graphid target_vid = existing_vids->elements[rand_idx]; vertex_entry *target_ve = get_vertex_entry(ggctx, target_vid); ListGraphId *target_edges = get_vertex_entry_edges_out(target_ve); float attach_prob = (float)target_edges->length / total_degree; free_list_graphid(target_edges); // 随机判定是否连接 if ((float)rand() / RAND_MAX < attach_prob) { create_edge(ggctx, new_vid, target_vid, "Connects", NULL); connected++; } } } free_list_graphid(existing_vids);
3. 清理资源
图生成完成后,必须调用清理函数释放GRAPH_global_context的所有资源,避免内存泄漏:
free_graph_global_context(ggctx);
关键注意事项
- 生命周期一致性:所有依赖
ggctx的操作(如get_vertex_entry、create_edge)必须在init_graph_global_context之后、free_graph_global_context之前执行。 - 临时资源释放:调用
get_vertex_entry_edges_out返回的ListGraphId必须用free_list_graphid手动释放,否则会造成内存泄漏。 - PostgreSQL环境适配:如果是在PostgreSQL扩展中开发图生成函数,
GRAPH_global_context通常由AGE的上层查询框架管理,无需手动初始化,但需要从查询上下文(如QueryDesc)中获取实例。
内容的提问来源于stack exchange,提问作者Matheus Farias
相关产品推荐
相关产品推荐

