我一直在研究我的图形/网络问题,我想我终于知道我想做什么了。现在我正在进入实现,我在决定使用哪些库时遇到了问题。该图本身非常简单,每个节点都由一个字符串标记,每个节点都是两个节点(变量)之间的概率/相关系数,并且是无向的。我想在图上执行的操作是:
- 插入新节点/边(快速)
- 找到所有对最短(1/概率)路径,并记住路径中的节点 - 可能是约翰逊的算法
- 为 k 个特定顶点构造最小权重 Steiner 树
- 使用约翰逊算法构建最短路径
- 遍历路径 p 中的当前节点,找到到 k 中剩余节点的最短路径
- 查看图表的平均度数
- 评估节点的介数
- 获取聚类系数
- 找到图的模块化
对于其中的许多,我想将结果与 Erdos-Renyi 模型进行比较,并将其作为零假设进行测试。此外,能够通过马尔可夫场使用统计力学定义会很有帮助,因为这样我就可以计算两个不相同的节点之间的相关性,并询问关于熵等的图形问题。所以一个好的映射到某种马尔可夫字段库上也会很有用。
目前问题的症结在于我正在尝试找到一个可以使用的 C++ 库。我看过 R,但我想要一些更健壮、更快的东西。我正在考虑的三个库是:
- 柠檬
- 易于使用和安装
- 简单明了的文档
- 有一些我想要的功能
- 通过读取文本文件动态创建图形,并确保没有重复的节点,这是我无法弄清楚的噩梦
- Boost 图形库
- 对象的难以处理、晦涩难懂的定义,以及如何使用它们
- 文档与代码的功能不匹配,必然
- 有很多我想要的算法,以及从文本文件创建图形的非常简单的方法
- 多线程图形库
- 并行性已经合并
- 比 BGL 更容易阅读
- 没有那么多功能
- 仍然是神秘的
再往前走,我设想图生活在分布式网络上,具有分布式存储(hadoop 或其他东西)。我怀疑整个图不适合内存,所以我必须想出一个缓存方案来查看图的某些部分。
对于我描述的问题,人们会建议什么图书馆?只使用 BGL 并编写我自己的函数会更好吗?多线程版本呢?是否有任何图书馆更适合我想做的工作类型,尤其是我想要计算的数量?
谢谢!
Edit1 所以我对 BGL 感到非常沮丧。我有一个邻接列表图,我想在图上运行我自己版本的约翰逊(或弗洛伊德,在这一点上,我并不挑剔),并返回距离矩阵供我查看。除了我无法让它工作。到目前为止,这是我的完整代码实现:
using namespace boost;
int main()
{
//Read in the file
std::ifstream datafile("stuff");
if (!datafile)
{
std::cerr << "No Stuff file" << std::endl;
return EXIT_FAILURE;
}
//Build the graph
typedef adjacency_list < vecS, vecS, undirectedS, property < vertex_name_t,
std::string >, property < edge_weight_t, double > > Graph;
Graph g;
//Build the two properties we want, string and double
//Note, you have to nest properties for more
typedef property_map< Graph, vertex_index_t >::type vertex_index_map_t;
vertex_index_map_t vertex_index_map = get(vertex_index, g);
typedef property_map < Graph, vertex_name_t >::type name_map_t;
name_map_t name_map = get(vertex_name, g);
typedef property_map < Graph, edge_weight_t >::type probability_map_t;
probability_map_t probability = get(edge_weight, g);
//Map of of the vertices by string
typedef graph_traits < Graph >::vertex_descriptor Vertex;
typedef std::map < std::string, Vertex > NameVertexMap;
NameVertexMap AllNodes;
//Load the file into the graph
for (std::string line; std::getline(datafile, line);)
{
char_delimiters_separator < char >sep(false, "", ";");
tokenizer <> line_toks(line, sep);
tokenizer <>::iterator i = line_toks.begin();
std::string conditionA = *i++;
NameVertexMap::iterator pos;
bool inserted;
Vertex u, v;
boost::tie(pos, inserted) = AllNodes.insert(std::make_pair(conditionA, Vertex()));
if (inserted)
{
u = add_vertex(g);
name_map[u] = conditionA;
pos->second = u;
}
else
{
u = pos->second;
}
std::string correlation = *i++;
std::istringstream incorrelation(correlation);
double correlate;
incorrelation >> correlate;
boost::tie(pos, inserted) = AllNodes.insert(std::make_pair(*i, Vertex()));
if (inserted) {
v = add_vertex(g);
name_map[v] = *i;
pos->second = v;
}
else
{
v = pos->second;
}
graph_traits < Graph >::edge_descriptor e;
boost::tie(e, inserted) = add_edge(u, v, g);
if (inserted)
probability[e] = 1.0/correlate;
}
typedef boost::graph_traits<Graph>::edge_iterator edge_iter;
std::pair<edge_iter, edge_iter> edgePair;
Vertex u, v;
for(edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first)
{
u = source(*edgePair.first, g);
v = target(*edgePair.first, g);
std::cout << "( " << vertex_index_map[u] << ":" << name_map[u] << ", ";
std::cout << probability[*edgePair.first] << ", ";
std::cout << vertex_index_map[v] << ":" << name_map[v] << " )" << std::endl;
}
}
其中输入文件的格式为 NodeA;correlation;NodeB。我在上面粘贴的代码有效,但是当我尝试包含 johnson_all_pairs_shortest_paths 功能时遇到了严重的麻烦。我真正想要的不仅是一个 DistanceMatrix D(我似乎无法正确构造它,我希望它是一个双精度方阵 double D[V][V], V = num_vertices(g),但它给了我回我没有正确调用该函数),还有沿着该路径采用的节点列表,类似于 wiki 文章中关于Floyd 算法的内容路径重构。我是否应该尝试为这个问题推出自己的算法,因为我无法确定功能是否存在(更不用说如何进行函数调用)?BGL 的文档与实现一样迟钝,所以我真的没有任何现代示例可以继续。