103 lines
2.9 KiB
Python
103 lines
2.9 KiB
Python
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.
|
|
|