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 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 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 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 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 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)
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
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
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 mif_main(self, g: MultiGraph, f: set, t) -> set: if f == g.nodes(): return f if not f: g_degree = g.degree() g_max_degree_node = max(g_degree, key=lambda n: n[1])[0] if g_degree[g_max_degree_node] <= 1: return set(g.nodes()) else: fx = f.copy() fx.add(g_max_degree_node) gx = g.copy() gx.remove_node(g_max_degree_node) mif_set1 = self.preprocess_1(g, fx, t) mif_set2 = self.preprocess_1(gx, f, t) if not mif_set1: return mif_set2 elif not mif_set2: return mif_set1 else: return max(mif_set1, mif_set2, key=len) # Set t as active vertex if t is None or t not in f: t = next(iter(f)) gd_over_3 = None gd_2 = None for v in g.neighbors(t): (gd_v, gn_v) = self.generalized_degree(g, f, t, v) if gd_v <= 1: f.add(v) return self.preprocess_1(g, f, t) elif gd_v >= 3: gd_over_3 = v else: gd_2 = (v, gn_v) if gd_over_3 is not None: # Cannot simply use "if gd_over_3" because v might be 0 fx = f.copy() fx.add(gd_over_3) gx = g.copy() gx.remove_node(gd_over_3) mif_set1 = self.preprocess_1(g, fx, t) mif_set2 = self.preprocess_1(gx, f, t) if not mif_set1: return mif_set2 elif not mif_set2: return mif_set1 else: return max(mif_set1, mif_set2, key=len) elif gd_2 is not None: (v, gn) = gd_2 fx1 = f.copy() fx2 = f.copy() fx1.add(v) for n in gn: fx2.add(n) gx = g.copy() gx.remove_node(v) try: find_cycle(gx.subgraph(fx2)) mif_set1 = None except: mif_set1 = self.preprocess_1(gx, fx2, t) mif_set2 = self.preprocess_1(g, fx1, t) if not mif_set1: return mif_set2 elif not mif_set2: return mif_set1 else: return max(mif_set1, mif_set2, key=len) return None
def mif_main(g: MultiGraph, f: set, t, k: int) -> set: k_set = k != None new_k1 = new_k2 = None if k_set and k > g.order(): return None if f == g.nodes() or (k_set and k <= 0): return f if (not f): g_degree = g.degree() g_max_degree_node = max(g_degree, key=lambda n: g_degree[n]) if (g_degree[g_max_degree_node] <= 1): return set(g.nodes()) else: fx = f.copy() fx.add(g_max_degree_node) gx = g.copy() gx.remove_node(g_max_degree_node) if k_set: new_k1 = k-1 new_k2 = k mif_set1 = mif_preprocess_1(g, fx, t, new_k1) mif_set2 = mif_preprocess_1(gx, f, t, new_k2) if not mif_set1: return mif_set2 elif not mif_set2: return mif_set1 else: return max(mif_set1, mif_set2, key=len) # Set t as active vertex if t == None or not t in f: t = next(iter(f)) gd_over_3 = None gd_2 = None for v in g.neighbors_iter(t): (gd_v, gn_v) = generalized_degree(g, f, t, v) if gd_v <= 1: f.add(v) if k_set: new_k1 = k-1 return mif_preprocess_1(g, f, t, new_k1) elif gd_v >= 3: gd_over_3 = v else: gd_2 = (v, gn_v) if gd_over_3 != None: # Cannot simply use "if gd_over_3" because v might be 0 fx = f.copy() fx.add(gd_over_3) gx = g.copy() gx.remove_node(gd_over_3) if k_set: new_k1 = k-1 new_k2 = k mif_set1 = mif_preprocess_1(g, fx, t, new_k1) mif_set2 = mif_preprocess_1(gx, f, t, new_k2) if not mif_set1: return mif_set2 elif not mif_set2: return mif_set1 else: return max(mif_set1, mif_set2, key=len) elif gd_2 != None: (v, gn) = gd_2 fx1 = f.copy() fx2 = f.copy() fx1.add(v) for n in gn: fx2.add(n) gx = g.copy() gx.remove_node(v) if k_set: new_k1 = k-2 new_k2 = k-1 try: cyc.find_cycle(gx.subgraph(fx2)) mif_set1 = None except: mif_set1 = mif_preprocess_1(gx, fx2, t, new_k1) mif_set2 = mif_preprocess_1(g, fx1, t, new_k2) if not mif_set1: return mif_set2 elif not mif_set2: return mif_set1 else: return max(mif_set1, mif_set2, key=len) return None