1:- module(icl, [on_icl_read/1,
2 explain/1, explain/2, explain/3,
3 op(1060, xfy, '&'),
4 op(900,fy, ~),
5 op(700,xfx, \=),
6 op(1150, xfx, <- ),
7 op(0, fx, (table) ) ]). 127:- op(1060, xfy, '&'). 128:- op(900,fy, ~). 129:- op(700,xfx, \=). 130:- op(1150, xfx, <- ). 135:- dynamic rul/2. 136:- dynamic control/1. 137:- dynamic hypothesis/2. 138:- dynamic nogood/2. 139:- dynamic example_query/1. 140
146clear :-
147 retractall(rul(_,_)),
148 retractall(control(_)),
149 retractall(hypothesis(_,_)),
150 retractall(nogood(_,_)),
151 retractall(done(_,_,_,_,_)).
163(H <- B) :- rule((H :- B)).
164
165rule(H) :- expand_rule_term(H,HH), H \=@=HH, !, rule(HH).
166rule((H :- B)) :- !,
167 assert_if_new(rul(H,B)).
168rule(H) :-
169 assert_if_new(rul(H,true)).
170
171expand_rule_term(H,HH):- expand_term(H,HH), !.
179lemma(_).
194:- op( 500, xfx, : ). 195:- dynamic hypothesis/2. 196random(L) :-
197 probsum(L,T),
198 randomt(L,T).
199probsum([],0).
200probsum([_:P|R],P1) :-
201 probsum(R,P0),
202 P1 is P0+P.
203randomt([],_).
204randomt([H:P|R],T) :-
205 NP is P/T,
206 assertz(hypothesis(H,NP)),
207 make_hyp_disjoint(H,R),
208 randomt(R,T).
209
210time_arg(P, N):-
211 functor(P, F,_),
212 assertz(is_time_arg(F,N)).
213
217make_hyp_disjoint(_,[]).
218make_hyp_disjoint(H,[H2 : _ | R]) :-
219 asserta(nogood(H,H2)),
220 asserta(nogood(H2,H)),
221 make_hyp_disjoint(H,R).
230random(X,H,L) :-
231 repvar(X,X1,H,H1),
232 asserta((nogood(H,H1) :- dif(X,X1))),
233 probsum(L,T),
234 random_each(X,H,L,T).
235random_each(_,_,[],_).
236random_each(X,H,[X:P|_],T) :-
237 NP is P/T,
238 asserta(hypothesis(H,NP)),
239 fail.
240random_each(X,H,[_|R],T) :-
241 random_each(X,H,R,T).
254:- op( 500, xfx, : ). 255controllable([]).
256controllable([H|R]) :-
257 asserta(control(H)),
258 make_cont_disjoint(H,R),
259 controllable(R).
263make_cont_disjoint(_,[]).
264make_cont_disjoint(H,[H2 | R]) :-
265 asserta(nogood(H,H2)),
266 asserta(nogood(H2,H)),
267 make_cont_disjoint(H,R).
286prove(ans(A),C,C,R,R,P,P,ans(A)) :- !,
287 ans(A,C,R, _R , P, _T).
288prove(report_cp,C,C,R,R,P,P,_) :- !,
289 report_cp(C,R,P).
290prove(report_evidence,C,C,R,R,P,P,_) :- !,
291 report_evidence(C,R,P).
296prove(true,C,C,R,R,P,P,true) :- !.
297prove((A & B),C0,C2,R0,R2,P0,P2,(AT & BT)) :- !,
298 prove(A,C0,C1,R0,R1,P0,P1,AT),
299 prove(B,C1,C2,R1,R2,P1,P2,BT).
300prove((A ; _),C0,C2,R0,R2,P0,P2,AT) :-
301 prove(A,C0,C2,R0,R2,P0,P2,AT).
302prove((_ ; B),C0,C2,R0,R2,P0,P2,BT) :-
303 prove(B,C0,C2,R0,R2,P0,P2,BT).
304prove((~ G),C0,C0,R0,R2,P0,P3,if(G,not)) :-
305 findall(R2,prove(G,C0,_,R0,R2,P0,_,_), ExpG),
306 duals(ExpG,R0,[exp(R0,P0)],ADs),
307 make_disjoint(ADs,MDs),
308 ( (tracn(yes); tracn(duals)) ->
309 writeln([' Proved ~ ',G ,', assuming ',R0,'.']) ,
310 writeln([' explanations of ',G,': ',ExpG]),
311 writeln([' duals: ',ADs]),
312 writeln([' disjointed duals: ',MDs])
313 ; true),!,
314 member(exp(R2,P3),MDs).
315prove(H,_,_,R,_,P,_,_) :-
316 tracn(yes),
317 writeln(['Proving: ',H,' assuming: ',R,' prob=',P]),
318 fail.
319prove(H,C,C,R,R,P,P,if(H,assumed)) :-
320 hypothesis(H,_),
321 member(H,R),
322 ( tracn(yes)
323 -> writeln([' Already assumed: ',H ,'.'])
324 ; true).
325prove(H,C,C,R,[H|R],P0,P1,if(H,assumed)) :-
326 hypothesis(H,PH),
327 \+ member(H,R),
328 PH > 0,
329 good(H,R),
330 P1 is P0*PH,
331 ( tracn(yes) -> writeln([' Assuming: ',H ,'.']) ; true).
332prove(H,C,C,R,R,P,P,if(H,given)) :-
333 control(H),member(H,C),!,
334 ( tracn(yes) -> writeln([' Given: ',H,'.']) ; true).
335prove(H,C,C,R,R,P,P,if(H,builtin)) :-
336 builtin(H), call(H).
337prove(A \= B,C,C,R,R,P,P,if(A \= B,builtin)) :-
338 dif(A,B).
339prove(G,C0,C1,R0,R1,P0,P1,if(G,BT)) :-
340 rul(G,B),
341 ( tracn(yes) ->
342 writeln([' Using rule: ',G ,' <- ',B,'.'])
343 ; true),
344 ( debgn(yes) -> deb(G,B) ; true),
345 tprove(G,B,C0,C1,R0,R1,P0,P1,BT),
346 ( tracn(yes) ->
347 writeln([' Proved: ',G ,' assuming ',R1,'.'])
348 ; true).
349prove(H,_,_,R,_,P,_,_) :-
350 tracn(yes),
351 writeln(['Failed: ',H,' assuming: ',R,' prob=',P]),
352 fail.
353tprove(_,B,C0,C1,R0,R1,P0,P1,BT) :-
354 prove(B,C0,C1,R0,R1,P0,P1,BT).
355tprove(G,_,_,_,R,_,P,_,_) :-
356 tracn(yes),
357 writeln([' Retrying: ',G,' assuming: ',R,' prob=',P]),
358 fail.
364:- dynamic builtin/1. 366builtin((_ is _)).
367builtin((_ < _)).
368builtin((_ > _)).
369builtin((_ =< _)).
370builtin((_ >= _)).
371builtin((_ = _)).
372builtin((user_help)).
373
374
378deb(G,B) :-
379 writeln([' Use rule: ',G ,' <- ',B,'? [y, n or off]']),
380 read(A),
381 ( A = y -> true ;
382 A = n -> fail ;
383 A = off -> debug(off) ;
384 true -> writeln(['y= use this rule, n= use another rule, off=debugging off']) ,
385 deb(G,B)
386 ).
387
396duals([],_,D,D).
397duals([S|L],R0,D0,D2) :-
398 split_each(S,R0,D0,[],D1),
399 duals(L,R0,D1,D2).
407split_each(R0,R0,_,D0,D0) :- !.
408split_each([A|R],R0,D0,PDs,D2) :-
409 negs(A,NA),
410 add_to_each(A,NA,D0,PDs,D1),
411 split_each(R,R0,D0,D1,D2).
419add_to_each(_,_,[],D,D).
420add_to_each(A,NA,[exp(E,_)|T],D0,D1) :-
421 member(A,E),!,
422 add_to_each(A,NA,T,D0,D1).
423add_to_each(A,NA,[exp(E,PE)|T],D0,D2) :-
424 bad(A,E),!,
425 insert_exp(exp(E,PE),D0,D1),
426 add_to_each(A,NA,T,D1,D2).
427add_to_each(A,NA,[B|T],D0,D2) :-
428 ins_negs(NA,B,D0,D1),
429 add_to_each(A,NA,T,D1,D2).
437ins_negs([],_,D0,D0).
438ins_negs([N|NA],exp(E,PE),D,D2) :-
439 hypothesis(N,PN),
440 P is PN * PE,
441 insert_exp(exp([N|E],P),D,D1),
442 ins_negs(NA,exp(E,PE),D1,D2).
450insert_exp(exp(_,0.0),L,L) :-!.
451insert_exp(E,[],[E]) :- !.
452insert_exp(exp(E,_),D,D) :-
453 member(exp(E1,_),D),
454 subset(E1,E),!.
455insert_exp(exp(E,P),[exp(E1,_)|D0],D1) :-
456 subset(E,E1),!,
457 insert_exp(exp(E,P),D0,D1).
458insert_exp(exp(E,P),[E1|D0],[E1|D1]) :-
459 insert_exp(exp(E,P),D0,D1).
470make_disjoint([],[]).
471make_disjoint([exp(R,P)|L],L2) :-
472 member(exp(R1,_),L),
473 \+ incompatible(R,R1),!,
474 member(E,R1), \+ member(E,R),!,
475 negs(E,NE),
476 split(exp(R,P),NE,E,L,L1),
477 make_disjoint(L1,L2).
478make_disjoint([E|L1],[E|L2]) :-
479 make_disjoint(L1,L2).
480split(exp(R,P),[],E,L,L1) :-
481 hypothesis(E,PE),
482 P1 is P*PE,
483 insert_exp1(exp([E|R],P1),L,L1).
484split(exp(R,P),[E1|LE],E,L,L2) :-
485 hypothesis(E1,PE),
486 P1 is P*PE,
487 split(exp(R,P),LE,E,L,L1),
488 insert_exp1(exp([E1|R],P1),L1,L2).
489negs(E,NE) :-
490 findall(N,nogood(E,N),NE).
491insert_exp1(exp(_,0.0),L,L) :-!.
492insert_exp1(exp(E,_),D,D) :-
493 member(exp(E1,_),D),
494 subset(E1,E),!.
495insert_exp1(exp(E,P),D,[exp(E,P)|D]).
508allgood([]).
509allgood([H|T]) :-
510 good(H,T),
511 allgood(T).
512
513good(A,T) :-
514 \+ ( makeground((A,T)), bad(A,T)).
515bad(A,[B|_]) :-
516 nogood(A,B).
517bad(A,[_|R]) :-
518 bad(A,R).
528:- dynamic done/4. 529explain(G) :-
530 explain(G,[],[]).
531explain(G,C) :-
532 explain(G,C,[]).
533explain(G,C,R) :-
534 statistics(runtime,_),
535 ex(G,C,R).
536:- dynamic false/6. 545:- dynamic done/5. 546ex(G,C,R0) :-
547 prove(G,C,_,R0,R,1,P,T),
548 ans(G,C,R0,R,P,T), fail.
549ex(G,C,R) :-
550 done(G,C,R,_,Pr),
551 append(C,R,CR),
552 nl,
553 writeln(['Prob( ',G,' | ',CR,' ) = ',Pr]),
554 statistics(runtime,[_,Time]),
555 writeln(['Runtime: ',Time,' msec.']).
556ex(G,C,R) :-
557 \+ done(G,C,R,_,_),
558 append(C,R,CR),
559 nl,
560 writeln(['Prob( ',G,' | ',CR,' ) = ',0.0]),
561 statistics(runtime,[_,Time]),
562 writeln(['Runtime: ',Time,' msec.']).
563
564ans(G,C,R0,R,P,T) :-
565 allgood(R),
566 ( retract(done(G,C,R0,Done,DC))
567 -> true
568 ; Done=[], DC=0),
569 DC1 is DC+P,
570 asserta(done(G,C,R0,[expl(R,P,T)|Done],DC1)),
571 nl,
572 length(Done,L),
573 append(C,R0,Given),
574 writeln(['***** Explanation ',L,' of ',G,' given ',Given,':']),
575 writeln([R]),
576 writeln(['Prior = ',P]).
582recap :-
583 done(G,C,R,_,Pr),
584 append(C,R,CR),
585 writeln(['Prob( ',G,' | ',CR,' ) = ',Pr]),
586 fail.
587recap.
588recap(G) :-
589 recap(G,_,_).
590recap(G,C) :-
591 recap(G,C,_).
592recap(G,C,R) :-
593 done(G,C,R,Expls,Pr),
594 append(C,R,CR),
595 writeln(['Prob( ',G,' | ',CR,' ) = ',Pr]),
596 writeln(['Explanations:']),
597 recap_each(_,Expls,Pr).
598recap_each(0,[],_).
599recap_each(N,[expl(R,P,_)|L],Pr) :-
600 recap_each(N0,L,Pr),
601 N is N0+1,
602 PP is P/Pr,
603 writeln([N0,': ',R,' Post Prob=',PP]).
604
610:- (h <- user_help). 611user_help :- writeln([
612'rule(R).','
613 asserts either a rule of the form H :- B or an atom.','
614H <- B. ','
615 is the same as rule((H :- B)). ','
616 Rules with empty bodies (facts) must be written as H <- true. or as rule(H).','
617random([h1:p1,...,hn:pn]).','
618 declares the hi to be pairwise disjoint hypotheses, with P(hi)=pi. ','
619random(X,h,[x1:p1,...,xn:pn]).','
620 declares h[X/xi] to be pairwise disjoint hypotheses with P(h[X/xi])=pi.','
621controllable([h1,...,hn]).','
622 declares the hi to be pairwise disjoint controllable variables.','
623explain(G,C). ','
624 finds explanations of G given list of controlling values C.','
625how(G,C,R,N).','
626 is used to explain the Nth explanation of G given controllables C,','
627 and randoms R.','
628diff(G,C,N,M) ','
629 prints difference in the proof tree for the Nth and Mth explanation','
630 of G given C.','
631check(G,C).','
632 checks for disjoint rules in the explanations of G given C.','
633recap(G). ','
634 recaps the explanations of G, with posterior probabilities (given G).','
635recap. ','
636 gives the prior probabilities of everything explained.','
637thconsult(filename). ','
638 loads a file called filename. ','
639tracing(F). ','
640 sets tracing to have status F which is one of {yes,no,duals}.','
641debug(F). ','
642 sets debugging to have status F which is one of {yes,no}.','
643check_undef.','
644 checks for undefined atoms in the body of rules.','
645clear.','
646 clears the knowedge base. Do this before reloading.','
647 Reconsulting a program will not remove old clauses and declarations.','
648help.','
649 print this message.']).
657:- dynamic tracn/1. 658tracing(V) :-
659 member(V,[yes,no,duals]),!,
660 retractall(tracn(_)),
661 asserta(tracn(V)).
662tracing(V) :-
663 member(V,[on,y]),!,
664 retractall(tracn(_)),
665 asserta(tracn(yes)).
666tracing(V) :-
667 member(V,[off,n]),!,
668 retractall(tracn(_)),
669 asserta(tracn(no)).
670tracing(_) :-
671 writeln(['Argument to tracing should be in {yes,no,duals}.']),
672 !,
673 fail.
674tracn(no).
676
681:- dynamic debgn/1. 682debgn(no).
683
684debug(V) :-
685 member(V,[yes,on,y]),!,
686 retractall(debgn(_)),
687 assert(debgn(yes)).
688debug(V) :-
689 member(V,[no,off,n]),!,
690 retractall(debgn(_)),
691 assert(debgn(no)).
692debug(_) :-
693 writeln(['Argument to debug should be in {yes,no}.']), !, fail.
704how(G,N) :-
705 how(G,[],[],N).
706how(G,C,N) :-
707 how(G,C,[],N).
708how(G,C,R,N) :-
709 tree(G,C,R,N,T),
710 traverse(T).
718tree(G,C,R,N,NT) :-
719 done(G,C,R,Done,_),
720 nthT(Done,N,NT).
721
722nthT([expl(_,_,T) |R],N,T) :-
723 length(R,N),!.
724nthT([_|R],N,T) :-
725 nthT(R,N,T).
732traverse(if(H,true)) :-
733 writeln([H,' is a fact']).
734traverse(if(H,builtin)) :-
735 writeln([H,' is built-in.']).
736traverse(if(H,assumed)) :-
737 writeln([H,' is assumed.']).
738traverse(if(H,given)) :-
739 writeln([H,' is a given controllable.']).
740traverse(if(H,not)) :-
741 writeln([~ H,' is a negation - I cannot trace it. Sorry.']).
742traverse(if(H,B)) :-
743 B \== true,
744 B \== builtin,
745 B \== assumed,
746 B \== given,
747 writeln([H,' :-']),
748 printbody(B,1,Max),
749 read(Comm),
750 interpretcommand(Comm,B,Max,if(H,B)).
760printbody((A&B),N,N2) :-
761 printbody(A,N,N),
762 N1 is N+1,
763 printbody(B,N1,N2).
764printbody(if(H,not),N,N) :-!,
765 writeln([' ',N,': ~ ',H]).
766printbody(if(H,_),N,N) :-
767 writeln([' ',N,': ',H]).
768printbody(true,N,N):-!,
769 writeln([' ',N,': true ']).
770printbody(builtin,N,N):-!,
771 writeln([' ',N,': built in ']).
772printbody(assumed,N,N):-!,
773 writeln([' ',N,': assumed ']).
774printbody(given,N,N):-!,
775 writeln([' ',N,': given ']).
782interpretcommand(N,B,Max,G) :-
783 integer(N),
784 N > 0,
785 N =< Max,
786 nth(B,N,E),
787 traverse(E),
788 traverse(G).
789interpretcommand(up,_,_,_).
790interpretcommand(N,_,Max,G) :-
791 integer(N),
792 (N < 1 ; N > Max),
793 writeln(['Number out of range: ',N]),
794 traverse(G).
795interpretcommand(help,_,_,G) :-
796 writeln(['Give either a number, up or exit. End command with a Period.']),
797 traverse(G).
798interpretcommand(C,_,_,G) :-
799 \+ integer(C),
800 C \== up,
801 C \== help,
802 C \== exit,
803 C \== end_of_file,
804 writeln(['Illegal Command: ',C,' Type "help." for help.']),
805 traverse(G).
806
808nth(A,1,A) :-
809 \+ (A = (_&_)).
810nth((A&_),1,A).
811nth((_&B),N,E) :-
812 N>1,
813 N1 is N-1,
814 nth(B,N1,E).
823diff(G,C,N,M) :-
824 tree(G,C,N,NT),
825 tree(G,C,M,MT),
826 diffT(NT,MT).
832diffT(T,T) :-
833 writeln(['Trees are identical']).
834
835diffT(if(H,B1),if(H,B2)) :-
836 immdiff(B1,B2),!,
837 writeln([H,' :-']),
838 printbody(B1,1,N1),
839 writeln([H,' :-']),
840 printbody(B2,N1,_).
841diffT(if(H,B1),if(H,B2)) :-
842 diffT(B1,B2).
843diffT((X&Y),(X&Z)) :- !,
844 diffT(Y,Z).
845diffT((X&_),(Y&_)) :-
846 diffT(X,Y).
847
848immdiff((A&_),(B&_)) :-
849 immdiff(A,B).
850immdiff((_&A),(_&B)) :-
851 immdiff(A,B).
852immdiff((_&_),if(_,_)).
853immdiff(if(_,_),(_&_)).
854immdiff(if(A,_),if(B,_)) :-
855 \+ A = B.
856immdiff(if(_,_),B) :-
857 atomic(B).
858immdiff(A,if(_,_)) :-
859 atomic(A).
869check :-
870 check(_,_,_).
871check(G) :-
872 check(G,_,_).
873check(G,C) :-
874 check(G,C,_).
875check(G,C,R) :-
876 done(G,C,R,Done,_),
877 check_done(Done).
878
879check_done([expl(R1,_,T1)|D]) :-
880 memberR(expl(R2,_,T2),D,DR),
881 \+ incompatible(R1,R2),
882 length(D,LD),
883 length(DR,L2),
884 icl_union(R1,R2,R),
885 writeln(['Non-disjoint rules ',LD,' & ',L2,' assuming ',R]),
886 diffT(T1,T2).
887check_done([_|D]) :-
888 check_done(D).
895check_disj(G0,G1):-
896 check_disj(G0,G1,_,_).
897check_disj(G0,G1,C,R):-
898 done(G0,C,R,D0,_),
899 done(G1,C,R,D1,_),
900 memberR(expl(R0,_,_),D0,LD0),
901 memberR(expl(R1,_,_),D1,LD1),
902 \+ incompatible(R0,R1),
903 length(LD0,L0),
904 length(LD1,L1),
905 append(C,R,CR),
906 writeln(['Explanation ',L0,' of ',G0,' and ',L1,' of ',G1,
907 ', given ',CR,' are compatible assuming:']),
908 icl_union(R0,R1,R),
909 writeln([R]).
910incompatible(R1,R2) :-
911 member(A1,R1),
912 member(A2,R2),
913 nogood(A1,A2).
921check_undef :-
922 forall(rul(H,B),
923 forall(body_elt_undefined(B,H,B), true)), !.
924
925
926body_elt_undefined(true,_,_) :- !,fail.
927body_elt_undefined((A&_),H,B) :-
928 body_elt_undefined(A,H,B).
929body_elt_undefined((_&A),H,B) :- !,
930 body_elt_undefined(A,H,B).
931body_elt_undefined((~ A),H,B) :- !,
932 body_elt_undefined(A,H,B).
933body_elt_undefined((A;_),H,B) :-
934 body_elt_undefined(A,H,B).
935body_elt_undefined((_;A),H,B) :- !,
936 body_elt_undefined(A,H,B).
937body_elt_undefined(call(A),H,B) :- !,
938 body_elt_undefined(A,H,B).
939body_elt_undefined(_ \= _,_,_) :- !,fail.
944body_elt_undefined(A,_,_) :-
945 builtin(A),!,fail.
946body_elt_undefined(A,_,_) :-
947 hypothesis(A,_),!,fail.
948body_elt_undefined(A,_,_) :-
949 control(A),!,fail.
950body_elt_undefined(A,_,_) :-
951 rul(A,_),!,fail.
952body_elt_undefined(A,H,B) :-
953 writeln(['Warning: no clauses for ',A,' in rule ',(H <- B),'.']),!,fail.
968thconsult(File) :-
969 current_input(OldFile),
970 open(File,read,Input),
971 set_input(Input),
972 read(T),
973 read_all(T),
974 set_input(OldFile),
975 writeln(['ICL theory ',File,' consulted.']),!.
979read_all(end_of_file) :- !.
980read_all(T) :-
981 (on_icl_read(T);format('Warning: ~w failed~n',[T])),
982 read(T2),
983 read_all(T2).
984
985:- module_transparent(on_icl_read/1). 986on_icl_read(T):- notrace(T == end_of_file), !, listing(example_query/1).
987on_icl_read(:- T):- must(T),!.
988on_icl_read(example_query(X)):- !,assertz(example_query(X)).
989on_icl_read(random(X)):- !, random(X).
990on_icl_read(T):- \+ predicate_property(icl:T, imported_from(_)), !, must(icl:T).
991on_icl_read(T):- must(T).
992
1009icl_union([],L,L).
1010
1011icl_union([H|X],Y,Z) :-
1012 member(H,Y),!,
1013 icl_union(X,Y,Z).
1014icl_union([H|X],Y,[H|Z]) :-
1015 icl_union(X,Y,Z).
1029memberR(A,[A|R],R).
1030memberR(A,[_|T],R) :-
1031 memberR(A,T,R).
1035subset([],_).
1036subset([H|T],L) :-
1037 member(H,L),
1038 subset(T,L).
1044makeground(T) :-
1045 numbervars(T,0,_).
1051repvar(X,X1,Y,X1) :- X==Y, !.
1052repvar(_,_,Y,Y) :- var(Y), !.
1053repvar(_,_,Y,Y) :- ground(Y), !.
1054repvar(X,X1,[H|T],[H1|T1]) :- !,
1055 repvar(X,X1,H,H1),
1056 repvar(X,X1,T,T1).
1057repvar(X,X1,T,T1) :-
1058 T =.. L,
1059 repvar(X,X1,L,L1),
1060 T1 =.. L1.
1066writeln([]) :- nl.
1067writeln([H|T]) :-
1068 write(H),
1069 writeln(T).
1096
1097
1098:- include(library(dialect/logicmoo/dialect_loader_incl)). 1099
1100prolog:dialect_reads(icl, on_icl_read)