class DagNode: def __init__(self, name, entity): self.name = name self.entity = entity #self.order = None self.level = 0 self._visitedby = list() def __repr__(self): return "<" + self.name + ">" # TODO: Gewichtung von Edges: Bspw. verweist ein Satellite zwar auf einen Hub - ist aber nicht zwingend auf dessen vorheriges Laden angewiesen. # Daher könnte man über einen Gewichtung der Edges von 0 - Loose bis 1 - strict das Level steuern # stage -> sat : strict # hub -> sat : loose # hub, sat -> pit : strict class Dag: def __init__(self, model): self.model = model self.nodes = dict() self.edges = list() def reset(self): for n in self.nodes.values(): n.level = 0 def add_node(self, node: DagNode): self.nodes[node.name] = node def add_edge(self, edge: tuple): self.edges.append(edge) def get_node(self, name): return self.nodes.get(name) def get_successors(self, nodename): return [self.nodes.get(e[1]) for e in self.edges if e[0] == nodename] def get_predecessor(self, nodename): return [self.nodes.get(e[0]) for e in self.edges if e[1] == nodename] def get_roots(self): return [n for n in self.nodes.values() if len(self.get_predecessor(n.name)) == 0] def get_forward_tree(self, node: DagNode, excludes=None, level=1, result = None): if result is None: result = [] if excludes is None: excludes = [] if node.name not in excludes: node.level = level if node not in result: result.append(node) for sn in self.get_successors(node.name): if sn.level <= level: sn.level = level + 1 result = self.get_forward_tree(sn, excludes, sn.level, result) return result def get_backward_tree(self, node: DagNode, excludes=None, level=0, result = None): if result is None: result = [] if excludes is None: excludes = [] if node.name not in excludes: node.level = level if node not in result: result.append(node) for sn in self.get_predecessor(node.name): if sn.level >= level: sn.level = level - 1 result = self.get_backward_tree(sn,excludes,sn.level, result) return result def num_level(self, nodes:list) -> int: return len(set([n.level for n in nodes])) def reverse_level(self, nodes:list) -> list: num_level = self.num_level(nodes) for n in nodes: n.level = num_level + n.level return nodes #def get_fastestPath(self): # returns fastest Path to each target. # Priority: fastest load of source to target.