Practical work on Environment Oriented Programming

Introduction

In the following exercises you will use a MAS with an environment deployed on multiple machines. You will develop some agent joining a remote workspace of this environment. This workspace is launched on a server machine. The code is thus organized into two JaCaMo projects: one for the MAS "kind-of" server, one for the MAS "kind-of" client.

  • The MAS server ("step_env") provides you with some artifacts deployed in the "server" workspace.
  • The MAS client ("step") is composed of agents that you will have to customize or develop. These agents will connect on the remote workspace to use artifacts that are deployed on this remote workspace.
  • For an agent deployed in the MAS client, use the action in the agent code: "joinRemoteWorkspace("default","localhost",WspID2)" where you replace "localhost" by the machine IP number.

Preamble

Default artifacts available in a workspace:

By default, each workspace contains a basic set of predefined artifacts that provide core functionalities to the agents.

  • node artifact (see the Node API): the node artifact (cartago.NodeArtifact) provides functionalities to create new workspaces, to join local and remote workspaces
  • workspace artifact (see the Workspace API): the workspace artifact (cartago.WorkspaceArtifact) provides functionalities to create, dispose, lookup, link, focus artifacts of the workspace. It provides also operations to set roles and policies related to the RBAC security model.
  • blackboard artifact: the blackboard artifact (cartago.tools.TupleSpace) provides a tuple space that agents can exploit to communicate and coordinate
  • console artifact: the console artifact (cartago.tools.Console) provides functionalities to print messages on standard output.

Making agents invoque operations of the artifact

  • In case of operation invocation with no specification of target artifact: the artifact is automatically selected from the workspace. If there are no artifacts providing such action, the action fails. if more than one artifact is found, artifacts created by the agent itself are considered first. 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.
  • In case of operation invocation with specification of a target artifact: This is done by adding the annotation [artifact_id(Id)], where Id must be bound to the artifact identifier. Alternatively, the annotation [artifact_name(Name)] can be used, where Name must be bound to the logic name of the artifact.
  • In case of operation invocation with specification of the target workspace: done by adding the annotation [wsp_id(WspID)], where WspID must be bound to the wsp identifier.

Making agents work in workspaces

  • By default an agent, when launched, joins the default workspace on current node.
  • 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.
  • Agents can join workspaces that are hosted on remote nodes, by means of a joinRemoteWorkspace action. As soon as the join succeed, the interaction within remote workspaces is the same as local workspace.
  • Infrastructure options:
    • by default, Jason programs using CArtAgO environment create a standalone CArtAgO node, i.e. not accessible through the network
    • To install a CArtAgO node accessible also to remote agents further parameters can be specified to the c4jason.CartagoEnvironment:
      • c4jason.CartagoEnvironment("infrastructure"{,WspName, protocol(ProtName, Address), …}): installs an infrastructure layer specifying the protocols to support and the local address where to start the service;
      • c4jason.CartagoEnvironment("remote"{,WspName, protocol(ProtName, Address), …}): does not install any node – agents directly join the specified remote workspace;
      • c4jason.CartagoEnvironment("local"{,WspName}): does not install any node – agents directly join the specified locak workspace.

Joining workspaces and using Artifacts

  • In the workspace running on the server, a very simple artifact, called "env" has been deployed. This artifact will be enriched step by step with actions and observable properties.
  • The first version of this artifact has one action "printMsg(String msg)". This action prints the parameter "msg" on the standard output adding the name of the emitter of this message
  • On the server, the "majordomo" agent creates the workspace and the artifact, and leaves a message
"majordomo" agent code:

!setup_and_monitor.

+!setup_and_monitor
        <-      createWorkspace("server");
                joinWorkspace("server",Id);
                !setupArtifacts.
                
+!setupArtifacts
        <- makeArtifact("env","easss.step1.Env",[]);
           printMsg("ready. Your turn!").

Exercise A: execution of a MAS acting on a simple artifact for leaving a message in different workspaces

  • Download the code for this step and install it in your eclipse workspace as jason projects.
  • Look at the code of the "guest_agent": it joins the remote workspace and leaves one message. Add an action in the plan of this agent so that the "guest_agent" leaves a message consisting of your name.
  • Launch your MAS client as soon as you see the message from the "majordomo" agent.

Note

  • You can execute this exercise in group where one member of the group launches the "server" and the other members of the group launch their "guest_agent" that joins this remote workspace.
  • You can use the internal action ".my_name(Name)" to get the name of the agent, the internal action ".concat(str1,str2,Result)" to concat str1 to str2 in Result.

Exercise B: test of a MAS acting on a more complex artifact for leaving a message in different workspaces

  • Download the code for this step and install it in your eclipse workspace as jason projects.
  • The artifact "env" running on the server has been changed. Its action "printMsg(String msg)" has an effect on a GUI version now.
  • Reuse the "guest_agent" that you have developed in the previous exercise and launch your MAS client as soon as the "majordomo" agent invites you to do so.

Observing Artifacts

  • On the server, the artifact "env" has been enriched with an observable property showing the number of messages left so far.

Exercise: execution of a MAS for "observing" artifacts situated in the environment

  • Download the code for this step and install it in your eclipse workspace as jason projects.
  • Look at the code of the "guest_agent": it joins the workspace and leaves a message for ever. Adapt this agent so that it leaves a message corresponding to the room ID in which you are situated.
  • Look at the code of the "observer" agent aiming at observing the "env" artifact. The "observer" agent joins the remote workspace, lookups for the artifact "env", focuses on this artifact and gets the value of the "numMsg" observable property of this artifact.
  • Launch your MAS client as soon as the "majordomo" agent invites you to do so.

Computing with Artifacts

  • The artifact "env" has been enriched with a "computePi" action (with output parameters "OpFeedbackParams")

Exercise: development of your first agent for computing

  • Download the code for this step and install it in your eclipse workspace as jason projects.
  • Write your first Jason Agent "YOURNAME_agent" with code for joining the remote workspace, using this "computePi" action. After computing PI, the agent prints the value and your name using the action "printMsg"
  • Modify the "main.mas2j" file for launching this new agent
  • Launch your MAS client as soon as the "majordomo" agent invites you to do so.

Some hints on debugging Environment Programs

  • Coming Soon

Coordination with the help of the artifact

  • The "env" artifact has been enriched to install mutual exclusion in the actions for leaving messages. It has a private attribute "locked" and two operations "lock" and "unlock" insuring the mutual exclusion. The multiple agents that will be launched in the system will use these actions to access in an exclusive way to the artifact and print the messages in sequence.
  • The "observer" agent in the client MAS, joins the workspace, lookups for the artifact "env", focuses on the artifact "env" and gets the value of the "numMsg" observable property.

Exercise: "let's coordinate - Don't interfere!"

  • Download the code for this step and install it in your eclipse workspace as jason projects.
  • Develop your own Jason Agent "YOURNAME_agent" based on the "guest_agent" code so that your agent leaves three messages in sequence.
  • Launch your MAS as soon as the "majordomo" agent invites you to do so.
  • Transform your Jason Agent using the "lock" and "unlock" operations to leave three messages in sequence in a synchronized way.
  • Relaunch your MAS client.

Coordination again by the way of artifact

  • The "env" artifact has been enriched with a synchronisation operation "sync" and with the possibility to setup a number of participants for the synchronization "setupBarrier".
  • The "majordomo" agent has been enriched to setup the barrier in the "env" artifact.
majordomo agent code:

!setup_and_monitor.

+!setup_and_monitor
        <- createWorkspace("server");
           joinWorkspace("server",Id);
           !setupArtifacts;
           setupBarrier(3).
                
+!setupArtifacts
        <- makeArtifact("env","easss.step5.Env",[]);
           printMsg("ready. Your turn!"). 

Exercise: Synchronization by the way of an artifact

  • Download the code for this step and install it in your eclipse workspace as jason projects.
  • Write a "YOURNAME_agent" writing 5 messages in sequence and then use the synchronisation between all agents provided by the artifact operation "sync"

Note

  • You can do this exercise using a common env server and connecting the agents developed by different students.

Modularity / Instances of Artifacts

With the previous implementation, we had a monolithic "env" artifact. It could cause some problems, for instance, if adding a long-term action such as computePi. A better way could be to decompose the "env" in multiple artifacts (types and instances). Let's do a little bit of software engineering.

For this step:

  • the artifact "env" has been refactored and decomposed into "msg_console", "calculator", "lock", "barrier"

Exercise: Using a world of artifacts

  • Download the code for this step and install it in your eclipse workspace as jason projects.
  • Add in the "YOURNAME_agent" the code for using these artifacts.

Creating a Counter Artifact

In this step, you are going to create your own artifacts building a simple counting world example. In this world, counter agents and observer agents are situated in the default workspace and use counting artifacts.

  • The "Counter" artifact is a simple artifact composed of a "count" observable property initialized to 0 when the artifact is created. The artifact has a single operation "inc" without any parameters. This operation increments "count" and sends a "tick" signal every time it is executed by an agent.
  • The "observer" agent:
    • sends a message to the "ticker" agent and starts focusing on this artifact, as soon as it receives a message telling it the name of the counter artifact that has been created "artifact_counter_is(Name)".
    • stops focusing on the artifact as soon as the observable property "count" is equal to 6.
    • prints a message "observed new value" with the value, each time the observable property is changed.
    • prints a message "/perceived a tick in /" with the name of the artifact in which a tick has been done.
// Agent observer code
/* Initial beliefs and rules */

/* Initial goals */
!observe.

/* Plans */ 

+!observe : true 
<-      println("Observer starting to work");
        lookupArtifact("counter",Count);
        +myTool(Count); 
        focus(Count).
...
  • The "ticker" agent:
    • creates the "counter" artifact and tells to all the agents that are in the MAS the name of this artifact ("tell", "artifact_counter_is(counter)"),
    • starts to use this artifact to increment the value of the counter as soon as it receives an answer of an agent
    • Being a lazy agent, it rests for a while (let's say 100 ticks), after each increment. It does this job for 100 cycles. Every time, it increments the artifact and prints a message.
// Agent ticker code
/* Initial beliefs and rules */

/* Initial goals */
!setup.

/* Plans */

+!setup : true <- 
        !setupCounter(Id);
        +counter(Id);
        !increment.

+!increment : ready[source(Ag)] & counter(Id) <-
        for (.range(I,1,100)) {
                .wait(100);
                inc[artifact_id(Id)];
                .print("incrementing");
        }.
        
+!increment : not ready[source(Ag)] <-
        !increment.
        
+!setupCounter(C) : true <-
        makeArtifact("counter","easss.step7.Counter",[],C);
        .broadcast(tell,artifact_counter_is(counter)).

Exercise: Counter Artifact

  • Download the code for this step and install it in your eclipse workspace as jason projects.
  • Write the code of the "Counter" artifact type.
  • Write the code of the "observer" agent (see template above)

Creating a Bounded Counter Artifact

In this step, we are going to extend the previous simple counting world example. Keeping the same agents, the "Counter" artifact will be transformed into a "bounded" counter artifact, i.e. its observable property "count" cannot be higher than a maximum value fixed at the initialisation. The artifact generates a failure signal when its action "inc" is no more possible.

Handling failure

  • The failed primitive is used to specify the failure of an operation:
failed(String failureMsg)
failed(String failureMsg, String descr, Object... args)
  • An action feedback is generated, reporting a failure msg and optionally also a tuple descr(Object…) describing the failure.
  • The annotation that you can use in the agent code, is a follows:
[error_msg(Msg),env_failure_reason(inc_failed("max_value_reached",Value))]

Exercise: Bounded Counter Artifact

  • Create a Jason project called "step8".
  • Reuse the code of the previous step and install it in "step8"
  • Change the code of the "Counter" artifact type, so that it behaves as described above
  • Change the code of the "ticker" agent so that it executes a plan in case of failure of the action "inc"

Going deeper in the use of Cartago


Olivier Boissier, Rafael Bordini, Jomi Hubner, Alessandro Ricci, June 2014