Source Code: Robbie the Robot

ROBBIE.KSL Listing

/*
    Robbie the Robot Example - Phil Vasey and Alan Westwood february 1999
    =====================================================================

    This example demonstrates the use of forward-chaining in a
    configuration and resource allocation problem.

    Description
    -----------
    This example implements a shopping expert system. The problem is in
    three distinct stages:

      1. Query the user to get the initial shopping list.
      2. Check the compatibility of the items on the shopping list.
      3. Pack the items on the shopping list into bags.

    Running the Example
    -------------------
    The top-level goal to run the expert system is run/0. This can
    be invoked by entering the following goal:

    ?- run.

    Flex Technical Points
    ---------------------
    The following flex technical points are demonstrated in this example:

    1. Data-driven launch procedure.

    2. The use of synonyms and templates

    3. The use of nested groups

*/

% the text "choose a carrier X for Y" is mapped on to choose_bag( X, Y )

template choose_bag
  choose a carrier ^ for ^ .

template pack_item
  pack ^ .

% the following action is the backbone of the expert system
% the three stages are clearly defined

action run ;
  do  restart

  and init_gensym( bag_number_ )
  and write( '<h3>Asking for the initial shopping list<//h3>' )

  and ask shopping
  and display_shopping( initial )

  and write( '<h3>Checking the compatibility of items<//h3>')

  and invoke ruleset checking_rules
  and display_shopping( final )

  and write( '<h3>Packing the items into bags<//h3>' )

  and invoke ruleset packing_rules
  and display_bags .


% the following actions display information of various kinds

action write_nl( Message )
  do  nl
  and write( Message )
  and nl .


action display_shopping( Stage )
  do  write( 'The shopping list at the <em>' )
  and write( Stage )
  and write( '<//em> stage is ...' )
  and write( '<ul>' )
  and for all member( Item, shopping )
      do write( '<li>' )
         and write( Item )
         and write( '<//li>' )
      end for
  and write( '<//ul>' ) .

% the nested for loops in the following action display every bag
% and every item in each bag

action display_bags
  do nl
  and for every Bag is some carrier
     do  write( '<h3>The contents of carrier ' )
     and write( Bag )
     and write( ' is<//h3>' )
         and for every Item is included in the contents of Bag
            do write( Item )
            and tab( 1 )
         end for
     end for .


action display_new_bag( Bag )
  do  write( '<p><em>I Need a new carrier : ' )
  and write( Bag )
  and write( '<//em><//p>' ) .


action display_packed_item( Item, Bag )
  do  write( 'Packing ' )
  and write( Item )
  and write( ' into ' )
  and write( Bag )
  and write( '<br>' ) .


% the word large_maximum is replaced by 1 wherever it occurs in the file

synonym large_maximum 1 .

synonym items_maximum 3 .


% a frame and a launch procedure define the carrier bags

frame carrier
  default contents are empty .


% the launch procedure creates and then reports a new carrier bag

launch new_carrier
  when Bag is a new carrier
  then display_new_bag( Bag ) .


% this action makes use of the choose_bag and pack_item templates to make
% the action easier to read

action pack an Item ;
  do  choose a carrier Bag for the Item
  and remove the Item from the shopping
  and include the Item in the Bag`s contents
  and display_packed_item( Item, Bag ) .


% this relation either selects a currently used bag or creates a new one

relation choose a carrier Bag for an Item
  if  the Bag is some carrier
  and length( the Bag`s contents, Count )
  and if   the Item`s size is large
      then Count is less than the large_maximum
      else Count is less than the items_maximum
      end if
  and ! .


relation choose a carrier Bag for an Item
  if  gensym( bag_number_, Bag )
  and Bag is a new carrier .


% the goods group also includes the drink and nibbles groups

group goods
  bread, butter, coffee, ice_cream, nibbles, drink, washing_powder .


group drink
  beer, lemonade .


group nibbles
  crisps, salted_peanuts .


% this section defines the characteristics of the items on the shopping

frame item .


frame large_item is an item ;
  default size is large .


frame medium_item is an item ;
  default size is medium .


frame small_item is an item ;
  default size is small .


frame bread is a medium_item
  default container is a plastic_bag and
  default condition is fresh .


frame butter is a small_item
  default container is a plastic_carton and
  default condition is fresh .


frame coffee is a medium_item
  default container is a jar and
  default condition is freeze_dried .


frame ice_cream is a medium_item
  default container is a cardboard_carton and
  default condition is frozen .


frame crisps is a small_item
  default container is a plastic_bag and
  default condition is fragile .


frame salted_peanuts is a small_item
  default container is a plastic_bag and
  default condition is salted .


frame beer is a large_item
  default container is a bottle and
  default condition is liquid .


frame lemonade is a large_item
  default container is a bottle and
  default condition is liquid .


frame washing_powder is a large_item
  default container is a cardboard_carton and
  default condition is powder .


% this section defines the questions used in the expert system

question shopping
  What is on your shopping list today ? ;
  choose some of goods
  because I need to check your shopping and then pack it into bags .

frame shopping_style ;
   default prefill is { crisps, butter } and
   default rows is 4 .

question drink
  You must select a drink ! ;
  choose one of drink
  because There are nibbles on your shopping list .

frame drink_style ;
  default method is radio and
  default infix is br and
  default rows is 4 and
  default prefill is lemonade .

% this ruleset defines the forward chaining checking phase
% successful rules are removed after they are fired

ruleset checking_rules contains
    check_nibbles,
    check_bread_and_butter,
    check_butter_and_bread ;
    update ruleset by removing each selected rule .


rule check_nibbles
  if the shopping includes X and X is some nibbles
  and  the shopping does not include some drink
  then ask drink
  and  include the drink in the shopping
  because Nibbles make you thirsty .


rule check_bread_and_butter
  if   the shopping includes bread
  and  the shopping does not include butter
  then include butter in the shopping
  and  write( '<p>You forgot the butter!<//p>' )
  because Bread is very dry by itself .


rule check_butter_and_bread
  if   the shopping includes butter
  and  the shopping does not include bread
  then include bread in the shopping
  and  write( '<p>You forgot the bread!<//p>' )
  because What is the use of butter without bread .


% this ruleset defines the forward chaining packing phase
% rules that do not apply are removed

ruleset packing_rules contains
    pack_frozen_item,
    pack_large_bottle,
    pack_other_large_item,
    pack_medium_item,
    pack_small_item ;
  update ruleset by removing any unsatisfied rules .


rule pack_frozen_item
  if   the shopping includes an Item
  and  the Item`s condition is frozen
  then pack the Item .


rule pack_large_bottle
  if   the shopping includes an Item
  and  the Item`s container is bottle
  and  the Item`s size is large
  then pack the Item .


rule pack_other_large_item
  if   the shopping includes an Item
  and  the Item`s size is large
  then pack the Item .


rule pack_medium_item
  if   the shopping includes an Item
  and  the Item`s size is medium
  then pack the Item .


rule pack_small_item
  if   the shopping includes an Item
  and  the Item`s size is small
  then pack the Item .