def __call__(self, treegraph: UGraph): GRAPH = self.stpg.graph vertices = set(treegraph.vertices) # Build the subgraph induced by the nodes in treegraph subgraph = UWGraph() for v in vertices: for u in GRAPH.adjacent_to(v): if u in vertices: weigth = GRAPH.weight(v, u) subgraph.add_edge(v, u, weight=weigth) # Compute the Prim MST for the subgraph mst = UGraph() queue = PriorityQueue() start = choice(tuple(vertices)) for next_node, weight in subgraph.edges[start].items(): queue.push(weight, (start, next_node)) while queue: node_start, node_end = queue.pop() if node_end not in mst: mst.add_edge(node_start, node_end) for next_node, weight in subgraph.edges[node_end].items(): queue.push(weight, (node_end, next_node)) return mst
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)}' stpg = self.stpg terminals = set(stpg.terminals) subgraph = UGraph() for edge in parent_a: u, v = edge subgraph.add_edge(u, v) for edge in parent_b: u, v = edge subgraph.add_edge(u, v) done = set() result = EdgeSet() v = terminals.pop() while terminals: done.add(v) adjacents = subgraph.adjacent_to(v, lazy=False) u = sample(adjacents, k=1)[0] if u not in done: result.add(v, u) terminals.discard(u) v = u return result
def test_is_steiner_tree(self): stpg = self.stpg chromosome = gen_random_kruskal(stpg) tree = UGraph() for edge in chromosome: v, u = edge tree.add_edge(v, u) _, response = is_steiner_tree(tree, stpg) self.assertTrue(response['all_terminals_in']) self.assertFalse(response['has_cycle']) self.assertTrue(response['all_edges_are_reliable']) self.assertTrue(response['graph_is_connected'])
def test_edge_non_exist_in_stpg_instance(self): filename = path.join("tests", "data", "test4.txt") stpg = ReaderORLibrary().parser(filename) tree = UGraph() edges = [(1, 3), (3, 8), (8, 5), (5, 6), (8, 9)] for edge in edges: v, u = edge tree.add_edge(v, u) evaluator = EvaluateTreeGraph(stpg) self.assertTrue(callable(evaluator)) with self.assertRaises(ValueError): cost, __ = evaluator(tree)
def __call__(self): GRAPH = self.stpg.graph terminals = self.stpg.terminals.copy() result = UGraph() v = terminals.pop() while terminals: adjacents = GRAPH.adjacent_to(v, lazy=False) u = sample(adjacents, k=1)[0] if u not in result: result.add_edge(v, u) terminals.discard(u) v = u return result
def test_example_solution_two_components(self): filename = path.join("tests", "data", "test4.txt") stpg = ReaderORLibrary().parser(filename) tree = UGraph() edges = [(1, 3), (3, 8), (8, 5), (5, 6), (2, 4)] for edge in edges: v, u = edge tree.add_edge(v, u) evaluator = EvaluateTreeGraph(stpg) self.assertTrue(callable(evaluator)) cost, nro_partition = evaluator(tree) self.assertEqual(nro_partition, 2) self.assertEqual(cost, (5 + 7 + 7 + 15 + 16))
def __call__(self, red: UGraph, blue: UGraph): child = UGraph() red_only = UGraph() blue_only = UGraph() for v, u in red.gen_undirect_edges(): if blue.has_edge(v, u): child.add_edge(v, u) else: red_only.add_edge(v, u) for v, u in blue.gen_undirect_edges(): if not red.has_edge(v, u): blue_only.add_edge(v, u) common_nodes_red = set(red_only.vertices) & set(blue.vertices) common_nodes_blue = set(blue_only.vertices) & set(red.vertices) red_partitions = self.find_partitions(red_only, common_nodes_red) blue_partitions = self.find_partitions(blue_only, common_nodes_blue) queue = PriorityQueue() for partition in red_partitions: queue.push(partition.cost, partition) for partition in blue_partitions: queue.push(partition.cost, partition) common_nodes = set(red.vertices) | set(blue.vertices) dset = DisjointSets() for v in common_nodes: dset.make_set(v) for v, u in child.gen_undirect_edges(): dset.union(v, u) while queue: partition = queue.pop() if check_portals(partition.portal, dset): # add edges for v, u in partition: child.add_edge(v, u) # update dset portals = iter(partition.portal) p_last = next(portals) for p in portals: dset.union(p_last, p) p_last = p return child
def test_if_is_it_a_tree(self): filename = path.join('datasets', 'ORLibrary', 'steinb15.txt') stpg = ReaderORLibrary().parser(filename) crossover = CrossoverKruskalRST(stpg) parent_a = gen_random_walk(stpg) parent_b = gen_random_walk(stpg) offspring = crossover(parent_a, parent_b) tree = UGraph() for edge in offspring: u, v = edge[0], edge[1] tree.add_edge(u, v) _, response = is_steiner_tree(tree, stpg) self.assertTrue(response['all_terminals_in']) self.assertFalse(response['has_cycle']) self.assertTrue(response['all_edges_are_reliable']) self.assertTrue(response['graph_is_connected'])
def test_penality_function(self): filename = path.join("tests", "data", "test4.txt") stpg = ReaderORLibrary().parser(filename) tree = UGraph() edges = [(1, 3), (3, 8), (8, 5), (5, 6), (2, 4)] for edge in edges: v, u = edge tree.add_edge(v, u) evaluator = EvaluateTreeGraph(stpg, penality_function=lambda nro: (nro - 1) * 100) self.assertTrue(callable(evaluator)) cost, nro_partition = evaluator(tree) self.assertEqual(nro_partition, 2) self.assertEqual(cost, (5 + 7 + 7 + 15 + 16 + 100))
def __call__(self, treegraph: UGraph): terminals = self.terminals result = UGraph() for v, u in treegraph.gen_undirect_edges(): result.add_edge(v, u) leaves = deque([ v for v in result.vertices if (v not in terminals) and (result.degree(v) == 1) ]) while leaves: v = leaves.pop() for w in result.adjacent_to(v): if (w not in terminals) and (result.degree(w) == 2): leaves.appendleft(w) result.remove_node(v) 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, red: UGraph, blue: UGraph): 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)}' 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) terminals = self.terminals.copy() done = set() result = UGraph() candidates_edges = set() vi = terminals.pop() done.add(vi) for u in union_g.adjacent_to(vi): candidates_edges.add((vi, u)) while candidates_edges and terminals: edge = sample(candidates_edges, k=1)[0] v, w = edge if w not in done: done.add(w) result.add_edge(v, w) terminals.discard(w) for u in union_g.adjacent_to(w): if u not in done: candidates_edges.add((w, u)) candidates_edges.discard((v, w)) return result
def __call__(self, red: UGraph, blue: UGraph): 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)}' terminals = self.terminals.copy() 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) done = set() result = UGraph() v = terminals.pop() while terminals: done.add(v) adjacents = union_g.adjacent_to(v, lazy=False) u = sample(adjacents, k=1)[0] if u not in done: result.add_edge(v, u) terminals.discard(u) v = u return result
def __call__(self, red: UGraph, blue: UGraph): f_weight = lambda v, u: self.stpg.graph.weight(v, u) 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) queue = PriorityQueue() start = choice(tuple(self.stpg.terminals)) for u in union_g.adjacent_to(start): queue.push(f_weight(start, u), (start, u)) result = UGraph() while queue: start, end = queue.pop() if end not in result: result.add_edge(start, end) for w in union_g.adjacent_to(end): queue.push(f_weight(end, w), (end, w)) return result
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, 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)}' stpg = self.stpg terminals = set(stpg.terminals) done = set() result = EdgeSet() subgraph = UGraph() for edge in parent_a: u, v = edge subgraph.add_edge(u, v) for edge in parent_b: u, v = edge subgraph.add_edge(u, v) vi = terminals.pop() done.add(vi) candidates_edges = set() for u in subgraph.adjacent_to(vi): candidates_edges.add((vi, u)) while candidates_edges and terminals: edge = sample(candidates_edges, k=1)[0] v, w = edge if w not in done: done.add(w) result.add(v, w) terminals.discard(w) for u in subgraph.adjacent_to(w): if u not in done: candidates_edges.add((w, u)) candidates_edges.discard((v, w)) return result
def test_exchange_edges(self): filename = path.join('tests', 'data', 'test3.txt') stpg = ReaderORLibrary().parser(filename) red = UGraph() edges = [(1, 3), (3, 8), (8, 5), (5, 6)] for edge in edges: red.add_edge(edge[0], edge[1]) blue = UGraph() edges = [(1, 3), (3, 8), (3, 7), (7, 4), (4, 6)] for edge in edges: blue.add_edge(edge[0], edge[1]) crossover = PXTree(stpg) child = crossover(red, blue) _, response = is_steiner_tree(child, stpg) self.assertTrue(response['all_terminals_in']) self.assertFalse(response['has_cycle']) self.assertTrue(response['all_edges_are_reliable']) self.assertTrue(response['graph_is_connected']) self.assertTrue(response['all_leaves_are_terminals'])
def test_simpliest(self): stpg = self.stpg mutate = MutationReplaceByRandomEdge(stpg) after = gen_random_prim(stpg) self.assertIsInstance(after, EdgeSet) before = mutate(after) self.assertIsInstance(before, EdgeSet) tree = UGraph() for edge in before: v, u = edge tree.add_edge(v, u) _, response = is_steiner_tree(tree, stpg) self.assertTrue(response['all_terminals_in']) self.assertFalse(response['has_cycle']) self.assertTrue(response['all_edges_are_reliable']) self.assertTrue(response['graph_is_connected'])
def __call__(self): result = UGraph() terminals = self.stpg.terminals.copy() GRAPH = self.stpg.graph edges = set() # or is it better a list? vi = sample(range(1, self.stpg.nro_nodes + 1), k=1)[0] terminals.discard(vi) for w in GRAPH.adjacent_to(vi): edges.add((vi, w)) while terminals and edges: edge = sample(edges, k=1)[0] # need to ensure randomness v, w = edge if w not in result: terminals.discard(w) result.add_edge(v, w) for u in GRAPH.adjacent_to(w): if u not in result: edges.add((w, u)) edges.remove(edge) # to remove from a list it can take O(n) return result
def __call__(self, red: UGraph, blue: UGraph): g_union = UGraph() for v, u in red.gen_undirect_edges(): g_union.add_edge(v, u) for v, u in blue.gen_undirect_edges(): g_union.add_edge(v, u) p_queue = PriorityQueue() vertices = list(g_union.vertices) v = choice(vertices) for u in g_union.adjacent_to(v): weight = self.f_weight(v, u) p_queue.push(weight, (v, u)) g_child = UGraph() done = set() done.add(v) while len(p_queue): v, u = p_queue.pop() if u not in done: g_child.add_edge(v, u) done.add(u) for w in g_union.adjacent_to(u): if w not in done: p_queue.push(self.f_weight(u, w), (u, w)) terminals = self.STPG.terminals prunne_leaves = deque([ v for v in g_child.vertices if ((g_child.degree(v) == 1) and (v not in terminals)) ]) while prunne_leaves: v = prunne_leaves.pop() prev = g_child.adjacent_to(v, lazy=False) g_child.remove_node(v) for w in prev: if g_child.degree(w) == 1 and w not in terminals: prunne_leaves.appendleft(w) return g_child
def __call__(self, red: UGraph, blue: UGraph): child = UGraph() red_only = UGraph() blue_only = UGraph() _vertices = set() for v, u in red.gen_undirect_edges(): if blue.has_edge(v, u): child.add_edge(v, u) _vertices.add(v) _vertices.add(u) else: red_only.add_edge(v, u) for v, u in blue.gen_undirect_edges(): if not red.has_edge(v, u): blue_only.add_edge(v, u) common_nodes_red = set(red_only.vertices) & set(blue.vertices) common_nodes_blue = set(blue_only.vertices) & set(red.vertices) red_partitions = self.find_partitions(red_only, common_nodes_red) blue_partitions = self.find_partitions(blue_only, common_nodes_blue) _vertices.update(common_nodes_red | common_nodes_blue) disjoint = DisjointSets() for v in _vertices: disjoint.make_set(v) for v, u in child.gen_undirect_edges(): disjoint.union(v, u) red_dict = _dict_matches_from(red_partitions, disjoint) blue_dict = _dict_matches_from(blue_partitions, disjoint) matches = red_dict.keys() & blue_dict.keys() while matches: child, red_dict, blue_dict, disjoint = select_partition_and_union( child, red_dict, blue_dict, disjoint, matches) red_dict = _dict_matches_from(red_dict.values(), disjoint) blue_dict = _dict_matches_from(blue_dict.values(), disjoint) matches = red_dict.keys() & blue_dict.keys() red_child = UGraph() blue_child = UGraph() for v, u in child.gen_undirect_edges(): red_child.add_edge(v, u) blue_child.add_edge(v, u) for partition in red_dict.values(): for v, u in partition: red_child.add_edge(v, u) for partition in blue_dict.values(): for v, u in partition: blue_child.add_edge(v, u) return red_child, blue_child