boolean.red 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. module boolean; % Propositional calculus support.
  2. % Author: Herbert Melenk
  3. % Konrad Zuse Zentrum Berlin
  4. % A form in propositional calculus is transformed to a canonical DNF
  5. % (disjuinct normal form) and then converted back to a or-not-form.
  6. % Polynomials are used as intermediate form mapping or to plus and
  7. % and to times. The variables are embedded in kernels prop* and
  8. % negated variables are represented as not_prop* operators.
  9. create!-package('(boolean),'(contrib misc));
  10. algebraic operator prop!*, not_prop!*;
  11. algebraic infix implies;
  12. algebraic infix equiv;
  13. algebraic precedence equiv,=>;
  14. algebraic precedence implies,equiv;
  15. algebraic
  16. let prop!*(~x)*prop!*(x)=>prop!*(x),
  17. not_prop!*(~x)*not_prop!*(x)=>not_prop!*(x),
  18. prop!*(~x)*not_prop!*(x)=>0;
  19. fluid '(propvars!* !'and !'or !'true !'false);
  20. symbolic procedure simp!-prop u;
  21. begin scalar propvars!*,w,opt;
  22. % convert to intermediate standard form.
  23. opt:=for each f in cdr u collect reval f;
  24. if member('and,opt) then
  25. <<!'and:='or; !'or:='and; !'true:=0; !'false:=1;>>
  26. else
  27. <<!'and:='and; !'or:='or; !'true:=1; !'false:=0;>>;
  28. w:=reval prepf simp!-prop1(car u,t);
  29. if w=0 then return simp !'false;
  30. % add for each variable a true value "and (x or not x)".
  31. for each x in propvars!* do
  32. w:=reval{'times,w,prepf simp!-prop1({!'or,x,{'not,x}},t)};
  33. % transform to distributive.
  34. w:=simp!-prop!-dist w;
  35. if not member('full,opt) then w:=simp!-prop2 w;
  36. w :=simp!-prop!-form w;
  37. if numberp w then return w ./ 1;
  38. if not atom w then w:={'boolean,w};
  39. return (w .**1 .*1 .+nil) ./ 1;
  40. end;
  41. put('boolean,'simpfn,'simp!-prop);
  42. symbolic procedure simp!-prop1(u,m);
  43. % Convert logical form to polynomial.
  44. begin scalar w;
  45. if atom u then goto z;
  46. if car u = !'and and m or car u=!'or and not m then
  47. <<w:=1; for each q in cdr u do
  48. w:=multf(w,simp!-prop1(q,m))>>
  49. else if car u=!'or and m or car u=!'and and not m then
  50. <<w:=nil; for each q in cdr u do
  51. w:=addf(w,simp!-prop1(q,m))>>
  52. else if car u='not then w:=simp!-prop1(cadr u,not m)
  53. else if car u ='implies then
  54. (if m then w:=simp!-prop1({'or,{'not,cadr u},caddr u},t) else
  55. w:=simp!-prop1({'or,{'not,caddr u},cadr u},t))
  56. else if car u= 'equiv then w:=simp!-prop1(
  57. {'or,{'and,cadr u,caddr u},{'and,{'not,cadr u},{'not,caddr u}}},m)
  58. else goto z1;
  59. return w;
  60. z:
  61. if u=1 or u=t or u='true then u:=m else
  62. if u=0 or u=nil or u='false then u:=not m;
  63. if u=t then return simp!-prop1('(or !*true (not !*true)),t);
  64. if u=nil then return simp!-prop1('(and !*true (not !*true)),t);
  65. z1:
  66. u:=reval u;
  67. if eqcar(u,'boolean) then return simp!-prop1(cadr u,m);
  68. w:= numr simp{if m then 'prop!* else 'not_prop!*,u};
  69. if not member(u,propvars!*) then propvars!*:=u.propvars!*;
  70. return w;
  71. end;
  72. symbolic procedure simp!-prop2 w;
  73. % Remove redundant elements, convert back.
  74. begin scalar y,z,o,q1,q2,term,old;
  75. for each x in propvars!* do
  76. <<old:=nil;
  77. while w do
  78. <<term := car w; w := cdr w;
  79. q1:={'prop!*,x}; q2:={'not_prop!*,x};
  80. if not member(q1,term) then <<y:=q2;q2:=q1;q1:=y>>;
  81. z:=subst(q2,q1,term);
  82. old:=term.old;
  83. if (o:=member(z,w)) then
  84. << if o then <<w:=delete(car o,w); old:=car o . old>>;
  85. term:=delete(q1,term);
  86. old:=union({term},old);
  87. >>;
  88. >>;
  89. w:=old;
  90. >>;
  91. return simp!-prop!-condense w;
  92. end;
  93. symbolic procedure simp!-prop!-condense u;
  94. begin scalar w,r;
  95. u:=sort(u,function(lambda(v1,v2);length(v1)<length(v2)));
  96. while u do
  97. <<w:=car u; u:=cdr u; r:=w.r;
  98. for each q in u do
  99. if subsetp(w,q) then u:=delete(q,u);
  100. >>;
  101. return ordn r;
  102. end;
  103. symbolic procedure simp!-prop!-dist w;
  104. % convert to a distributive form.
  105. <<if eqcar(w,'plus) then w :=cdr w else w:={w};
  106. w:=for each term in w collect
  107. <<term:=if eqcar(term,'times) then cdr term else {term};
  108. if numberp car term then term:=cdr term;
  109. sort(term,function(lambda(p1,p2); ordp(cadr p1,cadr p2)))
  110. >>;
  111. sort(w,function simp!-prop!-order)
  112. >>;
  113. symbolic procedure simp!-prop!-order(a,b);
  114. if null a then nil else
  115. if caar a = caar b then simp!-prop!-order(cdr a,cdr b) else
  116. if caar a = 'prop!* then t else nil;
  117. symbolic procedure simp!-prop!-form u;
  118. if u='(nil) then !'true else
  119. <<u:=for each term in u collect
  120. <<term := for each x in term collect
  121. if eqcar(x,'not_prop!*) then {'not,cadr x} else cadr x;
  122. if cdr term then !'and . term else car term>>;
  123. if cdr u then !'or . u else car u
  124. >>;
  125. fluid '(bool!-break!*);
  126. %symbolic procedure boolean!-eval u;
  127. % <<v:=boolean!-eval1 u;
  128. % if bool!-break!* then
  129. % rederr(u,"boolean evaluation");
  130. % v>> where v=nil,bool!-break!*=nil;
  131. %
  132. %put('boolean,'boolfn,'boolean!-eval);
  133. symbolic procedure test!-bool u;
  134. mk!*sq simp!-prop list boolean!-eval1 car u;
  135. put('testbool,'psopfn,'test!-bool);
  136. symbolic procedure boolean!-eval1 u;
  137. begin scalar v;
  138. return
  139. if eqcar(u,'sq!*) and cddr u and eqcar(v:=prespsq cadr u,'boolean)
  140. then boolean!-eval2 cadr v
  141. else boolean!-eval2 prepf numr simp!-prop list u;
  142. end;
  143. symbolic procedure boolean!-eval2 u;
  144. if eqcar(u,'boolean) then boolean!-eval2 cadr u else
  145. if eqcar(u,'and) or eqcar(u,'or) or eqcar(u,'not)
  146. then car u. for each x in cdr u collect boolean!-eval2 x
  147. else
  148. <<r:=errorset(formbool(u,nil,'algebraic),nil,nil)
  149. where !*protfg=t;
  150. if errorp r then <<bool!-break!*:=t;erfg!*:=nil; u>>
  151. else car r>>
  152. where r=nil;
  153. put('and,'prtch,"/\");
  154. put('or,'prtch," \/ ");
  155. endmodule;
  156. end;