Planning complex projects is difficult because it is hard to see which tasks depend on others and what order they must be completed in. This often leads to bottlenecks or starting work that cannot be finished yet.
It breaks a large goal into smaller tasks and maps out their connections to create a clear, step-by-step order of operations. It then ranks these tasks so you know exactly what to do next.
It turns a messy list of to-dos into a clear roadmap by identifying the logical flow of a project.
It was run in the sandbox and it failed. run output shows an error/traceback — the artifact does NOT run clean.
$ python3 graph_based_task_ranker_v2.py
Traceback (most recent call last):
File "/work/graph_based_task_ranker.py", line 108, in <module>
print("ськимов staveb:", ' -> '.join(sorted_tasks))
^^^^^^^^^^^^
NameError: name 'sorted_tasks' is not definedNo 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 — 108 lines, one file, standard library only.
#!/usr/bin/env python3
from collections import defaultdict, deque
import heapq
def build_graph(tasks):
graph = defaultdict(list)
for task in tasks:
task_id = task['id']
for dep in task['depends_on']:
graph[dep].append(task_id)
# Ensure all tasks are in the graph even if they have no outgoing edges
for task in tasks:
if task['id'] not in graph:
graph[task['id']] = []
return graph
def reverse_graph(original_graph):
reverse = defaultdict(list)
for node, neighbors in original_graph.items():
for neighbor in neighbors:
reverse[neighbor].append(node)
return reverse
def calculate_reachability_scores(graph):
reverse_graph = reverse_graph(graph)
scores = {}
for node in graph:
visited = set()
queue = deque([node])
visited.add(node)
while queue:
current = queue.popleft()
for neighbor in reverse_graph.get(current, []):
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
scores[node] = len(visited)
return scores
def topological_sort(graph):
in_degree = defaultdict(int)
adjacency = graph
for node in graph:
for neighbor in graph[node]:
in_degree[neighbor] += 1
queue = deque()
for node in graph:
if in_degree[node] == 0:
queue.append(node)
result = []
while queue:
node = queue.popleft()
result.append(node)
for neighbor in adjacency[node]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
if len(result) != len(graph):
raise ValueError("Graph has cycles and cannot be topologically sorted.")
return result
def calculate_longest_paths(graph):
topo_order = topological_sort(graph)
longest = {node: 1 for node in graph}
predecessors = {node: None for node in graph}
for node in topo_order:
for neighbor in graph[node]:
if longest[neighbor] < longest[node] + 1:
longest[neighbor] = longest[node] + 1
predecessors[neighbor] = node
max_length = max(longest.values(), default=0)
critical_nodes = [node for node in graph if longest[node] == max_length]
critical_paths = []
for node in critical_nodes:
path = []
current = node
while current is not None:
path.append(current)
current = predecessors.get(current)
path.reverse()
critical_paths.append(path)
return critical_paths, max_length
def main():
# Example tasks as input data
data = {
"tasks": [
{"id": "A", "depends_on": ["B", "C"]},
{"id": "B", "depends_on": []},
{"id": "C", "depends_on": ["D"]},
{"id": "D", "depends_on": []}
]
}
graph = build_graph(data['tasks'])
scores = calculate_reachability_scores(graph)
sorted_tasks = topological_sort(graph)
print("shima stav:", ' -> '.join(sorted_tasks))
critical_paths, max_length = calculate_longest_paths(graph)
print(f"Critical Path(s) with length {max_length}:")
for path in critical_paths:
print(' -> '.join(path))
if __name__ == "__main__":
main()