diff --git a/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths.rb b/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths.rb new file mode 100644 index 0000000..3ef755e --- /dev/null +++ b/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths.rb @@ -0,0 +1,45 @@ +# ShortestPaths example, from figure 1 of "Logic and lattices for +# distributed programming", Conway et. al, UCB tech report, 2012 +# +# Modified slightly: +# - added "bootstrap" section to give the algorithm some data +# - added "stdio <~ ..." to monitor results +# - added boilerplate to kickstart the program +# +# Problem: doesn't terminate or yield output, because cycles exist in +# the input. + +require 'rubygems' +require 'bud' + +class ShortestPaths + include Bud + + state do + table :link, [:from, :to] => [:cost] + scratch :path, [:from, :to, :next_hop, :cost] + scratch :min_cost, [:from, :to] => [:cost] + end + + bootstrap do + link <= [[1, 3, -2], + [2, 1, 4], + [2, 3, 3], + [3, 4, 2], + [4, 2, -1]] + end + + bloom do + path <= link {|l| [l.from, l.to, l.to, l.cost]} + path <= (link*path).pairs(:to => :from) do |l,p| + [l.from, p.to, l.to, l.cost + p.cost] + end + min_cost <= path.group([:from, :to], min(:cost)) + + stdio <~ path { |p| ["path" + p.to_s] } + stdio <~ min_cost { |m| ["min_cost" + m.to_s] } + end +end + +program = ShortestPaths.new() +program.run_fg diff --git a/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths.rkt b/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths.rkt new file mode 100644 index 0000000..7e0fbb0 --- /dev/null +++ b/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths.rkt @@ -0,0 +1,46 @@ +#lang prospect +;; After Figure 1 in "Logic and lattices for distributed programming", +;; Conway et. al, UCB tech report, 2012 +;; +;; Quasi-problem: doesn't terminate, because cycles exist in the +;; input. + +(require racket/set) +(require prospect/actor) + +(struct link (from to cost) #:prefab) +(struct path (from to cost) #:prefab) +(struct path-exists (from to) #:prefab) ;; Hmm. +(struct min-cost (from to cost) #:prefab) + +(actor (forever (assert (link 1 3 -2)) + (assert (link 2 1 4)) + (assert (link 2 3 3)) + (assert (link 3 4 2)) + (assert (link 4 2 -1)))) + +(actor (forever (during (link $from $to $cost) + (assert (path-exists from to)) + (assert (path from to cost))))) + +(actor (forever (during (link $A $B $link-cost) + (during (path B $C $path-cost) + (assert (path-exists A C)) + (assert (path A C (+ link-cost path-cost))))))) + +(actor (forever (during (path-exists $from $to) + #:collect [(costs (set)) (least +inf.0)] + (assert (min-cost from to least)) + (on (asserted (path from to $cost)) + (values (set-add costs cost) + (min least cost))) + (on (retracted (path from to $cost)) + (define new-costs (set-remove costs cost)) + (values new-costs + (for/fold [(least +inf.0)] [(x new-costs)] (min x least))))))) + +;; (actor (forever (during (path $from $to $cost) +;; #:init [(displayln `(+ ,(path from to cost)))] +;; #:done [(displayln `(- ,(path from to cost)))]))) +(actor (forever (on (asserted (min-cost $from $to $cost)) + (displayln (min-cost from to cost))))) diff --git a/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths2.rb b/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths2.rb new file mode 100644 index 0000000..158991d --- /dev/null +++ b/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths2.rb @@ -0,0 +1,44 @@ +# ShortestPaths example, from figure 1 of "Logic and lattices for +# distributed programming", Conway et. al, UCB tech report, 2012 +# +# Modified slightly: +# - added "bootstrap" section to give the algorithm some data +# - added "stdio <~ ..." to monitor results +# - added boilerplate to kickstart the program +# - repurposed next_hop field to track seen-set to avoid nontermination + +require 'rubygems' +require 'bud' +require 'set' + +class ShortestPaths + include Bud + + state do + table :link, [:from, :to] => [:cost] + scratch :path, [:from, :to, :seen, :cost] + scratch :min_cost, [:from, :to] => [:cost] + end + + bootstrap do + link <= [[1, 3, -2], + [2, 1, 4], + [2, 3, 3], + [3, 4, 2], + [4, 2, -1]] + end + + bloom do + path <= link {|l| [l.from, l.to, Set.new.add(l.from).add(l.to), l.cost]} + path <= (link*path).pairs(:to => :from) do |l,p| + [l.from, p.to, p.seen.clone.add(l.from), l.cost + p.cost] if not p.seen.include?(l.from) + end + min_cost <= path.group([:from, :to], min(:cost)) + + stdio <~ path { |p| ["path" + p.to_s] } + stdio <~ min_cost { |m| ["min_cost" + m.to_s] } + end +end + +program = ShortestPaths.new() +program.run_fg diff --git a/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths2.rkt b/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths2.rkt new file mode 100644 index 0000000..26321df --- /dev/null +++ b/prospect/examples/all-pairs-shortest-paths/all-pairs-shortest-paths2.rkt @@ -0,0 +1,44 @@ +#lang prospect +;; After Figure 1 in "Logic and lattices for distributed programming", +;; Conway et. al, UCB tech report, 2012 + +(require racket/set) +(require prospect/actor) + +(struct link (from to cost) #:prefab) +(struct path (from to seen cost) #:prefab) +(struct path-exists (from to) #:prefab) ;; Hmm. +(struct min-cost (from to cost) #:prefab) + +(actor (forever (assert (link 1 3 -2)) + (assert (link 2 1 4)) + (assert (link 2 3 3)) + (assert (link 3 4 2)) + (assert (link 4 2 -1)))) + +(actor (forever (during (link $from $to $cost) + (assert (path-exists from to)) + (assert (path from to (set from to) cost))))) + +(actor (forever (during (link $A $B $link-cost) + (during (path B $C $seen $path-cost) + (assert #:when (not (set-member? seen A)) (path-exists A C)) + (assert #:when (not (set-member? seen A)) + (path A C (set-add seen A) (+ link-cost path-cost))))))) + +(actor (forever (during (path-exists $from $to) + #:collect [(costs (set)) (least +inf.0)] + (assert (min-cost from to least)) + (on (asserted (path from to _ $cost)) + (values (set-add costs cost) + (min least cost))) + (on (retracted (path from to _ $cost)) + (define new-costs (set-remove costs cost)) + (values new-costs + (for/fold [(least +inf.0)] [(x new-costs)] (min x least))))))) + +(actor (forever (during (path $from $to $seen $cost) + #:init [(displayln `(+ ,(path from to seen cost)))] + #:done [(displayln `(- ,(path from to seen cost)))]))) +(actor (forever (on (asserted (min-cost $from $to $cost)) + (displayln (min-cost from to cost)))))