how to implement these semantics of OverLog rules in Bloom

77 views
Skip to first unread message

Dillon Peng

unread,
Dec 19, 2012, 3:53:47 AM12/19/12
to bloom...@googlegroups.com
hi, all
   I am implementing Chord in bloom, I hoped to get help from P2's chord.olg because 
I have studied and run many examples of p2, but now, I do not know how to implement these
snippets of chord.olg in Bloom as follows:

f4 eagerFinger(@NI,I,B,BI) :- fFix(@NI,E,I),
        lookupResults(@NI,K,B,BI,E).

f5 finger(@NI,I,B,BI) :- eagerFinger(@NI,I,B,BI).

f6 eagerFinger(@NI,I,B,BI) :- node(@NI,N), eagerFinger(@NI,I1,B,BI),
        I:=I1 + 1, K:=0x1I << I + N, K in (N,B), BI != NI.

in here, eagerFinger and lookupResults are unmaterialize table,  finger and node are defined
as below:
materialize(finger, 180, 160, keys(2)).
materialize(node, infinity, 1, keys(1)).

according to the context, my understanding about the above snippets are:
at first, when getting lookup results, the first record will be added in eagerFinger of rule f4,
and then, eagerFinger will be updated  159 times in rule f5, at the same time the content of eagerFinger
will be added to finger in f5. In summary, one table immediately changes many times when some one 
rule (here, f4) is met.

for bloom, I seemed to need more complicated rules:

  state do
    table :init1, [:t1, :t2] # like lookResults
    table :test1, [:t1] => [:t2] # assistant table
    table :test2, [:t1] => [:t2, :ruleName] # like eagerFinger
    periodic :tik, 1
  end

  bootstrap do
    test1 <= [[10, 0]]
  end

  bloom do
    # test2 will chang many times when test2 gets one ideal input (the interval is 3s) 
    test2 <+- init1 {|xo| [xo.t1, xo.t2, "rule1"]}
    test1 <+- (tik*test2*test1).combos  do |tk, t2,t1| 
      if t2.ruleName == "rule1"
        [t2.t1, t2.t2]
      else
        [t1.t1, t1.t2+2]
      end
    end
    test2 <+- test1 do |t|
      if t.t2.to_i == 10000
        [10,0,"NIL"] 
      end
    end

I am right? or there is a better method?

Thanks a lot in advance!

BEST REGARDS
PengCZ








Joe Hellerstein

unread,
Dec 19, 2012, 4:08:41 AM12/19/12
to bloom...@googlegroups.com
Hi Dillon:
I'm finding your examples confusing.  Can you be more specific about the Overlog feature you're trying to emulate in Bloom?  Did you want a bounded-length table?  

Joe
Message has been deleted

Dillon Peng

unread,
Dec 19, 2012, 2:52:56 PM12/19/12
to bloom...@googlegroups.com
hi,
   Thanks Joe!

在 2012年12月19日星期三UTC+8下午5时08分41秒,jmh写道:
Hi Dillon:
I'm finding your examples confusing.  Can you be more specific about the Overlog feature you're trying to emulate in Bloom?  
sorry, I am not so clear that what feature of Overlog this snippet uses, but I know what things it finished. For simplicity,  I write a complete olg that I need:

materialize(node, infinity, 1, keys(1)).
materialize(finger, 180, 16, keys(2)).
node(LOC). 

f1 fFixEvent(@NI, E, 0) :- periodic(@NI, E, 0.01),node(@NI).

f4 eagerFinger(@NI, I) :- fFixEvent(@NI, E,I).

f5 finger(@NI,I) :- eagerFinger(@NI,I).

f6 eagerFinger(@NI, I) :- node(@NI), eagerFinger(@NI, I1),
        I := I1 + 1.
 
watchmod(node, "id").
watchmod(finger, "dai").
watchmod(eagerFinger, "dai").
watchmod(fFixEvent, "abcdizs").

run with this command:
runOverLog -o test_mat.olg -D LOC=\"localhost:11111\" -n localhost -p 11111

I post the main messages:
fFixEvent!f1_eca!localhost:11111]:  [fFixEvent(localhost:11111, 1804289383, 0)]
finger!f5_eca!localhost:11111]:  [finger(localhost:11111, 0)]
finger!f5_eca!localhost:11111]:  [finger(localhost:11111, 1)]
finger!f5_eca!localhost:11111]:  [finger(localhost:11111, 2)]
...
!finger!f5_eca!localhost:11111]:  [finger(localhost:11111, 8)]
[fFixEvent(localhost:11111, 846930886, 0)]
finger!f5_eca!localhost:11111]:  [finger(localhost:11111, 0)]
finger!f5_eca!localhost:11111]:  [finger(localhost:11111, 1)]
finger!f5_eca!localhost:11111]:  [finger(localhost:11111, 2)]
...
!finger!f5_eca!localhost:11111]:  [finger(localhost:11111, 8)]
...

Of course, I had some idea and already tried to write appropriate bloom program, but 
I am afraid that I can not describe my mind clearly, so I only ask a question:
How to implement the above olg program in bloom? or tell me read some relative bloom examples
to help me write it myself, thanks! 
 
Did you want a bounded-length table?  
yes, some times I need a bounded-length, but I think I can use persistent table
to implement, so this should be not a question. of course , any advice will be welcomed!

Thanks

Dillon Peng

Dillon Peng

unread,
Dec 19, 2012, 7:49:18 PM12/19/12
to bloom...@googlegroups.com
hi, 
   Thanks Joe!
    Sorry, it was too much that I asked you help me translate olg into bloom! 
     So I tried my best to think that my question is what differences in tables between  Overlog and Bloom:
in Overlog, there are only materialize, peroidic, and un-materialize table,   but in Bloom, there are persistent table,. transient table scratch, channel and other tables, so whether I can think  un-materialize table is corresponding to scratch in the following rule
r0 eagerFinger(@NI, I) :- init(@NI, I) /* init is materialize table, I's initial value is 0*/
r1 eagerFinger(@NI I) :- eagerFinger(@NI, I1), I1 := I1 + 1 /* eagerFinger is a un-materialize table*/

but, in Bloom:
    table :init, [:t1, :t2]
    scratch :eagerFinger, [:t1, :t2]
eagerFinger <= init   # r0
eagerFinger <= eagerFinger {|e|  [e.t1, e.t2 + 1] #r1 

I found in Bloom, r1 will lead bloom program into infinite loop, ruby will occupy 100% cpu.
I must miss somthing? 

Thanks 
BEST REGARDS

Dillon

Joe Hellerstein

unread,
Dec 21, 2012, 1:07:50 AM12/21/12
to bloom...@googlegroups.com
1) Some general feedback for historians who are interested in Overlog. 

A scratch in Bloom is a purely node-local collection.    By contrast, Overlog's table syntax was "global" -- an abstract collection that was physically partitioned across nodes.  As a result, Overlog rules required a "localization rewrite" to translate them into locally executable code.  By contrast, in Bloom you need a notion of channels and asynchrony to achieve any non-local behavior.  Bloom is more "honest" in this regard, since it exposes to the programmer -- very explicitly -- the fact that networks introduce delay and failure, and logic that spans the network should account for that.

Here's how you might achieve an Overlog-style unmaterialized table in bloom:

state do
  interface input,   :insertToScratch, [:node, :key, :val]
  scratch :globalScratch, [:node, :key, :val]
  channel :chan, [:@node, :key, :val]
end

bloom do
  chan <~ insertToScratch
  globalScratch <= chan
end

Note that there's no confusion here -- because of the <~ operator, you can see that globalScratch will get populated in an uncontrollable, asynchronous way across the network.

2) Now wrt your example below.  The Bloom program is defining a table eagerFinger that *instantaneously*, within a single tick, contains an infinite number of tuples -- by induction.  Executing that, not surprisingly, causes that single tick to take infinitely long to compute.  If you change the second rule to use <+, you'll get a table that grows infinitely, but only by a finite number of tuples per tick.  In particular, if you start with one tuple in eagerFinger, you'll get one new tuple in eagerFinger each tick:

eagerFinger <+ eagerFinger {|e|  [e.t1, e.t2 + 1]} #r1 

Perhaps that's what you got in the P2 implementation of the Overlog program (I forget!).   This exposes some of the muddy semantics of Overlog that we fixed in Bloom (via Dedalus) -- r1 looks like a traditional, unsafe (i.e. infinite) Datalog rule to me.

Hope that helps.
Joe

Dillon Peng

unread,
Dec 21, 2012, 7:09:02 AM12/21/12
to bloom...@googlegroups.com
hi,
   Thank Joe Very much!
    After studying some bud-sandbox, I finally resolved my question,
but thank you, your explanations are very helpful for me!

On Friday, December 21, 2012 2:07:50 PM UTC+8, jmh wrote:
1) Some general feedback for historians who are interested in Overlog. 

A scratch in Bloom is a purely node-local collection.    By contrast, Overlog's table syntax was "global" -- an abstract collection that was physically partitioned across nodes.  As a result, Overlog rules required a "localization rewrite" to translate them into locally executable code.  By contrast, in Bloom you need a notion of channels and asynchrony to achieve any non-local behavior.  Bloom is more "honest" in this regard, since it exposes to the programmer -- very explicitly -- the fact that networks introduce delay and failure, and logic that spans the network should account for that.

Here's how you might achieve an Overlog-style unmaterialized table in bloom:

state do
  interface input,   :insertToScratch, [:node, :key, :val]
  scratch :globalScratch, [:node, :key, :val]
  channel :chan, [:@node, :key, :val]
end

bloom do
  chan <~ insertToScratch
  globalScratch <= chan
end

Note that there's no confusion here -- because of the <~ operator, you can see that globalScratch will get populated in an uncontrollable, asynchronous way across the network.

     Agreed, and understanding logic of Bloom programs will be easier. 
Reply all
Reply to author
Forward
0 new messages