[comp.lang.prolog] Forward chaining rule-based system

christil@BONNIE.ICS.UCI.EDU (05/31/90)

Hi, I'm new to this bboard.  I am programming an inference engine that selects
and applies rules to place furniture in a room.  My room rule base consists of
a number of rules of the sort:
	rule 2:
	  [1:furniture(end,end),
	   2: goal(read_furniture)]
	   ==>
	  [retract(all),
	   assert(goal(read_walls))].

There are a number of rules like the one above which should fire appropriate
rules according to the correct order of placing furniture in a room.  My
inference engine should prompt for the furniture in the room and the size, etc.
It should then select a rule whose left hand side conditions (left of
the "==>") match the current state as stored in the working storage,
the set of facts that have been asserted.  It should then execute the
RHS of that rule and repeat until all rules have been used.  This is what I
have so far:

% operator definitions

:- op(800,xfx,==>).		% used to separate LHS & RHS of rule
:- op(500,xfy,:).		% used to separate attributes & values
:- op(810,fx,rule).		% used to define rules

main :- welcome, supervisor.

welcome :-
  write('OOPS - A Toy Production System'), nl, nl,
  write('This is an interpreter for files containing rules coded in the'), nl,
  write('OOPS format.'), nl, nl,
  write('The => prompt accepts three commands:'), nl, nl,
  write('   load. - prompts for name of rules file'), nl,
  write('   exit. - does what you would expect'), nl,
  write('   go.   - starts the inference'), nl, nl.

/* the supervisor, uses a repeat fail loop to read and process commands
from the user */

supervisor :-
  repeat,
  write('=>'),
  read(X),
  doit(X),
  X == exit.

doit(X) :- do(X).

/*  actions to take based on commands  */

do(exit) :- !.
do(go) :- initialize, go, !.
do(load) :- load, !.
do(list) :- lst, !.		% lists all of working storage
do(list(X)) :- lst(X), !.	% lists match the pattern
do(_) :- write('invalid command').

/* loads the rules (Prolog terms) into the Prolog database */

load :-
  write('File name? '),
  read(F),
  reconsult(F).

/* assert each of the initial conditions into working storage */

initialize :-
  initial_data(X),
  assert_list(X).

/* working storage is represented by database terms stored under the
key "fact" */

assert_list([]) :- !.
assert_list([H|T]) :-
  assertz( fact(H) ),
  !, assert_list(T).

/* list all of the terms in working storage */

lst :-
  fact(X),
  write(X), nl,
  fail.
lst :- !.

/* lists all of the terms which match the pattern */

lst(X) :-
  fact(X),
  write(X), nl,
  fail.
lst(_) :- !.


/*--------------------------------------------------------------------------*/
/* the main inference loop, find a rule and try it.  if it fired, say so
and repeat the process.  if not go back and try the next rule.  when no
rules succeed, stop the inference                                           */
/*--------------------------------------------------------------------------*/

go :-         %inference engine goes here

*******************************************************************************


Can someone help me out or direct me to a book which might contain a
solution to coding the inference engine or reference to the "OOPS"
system shown above?

Note: the "intial_data" that the intialize procedure calls is located
in the room rule base:

initial_data(
  [goal(place_furniture),
  not_end_yet,                                  % not removed until all done
  legal_furniture([couch, chair, table_lamp, end_table,
                   coffee_table, tv, end]),
  opposite(north,south),
  opposite(south,north),
  opposite(east,west),
  opposite(west,east),
  right(north,west),
  right(west,south),
  right(south,east),
  right(east,north),
  left(north,east),
  left(east,south),
  left(south,west),
  left(west,north)]).


Thank you,
--Christine Lee
christil@bonnie.ics.uci.edu