Beispiel #1
0
def kruskals(inputFile):
    graph = open(inputFile)
    edges = [ ]
    nodes = {}
    count = 0
    '''
    The following reads in the input file
    and constructs an adjacency list of
    the graph.
    '''
    for line in graph:
        entry = line.split()
        edges.append((entry[2],entry[0],entry[1]))
        if entry[0] not in nodes.keys():
            nodes[entry[0]]= count
            count = count + 1
    total = 0
    solutions =[]
    disjoint = DisjointSet(len(nodes))
    edges.sort()
    for edge in edges:
        if disjoint.find(nodes[edge[1]]) != disjoint.find(nodes[edge[2]]):
            if disjoint.find(nodes[edge[1]]) < disjoint.find(nodes[edge[2]]):
                disjoint.union(nodes[edge[1]], nodes[edge[2]])
            else:
                disjoint.union(nodes[edge[2]], nodes[edge[1]])
            solutions.append(edge)
            total += int(edge[0])
    return total, solutions
Beispiel #2
0
def cluster(Vlist, dim):
    '''
    Function to cluster a list of nodes so that the single link distance between each
    pair of cluster is at least 3 and the number of clusters is maximized
    Input:
        Vlist: bit string representation of all nodes
        dim  : dimension of each node (length of bit string)
    Output:
        Largest number of clusters such that the spacing between any pair of clusters is at least 3
    '''
    distinct_V = {}
    i = 0
    for V in Vlist:
        intV = int(V, 2)
        if intV not in distinct_V:
            distinct_V[intV] = i
            i += 1
    dset = DisjointSet(len(distinct_V))
    ## create a list of bit strings with length <= dim and at most 2 bits are "1"
    permutation_lst = []
    for i in range(dim):
        permutation_lst.append("1" + "0" * i)
    for i in range(dim - 1):
        for j in range(i + 1, dim):
            permutation_lst.append("1" + "0" * (j - i - 1) + "1" + "0" *
                                   (23 - j))
    permutation_lst = [int(x, 2) for x in permutation_lst]
    for V in distinct_V.keys():
        V_permu2 = [V ^ x for x in permutation_lst]
        for v_permu in V_permu2:
            if v_permu in distinct_V:
                dset.union(distinct_V[V], distinct_V[v_permu])
    return len(dset)
Beispiel #3
0
def kruskal(nodes, edges):
    """
    implementation of kruskal's algorithm

    :param nodes: nodes for input.
    :param edges: edges for input.
    :return: edges of the minimum spanning tree.
    """
    # edges of the minimum spanning tree
    mst = []

    # initialize a forest for all nodes
    forest = DisjointSet(nodes)
    # sort the edges by their weights
    edges = sorted(edges, key=lambda x: x[2])
    # calculate the number of edges of the minimum spanning tree
    num_edges = len(nodes)

    # perform kruskal's algorithm
    for (src, dst, weight) in edges:
        # continue if source node or destination node doesn't exist
        if src not in nodes or dst not in nodes:
            continue
        # find the parents of src and dst respectively
        if forest.unite(src, dst):
            # add the current edge into the minimum spanning tree if it doesn't make a circuit
            mst.append((src, dst, weight))
            # terminate early
            if len(mst) == num_edges:
                break

    # return the minimum spanning tree
    return mst
def parallel_prim(sc, nodes, edges, num_partition=4):
    """
    implementation of parallel Prim's algorithm

    :param nodes: nodes for input.
    :param edges: edges for input.
    :param num_partition: number of partitions.
    :return:
    """
    # edges of the minimum spanning tree
    mst = []

    # initialize a forest for all nodes
    forest = DisjointSet(nodes)

    # define function for generating graph
    def generate_graph(iterator):
        for edge in iterator:
            for i in range(2):
                yield (edge[i], (edge[1 - i], edge[2]))

    # store the graph in an adjacency list
    adjacent = sc.parallelize(edges, num_partition) \
                 .mapPartitions(generate_graph, preservesPartitioning=True) \
                 .groupByKey(numPartitions=num_partition) \
                 .mapValues(lambda x: sorted(x, key=lambda y: y[1])) \
                 .persist()

    # candidate edges of the global MST
    candidates = [None]
    # loop until there is no candidate
    while len(candidates) != 0:
        # broadcast the forest to each machine
        connection = sc.broadcast(forest)

        # define function for finding minimum edges leaving each disjoint set
        def find_minimum(iterator):
            for group in iterator:
                src = group[0]
                for (dst, weight) in group[1]:
                    if connection.value.find(src) != connection.value.find(
                            dst):
                        yield (src, dst, weight) if src < dst else (dst, src,
                                                                    weight)
                        break

        # obtain the list of minimum edges leaving each disjoint set
        candidates = sorted(
            adjacent.mapPartitions(find_minimum).distinct().collect(),
            key=lambda x: x[2])

        # calculate the global MST
        for candidate in candidates:
            # find the parents of src and dst respectively
            if forest.unite(candidate[0], candidate[1]):
                # add the current edge into the minimum spanning tree if it doesn't make a circuit
                mst.append(candidate)

    # return the global MST
    return mst
def numIslands(grid):
    #获取行数和列数
    nrow = len(grid)
    if nrow == 0:
        return 0
    ncol = len(grid[0])
    if ncol == 0:
        return 0
    #所有1的坐标
    lands = set()
    for i in range(nrow):
        for j in range(ncol):
            if grid[i][j] == "1":
                lands.add((i, j))
    #初始化不相交集
    ds = DisjointSet(list(lands))
    #扫描所有可能相邻的1,不断地union
    for point in lands:
        h_adj_point = (point[0], point[1] + 1)  #右邻居
        v_adj_point = (point[0] + 1, point[1])  #下邻居
        #如果1的右邻居和下邻居都是1,则进行Union
        if h_adj_point in lands:
            ds.Union(point, h_adj_point)
        if v_adj_point in lands:
            ds.Union(point, v_adj_point)
    #最终返回不相交集的数目
    return ds.SetCnt
Beispiel #6
0
 def test_compress_path(self):
     s = DisjointSet(10)
     s.union(1, 2)
     s.union(3, 4)
     s.union(1, 3)
     self.assertEqual(s.getPath(1), [1, 2, 4])
     s.find(1)
     self.assertEqual(s.getPath(1), [1, 4])
Beispiel #7
0
 def __init__(self, length, width, initial_open=0.40):
     self.__length = length
     self.__width = width
     self.__area = length * width
     self.__map = []
     self.__ds = DisjointSet()
     self.__up_loc = 0
     self.center_pt = (int(self.__length / 2), int(self.__width / 2))
     self.__gen_initial_map(initial_open)
Beispiel #8
0
def findRedundantConnection(edges):
    n = len(edges)  #点的数目
    ds = DisjointSet(range(1, n + 1))  #初始化不相交集,下标从1开始
    PrevSetCnt = ds.SetCnt  #上一步的不相交集数目
    for edge in edges:
        ds.Union(edge[0], edge[1])
        if PrevSetCnt == ds.SetCnt:  #当加入一条边时不相交集的数目没有发生改变,则说明该边是多余的,形成了一个环
            return edge
        PrevSetCnt = ds.SetCnt
Beispiel #9
0
 def __init__(self, width, height, initial_open=0.60):
     self.__height = height
     self.__width = width
     self.__area = height * width
     self.__CAmap = []
     self.__rooms = []
     self.__leveldata = {}
     self.__ds = DisjointSet()
     self.__up_loc = 0
     self.center_pt = (int(self.__height / 2), int(self.__width / 2))
     self.__gen_initial_map(width, height, initial_open)
def findCircleNum(M):
    n = len(M)
    if n == 0:
        return 0
    #初始化不相交集
    DS = DisjointSet(range(n))
    #扫描M矩阵,完成Union操作
    for i in range(n):
        for j in range(i):
            if M[i][j] == 1:
                DS.Union(i, j)
    #返回不相交集的数目
    return DS.SetCnt
Beispiel #11
0
 def __init__(self, width, height, levelnum, initial_open=0.60):
     self.__height = height
     self.__width = width
     self.__area = height * width
     self.__map = []
     self.__levelnum = levelnum
     self.__rooms = []
     self.__ds = DisjointSet()
     self.__up_loc = 0
     self.center_pt = (int(self.__height / 2), int(self.__width / 2))
     self.objects = []
     self.eventdict = {}
     self.gen_map(initial_open)
def connected_components_dj(g):
    djset = DisjointSet()
    for v in g.vertices:
        djset.make_set(v)

    for v1, v2 in g.edges:
        if djset.find_set(v1) != djset.find_set(v2):
            djset.union(v1, v2)

    return djset.get_set()
def _create_sets(game_map, width, height):

    ds = DisjointSet()

    for x in range(0, width):

        for y in range(0, height):

            if game_map[x][y] == FLOOR:
                ds.find((x, y))

                _join_adjacent_tiles(x, y, game_map, ds)

    return ds
Beispiel #14
0
def is_forest(g):
    """
    A forest is an acyclic, undirected graph.

    :param g: undirected graph
    :return: True if graph is a forest, otherwise False
    """
    if not isinstance(g, Graph):
        return False

    djset = DisjointSet()

    for v in g.vertices:
        djset.make_set(v)

    eset = set()
    for v1, v2 in g.edges:
        if (v2, v1) not in eset:
            eset.add((v1, v2))

    for v1, v2 in eset:
        if djset.find_set(v1) != djset.find_set(v2):
            djset.union(v1, v2)
        else:
            return False
    return True
Beispiel #15
0
def getSurprise(graph, paredges, num_nodes, num_edges):
    n = num_nodes
    p = n * (n - 1) / 2
    m = num_edges
    mi, pi = 0, 0

    dse = DS()
    for e in paredges:
        dse.add(e[0], e[1])

    for x in dse.group.values():
        ni = len(x)
        pi += ni * (ni - 1) / 2
        mi += graph.subgraph(x).number_of_edges()
    return compute_surprise(p, pi, m, mi), p, pi, m, mi
Beispiel #16
0
def getSurprise(graph, paredges, num_nodes, num_edges):
    n = num_nodes
    p = n * (n - 1) / 2
    m = num_edges
    mi, pi = 0, 0

    dse = DS()
    for e in paredges:
        dse.add(e[0], e[1])

    for x in dse.group.values():
        ni = len(x)
        pi += ni * (ni - 1) / 2
        mi += graph.subgraph(x).number_of_edges()
    return compute_surprise(p, pi, m, mi), p, pi, m, mi
Beispiel #17
0
def kruskals(inputFile):

    graph = open(inputFile)
    
    pqueue = [] 
    
    mst = []
    
    totalCost = 0
    
    for line in graph:
        entry = line.split()
           
        # construct an edge for the adjacency list
        'We construct this edge and use the cost as the starting element for this tuple to use in the priority queue'
        edge = (int(entry[2]), entry[0], entry[1])
        'we push the edge onto the priority queue'
        heapq.heappush(pqueue, edge)

    '''
    We convert the length of the priority queue into an integer to use with a disjointset
    '''      
    size = len(pqueue)
    frontier = DisjointSet(size)
    
    '''
    Going through each edge in the priority queue, we set the newEdge equal to the current tuple in the priority queue
    and then perform the find function from disjointset on the two vertexes. Since the vertexes are in string form from 
    the tuple, the ord function is used to convert the vertexes into integers for use in the find function. 96 is subtracted from the 
    tuple vertexes to set the unicode code pointer equal to the integer value of the letter in the alphabet (a = 97 with the ord function, and subtracting 97 gives us a = 1).
    We then check if the two vertexes through integer values are not equal to each other. If they are not, we add the the nextEdge tuple to the 
    minimum spanning tree list, and perform a union of the two vertices using the find function from Disjoin set. We also calculate the cost in this 
    if statement.
    '''
    for newEdge in sorted(pqueue):
        newEdge = heapq.heappop(pqueue)
        v1 = frontier.find(ord(newEdge[1])-96)
        v2 = frontier.find(ord(newEdge[2])-96)
        if v1 != v2:
            totalCost = newEdge[0] + totalCost
            mst.append(newEdge)
            frontier.union(v1, v2)
    'Returns the total cost of the mst and the mst list'        
    return totalCost,mst
        
        
    return 0
Beispiel #18
0
def solve(board):
    if board:  #如果board为空则不做任何处理
        nrow, ncol = len(board), len(board[0])
        inner, border = [], []  #记录所有"O"出现的位置,分为内部和边界处
        #扫描,记录所有"O'的位置
        for i in range(nrow):
            for j in range(ncol):
                if board[i][j] == "O":
                    if i == 0 or i == nrow - 1 or j == 0 or j == ncol - 1:
                        border.append((i, j))
                    else:
                        inner.append((i, j))
        #如果边界上无O,则全部转换
        if not border:
            for loc in inner:
                board[loc[0]][loc[1]] = "X"
        else:
            #初始化不相交集
            ds = DisjointSet(border + inner)
            #将边界上的"O"点Union起来
            pivot = border[0]
            for loc in border[1:]:
                ds.Union(pivot, loc)
            #遍历inner和border,建立必要的连接
            for loc in border + inner:
                if loc[0] < nrow - 1:
                    if board[loc[0] + 1][loc[1]] == "O":
                        ds.Union(loc, (loc[0] + 1, loc[1]))
                if loc[1] < ncol - 1:
                    if board[loc[0]][loc[1] + 1] == "O":
                        ds.Union(loc, (loc[0], loc[1] + 1))
            #遍历inner中的点,若其不与border中的点同类,则转换
            for loc in inner:
                if ds.Find(loc) != ds.Find(pivot):
                    board[loc[0]][loc[1]] = "X"
Beispiel #19
0
 def __init__(self, length, width, initial_open=0.40):
     self.__length = length
     self.__width = width
     self.__area = length * width
     self.__map = []
     self.__ds = DisjointSet()
     self.__up_loc = 0
     self.center_pt = (int(self.__length / 2), int(self.__width / 2))
     self.__gen_initial_map(initial_open)
Beispiel #20
0
def mst_kruskal(g):
    djset = DisjointSet()
    mst = Graph()

    for u in g.vertices:
        djset.make_set(u)

    for u, v in sorted(g.edges, key=lambda e: g.weight(e[0], e[1])):
        if djset.find_set(u) != djset.find_set(v):
            djset.union(u, v)
            mst.add_edge(u, v, g.weight(u, v))
    return mst
Beispiel #21
0
def Prim(graph): # A revoir totalement avec tas binaire minimun ou fibonacci
  """Algorithme de Prim + Union-Find
  Retourne la liste des arretes du graphe de coût minimum
  """

  forest = DisjointSet()
  chemin = []
  tempEdges = []
  usedNodes = [] 

  for n in graph['Nodes']:
    forest.add(n)

  nbrNodes = len(graph['Nodes'])

  origin = graph['Nodes'][0]

  usedNodes.append(origin)

  while(len(chemin) != nbrNodes-1):
    tempNodes = []
    tempEdges = []    

    for node in forest:
      if forest[node] in usedNodes: # On cherche tous les sommets dont le père fait parti des sommet déjà parcouru
        tempNodes.append(node)

    for node in tempNodes: # A AMELIORER !! SOURCE DE PERTE DE TEMPS !!!!
      for edge in graph['Edges']:
        if node in edge and edge not in chemin:
          tempEdges.append(edge)

    tempEdges = sorted(tempEdges, key=itemgetter(2))   

    chemin.append(tempEdges[0]) # On prend l'arrete avec le plus petit poids

    if graph['Type'].upper() == "UNDIRECTED GRAPH":
      if chemin[-1][0] in usedNodes:
        forest.union(chemin[-1][0], chemin[-1][1])
        usedNodes.append(chemin[-1][0])
      else:
        forest.union(chemin[-1][1], chemin[-1][0])
        usedNodes.append(chemin[-1][1])             
    else:
      forest.union(chemin[-1][1], chemin[-1][0])
      usedNodes.append(chemin[-1][1])

  return chemin
Beispiel #22
0
 def connected_components(self):
     "Returns a list of sets of connected components"
     ds = DisjointSet()
     for v in self.vertices():
         ds.make_set(v)
         for u,v in self.edges():
             if ds.find_set(u) != ds.find_set(v):
                 ds.union(u,v)
     return ds.collection
Beispiel #23
0
 def __init__(self, width, height, initial_open=0.60):
     self.__height = height
     self.__width = width
     self.__area = height * width
     self.__CAmap = []
     self.__rooms = []
     self.__leveldata = {}
     self.__ds = DisjointSet()
     self.__up_loc = 0
     self.center_pt = (int(self.__height/2), int(self.__width/2))
     self.__gen_initial_map(width, height, initial_open)
def kruskal(graph):
    djs = DisjointSet(numel=len(graph.nodes))
    all_nodes = set(range(len(graph.nodes)))
    weight = 0
    edges = list(graph.get_edges())
    edges.sort(key=lambda tup: tup[2])
    fs = set()

    for e in edges:
        source = e[0]
        dest = e[1]
        wt = e[2]

        if not djs.same_set(source, dest):
            fs.add(source)
            fs.add(dest)
            weight += wt
            djs.union(source, dest)

    return weight
Beispiel #25
0
def Kruskal(graph):
  """Algorithme de Kruskal
  Retourne la liste des arretes du graphe de coût minimum
  """

  forest = DisjointSet()
  chemin = []

  for n in graph['Nodes']:
    forest.add(n)

  nbrNodes = len(graph['Nodes']) - 1

  for arc in sorted(graph['Edges'], key=itemgetter(2)): #O( --- )
    n1, n2, poids = arc

    t1 = forest.find(n1)
    t2 = forest.find(n2)

    if t2 != t1:
      chemin.append(arc)
      nbrNodes -= 1

      if nbrNodes == 0:
        return chemin

      forest.union(t1, t2)
Beispiel #26
0
 def __init__(self, width, height, levelnum, initial_open=0.60):
     self.__height = height
     self.__width = width
     self.__area = height * width
     self.__map = []
     self.__levelnum = levelnum
     self.__rooms = []
     self.__ds = DisjointSet()
     self.__up_loc = 0
     self.center_pt = (int(self.__height/2), int(self.__width/2))
     self.objects = []
     self.eventdict = {}
     self.gen_map(initial_open)
Beispiel #27
0
def eliminate_insiders(components):
    '''eliminates all components whose bounding boxes lie inside of others. The components object is manipulated in place

    Args:
        components: Components instance
    '''

    by_size = by_bbox_size(components)

    labels = DisjointSet(n_labels=len(by_size))

    # pairwise check of bounding boxes. once per pair.
    for a in range(len(by_size)):
        for b in range(a + 1, len(by_size)):
            if is_inside(by_size[a], by_size[b]):
                labels.unite(a, b)

    survivors = labels.final_labels()

    components.chars = [by_size[i] for i in survivors]

    return
 def testUnionFind(self):
     ds = DisjointSet(range(100))
     for i in range(100):
         ds.union(i, i % 5)
     for i in range(100):
         for j in range(i, 100):
             self.assertEqual(
                 ds.find_set(i) == ds.find_set(j), i % 5 == j % 5)
Beispiel #29
0
    def DisjointCycle(self, vertices):
        d = DisjointSet(vertices)
        for i, j in self.edges:
            a, b = d.find(i), d.find(j)
            if a == b:
                return True
            d.union(i, j)

        return False
Beispiel #30
0
class FindBridges:
    def __init__(self, V):
        self.graph = GraphAdj(V)
        self.disjointSet = DisjointSet(V)
        self.V = V

    def addEdge(self, u, v):
        self.graph.addEdge(u, v)

    def isConnected(self):
        # For each edge in the graph
        # Create a set for each vertex of the edge
        # Return False, if another disjoint set is found
        for v in range(self.V):
            self.disjointSet.makeSet(v)

        for u in range(self.V):
            for v in range(self.V):
                if self.graph.isValid(u, v):
                    uf = self.disjointSet.findSet(u)
                    vf = self.disjointSet.findSet(v)

                    self.disjointSet.unionSets(uf, vf)

        # Is there more than 1 set in the disjoint set
        first = self.disjointSet.findSet(0)
        for v in range(self.V):
            vf = self.disjointSet.findSet(v)
            if vf != first:
                return False

        return True

    # Find critical edge
    # For each edge
    #   Remove edge from graph
    #   Check if the rest of the vertices still create a single disjoint set
    def solve(self):
        criticalEdges = []
        for u in range(self.V):
            for v in range(self.V):
                if self.graph.isValid(u, v):
                    self.graph.removeEdge(u, v)

                    if not self.isConnected():
                        criticalEdges.append((u, v))

                    self.graph.addEdge(u, v)

        return criticalEdges
def minimum_spanning_tree(graph):
    """
    Find the minimum spanning tree in the given graph using 
    Kruskal's algorithm
    :param graph: the graph to find the MST in
    :return: the set of all edges in the MST
    """
    d = DisjointSet()  # initialize disjoint set data structure
    d.make_sets(graph.get_vertices())
    edges = graph.get_edges()  # All edges in graph
    solution = set()  # Set of edges in MST
    quick_sort(edges, 0, len(edges) - 1)  # Sort by edge weight in asc

    for e in edges:
        if d.find(e[0]) != d.find(e[1]):  # if the vertices wont make a cycle
            d.union(e[0], e[1])  # union them
            solution.add(e)  # add the edge to the solution
    return solution
Beispiel #32
0
    def makeKruskal(self):
        disjoint = DisjointSet()
        a = []
        soma = 0
        for node in self.nodes:
            disjoint.makeSet(node)
        sorted_edges = sorted(self.edges)
        for edge in sorted_edges:
            if disjoint.findSet(edge.node_from) != disjoint.findSet(
                    edge.node_to):
                soma += edge.weight
                a.append((edge.node_from, edge.node_to, edge.weight))
                disjoint.union(edge.node_from, edge.node_to)

        print('Caminho:')

        for edge in a:
            print(edge[0], ' -- ', edge[1], 'Peso:', edge[2])

        print('Peso do caminho gerado pelo Kruskal:', soma)
Beispiel #33
0
def cluster(Elist, nV, k):
    '''
    Function for single-linkage hierarchical clustering, which is based on 
    Kruskal's minimum spanning tree algorithm.
    Input:
        Elist: Edge list for a complete graph(contains end verticies and edge cost)
        nV   : total number of vertices
        k    : number of clusters
    Output:
        The shortest distance between two verticies that belong to different clusters.
    '''
    assert nV >= k, "Number of clusters can't be greater than number of nodes!"
    Elist.sort(key=lambda x: x[2])
    dset = DisjointSet(nV)
    i = 0
    while len(dset) > k:
        e = Elist[i]
        i += 1
        if dset.find(e[0]) != dset.find(e[1]):
            dset.union(e[0], e[1])
    while dset.find(Elist[i][0]) == dset.find(Elist[i][1]):
        i += 1
    return Elist[i][2]
Beispiel #34
0
def MST(G):
    '''
    图G
    '''
    V = G.V
    E = G.Adjlist

    MSTV = set()
    MSTE = {}
    Ds = DisjointSet(V)
    for v in V:
        MSTE[v] = Linklist()
    for u in MSTE.keys():
        curList = E[u]
        curNode = curList.head
        while (curNode != 0):
            v = curNode.data
            #使用并查集判断是否生成环
            #------------------------------------
            parentu = Ds.find(u)
            parentv = Ds.find(v)
            if parentu != parentv:
                #不会生成环
                MSTV.add(u)
                MSTV.add(v)
                MSTE[u].pushback(Node(v, curNode.weight))
                MSTE[v].pushback(Node(u, curNode.weight))
                #合并两并查集
                Ds.union(parentu, parentv)
            else:
                #加入该边会生成环
                MaxWeightEdge = getMaxWeightEdge(MSTV, MSTE, u, v)
                if curNode.weight < MaxWeightEdge.w:
                    MSTE[MaxWeightEdge.u].remove(MaxWeightEdge.v)
                    MSTE[MaxWeightEdge.v].remove(MaxWeightEdge.u)
                    MSTE[u].pushback(Node(v, curNode.weight))
                    MSTE[v].pushback(Node(u, curNode.weight))
                    #合并
                    Ds.union(parentu, parentv)
            curNode = curNode.next

    return Graph(MSTV, None, MSTE, kind='nodirect')
Beispiel #35
0
    def constructSpanningTree(self, vertexList, edgeList):

        disjointSet = DisjointSet(vertexList)
        spanningTree = []

        edgeList.sort()

        for edge in edgeList:
            u = edge.startVertex
            v = edge.targetVertex

            # check whether the edges don't form a cycle
            # if they don't then add the edge to the spanning tree
            # and union the two nodes
            if disjointSet.find(u.parentNode) != disjointSet.find(
                    v.parentNode):
                spanningTree.append(edge)
                disjointSet.union(u.parentNode, v.parentNode)

        # print the spanning tree by printing all the edges
        for edge in spanningTree:
            print(edge.startVertex.name, "-", edge.targetVertex.name)
Beispiel #36
0
    def __init__(self, points, edges):

        self.h0 = {}
        for p in points:
            self.h0[p['index']] = [p['time'], math.inf]

        djs = DisjointSet()
        edges.sort(key=itemgetter('time'))

        for d in edges:
            i0, i1 = d['p0']['index'], d['p1']['index']
            f0, f1 = djs.find(i0), djs.find(i1)
            if f0 != f1:
                djs.union(f0, f1)
                self.h0[f0][1] = d['time']

        self.h0 = list(
            map((lambda h: {
                'index': h,
                'life': self.h0[h],
                'persistence': (self.h0[h][1] - self.h0[h][0])
            }), self.h0.keys()))
        self.h0 = list(filter((lambda h: h['persistence'] > 0), self.h0))
        self.h0.sort(key=itemgetter('persistence'))
Beispiel #37
0
class CA_CaveFactory:
    def __init__(self, width, height, initial_open=0.60):
        self.__height = height
        self.__width = width
        self.__area = height * width
        self.__CAmap = []
        self.__rooms = []
        self.__leveldata = {}
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__height/2), int(self.__width/2))
        self.__gen_initial_map(width, height, initial_open)

    # Performs the CA operation, then joins separate rooms.  Returns the map, consisting of a grid of ints.
    def gen_map(self):
        loops = random.randrange(2, 4)
        while loops > 0:
            for r in range(1, self.__height-1):
                for c in range(1, self.__width-1):
                    if not self.__CAmap[c][r].permanent:
                        wall_count = self.__adj_wall_count(r, c)
                        if not self.__CAmap[c][r].blocked:
                            if wall_count > 5:
                                self.__CAmap[c][r].blocked = True
                                self.__CAmap[c][r].block_sight = True
                        elif wall_count < 4:
                            self.__CAmap[c][r].blocked = False
                            self.__CAmap[c][r].block_sight = False

            loops -= 1

        self.__join_rooms()

        return self.__CAmap

    def get_rooms(self):
        return self.__rooms

    def create_room(self, room, layout):
        # go through the tiles in the defined rectangle and construct them according to the layout
        x = room.x1 + 1
        y = room.y1
        for char in layout:
            if char == ".":
                self.__CAmap[x][y].permanent = True
                self.__CAmap[x][y].blocked = False
                self.__CAmap[x][y].block_sight = False
            if char == ",":
                self.__CAmap[x][y].permanent = False
                self.__CAmap[x][y].blocked = False
                self.__CAmap[x][y].block_sight = False
            if char == "X":
                self.__CAmap[x][y].permanent = True
                self.__CAmap[x][y].blocked = True
                self.__CAmap[x][y].block_sight = True
            if char == "x":
                self.__CAmap[x][y].permanent = False
                self.__CAmap[x][y].blocked = True
                self.__CAmap[x][y].block_sight = True
            x += 1
            if char == "\n":
                x = room.x1 + 1
                y += 1

    def create_room_features(self, room, layout):
        # Start with an empty set to put level data in
        leveldata = {}

        # go through the tiles in the defined rectangle and construct them according to the layout
        x = room.x1 + 1
        y = room.y1
        for char in layout:
            element = None
            if char == "=": element = "monastery doorway"
            if char == "b": element = "brazier"
            if element: leveldata.update({(x,y):element})
            x += 1
            if char == "\n":
                x = room.x1 + 1
                y += 1

        return leveldata


    def __set_border(self):
        # make all border squares walls
        # This could be moved to a superclass
        for j in range(0,self.__width-1):
            self.__CAmap[j][0].permanent = True
            self.__CAmap[j][self.__height-1].permanent = True

        for j in range(0,self.__height-1):
            self.__CAmap[0][j].permanent = True
            self.__CAmap[self.__width-1][j].permanent = True


    def __gen_initial_map(self,width,height,initial_open):
        # Create an initial map with random tiles removed, plus rooms and fixtures.
        self.__CAmap = map_init(height,width)

        open_count = int(self.__area * initial_open)
        self.__set_border()

        for r in range(MAX_ROOMS):

            # Pick a random selection from our options.
            roomselection = random.choice(roommaking.templefurniture.keys())
            layoutselection = roommaking.templefurniture[roomselection]

            # Get the width and height
            w, h = roommaking.measurements(layoutselection)

            # Find a spot without going off the edge of the map
            x = random.randrange(0, self.__width - w - 1)
            y = random.randrange(0, self.__height - h - 1)

            # Build rooms as Chambers
            new_room = Chamber(x, y, w, h, 'temple')

            # Check against other rooms to ensure this new room overlaps none of the others
            failed = False
            for other_room in self.__rooms:
                if new_room.intersect(other_room):
                    failed = True
                    break

            if not failed:
                # i.e., no intersections, so paint a room
                self.create_room(new_room, layoutselection)

                # Give it some features
                new_room_features = self.create_room_features(new_room, layoutselection)
                self.__leveldata.update(new_room_features)

                print self.__leveldata
                self.__rooms.append(new_room)

                (new_x, new_y) = new_room.center()  # Previously used for player placement (center of first room)

        tree = bspmaking.Leaf(20,20,20,10)
        tree.branch()
        leaves = tree.gatherleaves()
        for leaf in leaves:
            print "Leaf:", leaf.w, leaf.y

        # Chew out a certain amount of 'noise' for the CA function to work over.
        while open_count > 0:
            rand_r = random.randrange(1,self.__height-1)
            rand_c = random.randrange(1,self.__width-1)

            if self.__CAmap[rand_c][rand_r].blocked and not self.__CAmap[rand_c][rand_r].permanent:
                self.__CAmap[rand_c][rand_r].blocked = False
                self.__CAmap[rand_c][rand_r].block_sight = False
                open_count -= 1

    def __adj_wall_count(self,sr,sc):
    # How many walls are surrounding a tile?
        count = 0

        for r in (-1,0,1):
            for c in (-1,0,1):
                if self.__CAmap[(sc + c)][sr + r].blocked and not(c == 0 and r == 0):
                    count += 1

        return count

    def __join_rooms(self):
        # divide the square into equivalence classes
        for r in range(1,self.__height-1):
            for c in range(1,self.__width-1):
                if not self.__CAmap[c][r].blocked:
                    self.__union_adj_sqr(c,r)

        all_caves = self.__ds.split_sets()

        for cave in all_caves.keys():
            self.__join_points(all_caves[cave][0])

    def __join_points(self,pt1):
        next_pt = pt1

        while 1:
            dir = self.__get_tunnel_dir(pt1,self.center_pt) ### This determines the next point to 'drill' to.  Unfortunately it will still drill through 'permanent' tiles.  How to fix?  We could, possibly, use a pathfinding algorithm to get to work our way to the center point.  That should work but might be overkill.  Let's see how often it happens first while I work on cave building.

            if (dir[0] == 0) or (dir[1] == 0):
                next_pt = (pt1[0] + dir[0],pt1[1] + dir[1])
            else:
                if random.randrange(0,1):
                    next_pt = (pt1[0] + dir[0],pt1[1])
                else:
                    next_pt = (pt1[0],pt1[1] + dir[1])

            if self.__CAmap[next_pt[0]][next_pt[1]].permanent: print "Uh oh, permanent tile at", next_pt[0], next_pt[1]

            if self.__stop_drawing(pt1,next_pt,self.center_pt):
                return

            root1 = self.__ds.find(next_pt)
            root2 = self.__ds.find(pt1)

            if root1 != root2:
                self.__ds.union(root1,root2)

            self.__CAmap[next_pt[0]][next_pt[1]].blocked = False
            self.__CAmap[next_pt[0]][next_pt[1]].block_sight = False
            self.__CAmap[next_pt[0]][next_pt[1]].debug = True          # DEBUG

            pt1 = next_pt

    def __stop_drawing(self,pt,npt,cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and not self.__CAmap[npt[0]][npt[1]].blocked:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self,pt1,pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return (h_dir,v_dir)

    def __union_adj_sqr(self,sr,sc):
        loc = (sr,sc)

        for r in (-1,0):
            for c in (-1,0):
                nloc = (sr+r,sc+c)

                if not self.__CAmap[nloc[0]][nloc[1]].blocked and (r+c != -2):
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1,root2)
    'cd': 7,
    'de': 9,
    'bh': 11,
    'hi': 7,
    'ic': 2,
    'ig': 6,
    'cf': 4,
    'df': 14,
    'ah': 8,
    'hg': 1,
    'gf': 2,
    'fe': 10
}

vertexes = [a, b, c, d, e, f, g, h, i]
v_map = {i.identifier: DisjointSet(i.identifier) for i in vertexes}


def kl_mst():
    edges = list(i for i in e_map.items())
    edges.sort(key=lambda x: x[1])
    total = 0

    for edge in edges:
        key = edge[0]
        first_s, second_s = key
        first = v_map[first_s]
        second = v_map[second_s]

        if first.find().identifier != second.find().identifier:
            print(edge)
Beispiel #39
0
class CA_CaveFactory:
    def __init__(self, length, width, initial_open=0.40):
        self.__length = length
        self.__width = width
        self.__area = length * width
        self.__map = []
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__length / 2), int(self.__width / 2))
        self.__gen_initial_map(initial_open)

    def print_grid(self):
        x = 0
        row = ""

        for r in range(0, self.__length):
            for c in range(0, self.__width):
                if self.__map[r][c] in (WALL, PERM_WALL):
                    print '#',
                else:
                    print '.',

            print

    def gen_map(self):
        for r in range(1, self.__length - 1):
            for c in range(1, self.__width - 1):
                wall_count = self.__adj_wall_count(r, c)

                if self.__map[r][c] == FLOOR:
                    if wall_count > 5:
                        self.__map[r][c] = WALL
                elif wall_count < 4:
                    self.__map[r][c] = FLOOR

        self.__join_rooms()

        return self.__map

    # make all border squares walls
    # This could be moved to a superclass
    def __set_border(self):
        for j in range(0, self.__length):
            self.__map[j][0] = PERM_WALL
            self.__map[j][self.__width - 1] = PERM_WALL

        for j in range(0, self.__width):
            self.__map[0][j] = PERM_WALL
            self.__map[self.__length - 1][j] = PERM_WALL

    def __gen_initial_map(self, initial_open):
        for r in range(0, self.__length):
            row = []
            for c in range(0, self.__width):
                row.append(WALL)
            self.__map.append(row)

        open_count = int(self.__area * initial_open)
        self.__set_border()

        while open_count > 0:
            rand_r = randrange(1, self.__length - 1)
            rand_c = randrange(1, self.__width - 1)

            if self.__map[rand_r][rand_c] == WALL:
                self.__map[rand_r][rand_c] = FLOOR
                open_count -= 1

    def __adj_wall_count(self, sr, sc):
        count = 0

        for r in (-1, 0, 1):
            for c in (-1, 0, 1):
                if self.__map[(sr + r)][sc + c] != FLOOR and not(r == 0 and c == 0):
                    count += 1

        return count

    def __join_rooms(self):
        # divide the square into equivalence classes
        for r in range(1, self.__length - 1):
            for c in range(1, self.__width - 1):
                if self.__map[r][c] == FLOOR:
                    self.__union_adj_sqr(r, c)

        all_caves = self.__ds.split_sets()

        for cave in all_caves.keys():
            self.__join_points(all_caves[cave][0])

    def __join_points(self, pt1):
        next_pt = pt1

        while 1:
            dir = self.__get_tunnel_dir(pt1, self.center_pt)
            move = randrange(0, 3)

            if move == 0:
                next_pt = (pt1[0] + dir[0], pt1[1])
            elif move == 1:
                next_pt = (pt1[0], pt1[1] + dir[1])
            else:
                next_pt = (pt1[0] + dir[0], pt1[1] + dir[1])

            if self.__stop_drawing(pt1, next_pt, self.center_pt):
                return

            root1 = self.__ds.find(next_pt)
            root2 = self.__ds.find(pt1)

            if root1 != root2:
                self.__ds.union(root1, root2)

            self.__map[next_pt[0]][next_pt[1]] = FLOOR

            pt1 = next_pt

    def __stop_drawing(self, pt, npt, cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and self.__map[npt[0]][npt[1]] == FLOOR:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self, pt1, pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return (h_dir, v_dir)

    def __union_adj_sqr(self, sr, sc):
        loc = (sr, sc)

        for r in (-1, 0):
            for c in (-1, 0):
                nloc = (sr + r, sc + c)

                if self.__map[nloc[0]][nloc[1]] == FLOOR:
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1, root2)
Beispiel #40
0
        
    def __cmp__(self,other):
        return self.e - other.e

    def __str__(self):
        return str(self.v1) + ',' + str(self.v2) + ',' + str(self.e)

file = open('./clustering1.txt','r')
N = int(file.readline())
K = 4
data = file.readlines()
edges = [edge(int(line.split(' ')[0]),int(line.split(' ')[1]),int(line.split(' ')[2])) for line in data]
heap = []
for e in edges:
    heapq.heappush(heap,e)

clusterNum = N
disjointSet = DisjointSet(N)

while clusterNum > K:
    aedge = heapq.heappop(heap)
    if not disjointSet.within(aedge.v1,aedge.v2):
        disjointSet.union(aedge.v1,aedge.v2)    
        clusterNum -= 1
vmin = 32767
for e in edges:
    if not disjointSet.within(e.v1,e.v2) and vmin > e.e:
        vmin = e.e

print vmin
Beispiel #41
0
class FullMap:
    # A map using CA to build caves but also pre-set rooms.
    def __init__(self, width, height, levelnum, initial_open=0.60):
        self.__height = height
        self.__width = width
        self.__area = height * width
        self.__map = []
        self.__levelnum = levelnum
        self.__rooms = []
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__height/2), int(self.__width/2))
        self.objects = []
        self.eventdict = {}
        self.gen_map(initial_open)

    def gen_map(self, initial_open):
        # Create an initial map
        self.__map = map_init(self.__height, self.__width)

        # make all border squares walls
        for j in range(0, self.__width-1):
            self.__map[j][0].permanent = True
            self.__map[j][self.__height-1].permanent = True

        for j in range(0, self.__height-1):
            self.__map[0][j].permanent = True
            self.__map[self.__width-1][j].permanent = True

        # Chew out randomized spots on the map
        self.randomize(initial_open)

        # Make a list of level features to make
        levellist = levelmaking.choose_levelset(self.__levelnum)

        # Init a counter for events
        currentevent = 1

        # For each item, get the features to make a Chamber out of.  Make a chamber and dig a proper room out of it.
        for item in levellist:
            # Select an item from the possible ones, given the type.
            itemselection = levelmaking.select_elements(item)

            # Want to look until a placement is found.
            placed = False
            while not placed:

                # Given this item, what arguments do we need to actually make the room?
                args = levelmaking.set_element_values(item, itemselection, self.__width, self.__height)
                new_room = Chamber(*args)

                # Check against other rooms to ensure this new room overlaps none of the others
                # This needs to go somewhere else!
                intersected = False
                for other_room in self.__rooms:
                    if new_room.intersect(other_room):
                        intersected = True
                        print "Failed intersection test!"
                        break

                # In cases of intersection, note the failure, and try again (another loop).  Otherwise, perform the
                # dig-a-room operations and make a note to finish the loop.
                if intersected:
                    print "Failed making", new_room.style
                else:
                    # i.e., no intersections, so paint a room
                    levelmaking.dig_room(self.__map, new_room, itemselection)
                    roomobjects = levelmaking.collect_features(self.__map, new_room, itemselection)
                    self.objects += roomobjects
                    print "Successfully dug", new_room.style
                    self.__rooms.append(new_room)
                    placed = True

                    (new_x, new_y) = new_room.center()  # Previously used for player placement (center of first room)

        # Perform CA operation - how many loops to perform?
        loops = random.randrange(4, 5)
        self.ca_operation(loops)

        # Check for other room-making operations


        # Join the areas of the level
        self.__join_rooms()

    def finalize_map(self):
        return self.__map

    def finalize_obects(self):
        return self.objects

    def get_rooms(self):
        return self.__rooms

    def is_map_blocked(self, x, y):
        if self.__map[x][y].is_blocked:
            return True
        else:
            return False

    def randomize(self, initial_open):
        open_count = int(self.__width * self.__height * initial_open)
        while open_count > 0:
            rand_r = random.randrange(1, self.__height-1)
            rand_c = random.randrange(1, self.__width-1)

            if self.__map[rand_c][rand_r].blocked and not self.__map[rand_c][rand_r].permanent:
                self.__map[rand_c][rand_r].blocked = False
                self.__map[rand_c][rand_r].block_sight = False
                open_count -= 1

    def check_open(self):
        count = 0
        for x in range(1, self.__width):
            for y in range(1, self.__height):
                if self.__map[x][y].blocked:
                    count += 1
        print 'open tiles: ', count


    def ca_operation(self, loops):
    # For non-permanent tiles, grow or kill depending on their surroundings.
        while loops > 0:
            for r in range(1, self.__height-1):
                for c in range(1, self.__width-1):
                    if not self.__map[c][r].permanent:
                        wall_count = self.__adj_wall_count(r, c)
                        if not self.__map[c][r].blocked:
                            if wall_count > 5:
                                self.__map[c][r].blocked = True
                                self.__map[c][r].block_sight = True
                        elif wall_count < 4:
                            self.__map[c][r].blocked = False
                            self.__map[c][r].block_sight = False
            loops -= 1

    def __adj_wall_count(self, sr, sc):
    # How many walls are surrounding a tile?
        count = 0

        for r in (-1, 0, 1):
            for c in (-1, 0, 1):
                if self.__map[(sc + c)][sr + r].blocked and not(c == 0 and r == 0):
                    count += 1

        return count

    def __join_rooms(self):

        all_caves = self.__determine_areas()


        # Build a tunneling map for pathing - use the permanent state check to determine passability.
        tunnelingmap = libtcod.map_new(self.__width, self.__height)
        for x in range(1, self.__width-1):
            for y in range(1, self.__height-1):
                perm_wall = (self.__map[x][y].permanent and self.__map[x][y].blocked)
                libtcod.map_set_properties(tunnelingmap, x, y, True, not perm_wall)

        # The tunneling path will let us move from the origin to the center.
        tunnelingpath = libtcod.dijkstra_new(tunnelingmap, 0.0)

        # The center needs to be non-permanent, otherwise we can't path to it.
        center_x, center_y = self.__find_good_center(self.center_pt)

        for cave in all_caves.keys():
            # This comment used to run the joining.  The function is still usable!
            #self.__join_points(all_caves[cave][0])
            origin_x = all_caves[cave][0][0]
            origin_y = all_caves[cave][0][1]

            libtcod.dijkstra_compute(tunnelingpath, origin_x, origin_y)
            if not libtcod.dijkstra_path_set(tunnelingpath, center_x, center_y):
                print "Could not path! Center point permanent:", self.__map[center_x][center_y].permanent
            prev_pt = (origin_x, origin_y)
            while not libtcod.dijkstra_is_empty(tunnelingpath):
                x, y = libtcod.dijkstra_path_walk(tunnelingpath)
                next_pt = (x, y)
                if x is not None:

                    root1 = self.__ds.find(next_pt)
                    root2 = self.__ds.find(prev_pt)

                    if root1 != root2:
                        self.__ds.union(root1, root2)

                    self.__map[next_pt[0]][next_pt[1]].blocked = False
                    self.__map[next_pt[0]][next_pt[1]].block_sight = False
                    self.__map[next_pt[0]][next_pt[1]].debug = True          # DEBUG

                    if self.__stop_drawing(prev_pt, next_pt, self.center_pt):
                        print "Done cave", cave
                        break

                    prev_pt = next_pt

        all_caves = self.__determine_areas()
        if len(all_caves.keys())>1:
            self.__join_rooms()


    def __determine_areas(self):
        # divide the square into equivalence classes
        for r in range(1, self.__height-1):
            for c in range(1, self.__width-1):
                if not self.__map[c][r].blocked:
                    self.__union_adj_sqr(c, r)

        # Get a list of areas to work on, then remove small caves before returning
        areas = self.__ds.split_sets()
        zones = areas.keys()
        for zone in zones:
            if len(areas[zone])<9:
                for location in areas[zone]:
                    x = location[0]
                    y = location[1]
                    self.__map[x][y].permanent = False
                    self.__map[x][y].blocked = True
                    self.__map[x][y].block_sight = True
                areas.pop(zone)

        print "Number of areas is", len(areas)
        return areas

    def __find_good_center(self, pt):
        # This function randomly moves the center to find a good 'end' point for cave joining function.
        # That is, the center can't be permanent.
        x = pt[0]
        y = pt[1]
        while self.__map[x][y].permanent:
            x += random.randrange(-1, 1)
            y += random.randrange(-1, 1)
        pt = (x, y)
        return pt

    def __stop_drawing(self, pt, npt, cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and not self.__map[npt[0]][npt[1]].blocked:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self, pt1, pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return h_dir, v_dir

    def __union_adj_sqr(self, sr, sc):
        loc = (sr, sc)

        for r in (-1, 0):
            for c in (-1, 0):
                nloc = (sr+r, sc+c)

                if not self.__map[nloc[0]][nloc[1]].blocked and (r+c != -2):
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1, root2)
Beispiel #42
0
from DisjointSet import DisjointSet
import math
import collections

file = open('./clustering2.txt','r')
line = file.readline()
N,dimension = int(line.split(' ')[0]),int(line.split(' ')[1])
nodes = []
coutNum = N
dic = collections.defaultdict(lambda: set())
disjointSet = DisjointSet(N)
for i in range(0,N):
    nodestr = ''.join(file.readline().rstrip().split())
    nodes.append(nodestr)
    dic[nodestr].add(i)
    
def hamming(s1, s2):
    assert len(s1) == len(s2)
    return sum(ch1 != ch2 for ch1, ch2 in zip(s1, s2)) 

def candidate(l):
    result = []
    result.append(modify(l,-1,-1))
    for i in range(0,dimension):
        result.append(modify(l,-1,i))
    for i in range(0,dimension):
        for j in range(i + 1,dimension):
            result.append(modify(l,i,j))
    return result

def modify(l,i,j):