def __call__(self, chromosome, **kwargs): ''' Parameters: chromosome : is a EdgeSet type or a Bag Results : _cost : Number the edgeset cost nro_components : int graph components identified ''' assert isinstance( chromosome, EdgeSet ), f"unsupported operation for chromosome type {type(chromosome)}" disjointset = DisjointSets() _cost = 0 GRAPH = self.STPG.graph for v, u in chromosome: if not GRAPH.has_edge(v, u): raise RuntimeError("STPG instance has not this edge") _cost += GRAPH.weight(v, u) if v not in disjointset: disjointset.make_set(v) if u not in disjointset: disjointset.make_set(u) disjointset.union(v, u) nro_components = len(disjointset.get_disjoint_sets()) _cost += self.penality_function(nro_components) return _cost, nro_components
def __call__(self, parent_a, parent_b): assert isinstance( parent_a, EdgeSet ), f'parent_a has to be EdgeSet type. Give was {type(parent_a)}' assert isinstance( parent_b, EdgeSet ), f'parent_b has to be EdgeSet type. Give was {type(parent_b)}' edges = parent_a | parent_b done = DisjointSets() for v in edges.vertices: done.make_set(v) edges = set(edges) result = EdgeSet() while edges and len(done.get_disjoint_sets()) > 1: edge = sample(edges, k=1)[0] y, z = edge[0], edge[1] if done.find(y) != done.find(z): result.add(edge) done.union(y, z) edges.discard(edge) return result
def test_EvaluateZeroChromossome(self): stpg = self.stpg graph = self.stpg.graph nro_terminals = stpg.nro_terminals terminals = stpg.terminals disset = DisjointSets() for v in terminals: disset.make_set(v) edges_sum = 0 done = set() for t in terminals: done.add(t) for v in graph.adjacent_to(t): if v in terminals and v not in done: disset.union(t, v) edges_sum += graph.weight(t, v) qtd_disjoint_sets = len(disset.get_disjoint_sets()) expected_lenght = stpg.nro_nodes - stpg.nro_terminals chromosome = '0' * expected_lenght evaluator = EvaluateKruskalBased(stpg) evaluator_cost, qtd_partitions = evaluator(chromosome) self.assertEqual(evaluator_cost, ((qtd_partitions - 1) * 1_000) + edges_sum) self.assertEqual(evaluator_cost, ((qtd_disjoint_sets - 1) * 1_000) + edges_sum) self.assertEqual(qtd_partitions, qtd_disjoint_sets)
def __call__(self, red, blue): assert isinstance( red, UGraph), f'red parent must be UGraph. Given {type(red)}' assert isinstance( blue, UGraph), f'blue parent must be UGraph. Given {type(blue)}' done = DisjointSets() union_g = UGraph() for v, u in red.gen_undirect_edges(): union_g.add_edge(v, u) for v, u in blue.gen_undirect_edges(): union_g.add_edge(v, u) for v in union_g.vertices: done.make_set(v) all_edges = set() for edge in union_g.gen_undirect_edges(): all_edges.add(edge) result = UGraph() while all_edges and len(done.get_disjoint_sets()) > 1: edge = sample(all_edges, k=1)[0] v, u = edge[0], edge[1] if done.find(v) != done.find(u): result.add_edge(v, u) done.union(v, u) all_edges.remove(edge) return result
def __call__(self, chromosome, **kwargs): GRAPH = self.STPG.graph penality = self.penality_function vertices = self.vertices_from_chromosome(chromosome) # instânciando variáveis e funções auxiliares queue = PriorityQueue() dones = set() # adiciona uma aresta se os vértices extremos da aresta # estão contidos no conjunto vertices # mantém essas arestas em uma fila de prioridades para # formar uma MST baseado no algoritmo de Kruskal # (o trabalho de Kapsalis utilizava o algoritmo de Prim) for v in vertices: dones.add(v) for u in GRAPH.adjacent_to(v): if (u in vertices) and (u not in dones): weight = GRAPH.weight(v, u) queue.push(weight, (v, u, weight)) ## Monta a MST baseado no algoritmo de Kruskal DS = DisjointSets() for v in vertices: DS.make_set(v) total_cost = 0 while queue: v, u, weight = queue.pop() if DS.find(v) != DS.find(u): total_cost += weight DS.union(v, u) # Repare que não construimos a MST mas apenas # definimos os conjuntos disjuntos. # a quantidade de partições se refere a # quantidade de parents distintos temos no conjunto disjunto. qtd_partition = len(DS.get_disjoint_sets()) total_cost += penality(qtd_partition) return total_cost, qtd_partition
def test_inserting_item(self): DS = DisjointSets() for item in range(3, 50, 10): DS.make_set(item) self.assertEqual(len(DS), 5) self.assertEqual(len(DS), len(DS.get_disjoint_sets())) with self.assertRaises(ValueError): DS.make_set(13) ## check ignore_previous self.assertTrue(33 in DS) DS.make_set(33, ignore_previous=True) self.assertTrue(not 171 in DS) self.assertFalse(171 in DS)
def __call__(self): result = UGraph() done = DisjointSets() edges = [(u, v) for u, v in self.stpg.graph.gen_undirect_edges()] shuffle(edges) for v in self.stpg.terminals: done.make_set(v) while edges and len(done.get_disjoint_sets()) > 1: edge = edges.pop() y, z = edge[0], edge[1] if y not in done: done.make_set(y) if z not in done: done.make_set(z) if done.find(y) != done.find(z): result.add(y, z) done.union(y, z) return result
def __call__(self, treegraph: UGraph): GRAPH = self.stpg.graph disjointset = DisjointSets() result = UGraph() for v in treegraph.vertices: disjointset.make_set(v) # remove edge edges = [edge for edge in treegraph.gen_undirect_edges()] index = randint(0, len(edges)) for i, edge in enumerate(edges): if index != i: result.add_edge(*edge) disjointset.union(*edge) candidates = list() components = disjointset.get_disjoint_sets() lesser_idx = min(components, key=lambda key: len(components[key])) keys = components.keys() - set([lesser_idx]) # replace edge lesser_component = components[lesser_idx] for key in keys: other_component = components[key] for v in lesser_component: for w in GRAPH.adjacent_to(v): if w in other_component: candidates.append((v, w)) shuffle(candidates) while candidates: v, w = candidates.pop() if disjointset.find(v) != disjointset.find(w): result.add_edge(v, w) disjointset.union(v, w) break return result
def __call__(self, tree): GRAPH = self.STPG.graph total_cost = 0 qtd_partition = 0 DS = DisjointSets() for v in tree.vertices: DS.make_set(v) for v, u in tree.gen_undirect_edges(): if DS.find(v) == DS.find(u): ## trocar isso por um log print("FOI IDENTIFICADO UM CICLO EM UMA DAS SOLUÇÕES") DS.union(v, u) total_cost += GRAPH.weight(v, u) qtd_partition = len(DS.get_disjoint_sets()) if self.apply_penalization: total_cost += self.penality(qtd_partition) return total_cost, qtd_partition
def gen_random_kruskal(stpg: SteinerTreeProblem): terminals = set(stpg.terminals) edges = [(u, v) for u, v in stpg.graph.gen_undirect_edges()] shuffle(edges) done = DisjointSets() for v in terminals: done.make_set(v) result = EdgeSet() while edges and len(done.get_disjoint_sets()) > 1: edge = edges.pop() y, z = edge[0], edge[1] if y not in done: done.make_set(y) if z not in done: done.make_set(z) if done.find(y) != done.find(z): result.add(y, z) done.union(y, z) terminals.discard(y) terminals.discard(z) return result