Find the best path from a end to a start node, producing a certain type of data given the set of currently available data and the current set of activated nodes.
We can always ask the algorithm to trace the part from end to start for this data type (this data is in endnode by construction). If we have to go along an edge where the data is not yet available then we need to add this data to our list of data to produce.
299 def _bestPath(self, data, dataAvailable, startNodeName = '_start', endNodeName = None):
301 if endNodeName
is None:
302 endNodeName =
'_end_{0}'.
format(data)
304 if endNodeName
not in self._nodeDict:
305 raise trfExceptions.TransformGraphException(trfExit.nameToCode(
'TRF_GRAPH_ERROR'),
306 'Node {0} was not found - the transform data connection definition is broken'.
format(endNodeName))
311 pathSet = [graphPath(endNodeName, data),]
313 msg.debug(
'Started path finding with seed path {0}'.
format(pathSet[0]))
316 while len(pathSet) > 1
or pathSet[0].path[0] != startNodeName:
317 msg.debug(
'Starting best path iteration with {0} paths in {1}'.
format(len(pathSet), pathSet))
319 for path
in pathSet[:]:
320 msg.debug(
'Continuing path finding with path {0}'.
format(path))
321 currentNodeName = path.path[0]
322 if currentNodeName == startNodeName:
323 msg.debug(
'Path {0} has reached the start node - finished'.
format(path))
326 if len(self._nodeDict[currentNodeName].connections[
'in']) == 0:
327 msg.debug(
'Path {0} is a dead end - removing'.
format(path))
331 if len(self._nodeDict[currentNodeName].connections[
'in']) == 1:
332 msg.debug(
'Single exit from path {0} - adding connection to {1}'.
format(path,
list(self._nodeDict[currentNodeName].connections[
'in'])[0]))
333 self._extendPath(path, currentNodeName,
list(self._nodeDict[currentNodeName].connections[
'in'])[0])
336 msg.debug(
'Multiple exits from path {0} - will clone for each extra exit'.
format([path]))
337 for nextNodeName
in list(self._nodeDict[currentNodeName].connections[
'in'])[1:]:
338 newPath = copy.deepcopy(path)
339 msg.debug(
'Cloned exit from path {0} to {1}'.
format(newPath, nextNodeName))
340 self._extendPath(newPath, currentNodeName, nextNodeName)
341 pathSet.append(newPath)
343 msg.debug(
'Adding exit from original path {0} to {1}'.
format(path,
list(self._nodeDict[currentNodeName].connections[
'in'])[0]))
344 self._extendPath(path, currentNodeName,
list(self._nodeDict[currentNodeName].connections[
'in'])[0])
347 lowestCostPath =
None
348 for path
in pathSet[:]:
349 currentNodeName = path.path[0]
350 if currentNodeName == startNodeName:
351 if lowestCostPath
is None:
352 lowestCostPath = path
354 if path.cost >= lowestCostPath.cost:
355 msg.debug(
'Path {0} is no cheaper than best path {1} - removing'.
format(path, lowestCostPath))
358 msg.debug(
'Path {0} is cheaper than previous best path {1} - removing previous'.
format(path, lowestCostPath))
359 pathSet.remove(lowestCostPath)
360 lowestCostPath = path
363 if len(pathSet) == 0:
364 raise trfExceptions.TransformGraphException(trfExit.nameToCode(
'TRF_GRAPH_ERROR'),
365 'No path found between {0} and {1} for {2}'.
format(startNodeName, endNodeName, data))