Exercise 1

Make a basic robot agent that contains a Java method that prints a message to indicate that the robot is painting a part.

Introduction

The aim of this exercise is to demonstrate how to build, compile and run a JACK program using the JACK Development Environment (JDE). Consequently, no agent-oriented programming concepts other than agent creation are involved.


Note: The practicals will make use of the design tool to produce design diagrams and to create initial skeleton type definitions for the application. The JDE supports multiple ways to add detail to the type definitions. However, to avoid confusion during the practicals we will always use the Edit as JACK File option to add type definition details.

Instructions

1. Make sure that CLASSPATH is set to include jack.jar and the root path for your application.

2. In a new directory (called ex1) start the JDE using the following command:

   java -Xmx90m aos.main.Jack

3. Create a new project as follows:

4. We will now develop our application using the design tool. In this application we will develop the following types of diagrams:

Note that when we add new components to a design diagram, the skeleton for the type definition is automatically created and added to the browser. Links created between components on the design canvas result in the corresponding declarations being added to the type definitions in the browser. Removing a link from a design diagram removes the link from the underlying model and the change will be reflected in the browser. Removing a component from the design diagram does not remove it from the underlying model. It will still exist in the browser and can be dragged back on to the design canvas to view its relationships with other components in the diagram.

5. Create the top level agent diagram using the design tool.

6. In the browser, edit the Robot agent by right-clicking on the robot agent and selecting Edit as JACK file. Add a Java method called paintPart() that contains the statement

System.out.println("Painting part now").

Close the robot agent file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the robot agent file, click the Save button and then the Close button.

7. Use the browser to add the main program. This is added in the Other Files folder at the top level of the browser hierarchy. Right-click on the Other Files folder and select Add New File from the pop-up menu. Add the code for the main program in the Edit File window which appears. Save the main program with the name Program.java. The following main program can be used to test the paint robot:

   import robot.Robot;

   public class Program {
      public static void main( String args[] ) {
         Robot robot1 = new Robot("robbie");
         robot1.paintPart();
         System.exit(0);
      }
   }

8. Save the project. This can be achieved by selecting the Save Project option from the File menu in the top left hand corner of the JDE.

The JDE window should look similar to the following:

Figure 1: The JDE window with project browser, Robot_AD design, design palette and Program.java windows

9. Compile and run the program within the JDE.

Figure 2: The Run Application tab of the Compiler Utility


Exercise 2

Extend the robot agent to use a JACK plan.

Introduction

In this exercise, the robot agent's paintPart() method will post a Paint event, thus allowing a plan to be chosen to respond to this event. At this stage we will only have one plan, PaintSpecifiedCurrentColour, which handles the Paint event. The plan will print a message to indicate that the robot is painting a part a particular colour. Note that the plan PaintSpecifiedCurrentColour would be more appropriately named PaintSpecifiedColour at this stage in the practical. However, this plan will be used to paint a part a specified colour which matches the robot's current paint colour in later exercises, and it was felt that it would be less confusing if the name was not changed.

As before, paintPart() is invoked from a Java main() method (and runs on the Java main thread) and is followed by a System.exit(0) call.

Plans and events are described in the Introduction to JACK notes. If necessary, read these before beginning the exercise.

Instructions:

1. Use the design tool to add a Paint event to the application.

2. On the design canvas, create a posts link from the Robot agent to the Paint event. Observe that a declaration is added automatically by the JDE in the External Events folder of the Robot agent.

3. On the design canvas, create a handles link from the Paint event to the Robot agent.

4. Add a PaintSpecifiedCurrentColour plan to the Robot_AD canvas. The plan must also be in the robot package.

5. On the design canvas, create a uses link from the Robot agent to the PaintSpecifiedCurrentColour plan.

6. On the design canvas, create a handles link from the Paint event to the PaintSpecifiedCurrentColour plan. Your design diagram should now be similar to the following diagram:

Figure 3: The Robot_AD design diagram with one plan, PaintSpecifiedCurrentColour

7. In the browser, right-click on the Paint event and select Edit as JACK file from the pop-up menu. Complete the Paint event by making it:


   package robot;

   public event Paint extends BDIGoalEvent {
      public String colour;

      #posted as
      paint(String c)
      {
         colour = c;
      }
   }

Close the file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the file, click the Save button and then the Close button.

8. Using the Edit as a JACK File option, edit the Robot agent and

        #posts event Paint pev;
      postEventAndWait(pev.paint("white"));

Close the file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the file, click the Save button and then the Close button.

9. Using the Edit as a JACK File option edit the PaintSpecifiedCurrentColour plan as follows:

      System.out.println("Painting the part the requested colour: " +
                          ev.colour);

Close the file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the file, click the Save button and then the Close button.

10. Save, compile and run the application.

Questions

1. What would happen if you used postEvent() inside paintPart() instead of postEventAndWait()? Try it!

If you did not observe any difference, add @sleep(2) before the print the statement in the PaintSpecifiedCurrentColour plan. Run the program using postEventAndWait() in the paintPart() method. Replace the postEventAndWait with postEvent() and run the program again. Explain your observations. Remove the @sleep(2) from the plan before you begin the next exercise.

Make sure you change postEvent() back into postEventAndWait() before you begin the next exercise.

2. postEventAndWait() should only be called from the Java main thread or from other Java threads that are external to JACK. While the agent handles this event, the calling thread is blocked and must wait until the agent returns its result. What problem would you envisage if postEventAndWait() was called from an agent task?


Exercise 3

Enable the robot agent to select between multiple plans through relevance.

Introduction

In this example, the agent has two plans that can handle a Paint event: PaintAnyColour and PaintSpecifiedCurrentColour.

The PaintAnyColour plan prints the string "No colour specified. Painting the part."

The PaintSpecifiedCurrentColour plan prints the string "Painting part the requested colour:" followed by the colour that was requested in the Paint event.

Whenever an event is posted and an agent begins a task to handle the event, the first thing that the agent must do is find an applicable plan to handle the event. Note that each plan is only capable of handling a single event type which is identified by the plan's #handles event declaration. It is possible (as in this example) that there is more than one plan capable of handling a particular event type. To decide which of the plans are applicable, JACK employs the following steps.

  1. Identify the plans which handle the event type.
  2. Use the relevant() method to check additional information regarding the event.
  3. Use the context() method to check information stored as part of the agent's beliefs.
  4. If there are still multiple plans left in the applicable plan set, additional means are used to select one of them. At this stage, we will only be considering prominence (or declaration order). For more details, refer to the Agent Manual.

We will be looking at the relevant() method in this example. The PaintSpecifiedCurrentColour plan will contain a relevant() method to ensure that the plan is only selected if there is a colour specified in the colour data member of the Paint event. If a plan does not specify a relevant() method, the plan is relevant for all instances of the event. The relevant() method takes the following form:

   static boolean relevant(EventType eventref)
   {
      // Code to determine when the plan is relevant to this event.
   }

The next level of 'filtering' in plan selection (assuming the plan can handle the event and is relevant for a particular instance of the event) is the context() method. This is discussed in Exercise 4.

Note that the order of plan declarations within the agent (or capability) also has a bearing on plan selection. The order is called prominence, and the most prominent applicable plan will be selected first. This means that if PaintAnyColour is declared before PaintSpecifiedCurrentColour, it will always be the plan selected to handle Paint events as it does not have a relevant() or a context() method associated with it.

Instructions

1. Use the design tool to add a new plan called PaintAnyColour to the Robot_AD design diagram.

Figure 4: The Robot_AD design diagram with the PaintSpecifiedCurrentColour and PaintAnyColour plans

2. Use the Edit as a JACK File option to modify the PaintSpecifiedCurrentColour plan so that its relevant() method performs a test that recognises events with non-empty strings. For example,

   static boolean relevant(Paint ev)
   {
      return (ev.colour != null && ev.colour.length() > 0);
   }

This plan will be used to paint a part the colour that was requested in the colour member of the Paint event. Note that if the robot is not currently painting with the requested colour an alternative plan will be required. We will not write that plan or test for that condition in this exercise – that is deferred until the next exercise.

Close the file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the file, click the Save button and then the Close button.

3. Use Edit as a JACK File to edit the new plan to add the following print statement to its body reasoning method:

   System.out.println("No specified colour. Painting the part");

This is the plan to be used when a Paint event does not include a specific colour request. The colour string will be null or empty. In this case the part will be painted with the colour being used by the robot at the time of the paint request.

Close the file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the file, click the Save button and then the Close button.

4. The #uses plan PaintAnyColour declaration should appear after the PaintSpecifiedCurrentColour plan declaration. Check the order by editing the Robot agent. If necessary swap the declarations via the project browser or by editing the file as a JACK file.

If editing the file as a JACK file, save and close the file before continuing.

5. Edit the Robot and modify its paintPart() method so that it now takes a String argument (the colour) and passes it to the paint posting method.

If editing the file as a JACK file, save and close the file before continuing.

6. Edit the main() method in Program.java, so that the paintPart() method is invoked with the first program argument, if any, and null otherwise. For example:

   robot1.paintPart( (args.length==0) ? null : args[0] );

Save and close the file to apply the changes before continuing.

7. Save the project.

8. Compile and run the program a few times with and without command line arguments. The command line arguments are added in the Extra Args text box of the Compiler Utility's Run Application window.

9. Swap the plan declarations within the agent. Compile and run the program again (with and without command line arguments).

10. Swap the plan declarations back to normal before moving on to Exercise 4.

Questions

  1. How is JACK choosing which plan to use when both plans are applicable?

Exercise 4

Enable the robot agent to select between multiple plans through context, as well as relevance.

Introduction

The context() method provides the next level of 'filtering' after relevant(). If a plan is relevant to a particular event, the context() method determines whether the plan is applicable given the agent's current knowledge. The context() method does not take any arguments and its body is always a single JACK Agent Language logical expression. (JAL logical expressions are composed of boolean members, logical members and beliefset cursor expressions which can, in general, bind to multiple values. Logical expressions and cursors are discussed in more detail in the Agent Manual.) When evaluating the context() method, the agent will consider all possible alternatives. Note that for every possible set of values that can satisfy the context() method, a separate instance of the plan will be generated and will be available for execution. This concept of multiple possible bindings and plan instances is illustrated in the introductory beliefset exercise found in Practical 2.

The context() method takes the following form:

   context()
   {
      // Logical condition to determine which plan instances are
      // applicable (in this example test the value of paintColour).
   }

To illustrate the use of context() in a plan, the robot agent will have a String data member called paintColour, which stores the colour being used.

In this example we will also use

   #uses interface Robot self;

within a plan. This statement gives the plan access to the members and methods in the Robot class interface. In this particular example, it will allow the plan to access the robot's paintColour member (self.paintColour).

Instructions

1. Use the design tool to add a new plan called PaintSpecifiedNewColour to the Robot_AD diagram. This plan is to deal with Paint events that request a specific colour, but which could not be handled by the PaintSpecifiedCurrentColour plan, as the colour requested is not the same as the agent's current paintColour. In the PaintSpecifiedNewColour plan, the agent's paintColour member must first be changed to the new colour. In addition, when the colour changes, it is necessary to give the part two coats of paint to ensure that no trace of the previous colour remains. Use the design tool to add the required links between the plan, the agent and the Paint event as follows:

Your design diagram should be similar to the following diagram:

Figure 5: The Robot_AD design diagram with the PaintSpecifiedCurrentColour, PaintAnyColour and PaintSpecifiedNewColour plans

2. Use Edit as a JACK File to modify the Robot agent to:

Ensure that the plans are declared in the following order:

    #uses plan PaintSpecifiedCurrentColour;
    #uses plan PaintSpecifiedNewColour;
    #uses plan PaintAnyColour;

Close the file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the file, click the Save button and then the Close button.

3. Use the Edit as a JACK File option to make the following changes to the new PaintSpecifiedNewColour plan:

      #handles event Paint ev;

Close the file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the file, click the Save button and then the Close button.

4. Use the Edit as a JACK File option to edit the PaintSpecifiedCurrentColour plan.

      context()
      {
         self.paintColour.equals(ev.colour);
      }
      System.out.println("Painting part the current colour "+
                            self.paintColour);

Close the file to ensure that there are no conflicts between editing the file in the JDE browser and as a JACK file. In the editor window of the file, click the Save button and then the Close button.

5. Modify the PaintAnyColour plan so that it now prints the string "No colour specified. Painting the part" followed by the robot's current paintColour. To access the paintColour member inside the plan, add a #uses interface Robot self declaration at the beginning of the plan.

If editing the file as a JACK file, save and close the file before continuing.

6. Modify the main() method in Program.java so that it no longer passes a command line argument to the paintPart() method but instead invokes the method several times as follows:

      System.out.println("test with red");
      robot1.paintPart("red");     // Should result in two coats.
      System.out.println("test with no specified colour (null)");
      robot1.paintPart(null);      // Should only be one coat –
                                   // slightly different message.
      System.out.println("test with green");
      robot1.paintPart("green");   // Should result in two coats.
      System.out.println("test with green again");
      robot1.paintPart("green");   // Should only be one coat.

Save and close the file to apply the changes before continuing.

7. Save the project.

8. Compile and run the program. Check that the output is correct.


Exercise 5

Illustrate the reposting of events when a plan fails.

Introduction

The way that an agent handles an event depends on the type of event. For example, when a normal event is received by an agent, the agent initiates a task to handle the event. This task involves selecting and executing the first plan that is both relevant and applicable to this event. With normal events the initial selection is the only plan that is executed. In the case of BDI events, the agent can apply more sophisticated reasoning to the plan selection, and can also attempt to achieve its goal using other applicable plans if a plan fails.

This exercise illustrates how a BDIGoalEvent will attempt every applicable plan until it succeeds. It will only fail when no more applicable plan instances remain to be tried. The body() method in a plan is the plan's main reasoning method. It is executed whenever a plan is executed. Reasoning methods do not have the same execution structure as ordinary Java methods. Each statement in a reasoning method is treated like a boolean expression, and each semicolon between statements like an AND connector. This means that if any statement fails, then the reasoning method terminates immediately and fails. In this exercise you can make the plan fail by adding the following statement in its body() method:

   false;

Instructions

1. Modify the PaintSpecifiedNewColour plan so that it prints the painting message once and then fails (add false; after the first print statement). To illustrate that the plan actually stops at that point, add System.out.println("After false statement"); after the false statement. This print statement should not be executed.

If editing the file as a JACK file, save and close the file before continuing.

2. Save the project.

3. Compile and run the program.

4. Add a fail() reasoning method that prints the string "PaintSpecifiedNewColour plan failed".

If editing the file as a JACK file, save and close the file before continuing.

5. Save the project.

6. Compile and run the program.

Questions

1. Which plan is now responsible for printing the second paint message that corresponds to the second coat of paint?


Exercise 6

Provide the robot agent with a Painting capability.

Introduction

The capability concept is a means of structuring reasoning elements of agents into 'clusters' that implement selected reasoning capabilities. This technique simplifies agent system design and allows code reuse and encapsulation of agent functionality. In this example, we encapsulate both the set of plans you have written so far and the Paint event into a Painting capability.

Capabilities are described in the Introduction to JACK notes. If necessary, read through the notes before beginning the exercise.

Instructions

1. Add a new design diagram called Painting_DEP. This will be the DEP diagram for a new Painting capability. Then

Figure 6: The Painting_DEP design diagram with the PaintSpecifiedCurrentColour, PaintAnyColour and PaintSpecifiedNewColour plans

2. Now that the plans and event are encapsulated in the new capability, we should remove the links from the agent to the plans and declare that the Robot agent has the Painting capability. This can be achieved by:

Figure 7: The Robot_AD design diagram with the Robot agent and Paint event

Figure 8: The Robot_cap_hier design diagram with the Robot agent and Painting capability

3. Edit the Painting capability and check that the #uses plan declarations are declared in the the following order:

    #uses plan PaintSpecifiedCurrentColour;
    #uses plan PaintSpecifiedNewColour;
    #uses plan PaintAnyColour;

This is the same order as they were previously declared in the agent declaration. If editing the file as a JACK file, save and close the file before continuing.

4. Save the project.

5. Compile and run the application. Check that the output is correct. It should be similar to the following:

   test with red
   Painting part the requested colour: red
   PaintSpecifiedNewColour plan failed
   painting the part the current colour: red
   test with no specified colour
   No specified colour. Painting the part red
   test with green
   Painting part the requested colour (1st coat) green
   PaintSpecifiedNewColour plan failed
   painting the part the current colour: green
   test with green again
   painting the part the current colour: green

Exercise 7

Create a multi-agent system consisting of a robot agent and a part agent.

Introduction

In this exercise you will create a part agent that interacts with the robot agent. The part agent will have a PaintRequesting capability that will enable it to send painting requests to the robot agent. The part agent will post itself PaintRequest events (by the invocation of a submitPaintRequest() method in the main Java thread). The PaintRequest event will be handled by the part agent's SendPaintCommand plan. The SendPaintCommand plan will send a Paint event to the robot agent.

Note that the Paint event must now be a BDIMessageEvent (a message event is required if the event is to be sent between agents). We will also need to add

   #set behavior Recover repost

to the Paint event. BDI events have a default behaviour that determines what happens with respect to plan reconsideration, applicable plan set recalculation and meta-level reasoning (reasoning about which plan to choose). These default behaviours can be modified by setting behaviour attributes. In this example, we set the recover attribute to repost which means that the event will be reposted on failure. The applicable plan set will be recomputed (with possibly different results/bindings – in this case our failed PaintSpecifiedNewColour plan will have changed the agent's paintColour member) and another applicable plan will be tried. This should become clearer when you run the example.

Instructions

7a – Organise the code into sub-folders in the JDE browser.

Before we begin adding the definitions for our Part agent, we will organise the code so that all the code related to the Robot will be in Robot sub-folders in the JDE browser.

It is useful to organise the project in the browser according to entities that relate to the Robot and entities that relate to the Part. This can be achieved by right-clicking on a folder/container and selecting Add Nested Container. The new nested container can be given an appropriate name (e.g. robot or part). Components can be dragged and dropped into the appropriate nested container (e.g. all the painting plans can be dragged into a nested robot container inside the Plan Types folder).

1. Organise the remainder of the project in the browser so that each folder has a nested robot folder containing the definitions related to the robot. (It is not always clear which package an event should belong to. We generally add them to the package of the agent that can handle the event.)

2. Save the project. The browser window should look similar to the following:

Figure 9: The browser window with the project organised into nested containers

3. Compile and run the application.

7b – Create the Part agent and incorporate it into the application

1. Create a new design diagram called Part_AD and

2. In the browser create a nested container for the Part agent in the Event Types folder. Drag the PaintRequest event into the Part folder. As more components (plans etc.) are added for the Part and Robot, store them in appropriate nested folders in the browser.

3. Create a new design diagram called Part_cap_hier and

4. Create a new diagram called PaintRequesting_DEP and

Figure 10: The PaintReqesting_DEP design diagram

5. Edit the PaintRequest event as follows. The event must

      String robot;     // The name of robot agent to receive the
                        // paint request.
      String colour;    // The colour to paint the part.

If editing the file as a JACK file, save and close the file before continuing.

6. Edit the Part agent and add a submitPaintRequest(String robot, String colour) method that will post a PaintRequest event containing the name of the robot to send the paint request to and the colour that the part is to be painted. Use postEventAndWait() to post the event.

If editing the file as a JACK file, save and close the file before continuing.

7. Edit the SendPaintCommand plan as follows:

         @send(preqev.robot, pev.paint(preqev.colour));

If editing the file as a JACK file, save and close the file before continuing.

8. Edit the Paint event to extend BDIMessageEvent, and set its Recover behaviour attribute to be repost (#set behavior Recover repost).

If editing the file as a JACK file, save and close the file before continuing.

9. Edit the Robot agent and remove the paintPart() method and the #posts event Paint declaration.

If editing the file as a JACK file, save and close the file before continuing.

10. Modify the main() method in Program.java so that it:

      System.out.println("test with red");
      part1.submitPaintRequest("robbie","red");
      System.out.println("test with no specified colour (null)");
      part1.submitPaintRequest("robbie",null);
      System.out.println("test with green");
      part1.submitPaintRequest("robbie","green");
      System.out.println("test with green again");
      part1.submitPaintRequest("robbie","green");

11. Comment out the System.exit(0); statement in Program.java.

Save and close the file to apply the changes before continuing.

12. Save the project.

13. Compile the program.

14. Predict what you would expect to be output by the program. Run the program. Are your predictions correct?

Questions

1. What would happen if you had not added #set behavior Recover repost to the Paint event? Test your prediction by commenting out the #set behavior statement. Why wasn't this required when the Paint event was a BDIGoalEvent?

2. Explain the order of the output statements.


Exercise 8

Make the part/robot messaging protocol two-way and demonstrate the use of the JACK Interaction Diagram.

Introduction

In this exercise the robot agent will send a message to the part agent when it has finished painting the part. The part agent will use a DisplayFinished plan to handle the Finished event and will print a message to indicate that it has been painted.

Instructions

  1. Now that we have illustrated the reposting of events, modify the PaintSpecifiedNewColour plan so that it no longer fails, but instead has two painting print statements (to provide two coats of paint).
  2. Open the PaintRequesting_DEP.
    • drag a new event onto the design diagram. This new event is to be called Finished and is to be in the part package. A Finished event is sent by the robot to indicate that it has finished painting the part the specified colour.
    • Drag a new plan onto the canvas. This new plan is called DisplayFinished and is to be in the part package. The DisplayFinished plan is to handle a Finished event sent to the Part agent by the Robot agent when it has finished painting the part. This will allow us to view the interaction between the agents on the interaction diagram.
    • Create a handles link from the Finished event to the DisplayFinished plan.
    • Drag the PaintRequesting capability from the browser onto the design diagram.
    • Create a uses link from the PaintRequesting capability to the DisplayFinished plan.
    • Create a handles link from the Finished event to the PaintRequesting capability.
    • Remove the PaintRequesting capability from the design diagram. Your PaintRequesting_DEP diagram should be similar to the following:

Figure 11: The PaintReqesting_DEP design diagram with the DisplayFinished plan

  1. Edit the Finished event and complete its definition. It must:
    • extend BDIMessageEvent;
    • have a String data member called colour;
    • have a posting method finished(String c)which assigns c to the colour data member;

As this is a message event, it can display information on an interaction diagram – include the following statement in the posting method

      message = "finished painting " + c;

where c is the colour passed to the posting method and message is the (inherited) String data member that will be displayed on the interaction diagram.

If editing the file as a JACK file, save and close the file before continuing.

  1. Edit the DisplayFinished plan as follows:
    • change the reference for the Finished event to fev
    • add a #uses interface Part self; declaration to the plan
    • add the following print statement to the body reasoning method of the plan:
      System.out.println(self.name() + " has been painted " +
                         fev.colour);

If editing the file as a JACK file, save and close the file before continuing.

  1. Open the Painting_DEP design diagram and
    • Drag the Finished event from the browser onto the canvas.
    • Create a sends link from each of the three painting plans to the Finished event. Remember that the default link type is posts – this will need to be changed to sends.
    • Drag the Painting capability from the browser onto the design diagram and create a sends link from the Painting capability to the Finished event.
    • Remove the Painting capability from the Painting_DEP design diagram. Your diagram should be similar to the following:

Figure 12: The Painting_DEP design diagram

  1. Modify the PaintAnyColour, PaintSpecifiedCurrentColour and PaintSpecifiedNewColour plans so that when they have finished painting a part, they send the part involved a Finished event using:
      @send(ev.from, fev.finished(self.paintColour));

where ev is the reference to the Paint event being handled by the plan, and fev is the reference used in the #sends event Finished fev declaration in the plan. from is an inherited String data member.

If editing the file as a JACK file, save and close the file before continuing.

  1. Edit the Paint event, so that the message member contains information about the paint colour. Inside the posting method assign a String to message, composed of Paint colour plus the colour passed to the posting method. The inherited String data member message will be displayed on the interaction diagram.

If editing the file as a JACK file, save and close the file before continuing.

  1. Modify the main() method in Program.java, so that instead of one part agent there are four. Modify the code so that each submitPaintRequest() is associated with a different part.

Save and close the file to apply the changes before continuing.

  1. Save the project.
  2. Predict what you would expect to be output by the program. Compile and run your program to test your predictions. When all the parts have been painted, press the Stop button to stop the application.
  3. Run the program with the interaction diagram. This is achieved by running the program with -Djack.tracing.idisplay.type=id set in the Java Args text box in the Compiler Utility's Run Application window.

Questions

1. Explain the order of the output from trace statements from the main program and the JACK agents.


Exercise 9

Modify the behaviour of the robot agent so that painting takes a specific period of time to complete.

Introduction

In the previous exercise, parts were painted the requested colours. However, painting only took the amount of time required to print out a statement indicating that the robot was painting the part a particular colour. We will discover some interesting effects if we allow the plans involved to 'sleep' for a short time while the robot paints the part. To achieve this, we use the reasoning method statement @sleep.

The @sleep statement takes the following form:

   @sleep(double timeout);

timeout represents the period of time that the agent must wait before continuing with the plan. The time-out period is specified in 'ticks' on the agent's clock. The actual time depends on the Timer that the agent is using. If the timer is the real-time clock (the default), then it represents a sleep period in seconds.


Note: @sleep only causes the current task to sleep. Any other tasks that the agent is currently executing proceed as normal.

Instructions

1. Modify the 'painting' plans so that they contain an @sleep(5) statement to sleep for 5 seconds after they print the message to indicate that they are painting a part.

If editing the files as JACK files, save and close them before continuing.

2. Save the project.

3. Compile and run the program with the interaction diagram.

Questions

1. How do you explain the output?

2. How can you ensure that the robot does not begin a new task to start painting another part while it is still 'busy'?


Exercise 10

Synchronise the message protocol between the part and the robot.

Introduction

In the previous example, we found that while the robot was painting a part, it was possible for it to receive requests to perform other tasks. If there is nothing in the plans to make them wait until the robot is not busy, the robot may begin a new task and change paintColour before it has finished painting a particular part. There are various schemes you may have thought of to deal with this. Some of them may require features in JACK that we have not yet covered, such as using a beliefset to store the robot state and waiting until the robot is no longer busy before servicing the next request.

In this exercise, we illustrate the use of @reply to set up a protocol between the part and the robot. The part sends the request to the robot, then waits for a reply before continuing to the end of the SendPaintCommand plan. The SendPaintCommand plan is executed in response to the PaintRequest event that is posted using postEventAndWait() inside the submitPaintRequest() method. As it uses postEventAndWait(), the method will not return until the SendPaintCommand plan has completed. This means that the next submitPaintRequest() in the main thread will not be invoked until the part involved in the previous request has received a reply to indicate that it has been painted.

Of course, if any other Paint events are sent to the robot from elsewhere, it is still possible to have the problems we experienced in Exercise 9. In Exercise 11, we will use an alternative solution to avoid this problem.

The @reply statement takes the form:

   @reply(OriginalMessageEvent, ReplyMessageEvent)

The @reply statement is used by an agent to reply to a message that it has received from another agent. It replies to the sending agent with a message event which arrives as a data object on the reply queue of the original message. This is illustrated in the following code fragment:

   // In the part's sending plan.

   plan SendPaintCommand extends Plan
   {
      #sends event Paint pev;
         :
         :

      body()
      {
         // Need to have an instance of the MyMessage event to use
         // with replied() and getReply()
         Paint q = pev.paint(...);

         //Send to robot1
         @send("robot1",q);
         @waitFor(q.replied());

         // Finished is an event defined in your system
         Finished fev = (Finished) q.getReply();

         // Do something with reply
           :
           :
      }
   }

   // In the robot's receiving plan
   plan PaintCurrentColour extends Plan
   {
      #handles event Paint pev;
      #sends event Finished rev;
                :
                :

      body()
      {
                :
                :
         @reply(pev, rev.finished(...));
                :
                :
      }
   }

Note that the message event that is returned using @reply does not trigger a new task or plan.

Instructions

1. Remove the DisplayFinished plan from the project by removing it from the plans folder in the browser. This is achieved by right-clicking on the plan and selecting Remove "DisplayFinished" from the pop-up menu. Note that you also need to remove the #handles external event Finished declaration from the PaintRequesting capability.

2. Modify the SendPaintCommand plan so that after it sends a Paint message to the robot it waits for a reply. When it receives the reply it uses getReply() to access the reply (which will be a Finished event). It must then print a message to indicate that it (the agent name), has been painted a particular colour. The colour is available from the reply (i.e. the Finished event).

If editing the file as a JACK file, save and close the file before continuing.

3. Modify the robot's paint plans, so that when they complete painting a part they use @reply to reply with a Finished event (which conveys the colour that the part was painted). Remove the @send statements that were used to send the Finished event in the earlier exercises.

If editing the file as a JACK file, save and close the file before continuing.

4. Save the project.

5. Compile and run the program with the interaction diagram.


Exercise 11

Use a semaphore to ensure that the robot only attempts to paint one part at a time.

Introduction

In Exercise 10, the main program only sent a new paint request to the robot when the previous part had been painted. This was because the submitPaintRequest methods invoked from the main Java thread used the postEventAndWait method. The submitPaintRequest method did not return until the part had received a reply to indicate that the paint process had been completed. If this was guaranteed to be the only way that paint requests were sent to the robot, no conflict would arise. However, if any other paint requests were sent from the JACK thread, the robot could attempt to paint more than one part at the same time.

An alternative technique to ensure that the robot only attempts to paint one part at a time is to use a semaphore. A semaphore is a synchronisation resource which can be used to establish mutual exclusion regions of processing in JACK plans and threads. A semaphore is a binary resource that plans and threads may wait for and signal on when they have completed. Waiting entities queue on the semaphore and acquire the semaphore in FIFO order.

The semaphore has a single constructor:

   Semaphore()

Methods are provided to grab and release the semaphore. signal() is used to release the semaphore. The semaphore is grabbed initially by the constructing thread (or plan) and must thus be released by a call to signal(). To grab the semaphore from within a plan, use planWait(). The planWait() method returns a special JACK type, the Cursor.

The cursor concept originates from relational databases, where a query can return multiple tuples in the form of a result set. Access to the elements in this set is then provided through a cursor. In JACK, these concepts have been extended to provide cursors which not only operate in the conventional manner but also operate on the temporal evolution of a query. The latter type of cursor is typically used in JACK applications to determine when a particular condition becomes true. Cursors which provide this additional capability within JACK are implemented as triggered cursors. Triggered cursors are not checked using a busy-wait loop – rather, they are only tested when the agent performs a modification action that impacts on the cursor. The cursor returned by the planWait() method is triggered when the semaphore is grabbed by the plan.

This means that a plan can use the @waitFor reasoning statement to wait until the plan has been able to grab the semaphore before it begins painting the part.

In this exercise we introduce a new ProcessPaintRequest plan. This plan can only paint a part when it has the semaphore. If it does not have the semaphore, it must wait until it gets the semaphore before it paints the part.

Instructions

1. Create the named data of type Semaphore that is to be used to prevent the robot from attempting to paint more than one part at a time.

2. Open the Painting_DEP design diagram and

Figure 13: The Painting_DEP design diagram with the ProcessPaintRequest plan, StartPainting event and mutex named data

3. Edit the StartPainting event so that it:

      startPainting(String c, String f)
      {
         colour = c;
         from = f;
      }

If editing the file as a JACK file, save and close the file before continuing.

4. As the semaphore is grabbed initially by the constructing thread, it must also be released by a call to signal(). The #private data Semaphore mutex(); declaration constructs the semaphore in the capability. Painting capability. To release the semaphore after it has been constructed, edit the capability and override its autorun method as follows:

      protected void autorun()
      {
         mutex.signal();
      }

5. Edit the ProcessPaintRequest plan as follows:

      #handles event Paint pev;
      #posts event StartPainting spev;
      #sends event Finished fev;
      @waitFor(mutex.planWait()); // Wait for semaphore (mutex).

      try {
         @subtask(spev.startPainting(pev.colour, pev.from));
         @send(pev.from, fev.finished(pev.colour));
      }
      finally {
         mutex.signal(); // Release semaphore (mutex).
      }

If editing the file as a JACK file, save and close the file before continuing.

6. Use the browser to remove the @reply statements from the three 'painting' plans.

7. Remove the @waitFor reply and associated statements from the Part agent's SendPaintCommand plan.

8. Open the PaintRequesting_DEP design diagram and

Figure 14: The PaintReqesting_DEP design diagram with the DisplayFinished plan and Finished event

9. Edit the DisplayFinished plan and

      System.out.println(self.name()+" has been painted "
                         +fev.colour);

If editing the file as a JACK file, save and close the file before continuing.

10. Save the project.

11. Compile and run the project.