Exercise 1

Set up a Bill of Materials (BOM) beliefset.

Introduction

In this exercise you will create a simplified BOM beliefset to be used within a Planner agent. A BOM is a data structure used in manufacturing to describe the component/subcomponent structure of part assemblies. In this tutorial, the BOM will only capture the component/subcomponent structure: in practice, it will contain much more information, such as the number of a particular component that is required, whether the component is made internally or is outsourced etc.

You will also create a main program to read BOM data provided by the user. This information will be stored in a JACK beliefset which is private to the Planner agent. An alternative mechanism for initialising the beliefset is to use a JACOB file. This alternative is used in Exercise 5.

Instructions

1. Create a directory called practical2/ex1. In this directory, start the JDE and open a new project called BOM.

2. Create a beliefset type called BOM:


      package bom;

      public beliefset BOM extends OpenWorld {
          #key field String component;
          #key field String subcomponent;
          #indexed query getSubcomponent(String component,
                                  logical String subcomponent);
      }

3. We will now use the design tool to define an agent, Planner, that will store component/subcomponent tuples in a private beliefset of type BOM:

4. The beliefset will be populated at agent construction time. Consequently the agent's constructor will be passed two strings – the agent's name and the name of a file containing component-subcomponent details. The constructor must read each component-subcomponent relation from the file, and add the information to the agent's BOM beliefset. The code to achieve this can be added to the agent by using the browser to edit the agent as a JACK file. Sample code for the constructor follows:

   public Planner(String name, String  filename)
   {
      super(name);

      StringTokenizer tokens;
      String record;
      String t1,t2;
      BufferedReader datafile = null;

      try {
         datafile = new BufferedReader(new FileReader(filename));
      }
      catch (FileNotFoundException e) {
         System.err.println("unable to open file "+e.toString());
         System.exit(1);
      }

      try {
         while ((record = datafile.readLine())!=null) {
            tokens = new StringTokenizer(record);
            t1 = tokens.nextToken();
            t2 = tokens.nextToken();
            bom.add(t1,t2);
         }
      }

      catch (Exception e) {
         System.err.println("error reading bom data into beliefset");
         System.exit(1);
      }
   }

Make sure that the Planner agent has the following import statements:

   import java.io.*;
   import java.util.*;

5. Add a new file called Program.java to the Other Files folder in the browser. It will create a Planner agent, perhaps as follows:

   import java.io.*;
   import bom.Planner;

   public class Program {
      public static void main( String args[] )
      {
         Planner planner = new Planner("planner1","bom.dat");
         System.exit(0);
      }
   }

If you wish to run the project from within the JDE make sure that you use the full pathname for bom.dat.

6. Create the file bom.dat and populate it with component/subcomponent records. It could contain:

   chair back
   chair seat
   chair leg
   chair arm
   table top
   table leg
   cupboard door
   cupboard drawer
   cupboard leg
   cupboard cabinet

7. Compile and run the program. No output is generated by the program at this stage, but it provides the basis for the remaining exercises.


Exercise 2

Use the indexed query to find a component's subcomponents.

Introduction

This step involves the use of indexed queries and a plan with a context() method to print out one of the subcomponents of a component. Initially we use a BDIGoalEvent so that only the first successful applicable plan is executed. This means that if we post only one event (e.g. find a subcomponent of component X), the first plan to have a context that finds a binding for a subcomponent of X will be executed. In that case we will only find (at most) one subcomponent.

Instructions

1. Open the Planner_AD design diagram and

2. In the Planner_AD design diagram:

3. Edit the FindSubcomponent event so that it:

4. Edit the FindSubcomponentPlan plan so that it

         System.out.println($subcomp.getValue()+" is a subcomponent of "
                            +ev.component);

5. Modify the Planner agent so that it contains a findSubcomponent(String component) method which will post a FindSubcomponent event using postEventAndWait().

6. Modify the main program so that it makes several invocations of the Planner agent's findSubcomponent() method with the name of a component that is in the agent's BOM beliefset. Ensure that for at least one of the invocations the component is composed of several subcomponent types.

7. Compile and run the program.

Questions

1. Why aren't all the component's subcomponents printed out?


Exercise 3

Use the InferenceGoalEvent class instead of BDIGoalEvent.

Introduction

In this example, you will use an InferenceGoalEvent instead of the BDIGoalEvent. This illustrates two concepts. The first is the difference between these two types of event (i.e. the InferenceGoalEvent will cause all applicable plans to be executed). Secondly, it shows that there is a separate plan instance generated in the applicable set for each of the possible bindings in the context method. This means that in this example we will see all the subcomponents being printed. A separate plan instance will be responsible for printing the message about each subcomponent.

Instructions

1. Modify the FindSubcomponent event so that it is an InferenceGoalEvent and not a BDIGoalEvent.

2. Compile and test the program. The tests should involve at least one component which is composed of four or more subcomponents.


Exercise 4

Use a beliefset callback method.

Introduction

In this exercise you add an order beliefset to your Planner agent and use a beliefset callback method to post a FindSubcomponent event to the agent. This will result in a list of subcomponents being printed for the required new component.

Instructions

1. Use the JDE to create a new beliefset type called Orders that belongs to the bom package. It will have one key field (String orderId) and three non-key fields (String component, int numberRequired, String date). Add at least one query to the beliefset.

2. Open the Planner_AD design diagram and

3. Modify the Planner agent so that it contains a new method addOrder(String orderId, String component, int numberRequired, String dueDate) that will add a new order into the orders beliefset. Note that the add() method may throw a BeliefSetException, so add must be invoked from inside a try/catch block. You will also need to import aos.jack.jak.beliefset.BeliefSetException. Your addOrder() method should be similar to the following:

    public void addOrder(String id, String comp, int n, String dd)
    {
         try {
            orders.add(id,comp,n,dd);
         }
         catch (BeliefSetException e) {
            System.err.println("error entering data in orders db");
            System.exit(1);
         }
    }

4. Edit the Orders beliefset type and

5. Modify the main program so that it:

   import java.util.*;
       StringTokenizer tokens;
       String record;
       String t1,t2,t3,t4;
       BufferedReader datafile = null;
       Planner planner = new Planner("planner1","bom.dat");

       try {
          datafile = new BufferedReader(new FileReader("orders.dat"));
       }
       catch (FileNotFoundException e) {
          System.err.println("unable to open file "+e.toString());
          System.exit(1);
       }

       try {
          while ( (record = datafile.readLine()) != null ) {
             tokens = new StringTokenizer(record);
             t1 = tokens.nextToken();
             t2 = tokens.nextToken();
             t3 = tokens.nextToken();
             t4 = tokens.nextToken();
             planner.addOrder(t1,t2,Integer.parseInt(t3),t4);
          }
       }
       catch (Exception e) {
          System.err.println("error reading orders data ");
          System.exit(1);
       }

6. Create a data file that contains several orders. At least one order should be for a component that has four or more subcomponents.

7. Compile and run the program.


Exercise 5

Use a JACOB initialisation file to initialise the BOM beliefset.

Introduction

In this exercise, you will modify the Planner agent's constructor so that it no longer reads the data from the text file used in the earlier exercises. Instead, you will create a file in JACOB ASCII format that is read in either when the beliefset is constructed, or by using the beliefset read method in the agent's constructor.

Instructions

1. Edit the Planner.agent and remove the code to read the BOM data from the filename passed into the constructor.

2. Modify the #private data BOM bom() declaration so that the filename is now passed to the BOM constructor (#private data BOM bom("bom.dat")).

3. Edit the file bom.dat so that it contains the data in JACOB ASCII format. An example data file is shown below.

   <TupleTable
      :tuples(
         <BOM__Tuple
            :component "table"
            :subcomponent "leg"
         >
         <BOM__Tuple
            :component "table"
            :subcomponent "table_top"
         >
      )
   >

4. Compile and run the program.

5. It is also possible to explicitly invoke the beliefset's read method to read data in JACOB ASCII format. This means that the filename can then be passed as a parameter to the agent's constructor.

 bom.read(filename);