dprove(A,Hs,[A|Hs]) :- hypo(A).
dprove(A,Hs,Hs) :- member(A,Hs).
dprove(A,Hs,Hs) :- fact(A).
dprove(A,Hs,Os) :-
	rule(A,Body),
	dproveall(Body,Hs,Os).
dproveall([],Hs,Hs).
dproveall([A|R],Hs,Os) :-
	dprove(A,Hs,Ms),
	dproveall(R,Ms,Os).

aprove(A,Hs) :- member(A,Hs).
aprove(A,Hs) :- fact(A).
aprove(A,Hs) :-
	rule(A,Body),
	aproveall(Body,Hs).
aproveall([],Hs).
aproveall([A|R],Hs) :-
	aprove(A,Hs),
	aproveall(R,Hs).

inconsistent(H) :-
	conflict(U),
	aproveall(U,H).

explain(R,H) :-
	dproveall(R,[],H),
	\+ inconsistent(H).

member(A,[A|_]).
member(A,[_|R]) :- member(A,R).

hypo(interested_in(_Agent,_Topic)).
hypo(bored(_Agent,_Topics)).

rule(selects(Agent,Article),
	[about(Article,Topics),
	 member(Topic,Topics),
	 interested_in(Agent,Topic)]).
rule(rejects(Agent,Article),
	[about(Article,Topics),
	 bored(Agent,Topics)]).

fact(member(T,[T|_])).
rule(member(T,[_|R]), [member(T,R)]).

conflict([interested_in(Agent,Topic),
	  bored(Agent,Topics),
	  member(Topic,Topics)]).

fact(about(article94,[ai,skiing])).
fact(about(article34,[ai,infobahn])).
fact(about(article57,[ai,cricket])).

% Queries to try:
%
% explain([selects(u,article94)], H).
% explain([selects(u,article94), selects(u,article34)], H).
% explain([selects(u,article94), selects(u,article34), rejects(u,article57)], H).
