def create_coarse_graph(graph, groups, coarse_graph_size): '''create the coarser graph and return it based on the groups array and coarse_graph_size''' coarse_graph = Graph(coarse_graph_size, graph.edge_num) coarse_graph.finer = graph graph.coarser = coarse_graph cmap = graph.cmap adj_list = graph.adj_list adj_idx = graph.adj_idx adj_wgt = graph.adj_wgt node_wgt = graph.node_wgt coarse_adj_list = coarse_graph.adj_list coarse_adj_idx = coarse_graph.adj_idx coarse_adj_wgt = coarse_graph.adj_wgt coarse_node_wgt = coarse_graph.node_wgt coarse_degree = coarse_graph.degree coarse_adj_idx[0] = 0 nedges = 0 # number of edges in the coarse graph for idx in range(len(groups)): # idx in the graph coarse_node_idx = idx neigh_dict = dict( ) # coarser graph neighbor node --> its location idx in adj_list. group = groups[idx] for i in range(len(group)): merged_node = group[i] if (i == 0): coarse_node_wgt[coarse_node_idx] = node_wgt[merged_node] else: coarse_node_wgt[coarse_node_idx] += node_wgt[merged_node] istart = adj_idx[merged_node] iend = adj_idx[merged_node + 1] for j in range(istart, iend): k = cmap[adj_list[ j]] # adj_list[j] is the neigh of v; k is the new mapped id of adj_list[j] in coarse graph. if k not in neigh_dict: # add new neigh coarse_adj_list[nedges] = k coarse_adj_wgt[nedges] = adj_wgt[j] neigh_dict[k] = nedges nedges += 1 else: # increase weight to the existing neigh coarse_adj_wgt[neigh_dict[k]] += adj_wgt[j] # add weights to the degree. For now, we retain the loop. coarse_degree[coarse_node_idx] += adj_wgt[j] coarse_node_idx += 1 coarse_adj_idx[coarse_node_idx] = nedges coarse_graph.edge_num = nedges coarse_graph.resize_adj(nedges) C = cmap2C(cmap) # construct the matching matrix. graph.C = C coarse_graph.A = C.transpose().dot(graph.A).dot(C) return coarse_graph
def _read_graph_from_metis(ctrl, file_path): '''Assume idx starts from *1* and are continuous. Edge shows up twice. Assume single connected component.''' # logging.info("Reading graph from metis...") in_file = open(file_path) first_line = [int(ele) for ele in in_file.readline().strip().split()] weighted = False if len(first_line) == 3 and first_line[-1] == 1: weighted = True node_num, edge_num = first_line[:2] edge_num *= 2 graph = Graph(node_num, edge_num) edge_cnt = 0 graph.adj_idx[0] = 0 for idx in range(node_num): graph.node_wgt[idx] = 1 eles = in_file.readline().strip().split() j = 0 while j < len(eles): neigh = int( eles[j]) - 1 # needs to minus 1 as metis starts with 1. if weighted: wgt = float(eles[j + 1]) else: wgt = 1.0 graph.adj_list[edge_cnt] = neigh # self-loop included. graph.adj_wgt[edge_cnt] = wgt graph.degree[idx] += wgt edge_cnt += 1 if weighted: j += 2 else: j += 1 graph.adj_idx[idx + 1] = edge_cnt graph.A = graph_to_adj(graph, self_loop=False) # check connectivity in debug mode if ctrl.debug_mode: assert nx.is_connected(graph2nx(graph)) return graph, None
def read_graph_from_adj(adj, dataset_name): '''Assume idx starts from *1* and are continuous. Edge shows up twice. Assume single connected component.''' # logging.info("Reading graph from metis...") with open("data/ind.{}.{}".format(dataset_name, 'graph'), 'rb') as f: if sys.version_info > (3, 0): in_file = pkl.load(f, encoding='latin1') else: in_file = pkl.load(f) weighted = False node_num = adj.shape[0] edge_num = np.count_nonzero(adj.toarray()) * 2 graph = Graph(node_num, edge_num) edge_cnt = 0 graph.adj_idx[0] = 0 for idx in range(node_num): graph.node_wgt[idx] = 1 eles = in_file[idx] j = 0 while j < len(eles): neigh = int(eles[j]) # if weighted: wgt = float(eles[j + 1]) else: wgt = 1.0 graph.adj_list[edge_cnt] = neigh # self-loop included. graph.adj_wgt[edge_cnt] = wgt graph.degree[idx] += wgt edge_cnt += 1 if weighted: j += 2 else: j += 1 graph.adj_idx[idx + 1] = edge_cnt graph.A = graph_to_adj(graph, self_loop=False) # check connectivity in debug mode # if ctrl.debug_mode: # assert nx.is_connected(graph2nx(graph)) return graph, None
def _read_graph_from_edgelist(ctrl, file_path): '''Assume each edge shows up ONLY once: small-id<space>large-id, or small-id<space>large-id<space>weight. Indices are not required to be continuous.''' # logging.info("Reading graph from edgelist...") in_file = open(file_path) neigh_dict = defaultdict(list) max_idx = -1 edge_num = 0 for line in in_file: eles = line.strip().split() n0, n1 = [int(ele) for ele in eles[:2]] assert n0 <= n1, "first id in a row should be the smaller one..." if len(eles) == 3: # weighted graph wgt = float(eles[2]) neigh_dict[n0].append((n1, wgt)) if n0 != n1: neigh_dict[n1].append((n0, wgt)) else: neigh_dict[n0].append(n1) if n0 != n1: neigh_dict[n1].append(n0) if n0 != n1: edge_num += 2 else: edge_num += 1 max_idx = max(max_idx, n1) in_file.close() weighted = (len(eles) == 3) continuous_idx = (max_idx + 1 == len(neigh_dict)) # starting from zero mapping = None if not continuous_idx: old2new = dict() new2old = dict() cnt = 0 sorted_keys = sorted(neigh_dict.keys()) for key in sorted_keys: old2new[key] = cnt new2old[cnt] = key cnt += 1 new_neigh_dict = defaultdict(list) for key in sorted_keys: for tpl in neigh_dict[key]: node_u = old2new[key] if weighted: new_neigh_dict[node_u].append((old2new[tpl[0]], tpl[1])) else: new_neigh_dict[node_u].append(old2new[tpl]) del sorted_keys neigh_dict = new_neigh_dict # remapped mapping = Mapping(old2new, new2old) node_num = len(neigh_dict) graph = Graph(node_num, edge_num) edge_cnt = 0 graph.adj_idx[0] = 0 for idx in range(node_num): graph.node_wgt[idx] = 1 # default weight to nodes for neigh in neigh_dict[idx]: if weighted: graph.adj_list[edge_cnt] = neigh[0] graph.adj_wgt[edge_cnt] = neigh[1] else: graph.adj_list[edge_cnt] = neigh graph.adj_wgt[edge_cnt] = 1.0 edge_cnt += 1 graph.adj_idx[idx + 1] = edge_cnt if ctrl.debug_mode: assert nx.is_connected( graph2nx(graph) ), "Only single connected component is allowed for embedding." graph.A = graph_to_adj(graph, self_loop=False) return graph, mapping