master > master: src-py tarjan alg
This commit is contained in:
parent
4b4634994c
commit
cd265e4ee9
91
code/python/src/graphs/tarjan.py
Normal file
91
code/python/src/graphs/tarjan.py
Normal file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from enum import Enum;
|
||||
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.stacks.stack import *;
|
||||
from src.graphs.graph import *
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'tarjan_algorithm',
|
||||
];
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class State(Enum):
|
||||
UNTOUCHED = 0;
|
||||
PENDING = 1;
|
||||
FINISHED = 2;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Tarjan Algorithm
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class NodeInformation:
|
||||
root: int;
|
||||
index: int;
|
||||
state: State;
|
||||
|
||||
def __init__(self):
|
||||
self.root = self.index = 0;
|
||||
self.state = State.UNTOUCHED;
|
||||
|
||||
def tarjan_algorithm(G: Graph) -> List[Any]:
|
||||
'''
|
||||
runs the Tarjan-Algorithm to compute the strongly connected components
|
||||
'''
|
||||
|
||||
# sonst Stack erstellen und Bearbeitungszustand der Knoten im Speicher notieren:
|
||||
S = Stack();
|
||||
index = 0;
|
||||
infos = { u: NodeInformation() for u in G.nodes };
|
||||
components = [];
|
||||
|
||||
def tarjan_visit(v: Any):
|
||||
'''
|
||||
recursive depth-first search algorithm to compute components
|
||||
'''
|
||||
nonlocal G, S, index, components;
|
||||
|
||||
if not(infos[v].state == State.UNTOUCHED):
|
||||
return;
|
||||
|
||||
index += 1;
|
||||
infos[v].index = infos[v].root = index;
|
||||
S.push(v);
|
||||
|
||||
infos[v].state = State.PENDING;
|
||||
# depth first search:
|
||||
for u in G.successor(v):
|
||||
tarjan_visit(u);
|
||||
# remains relevant for v, provided u still in Stack:
|
||||
if u in S:
|
||||
infos[v].root = min(infos[v].root, infos[u].root);
|
||||
infos[v].state = State.FINISHED;
|
||||
|
||||
# if at root of component pop everything from stack up to root and add component:
|
||||
if infos[v].index == infos[v].root:
|
||||
component = [];
|
||||
condition_reached_root = False;
|
||||
while not condition_reached_root:
|
||||
u = S.pop();
|
||||
component.append(u);
|
||||
condition_reached_root = (u == v);
|
||||
components.append(component);
|
||||
return;
|
||||
|
||||
for v in G.nodes:
|
||||
tarjan_visit(v);
|
||||
return components;
|
Loading…
x
Reference in New Issue
Block a user