예제 #1
0
def clustering(agraph, k):
    """
	Max-Spacing k clustering

	Return maximum spacing of a k-clustering
	and corresponding mst.
	"""
    # minimum spanning tree
    mst = []

    # disjoint set
    disjoint_set = DisjointSet()

    # make set
    for vertex in agraph.Vertices():
        disjoint_set.make_set(vertex)

    # edges of the graph
    edges = agraph.edges()
    edges.sort(key=lambda tup: tup[2])

    for u, v, cost in edges:
        if len(disjoint_set) >= k:

            if disjoint_set.find_set(u) != disjoint_set.find_set(v):
                mst.append((u, v, cost))
                max_cost = cost
                disjoint_set.union(u, v)
        else:
            break

    return max_cost, mst
예제 #2
0
def kruskal_minimum_spanning_tree(graph: Graph) -> list[Edge]:
    """Return list of edges, representing minimum spanning tree"""
    vertices = get_all_nodes(graph)
    edges = get_all_edges(graph)

    djs = DisjointSet(vertices)
    sorted_edges = sorted(edges, key=lambda edge: edge.weight)

    res: list[Edge] = []
    for edge in sorted_edges:
        if djs.find_set(edge.u) != djs.find_set(edge.v):
            res.append(edge)
            djs.union_sets(edge.u, edge.v)
    return res
예제 #3
0
def kruskal(graph: DisjointSet, edges):
    '''
    Keep edges as a list with
    (source: disjoint_set node, destination: disjoint_set node, weight)
    as items
    and graph is the DisjointSet
    '''
    s_edges = sorted(edges, key=itemgetter(2))
    tree = list()
    for u, v, w in s_edges:
        if graph.find_set(u) is not graph.find_set(v):
            tree.append((u, v, w))
            graph.union(u, v)
    return tree
예제 #4
0
def kruskal_mst(agraph):
    """
	Return a minimum spanning tree using kruskal's algorithm
	"""
    # minimum spanning tree
    mst = []

    # disjoint set
    disjoint_set = DisjointSet()

    # make set
    for vertex in agraph.Vertices():
        disjoint_set.make_set(vertex)

    # edges of the graph
    edges = agraph.edges()
    edges.sort(key=lambda tup: tup[2])

    for u, v, cost in edges:
        if disjoint_set.find_set(u) != disjoint_set.find_set(v):
            mst.append((u, v, cost))
            disjoint_set.union(u, v)
    return mst
예제 #5
0
    def minimize(self):

        self._remove_unreachable_states()

        def order_tuple(a, b):
            return (a, b) if a < b else (b, a)

        table = {}

        sorted_states = sorted(self.states)

        # initialize the table
        for i, item in enumerate(sorted_states):
            for item_2 in sorted_states[i + 1:]:
                table[(item, item_2)] = (item in self.final_states) != (item_2 \
                                                                        in self.final_states)

        flag = True

        # table filling method
        while flag:
            flag = False

            for i, item in enumerate(sorted_states):
                for item_2 in sorted_states[i + 1:]:

                    if table[(item, item_2)]:
                        continue

                    # check if the states are distinguishable
                    for w in self.terminals:
                        t1 = self.transitions.get((item, w), None)
                        t2 = self.transitions.get((item_2, w), None)

                        if t1 is not None and t2 is not None and t1 != t2:
                            marked = table[order_tuple(t1, t2)]
                            flag = flag or marked
                            table[(item, item_2)] = marked

                            if marked:
                                break

        d = DisjointSet(self.states)

        # form new states
        for k, v in table.items():
            if not v:
                d.union(k[0], k[1])

        self.states = [str(x) for x in range(1, 1 + len(d.get()))]
        new_final_states = []
        self.start_state = str(d.find_set(self.start_state))

        for s in d.get():
            for item in s:
                if item in self.final_states:
                    new_final_states.append(str(d.find_set(item)))
                    break

        self.transitions = {(str(d.find_set(k[0])), k[1]): str(d.find_set(v))
                            for k, v in self.transitions.items()}

        self.final_states = new_final_states
예제 #6
0
    def minimize(self):
        # Removendo os estados inatingíveis
        self._remove_unreachable_states()

        # Manter a ordem dos elementos na tuplas será importante
        # para saber quais "quadrados" já foram marcados na tabela
        def order_tuple(a, b):
            return (a, b) if a < b else (b, a)

        # Usaremos o algoritmo da tabela visto em aula para marcar
        # os estados que são distintos
        table = {}

        # Ordenamos os estados para que possamos fazer tudo em sequência,
        # do primeiro até o último estado
        sorted_states = sorted(self.states)

        # Inicializando a tabela marcando todos os quadrados onde
        # temos um estado final e um estado não final, que são, trivialmente
        # distintos
        for i, item in enumerate(sorted_states):
            for item_2 in sorted_states[i + 1:]:
                table[(item, item_2)] = (item in self.final_states) != (
                    item_2 in self.final_states)

        flag = True

        # Preenchendo o resto da tabela
        while flag:
            flag = False

            # Vamos olhar para as cobinações de estados da seguinte maneira
            # Pegamos um estado qi, com 0 <= i < n (n = quantidade de estados), com qj, com i < j < n.
            for i, item in enumerate(sorted_states):
                for item_2 in sorted_states[i + 1:]:

                    # Verificamos se o quadrado já está marcado
                    if table[(item, item_2)]:
                        # Se estiver, então os estados são distintos
                        continue

                    # Precisamos checar as transições dos estado item e item_2
                    # para saber se eles são distinguíveis
                    for w in self.terminals:
                        # 'None' é para o caso em que algum estado não esteja
                        # definido para algum determinado terminal
                        t1 = self.transitions.get((item, w), None)
                        t2 = self.transitions.get((item_2, w), None)

                        if t1 is not None and t2 is not None and t1 != t2:
                            # Se para pelo menos um transição os estados forem
                            # distintos, então os marcamos na tabela
                            marked = table[order_tuple(t1, t2)]
                            flag = flag or marked
                            # Se os estads t1 e t2 forem distintos, então os
                            # estados item e item_2 também serão distintos
                            # então, ao invés de criar uma lista de dependências,
                            # já vamos logo marcando (item,item_2) como sendo distintos
                            table[(item, item_2)] = marked

                            if marked:
                                break

        d = DisjointSet(self.states)

        # Após analisar os estados, e descobrir aqueles que são distintos
        # e aqueles que não são, unimos aqueles que são iguais num único estado
        for k, v in table.items():
            if not v:
                d.union(k[0], k[1])

        # Atualizando os estados após a união dos estados iguais
        # d.get() retorna o conjunto com os arrays
        # de estados, se o array tem um único elemento
        # então não há estados equivalentes ao estado
        # em questão, se houver dois ou mais estados
        # no mesmo array, então todos aqueles estados são
        # equivalentes
        self.states = [str(x) for x in range(1, 1 + len(d.get()))]
        new_final_states = []
        # Buscando no disjoint set o array onde
        # está o estado inicial
        self.start_state = str(d.find_set(self.start_state))

        # Pegando os arrays de estados do 'd'
        for s in d.get():
            # Pegando os estados de 's'
            for item in s:
                if item in self.final_states:
                    # Construindo uma lista de novos estados finais
                    new_final_states.append(str(d.find_set(item)))
                    break

        # Atualizando as transições
        self.transitions = {(str(d.find_set(k[0])), k[1]): str(d.find_set(v))
                            for k, v in self.transitions.items()}

        self.final_states = new_final_states
        print("AFD minimizado")