Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

pl:prolog:pllib:shell [2019/06/27 15:50] (aktualna)
Linia 1: Linia 1:
 +====== Shell ======
 +{{tag>​expert_systems expert_shell}}
 +===== Description =====
 +An expert system shell.
 +
 +**Source**: ​ PROLOG programming for artificial intelligence,​ 3rd Edition, Harlow, 2001, ISBN 0-201-40375-7.
 +===== Download =====
 +Program source code: {{shell.pl}}
 +===== Listing =====
 +<code prolog>
 +%  Figures 16.6, 16.7, 16.8, 16.9 combined, with small improvements
 +
 +
 +%  An expert system shell
 +
 +
 +:-  op( 900, xfx, ::).
 +:-  op( 800, xfx, was).
 +:-  op( 870, fx, if).
 +:-  op( 880, xfx, then).
 +:-  op( 550, xfy, or).
 +:-  op( 540, xfy, and).
 +:-  op( 300, fx, '​derived by').
 +:-  op( 600, xfx, from).
 +:-  op( 600, xfx, by).
 +:-  op( 900, fy, not).
 +
 +% Program assumes built-in operator: op( 700, xfx, is)
 +
 +% Top-level driving procedure
 +
 +expert ​ :-
 +  getquestion( Question), ​      % Input user's question
 +  ( answeryes( Question);​ % Try to find positive answer
 +    answerno( Question) ). % If no positive answer then find negative
 +
 +answeryes( Question) ​ :- % Look for positive answers to Question
 +  markstatus( negative), % No positive answer yet
 +  explore( Question, [], Answer), ​      % Trace is empty
 +  positive( Answer), ​                   % Look for positive answers
 +  markstatus( positive),​ % Positive answer found
 +  present( Answer), nl,
 +  write('​More solutions? '​), ​
 +  getreply( Reply), % Read user's reply
 +  Reply = no.            % Otherwise backtrack to '​explore'​
 +
 +answerno( Question) ​ :- % Look for negative answer to question
 +  retract( no_positive_answer_yet),​ !,  % Has there been no positive answer?
 +  explore( Question, [], Answer),
 +  negative( Answer),
 +  present( Answer), nl,
 +  write('​More negative solutions? '​), ​
 +  getreply( Reply),
 +  Reply = no. % Otherwise backtrack to '​explore'​
 +
 +markstatus( negative) ​ :-
 +  assert( no_positive_answer_yet).
 +
 +markstatus( positive) ​ :-
 +  retract( no_positive_answer_yet),​ !; true.
 +
 +getquestion( Question) ​ :-
 +  nl, write( '​Question,​ please '),
 +  nl,
 +  read( Question).
 +
 +
 +% explore( Goal, Trace, Answer):
 +%   find Answer to a given Goal. Trace is a chain of ancestor
 +%   goals and rules. ​
 +%   '​explore'​ tends to find a positive answer to a question.
 +%   ​Answer is '​false'​ only when all the possibilities have been
 +%   ​investigated and they all resulted in '​false'​
 +
 +
 +explore( Goal, Trace, _)  :-
 +  copy_term( Goal, Copy), % Make copy of Goal with variables renamed
 +  member( Copy by Rule, Trace), % Similar ancestor goal?
 +  instance_of( Copy, Goal), ​   % Ancestor goal as general as Goal?
 +  !, fail. % Abandon Goal because of cycle!
 +
 +explore( Goal, Trace, Goal is true was 'found as a fact'​) ​ :-
 +  fact :: Goal.
 +
 +explore( Goal, Trace,​  ​              % Assume only one rule about each type of goal
 +    Goal is TruthValue was '​derived by' Rule from Answer) ​ :-
 +  Rule :: if Condition then Goal,      % Rule relevant to Goal
 +  explore( Condition, [Goal by Rule | Trace], Answer),
 +  truth( Answer, TruthValue).
 +
 +explore( Goal1 and Goal2, Trace, Answer) ​ :-  !,
 +  explore( Goal1, Trace, Answer1),
 +  continue( Answer1, Goal1 and Goal2, Trace, Answer).
 +
 +explore( Goal1 or Goal2, Trace, Answer) ​ :-
 +  exploreyes( Goal1, Trace, Answer) ​         % Positive answer to Goal1
 +  ;
 +  exploreyes( Goal2, Trace, Answer). ​        % Positive answer to Goal2
 +
 +explore( Goal1 or Goal2, Trace, Answer1 and Answer2) ​ :-  !,
 +  not exploreyes( Goal1, Trace, _),
 +  not exploreyes( Goal2, Trace, _),          % No positive answer
 +  explore( Goal1, Trace, Answer1),      % Answer1 must be negative
 +  explore( Goal2, Trace, Answer2). ​          % Answer2 must be negative
 +
 +
 +explore( not Goal, Trace, Answer) ​ :-  !,    % Assuming no variables in Goal
 +  explore( Goal, Trace, Answer1),
 +  invert( Answer1, Answer).
 +
 +explore( Goal, Trace, Goal is Answer was told)  :-
 +  useranswer( Goal, Trace, Answer). ​                % User-supplied answer
 +
 +exploreyes( Goal, Trace, Answer) ​ :-
 +  explore( Goal, Trace, Answer),
 +  positive( Answer).
 +
 +continue( Answer1, Goal1 and Goal2, Trace, Answer) ​ :-
 +  positive( Answer1),
 +  explore( Goal2, Trace, Answer2),
 +  (  positive( Answer2), Answer = Answer1 and Answer2
 +     ;
 +     ​negative( Answer2), Answer = Answer2 ).
 +
 +continue( Answer1, Goal1 and Goal2, _, Answer1) ​ :-
 +  negative( Answer1).
 +
 +truth( Question is TruthValue was Found, TruthValue) ​ :-  !.
 +
 +truth( Answer1 and Answer2, TruthValue) ​ :-
 +  truth( Answer1, true),
 +  truth( Answer2, true), !,
 +  TruthValue = true
 +  ;
 +  TruthValue = false.
 +
 +positive( Answer) ​ :-
 +  truth( Answer, true).
 +
 +negative( Answer) ​ :-
 +  truth( Answer, false).
 +
 +
 +invert( Quest is true was Found, (not Quest) is false was Found).
 +
 +invert( Quest is false was Found, (not Quest) is true was Found).
 +
 +instantiated( Term)  :-
 +  numbervars( Term, 0, 0).    % No variables in Term
 +
 +
 +% useranswer( Goal, Trace, Answer):
 +%   ​Generate,​ through backtracking,​ user-supplied solutions to Goal.
 +%   Trace is a chain of ancestor goals and rules used for '​why'​ explanation
 +
 +useranswer( Goal, Trace, Answer) ​ :-
 +  askable( Goal, _),                    % May be asked of the user
 +  freshcopy( Goal, Copy), ​              % Variables in Goal renamed
 +  useranswer( Goal, Copy, Trace, Answer, 1).
 +
 +% Do not ask again about an instantiated goal
 +
 +useranswer( Goal, _, _, _, N)  :-
 +  N > 1,             % Repeated question?
 +  instantiated( Goal), !,
 +  fail.  ​                   % Do not ask again
 +
 +% Is Goal implied true or false for all instantiations?​
 +
 +useranswer( Goal, Copy, _, Answer, _)  :-
 +  wastold( Copy, Answer, _),
 +  instance_of( Copy, Goal), !.     % Answer to Goal implied
 +
 +
 +% Retrieve known solutions, indexed from N on, for Goal.
 +
 +useranswer( Goal, _, _, true, N)  :-
 +  wastold( Goal, true, M),
 +  M >= N.
 +
 +% Has everything already been said about Goal?
 +
 +useranswer( Goal, Copy, _, Answer, N)  :-
 +  end_answers( Copy),
 +  instance_of( Copy, Goal), !,     % Everything was already said about Goal
 +  not wastold( Goal, _, _),        % There was no explicit answer
 +  Answer = false. ​                 % It follows Answer must be negative
 +
 +% Ask the user for (more) solutions
 +
 +useranswer( Goal, _, Trace, Answer, N)  :-
 +  askuser( Goal, Trace, Answer, N).
 +
 +askuser( Goal, Trace, Answer, N)  :-
 +  askable( Goal, ExternFormat),​
 +  format( Goal, ExternFormat,​ Question, [], Variables), ​   % Get question format
 +  ask( Goal, Question, Variables, Trace, Answer, N).
 +
 +ask( Goal, Question, Variables, Trace, Answer, N)  :-
 +  nl,
 +  (  Variables = [], !,              % Introduce question
 +     ​write( 'Is it true: ')
 +     ;
 +     ​write( 'Any (more) solution to: '​) ​
 +  ),
 +  write( Question), write('?​ '​), ​
 +  getreply( Reply), !,                       % Reply = yes/no/why
 +  process( Reply, Goal, Question, Variables, Trace, Answer, N).
 +
 +
 +process( why, Goal, Question, Variables, Trace, Answer, N)  :-
 +  showtrace( Trace),
 +  ask( Goal, Question, Variables, Trace, Answer, N).
 +
 +process( yes, Goal, _, Variables, Trace, true, N)  :-
 +  nextindex( Next), ​                         % Get new free index for '​wastold'​
 +  Next1 is Next + 1,
 +  (  askvars( Variables),
 +     ​assertz( wastold( Goal, true, Next)) ​             % Record solution
 +     ;
 +     ​copy_term( Goal, Copy), ​                          % Copy of Goal
 +     ​useranswer( Goal, Copy, Trace, Answer, Next1) ).  % More answers?
 +
 +process( no, Goal, _, _, _, false, N)  :-
 +  freshcopy( Goal, Copy),
 +  wastold( Copy, true, _), !,               % '​no'​ means: no more solutions
 +  assertz( end_answers( Goal)), ​            % Mark end of answers
 +  fail
 +  ;
 +  nextindex( Next), ​                        % Next free index for '​wastold'​
 +  assertz( wastold( Goal, false, Next)). ​   % '​no'​ means: no solution
 +
 +
 +format( Var, Name, Name, Vars, [Var/​Name|Vars]) ​ :-
 +  var( Var), !.
 +
 +format( Atom, Name, Atom, Vars, Vars)  :-
 +  atomic( Atom), ​ !,
 +  atomic( Name).
 +
 +format( Goal, Form, Question, Vars0, Vars)  :-
 +  Goal =.. [Functor|Args1],​
 +  Form =.. [Functor|Forms],​
 +  formatall( Args1, Forms, Args2, Vars0, Vars),
 +  Question =.. [Functor|Args2],​ !.
 +
 +% If formatting failed due to structural difference format Goal after itself
 +
 +format( Goal, _, Question, Vars0, Vars)  :-
 +  format( Goal, Goal, Question, Vars0, Vars).
 +
 +formatall( [], [], [], Vars, Vars).
 +
 +formatall( [X|XL], [F|FL], [Q|QL], Vars0, Vars)  :-
 +  formatall( XL, FL, QL, Vars0, Vars1),
 +  format( X, F, Q, Vars1, Vars).
 +
 +askvars( []).
 +
 +askvars( [Variable/​Name|Variables]) ​ :-
 +  nl, write( Name), write( ' = '​), ​
 +  read( Variable),
 +  askvars( Variables).
 +
 +showtrace([]) ​ :-
 +  nl, write('​This was your question'​),​ nl.
 +
 +showtrace( [Goal by Rule | Trace]) ​ :-
 +  nl, write( 'To investigate,​ by '),
 +  write( Rule), write( ', '),
 +  write( Goal),
 +  showtrace( Trace).
 +
 +% instance-of( T1, T2) means: instance of T1 is T2; that is
 +% term T1 is more general than T2 or equally general as T2
 +
 +instance_of( Term, Term1) ​ :- % Instance of Term is Term1
 +  copy_term( Term1, Term2), % Copy of Term1 with fresh set of variables
 +  numbervars( Term2, 0, _), !,
 +  Term = Term2. ​                % This succeeds if Term1 is instance of Term
 +
 +freshcopy( Term, FreshTerm) ​ :- % Make a copy of Term with variables renamed
 +  asserta( copy( Term)),
 +  retract( copy( FreshTerm)),​ !.
 +
 +
 +nextindex( Next)  :-            % Next free index for '​wastold'​
 +  retract( lastindex( Last)), !,
 +  Next is Last + 1,
 +  assert( lastindex( Next)).
 +
 +% Initialise dynamic procedures lastindex/​1,​ wastold/3, end_answers/​1
 +
 +:- assert( lastindex( 0)),
 +   ​assert( wastold( dummy, false, 0)),
 +   ​assert( end_answers( dummy)).
 +
 +% Displaying the conclusion of a consultation and '​how'​ explanation
 +
 +present( Answer) ​ :-
 +  nl, showconclusion( Answer),
 +  nl, write( 'Would you like to see how?'​),​
 +  nl, 
 +  getreply( Reply),
 +  ( Reply = yes, !, show( Answer)
 +    ;
 +    true ).
 +
 +showconclusion( Answer1 and Answer2) ​ :-  !,
 +  showconclusion( Answer1), write( ' and '),
 +  showconclusion( Answer2).
 +
 +showconclusion( Conclusion was Found) ​ :-
 +  write( Conclusion).
 +
 +% '​show'​ displays a complete soltuin tree
 +
 +show( Solution) ​ :-
 +  nl, show( Solution, 0), !.            % Indent by 0
 +
 +show( Answer1 and Answer2, H)  :-  !,   % Indent by H
 +  show( Answer1, H),
 +  tab( H), write(and), nl,
 +  show( Answer2, H).
 +
 +show( Answer was Found, H)  :-          % Indent by H
 +  tab( H), writeans( Answer), ​          % Show conclusion
 +  nl, tab( H),
 +  write( ' ​ was '),
 +  show1( Found, H).                     % Show evidence
 +
 +show1( Derived from Answer, H)  :-  !,
 +  write( Derived), write('​ from'​), ​     % Show rule name
 +  nl, H1 is H + 4,
 +  show( Answer, H1).                    % Show antecedent
 +
 +show1( Found, _)  :-                    % Found = '​told'​ or 'found as fact'
 +  write( Found), nl.
 +
 +writeans( Goal is true)  :-  !,
 +  write( Goal).  ​               % Omit 'is true' on output
 +
 +writeans( Answer) ​ :-                   % This is negative answer
 +  write( Answer).
 +
 +means( why, why)  :-  !.
 +means( w,   ​why) ​ :-  !.
 +
 +means( yes, yes)  :-  !.
 +means( y,   ​yes) ​ :-  !.
 +
 +means( no,  no)   :​- ​ !.
 +means( n,   ​no) ​  :​- ​ !.
 +
 +% Note: getreply should not be called with the argument instantiated
 +
 +getreply( Meaning) ​ :-
 +  read( Reply),
 +  means( Reply, Meaning), ​ !;          % Reply means something?
 +  nl, write('​Answer unknown, try again please!'​), ​    % Handle bad reply
 +  nl, 
 +  getreply( Meaning). ​                 % Try again
 +
 +
 +member( X, [X|_]).
 +
 +member( X, [_|L]) ​ :-
 +  member( X, L).
 +
 +numbervars( Term, N, Nplus1) ​ :-
 +  var( Term), !,                      % Variable?
 +  Term = var/N,
 +  Nplus1 is N + 1.
 +
 +numbervars( Term, N, M)  :-
 +  Term =.. [Functor | Args], ​         % Structure or atomic
 +  numberargs( Args, N, M).
 +
 +numberargs( [], N, N)  :-  !.
 +
 +numberargs( [X | L], N, M)  :-
 +  numbervars( X, N, N1),
 +  numberargs( L, N1, M).
 +
 +</​code>​
 +===== Comments =====
  
pl/prolog/pllib/shell.txt · ostatnio zmienione: 2019/06/27 15:50 (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