Cartago by Example: Deis, Universit' A Di Bologna, Italy
Cartago by Example: Deis, Universit' A Di Bologna, Italy
Cartago by Example: Deis, Universit' A Di Bologna, Italy
version: 2.0.1
Main author: aricci, asanti
Creation date: 20100801
Last Changes date: 20110412
1 Introduction 2
2 Examples 5
2.1 Example 00 - Hello World . . . . . . . . . . . . . . . . . . . . 5
2.2 Example 01 - Artifact definition, creation and use . . . . . . . 7
2.3 Example 02 - Action Failure . . . . . . . . . . . . . . . . . . . 12
2.4 Example 03 - Operations with output parameters (i.e. actions
with feedbacks) . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.5 Example 04 - Operations with guards . . . . . . . . . . . . . 16
2.6 Example 05 - Structured Operations . . . . . . . . . . . . . . 19
2.7 Example 05a - Implementing coordination artifacts . . . . . . 22
2.8 Example 06 - Internal operations and timed await: imple-
menting a clock . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.9 Example 07 - Await with blocking commands: Implementing
artifacts for I/O . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.10 Example 07a - Programming GUI as Artifacts . . . . . . . . . 32
2.11 Example 07b - Doing I/O with the Operating System - Shell
artifact . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.12 Example 08 - Linkability . . . . . . . . . . . . . . . . . . . . . 38
2.13 Example 09 - Java data-binding . . . . . . . . . . . . . . . . . 41
2.14 Example 10 - Working with Multiple Workspaces . . . . . . . 43
2.15 Example 11 - Working in Remote Workspaces . . . . . . . . . 45
2.16 Example 11a - Working in Remote Workspaces using LIP
RMI Protocol (JaCa-Android) . . . . . . . . . . . . . . . . . 48
2.17 Example 12 - Contract Net Protocol (CNP) using Artifacts . 49
1
Chapter 1
Introduction
2
artifacts, disposing existing ones), the repertoire of actions is dynamic
too.
3
– null value is mapped into an unbound variable
– arrays are mapped into lists
– objects in general are mapped by atoms cobj XXX that work as
object reference
Jason agents do not share objects: each agent has its own object pool.
4
Chapter 2
Examples
agents:
hello_agent agentArchClass c4jason.CAgentArch;
classpath: "../../../../lib/cartago.jar";
"../../../../lib/c4jason.jar";
}
!hello.
5
+!hello : true
<- println("Hello, world!").
Highlights:
6
2.2 Example 01 - Artifact definition, creation and
use
This example shows the basics about artifact creation and use, including
observation. Two agents create, use and observe a shared artifact.
MAS example01_useobs {
environment:
c4jason.CartagoEnvironment
agents:
user user agentArchClass c4jason.CAgentArch #1;
observer observer agentArchClass c4jason.CAgentArch #1;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
!create_and_use.
+!create_and_use : true
<- !setupTool(Id);
inc;
inc [artifact_id(Id)].
+!setupTool(C): true
<- makeArtifact("c0","c4jexamples.Counter",[],C).
Hightlights:
7
action fails. If more than one artifact is found, first artifacts created
by the agent itself are considered. If more than one artifact is found,
one is selected non deterministically. Then, the rest of the artifacts
are considered, and one is selected non deterministically.
import cartago.*;
void init(){
defineObsProperty("count",0);
}
Highlights
• Artifact definition – an artifact template can be implemented by defin-
ing a class – whose name corresponds to the artifact template name –
extending the Artifact base class.
8
created. The actual parameter of the init method – in this case there
are no parameters – can be specified when executing the makeArtifact
action.
9
If an operation fails, changes to the observable state of the artifact are
rolled back.
Finally, an observer agent observes the counter and prints on standard out-
put a message each time it perceives a change in count observable property
or a tick signal:
!observe.
+!observe : true
<- ?myTool(C); // discover the tool
focus(C).
+count(V)
<- println("observed new value: ",V).
+tick [artifact_name(Id,"c0")]
<- println("perceived a tick").
+?myTool(CounterId): true
<- lookupArtifact("c0",CounterId).
-?myTool(CounterId): true
<- .wait(10);
?myTool(CounterId).
Highlights
• Focus action – agents can select which parts (artifacts) of the envi-
ronment to observe by means of the focus action, provided by the
workspace artifact, specifying the identifier of the artifact to focus.
Variants:
10
– focusWhenAvailable(String artName) – focuses the specified ar-
tifact as soon as it is available in the workspace;
11
2.3 Example 02 - Action Failure
This example is a simple variation of the previous one, to show action failure.
As in the previous case, two agents create, use and observe a shared artifact,
in this case a bounded counter :
MAS example01b_useobs {
environment:
c4jason.CartagoEnvironment
agents:
user2 agentArchClass c4jason.CAgentArch #1;
observer agentArchClass c4jason.CAgentArch #1;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
Highlights:
– failed(String failureMsg)
12
– failed(String failureMsg, String descr, Object... args)
+!create_and_use : true
<- !setupTool(Id);
!use(Id).
+!use(Counter)
<- for (.range(I,1,100)){
inc [artifact_id(Counter)];
}.
-!use(Counter) [error_msg(Msg),inc_failed("max_value_reached",Value)]
<- println(Msg);
println("last value is ",Value).
+!setupTool(C): true
<- makeArtifact("c0","c4jexamples.BoundedCounter",[50],C).
Highlights:
13
2.4 Example 03 - Operations with output param-
eters (i.e. actions with feedbacks)
Operations can have output parameters, i.e. parameters whose value is
meant to be computed by the operation execution. On the agent side such
parameters are managed as action feedbacks. At the API level, output
parameters are represented by the class OpWithFeedbackParam<ParamType>,
where ParamType must be the specific type of the output parameter. The
class provides then a set method to set the output parameter value.
In the following example, an agent creates and uses a Calc artifact, by
executing operations with output parameters:
MAS example03_output_param {
environment:
c4jason.CartagoEnvironment
agents:
calc_user agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
@OPERATION
void sum(double a, double b, OpFeedbackParam<Double> sum){
sum.set(a+b);
}
@OPERATION
void sumAndSub(double a, double b, OpFeedbackParam<Double> sum,
OpFeedbackParam<Double> sub){
sum.set(a+b);
sub.set(a-b);
}
}
!use_calc.
14
+!use_calc
<- makeArtifact("myCalc","c4jexamples.Calc",[]);
sum(4,5,Sum);
println("The sum is ",Sum);
sumAndSub(0.5, 1.5, NewSum, Sub);
println("The new sum is ",NewSum," and the sub is ",Sub).
Highlights:
15
2.5 Example 04 - Operations with guards
When defining an operation, a guard can be specified as a condition that
must be verified to start operation execution, otherwise such execution is sus-
pended. This can be done by including a guard attribute in the @OPERATION
annotation, specifying the name of the boolean method (guard method)
– annotated with @GUARD, representing the condition to be tested. Guard
methods are called passing the same parameters of the guarded operation
(so they must declare the same parameters). Typically guard methods do
checks on the value of internal and observable state of the artifact, without
changing it.
Operations with guards are useful to realise artifacts with synchronisa-
tion functionalities. In the following example, guards are used to implement
a bounded buffer artifact in a producers-consumers architecture.
MAS example04_prodcons {
environment:
c4jason.CartagoEnvironment
agents:
producer agentArchClass c4jason.CAgentArch #10;
consumer agentArchClass c4jason.CAgentArch #10;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
Ten producers agents and ten consumers agents exchange information items
by exploiting the bounded buffer. Guarded operations allow for realising a
simple coordinated behaviour, such that consumers’ get action is suspended
if the buffer is empty, and producers’ put action is suspended if the buffer
is full. Bounded buffer code:
16
@OPERATION(guard="bufferNotFull")
void put(Object obj){
items.add(obj);
getObsProperty("n_items").updateValue(items.size());
}
@OPERATION(guard="itemAvailable")
void get(OpFeedbackParam<Object> res){
Object item = items.removeFirst();
res.set(item);
getObsProperty("n_items").updateValue(items.size());
}
@GUARD
boolean itemAvailable(OpFeedbackParam<Object> res){
return items.size() > 0;
}
@GUARD
boolean bufferNotFull(Object obj){
return items.size() < nmax;
}
}
Producers code:
item_to_produce(0).
!produce.
+?nextItemToProduce(N) : true
<- -item_to_produce(N);
+item_to_produce(N+1).
17
makeArtifact("myBuffer","c4jexamples.BoundedBuffer",[10],Buffer).
Consumers code:
!consume.
+!consume: true
<- ?bufferReady;
!consumeItems.
+!consumeItems: true
<- get(Item);
!consumeItem(Item);
!!consumeItems.
+!consumeItem(Item) : true
<- .my_name(Me);
println(Me,": ",Item).
+?bufferReady : true
<- lookupArtifact("myBuffer",_).
-?bufferReady : true
<-.wait(50);
?bufferReady.
Highlights:
18
2.6 Example 05 - Structured Operations
In order to realise complex operations, a family of primitives (called await) is
provided to suspend the execution of an operation until some specified condi-
tion is met, breaking the execution of an operation in multiple transactional
steps. By suspending the execution of an operation, other operations can
be invoked before the current one is terminated. When the specified condi-
tion holds and no operations are in execution, the suspended operation is
resumed.
Complex operations which can be implemented by using this mechanism
include:
• long-term operations which need not to block the use of the artifact;
environment:
c4jason.CartagoEnvironment
agents:
complexop_userA agentArchClass c4jason.CAgentArch;
complexop_userB agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
The artifact used by the two agents has the following code:
public class ArtifactWithComplexOp extends Artifact {
int internalCount;
void init(){
internalCount = 0;
}
19
signal("step1_completed");
await("myCondition", ntimes);
signal("step2_completed",internalCount);
}
@do_test
+!do_test
<- println("[userA] creating the artifact...");
makeArtifact("a0","c4jexamples.ArtifactWithComplexOp",[],Id);
focus(Id);
println("[userA] executing the action...");
complexOp(10);
println("[userA] action completed.").
+step1_completed
20
<- println("[userA] first step completed.").
+step2_completed(C)
<- println("[userA] second step completed: ",C).
It is worth noting that the agent reacts to step1 completed signal generated
by the artifact, printing a message on the console, even if the do test plan
execution is suspended waiting for complexOp(10) action completion.
complexop userB source code:
!do_test.
+!do_test
<- !discover("a0");
!use_it(10).
+!use_it(0)
<- println("[userB] completed.").
+!discover(ArtName)
<- lookupArtifact(ArtName,_).
-!discover(ArtName)
<- .wait(10);
!discover(ArtName).
The agent simply executes for 10 times the update operation. By running
the example it is possible to see the interleaving of the agent actions.
Highlights:
21
2.7 Example 05a - Implementing coordination ar-
tifacts
Here we show an example of how to exploit structured operations to im-
plement a coordination artifact, a simple tuple space, and its usage to solve
the dining philosophers coordination problem. The in and rd operations
(that corresponds to the in and rd Linda primitives) are easily implemented
exploiting the await mechanism:
public class TupleSpace extends Artifact {
TupleSet tset;
void init(){
tset = new TupleSet();
}
22
@GUARD boolean foundMatch(TupleTemplate tt){
return tset.hasTupleMatching(tt);
}
}
(The description of Tuple, TupleTemplate and TupleSet classes is omitted).
This is actually the implementation of the blackboard tuple space artifact
available by default in any workspace.
It follows a solution to the dining philosophers problem using a tuple space:
MAS example05a_philo {
environment:
c4jason.CartagoEnvironment
agents:
waiter agentArchClass c4jason.CAgentArch;
philo agentArchClass c4jason.CAgentArch #5;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
The MAS is composed by a waiter agent and five philosophers The waiter is
responsible of preparing the environment, injecting the tuples representing
the forks (five fork(F) tuples) and tickets (four ticket tuples), which allow
for avoiding deadlocks.
philo(0,"philo1",0,1).
philo(1,"philo2",1,2).
philo(2,"philo3",2,3).
philo(3,"philo4",3,4).
philo(4,"philo5",4,0).
!prepare_table.
+!prepare_table
<- for ( .range(I,0,4) ) {
out("fork",I);
?philo(I,Name,Left,Right);
out("philo_init",Name,Left,Right);
};
for ( .range(I,1,4) ) {
out("ticket");
};
println("done.").
23
The philosophers repeatedly get a couple of forks, use them to eat, and
then release them. Before taking the forks they must get a ticket, which is
released then after releasing the forks.
!start.
+!start
<- .my_name(Me);
in("philo_init",Me,Left,Right);
+my_left_fork(Left);
+my_right_fork(Right);
println(Me," ready.");
!!living.
+!living
<- !thinking;
!eating;
!!living.
+!eating
<- !acquireRes;
!eat;
!releaseRes.
+!acquireRes :
my_left_fork(F1) & my_right_fork(F2)
<- in("ticket");
in("fork",F1);
in("fork",F2).
+!releaseRes:
my_left_fork(F1) & my_right_fork(F2)
<- out("fork",F1);
out("fork",F2);
out("ticket").
+!thinking
<- .my_name(Me); println(Me," thinking").
+!eat
<- .my_name(Me); println(Me," eating").
Highlights:
24
2.8 Example 06 - Internal operations and timed
await: implementing a clock
Sometimes it is useful to implement operations that trigger the asynchronous
execution of other operations inside the artifact, which are typically long-
term. For instance: a clock artifact can have the start operation, triggering
the execution of a long-term counting operation. Such operations are typ-
ically internal, i.e. not (necessarily) part of the usage interface, and are
annotated with @INTERNAL OPERATION. To trigger the execution of an inter-
nal operation the execInternalOp primitive is provided.
In the following example, an agent creates a clock and uses it.
MAS example06_clock {
environment:
c4jason.CartagoEnvironment
agents:
clock_user agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
The clock artifact has two usage interface operations – start and stop – and
an internal operation count, triggered by start:
public class Clock extends Artifact {
boolean counting;
final static long TICK_TIME = 100;
void init(){
counting = false;
}
25
@OPERATION void stop(){
counting = false;
}
Highlights:
+!test_clock
<- makeArtifact("myClock","c4jexamples.Clock",[],Id);
focus(Id);
+n_ticks(0);
start;
println("clock started.").
@plan1
+tick: n_ticks(10)
<- stop;
println("clock stopped.").
@plan2 [atomic]
+tick: n_ticks(N)
<- -+n_ticks(N+1);
println("tick perceived!").
Highlights:
26
• Controllable processes – these features make it possible to exploit arti-
facts also to implement controllable long-term processes, without the
need to use agents for this purpose (e.g. clock agent).
27
2.9 Example 07 - Await with blocking commands:
Implementing artifacts for I/O
In order to implement artifacts that provides I/O functionalities for inter-
acting with the external world (e.g. network communication, user I/O, GUI,
etc.), a further kind of await primitive is provided, accepting an object of
type IBlockingCommand representing a command to be executed. The prim-
itive suspends the execution of the operation until the specified command –
which typically contains some kind of I/O and a blocking behaviour – has
been executed.
In the following example, two agents communicate by means of two artifacts
that function as network port, providing I/O network communication based
on UDP sockets.
MAS example07_extcommand {
environment: c4jason.CartagoEnvironment
agents:
sender agentArchClass c4jason.CAgentArch #1;
receiver agentArchClass c4jason.CAgentArch #1;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
The agent sender creates and uses its port to send two messages:
!send_info.
+!send_info : true
<- makeArtifact("senderPort","c4jexamples.Port",[23000]);
sendMsg("hello1","localhost:25000");
sendMsg("hello2","localhost:25000").
The agent receiver creates and uses its own port to get the messages, using
two different receiving styles:
!receive_msgs.
+!receive_msgs : true
<- makeArtifact("receiverPort","c4jexamples.Port",[25000],Id);
receiveMsg(Msg,Sender);
println("received ",Msg," from ",Sender);
focus(Id);
28
startReceiving.
+new_msg(Msg,Sender)
<- println("received ",Msg," from ",Sender).
DatagramSocket socket;
ReadCmd cmd;
boolean receiving;
@OPERATION
void init(int port) throws Exception {
socket = new DatagramSocket(port);
cmd = new ReadCmd();
receiving = false;
}
@OPERATION
void sendMsg(String msg, String fullAddress) {
try {
int index = fullAddress.indexOf(’:’);
InetAddress address = InetAddress.getByName(fullAddress.substring(
0, index));
int port = Integer.parseInt(fullAddress.substring(index + 1));
socket.send(new DatagramPacket(msg.getBytes(),
msg.getBytes().length, address, port));
} catch (Exception ex) {
this.failed(ex.toString());
}
}
@OPERATION
void receiveMsg(OpFeedbackParam<String> msg, OpFeedbackParam<String> sender) {
await(cmd);
msg.set(cmd.getMsg());
sender.set(cmd.getSender());
}
@OPERATION
29
void startReceiving() {
receiving = true;
execInternalOp("receiving");
}
@INTERNAL_OPERATION
void receiving() {
while (true) {
await(cmd);
signal("new_msg", cmd.getMsg(), cmd.getSender());
}
}
@OPERATION
void stopReceiving() {
receiving = false;
}
public ReadCmd() {
packet = new DatagramPacket(new byte[1024], 1024);
}
30
}
}
31
2.10 Example 07a - Programming GUI as Arti-
facts
An important example of artifacts encapsulating I/O functionalities is given
by GUI artifacts, i.e. artifacts functioning as GUI components, enabling
the interaction between human users and agents. Such artifacts allow to
use Swing to define the structure of a GUI; then, they allow for defining –
on the one side – operations corresponding to user actions on the GUI, so
handling specific GUI events. Such operations generates signals or change
some observable events to trigger agents observing the GUI; on the other
side, they provide operations that can be possibly used by agents to change
the GUI.
In the following example, a gui tester agent creates and uses a GUI artifact
to interact with the user.
MAS example07a_gui {
environment:
c4jason.CartagoEnvironment
agents:
gui_tester agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
32
linkActionEventToOp(frame.okButton,"ok");
linkKeyStrokeToOp(frame.text,"ENTER","updateText");
linkWindowClosingEventToOp(frame, "closed");
defineObsProperty("value",getValue());
frame.setVisible(true);
}
public MyFrame(){
setTitle("Simple GUI ");
setSize(200,100);
JPanel panel = new JPanel();
setContentPane(panel);
okButton = new JButton("ok");
okButton.setSize(80,50);
text = new JTextField(10);
text.setText("0");
text.setEditable(true);
33
panel.add(text);
panel.add(okButton);
}
Highlights:
+!test_gui
<- makeArtifact("gui","c4jexamples.MySimpleGUI",[],Id);
focus(Id).
+value(V)
<- println("Value updated: ",V).
+ok : value(V)
<- setValue(V+1).
+closed
<- .my_name(Me);
.kill_agent(Me).
In particular, the agent reacts to the pressing of the button by setting a new
value in the GUI; it prints a message on the console as soon as a new value
is observed; it shutdown as soon as the window is closed.
34
2.11 Example 07b - Doing I/O with the Operating
System - Shell artifact
This example shows how to implement an artifact (Shell) that makes it
possible for agents to execute shell commands and get results, using various
style of interaction.
MAS example07b_shell {
environment: c4jason.CartagoEnvironment
agents:
shell_user agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
import cartago.*;
import java.io.*;
35
}
36
!test.
+!test
<- makeArtifact("shell","c4jexamples.Shell",[],Id);
!test_whoami;
focus(Id);
!test_traceroute.
+!test_whoami : true
<- println("who is the user:");
whoami(User);
println(User).
+!test_traceroute
<- println("Tracing the route to CArtAgO site:");
traceroute("cartago.sourceforge.net");
println("done.").
+hop(N,Addr,IP,D0,D1,D2)
<- println(N," ",Addr," (",IP,") ",D0," ",D1," ",D2).
The agent simply tests the two commands, using a reactive plan to observe
to hop signals generated by traceroute. An example of output:
[ shell_user ] who is the user:
[ shell_user ] uid=501(aricci) gid=20(staff) groups=20(staff),204(_developer),100(_lpoperator),
98(_lpadmin),81(_appserveradm),80(admin),79(_appserverusr),61(localaccounts),
12(everyone),402(com.apple.sharepoint.group.1),401(com.apple.access_screensharing)
37
2.12 Example 08 - Linkability
Linkability is the mechanism that makes it possible to create interactions
among artifacts, i.e. execute inter-artifacts operations. Besides the usage
interface, an artifact can expose operations – to be tagged with @LINK. These
operations are meant to be called by other artifacts. In order to allow an
artifact A to execute operations over an artifact B, two options are provided:
In the following example, an agent creates and links together two artifacts.
Then, it executes some operations of one artifact, the linking one, which in
turns executes operations over the second one, the linked one:
MAS example08_linkability {
environment:
c4jason.CartagoEnvironment
agents:
linkability_tester agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
int count;
void init(){
count = 0;
}
38
@LINK void inc(){
log("inc invoked.");
count++;
}
Highlights:
@ARTIFACT_INFO(
outports = {
@OUTPORT(name = "out-1")
}
) public class LinkingArtifact extends Artifact {
39
}
The test and test2 operations executes respectively the inc and getValue
operation over the artifact linked to the out-1 port. The operation test3
instead creates an artifact and executes a linked operation directly using
artifact identifier. Highlights:
• Output ports – output ports are declared in the @ARTIFACT INFO anno-
tation of the artifact class, outports attribute;
+!test_link
<- makeArtifact("myArtifact","c4jexamples.LinkingArtifact",[],Id1);
makeArtifact("count","c4jexamples.LinkableArtifact",[],Id2);
linkArtifacts(Id1,"out-1",Id2);
println("artifacts linked: going to test");
test;
test2(V);
println("value ",V);
test3.
Highlights:
• Linking artifacts – linkArtifacts’s parameters include the identifier of
the linking artifact, its outport and the identifier of the linked artifact.
40
2.13 Example 09 - Java data-binding
Since CArtAgO data model is based on Java object (POJO), a set of internal
actions is provided on the agent side to create/manipulate Java objects. In
particular:
environment:
c4jason.CartagoEnvironment
agents:
java_data_binding_tester agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
+!test_java_api
<- cartago.new_obj("c4jexamples.FlatCountObject",[10],Id);
cartago.invoke_obj(Id,inc);
cartago.invoke_obj(Id,getValue,Res);
println(Res);
cartago.invoke_obj("java.lang.System",currentTimeMillis,T);
println(T);
cartago.invoke_obj("java.lang.Class",
forName("c4jexamples.FlatCountObject"),Class);
println(Class).
41
package c4jexamples;
public FlatCountObject(){
count = 0;
}
Highlights:
• No sharing – Java objects are not meant to be shared, each agent has
its own Java library, managing its own Java objects
42
2.14 Example 10 - Working with Multiple
Workspaces
In the following example, creates two workspaces, joins both and prints
messages using different console artifacts, and then uses internal actions to
set the current workspace.
MAS example10_workspaces {
environment:
c4jason.CartagoEnvironment
agents:
wsp_tester agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
+!test_wsp
<- ?current_wsp(Id0,Name,NodeId);
println("current workspace ",Name," ",NodeId);
println("creating new workspaces...");
createWorkspace("myNewWorkspace1");
createWorkspace("myNewWorkspace2");
joinWorkspace("myNewWorkspace1",WspID1);
?current_wsp(_,Name1,_);
println("hello in ",Name1);
makeArtifact("myCount","c4jexamples.Counter",[],ArtId);
joinWorkspace("myNewWorkspace2",WspID2);
?current_wsp(_,Name2,_);
println("hello in ",Name2);
println("using the artifact of another wsp...");
inc [artifact_id(ArtId)];
cartago.set_current_wsp(WspID1);
println("hello again in ",WspID1);
println("quit..");
quitWorkspace;
?current_wsp(_,Name3,_);
println("back in ",Name3);
quitWorkspace;
cartago.set_current_wsp(Id0);
43
?current_wsp(_,Name4,_);
println("...and finallly in ",Name4," again.").
Highlights:
• Working with mutiple workspaces – Agents can create, join and work
in multiple workspace at a time. However there is always a current
workspace, to which are routed actions with no artifact id or workspace
id specified. Current workspace info are automatically tracked by the
current wsp(WspId,Name,NodeId belief.
44
2.15 Example 11 - Working in Remote
Workspaces
Agents can join workspaces that are hosted on remote nodes, by means of a
joinRemoteWorkspace action (provided by the NodeArtifact. As soon as the
join succeed, the interaction within remote workspaces is the same as local
workspace.
In the following example, a Jason agent joins the default workspace of a
CArtAgO node running on localhost. The following Java program installs a
CArtAgO node on localhost, to make it reachable (also) by remote agents:
package examples;
import cartago.*;
import cartago.util.BasicLogger;
45
Then, it follows the Jason program which creates a standalone CArtAgO
node with a single agent:
MAS example11_remote {
environment:
c4jason.CartagoEnvironment
agents:
voyager agentArchClass c4jason.CAgentArch;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
The voyager agent boots in the standalone node, then it joins a remote
workspace, where he creates and uses an artifact.
!test_remote.
+!test_remote
<- ?current_wsp(Id,_,_);
+default_wsp(Id);
println("testing remote..");
joinRemoteWorkspace("default","localhost",WspID2);
?current_wsp(_,WName,_);
println("hello there ",WName);
!use_remote;
quitWorkspace.
+!use_remote
<- makeArtifact("c0","examples.Counter",[],Id);
focus(Id);
inc;
inc.
+count(V)
<- ?default_wsp(Id);
println("count changed: ",V)[wsp_id(Id)].
-!use_remote [makeArtifactFailure("artifact_already_present",_)]
<- ?default_wsp(WId);
println("artifact already created ")[wsp_id(WId)];
lookupArtifact("c0",Id);
focus(Id);
inc.
Highlights:
46
• Infrastructure options – By default, Jason programs using CArtAgO
environment create a standalone CArtAgO node, i.e. not accessible
through the network, and install the default infrastructure layer (RMI)
for joining remote workspaces. Besides the default CArtAgO installa-
tion, Jason programs have the possibility to work with CArtAgO envi-
ronment technology in four different ways specifying a set of param-
eters in the c4jason.CartagoEnvironment definition inside the Jason
mas2j file:
– c4jason.CartagoEnvironment("standalone"{,
protocol(ProtName), ...})
analogous to the default installation except for the decla-
ration of one (or more) infrastructure layers that specify
the protocols used for working with remote workspaces (ex:
c4jason.CartagoEnvironment(”standalone”,protocol(lipermi)).
– c4jason.CartagoEnvironment("infrastructure"{,
protocol(ProtName), ..., service(ServName)})
installs a CArtAgO node accessible through the network.
The default service protocol supported by the node is RMI,
other service protocols can be installed specifying one or
more service attributes. RMI is installed as the de-
fault protocol for joining remote workspaces but other pro-
tocols can be installed as well using the protocol at-
tribute (ex: c4jason.CartagoEnvironment(”infrastructure”, ser-
vice(”lipermi”), protocol(”lipermi”))).
– c4jason.CartagoEnvironment("remote"{,
WspName, WspAddress, protocol(ProtName, Address), ...})
does not install any node – agents directly join the specified
remote workspace. As usual RMI is installed by default and fur-
ther protocols can be specified using the protocol attribute (ex:
c4jason.CartagoEnvironment(”remote”, ”myWsp”, ”localhost”,
protocol(”lipermi”))).
– c4jason.CartagoEnvironment("local"{,WspName})
does not install any node – agents directly join the specified local
workspace (or the default workspace if no workspace name is spec-
ified) (ex: c4jason.CartagoEnvironment(”local”, ”WspName”)).
47
2.16 Example 11a - Working in Remote
Workspaces using LIP RMI Protocol (JaCa-
Android)
To be completed.
48
2.17 Example 12 - Contract Net Protocol (CNP)
using Artifacts
This example shows a contract net protocol, which is a well-known pro-
tocol used for MAS coordination, realized using artifacts instead of direct
communication. In particular, two kinds of artifacts are used:
• a task board, used by announcers to announce a new task to do and
by bidders to be aware of available tasks.
• a contract net board, used to manage the coordination between an
announcer and the bidders involved in the CNP for a specific task.
So one instance of task board is created and one of contract net board for
each task which is announced.
It follows the implementation TaskBoard of the task board artifact:
public class TaskBoard extends Artifact {
private int taskId;
void init(){
taskId = 0;
}
49
It follows the ContractNetBoard implementation of the contract net board :
public class ContractNetBoard extends Artifact {
50
public Bid(int id, String descr){
this.descr = descr;
this.id = id;
}
The observable property state is used to keep track of the state of the ses-
sion, which is open until the timeout specified by the announcer expires, after
that the state is set to closed – this behavior is realized by the checkDeadline
internal operation, triggered during artifact initialization. While the state is
open, bidders can submit their bids by means of the bid operation, getting
back as action feedback an identifier of their bid. The operation fails if the
state is closed. The announcer can use the artifact to first retrieve the sub-
mitted list of bidders by means of the getBids action, which completes as
soon as the session closes, and then to award a bidder by means of the award
action, whose effect is to create a new observable property winner carrying
on the identifier of the selected bid.
The main of the application launches a simple MAS composed by an an-
nouncer and a bunch of bidders:
MAS example12_cnp {
environment: c4jason.CartagoEnvironment
agents:
announcer agentArchClass c4jason.CAgentArch;
bidder agentArchClass c4jason.CAgentArch #5;
classpath: "../../../lib/cartago.jar";"../../../lib/c4jason.jar";
}
+!allocate_task(Task,Timeout)
<- makeArtifact("task_board","c4jexamples.TaskBoard",[]);
println("taskboard allocated");
announce(Task,Timeout,CNPBoardName);
51
println("announced: ",Task," on ",CNPBoardName);
getBids(Bids) [artifact_name(CNPBoardName)];
println("got bids (",.length(Bids),")");
!select_bid(Bids,Bid);
println("selected: ",Bid);
award(Bid)[artifact_name(CNPBoardName)];
println("awarded: ",Bid);
clear(Task).
+!select_bid([Bid|_],Bid).
The agent first create a task board, then announce a task by doing the
announce action. Then it retrieves the bids, selects a bid – in this case
choosing always the first in the list – award it.
Bidder agents observe the task board and react as soon as a new task
matching their capabilities is announced. In this simple case all bidders are
interested to do t0 tasks, so there is a full competition.
!look_for_tasks("t0",1400).
+!look_for_tasks(Task,MaxBidMakingTime)
<- +task_descr(Task);
+max_bid_time(MaxBidMakingTime);
focusWhenAvailable("task_board");
println("task board located.").
+task(Task,CNPBoard) : task_descr(Task)
<- println("found a task: ",Task);
lookupArtifact(CNPBoard,BoardId);
focus(BoardId);
!make_bid(Task,BoardId).
+winner(BidId) : my_bid(BidId)
<- println("awarded!.").
+!make_bid(Task,BoardId)
<- !create_bid(Task,Bid);
bid(Bid,BidId)[artifact_id(BoardId)];
+my_bid(BidId);
println("bid submitted: ",Bid," - id: ",BidId).
52
-!make_bid(Task,BoardId)
<- println("too late for submitting the bid.");
.drop_all_intentions.
+!create_bid(Task,Bid)
<- ?max_bid_time(Timeout);
Num = math.random(Timeout);
.wait(Num);
.my_name(Name);
.concat("bid_",Name,Bid).
• TBC
53
TODO:
54