It is difficult to accurately rank paths in a network when you need to account for both the sequence of steps and how much those steps stretch out over time.
It analyzes paths through a network and applies a scoring system that penalizes longer routes based on their time-weighted transitions.
It allows for a more accurate ranking of paths by balancing flow patterns with time-based decay.
It was run in the sandbox and it failed. run output shows an error/traceback — the artifact does NOT run clean.
$ python3 path_decay.py
Traceback (most recent call last):
File "/work/temporal_path_decay.py", line 63, in <module>
scorer = TemporalPathScorer(graph, 'A', 'D')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/work/temporal_path_decay.py", line 12, in __init__
self.scores = self._calculate_scores()
^^^^^^^^^^^^^^^^^^^^^^^^
File "/work/temporal_path_decay.py", line 41, in _calculate_scores
path: self._temporal_decay(self._path_weight(path))
TypeError: unhashable type: 'list'No screenshot — there is nothing working to show. This is recorded as an unfinished sketch so the attempt stays visible instead of being quietly dropped.
All of it — 75 lines, one file, standard library only.
import math
from collections import defaultdict
class PathGraph:
def __init__(self, graph, source, target, decay_rate=0.5):
self.graph = graph
self.source = source
self.target = target
self.decay_rate = decay_rate
self.paths = self._find_all_paths()
self.scores = self._calculate_scores()
self.bottlenecks = self._calculate_bottlenecks()
def _find_all_paths(self, path=[]):
if path == [] or path[-1] == self.source:
path = [self.source]
if path[-1] == self.target:
return [path]
all_paths = []
if path[-1] in self.graph:
for neighbor, weight in self.graph[path[-1]]:
if neighbor not in path:
new_paths = self._find_all_paths(path + [neighbor])
all_paths.extend(new_paths)
return all_paths
def _path_weight(self, path):
total = 0
for i in range(len(path)-1):
for neighbor, weight in self.graph[path[i]]:
if neighbor == path[i+1]:
total += weight
break
return total
def _calculate_scores(self):
return {
path: self._temporal_decay(self._path_weight(path))
for path in self.paths
}
def _temporal_decay(self, weight):
return math.exp(-self.decay_rate * weight)
def getRankedPaths(self):
return sorted(self.scores.items(), key=lambda x: x[1], reverse=True)
def _calculate_bottlenecks(self):
node_flow = defaultdict(int)
for path in self.paths:
for node in path[1:-1]:
node_flow[node] += 1
sorted_bottlenecks = sorted(
node_flow.items(),
key=lambda x: (-x[1], x[0])
)
return sorted_bottlenecks
def getBottlenecks(self):
return self.bottlenecks
if __name__ == "__main__":
graph = {
'A': [('B', 2), ('C', 5)],
'B': [('D', 1)],
'C': [('D', 3)],
'D': []
}
scorer = PathGraph(graph, 'A', 'D')
print("Top ranked paths:")
for path, score in scorer.getRankedPaths():
print(f"Path: {path}, Score: {score:.4f}")
print("Bottlenecks:")
for node, count in scorer.getBottlenecks():
print(f"Node: {node}, Flow count: {count}")