Java 如何生成随机图?

Java 如何生成随机图?,java,algorithm,random,graph,Java,Algorithm,Random,Graph,我希望能够在Java中生成随机、无向和连通的图。此外,我希望能够控制图形中顶点的最大数量。我不确定解决这个问题的最佳方法是什么,但我可以想到以下几点: (1) 生成一个介于0和n之间的数字,并将其作为顶点数。然后,以某种方式将顶点随机链接在一起(可能每个顶点生成一个随机数,并让它成为从所述顶点出来的边数)。从任意顶点开始遍历图(比如广度优先搜索),让随机图G成为所有访问的节点(这样,我们确保G是连接的) (2) 生成边长在0和1之间的随机平方矩阵(以某种方式)。这将是我们图形的邻接矩阵(矩阵的对

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

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

(2) 生成边长在
0
1
之间的随机平方矩阵(以某种方式)。这将是我们图形的邻接矩阵(矩阵的对角线应该是全部
1
,或者全部
0
)。从图中创建一个数据结构,并从任何节点遍历图,以获得连接的节点列表,并调用该图
G

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

下面是我正在使用的Java
节点
类:

public class Node<T> {
    T data;
    ArrayList<Node> children= new ArrayList<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);
//下面是一个“kite”图G(以“a”为主节点)。
/*a-b
|/|
c-d
*/
节点a=新节点(“a”);
节点b=新节点(“b”);
节点c=新节点(“c”);
节点d=新节点(“d”);
a、 儿童(b);
a、 addChild(c);
b、 addChild(a);
b、 addChild(c);
b、 addChild(d);
c、 addChild(a);
c、 儿童(b);
c、 addChild(d);
d、 addChild(c);
d、 儿童(b);
图G1=新图(a);

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


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

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

如果我是正确的,我建议您使用:它很简单,与您最初的建议不远,并且允许您控制图形密度(因此,基本上是:链接的数量)

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

  • 定义概率值p(p越高,图形越密集:0=无链接,1=完全连接的图形)
  • 创建n个节点(作为对象、邻接矩阵或任何适合您的对象)
  • 每对节点以(独立的)概率p连接。所以,你必须用概率p来决定它们之间是否存在联系。例如,我想你可以随意画一个介于0和1之间的值q,然后创建链接iff q
    在这个模型中,如果你的p足够大,那么你的图很有可能是连通的(详见维基百科参考资料)。在任何情况下,如果有多个组件,也可以通过在不同组件的节点之间创建链接来强制其连接。首先,您必须通过执行广度优先搜索(每个组件一个)来识别每个组件。然后,在两个不同的组件中选择节点对,在它们之间创建链接,并将两个组件看作合并。重复这个过程,直到剩下一个组件。

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

    法比恩·维格,马修·拉塔皮


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

    为此,您可以使用随机数据生成库,如Quickcheck For Java。然而,这些库通常没有生成图形的内置方法,因此这可能有点棘手。试试这个,如果你有问题就回答。我会把这两种方法结合起来。首先,通过将图中不存在的随机节点连接到图中的随机节点来创建一个简单的连通图。然后从未勾选的可能顶点(矩阵中的
    0
    s)中,选择一个数字添加到图形中,使其更密集。@RobinGreen,虽然快速检查看起来有助于生成基本体,但我仍然必须生成包含这些基本体的
    节点
    s(这是更难的部分)。我也在寻找一个更明确的结构,而不使用库。@bourbaki4481472[与这个问题无关]我明白了
    //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);