def get_fbvs_max_size(self, g: MultiGraph, k: int) -> set: if len(g) <= k + 2: return set(g.nodes()[:k]) # Construct a trivial FVS of size k + 1 on the first k + 3 vertices of G. nodes = g.nodes() # The set of nodes currently under consideration. node_set = set(nodes[:(k + 2)]) # The current best solution, of size (k + 1) before each compression step, # and size <= k at the end. soln = set(nodes[:k]) for i in range(k + 2, len(nodes)): soln.add(nodes[i]) node_set.add(nodes[i]) if len(soln) < k + 1: continue assert (len(soln) == (k + 1)) assert (len(node_set) == (i + 1)) new_soln = self.ic_compression(g.subgraph(node_set), soln, k) if new_soln is None: return None soln = new_soln assert (len(soln) <= k) return soln
def test_auto_neb(self): # Test AutoNEB procedure graph = MultiGraph() for idx, minimum in enumerate(self.minima): graph.add_node(idx + 1, **minimum) # Set up AutoNEB schedule spring_constant = float("inf") eval_config = EvalConfig(128) optim_config_1 = OptimConfig(10, SGD, {"lr": 0.1}, None, None, eval_config) optim_config_2 = OptimConfig(10, SGD, {"lr": 0.01}, None, None, eval_config) weight_decay = 0 subsample_pivot_count = 1 neb_configs = [ NEBConfig(spring_constant, weight_decay, equal, {"count": 2}, subsample_pivot_count, optim_config_1), NEBConfig(spring_constant, weight_decay, highest, {"count": 3, "key": "dense_train_loss"}, subsample_pivot_count, optim_config_1), NEBConfig(spring_constant, weight_decay, highest, {"count": 3, "key": "dense_train_loss"}, subsample_pivot_count, optim_config_2), NEBConfig(spring_constant, weight_decay, highest, {"count": 3, "key": "dense_train_loss"}, subsample_pivot_count, optim_config_2), ] auto_neb_config = AutoNEBConfig(neb_configs) self.assertEqual(auto_neb_config.cycle_count, len(neb_configs)) # Run AutoNEB auto_neb(1, 2, graph, self.model, auto_neb_config) self.assertEqual(len(graph.edges), auto_neb_config.cycle_count)
def auto_neb(m1, m2, graph: MultiGraph, model: models.ModelWrapper, config: config.AutoNEBConfig, callback: callable = None): # Continue existing cycles or start from scratch if m2 in graph[m1]: existing_edges = graph[m1][m2] previous_cycle_idx = max(existing_edges) connection_data = graph[m1][m2][previous_cycle_idx] start_cycle_idx = previous_cycle_idx + 1 else: connection_data = { "path_coords": torch.cat([graph.nodes[m]["coords"].view(1, -1) for m in (m1, m2)]), "target_distances": torch.ones(1) } start_cycle_idx = 1 assert start_cycle_idx <= config.cycle_count # Run NEB and add to graph for cycle_idx in helper.pbar( range(start_cycle_idx, config.cycle_count + 1), "AutoNEB"): cycle_config = config.neb_configs[cycle_idx - 1] connection_data = neb(connection_data, model, cycle_config) graph.add_edge(m1, m2, key=cycle_idx, **helper.move_to(connection_data, "cpu")) if callback is not None: callback()
def test_relabel_nodes_multigraph(): """failed after switching to dg.relabel_nodes""" G = MultiGraph([('a', 'b'), ('a', 'b')]) mapping = {'a': 'aardvark', 'b': 'bear'} G = relabel_nodes(G, mapping, copy=False) assert sorted(G.nodes()) == ['aardvark', 'bear'] assert_edges_equal(sorted(G.edges()), [('aardvark', 'bear'), ('aardvark', 'bear')])
def connect_routes(lab, lst, g: nx.MultiGraph): links = list(lst.linkid) if len(links) == 0: return for i in range(len(links)-1): conn = g.edges.get((links[i], links[i+1], 0)) if conn is None or conn['label'] != lab.iloc[0]: g.add_edge(links[i], links[i+1], label=lab.iloc[0])
def initGraph(self): self.shuttlingGraph = MultiGraph() for edge in self: self.shuttlingGraph.add_node(edge.startName) self.shuttlingGraph.add_node(edge.stopName) self.shuttlingGraph.add_edge(edge.startName, edge.stopName, key=hash(edge), edge=edge, weight=abs(edge.stopLine-edge.startLine)) self.nodeLookup[edge.startLine] = edge.startName self.nodeLookup[edge.stopLine] = edge.stopName
def __make_route_graph(routes): graph = MultiGraph() for route in routes: # assume each segment has weight 1 - we could estimate edge weight via # distance bewteen stops (we have location information), but we have # no information to tell us how fast any particular service is. make_route_segment = lambda src, dst: (src, dst, {'route': route}) segments = zip_with(make_route_segment, route.stops(), tail(route.stops())) graph.add_edges_from(segments) return graph
def reduction3(self, g: MultiGraph, k: int) -> (int, List[int], bool): """ If there is a vertex v of degree at most 1, delete v. """ changed = False for v in g.nodes(): if g.degree(v) <= 1: g.remove_node(v) changed = True return k, None, changed
def rem(g: nx.MultiGraph) -> None: node_attributes = nx.get_node_attributes(G, 'elderly') nodes = list(g.nodes) for node in nodes: neigh = list(g.neighbors(node)) if len(neigh) == 2 and (g.degree(node) % 2) == 0: try: set1 = { edge['label'] for edge in g.get_edge_data(node, neigh[0]).values() } except: print(g.get_edge_data(node, neigh[0])) set2 = { edge['label'] for edge in g.get_edge_data(node, neigh[1]).values() } if set1 == set2: #prec=node_attributes[neigh[0]]+0.001 succ = node_attributes[neigh[1]] + 0.001 node_attr = node_attributes[node] + 0.001 # if (abs((node_attr-prec))<1000) and (abs((node_attr-succ))<1000): if (abs((node_attr - succ)) < 1000): g.remove_node(node) for edge_label in set1: g.add_edge(neigh[0], neigh[1], label=edge_label)
def add_drugs_in_graph(graph: nwx.MultiGraph, drugs_list_graph: list): ''' Add graph node in a graph @parameter : graph @parameter : drugs_list_graph @return : drugs_list_graph ''' for item in drugs_list_graph: graph.add_node(item["drug"], atccode=item["atccode"]) return graph
def add_edge_journal_in_graph(graph: nwx.MultiGraph, journal_edge): for item in journal_edge: if item['edge_list']: for edge in item['edge_list']: graph.add_edge(edge[0], edge[1], journal=item['journal'], date=item['date']) return graph
def reduction1(self, g: MultiGraph, k: int) -> (int, List[int], bool): """ If there is a loop at a vertex v, delete v from the graph and decrease k by 1. """ changed = False vs = g.nodes_with_selfloops() for v in vs: g.remove_node(v) k -= 1 changed = True return k, vs, changed
def get_fbvs(graph): if is_acyclic(graph): return set() if type(graph) is not MultiGraph: graph = MultiGraph(graph) for i in range(1, graph.number_of_nodes()): result = get_fbvs_max_size(graph, i) if result is not None: return result # in the worst case, result is n-2 nodes
def test_diamond(): multigraph = MultiGraph() multigraph.add_nodes_from(range(4)) breakpoint_graph = BreakpointGraph(multigraph) first_color = ['A', 'C'] second_color = ['B', 'D'] topology = (first_color, second_color) breakpoint_graph.add_edge(0, 1, Multicolor(*[A])) breakpoint_graph.add_edge(2, 3, Multicolor(*[B])) breakpoint_graph.add_edge(1, 2, Multicolor(*[C])) breakpoint_graph.add_edge(0, 3, Multicolor(*[D])) assert (len(find_diamond_patterns(breakpoint_graph)) == 1)
def add_edge_pubmed_in_graph(graph: nwx.MultiGraph, pubmed_edge): for item in pubmed_edge: if item['edge_list']: for edge in item['edge_list']: graph.add_edge(edge[0], edge[1], id_pubmed=item['id_pubmed'], title_pubmed=item['title_pubmed'], date=item['date']) return graph
def test_paths(): multigraph = MultiGraph() multigraph.add_nodes_from(range(4)) breakpoint_graph = BreakpointGraph(multigraph) first_color = ['A', 'C'] second_color = ['B', 'D'] topology = (first_color, second_color) breakpoint_graph.add_edge(0, 1, Multicolor(*first_color)) breakpoint_graph.add_edge(2, 3, Multicolor(*first_color)) breakpoint_graph.add_edge(1, 2, Multicolor(*second_color)) breakpoint_graph.add_edge(0, 3, Multicolor(*second_color)) assert (get_size_of_alternating_structures(breakpoint_graph, topology) == 3)
def add_edge_clinical_in_graph(graph: nwx.MultiGraph, clinical_edge): for item in clinical_edge: if item['edge_list']: for edge in item['edge_list']: graph.add_edge(edge[0], edge[1], id_clinical=item['id_clinical'], title_clinical=item['title_clinical'], date=item['date']) return graph
def generate_snapshots_over_time(G: nx.MultiGraph, minutes=0, hours=0, days=0, max_snapshots=None, interval=None, include_final=False, cummulative=True): """ :param G: MultiGraph you want to watch over time, with "created_at" edge attribute :param minutes: Number of minutes between two snapshots (Default 0) :param hours: Number of hours between two snapshots (Default 0) :param days: Number of days between two snapshots (Default 0) :param max_snapshots: Maximum number of generated snapshots (Default None - all snapshots are created) :param interval: Tuple (start, end) specifying in which interval to generate snapshots (Default None - takes min, max created_at date of G) :param include_final: If True, set G as value for max_date (Default False) :return: A dict with timestamps """ if nx.get_edge_attributes(G, "created_at") == {}: raise Exception("Graph needs 'created_at' edge attribute") if minutes < 0 or hours < 0 or days < 0 or minutes + hours + days <= 0: raise Exception("Illegal minutes, hours or days values") edges = G.edges(data=True) created_ats = [attr["created_at"] for (_, _, attr) in edges] if interval is None: date = str_to_datetime(min(created_ats)) max_date = str_to_datetime(max(created_ats)) else: date = str_to_datetime(interval[0]) max_date = str_to_datetime(interval[1]) snapshots = {} while date <= max_date and (max_snapshots is None or len(snapshots) < max_snapshots): if cummulative: edges_snapshot = [(a, b) for (a, b, attr) in edges if str_to_datetime(attr["created_at"]) <= date] else: edges_snapshot = [ (a, b) for (a, b, attr) in edges if (date <= str_to_datetime(attr["created_at"]) <= date + timedelta(minutes=minutes, hours=hours, days=days)) ] nodes_snapshot = list(sum(edges_snapshot, ())) G_snapshot = G.subgraph(nodes_snapshot) snapshots[date] = reduce_multi_graph(G_snapshot) date += timedelta(minutes=minutes, hours=hours, days=days) if include_final: snapshots[max_date] = reduce_multi_graph(G) return snapshots
def __init__(self, nodes=None, edges=None): self.graph = MultiGraph() # Nodes nodes = nodes or {} for node_id, (lon, lat) in nodes.items(): self.add_node(node_id, lon, lat) # Edges edges = edges or {} for (n1, n2), (edge_type, dict_attrs) in edges.items(): self.add_edge(n1, n2, edge_type, **dict_attrs)
def generalized_degree(self, g: MultiGraph, f: set, active_node, node) -> (int, set): assert g.has_node(node), "Calculating gd for node which is not in g!" k = set(g.neighbors(node)) k.remove(active_node) k = k.intersection(f) gx = self.compress(g, k, node) neighbors = list(gx.neighbors(node)) neighbors.remove(active_node) return len(neighbors), neighbors
def generalized_degree(g: MultiGraph, f: set, active_node, node) -> (int, set): assert g.has_node(node), "Calculating gd for node which is not in g!" k = set(g.neighbors(node)) k.remove(active_node) k = k.intersection(f) gx = compress(g, k, node) neighbors = gx.neighbors(node) neighbors.remove(active_node) return (len(neighbors), neighbors)
def add_weak_gene(gene: EdgeGene, graph: nx.MultiGraph) -> bool: key = gene.A1 + gene.A2 edge = (gene.P1, gene.P2, key) if any(starmap( lambda p, a: p in graph and not any(x == a for x in get_node_space(graph, p)), [(gene.P1, gene.A1), (gene.P2, gene.A2)])): return False if graph.has_edge(gene.P1, gene.P2): keys = graph[gene.P1][gene.P2] if len(keys) > 1: return False graph.remove_edge(gene.P1, gene.P2, next(iter(keys))) graph.add_edge(*edge, gene=gene) return True
def _transact(graph: nx.MultiGraph, src: int, tgt: int, amount: int, new_node: int, info: dict): from more_itertools import pairwise path, weights, fees = find_route(graph, src, tgt, amount) # no path found if path is None: info['no_path'] += 1 return for (node, neighbour) in pairwise(path): channel_trans_amt = weights[neighbour] channel_policy = graph.get_policy(node, neighbour) # channel cannot handle transaction if channel_policy.balance < channel_trans_amt: info['channel_imbalance'] += 1 if node == new_node or neighbour == new_node: info['failure'][node, neighbour] += 1 raise Exception('Adversary channel imbalance') return # record successful transaction info['total_success'] += 1 total_amt = 0 # move amount between nodes in path for (node, neighbour) in pairwise(path): if neighbour is None: # remove total amount from src graph.nodes[path[0]]['data'].capacity -= total_amt # add amount to tgt graph.nodes[node]['data'].capacity += weights[node] break channel_trans_amt = weights[neighbour] channel_policy = graph.get_policy(node, neighbour) # pay channel fees to node graph.nodes[node]['data'].capacity += fees[node] total_amt += fees[node] # shift channel balance channel_policy.balance -= channel_trans_amt graph.get_policy(neighbour, node).balance += channel_trans_amt # record profit for adversary if node == new_node or neighbour == new_node: info['success'][node, neighbour] += 1 info['profit'][node, neighbour] += fees[node]
def main(): parser = ArgumentParser() parser.add_argument("project_directory", nargs=1) parser.add_argument("config_file", nargs=1) parser.add_argument("--no-backup", default=False, action="store_true") args = parser.parse_args() project_directory = args.project_directory[0] config_file = args.config_file[0] graph_path, project_config_path = setup_project(config_file, project_directory) model, minima_count, min_config, lex_config = read_config_file( project_config_path) # Setup Logger root_logger = getLogger() root_logger.setLevel(INFO) root_logger.addHandler(StreamHandler(sys.stdout)) root_logger.addHandler( FileHandler(join(project_directory, "exploration.log"))) # === Create/load graph === if isfile(graph_path): if not args.no_backup: root_logger.info("Copying current 'graph.p' to backup file.") copyfile( graph_path, graph_path.replace(".p", f"_bak{strftime('%Y%m%d-%H%M')}.p")) else: root_logger.info( "Not creating a backup of 'graph.p' because of user request.") graph = repair_graph(load_pickle_graph(graph_path), model) else: graph = MultiGraph() # Call this after every optmisiation def save_callback(): store_pickle_graph(graph, graph_path) # === Ensure the specified number of minima === for _ in pbar(range(len(graph.nodes), minima_count), "Finding minima"): minimum_data = find_minimum(model, min_config) graph.add_node( max(graph.nodes) + 1 if len(graph.nodes) > 0 else 1, **move_to(minimum_data, "cpu")) save_callback() # === Connect minima === landscape_exploration(graph, model, lex_config, callback=save_callback)
def subgraph_by_timestamp(mg: nx.MultiGraph, start: int, end: int) -> nx.Graph: edges = filter( lambda edge: start <= edge[2]["timestamp"] and edge[2]["timestamp"] < end, mg.edges(data=True), ) g = nx.Graph() for node in mg.nodes(): g.add_node(node) for u, v, data in edges: if g.has_edge(u, v): g[u][v]["weight"] += data["weight"] else: g.add_edge(u, v, weight=data["weight"]) return g
def get_graph_extents( networkX_multigraph: nx.MultiGraph ) -> Tuple[float, float, float, float]: """ Parameters ---------- networkX_multigraph A `NetworkX` `MultiGraph` with `x` and `y` node parameters. Returns ------- Tuple A tuple of `min_x`, `min_y`, `max_x`, `max_y` values. """ # get min and maxes for x and y min_x = np.inf max_x = -np.inf min_y = np.inf max_y = -np.inf for n, d in networkX_multigraph.nodes(data=True): if d['x'] < min_x: min_x = d['x'] if d['x'] > max_x: max_x = d['x'] if d['y'] < min_y: min_y = d['y'] if d['y'] > max_y: max_y = d['y'] return min_x, min_y, max_x, max_y
def _get_fbvs_max_size(self, g: MultiGraph, k: int) -> set: # Exhaustively apply reductions k, x0 = self.apply_reductions(g, k) # Originally reduction 5: if k < 0, terminate the algorithm and conclude that # (G, k) is a no-instance. if k < 0: return None # If G is an empty graph, then we return soln_redux if len(g) == 0: return x0 # Pick a random edge, then a random end node of that edge rand_edge = choice(g.edges()) v = choice(rand_edge) # We recurse on (G - v, k − 1). xn = self._get_fbvs_max_size(graph_minus(g, {v}), k - 1) if xn is None: # If the recursive step returns a failure, then we return a failure as well. return None else: # If the recursive step returns a feedback vertex set Xn, then we return X = Xn ∪ {v} ∪ X0. return xn.union({v}).union(x0)
def setUp(self): # Create digraph with negative resource costs with unreachable node 'E' self.G = DiGraph(directed=True, n_res=2) self.G.add_edge('Source', 'A', res_cost=array([1, 2]), weight=0) self.G.add_edge('A', 'C', res_cost=array([-1, 0.3]), weight=0) self.G.add_edge('A', 'B', res_cost=array([-1, 3]), weight=0) self.G.add_edge('B', 'D', res_cost=array([-1, 2]), weight=0) # Unreachable node E self.G.add_edge('B', 'E', res_cost=array([10, 1]), weight=0) self.G.add_edge('C', 'D', res_cost=array([1, 0.1]), weight=0) self.G.add_edge('D', 'Sink', res_cost=array([1, 0.1]), weight=0) # Create digraph with a resource infeasible minimum cost path self.H = MultiGraph(directed=True) self.H.add_edge('Source', 'A', res_cost=array([1, 1]), weight=-1) self.H.add_edge('A', 'B', res_cost=array([1, 1]), weight=-1) self.H.add_edge('B', 'Sink', res_cost=array([1, 1]), weight=-1) self.H.add_edge('Sink', 'Source', weight=-1) self.max_res, self.min_res = ["foo"], ["bar"] # Create digraph to test issue 72 self.F = DiGraph(n_res=1) self.F.add_edge('Source', 'A', res_cost=array([1]), weight=1) self.F.add_edge('A', 'B', res_cost=array([10]), weight=1) self.F.add_edge('A', 'Sink', res_cost=array([1]), weight=1)
def compress(g: MultiGraph, t: set, compressed_node, mutate=False) -> MultiGraph: if not t: return g if mutate: gx = g else: gx = g.copy() tx = t if compressed_node in tx: tx = t.copy() tx.remove(compressed_node) gx.add_node(compressed_node) for node in tx: for edge in gx.edges(node): if edge[0] == node: node_2 = edge[1] else: node_2 = edge[0] if not (node_2 in t or node_2 == compressed_node): gx.add_edge(compressed_node, node_2) gx.remove_node(node) remove = set() for node in gx.adj[compressed_node]: if len(gx.adj[compressed_node][node]) >= 2: # Using a set to remove to avoid messing up iteration of adj remove.add(node) for node in remove: gx.remove_node(node) return gx
def test_run_walks(): mg = MultiGraph() mg.add_edge('a', 'b') mg.add_edge('b', 'c') dw = DeepWalk(mg, 10, 100) dw.get_walks(workers=1) # Number of neighbors for all nodes together is 4, times niter: 400 assert len(dw.walks) == 400, len(dw.walks) assert len([w for w in dw.walks if w[0] == 'a']) == 100 assert len([w for w in dw.walks if w[0] == 'b']) == 200 dw.get_walks(workers=2) # Number of neighbors for all nodes together is 4, times niter: 400 assert len(dw.walks) == 400, len(dw.walks) assert len([w for w in dw.walks if w[0] == 'a']) == 100 assert len([w for w in dw.walks if w[0] == 'b']) == 200
def multiple_edges(self, new): """ Get/set whether or not self allows multiple edges. INPUT: new: boolean or None DOCTEST: sage: G = sage.graphs.base.graph_backends.NetworkXGraphBackend() sage: G.multiple_edges(True) sage: G.multiple_edges(None) True """ try: assert(not isinstance(self._nxg, (NetworkXGraphDeprecated, NetworkXDiGraphDeprecated))) except AssertionError: self._nxg = self._nxg.mutate() from networkx import Graph,MultiGraph,DiGraph,MultiDiGraph if new is None: return self._nxg.is_multigraph() if new == self._nxg.is_multigraph(): return if new: if self._nxg.is_directed(): self._nxg = MultiDiGraph(self._nxg) else: self._nxg = MultiGraph(self._nxg) else: if self._nxg.is_directed(): self._nxg = DiGraph(self._nxg) else: self._nxg = Graph(self._nxg)
def compress(self, g: MultiGraph, t: set, compressed_node, mutate=False) -> MultiGraph: if not t: return g if mutate: gx = g else: gx = g.copy() tx = t if compressed_node in tx: tx = t.copy() tx.remove(compressed_node) gx.add_node(compressed_node) for node in tx: for edge in gx.edges(node): if edge[0] == node: node_2 = edge[1] else: node_2 = edge[0] if not (node_2 in t or node_2 == compressed_node): gx.add_edge(compressed_node, node_2) gx.remove_node(node) remove = set() for node in gx.adj[compressed_node]: if len(gx.adj[compressed_node][node]) >= 2: # Using a set to remove to avoid messing up iteration of adj remove.add(node) for node in remove: gx.remove_node(node) return gx
def __init__(self, symbols=None, positions=None, numbers=None, tags=None, momenta=None, masses=None, magmoms=None, charges=None, scaled_positions=None, cell=None, pbc=None, celldisp=None, constraint=None, calculator=None, info=None, edges=None): super().__init__(symbols, positions, numbers, tags, momenta, masses, magmoms, charges, scaled_positions, cell, pbc, celldisp, constraint, calculator, info) if self.pbc.any(): self._graph = MultiGraph() else: self._graph = Graph() nodes = [[i, { 'number': n }] for i, n in enumerate(self.arrays['numbers'])] self._graph.add_nodes_from(nodes) if edges: self._graph.add_edges_from(edges, bonds=1) self._surface_atoms = None
def simplify(streckennetz: nx.MultiGraph) -> nx.MultiGraph: print('simplifying...') # Remove the shorter edge of two parallel edges edges_to_remove = [] for edges_index in streckennetz.edges(): edges = streckennetz[edges_index[0]][edges_index[1]] if len(edges) > 1: min_length = edges[0]['length'] min_length_index = 0 for i in edges: if edges[i]['length'] < min_length: min_length = edges[i]['length'] min_length_index = i edges_to_remove.append(list(edges_index) + [min_length_index]) print('found', len(edges_to_remove), 'parallel edges') streckennetz.remove_edges_from(edges_to_remove) # Remove nodes, that only have a single edge while True: nodes_to_remove = [] for node in streckennetz.nodes(): if streckennetz.degree( node) < 2 and 'type' not in streckennetz.nodes[node]: nodes_to_remove.append(node) if nodes_to_remove: print('found', len(nodes_to_remove), 'deadend nodes') streckennetz.remove_nodes_from(nodes_to_remove) nodes_to_remove = [] else: break return streckennetz
def reward(g: nx.MultiGraph, edge: Tuple[int, int], const_amt: int, fee_type: str, fee: int = None) -> int: # debugging # print_flag = fee is not None u, v = edge if fee is not None: g.update_fee(u, v, fee, fee_type) else: fee = getattr(g.get_policy(u, v), fee_type) ebc = edge_betweenness(g, const_amt)[edge] # debugging # if print_flag: # print('({:>3d}, {:>3d}) fee {:>9d} ebc {:>9f} '.format( # u, v, fee, ebc), end='') return fee * ebc
def get_fbvs_max_size(self, g: MultiGraph, k: int) -> set: # we will run the algorithm 4^k times n = 4 ** k for _ in range (1, n): # pass a copy of g, since we need a fresh copy of g for every run sol = self._get_fbvs_max_size(g.copy(), k) if sol is not None: # we found a fbvs for (g,k), so we can return it right away return sol return None
def graph_minus(g: MultiGraph, w: set) -> MultiGraph: gx = MultiGraph() for (n1, n2) in g.edges(): if n1 not in w and n2 not in w: gx.add_edge(n1, n2) for n in g.nodes(): if n not in w: gx.add_node(n) return gx
def fvs_disjoint(self, g: MultiGraph, w: set, k: int) -> set: """ Given an undirected graph G and a fbvs W in G of size at least (k + 1), is it possible to construct a fbvs X of size at most k using only the nodes of G - W? :return: The set X, or `None` if it's not possible to construct X """ # If G[W] isn't a forest, then a solution X not using W can't remove W's cycles. if not is_acyclic(g.subgraph(w)): return None # Apply reductions exhaustively. k, soln_redux = self.apply_reductions(g, w, k) # If k becomes negative, it indicates that the reductions included # more than k nodes. In other word, reduction 2 shows that there are more than k nodes # in G - W that will create cycle in W. Hence, no solution of size <= k exists. if k < 0: return None # From now onwards we assume that k >= 0 # If G has been reduced to nothing and k is >= 0 then the solution generated by the reductions # is already optimal. if len(g) == 0: return soln_redux # Recall that H is a forest as W is a feedback vertex set. Thus H has a node x of degree at most 1. # Find an x in H of degree at most 1. h = graph_minus(g, w) x = None for v in h.nodes(): if h.degree(v) <= 1: x = v break assert x is not None, "There must be at least one node x of degree at most 1" # Branch on (G - {x}, W, k−1) and (G, W ∪ {x}, k) # G is copied in the left branch (as it is modified), but passed directly in the right. soln_left = self.fvs_disjoint(graph_minus(g, {x}), w, k - 1) if soln_left is not None: return soln_redux.union(soln_left).union({x}) soln_right = self.fvs_disjoint(g, w.union({x}), k) if soln_right is not None: return soln_redux.union(soln_right) return None
def reduction1(g: MultiGraph, w: set, h: MultiGraph, k: int) -> (int, int, bool): changed = False for v in g.nodes(): if g.degree(v) <= 1: g.remove_node(v) h.remove_nodes_from([v]) changed = True return (k, None, changed)
def reduction2(g: MultiGraph, w: set, h: MultiGraph, k: int) -> (int, int, bool): for v in h.nodes(): # Check if G[W ∪ {v}] contains a cycle. if not is_forest(g.subgraph(w.union({v}))): g.remove_node(v) h.remove_nodes_from([v]) return (k - 1, v, True) return (k, None, False)
def mif_preprocess_2(g: MultiGraph, f: set, active_v, k: int) -> set: mif_set = set() while not is_independent_set(g, f): mif_set = mif_set.union(f) for component in nxc.connected_components(g.subgraph(f)): if len(component) > 1: if active_v in component: active_v = component.pop() compressed_node = active_v else: compressed_node = component.pop() g = compress(g, component, compressed_node, True) f = f.intersection(g.nodes()) # Maybe faster with # f = f.difference(component) # f.add(compressed_node) mif_set = mif_set.union(component) break mif_set2 = mif_main(g, f, active_v, k) if mif_set2: mif_set = mif_set2.union(mif_set) if k == None or len(mif_set) >= k: return mif_set return None
def reduction1(self, g: MultiGraph, w: set, h: MultiGraph, k: int) -> (int, int, bool): """ Delete all nodes of degree 0 or 1 as they can't be part of any cycles. """ changed = False for v in g.nodes(): if g.degree(v) <= 1: g.remove_node(v) h.remove_nodes_from([v]) changed = True return k, None, changed
def mif_preprocess_1(g: MultiGraph, f: set, active_v, k: int) -> set: if nxc.number_connected_components(g) >= 2: mif_set = set() for component in nxc.connected_components(g): f_i = component.intersection(f) gx = g.subgraph(component) component_mif_set = mif_preprocess_2(gx, f_i, active_v, None) if component_mif_set: mif_set = mif_set.union(component_mif_set) if k != None: k -= (len(component_mif_set) - len(f_i)) if k <= 0: return mif_set if k == None or len(mif_set) >= k: return mif_set return None return mif_preprocess_2(g, f, active_v, k)
def fvs_disjoint(g: MultiGraph, w: set, k: int) -> set: # Check that G[W] is a forest. # If it isn't, then a solution X not using W can't remove W's cycles. if not is_forest(g.subgraph(w)): return None # Apply reductions exhaustively. k, soln_redux = apply_reductions(g, w, k) # If k becomes negative, it indicates that the reductions included # more than k vertices, hence no solution of size <= k exists. if k < 0: return None # If G has been reduced to nothing and k is >= 0 then the solution generated by the reductions # is already optimal. if len(g) == 0: return soln_redux # Find an x in H of degree at most 1. h = graph_minus(g, w) x = None for v in h.nodes(): if h.degree(v) <= 1: x = v break assert x is not None # Branch. # G is copied in the left branch (as it is modified), but passed directly in the right. soln_left = fvs_disjoint(graph_minus(g, {x}), w, k - 1) if soln_left is not None: return soln_redux.union(soln_left).union({x}) soln_right = fvs_disjoint(g, w.union({x}), k) if soln_right is not None: return soln_redux.union(soln_right) return None
def reduction2(self, g: MultiGraph, w: set, h: MultiGraph, k: int) -> (int, int, bool): """ If there exists a node v in H such that G[W ∪ {v}] contains a cycle, then include v in the solution, delete v and decrease the parameter by 1. That is, the new instance is (G - {v}, W, k - 1). If v introduces a cycle, it must be part of X as none of the vertices in W will be available to neutralise this cycle. """ for v in h.nodes(): # Check if G[W ∪ {v}] contains a cycle. if not is_acyclic(g.subgraph(w.union({v}))): g.remove_node(v) h.remove_nodes_from([v]) return k - 1, v, True return k, None, False
def test_bag(): multigraph1 = MultiGraph() multigraph1.add_nodes_from(range(4)) breakpoint_graph1 = BreakpointGraph(multigraph1) double_color = ['A', 'B'] breakpoint_graph1.add_edge(0, 1, Multicolor(*double_color)) breakpoint_graph1.add_edge(2, 3, Multicolor('A')) breakpoint_graph1.add_edge(1, 2, Multicolor('C')) breakpoint_graph1.add_edge(0, 3, Multicolor('D')) assert (len(find_bag_patterns(breakpoint_graph1)) == 1) multigraph2 = MultiGraph() multigraph2.add_nodes_from(range(4)) breakpoint_graph2 = BreakpointGraph(multigraph2) double_color = ['A', 'B'] breakpoint_graph2.add_edge(0, 1, Multicolor(*double_color)) breakpoint_graph2.add_edge(2, 3, Multicolor('B')) breakpoint_graph2.add_edge(1, 2, Multicolor('C')) breakpoint_graph2.add_edge(0, 3, Multicolor('C')) assert (len(find_bag_patterns(breakpoint_graph2)) == 0)
def reduction4(self, g: MultiGraph, k: int) -> (int, List[int], bool): """ If there is a vertex v of degree 2, delete v and connect its two neighbors by a new edge. """ for v in g.nodes(): if g.degree(v) == 2: # Delete v and make its neighbors adjacent. ne = g.neighbors(v) # We must check whether v has 2 neighbors, or just one but connected to v by multiple edges if len(ne) == 2: [n1, n2] = ne else: [n1] = ne n2 = n1 g.remove_node(v) # Only add the edge if there are currently less than 2 edges between these two nodes es = g[n1].get(n2, {}) if len(es) < 2: g.add_edge(n1, n2) return k, None, True return k, None, False
def graph_minus_slow(g: MultiGraph, w: set) -> MultiGraph: gx = g.copy() gx.remove_nodes_from(w) return gx
class ShuttlingGraph(list): def __init__(self, shuttlingEdges=list() ): super(ShuttlingGraph, self).__init__(shuttlingEdges) self.currentPosition = None self.currentPositionName = None self.nodeLookup = dict() self.currentPositionObservable = Observable() self.graphChangedObservable = Observable() self.initGraph() self._hasChanged = True def initGraph(self): self.shuttlingGraph = MultiGraph() for edge in self: self.shuttlingGraph.add_node(edge.startName) self.shuttlingGraph.add_node(edge.stopName) self.shuttlingGraph.add_edge(edge.startName, edge.stopName, key=hash(edge), edge=edge, weight=abs(edge.stopLine-edge.startLine)) self.nodeLookup[edge.startLine] = edge.startName self.nodeLookup[edge.stopLine] = edge.stopName def rgenerateNodeLookup(self): self.nodeLookup.clear() for edge in self: self.nodeLookup[edge.startLine] = edge.startName self.nodeLookup[edge.stopLine] = edge.stopName @property def hasChanged(self): return self._hasChanged @hasChanged.setter def hasChanged(self, value): self._hasChanged = value def position(self, line): return self.nodeLookup.get(line) def setPosition(self, line): if self.currentPosition!=line: self.currentPosition = line self.currentPositionName = self.position(line) self.currentPositionObservable.fire( line=line, text=firstNotNone(self.currentPositionName, "") ) def getMatchingPosition(self,graph): """Try to match node name/position to the current settings in the provided ShuttlingGraph.""" if not graph: return self.currentPosition # no change # Matching node name. Need to set the corresponding position for edge in self: if edge.startName == graph.currentPositionName: return edge.startLine if edge.stopName == graph.currentPositionName: return edge.stopLine #if graph.currentPosition: # return graph.currentPosition #just use the graph's position return self.currentPosition def addEdge(self, edge): self._hasChanged = True self.append(edge) self.shuttlingGraph.add_edge(edge.startName, edge.stopName, key=hash(edge), edge=edge, weight=abs(edge.stopLine-edge.startLine)) self.nodeLookup[edge.startLine] = edge.startName self.nodeLookup[edge.stopLine] = edge.stopName self.graphChangedObservable.firebare() self.setPosition(self.currentPosition) def isValidEdge(self, edge): return ((edge.startLine not in self.nodeLookup or self.nodeLookup[edge.startLine] == edge.startName) and (edge.stopLine not in self.nodeLookup or self.nodeLookup[edge.stopLine] == edge.stopName)) def getValidEdge(self): index = 0 while self.shuttlingGraph.has_node("Start_{0}".format(index)): index += 1 startName = "Start_{0}".format(index) index = 0 while self.shuttlingGraph.has_node("Stop_{0}".format(index)): index += 1 stopName = "Stop_{0}".format(index) index = 0 startLine = (max( self.nodeLookup.keys() )+1) if self.nodeLookup else 1 stopLine = startLine + 1 return ShuttleEdge(startName, stopName, startLine, stopLine, 0, 0, 0, 0) def removeEdge(self, edgeno): self._hasChanged = True edge = self.pop(edgeno) self.shuttlingGraph.remove_edge(edge.startName, edge.stopName, hash(edge)) if self.shuttlingGraph.degree(edge.startName) == 0: self.shuttlingGraph.remove_node(edge.startName) if self.shuttlingGraph.degree(edge.stopName) == 0: self.shuttlingGraph.remove_node(edge.stopName) self.graphChangedObservable.firebare() self.rgenerateNodeLookup() self.setPosition(self.currentPosition) def setStartName(self, edgeno, startName): self._hasChanged = True startName = str(startName) edge = self[edgeno] if edge.startName != startName: self.shuttlingGraph.remove_edge(edge.startName, edge.stopName, key=hash(edge)) if self.shuttlingGraph.degree(edge.startName) == 0: self.shuttlingGraph.remove_node(edge.startName) edge.startName = startName self.shuttlingGraph.add_edge(edge.startName, edge.stopName, key=hash(edge), edge=edge, weight=abs(edge.stopLine-edge.startLine) ) self.graphChangedObservable.firebare() self.setPosition(self.currentPosition) self.rgenerateNodeLookup() return True def setStopName(self, edgeno, stopName): self._hasChanged = True stopName = str(stopName) edge = self[edgeno] if edge.stopName != stopName: self.shuttlingGraph.remove_edge(edge.startName, edge.stopName, key=hash(edge)) if self.shuttlingGraph.degree(edge.stopName) == 0: self.shuttlingGraph.remove_node(edge.stopName) edge.stopName = stopName self.shuttlingGraph.add_edge(edge.startName, edge.stopName, key=hash(edge), edge=edge, weight=abs(edge.stopLine-edge.startLine) ) self.graphChangedObservable.firebare() self.rgenerateNodeLookup() self.setPosition(self.currentPosition) return True def setStartLine(self, edgeno, startLine): self._hasChanged = True edge = self[edgeno] if startLine != edge.startLine and (startLine not in self.nodeLookup or self.nodeLookup[startLine] == edge.startName): self.nodeLookup.pop(edge.startLine) edge.startLine = startLine self.shuttlingGraph.edge[edge.startName][edge.stopName][hash(edge)]['weight'] = abs(edge.stopLine-edge.startLine) self.rgenerateNodeLookup() self.graphChangedObservable.firebare() self.setPosition(self.currentPosition) return True return False def setStopLine(self, edgeno, stopLine): self._hasChanged = True edge = self[edgeno] if stopLine != edge.stopLine and (stopLine not in self.nodeLookup or self.nodeLookup[stopLine] == edge.stopName): self.nodeLookup.pop(edge.stopLine) edge.stopLine = stopLine self.shuttlingGraph.edge[edge.startName][edge.stopName][hash(edge)]['weight'] = abs(edge.stopLine-edge.startLine) self.rgenerateNodeLookup() self.graphChangedObservable.firebare() self.setPosition(self.currentPosition) return True return False def setIdleCount(self, edgeno, idleCount): self._hasChanged = True self[edgeno].idleCount = idleCount return True def setSteps(self, edgeno, steps): self._hasChanged = True self[edgeno].steps = steps return True def shuttlePath(self, fromName, toName ): fromName = firstNotNone(fromName, self.currentPositionName) fromName = fromName if fromName else self.position(float(self.currentPosition)) if fromName not in self.shuttlingGraph: raise ShuttlingGraphException("Shuttling failed, origin '{0}' is not a valid shuttling node".format(fromName)) if toName not in self.shuttlingGraph: raise ShuttlingGraphException("Shuttling failed, target '{0}' is not a valid shuttling node".format(toName)) sp = shortest_path(self.shuttlingGraph, fromName, toName) path = list() for a, b in pairs_iter(sp): edge = sorted(self.shuttlingGraph.edge[a][b].values(), key=itemgetter('weight'))[0]['edge'] path.append((a, b, edge, self.index(edge))) return path def nodes(self): return self.shuttlingGraph.nodes() def toXmlElement(self, root): mydict = dict( ( (key, str(getattr(self, key))) for key in ('currentPosition', 'currentPositionName') if getattr(self, key) is not None ) ) myElement = ElementTree.SubElement(root, "ShuttlingGraph", attrib=mydict ) for edge in self: edge.toXmlElement( myElement ) return myElement def setStartType(self, edgeno, Type): self._hasChanged = True self[edgeno].startType = str(Type) return True def setStopType(self, edgeno, Type): self._hasChanged = True self[edgeno].stopType = str(Type) return True def setStartLength(self, edgeno, length): edge = self[edgeno] if length!=edge.startLength: if length+edge.stopLength<edge.sampleCount: self._hasChanged = True edge.startLength = int(length) else: return False return True def setStopLength(self, edgeno, length): edge = self[edgeno] if length!=edge.stopLength: if edge.startLength+length<edge.sampleCount: self._hasChanged = True edge.stopLength = int(length) else: return False return True @staticmethod def fromXmlElement( element ): edgeElementList = element.findall("ShuttleEdge") edgeList = [ ShuttleEdge.fromXmlElement(e) for e in edgeElementList ] return ShuttlingGraph(edgeList)
def fvs_via_mif(g: MultiGraph, k: int) -> set: mif_set = mif(g, g.order()-k) if mif_set: nodes = set(g.nodes()) mif_set = nodes.difference(mif_set) return mif_set
for n in N: f.write(str(round(my_data[n][0])) + " ") f.write(str(round(my_data[n][1])) + " ") f.write(str(round(my_data[n][2]))) f.write("\n") f.close() fh = open("trash","w") call(["./blossom4","-3", "-x","data.dat", "-w", "output.dat"], stdout=fh) fh.close() result = genfromtxt('output.dat', delimiter=' ', usecols = (0, 1)) result = result[1:] #MINMAXMATCHING END H = MultiGraph() H.add_nodes_from(T.nodes()) H.add_edges_from(T.edges()) for (key, value) in a.items(): if N < N: H.add_edge(N, N) t = Set() for (i, j) in eulerian_circuit(H): if i in t: continue t.add(i) print i #the result is t #t_e = zip(t[:-1], t[1:])
def is_independent_set(g: MultiGraph, f: set) -> bool: for edge in itertools.combinations(f, 2): if g.has_edge(edge[0], edge[1]): return False return True
def reduction3(self, g: MultiGraph, w: set, h: MultiGraph, k: int) -> (int, int, bool): """ If there is a node v ∈ V(H) of degree 2 in G such that at least one neighbor of v in G is from V (H), then delete this node and make its neighbors adjacent (even if they were adjacent before; the graph could become a multigraph now). """ for v in h.nodes(): if g.degree(v) == 2: # If v has a neighbour in H, short-curcuit it. if len(h[v]) >= 1: # Delete v and make its neighbors adjacent. [n1, n2] = g.neighbors(v) g.remove_node(v) g.add_edge(n1, n2) # Update H accordingly. h.remove_nodes_from([v]) if n1 not in w and n2 not in w: h.add_edge(n1, n2) return k, None, True return k, None, False
basename = splitext(basename(sys.argv[1]))[0] random.seed(1) print "Reading {}, writing {}".format(sys.argv[1], outname) graph = read_gml(sys.argv[1]) hsubspec = "flowsize=exponential(1/10000.0) flowstart=exponential(100) ipproto=randomchoice(6) sport=randomchoice(22,80,443) dport=randomunifint(1025,65535) lossrate=randomchoice(0.001)" mnodes = add_measurement(graph) newgraph = MultiGraph(name=basename, counterexportfile=basename+"_counters", flowexport="text", flowsampling=1.0, pktsampling=1.0, exportcycle=60, counterexport=True, counterexportinterval=1, longflowtmo=60, flowinactivetmo=60, harpoonsubspec=hsubspec, measurementnodes=mnodes) def get_cap(label): if 'OC192/STM64' in label: return '10Gb' elif 'OC3' in label: return '155Mb' elif 'OC12' in label: return '622Mb' elif 'OC48' in label: return '2.4Gb'
for n in N: f.write(str(round(my_data[n][0])) + " ") f.write(str(round(my_data[n][1])) + " ") f.write(str(round(my_data[n][2]))) f.write("\n") f.close() fh = open("trash.dat","w") call(["./blossom4","-3", "-x","data.dat", "-w", "output.dat"], stdout=fh) fh.close() result = genfromtxt('output.dat', delimiter=' ', usecols = (0, 1)) result = result[1:] #MINMAXMATCHING END H = MultiGraph() H.add_nodes_from(T.nodes()) H.add_edges_from(T.edges()) for (key, value) in result: H.add_edge(N[int(key)], N[int(value)]) f = open("data.dat", "wb") t = Set() for (i, j) in eulerian_circuit(H): if i in t: continue t.add(i) f.write(str(i) + " ") f.close() fh = open("trash.dat", "w")
def reduction3(g: MultiGraph, w: set, h: MultiGraph, k: int) -> (int, int, bool): for v in h.nodes(): if g.degree(v) == 2: # If v has a neighbour in H, short-curcuit it. if len(h[v]) >= 1: # Delete v and make its neighbors adjacent. [n1, n2] = g.neighbors(v) g.remove_node(v) g.add_edge(n1, n2) # Update H accordingly. h.remove_nodes_from([v]) if n1 not in w and n2 not in w: h.add_edge(n1, n2) return (k, None, True) return (k, None, False)