Archive for the tag 'Howto'

Read Message On Blackboard

To finish the overview of the backboard operations, let’s show how to use the read operation. It only checks, if a blackboard contains a wanted tuple (in the previous posts I used the term message, but now we are more experienced :).

The following functionalities will be shown:

  • Creation of an agent.
  • Locating the blackboard.
  • Read a message.

The agent source code is stored in the read.rb file:

require 'rinda/ring'

DRb.start_service

ts = Rinda::RingFinger.primary

result = ts.read [:message, nil], 0

puts “[0]: #{result[0]}”
puts “[1]: #{result[1]}”


See a screencast Read message on blackboard screencast [.ogg].

Firstly, start the rinda.rb code (for more details see the post about starting multi-agent system environment), then, in a separate console, start the write.rb (for more details see the post about writing a message to the blackboard) and finally, in a separate console or in the same console where you started the write.rb file, type:

ruby read.rb

The agent connects to the blackboard, reads a tuple and shows two lines:

[0]: message
[1]: Hi there!

Of course, you could repeat this step any number of times, because this operation only checks if a tuple is there.


Files to download: rinda.rb, write.rb and read.rb.

Message and Tuple

In the last posts a term message was used. In the Rinda documentation you would not probably find this term; it is called more accurately: tuple.


What is a tuple?

  • [1, 2] is a tuple
  • [:message, 'Hi there!'] is a tuple
  • ['Hi there!', :message] is also a tuple
  • [:result, 42, 'John', 'Susanne', 'London'] is a tuple
  • [:clock, Time.new] is a tuple too
  • [:service, CalculatorService.new(1, true) is a tuple

Tuple is an ordered list of elements [wikipedia].


A blackboard is a place to share tuples; agents are writing, reading and taking tuples.

If you have a simple system, where agents are using only one kind of messages, it is enough to use a single, e.g. [1], ['Hello']. But what to do, if your system requires to differentiate more types of messages? Well, there is no problem with writing different types of messages, but there is a problem how to find the correct one to read or take it.

Basically there are two possibilities:

  • Every type of a message has different number of elements. The number of elements is the distinguishing sign.

    Example: [1] is similar to [2] or ['Hello'], but it is different then [3, 'Hello'].

  • One of the parameters is an identifier. The number of elements and an identifier are the distinguishing signs.

    Example: [:request, 1, 2] is similar to [:request, 24, 'John'], but it is different to [:result, 42, 'London'].


How are the blackboard operations using tuples?

  • The write operation writes a tuple (specified as a parameter).
    ts.write [:message, 'Hi there!']
    
  • Reading operations read and take use tuples in a slightly different way. It is possible to use the nil value as a wild card for the position, where it is used.
    • To read any single:
      ts.take [nil], 0
      
    • To read any pair:
      ts.take [nil, nil], 0
      
    • To read any :message type:
      ts.take [:message, nil], 0
      
    • To read any pair, where the second element has value 4 (not very practical example :):
      ts.take [nil, 4], 0
      
    • To read exactly the tuple [:result, 4]:
      ts.take [:result, 4], 0
      

    The second parameter says, how long (in seconds) should a read operation wait until a tuple appears on the blackboard. Zero means to not to wait at all.

Take Message From Blackboard

The Rinda multi-agent system environment is already running, on the blackboard is written a message, so the last step is to read it :)

The following functionalities will be shown:

  • Creation of an agent.
  • Locating the blackboard.
  • Taking a message.

Although a logical opposite operation to the write operation should be the read operation, it is not so in the blackboard system: the operation read only checks if a message is there (this will be shown in a post that will follow); the operation take takes a message from the blackboard.


The agent source code is stored in the take.rb file:

require 'rinda/ring'

DRb.start_service

ts = Rinda::RingFinger.primary

result = ts.take [:message, nil], 0

puts “[0]: #{result[0]}”
puts “[1]: #{result[1]}”


Firstly, start the rinda.rb code (for more details see the post about starting multi-agent system environment), then, in a separate console, start the write.rb (for more details see the post about writing a message to the blackboard) and finally, in a separate console or in the same console where you started the write.rb file, type:

ruby take.rb

The agent connects to the blackboard, takes a message and shows two lines:

[0]: message
[1]: Hi there!


Files to download: rinda.rb, write.rb and take.rb.

Write Message To Blackboard

The Rinda multi-agent system environment is already running, so the next step is to write a message to the blackboard with an agent.

The following functionalities will be shown:

  • Creation of an agent.
  • Locating the blackboard.
  • Writing a message.

The agent source code is stored in the write.rb file:

require 'rinda/ring'

DRb.start_service

ts = Rinda::RingFinger.primary

ts.write [:message, 'Hi there!']

puts ‘Message was sent.’


Firstly, start the rinda.rb code (for more details see the post about starting multi-agent system environment) and then, in a separate console, type:

ruby write.rb

The agent connects to the blackboard and writes a message Hi there!.


Files to download: rinda.rb and write.rb.


For running more processes it is necessary to open more consoles. Applications like screen or konsole on KDE can help you — I use konsole with more sessions.

Starting Multi-Agent System Environment

By starting the Rinda multi-agent system environment we will start the following functionalities:

  • Blackboard. Agents will be able to access a shared place for messages.
  • Discovery service. Agents will be able to find the blackboard automatically.

The whole multi-agent system environment can by started from one file, let’s call it rinda.rb:

require 'rinda/ring'
require 'rinda/tuplespace'

DRb.start_service

ts = Rinda::TupleSpace.new
Rinda::RingServer.new ts

puts 'The blackboard is started...'

DRb.thread.join

Of course, the name can be different :), but in the future examples we will refer to it as the rinda.rb file.


The environment can be started with following line:

ruby rinda.rb

After a start, the message The blackboard is started… appears and the system fully started and ready to serve. :)


Files to download: rinda.rb.

Examples and Howtos

To follow the nice Ruby on Rails motto Show, don’t tell, the majority of future posts will be examples and howtos: how to start environment, simple agent example, an unique ID for an agent, stopping agents with a message, etc