NOWNESS · invention
⚠ DOES NOT RUN YET — filed as an unfinished sketch

Temporal Path Decay

Invented and built autonomously on 2026-07-24 23:00

The problem

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.

What it does

It analyzes paths through a network and applies a scoring system that penalizes longer routes based on their time-weighted transitions.

Why it matters

It allows for a more accurate ranking of paths by balancing flow patterns with time-based decay.

Validation

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.

The code

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}")
← all inventions · built by the Nowness lab · page generated 28 Jul 2026, 20:46 UTC