summaryrefslogtreecommitdiff
path: root/tool/lrama/lib/lrama/digraph.rb
diff options
context:
space:
mode:
Diffstat (limited to 'tool/lrama/lib/lrama/digraph.rb')
-rw-r--r--tool/lrama/lib/lrama/digraph.rb53
1 files changed, 53 insertions, 0 deletions
diff --git a/tool/lrama/lib/lrama/digraph.rb b/tool/lrama/lib/lrama/digraph.rb
new file mode 100644
index 0000000000..28f26781b1
--- /dev/null
+++ b/tool/lrama/lib/lrama/digraph.rb
@@ -0,0 +1,53 @@
+module Lrama
+ # Algorithm Digraph of https://dl.acm.org/doi/pdf/10.1145/69622.357187 (P. 625)
+ class Digraph
+ def initialize(sets, relation, base_function)
+ # X in the paper
+ @sets = sets
+ # R in the paper
+ @relation = relation
+ # F' in the paper
+ @base_function = base_function
+ # S in the paper
+ @stack = []
+ # N in the paper
+ @h = Hash.new(0)
+ # F in the paper
+ @result = {}
+ end
+
+ def compute
+ @sets.each do |x|
+ next if @h[x] != 0
+ traverse(x)
+ end
+
+ return @result
+ end
+
+ private
+
+ def traverse(x)
+ @stack.push(x)
+ d = @stack.count
+ @h[x] = d
+ @result[x] = @base_function[x] # F x = F' x
+
+ @relation[x] && @relation[x].each do |y|
+ traverse(y) if @h[y] == 0
+ @h[x] = [@h[x], @h[y]].min
+ @result[x] |= @result[y] # F x = F x + F y
+ end
+
+ if @h[x] == d
+ while true do
+ z = @stack.pop
+ @h[z] = Float::INFINITY
+ @result[z] = @result[x] # F (Top of S) = F x
+
+ break if z == x
+ end
+ end
+ end
+ end
+end