简体   繁体   English

在给定节点数和节点度的情况下,生成许多具有多条边的不同随机无向图的最快算法

[英]Fatest algorithm to generate many distinct random undirected graphs with multiple edges given number of nodes and node degree

I wrote an algorithm that generates random graphs given number of nodes and associated node degree.我编写了一个算法,该算法在给定节点数和相关节点度数的情况下生成随机图。 The algorithm is slow for large graphs.对于大型图,该算法很慢。 It works like this:它是这样工作的:

  1. Pick 2 random nodes from node list and connect them while checking node degree of these nodes hasn't reached capacity.从节点列表中选择 2 个随机节点并连接它们,同时检查这些节点的节点度是否达到容量。 Also every random graph must be different from previous ones given this is possible (1000 graphs)此外,每个随机图都必须与以前的不同,因为这是可能的(1000 个图)

Sometimes algorithm reaches an exception as I randomly pick nodes to connect, and in the end I am left with a node with a large unassigned degree.有时算法会在我随机选择要连接的节点时遇到异常,最后我会得到一个未分配度数很大的节点。 And since I cannot have self loops, I start breaking random edges from intermediate graph and connecting them to this node.而且由于我不能有自循环,我开始从中间图中破坏随机边并将它们连接到这个节点。 I think this is naive and inefficient.我认为这是幼稚和低效的。 Any guidance on how to go about this?关于如何 go 的任何指导? Graph is undirected with no self loops but multiple edges between 2 nodes.图是无向的,没有自环,但 2 个节点之间有多个边。 Tried using python libraries that do this like configuration model but they allow self loops尝试使用像配置 model 一样执行此操作的 python 库,但它们允许自循环

for iteration in range(1000):  # 1000 random graphs
    all_stop = False
    all_stop_2 = False
    count = count +1
    
    success_dict = defaultdict(list)  
    popped_dict = defaultdict(dict)
    grid_dens_dict = defaultdict(set)
        
    with open(filename2,'rb') as handle:
        pfxlinks = pickle.load(handle,encoding ='latin-1')  


    with open(filename3,'rb') as handle:
        grid_ids_withlinks = pickle.load(handle,encoding ='latin-1')
    
    for pfxpair in pfxlinks:
        start_put = False    
        end_put = False 
        
        if all_stop_2 == True:
            break
        
        while True:
            
            if all_stop == True:
                all_stop_2 = True
                break
           
            try:
                grid_start_id, grid_end_id = (np.random.choice(list(grid_ids_withlinks.keys()),size = 2, replace = False)) # get 2 random node ids
                grid_start_id = int(grid_start_id)
                grid_end_id = int(grid_end_id)
                
                if start_put == False:
                    
                    start_value = grid_dens_dict.get(grid_start_id)    # if node id exists in my dict and node degree hasnt reached capacity
                    
                    start_process_condition = (not start_value) or ( (start_value) and (len(grid_dens_dict[grid_start_id]) < grid_ids_withlinks[grid_start_id]) )
                    if start_process_condition:
                        grid_dens_dict[grid_start_id].add(pfxpair)
                        start_put = True
                    
                        if len(grid_dens_dict[grid_start_id]) == grid_ids_withlinks[grid_start_id]: # node degree for node full, remove from dict
                            
                            try:
                                #print('deleted key: ',grid_start_id, 'with size:',grid_dens_dict[grid_start_id],'Capacity:',grid_ids_withlinks[grid_start_id])
                                popped_dict[grid_start_id] = {'orig_capacity': grid_ids_withlinks[grid_start_id],'size':len(grid_dens_dict[grid_start_id]) }
        
                                grid_ids_withlinks.pop(grid_start_id)
                            
                            except:
                                print('already popped')
                else:
                    print('check')
                              
                if end_put == False: 
                    
                                        
                    end_value = grid_dens_dict.get(grid_end_id)
                    if (not end_value) or (end_value and (len(grid_dens_dict[grid_end_id]) < grid_ids_withlinks[grid_end_id])):
                        grid_dens_dict[grid_end_id].add(pfxpair)
                        end_put = True
                        
                        if len(grid_dens_dict[grid_end_id]) == grid_ids_withlinks[grid_end_id]:
                            try:
                                #print('deleted key: ',grid_end_id, 'with size:',grid_dens_dict[grid_end_id],'Capacity:',grid_ids_withlinks[grid_end_id])
                                popped_dict[grid_end_id] = {'orig_capacity': grid_ids_withlinks[grid_end_id],'size':len(grid_dens_dict[grid_end_id]) }
        
                                grid_ids_withlinks.pop(grid_end_id)
        
                            except:
                                print('already popped')
                else:
                    print('check')
                
                if (start_put == False and end_put == True):      # only end while when both nodes have been assigned a link
                    grid_dens_dict[grid_end_id].discard(pfxpair)
                    end_put = False
                if (start_put == True and end_put == False):
                    grid_dens_dict[grid_start_id].discard(pfxpair)
                    start_put = False
        
                        
                if start_put == True and end_put == True:
                    success_dict[pfxpair].append((grid_start_id,grid_end_id))
        
                    break

You could solve for the graph with maximum edge weight subject to degree constraints using linear programming.您可以使用线性规划求解受度数约束的具有最大边权重的图。 In general, choosing different random weights will lead to different graphs.一般来说,选择不同的随机权重会导致不同的图表。 Here is an example using PuLP:以下是使用纸浆的示例:

# !pip install PuLP
import pulp
import numpy as np
from itertools import combinations

# set up fake data
np.random.seed(0)
num_nodes = 10
node_list = list(range(num_nodes))
degrees = np.random.randint(1, 5, size=num_nodes)

# random weights, num_nodes by num_nodes
rw = np.random.rand(num_nodes, num_nodes)

# define optimization problem
lp_problem = pulp.LpProblem(name="RandomGraph")

# define optimization variables
edges = pulp.LpVariable.dicts("Edges", (node_list, node_list), cat="Binary")

# objective is to find the matching with maximum random edge weights
lp_problem += sum(edges[i][j] * rw[i,j]
            for i in node_list for j in node_list)

# graph is undirected:
for i, j in combinations(node_list, 2):
  lp_problem += edges[i][j] == edges[j][i]

# no self-loops:
for i in node_list:
  lp_problem += edges[i][i] == 0

# degree constraints are respected:
for i in node_list:
  lp_problem += sum(edges[i][j] for j in node_list) == degrees[i]

# solve the problem
lp_problem.solve()
# make sure that we got an optimal solution
assert lp_problem.status == 1
# recover edges
edges_solution = [(i, j) for i in node_list for j in node_list
                   if edges[i][j].varValue == 1]

# visualize the graph
import networkx as nx

# construct networkx graph
g = nx.Graph()
g.add_edges_from(edges_solution)
for i, d in enumerate(degrees):
  g.nodes[i]["intended_degree"] = d

# draw, labeling the intended degrees
labels = nx.get_node_attributes(g, 'intended_degree')
nx.draw_circular(g, labels=labels) 

The following picture shows that node degrees are correct:下图显示节点度数是正确的:

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 给定节点和度数生成随机多重图(无向)的有效算法 - Efficient algorithm to generate random multigraph (undirected) given nodes and degree 给定节点数和边数,如何生成随机图? - How to generate a random graph given the number of nodes and edges? 给定无向图中的边,在最大化图的度数的同时限制最大图度的算法是什么? - Given edges in a undirected graph, what is an algorithm for limiting the maximum degree of the graph while maximizing the degree of the graph? 创建具有平行边但没有具有给定节点度的自环的随机多重图 - Creating random multigraph with parallel edges but no self loops with given node degree 使用networkx计算加权无向图中连接到一个节点的每个子图中的节点和边数 - Count the number of nodes and edges in each subgraph connected to one node in a weighted undirected graph with networkx 删除节点的随机边直到 degree = 1.networkx - delete random edges of a node till degree = 1 networkx 在十亿个节点的无向​​图中无循环地从正好k个边的源节点中找到目标节点的算法/方法 - Algorithm/Approach to find destination node from source node of exactly k edges in undirected graph of billion nodes without cycle 获取具有给定数量的节点和边的所有可能的图形(使用图形工具) - Get all possible graphs with a given number of nodes and edges (with graph-tools) 生成具有 n 个节点和 m 个边的随机图 - Generate random graph with n nodes and m edges 边界少于n的无向图 - Undirected graphs with less than n edges
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM