我希望能够在Java中生成随机,无向和连接的图形。另外,我希望能够控制图中的最大顶点数。我不确定解决这个问题的最佳方法是什么,但这里有一些我能想到的:
(1)在0
和n
之间生成一个数字,并将其作为顶点数。然后,以某种方式将顶点随机链接在一起(可能每个顶点生成一个随机数,并将其作为从所述顶点出来的边数)。从任意顶点开始遍历图形(比如使用广度优先搜索),让我们的随机图G
成为所有访问过的节点(这样,我们确保G
已连接)。
(2)生成一个随机方阵(0
和1
),边长在0
和n
之间(某种程度上)。这将是我们图形的邻接矩阵(矩阵的对角线应该是全部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);
答案 0 :(得分:14)
无论你想用图表做什么,我猜它的密度也是一个重要的参数。否则,您只需使用随机大小生成一组小团队(完整图表),然后随机连接它们。
如果我是对的,我建议你使用Erdős-Rényi model:它很简单,离你最初的建议不远,并允许你控制图密度(所以,基本上:链路)。
以下是此型号的简短说明:
使用此模型,如果您的p足够大,那么您的图形很可能已连接(请参阅Wikipedia参考以获取详细信息)。在任何情况下,如果您有多个组件,还可以通过在不同组件的节点之间创建链接来强制其连接性。首先,您必须通过执行广度优先搜索(每个组件一个)来识别每个组件。然后,在两个不同的组件中选择节点对,在它们之间创建链接并将两个组件视为合并。重复此过程,直到剩下单个组件为止。
答案 1 :(得分:3)
唯一棘手的部分是确保最终图形连接。为此,您可以使用disjoint set data structure。跟踪组件的数量,最初是n。重复选择随机顶点u和v对,将边(u,v)添加到图和不相交的集结构中,并在该结构告诉你u和v属于不同的组件时减少组件数。当组件计数达到1时停止。(请注意,使用邻接矩阵可以简化管理图中已存在边(u,v)的情况:在这种情况下,adj [u] [v]将设置为1第二次,根据需要没有效果。)
如果您发现这会创建太密集(或太稀疏)的图形,那么您可以使用另一个随机数来仅在端点已经是同一组件的一部分时(或者当它们是部分不同的组成部分),对于一些k。
答案 2 :(得分:1)
以下论文提出了一种算法,该算法可以均匀采样连接具有指定度数序列的随机图,并具有高效的实现。它在多个库中可用,例如 Networkit 或 igraph。
Fast generation of random connected graphs with prescribed degrees. 法比安·维格,马修·拉塔皮
对随机图进行模拟时要小心:如果它们不是均匀采样的,那么它们可能具有影响模拟的隐藏属性;或者,均匀采样的图可能与您的代码在实践中遇到的非常不同...