oops.pl

% OOPS2 - A toy production system interpreter.  It uses a forward chaining,
%        data driven, rule based approach for expert system development.
%
% Version 2, the simplest version without LEX, MEA, or conflict sets
%
% author Dennis Merritt
% Copyright (c) Dennis Merritt, 1986
 
 
% fixed for SWI Prolog by GJN 12.2005
%%%%%%%%%  To start program write main. or uncomment the last line in this file %%%%%%%%%%%%%%%%%%%%%
:- write('********To start program write main.**********').
 
info(X):-
   jpl_datums_to_array(X,Q),
   jpl_new('miw2.Info',[Q],_).
 
readF(File):-
				jpl_new('miw2.PlFileChooser',[],F),
				jpl_call(F,getFile,[],File).
 
control(X,Buttons):-
            repeat,
			jpl_datums_to_array(Buttons,B),
            jpl_new('miw2.ControlForm',[X,B],F),
			jpl_call(F,getValue,[],V),
			change(V,Z),
			doit(Z),
			Z = exit.
 
change(0,load).
change(1,list).			
change(2,go).
 
% operator definitions
 
:-op(800,xfx,==>).          % used to separate LHS and RHS of rule
:-op(500,xfy,:).            % used to separate attributes and values
:-op(810,fx,rule).          % used to define rule
:-op(700,xfy,#).            % used for unification instead of =
 
main :- welcome, write_help.
 
welcome:-
	info(['OOPS - A Toy Production System',
	'This is an interpreter for files containing rules coded in the',
	'OOPS format.']).
 
write_help :-
	control('Commands:\n
load -  prompts for name of rules file enclose in single quotes\n
list -  lists working memory\n
go   -  starts the inference\n
exit -  does what you\'d expect',['load','list','go']).
 
% the supervisor, uses a repeat fail loop to read and process commands
% from the user
 
supervisor :-
	repeat,
	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 all which match the pattern
do(_) :- info(['invalid command!']),nl,write_help.
 
% loads the rules (Prolog terms) into the Prolog database
 
load :-
	readF(F),
	consult(F).            % loads a rule file into interpreter work space
 
% 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).
 
% 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 :-
	call(rule ID: LHS ==> RHS),
	try(LHS,RHS),
	info(['Rule fired ',ID]),
	!,go.
go.
 
% find the current conflict set.
 
% conflict_set(CS) :-
%	bagof(rule ID: LHS ==> RHS,
%		[rule ID: LHS ==> RHS, match(LHS)],CS).
 
% match the LHS against working storage, if it succeeds process the
% actions from the RHS
 
try(LHS,RHS) :-
	match(LHS),
	process(RHS,LHS),!.
 
% recursively go through the LHS list, matching conditions against
% working storage
 
match([]) :- !.
match([_:Prem|Rest]) :-
	!,
	(fact(Prem);
	 test(Prem)),          % a comparison test rather than a fact
	match(Rest).
match([Prem|Rest]) :-
	(fact(Prem);    % condition number not specified
	 test(Prem)),
	match(Rest).
 
% various tests allowed on the LHS
 
test(not(X)) :-
	fact(X),
	!,fail.
test(not(_)) :- !.
test(X#Y) :- X=Y,!.
test(X>Y) :- X>Y,!.
test(X>=Y) :- X>=Y,!.
test(X<Y) :- X<Y,!.
test(X=<Y) :- X=<Y,!.
test(X = Y) :- X is Y,!.
test(member(X,Y)) :- member(X,Y),!.
 
% recursively execute each of the actions in the RHS list
 
process([],_) :- !.
process([Action|Rest],LHS) :-
	take(Action,LHS),
	!,process(Rest,LHS).
 
% if its retract, use the reference numbers stored in the Lrefs list,
% otherwise just take the action
 
take(retract(N),LHS) :-
	(N == all; integer(N)),
	retr(N,LHS),!.
take(A,_) :-take(A),!.
 
take(retract(X)) :- retract(fact(X)), !.
take(assert(X)) :- asserta(fact(X)),write(adding-X),info([{X}]),nl,!.
take(X # Y) :- X=Y,!.
take(X = Y) :- X is Y,!.
take(write(X)) :- write(X),!.
take(nl) :- nl,!.
take(read(X)) :- read(X),!.
take(prompt(X,Y)) :- nl,write(X),read(Y),!.
take(member(X,Y)) :- member(X,Y), !.
take(list(X)) :- lst(X), !.
 
% logic for retraction
 
retr(all,LHS) :-retrall(LHS),!.
retr(N,[]) :-write('retract error, no '-N),nl,!.
retr(N,[N:Prem|_]) :- retract(fact(Prem)),!.
retr(N,[_|Rest]) :- !,retr(N,Rest).
 
retrall([]).
retrall([_:Prem|Rest]) :-
	retract(fact(Prem)),
	!, retrall(Rest).
retrall([Prem|Rest]) :-
	retract(fact(Prem)),
	!, retrall(Rest).
retrall([_|Rest]) :-		% must have been a test
	retrall(Rest).
 
% list all of the terms in working storage
 
lst :-
	fact(X),
	info([{X}]),nl,
	fail.
lst :- !.
 
% lists all of the terms which match the pattern
 
lst(X) :-
	fact(X),
	info([{X}]),nl,
	fail.
lst(_) :- !.
 
% utilities
 
member(X,[X|_]).
member(X,[_|Z]) :- member(X,Z).
 
:-dynamic(fact/1).
 
% :- main.
pl/miw/miw08_ruleruntimeg/oops.txt · ostatnio zmienione: 2017/07/17 08:08 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0