【问题标题】:How to generate random graphs?如何生成随机图?
【发布时间】:2013-12-08 22:18:23
【问题描述】:

我希望能够在 Java 中生成随机、无向和连通图。另外,我希望能够控制图中的最大顶点数。我不确定解决此问题的最佳方法是什么,但我能想到以下几种方法:

(1) 生成一个介于0n 之间的数字,并将其作为顶点数。然后,以某种方式将顶点随机链接在一起(可能为每个顶点生成一个随机数,并将其作为从所述顶点出来的边数)。从任意顶点开始遍历图(比如使用广度优先搜索),让我们的随机图 G 成为所有访问节点(这样,我们确保 G 已连接)。

(2) 生成一个随机方阵(由01 组成),边长在0n 之间(不知何故)。这将是我们图的邻接矩阵(矩阵的对角线应该全部为1 或全部为0)。从图中做一个数据结构,从任意节点遍历图,得到一个连接的节点列表,称之为图G

欢迎任何其他生成足够随机图的方法。 注意:我不需要纯随机图,即您生成的图不必具有任何特殊的数学属性(例如某种一致性)。我只是需要很多图表来测试其他东西。

这是我正在使用的 Java Node 类:

public class Node<T> {
    T data;
    ArrayList<Node> children= new ArrayList<Node>();
    ...}

这是我正在使用的Graph 类(你可以知道为什么我现在只对连通图感兴趣):

public class Graph {
    Node mainNode;
    ArrayList<Node> V= new ArrayList<Node>();

    public Graph(Node node){
        mainNode= node;
    }
    ...}

例如,这就是我现在为测试目的制作图表的方式:

//The following makes a "kite" graph G (with "a" as the main node).

/*     a-b
        |/|
        c-d
*/
Node<String> a= new Node("a");
Node<String> b= new Node("b");
Node<String> c= new Node("c");
Node<String> d= new Node("d");
a.addChild(b);
a.addChild(c);
b.addChild(a);
b.addChild(c);
b.addChild(d);
c.addChild(a);
c.addChild(b);
c.addChild(d);
d.addChild(c);
d.addChild(b);
Graph G1= new Graph(a);

【问题讨论】:

  • 为此,您可以使用随机数据生成库,例如 Java 的 Quickcheck。但是,此类库通常没有用于生成图形的内置方法,因此这可能有点棘手。试试这个,如果有问题就回复。
  • 我会结合这两种方法。最初通过将不在图中的随机节点连接到图中的随机节点来创建简单的连通图。然后从未选择的可能顶点(矩阵中的0s)中选择一个数字添加到图中以使其更密集。
  • @RobinGreen,虽然看起来 Quickcheck 有助于生成原语,但我仍然必须生成包含这些原语的 Nodes(这是更难的部分)。我也在寻找更明确的构造,而不使用库。
  • @bourbaki4481472 [与此问题无关] 我看到您已删除您的recent question。只是让您知道,这里有一个您可能感兴趣的解决方案jsfiddle.net/DerekL/Lh3fy5dr
  • @bourbaki4481472 我刚刚将代码 (jsfiddle.net/DerekL/Lh3fy5dr/1) 更新为更简洁的代码……希望对您有所帮助。

标签: java algorithm random graph


【解决方案1】:

唯一棘手的部分是确保最终图是连接的。为此,您可以使用disjoint set data structure。跟踪组件的数量,最初为 n。重复选择随机顶点对 u 和 v,将边 (u, v) 添加到图和不相交的集合结构中,并在该结构告诉您 u 和 v 属于不同组件时减少组件计数。当组件计数达到 1 时停止。(请注意,使用邻接矩阵简化了管理图中已经存在边 (u, v) 的情况:在这种情况下,adj[u][v] 将设置为 1第二次,根据需要没有效果。)

如果您发现这会创建太密集(或太稀疏)的图,那么您可以使用另一个随机数添加边,仅当端点已经是同一组件的一部分时(或者当它们是不同组件的一部分),对于一些 k。

【讨论】:

  • 谢谢。在邻接矩阵中将 adj[u][v] 设置为 1(一旦识别出两个不相交的集合),这将有助于解决这个问题。
【解决方案2】:

无论你想对你的图表做什么,我猜它的密度也是一个重要的参数。否则,您只需使用随机大小生成一组小团(完整图),然后随机连接它们。

如果我是正确的,我建议您使用Erdős-Rényi model:它很简单,与您最初提出的建议相距不远,并且允许您控制图形密度(因此,基本上:链接数) .

以下是对该模型的简短描述:

  1. 定义一个概率值 p(p 越高,图越密集:0=无链接,1=全连通图);
  2. 创建您的 n 个节点(作为对象、作为邻接矩阵或任何适合您的东西);
  3. 每对节点都以(独立的)概率 p 连接。因此,您必须使用此概率 p 来确定它们之间是否存在联系。例如,我猜你可以随机绘制一个介于 0 和 1 之间的值 q 并创建链接 iff q

使用此模型,如果您的 p 足够大,那么您的图很可能是连接的(请参阅 Wikipedia 参考以了解详细信息)。在任何情况下,如果您有多个组件,您还可以通过在不同组件的节点之间创建链接来强制其连接。首先,您必须通过执行广度优先搜索(每个组件一个)来识别每个组件。然后,您选择两个不同组件中的节点对,在它们之间创建链接并将两个组件视为合并。重复这个过程,直到剩下一个组件。

【讨论】:

  • 感谢您的解释和链接。这个模型可能适合我。
  • 虽然我不得不说我对维基百科文章谈到的两种模型之间的差异有点困惑。
  • 在第一个模型中,您考虑所有可能的图表,考虑到一些参数(节点和链接的数量),然后随机选择一个。在第二个中,您通过将链接随机添加到最初为空的图形来构建图形。我发现第二种模型更适合实现,所以这是我在帖子中介绍的。
【解决方案3】:

以下论文提出了一种算法,该算法均匀对具有规定度数序列的连接随机图进行采样,并具有高效的实现。它在多个库中可用,例如 Networkit 或 igraph。

Fast generation of random connected graphs with prescribed degrees. Fabien Viger,马蒂厄·拉塔皮

在随机图上进行模拟时要小心:如果它们的采样不均匀,那么它们可能具有影响模拟的隐藏属性;或者,均匀采样的图可能与您的代码在实践中遇到的图大不相同...

【讨论】:

  • 您好,欢迎来到 SO!请阅读tourHow do I write a good answer? 添加链接很棒,但解释他们如何解决问题要好得多。
  • 感谢@TomerShetah 的评论。我的链接是一篇论文准确地解决了这个问题,在我在答案开头解释的上下文中(统一生成,规定的学位)。你的意思是我应该在这里总结一下算法吗?会不会是多余的和过于复杂的?
  • 你不应该参考其他网站来获得完整的答案。例如,看看接受的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-06
  • 2017-05-10
  • 2011-02-19
  • 2011-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多