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:
- Left-click on the File menu at the top left corner of the screen.
- Left-click on New Project.
- A New Project File dialog box will appear.
- Name the project file PaintRobot and click on the New button. The project file suffix (.prj) will be added automatically.
- The New Project File dialog box will close and return the user to the JDE screen.
- In the top left corner of the browser window, the name of the new project will appear in red text.
4. We will now develop our application using the design tool. In this application we will develop the following types of diagrams:
- A top level agent diagram which includes the details of messages sent/handled by an agent.
- An agent-capability hierarchy diagram for each agent.
- A Data-Event-Plan (DEP) diagram for each capability.
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.
- To access the design tool, right-click on the Design Views folder in the JDE. A pop-up menu will appear.
- Select Add New Design View from the menu. A pop-up dialog box will appear requesting a name for the design diagram.
- Give the design a name (Robot_AD) and click on the Add New button.
- The design tool canvas will appear. Left-click on the Open design palette button on the design tool menu bar.
- Drag the Agent icon from the design tool palette to the design tool canvas.
- Fill in the pop-up dialog box with details of the Robot agent. Make sure that the Robot agent is in a package called robot. Click on the Add New button. (The agent will now be displayed in the browser in the Agent Types folder inside the Agent Model.)
- You can choose to be in either Selection mode or Link mode. To enter Selection mode, click the Change to selection mode button on the design tool tool bar (the Change to selection mode button displays an arrow icon). In Selection mode, you can click on entities on the canvas and change their location on the diagram. Selected entities or links can also be removed by first selecting them, then pressing the Delete selected objects button. The Delete selected objects button is the button displaying a cross icon. To enter Link mode, click on the Change to link mode button (the Change to link mode button displays a diagonal line). In Link mode you can make connections between the entities on your diagram. Note that the direction of a link is significant.
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.
- Click on the Tools menu and select Compiler Utility from the drop-down menu.
- Click on the Compile Application tab and click the Compile button. If there are any errors, they can be viewed in the Output/Errors tab in the Compiler Utility.
- When you have successfully compiled the application, click on the Run Application tab in the Compiler Utility. Click on Program.class from the contents window and then click on the Select File button. The Run button can then be selected to start running the program.
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.
- If necessary, open the Robot_AD canvas by right-clicking on Robot_AD in the Design Views folder and selecting Edit "Robot_AD" from the pop-up menu.
- Drag an event from the design palette onto the canvas.
- Fill in the pop-up dialog box with details of the Paint event. Make sure that the Paint event is in the robot package.
- Click on the Add New button. (The event will now be displayed in the browser in the Event Types folder inside the Agent Model.)
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:
- Extend BDIGoalEvent;
- Contain a String data member(field) called colour (this is the information that will be carried with the event); and
- Include a posting method, paint(String c). The parameter c is to be assigned to the event data member colour inside the posting method. The completed Paint event follows:
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
- modify the #posts event Paint declaration so that it becomes:
#posts event Paint pev;
- modify the paintPart() method in the Robot agent so that it uses the postEventAndWait() method to post a Paint event with the colour "white" as follows:
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:
- check that the reference to the Paint event handled by the plan is ev
- add the following statement to the plan's body reasoning method:
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.
- Identify the plans which handle the event type.
- Use the relevant() method to check additional information regarding the event.
- Use the context() method to check information stored as part of the agent's beliefs.
- 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.
- Add a link from the Robot agent to the new plan.
- Add a link from the Paint event to the new plan. Your design diagram should be similar to the following 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
- 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:
- create a link from the Paint event to the plan
- create a link from the Robot agent to the plan
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:
- contain a paintColour member of type String with initial value black (this stores the colour currently being used by the robot); and
- contain a method setColour(String colour) that changes paintColour to colour.
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:
- check that it has the following declaration with ev used as the reference to the event:
#handles event Paint ev;
- modify the relevant() method to check that the Paint event's colour is a non-empty string;
- add a #uses interface Robot self declaration so that it can access the robot's setColour method to change the colour;
- invoke the setColour method to change the robot's paintColour to the colour requested by the Paint event. This must be invoked inside the plan's body() method before the 'painting' begins; and
- print the string "Painting part the requested colour: "+self.paintColour using an appropriate print statement inside the body() method of the plan. This message should appear twice, indicating that the part received two coats of paint.
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.
- add a #uses interface Robot self declaration so that it can access the robot's setColour method to change the colour;
- modify the context() method to test the agent's current paintColour as follows:
context() { self.paintColour.equals(ev.colour); }
- change the print statement in body() to
System.out.println("Painting part the current colour "+ self.paintColour);
-
This will make it easier to distinguish between the alternative plans in the program output.
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
- Drag a new capability from the design palette onto the new canvas. Call this new capability Painting and add it to the robot package.
- Drag the three painting plans from the browser onto the Painting_DEP design diagram.
- Drag the Paint event from the browser onto the Painting_DEP design diagram.
- Create links from the Painting capability icon to each of the plans.
- Create a handles link from the Paint event to the Painting capability.
- The diagram becomes quite cluttered if we keep the capability on its DEP diagram. It is useful to have it on the diagram to make the links and to check the links. However, when this task is complete, the capability icon can be removed from the diagram without changing the links. This is achieved by using the design tool in Selection mode, selecting the capability icon on the canvas and then selecting the Remove selected objects from diagram button. Use this procedure to remove the capability from the Painting_DEP design diagram. Your Painting_DEP diagram should be similar to the following diagram.
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:
- deleting the uses links between the Robot agent and each of the painting plans on the Robot_AD design diagram. Take care that you do not delete the link that corresponds to the #uses interface Robot self declaration in each of the plans. An alternative mechanism for removing the links from the Robot to the plans is to edit the Robot type definition using the Edit as JACK File option.
- deleting the handles link between the Paint event and the Robot agent on the Robot_AD design diagram.
- removing the components no longer required on the Robot_AD design diagram (i.e. remove the three painting plans from the design diagram). Your Robot_AD diagram should be similar to the following diagram:
Figure 7: The Robot_AD design diagram with the Robot agent and Paint event
- creating a new design canvas called Robot_cap_hier, dragging the Robot agent and Painting capability onto the new design diagram, then creating a has link from the Robot agent to the Painting capability. The Robot_cap_hier should appear similar to the following diagram:
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
- Drag a new agent from the design palette onto the new canvas. Name the new agent type Part and add it to a new part package.
- Drag a new event from the design palette onto the Part_AD design diagram. Name the new event type PaintRequest and add it to the part package.
- On the design canvas, create a posts link from the Part agent to the PaintRequest event.
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
- Drag the Part agent from the browser onto the Part_cap_hier canvas.
- Drag a new capability from the design palette onto the Part-cap_hier canvas. The new capability is called PaintRequesting and must be added to the part package.
- Create a has link from the Part agent to the PaintRequesting capability.
4. Create a new diagram called PaintRequesting_DEP and
- Drag a new plan from the design palette onto the new PaintRequesting_DEP canvas. This plan is called SendPaintCommand and is to be included in the part package.
- Drag the PaintRequest event from the browser onto the PaintRequesting_DEP canvas.
- Drag the Paint event from the browser onto the PaintRequesting_DEP canvas.
- Create a handles link from the PaintRequest event to the SendPaintCommand plan on the PaintRequesting_DEP design diagram.
- Create a sends link from the SendPaintCommand plan to the Paint event on the PaintRequesting_DEP design diagram. Note that it will be necessary to double-click on the link and change it from the default posts link to a sends link.
- Drag the PaintRequesting capability from the browser onto the PaintRequesting_DEP design diagram. We will only have this on the diagram while we create/check the required links between the capability and its components, otherwise the design diagram will become too cluttered. While the capability is on the canvas, create the following links:
- a uses link from the PaintRequesting capability to the SendPaintCommand plan.
- a handles link from the PaintRequest event to the PaintRequesting capability
- a sends event from the PaintRequesting capability to the Paint event.
- Remove the PaintRequesting capability from the diagram. Note that the capability and the newly created links still remain in the browser. (If you were to drag the capability back onto the design diagram, you would see the links on the diagram.) Your PaintRequesting_DEP diagram should be similar to the following design diagram:
Figure 10: The PaintReqesting_DEP design diagram
5. Edit the PaintRequest event as follows. The event must
- Be a BDIGoalEvent;
- Have two members:
String robot; // The name of robot agent to receive the // paint request. String colour; // The colour to paint the part.
- Have a posting method request(String r, String c). Inside the posting method, the parameter r should be assigned to the event data member robot, and the parameter c should be assigned to the event data member colour.
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:
- Change the name of the PaintRequest event being handled by the plan to preqev.
- Change the reference to the Paint event type in the sends declaration to pev.
- The body of this plan must use the @send reasoning statement to send a Paint event to preqev.robot using the Paint event's paint() posting method. preqev.colour is passed as the argument to the paint() posting method. The send statement to be included in the body is therefore:
@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:
- Creates a part agent as well as a robot agent;
- Invokes the part's submitPaintRequest(), with the name of the robot and the required colour (instead of invoking the now defunct paintPart() method). The code should contain tests similar to the following:
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");
- Includes an import part.Part; statement.
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
- 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).
- 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
- 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.
- 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.
- 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
- 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.
- 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.
- 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.
- Save the project.
- 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.
- 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.
- Open the Data Model container.
- Right-click on the External Classes folder and select Add New External Class.
- In the pop-up window that appears enter Semaphore as the name of the external class and enter aos.jack.util.thread as the package.
- Click on the Add New button.
- In the Agent Model container, right-click on the Named Data folder and select Add New Named Data from the menu.
- In the pop-up window enter mutex as the name of the data and select aos.jack.util.thread.Semaphore as its type.
- Click on the Add New button.
2. Open the Painting_DEP design diagram and
- Remove the sends links from the three 'painting' plans to the Finished event.
- Drag a new plan from the design palette onto the Painting_DEP design diagram canvas. The new plan is called ProcessPaintRequest and is to be part of the robot package.
- Create a new link from the ProcessPaintRequest event to the Finished event.
- Drag a new event from the design palette onto the Painting_DEP design diagram canvas. The new event is to be called StartPainting and is to be part of the robot package.
- Remove the links between the Paint event and the three 'paint' plans.
- Create a new link from the Paint event to the ProcessPaintRequest plan.
- Create a posts event link from the ProcessPaintRequest plan to the StartPainting event.
- Create handles links from the StartPainting event to each of the three 'painting' plans.
- Drag the mutex named data onto the canvas.
- Create a link from the ProcessPaintRequest plan to the mutex named data.
- Drag the Painting capability onto the Painting_DEP design diagram.
- Create the following links:
- A uses link from the Painting capability to the ProcessPaintRequest plan.
- A handles link from the StartPainting event to the Painting capability.
- A posts link from the Painting capability to the StartPainting event.
- A #private link from the Painting capability to the mutex data.
- Remove the Painting capability from the Painting_DEP design diagram. Your Painting_DEP should be similar to the following diagram:
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:
- Extends BDIGoalEvent.
- Has a String member colour and a String member from.
- Has a posting method called startPainting:
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:
- Edit the declarations at the beginning of the plan to use the following event references:
#handles event Paint pev; #posts event StartPainting spev; #sends event Finished fev;
- Edit the body of the plan. This plan waits until it owns the semaphore before it subtasks the appropriate 'painting' plan to paint the part. When the 'painting' subtask is complete, the ProcessPaintRequest plan must send a Finished event back to the part. In addition, when the subtask is complete, this plan must release the semaphore. The body should therefore be as follows:
@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
- Drag a new plan from the design palette onto the PaintRequesting_DEP design diagram canvas. The new plan is to be called DisplayFinished and is to be part of the part package.
- Create a handles link from the Finished event to the DisplayFinished plan.
- Drag the PaintRequesting capability onto the PaintRequesting_DEP design diagram canvas.
- Create the following links:
- A uses link from the PaintRequesting capability to the DisplayFinished plan.
- A handles link from the Finished event to the PaintRequesting capability.
- Remove the PaintRequesting capability from the PaintRequesting_DEP design diagram. Your PaintRequesting_DEP diagram should be similar to the following:
Figure 14: The PaintReqesting_DEP design diagram with the DisplayFinished plan and Finished event
9. Edit the DisplayFinished plan and
- modify the #handles declaration to use fev as the reference to the Finished event handled by the plan.
- Add a #uses interface Part self; declaration.
- Add the details to the body of the plan. All that this plan needs to do is to display a message to indicate that the part has been painted a particular colour. It should contain a print statement similar to the following:
System.out.println(self.name()+" has been painted " +fev.colour);
-
where fev is the reference to the Finished event handled by the plan.
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.