前後順序のある有向エッジのトポロジカルソート
(例えば、前工程のあるタスクの順序の解決等)を行えるライブラリです。
次のような矢印のあるグラフ
graph LR
A --> C
B --> C
B --> D
C --> E
D --> E
に対応するTopologicalSorterのインスタンスは以下で定義できます。
import graphlib
# TopologicalSorter(graph=None) graph:はノードとその先行ノードの辞書
graph = {'E': {'C', 'D'}, 'D': {'B'}, 'C': {'A', 'D'}}
ts = graphlib.TopologicalSorter(graph)
あるいはadd
でも指定できます。
ts = graphlib.TopologicalSorter()
# add(node, *predecessors) node:ノード, predecessors:先行ノード
ts.add('C', 'A', 'D')
ts.add('D', 'B')
ts.add('E', 'C', 'D')
辞書{'C': {'A', 'D'}
や引数('C', 'A', 'D')
は
C
graphlibのメソッドは以下があります。
これらを使って矢印で先行しているノードから順番にマーキングを行うことができます。
以下ノードを順番にマークする流れです。
まずグラフを準備します。
graph = {'E': {'C', 'D'}, 'D': {'B'}, 'C': {'A', 'B'}}
ts = graphlib.TopologicalSorter(graph)
ts.prepare()
graph LR
A --> C
B --> C
B --> D
C --> E
D --> E
最初にマークできるのは'A'と'B'のノード。(※以降マーク可能なノードを薄い黄色、マークしたノードを濃い黄色にします)
ts.is_active() #= > True
ts.get_ready() # => ('B', 'A')
ts.get_ready() # => () 1回取得すると同じノードは2回は取得されない
ts.is_active() #= > True
graph LR
A:::mark --> C
B:::mark --> C
B --> D
C --> E
D --> E
classDef mark fill:lightyellow,stroke:black,stroke-width:1px,color:black,background-color:lightyellow;
A
にマークを行う。
ts.done('A')
ts.get_ready() # => ()
ts.is_active() #= > True
graph LR
A:::done --> C
B:::mark --> C
B --> D
C --> E
D --> E
classDef mark fill:lightyellow,stroke:black,stroke-width:1px,color:black,background-color:lightyellow;
classDef done fill:gold,stroke:black,stroke-width:1px,color:black,background-color:gold;
B
にマークを行う。
ts.done('B')
ts.get_ready() # => ('D', 'C')
ts.is_active() #= > True
graph LR
A:::done --> C
B:::done --> C
B --> D
C:::mark --> E
D:::mark --> E
classDef mark fill:lightyellow,stroke:black,stroke-width:1px,color:black,background-color:lightyellow;
classDef done fill:gold,stroke:black,stroke-width:1px,color:black,background-color:gold;
C
にマークを行う。
ts.done('C')
ts.get_ready() # => ()
ts.is_active() #= > True
graph LR
A:::done --> C
B:::done --> C
B --> D
C:::done --> E
D:::mark --> E
classDef mark fill:lightyellow,stroke:black,stroke-width:1px,color:black,background-color:lightyellow;
classDef done fill:gold,stroke:black,stroke-width:1px,color:black,background-color:gold;
D
にマークを行う。
ts.done('D')
ts.get_ready() # => ('E',)
ts.is_active() #= > True
graph LR
A:::done --> C
B:::done --> C
B --> D
C:::done --> E:::mark
D:::done --> E
classDef mark fill:lightyellow,stroke:black,stroke-width:1px,color:black,background-color:lightyellow;
classDef done fill:gold,stroke:black,stroke-width:1px,color:black,background-color:gold;
E
にマークを行う。
ts.done('E')
ts.get_ready() # => ()
ts.is_active() #= > False マーク終了
graph LR
A:::done --> C
B:::done --> C
B --> D
C:::done --> E:::done
D:::done --> E
classDef done fill:gold,stroke:black,stroke-width:1px,color:black,background-color:gold;
graph = {'E': {'C', 'D'}, 'D': {'B'}, 'C': {'A', 'B'}}
ts = graphlib.TopologicalSorter(graph)
ts.prepare()
while ts.is_active():
ready_nodes = ts.get_ready()
ts.done(*ready_nodes)
print(ready_nodes)
#=>
# ('B', 'A')
# ('D', 'C')
# ('E',)
graph = {'E': {'C', 'D'}, 'D': {'B'}, 'C': {'A', 'B'}}
ts = graphlib.TopologicalSorter(graph)
list(ts.static_order())
# => ['B', 'A', 'D', 'C', 'E']
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント