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 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 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 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}