def bipartite_connected(
    g: Graph, s: Graph.Vertex, discovered: Set[Graph.Vertex]
) -> Optional[Tuple[List[Graph.Vertex], List[Graph.Vertex]]]:
    """
    :param g: grafo non orientato
    :param s: vertice di partenza
    :param discovered: set di nodi già visitati
    :return: restituisce le due partizioni altrimenti None
    """
    colour = {s: 0}  # assegno al primo vertice colore 0
    q = [s]  # creo una coda con i vertici da considerare
    x = [s]  # creo la sotto-partizione 1 con assegnato il primo vertice
    y = []  # creo la sotto- partizione 2

    while q:  # finché la coda non è vuota
        current = q.pop()  # prendo il vertice da elaborare
        next_colour = 1 - colour[
            current]  # i vertici opposti avranno colore opposto al vertice corrente
        for dest in g.incident_edges(
                current):  # considero tutti gli archi uscenti
            v = dest.opposite(current)  # e mi prendo il vertice opposto
            if v not in discovered:  # se è la prima volta che vedo quel vertice
                discovered.add(v)  # lo segno come visitato
                colour[v] = next_colour  # gli assegno il nuovo colore
                if next_colour == 0:  # se 0
                    x.append(v)  # lo assegno alla prima sotto-partizione
                else:  # altrimenti
                    y.append(v)  # lo assegno alla seconda sotto-partizione
                q.append(
                    v
                )  # il vertice visitato dovrà essere considerato al prossimo ciclo
            elif colour[
                    v] != next_colour:  # altrimenti se ho già visto il vertice e il suo colore non è opposto al vertice corrente
                return None  # la componente connessa al vertice sorgente non è bipartibile
    return x, y  # se arrivo qui vuol dire che è bipartibile e restituisco le partizioni
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
Beispiel #3
0
def bipartite(graph: Graph, start: Graph.Vertex, x: List, y: List,
              discover: Dict):
    """

    :param graph: grafo non diretto
    :param start: nodo di partenza
    :param x: partizione sinistra dei nodi
    :param y: partizione destra dei nodi
    :param discover: nodi visitati
    :return: true se è bipartito, false se non lo è
    """
    level = [start]
    i = 0
    while len(level) > 0:
        next_level = []
        i = (i + 1) % 2
        for vertex in level:
            for edges in graph.incident_edges(vertex):
                opposite_vertex = edges.opposite(vertex)
                if opposite_vertex not in discover:
                    discover[opposite_vertex] = i
                    if i % 2 == 0:
                        x.append(opposite_vertex)
                    else:
                        y.append(opposite_vertex)
                    next_level.append(opposite_vertex)
                elif discover[opposite_vertex] == (i + 1) % 2:
                    # L'ho inserito nell'altro insieme e ora devo inserirlo in i ==> Errore
                    return False
        level = next_level
    return True
Beispiel #4
0
def children(graph: Graph, root: Graph.Vertex, parent: Graph.Vertex):
    """ 
    Helper function.
    Return an iterator on the children of root,
    a children is defined as every neighbour except the vertex passed as parent
    """
    for edge in graph.incident_edges(root):
        opposite_vertex = edge.opposite(root)
        if opposite_vertex != parent:
            yield opposite_vertex
Beispiel #5
0
def DFS_bridge(g, u, discovered, ordineVisita):

    for e in g.incident_edges(u):  # for every outgoing edge from u
        v = e.opposite(u)

        if v not in discovered:  # v is an unvisited vertex
            newEdge = Graph.Edge(u, v, None)
            ordineVisita.append(newEdge)
            discovered[v] = e  # e is the tree edge that discovered v
            DFS_bridge(g, v, discovered,
                       ordineVisita)  # recursively explore from v
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
Beispiel #7
0
def installer(graph: Graph, root: Graph.Vertex):
    """
    Install the software on the minimum number of vertices so that for every pair of vertices,
    at least one of them has the software.

    Return a 2 elements tuple composed by the number of vertices on which the software is 
    installed and a list of such vertices
    """

    if not graph.degree(root):  # Base Case single vertex tree
        return (1, [root])

    # Start iteration
    return install(graph, root, None, {}, [])
Beispiel #8
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
def iterative_dfs(starting_vertex, graph):
    """Perform DFS of the undiscovered portion of Graph g starting at Vertex u.
    It takes O(sum(degree(v)^2) + V)"""
    starting_vertex.discovered = True
    starting_vertex.discovery_edge = Graph.Edge(starting_vertex, None,
                                                None)  # Dummy edge
    walk = starting_vertex

    while walk is not None:
        has_to_go_back = True
        for edge in graph.incident_edges(walk):
            opposite = edge.opposite(walk)
            if not opposite.discovered:
                opposite.discovered = True
                opposite.discovery_edge = edge
                walk = opposite
                has_to_go_back = False
                break

        if has_to_go_back:
            walk = walk.discovery_edge.opposite(walk)

    starting_vertex.discovery_edge = None  # Remove dummy edge
Beispiel #10
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}
Beispiel #11
0
from TdP_collections.graphs.graph import Graph
from Gruppo6_4_TdP.pkg_3.emergency_call import emergency_call
import string
from Gruppo6_4_TdP.util import randList

grafo1 = Graph(True)

v0 = grafo1.insert_vertex(0)
v1 = grafo1.insert_vertex(1)
v2 = grafo1.insert_vertex(2)
v3 = grafo1.insert_vertex(3)
v4 = grafo1.insert_vertex(4)
v5 = grafo1.insert_vertex(5)
v6 = grafo1.insert_vertex(6)

grafo1.insert_edge(v1, v0, 1)
grafo1.insert_edge(v0, v4, 4)
grafo1.insert_edge(v3, v4, 3)
grafo1.insert_edge(v1, v3, 10)
grafo1.insert_edge(v1, v2, 1)
grafo1.insert_edge(v4, v5, 2)
grafo1.insert_edge(v5, v6, 1)
grafo1.insert_edge(v2, v6, 1)
grafo1.insert_edge(v6, v4, 1)

# polizia = {v4: 1, v5: 2, v6: 3}

polizia = {1: v4, 2: v5, 3: v6}

volanti = emergency_call(grafo1, polizia, v5, 2)
Beispiel #12
0
from TdP_collections.graphs.graph import Graph
from Ex4 import FakeNewsDetector

graph = Graph()

vertices = []
for i in range(0, 9):
    vertices.append(graph.insert_vertex(i))

graph.insert_edge(vertices[0], vertices[1])
graph.insert_edge(vertices[0], vertices[2])
graph.insert_edge(vertices[0], vertices[3])
graph.insert_edge(vertices[1], vertices[4])
graph.insert_edge(vertices[1], vertices[5])
graph.insert_edge(vertices[2], vertices[6])
graph.insert_edge(vertices[3], vertices[7])
graph.insert_edge(vertices[5], vertices[8])

n, l = FakeNewsDetector.installer(graph, vertices[0])
print(n)
print(*l, sep="-")
Beispiel #13
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
Beispiel #14
0
from TdP_collections.graphs.graph import Graph
from pkg_4.esercizio4 import complete_bipartite

graph1 = Graph()
graph2 = Graph()
graph3 = Graph()
graph4 = Graph()
vertex = []

print("TEST GRAFO BIPARTIBILE")
for i in range(4):
    vertex.append(graph1.insert_vertex(i))

graph1.insert_edge(vertex[0], vertex[1])
graph1.insert_edge(vertex[0], vertex[2])
graph1.insert_edge(vertex[1], vertex[3])
graph1.insert_edge(vertex[2], vertex[3])

bipartibile, x, y = complete_bipartite(graph1)

if bipartibile:
    print("E' bipartibile ")
    print("Insieme di bipartizione X")
    for k in x:
        print(k)
    print("Insieme di bipartizione Y")
    for k in y:
        print(k)
else:
    print("Non e' bipartibile ")
Beispiel #15
0
def test_bipartite_unconnected_not_verified():
    B = Graph()
    v1 = B.insert_vertex(1)
    v2 = B.insert_vertex(2)
    v3 = B.insert_vertex(3)
    v4 = B.insert_vertex(4)
    v5 = B.insert_vertex(5)
    v6 = B.insert_vertex(6)
    v7 = B.insert_vertex(7)
    B.insert_edge(v1, v2, 3)
    B.insert_edge(v1, v4, 3)
    B.insert_edge(v3, v2, 5)
    B.insert_edge(v3, v4, 2)

    B.insert_edge(v5, v6, 1)
    B.insert_edge(v5, v7, 1)

    # arco rotto
    B.insert_edge(v2, v4, 2)

    if bipartite(B) is None:
        print('Test test_bipartite_unconnected_not_verified passed')
    else:
        print('Test test_bipartite_unconnected_not_verified failed')
Beispiel #16
0
def test_bipartite_connected_not_verified():
    """
    Verifica che che bipartite() riconosca correttamente un grafo connesso non bipartito
    :return:
    """
    B = Graph()
    v1 = B.insert_vertex(1)
    v2 = B.insert_vertex(2)
    v3 = B.insert_vertex(3)
    v4 = B.insert_vertex(4)
    v5 = B.insert_vertex(5)
    v6 = B.insert_vertex(6)
    v7 = B.insert_vertex(7)
    B.insert_edge(v1, v2, 3)
    B.insert_edge(v1, v4, 3)
    B.insert_edge(v2, v3, 5)
    B.insert_edge(v3, v4, 2)
    B.insert_edge(v4, v5, 5)
    B.insert_edge(v5, v6, 1)
    B.insert_edge(v5, v7, 1)

    # arco rotto
    B.insert_edge(v2, v4, 5)

    if bipartite(B) is None:
        print('Test test_bipartite_connected_not_verified passed')
    else:
        print('Test test_bipartite_connected_not_verified failed')
Beispiel #17
0
                            )  # se il vertice attuale è rosso coloro quelli collegati di blu
                        elif color == 2:
                            red.add(
                                v
                            )  # se il vertice attuale è blu coloro quelli collegati di rosso
                    else:
                        if v in red and color == 1 or v in blue and color == 2:  # se i vertici collegati a quello attuale sono già stati visitati controllo il loro colore e se è lo stesso
                            nb = None  # attuale imposto la variabile non bipartito a None

        level = next_level  # vado a controllare il livello successivo
    return nb, red, blue  # ritorno il valore di nb e le due partizioni


if __name__ == '__main__':

    gbi = Graph()  #GRAFO UNO

    a = gbi.insert_vertex("A")
    b = gbi.insert_vertex("B")
    c = gbi.insert_vertex("C")
    d = gbi.insert_vertex("D")
    e = gbi.insert_vertex("E")

    gbi.insert_edge(a, b)
    gbi.insert_edge(a, c)
    gbi.insert_edge(b, d)
    gbi.insert_edge(d, e)
    gbi.insert_edge(e, a)

    gbi2 = Graph()  #GRAFO DUE
Beispiel #18
0
    print("\nprima   partizione composta da : ", sol)
    sol = ""
    for elem in Y:
        sol += str(elem)
        sol += ", "
    print("seconda partizione composta da : ", sol)


print(
    "---------------------------------------- TEST_BIPARTITE ----------------------------------------"
)
print("******* CASO 1 *******")
print(
    "Grafo composto da due componenti non connesse tra di loro ma entrambe bipartibili\n**********************"
)
g = Graph()
v = []
for i in range(1, 9):
    v.append(g.insert_vertex(i))
print("Prima componente connessa composta da 1, 2, 3, 4, 5, 6, 7, 8")
g.insert_edge(v[0], v[1])
g.insert_edge(v[0], v[3])
g.insert_edge(v[2], v[1])
g.insert_edge(v[2], v[3])
g.insert_edge(v[2], v[5])
g.insert_edge(v[4], v[3])
g.insert_edge(v[4], v[5])
g.insert_edge(v[4], v[7])
g.insert_edge(v[6], v[5])
g.insert_edge(v[6], v[7])
Beispiel #19
0
def test_bipartite_connected():
    """
    Verifica che che bipartite() riconosca correttamente un grafo connesso bipartito
    :return:
    """
    B = Graph()
    v1 = B.insert_vertex(1)
    v2 = B.insert_vertex(2)
    v3 = B.insert_vertex(3)
    v4 = B.insert_vertex(4)
    v5 = B.insert_vertex(5)
    v6 = B.insert_vertex(6)
    v7 = B.insert_vertex(7)
    B.insert_edge(v1, v2, 3)
    B.insert_edge(v1, v4, 3)
    B.insert_edge(v2, v3, 5)
    B.insert_edge(v3, v4, 2)
    B.insert_edge(v4, v5, 5)
    B.insert_edge(v5, v6, 1)
    B.insert_edge(v5, v7, 1)
    e = B.edges()

    if bipartite(B) is None:
        print('Test test_bipartite_connected failed')
    else:
        A, B = bipartite(B)
        C = set()
        D = set()
        for x in A:
            C.add(x.element())
        for y in B:
            D.add(y.element())
        graphic_from_partition(C, D, e, 'test_bipartite_connected')
Beispiel #20
0
def test_bipartite_unconnected():
    B = Graph()
    v1 = B.insert_vertex(1)
    v2 = B.insert_vertex(2)
    v3 = B.insert_vertex(3)
    v4 = B.insert_vertex(4)
    v5 = B.insert_vertex(5)
    v6 = B.insert_vertex(6)
    v7 = B.insert_vertex(7)
    B.insert_edge(v1, v2, 3)
    B.insert_edge(v1, v4, 3)
    B.insert_edge(v3, v2, 5)
    B.insert_edge(v3, v4, 2)

    B.insert_edge(v5, v6, 1)
    B.insert_edge(v5, v7, 1)
    e = B.edges()

    if bipartite(B) is None:
        print('Test test_bipartite_unconnected failed')
    else:
        A, B = bipartite(B)
        C = set()
        D = set()
        for x in A:
            C.add(x.element())
        for y in B:
            D.add(y.element())
        graphic_from_partition(C, D, e, 'test_bipartite_unconnected')