Ruby Modules
The DBM library has now a binding to the popular Ruby language
(see www.rubycentral.com or
www.ruby-doc.org to start
with Ruby). The binding offers several modules as different layers
on top of the DBM library, depending on what the user wants to
do. The different modules are:
- udbm: This is the core binding that provides the classes
Constraint to define constraints <=c or <c,
Matrix to enter specific DBM matrices, Relation to
type results of relations between federations (inclusion checking),
and Fed that wraps the C++ fed_t type in a Ruby
friendly manner. Try
(UDBM::Fed.public_instance_methods-Object.public_instance_methods).sort
to get a
taste of what is supported. Documentation will come later, this is a
pre-release. For now, you can check fed.h to see what these
methods are doing and check udbm.cpp to see how they are
wrapped (pretty straight-forward).
- udbm-callback: This is a light wrapper that uses Ruby
magic to callback a user defined function whenever a modifying
method (of the form name!) is called. It's a change listener
facility.
- udbm-gtk: This is a graphical viewer binding to
gtk. You'll obviously need ruby-gtk to have this work. Main commands
are UDBM::Fed.show(name), UDBM::Fed.hide, and
UDBM::hide(name) to show and hide federations under a named
tab in the viewer. If the federation instance changes, its view is
updated on-the-fly. The viewer is a particular listener attached to
a federation instance. If you want it to work properly, be careful
with your references, e.g, a.show('me') followed by a = something
new will stop further updates like a.up!. This module is
using udbm-mdi, a nifty graphical component found on Ruby
site. We only renamed it and modified it slightly. You don't have to
worry about this module at all.
- udbm-sys: This offers a higher level view of federations
as systems of constraints. This needs documentation, I
know, but it is written in Ruby and it is therefor easy to read
;). It offers the possibility to manipulate sets (of clock
valuations) as constraints between clocks that you define within
contexts. Say you have a = Context.create('a',:x,:y,:z), this
gives you access to the clocks x, y, and z. Now you can use sets
defined like (a.x < a.y) & (a.y > 3) or (a.x > 4) | (a.y > 5),
compute intersections, relations, unions, whatever you can do on
federations, but with sets instead. It is another view of
federations.
Release
Documentation is still work-in-progress. The draft manual is now
available in the distribution. Some examples are also provided, e.g.,
a simple reachability algorithm for Fisher's mutual exclusion protocol.
Download (linux binaries + source):
ruby-udbm-0.11.tgz
Download (Windows binaries):
ruby-udbm-0.11-win.zip
Note: Please do not try to compile for Windows, you will certainly
suffer.
Known issue: Ruby multi-threading under Windows is terrible and
the Gtk window is definitely not responsive. Try to move your
console away from it and avoid causing expose/redraw events on the
window.
Installing Under Windows
Please follow the steps given on
this page.
In short you need to download and install:
- Ruby for Windows.
- Ruby/Gtk2 for Windows.
- Glade runtime for Windows.
- This Ruby-DBM binding for Windows. Installation is manual (copy
files), or automatic depending if you have a unix shell emulation or
not under Windows. Please INSTALL.TXT. Please choose default paths
for the installations.
Getting Started
Now that you've installed painlessly Ruby and this binding (plus
Gtk and Glade for Windows), you want to try it quickly. Let's get
started. Fire irb, the Ruby interpreter.
prompt>irb
irb(main):001:0>
|
Let's try the most user friendly access, via sets. Of course we want
the Gtk module loaded in too, and we include the module in the
top-level, which is like using the namespace.
irb(main):001:0> require 'udbm-sys'
=> true
irb(main):002:0> require 'udbm-gtk'
=> true
irb(main):003:0> include UDBM
=> Object
irb(main):004:0>
|
Declare a context within which our clocks will exist, say context
named 'C' with clocks x, y, and z. Notice that 'c' is the ruby
variable holding a reference to our named context. Let's check our
clocks.
irb(main):004:0> c=Context.create('C',:x,:y,:z)
=> #<UDBM::Context_C {C.x,C.y,C.z}>
irb(main):005:0> c.x
=> #<UDBM::Context::Clock C.x>
irb(main):006:0> c.y
=> #<UDBM::Context::Clock C.y>
irb(main):007:0> c.z
=> #<UDBM::Context::Clock C.z>
irb(main):008:0>
|
It would have been clearer to use the same variable names. We can
fix this easily. Let's declare two sets with constraints on our
clocks.
irb(main):008:0> C=c
=> #<UDBM::Context_C {C.x,C.y,C.z}>
irb(main):009:0> a=(C.x>C.y)&(C.z<4)&(C.y<3)
=> #<UDBM::Context_C::Set_C (((C.x>C.y)&(C.z<4))&(C.y<3))>
irb(main):010:0> b=a&((C.x<2)|(C.x>=3))
=> #<UDBM::Context_C::Set_C ((((C.x>C.y)&(C.z<4))&(C.y<3))&((C.x<2)|(C.x>=3)))>
irb(main):011:0>
|
You want to see these sets, don't you?
irb(main):011:0> a.show('a')
=> #<UDBM::Context_C::Set_C (C.y<3 & C.y-C.x<0 & C.z<4)>
irb(main):012:0> b.show('b')
=> #<UDBM::Context_C::Set_C (3<=C.x & C.y<3 & C.z<4)|(C.x<2 & C.y-C.x<0 & C.z<4)>
irb(main):013:0>
|
And you obtain magically these under different views:
Hmm, nice with color blending, isn't it? But wait, our sets changed
or what? Let's have a look at them again:
irb(main):013:0> a
=> #<UDBM::Context_C::Set_C (C.y<3 & C.y-C.x<0 & C.z<4)>
irb(main):014:0> b
=> #<UDBM::Context_C::Set_C (3<=C.x & C.y<3 & C.z<4)|(C.x<2 & C.y-C.x<0 & C.z<4)>
irb(main):015:0>
|
They look slightly different but they correspond to what we
asked for. Actually, the library does lazy evaluation whenever
possible. The first declaration gave dummy formulas and asking to
show the sets evaluates them. Notice the slight bold borders that
correspond to non strict constraints. Well, let's play with 'b' now.
irb(main):015:0> b.up!
= > #<UDBM::Context_C::Set_C (3<=C.x & C.y-C.x<0 & C.y-C.z<3 & C.z-C.x<1 & C.z-C.y<4)|(C.x-C.y<2 & C.x-C.z<2 & C.y-C.x<0 & C.z-C.y<4)>
irb(main):016:0>
|
The graphical representation gets automagically updated to these, by
the way :). The colors are blended, which is more useful to
distinguish sets that partially overlap with each other.
All right, let's change the view, do a projection (reset to 1), and
up again.
irb(main):016:0> b.x=1
=> 1
irb(main):017:0> b.up!
=> #<UDBM::Context_C::Set_C (1<=C.x & C.x-C.y<=1 & C.x-C.z<=1 & C.y-C.z<3 & C.z-C.y<4)|(1<=C.x & C.x-C.y<=1 & C.x-C.z<=1 & C.y-C.z<2 & C.z-C.y<4)>
irb(main):018:0>
|
Aha! We could simplify this to one set (notice the overlapping
color orange instead of pink). Let's reduce this.
irb(main):018:0> b.reduce!
=> #<UDBM::Context_C::Set_C (1<=C.x & C.x-C.y<=1 & C.x-C.z<=1 & C.y-C.z<3 & C.z-C.y<4)>
irb(main):019:0>
|