Skip to content

Instantly share code, notes, and snippets.

@dnmfarrell
Created February 7, 2025 18:24
Show Gist options
  • Save dnmfarrell/919c9f3a1c24b6ac9bec332d2b046587 to your computer and use it in GitHub Desktop.
Save dnmfarrell/919c9f3a1c24b6ac9bec332d2b046587 to your computer and use it in GitHub Desktop.
A layered meta-interpreter which handles disjunction, cut, negation and more.
% Explaining Prolog Based Expert Systems Using a Layered Meta-interpreter
% Leon Sterling and L. Umit Yalcinalp
% https://www.ijcai.org/Proceedings/89-1/Papers/011.pdf
%
% GOAL LAYER
solve_goal(Goal,Result) :-
copy_term(Goal,Copy),
solve_branch(Copy,Branch_Result),
(Branch_Result = commit -> !;true),
filter_failure(Branch_Result,Result,Goal,Copy).
solve_goal(_,no).
filter_failure(yes,yes,Goal,Goal).
filter_failure(commit,commit,Goal,_) :-
non_singular(Goal),!.
filter_failure(commit,no,_,_). % for single goals
filter_failure(no,_,_,_) :- fail.
% BRANCH LAYER
solve_branch(true,yes) :- !.
solve_branch((A,B),Result) :- !, % A and B
solve_goal(A,RA),
solve_branch_and(RA,A,Result,B).
solve_branch((A->B;C),Result) :-
solve_goal(A,ResultA),!,
solve_branch_if(ResultA,Result,B,C).
solve_branch((A->B),Result) :-
solve_goal(A,ResultA),!,
solve_branch_if_one(ResultA,Result,B).
solve_branch((A;B),Result) :- !, % A or B
solve_goal(A,RA),
solve_branch_or(RA,Result,B).
solve_branch(\+ Goal,Result) :-
solve_goal(Goal,Result_Not),!,
invert(Result_Not,Result).
solve_branch(findall(X,P,L),Result) :-
findall(X-R,solve_goal(R,P),AList),
eliminate(Result,AList,L).
solve_branch(!,yes).
solve_branch(!,commit) :- !.
solve_branch(A,Result) :-
sys(A),A,Result = yes.
solve_branch(A,Result) :-
sys(A),Result = no,!.
solve_branch(A,no) :-
\+ clause(A,_),!.
solve_branch(A,Result) :-
clause(A,Body),
solve_goal(Body,Result).
% these are undefined in the paper
%solve_branch(A,Result) :-
% askable(A),
% investigate_goal(A,Result).
invert(yes,no).
invert(no,yes).
% HANDLING CONJUNCTION
solve_branch_and(yes,!,Result,B) :- !,
solve_goal(B,ResultB),
((ResultB = no; ResultB = commit) ->
Result = commit; Result = yes).
solve_branch_and(yes,_,Result,B) :- !,
% when A is not a cut
solve_goal(B,Result).
solve_branch_and(no,_,no,_).
% HANDLING DISJUNCTION
solve_branch_or(yes,yes,_) :- !.
solve_branch_or(no,Result,B) :- !,
solve_goal(B,Result).
solve_branch_or(commit,commit,_) :- !.
% HANDLING IF BRANCHES
solve_branch_if_one(yes,Result,B) :- !,
solve_goal(B,Result).
solve_branch_if_one(NoResult,NoResult,_) :-
(NoResult = commit ; NoResult = no),!.
solve_branch_if(yes,Result,B,_) :- !,
solve_goal(B,Result).
solve_branch_if(no,Result,_,C) :- !,
solve_goal(C,Result).
solve_branch_if(commit,commit,_,_) :- !.
sys(A) :-
predicate_property(A,built_in).
% N.B. non_singular/1 is described, but not implemented in the paper
non_singular((_;_)).
non_singular((_,_)).
non_singular((_->_)).
non_singular((_->_;_)).
non_singular((!)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment