def test_construct_weighted_hypergraph(self): num_nodes = 7 num_nets = 4 hyperedge_indices = [0, 2, 6, 9, 12] hyperedges = [0, 2, 0, 1, 3, 4, 3, 4, 6, 2, 5, 6] node_weights = [1, 2, 3, 4, 5, 6, 7] edge_weights = [11, 22, 33, 44] k = 2 hypergraph = kahypar.Hypergraph(num_nodes, num_nets, hyperedge_indices, hyperedges, k, edge_weights, node_weights) self.assertEqual(hypergraph.nodeWeight(0), 1) self.assertEqual(hypergraph.nodeWeight(1), 2) self.assertEqual(hypergraph.nodeWeight(2), 3) self.assertEqual(hypergraph.nodeWeight(3), 4) self.assertEqual(hypergraph.nodeWeight(4), 5) self.assertEqual(hypergraph.nodeWeight(5), 6) self.assertEqual(hypergraph.nodeWeight(6), 7) self.assertEqual(hypergraph.edgeWeight(0), 11) self.assertEqual(hypergraph.edgeWeight(1), 22) self.assertEqual(hypergraph.edgeWeight(2), 33) self.assertEqual(hypergraph.edgeWeight(3), 44)
def cut(self): context = self._get_context() num_nodes = self.num_of_nodes() node_weights = [1] * num_nodes k = 2 # Debug messages # print("Creating hypergraph:") # print(f"\t num_nodes: {num_nodes}") # print(f"\t num_of_hyperedges: {self.num_of_hyperedges()}") # print(f"\t net_indices: {self.net_indices}") # print(f"\t nets: {self.nets}") # print(f"\t net_weights: {self.net_weights}") # print(f"\t node_weights: {node_weights}") hypergraph = kahypar.Hypergraph(num_nodes, self.num_of_hyperedges(), self.net_indices, self.nets, k, self.net_weights, node_weights) kahypar.partition(hypergraph, context) left_partition = [ node for node in range(num_nodes) if hypergraph.blockID(node) == 0 ] right_partition = [ node for node in range(num_nodes) if hypergraph.blockID(node) == 1 ] # print(left_partition) # print(right_partition) # IDK what triggers this but a partition can be empty. In that case, tighten the imbalance restriction and retry if len(left_partition) == 0 or len(right_partition) == 0: self.set_epsilon(self.epsilon / 4) return self.cut() self.epsilon = self.startEpsilon return set(self._to_lnum(left_partition)), set( self._to_lnum(right_partition))
def hgpa(labels, nclass, random_state): """HyperGraph Partitioning Algorithm (HGPA). Parameters ---------- labels: Labels generated by multiple clustering algorithms such as K-Means. nclass: Number of classes in a consensus clustering label. random_state: Used for reproducible results. Return ------- label_ce: Consensus clustering label obtained from HGPA. """ # Create hypergraph for kahypar H = create_hypergraph(labels) n_nodes, n_nets = H.shape node_weights = [1] * n_nodes edge_weights = [1] * n_nets hyperedge_indices = [0] hyperedges = [] HT = H.T for i in range(n_nets): h = HT.getrow(i) idx_row, idx_col = h.nonzero() hyperedges += list(idx_col) hyperedge_indices.append(len(hyperedges)) hypergraph = kahypar.Hypergraph(n_nodes, n_nets, hyperedge_indices, hyperedges, nclass, edge_weights, node_weights) # Settings for kahypar context = kahypar.Context() config_path = os.path.dirname( __file__) + "/kahypar_config/km1_kKaHyPar_sea20.ini" context.loadINIconfiguration(config_path) if random_state is not None: context.setSeed(random_state) context.setK(nclass) context.setEpsilon(0.03) context.suppressOutput(True) # Hypergraph partitioning kahypar.partition(hypergraph, context) label_ce = np.empty(n_nodes, dtype=int) for i in range(n_nodes): label_ce[i] = hypergraph.blockID(i) return label_ce
def _init_hypergraph_tanner(self, graph, k=2): nodes = list(range(1, graph.shape[0])) edges = list(range(graph.shape[1])) hyperedge_indices = [0] hyperedges = [] edge_weights = [] for edge in range(graph.shape[1]): hyperedges += list(numpy.where(graph[1:, edge])[0]) hyperedge_indices.append(len(hyperedges)) edge_weights.append(1) hp = kahypar.Hypergraph(len(nodes), len(edges), hyperedge_indices, hyperedges, k, edge_weights, []), nodes, edges return hp
def test_construct_hypergraph(self): num_nodes = 7 num_nets = 4 hyperedge_indices = [0, 2, 6, 9, 12] hyperedges = [0, 2, 0, 1, 3, 4, 3, 4, 6, 2, 5, 6] k = 2 hypergraph = kahypar.Hypergraph(num_nodes, num_nets, hyperedge_indices, hyperedges, k) self.assertEqual(hypergraph.numNodes(), 7) self.assertEqual(hypergraph.numEdges(), 4) self.assertEqual(hypergraph.numPins(), 12)
def kahypar_subgraph_find_membership( inputs, output, size_dict, weight_nodes='const', weight_edges='log', fix_output_nodes=False, parts=2, imbalance=0.01, compress=0, seed=None, profile=None, mode='direct', objective='cut', quiet=True, ): import kahypar as kahypar if seed is None: seed = random.randint(0, 2**31 - 1) nv = len(inputs) if parts >= nv: return list(range(nv)) hg = get_hypergraph(inputs, output, size_dict, accel=False) if compress: hg.compress(compress) winfo = to_sparse(hg, weight_nodes=weight_nodes, weight_edges=weight_edges) hypergraph_kwargs = { 'num_nodes': hg.get_num_nodes(), 'num_edges': hg.get_num_edges(), 'index_vector': winfo['hyperedge_indices'], 'edge_vector': winfo['hyperedges'], 'k': parts, } edge_weights, node_weights = { (False, False): (None, None), (False, True): ([], winfo['node_weights']), (True, False): (winfo['edge_weights'], []), (True, True): (winfo['edge_weights'], winfo['node_weights']), }[winfo['has_edge_weights'], winfo['has_node_weights']] if edge_weights or node_weights: hypergraph_kwargs['edge_weights'] = edge_weights hypergraph_kwargs['node_weights'] = node_weights hypergraph = kahypar.Hypergraph(**hypergraph_kwargs) if fix_output_nodes: # make sure all the output nodes (those with output indices) are in # the same partition onodes = tuple(hg.output_nodes()) if parts >= nv - len(onodes) + 1: # too many partitions, simply group all outputs and return groups = itertools.count(1) return [0 if i in onodes else next(groups) for i in range(nv)] for i in onodes: hypergraph.fixNodeToBlock(i, 0) # silences various warnings mode = 'recursive' if profile is None: profile_mode = {'direct': 'k', 'recursive': 'r'}[mode] profile = f"{objective}_{profile_mode}KaHyPar_sea20.ini" context = kahypar.Context() context.loadINIconfiguration(join(KAHYPAR_PROFILE_DIR, profile)) context.setK(parts) context.setSeed(seed) context.suppressOutput(quiet) context.setEpsilon(imbalance * parts) kahypar.partition(hypergraph, context) return [hypergraph.blockID(i) for i in hypergraph.nodes()]
import os import kahypar as kahypar num_nodes = 7 num_nets = 4 hyperedge_indices = [0,2,6,9,12] hyperedges = [0,2,0,1,3,4,3,4,6,2,5,6] node_weights = [1,2,3,4,5,6,7] edge_weights = [11,22,33,44] k=2 hypergraph = kahypar.Hypergraph(num_nodes, num_nets, hyperedge_indices, hyperedges, k, edge_weights, node_weights) context = kahypar.Context() context.loadINIconfiguration("/home/ags/code/kahypar/config/km1_kKaHyPar_sea20.ini") context.setK(k) context.setEpsilon(0.03) kahypar.partition(hypergraph, context)
def partition_hygr(self, h): if (h._nverts <= self._tilesize): return range(h._nverts) tilesize = self._tilesize nparts = int((h._nverts + tilesize - 1) / tilesize) curnhygr = 1 kway_bound = nparts totalcut = 0 gpvec = [0] * h._nverts context = self._context context.setK(2) # will always partition into 2 # nparts should be > 1 at this point assert (nparts > 1) if (nparts & (nparts - 1) != 0): kway_bound = int(math.pow(2, int(math.log2(nparts)) + 1)) # each entry three elems: [hygr, curk, gcids, ne, pe] # ne and pe include supernets curlvl = [None] nextlvl = [[None] * 5, [None] * 5] curlvl[0] = [ h, nparts, [x for x in range(h._nverts)], h._nnets, h._npins ] while (curnhygr != kway_bound): lastid = 0 for i in range(curnhygr): if (curlvl[i][1] == 1): lastid += 1 continue if (curlvl[i][0] is None): continue if (curnhygr > 1 and self._addMsgNets): self._add_send_msg_nets(h, lastid, 2 * curnhygr, gpvec, curlvl, i) # compute target pw curk = curlvl[i][1] tpw = [None] * 2 if (curlvl[i][0]._nverts % tilesize != 0): tmp = int((curk + 1) / 2) tpw[0] = tmp * tilesize tpw[1] = curlvl[i][0]._nverts - tpw[0] else: if (curk % 2 == 0): tpw[0] = tpw[1] = (curk / 2) * tilesize else: tmp = int(curk / 2) tpw[0] = (tmp + 1) * tilesize tpw[1] = tmp * tilesize tpw[0] = int(tpw[0]) tpw[1] = int(tpw[1]) # form kahypar hypergraph hk = kahypar.Hypergraph( curlvl[i][0]._nverts, curlvl[i][3], # with msg nets curlvl[i][0]._xpins, curlvl[i][0]._pins, 2, curlvl[i][0]._nwghts, curlvl[i][0]._cwghts) context.setCustomTargetBlockWeights(tpw) context.suppressOutput(True) # partition and get part vector kahypar.partition(hk, context) lpvec = [None] * curlvl[i][0]._nverts for v in range(curlvl[i][0]._nverts): lpvec[v] = hk.blockID(v) # @TODO if tpw is not achieved, return id perm curcut = kahypar.cut(hk) totalcut += curcut assert (hk.blockWeight(0) == tpw[0] and hk.blockWeight(1) == tpw[1]) # update global partvec for v in range(h._nverts): # orig hygr if (gpvec[v] > lastid): gpvec[v] += 1 for v in range(curlvl[i][0]._nverts): if (lpvec[v] == 1): gpvec[curlvl[i][2][v]] += 1 lastid += 2 left = 2 * i right = 2 * i + 1 nextlvl[right][1] = int(curk / 2) nextlvl[left][1] = nextlvl[right][1] + (curk % 2) # bisect self._bisect(curlvl, lpvec, nextlvl, i) curnhygr = curnhygr * 2 # update curlvl and nextlvl if (curnhygr != nparts): curlvl = nextlvl nextlvl = [[None] * 5 for i in range(2 * curnhygr)] return gpvec
def kahypar_subgraph_find_membership( inputs, output, size_dict, weight_nodes='constant', weight_edges='log', fuse_output_inds=False, parts=2, imbalance=0.01, seed=None, profile=None, mode='direct', objective='cut', quiet=True, ): import kahypar as kahypar if seed is None: seed = random.randint(0, 2**31 - 1) nv = len(inputs) if parts >= nv: return list(range(nv)) HG = HyperGraph(inputs, output, size_dict, weight_edges=weight_edges, weight_nodes=weight_nodes, fuse_output_inds=fuse_output_inds) hyperedge_indices, hyperedges = HG.to_sparse() hypergraph_kwargs = { 'num_nodes': HG.num_vertices, 'num_edges': HG.num_edges, 'index_vector': hyperedge_indices, 'edge_vector': hyperedges, 'k': parts, } edge_weights, node_weights = { (False, False): (None, None), (False, True): ([], HG.node_weights), (True, False): (HG.edge_weights, []), (True, True): (HG.edge_weights, HG.node_weights), }[HG.has_edge_weights, HG.has_node_weights] if edge_weights or node_weights: hypergraph_kwargs['edge_weights'] = edge_weights hypergraph_kwargs['node_weights'] = node_weights hypergraph = kahypar.Hypergraph(**hypergraph_kwargs) if profile is None: profile_mode = {'direct': 'k', 'recursive': 'r'}[mode] profile = f"{objective}_{profile_mode}KaHyPar_dissertation.ini" context = kahypar.Context() context.loadINIconfiguration(join(KAHYPAR_PROFILE_DIR, profile)) context.setK(parts) context.setSeed(seed) context.suppressOutput(quiet) context.setEpsilon(imbalance * parts) kahypar.partition(hypergraph, context) return [hypergraph.blockID(i) for i in hypergraph.nodes()]