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
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
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
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
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, {}, [])
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
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}
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)
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="-")
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
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 ")
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')
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')
) # 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
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])
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')
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')