def maximum_k(node_list=[], node_length=24, maximum_spacing=3): """ Input: list of nodes (edges defined implictly by Hamming distances between nodes) Output: max number of clusters with specified maximum spacing Method: BRUTE FORCE For each node iterate through all permuations of possible n-bit differences from 1 up to max_spacing - 1. For example, for max_spacing = 3, node length 24 bits, the number of permutations is (24 C 1) + (24 C 2) = 300. """ node_set = set(node_list) node_list = list(node_set) union_find = UnionFind(nodes=node_list) bitmasks = get_bitmasks(node_length) for node1 in node_list: for i in xrange(1, maximum_spacing): for permutation in combinations(xrange(node_length), i): node2 = node1 for pos in permutation: node2 ^= bitmasks[pos] if node2 in node_set: if union_find.find(node1) != union_find.find(node2): union_find.union(node1, node2) return len(set(union_find.leader_lookup.values()))
def kruskal(node_list, edge_list): edge_list.sort() mst = defaultdict(dict) # minimum spanning tree union_find = UnionFind(nodes=node_list) for edge in edge_list: weight, node1, node2 = edge if union_find.find(node1) != union_find.find(node2): union_find.union(node1, node2) mst[node1][node2] = weight mst[node2][node1] = weight else: continue return mst
def maximum_spacing(node_list=[], edge_list=[], k=0): """ Returns maximum spacing between k clusters""" edge_order = [] # mst = defaultdict(dict) union_find = UnionFind(nodes=node_list) edge_list.sort() for edge in edge_list: weight, node1, node2 = edge if union_find.find(node1) != union_find.find(node2): union_find.union(node1, node2) # mst[node1][node2] = weight # mst[node2][node1] = weight edge_order.append(edge) else: continue return edge_order[-(k - 1)][0]
class KruskalGraph(WeightedGraph): edges = [] spanning_tree = [] components = {} union = None def __init__(self, graph={}, directed=False, *args, **kwargs): super(KruskalGraph, self).__init__(graph, directed, *args, **kwargs) self.union = UnionFind() # find and insert edges for vertex, edges in self.graph.items(): self.components[vertex] = Node(vertex) for edge, weight in edges.items(): self._add_edge(vertex, edge, weight) # sort edges self.edges = sorted(self.edges, key=lambda edges: edges[2]) def build(self): """ Build the MST using Kruskal's Algorithm. """ for x, y, weight in self.edges: x_root = self.union.find(self.components[x]) y_root = self.union.find(self.components[y]) if x_root != y_root: self.spanning_tree.append((x, y, weight)) self.union.union(x_root, y_root) def show(self): for edge in self.spanning_tree: print edge[0], edge[1], edge[2] def _add_edge(self, x, y, weight): edge = (x, y, weight) reverse_edge = (y, x, weight) if edge not in self.edges and reverse_edge not in self.edges: self.edges.append((x, y, weight))