def setUp(self): self.graph = Graph() self.emptyGraph = Graph() self.values = [3, 1, 4, 5, 9, 2, 6, 8, 7, 0] self.pairs = [(3, 4), (2, 9), (2, 4)] for n in self.values: self.graph.add_node(n) for n1, n2 in self.pairs: self.graph.add_edge(n1, n2) self.values.sort()
def test_weighted_vertices(self): g = Graph.from_file_weighted_vertices('graph_weighted_vertices') self.assertListEqual(dijkstra(g, 0, 7), [0, 1, 7]) self.assertListEqual(dijkstra(g, 0, 6), [0, 1, 7, 6]) self.assertListEqual(dijkstra(g, 0, 2), [0, 3, 2]) self.assertListEqual(dijkstra(g, 4, 5), [4, 1, 0, 3, 5]) self.assertListEqual(dijkstra(g, 4, 2), [4, 7, 6, 2]) self.assertListEqual(dijkstra(g, 4, 7), [4, 7])
def test_bfs(): a = Graph(["0", "1", "2", "3", "5", "6"], [("0", "1"), ("1", "2"), ("1", "6"), ("2", "5"), ("2", "3")]) assert bfs(a, "0", "7", set()) is False assert bfs(a, "0", "6", set()) is True assert bfs(a, "0", "3", set()) is True assert bfs(a, "0", "2", set()) is True
def __init__(self, id_, name, electrical_system, province, commune, cross_sectional_area, receptor): self.id_structure = id_ self.name = name self.electrical_system = electrical_system self.province = province self.commune = commune self.cross_sectional_area = cross_sectional_area self.connected_to = Graph(id_, self) self.receptor = receptor self.max_of_parents = inf self.power_consumed = 0.0 # potencia que se necesita para funcionar self.parents_data = List() self.received_power = 0.0 self._demanded_power = 0.0 # Guarda el valor de la demanda, # así este solo se calcula una vez self.received = False self.extra_energy = 0
def maybe_remove_duplicate_edges(graph: Graph): if graph.is_oriented: return graph new_edges = [] for edge in graph.edges: if not _has_adjacent_edge(edge, new_edges): new_edges.append(edge) graph.edges = new_edges return graph
def dfs(graph: Graph, start_node: str, target_node: str, visited_nodes: set): stack = Stack() stack.push(start_node) while not stack.is_empty(): current = stack.pop() if current == target_node: return True adj = graph.get_edges_node(current) for node in adj: if node not in visited_nodes: stack.push(node) return False
def __init__(self, config, passenger_generator=PoissonPassengerGenerator): """ Read configuration and do sth with it :param config :type config: Config """ Bus.BUS_COUNTER = 0 self.finished = False self.steps = -1 self.__buses = [] self.__lines = [] self.__stops = {} self.__create_stops(config.stops) self.__graph = Graph.from_config(config.graph_dict) self.__create_lines(config.lines_dict) self.__passengers_generator = passenger_generator( config.traffic_data_dict)
def bfs(graph: Graph, start_node: str, target_node: str, visited_nodes: set): queue = Queue() queue.enqueue(start_node) while not queue.is_empty(): current = queue.deque() if current == target_node: return True adj = graph.get_edges_node(current) for node in adj: if node not in visited_nodes: queue.enqueue(node) visited_nodes.add(current) return False
def get_mst_kruskal(graph): # create a new graph structure to hold the MST mst = Graph() # create and a disjoint set # and populate it with all the vertices in the graph disjoint_set = DisjointSet() for i in range(len(graph)): disjoint_set.add(i) # create a list of edges and sort it in descending order edges = [(u, v, w) for u, adjacencies in graph.adjacencies.items() for v, w in adjacencies.items()] # iterate over the edge list # we first sort the edge list by ascending weight for edge in sorted(edges, key=lambda edge: edge[2], reverse=True): # isolate the components of this edge u, v, w = edge # for each vertex in the edge, # find the parent in each set u_parent = disjoint_set.find(u) v_parent = disjoint_set.find(v) # if two vertices share the same parent, # they have already been added to the MST # since we don't want to create cycles, we skip adding edges that join # vertices that have already been joined to the MST if u_parent.id != v_parent.id: # if the vertices haven't been joined to the MST... # ...we add that edge to the MST mst.addEdge(u, v, w) # and add it to the disjoint set to help track which vertices # have been added to the MST disjoint_set.union(u, v) return mst
def test_kruskal(self): mst_total_weight = 23 g = Graph.from_file('graph_MST') result = kruskal(g) self.assertEqual(result, mst_total_weight)
def test_dijkstra(self): g = Graph.from_file('graph_shortest_path') result = dijkstra(g, 0, 7) self.assertListEqual(result, [0, 1, 7]) result = dijkstra(g, 0, 4) self.assertListEqual(result, [0, 1, 7, 4])
def test_bfs(self): g = Graph.from_file('graph_bfs') result = bfs(g, 0) self.assertDictEqual(result, {1: 0, 2: 1, 4: 0, 3: 4, 5: 0})
from data_structures import Graph, Stack def dfs(graph: Graph, start_node: str, target_node: str, visited_nodes: set): stack = Stack() stack.push(start_node) while not stack.is_empty(): current = stack.pop() if current == target_node: return True adj = graph.get_edges_node(current) for node in adj: if node not in visited_nodes: stack.push(node) return False a = Graph(["0", "1", "2", "3", "5", "6"], [ ("0", "1"), ("1", "3"), ("2", "3"), ("2", "5"), ("1", "6")]) print(dfs(a, "0", "3", visited_nodes=set()))
graph -- Graph -- graph structure of sentences Postondition: returns Nothing creates html file in same directory """ f = open(file_name + ".html", "w+") f.write("<!DOCTYPE html>") f.write("<html><body><ul>") f.write(graph.to_html_structure(graph.root)) f.write("</ul></body></html>") f.close() # TEST if __name__ == "__main__": graph = Graph() graph.add_node("Root**") graph.add_node("Suptopic1*") graph.add_node("Suptopic2*") graph.add_node("sentence1") graph.add_node("sentence2") graph.add_node("sentence3") graph.add_node("sentence4") graph.add_node("sentence5") graph.add_node("sentence6") graph.add_node("sentence7") graph.set_root("Root**") graph.add_child_edges("Root**", "Suptopic1*") graph.add_child_edges("Root**", "Suptopic2*") graph.add_child_edges("Suptopic1*", "sentence1")
def test_prims(self): mst_total_weight = 23 g = Graph.from_file('graph_MST') result = prim(g, 0) self.assertEqual(result, mst_total_weight)
class TestGraph(unittest.TestCase): def setUp(self): self.graph = Graph() self.emptyGraph = Graph() self.values = [3, 1, 4, 5, 9, 2, 6, 8, 7, 0] self.pairs = [(3, 4), (2, 9), (2, 4)] for n in self.values: self.graph.add_node(n) for n1, n2 in self.pairs: self.graph.add_edge(n1, n2) self.values.sort() def test_add_node(self): '''Test adding nodes to a graph.''' # implicitly test Graph.nodes() as well self.assertEqual(self.graph.nodes(), self.values) self.assertEqual(self.emptyGraph.nodes(), []) # test adding a duplicate node self.graph.add_node(0) self.assertEqual(self.graph.nodes(), self.values) def test_add_edge(self): '''Test adding edges to a graph (w/o using has_edge).''' test = set([]) # create a set listing edges as tuples for n1, edges in self.graph.Nodes.iteritems(): for n2 in edges: pair = (n1, n2) test.add((min(pair), max(pair))) # ensure that setUp appropriately added edges self.assertEqual(test, set(self.pairs)) # test adding an existent edge self.graph.add_edge(3, 4) self.assertTrue(3 in self.graph.Nodes[4]) self.assertTrue(4 in self.graph.Nodes[3]) # test adding an edge to a non-existent node self.graph.add_edge(3, 10) self.assertTrue(3 in self.graph.Nodes[10]) self.assertTrue(10 in self.graph.Nodes[3]) self.assertEqual(self.graph.nodes(), range(11)) # test adding an edge to multiple non-existent nodes self.emptyGraph.add_edge(2, 1) # self.assertEqual(self.emptyGraph.edges(), [set((2, 1))]) self.assertTrue(2 in self.emptyGraph.Nodes[1]) self.assertTrue(1 in self.emptyGraph.Nodes[2]) self.assertEqual(self.emptyGraph.nodes(), [1, 2]) def test_del_node(self): '''Test deleting nodes from a graph.''' self.graph.del_node(1) self.graph.del_node(4) self.assertEqual(self.graph.nodes(), [0, 2, 3, 5, 6, 7, 8, 9]) self.assertFalse(4 in self.graph.Nodes[2]) self.assertFalse(4 in self.graph.Nodes[3]) # test deleting fron an empty graph with self.assertRaises(ValueError): self.emptyGraph.del_node(0) def test_del_edge(self): '''Test deleting edges from a graph.''' # test deleting an existent edge self.graph.del_edge(3, 4) self.assertFalse(3 in self.graph.Nodes[4]) self.assertFalse(4 in self.graph.Nodes[3]) # ensure that the nodes remained intact self.assertEqual(self.graph.nodes(), self.values) # test deleting a non-existent edge between existent nodes with self.assertRaises(ValueError): self.graph.del_edge(1, 2) # test deleting an edge between non-existent nodes with self.assertRaises(ValueError): self.emptyGraph.del_edge(1, 2) def test_has_node(self): '''Test checking whether a graph contains certain nodes.''' for n in self.values: self.assertTrue(self.graph.has_node(n)) self.assertFalse(self.graph.has_node(99)) self.assertFalse(self.emptyGraph.has_node(99)) def test_neighbors(self): '''Test listing the neighbors of nodes in a graph.''' self.assertEqual(self.graph.neighbors(0), []) self.assertEqual(self.graph.neighbors(3), [4]) self.assertEqual(self.graph.neighbors(4), [2, 3]) # test listing neighbors for non-existent nodes with self.assertRaises(ValueError): self.emptyGraph.neighbors(99) def test_is_adjacent(self): '''Test checking whether two nodes are adjacent.''' self.assertFalse(self.graph.is_adjacent(0, 9)) self.assertTrue(self.graph.is_adjacent(4, 3)) # test checking adjacency with non-existent nodes with self.assertRaises(ValueError): self.emptyGraph.is_adjacent(0, 99)
def kmeans_merge_clustering(self, sentences, vectors, graph=None, num_clusters=None): """does recursive kmeans merge clustering Preconditions: sentences -- list -- list of sentences vectors -- 2d numpy array -- vectors graph -- Graph() -- for recursion num_clusters -- int -- number of clusters Postconditions: returns graph (Graph()) structure of sentence nodes """ if num_clusters == None: num_clusters = self.pick_number_clusters(vectors) if graph == None: graph = Graph() for s in sentences: graph.add_node(s) table = Table(sentences, vectors) parent_sentences = [] parent_vectors = [] labels, centroids = self.train(vectors, num_clusters) label_dict = {} for i in range(num_clusters): label_dict[i] = [] for i in range(vectors.shape[0]): label_dict[labels[i]].append(vectors[i]) #determine the new_sentences for i in range(num_clusters): min_vector = self.find_closest_vector(centroids[i], label_dict[i]) #found the min_vector, so go add entry to table and make parent graph.add_node(table.retrieve_sentence(min_vector) + "*") parent_sentences.append(table.retrieve_sentence(min_vector) + "*") parent_vectors.append(np.array(centroids[i], copy=True)) #add edges to the graph, parent to child for v in label_dict[i]: graph.add_child_edges(parent_sentences[i], table.retrieve_sentence(v)) vectors = np.array(parent_vectors, copy=True) # base case if num_clusters == 1: graph.set_root(parent_sentences[0]) return graph # recursive case else: return self.kmeans_merge_clustering(parent_sentences, vectors, graph)
def __init__(self): self.graph = Graph()
class Entity: def __init__(self, id_, name, electrical_system, province, commune, cross_sectional_area, receptor): self.id_structure = id_ self.name = name self.electrical_system = electrical_system self.province = province self.commune = commune self.cross_sectional_area = cross_sectional_area self.connected_to = Graph(id_, self) self.receptor = receptor self.max_of_parents = inf self.power_consumed = 0.0 # potencia que se necesita para funcionar self.parents_data = List() self.received_power = 0.0 self._demanded_power = 0.0 # Guarda el valor de la demanda, # así este solo se calcula una vez self.received = False self.extra_energy = 0 @property def current_power(self): if isinstance(self, Consumer) and self.received_power > 30: raise ElectricalOverload("Añadir", f"{self._demanded_power - 30} mW") available = self.received_power - self.power_consumed if available <= 0: return 0 return available @property def used_power(self): used = self.received_power - self.current_power if used < 0: return self.received_power return used @property def demanded_power(self): """ Retorna la potencia demandada por el nodo actual mas la potencia demandada por los hijos de este considerando la perdida de energia """ total_power = self.power_consumed for i in self.connected_to: total_power += self.power_required_to_send(i) # resistencia if len(self.parents_data) > 0: self._demanded_power = total_power / len(self.parents_data) if self._demanded_power > 30 and isinstance(self, Consumer): raise ElectricalOverload("Add_connection", f"{self._demanded_power - 30} mW") return total_power / len(self.parents_data) # Se divide el gasto # entre los padres del nodo self._demanded_power = total_power # Asi se accede más rapido a este # valor if self._demanded_power > 30 and isinstance(self, Consumer): raise ElectricalOverload("Add_connection", f"{self._demanded_power - 30} mW") return total_power @property def drained_energy(self): total_drained = 0 direct_connnection = self.find_direct_connection() if direct_connnection is None: print("Casa aislada") return 0 first = 0 second = 1 while first < len(direct_connnection) - 1: total_drained += ( direct_connnection[first].value.get_relative_power_to_send( direct_connnection[second].value) * direct_connnection[second].value.get_resistance( direct_connnection[first].value)) # Se suma: Potencia mandada * Resistenca = Potencia perdida en el # cable first += 1 second += 1 return total_drained def find_direct_connection(self): # Busca la conexion directa a una # elevadora if isinstance(self, LiftingStation): # Caso base: Llegamos a la # estacion elevadora return List(self) for i in self.parents_data: # De lo contrario buscamos en los padres result = i.value[0].value.find_direct_connection() if result is not None: result.append(self) # Se agrega a si mismo y se retorna return result def power_required_to_send(self, element): # Retorna # potencia requerida por un element que es hijo del nodo actual return element.demanded_power / (1 - element.get_resistance(self)) def get_relative_power_to_send(self, element): # Emtrega la cantidad de energia que debe mandar a element en relacion # a lo que están demandadando en total al nodo actual total = 0 element_demand = element._demanded_power / ( 1 - element.get_resistance(self)) for i in self.connected_to: total += i._demanded_power / (1 - i.get_resistance(self)) return self.current_power * (element_demand / max(1, total)) def get_resistance(self, from_): # Entrega solo la potencia pérdida # entre el nodo actual y un padre RESISTIVITY = 0.0172 for i in self.parents_data: if i.value[0].value == from_: return RESISTIVITY * i.value[1].value / i.value[2].value def use_extra_energy(self, demanded_power, power_to_send): if self.extra_energy == 0: return power_to_send # Si es 0 no ocurre nada if demanded_power - power_to_send <= self.extra_energy: self.extra_energy -= demanded_power - power_to_send # Se le resta # lo que se ocupa de esta sobra return demanded_power # Se suple la demanda aditional = power_to_send + self.extra_energy # Se usa extra self.extra_energy = 0 # Se usará toda return aditional def send_power(self, element): power_to_send = self.get_relative_power_to_send(element) # Se verifica que no se mande más de lo necesario if power_to_send > element._demanded_power / ( 1 - element.get_resistance(self)): self.extra_energy += power_to_send - ( element._demanded_power / (1 - element.get_resistance(self))) element.received_power += element._demanded_power # Se suple su # demanda else: element.received_power += self.use_extra_energy( element._demanded_power, power_to_send) * (1 - element.get_resistance(self)) def distribute_power(self, to=None): # Primero el nodo le pide a todos sus padres que le manden energia if not self.received: for i in self.parents_data: i.value[0].value.distribute_power(self) # Luego de que ya le llega energía desde todos sus padres # entonces le manda a sus hijos self.received = True # Ya recibio la energia asi que dejamos el # registro de que recibio completamente su energia if to is not None: for i in self.connected_to: if i == to: self.send_power(i) return def set_parent_data(self, element, distance): """ Envia la informacion del padre a parents_data de element """ data = List(self, distance, self.cross_sectional_area) element.parents_data.append(data) def delete_parent_data(self, element): index_ = 0 for i in element.parents_data: if i.value[0].value == self: element.parents_data.remove(index_) return index_ += 1 def quick_connection(self, element, distance): # Funciona igual que # add_connection solo que se evita hacer comparaciones self.set_parent_data(element, distance) self.connected_to.add_node(element.id_structure, element) self.connected_to.add_connection(element.id_structure) def add_connection(self, element, distance): if (isinstance(element, TransmisionSubstation) or isinstance(element, DistributionSubstation)) and len( element.parents_data) > 0: raise ForbbidenAction( "add_connection", "Subestaciones de " "transmision no admiten " "más de un padre") if ((isinstance(self, Consumer) or isinstance(self, DistributionSubstation)) and isinstance( element, Consumer)) and \ self.commune != element.commune: raise ForbbidenAction( "add_connection", f"Imposible unir " f"{type(self)} con {type(element)} debido a " f"que son de distintas comunas") if self.electrical_system == element.electrical_system: if type(element) == self.receptor: if element not in self.connected_to: self.connected_to.add_node(element.id_structure, element) self.connected_to.add_connection(element.id_structure) self.set_parent_data(element, distance) else: # Si la conexion existe raise ForbbidenAction("add_connection", f"El camino ya " f"existe") return raise ForbbidenAction( "add_connection", f"{type(self)} no " f"puede unirse a " f"{type(element)}") raise ForbbidenAction("add_connection", "Nodos de distintos sistemas " "electricos") def remove_connection(self, element): if element in self.connected_to: self.connected_to.remove_connection(element.id_structure) self.delete_parent_data(element) else: raise ForbbidenAction("remove_connection", f"Camino no existente") def remove_self(self, liftings, transmisions, distributions, consumers): for i in self.parents_data: # Se desconecta de los padres i.value[0].value.remove_connection(self) for i in self.connected_to: # Se desconecta de los hijos self.remove_connection(i) if len(i.parents_data) == 0: # En caso que el hijo se quede sin # padre también se extrae i.remove_self(liftings, consumers, distributions, consumers) # Finalmente el nodo se quita de la lista if isinstance(self, LiftingStation): liftings.remove(self.id_structure) elif isinstance(self, TransmisionSubstation): transmisions.remove(self.id_structure) elif isinstance(self, DistributionSubstation): distributions.remove(self.id_structure) elif isinstance(self, Consumer): consumers.remove(self.id_structure) def __eq__(self, other): return self.id_structure == other.id_structure