% mpp.pl - A simple meta interpreter with "probabilities"

:- op(1175,xfx,'#').
:- op(1150,xfy,'if').
:- op(1100,xfy,'or').
:- op(1000,xfy,'and').
:- op(900,fy,'~').

:- dynamic 'if'/2.
:- dynamic '#'/2.

demo(true,1) :- !.
demo(false,0) :- !.

demo((P1 and P2),Belief) :- 
  !,
  demo(P1,Belief1),
  demo(P2,Belief2),
  min(Belief1,Belief2,Belief).

demo((P1 or P2),Belief) :- 
  !,
  demo(P1,Belief1),  
  demo(P2,Belief2),
  max(Belief1,Belief2,Belief).

demo(~(P),Belief) :- 
  !,
  demo(P,BeliefNot),
  Belief is 1-BeliefNot.

demo(P,BP) :-  
  \+ (builtin(P)),
  !,
  bagof(B,
        Q^BR^BQ^(pclause(P,Q,BR),
                 demo(Q,BQ),
                 B is BQ*BR),
          BPs),
  cb(BPs,BP).

demo(P,1) :- call(P),!.
demo(_,0).


% succeeds if P is a builtin predicate (i.e., there
% are no pclause rules for P).
builtin(P) :- 
  functor(P,Predicate,Arity),
  functor(P2,Predicate,Arity),
  \+(pclause(P2,_,_)).

% min(N1,N2,N3) true iff N3=min(N1,N2)
min(N1,N2,N1) :- N1<N2,!.
min(N1,N2,N2) :- N1=<N2.

% max(N1,N2,N3) true iff N3=max(N1,N2)
max(N1,N2,N1) :- N1>N2,!.
max(N1,N2,N2) :- N1=<N2.

% cb(L,Belief) combines the Beliefs
% in list L into a single measure: Belief.
cb([],0).
cb([H|T],B) :- 
  cb(T,BT),
  cb1(H,BT,B).

%cb1(B1,B2,B) combines beliefs B1,B2 into B.
cb1(B1,B2,B) :- B is B1+B2*(1-B1).

% pclause(P,_,_) looks for rules and 
% facts for concluding P.

% a weighted rule.
pclause(P,Q,Belief) :- 
  (P if Q # Belief2),
  Belief is Belief2/100.

% a weighted fact.
pclause(P,true,Belief) :- 
  (P # Belief2),
  \+( P = (_ if _)),
  Belief is Belief2/100.

% a rule with implicit weight of 100.
pclause(P,Q,1) :- (P if Q).

