Esempio n. 1
0
def bipartite(
        g: Graph) -> Optional[Tuple[List[Graph.Vertex], List[Graph.Vertex]]]:
    """
    La funzione	bipartite() prende in input un grafo G	non	diretto, verifica se G è bipartito e restituisce una
    partizione (X, Y) dei vertici di G tale che tutti gli archi del grafo	collegano un vertice di	X ad un	vertice	di	Y.

    :param g: grafo non orientato
    :return: partizione (X, Y) o None se il grafo non è bipartibile
    """
    visited = set()  # Insieme dei vertici visitati
    x = []  # init partizione 1
    y = []  # init partizione 2
    for u in g.vertices():  # per ogni vertice del grafo
        if u not in visited:  # che non ho ancora visitato
            visited.add(u)  # lo segno come visitato
            result = bipartite_connected(
                g, u, visited
            )  # calcolo bipartite della componente connessa del grafo
            # in cui si trova il vertice
            if result is not None:  # se la componente connessa è bipartibile
                x = x + result[0]  # aggiorno la partizione 1
                y = y + result[1]  # aggiorno la partizione 2
            else:  # altrimenti
                return None  # il grafo non è bipartibile
    return x, y  # restituisco le partizioni
Esempio n. 2
0
def graph_randomize(n: int):
    graph = Graph()
    random = Random()

    for i in range(0, n):
        graph.insert_vertex(i)

    for v in graph.vertices():
        for u in graph.vertices():
            if bool(random.getrandbits(1)) and u != v and graph.get_edge(
                    u, v) is None:
                graph.insert_edge(u, v)

    print("number of vertices " + str(graph.vertex_count()) +
          "\nnumber of edges " + str(graph.edge_count()))

    return graph
def bipartite(G: Graph):
    """
    La funzione verifica se G è bipartito e restituisce una partizione (X, Y) dei vertici di G tale che
    tutti gli archi del grafo collegano un vertice di X ad un vertice di Y. Nel caso in cui il grafo non
    sia bipartito la funzione deve restituire None.
    :param G: grafo non diretto da ispezionare
    :return: None se il grafo non è bipartito, altrimenti una sua partizione

    Il problema corrisponde alla verifica della k-colorabilità di un grafo, cioè verificare se è possibile,
    dato un grafo non diretto, colorarlo con al più k colori in modo che non esistano due vertici adiacenti
    dello stesso colore. Nel caso il problema si riduce alla 2-colorabilità.
    La complessità computazionale è la stessa della DFS completa, e cioè O(n+m), siccome la classe Graph
    rappresenta il grafo utilizzando liste di adiacenza, in cui n è il numero di vertici ed m il numero di archi.
    """
    discovered = {}  # dizionario per tenere traccia dei nodi visitati
    color = {}  # dizionario per tenere traccia dei colori dei nodi
    X = set()  # partizioni del grafo
    Y = set()
    partition = None

    for node in G.vertices():  # inizializza i colori dei nodi
        if node not in color:
            color[node] = False
    for v in G.vertices():     # tiene conto di grafi non connessi
        if v not in discovered:
            partition = color_dfs(G, v, discovered, color)
            if partition is None:
                return partition
    if partition is not None:
        # popola le due partizioni del grafo
        for x in partition.items():
            if x[1] is True:
                X.add(x[0])
            else:
                Y.add(x[0])
        return X, Y
    else:
        return partition
Esempio n. 4
0
def complete_bipartite(graph: Graph):
    """

    :param graph: grafo non diretto
    :returns: True/False se il grafo è bipartito o meno, x e y come partizioni contenenti i nodi (se bipartito)
    """
    discover = {}
    x = []
    y = []

    for vertex in graph.vertices():
        if vertex not in discover:
            discover[vertex] = 0
            x.append(vertex)
            if not bipartite(graph, vertex, x, y, discover):
                return False, None, None

    return True, x, y
Esempio n. 5
0
def bacefook_greedy_algorithm(graph: Graph):
    """
        greedy algorithm to compute the minimum number of nodes
        with software

        map structure:

        -Key store all vertices of the graph
        -Value is a dict

            dict structure:

            -token store locator from priority queue
            -so_sw_count store the number of adj nodes
            -has_sw bool if the node has the software

        Priority queue store all the nodes of the graph ordered by number of adj nodes
    """
    priority_queue = AdaptableHeapPriorityQueue()
    map = {}
    for v in graph.vertices():
        token = priority_queue.add(-graph.degree(v), v)
        map[v] = {
            'token': token,
            'no_sw_count': graph.degree(v),
            'has_sw': False
        }

    for i in range(0, graph.vertex_count()):
        k, v = priority_queue.remove_min()
        if graph.degree(v) == 0:
            continue
        if k == 0:
            break
        map[v]['has_sw'] = True
        for e in graph.incident_edges(v):
            adj_v = e.opposite(v)
            if not map[adj_v]['has_sw']:
                map[adj_v]['no_sw_count'] -= 1
                priority_queue.update(map[adj_v]['token'],
                                      -map[adj_v]['no_sw_count'], adj_v)

    return {v._element: map[v]['has_sw'] for v in map}