clnf.red 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. % ----------------------------------------------------------------------
  2. % $Id: clnf.red,v 1.11 1999/04/13 13:10:58 sturm Exp $
  3. % ----------------------------------------------------------------------
  4. % Copyright (c) 1995-1999 Andreas Dolzmann and Thomas Sturm
  5. % ----------------------------------------------------------------------
  6. % $Log: clnf.red,v $
  7. % Revision 1.11 1999/04/13 13:10:58 sturm
  8. % Updated comments for exported procedures.
  9. %
  10. % Revision 1.10 1999/03/22 17:08:07 dolzmann
  11. % Changed copyright information.
  12. %
  13. % Revision 1.9 1999/03/19 16:07:17 dolzmann
  14. % Fixed a bug in cl_tnf: cl_tnff and cl_tnft call rl_t2cdl instead of
  15. % ofsf_t2cdl.
  16. %
  17. % Revision 1.8 1997/08/14 10:09:16 sturm
  18. % Added documentation for cl_rename!-vars.
  19. %
  20. % Revision 1.7 1996/10/17 13:51:54 sturm
  21. % Introduced services rlvarl, rlfvarl, and rlbvarl. Renamed cl_varl to
  22. % cl_varl1 for this.
  23. %
  24. % Revision 1.6 1996/10/07 11:45:51 sturm
  25. % Added fluids for CVS and copyright information.
  26. %
  27. % Revision 1.5 1996/10/02 10:24:06 dolzmann
  28. % Fixed a bug in cl_tnft.
  29. %
  30. % Revision 1.4 1996/10/01 10:24:54 reiske
  31. % Introduced new service rltnf and related code.
  32. %
  33. % Revision 1.3 1996/07/07 14:35:37 sturm
  34. % Turned some cl calls into service calls.
  35. % Introduced new service rl_nnfnot.
  36. %
  37. % Revision 1.2 1996/06/05 15:06:40 sturm
  38. % Added procedure cl_varl as an entry point for cl_varl1.
  39. %
  40. % Revision 1.1 1996/03/22 10:31:30 sturm
  41. % Moved and split.
  42. %
  43. % ----------------------------------------------------------------------
  44. lisp <<
  45. fluid '(cl_nf_rcsid!* cl_nf_copyright!*);
  46. cl_nf_rcsid!* := "$Id: clnf.red,v 1.11 1999/04/13 13:10:58 sturm Exp $";
  47. cl_nf_copyright!* := "(c) 1995-1999 by A. Dolzmann and T. Sturm"
  48. >>;
  49. module clnf;
  50. % Common logic normal forms. Submodule of [cl].
  51. procedure cl_expand!-extbool(f);
  52. % Common logic expand extended boolean operators. [f] is a formula.
  53. % Returns a formula equivalent to [f] that does not contain any
  54. % extended boolean operator.
  55. begin scalar op;
  56. op := rl_op f;
  57. if rl_quap op then
  58. return rl_mkq(op,rl_var f,cl_expand!-extbool(
  59. rl_mat f));
  60. if rl_basbp op then
  61. return rl_mkn(op,for each subf in rl_argn f collect
  62. cl_expand!-extbool(subf));
  63. if op eq 'impl then
  64. return cl_expand!-extbool(rl_mk2('or,
  65. rl_mk1('not,rl_arg2l f),rl_arg2r f));
  66. if op eq 'repl then
  67. return cl_expand!-extbool(rl_mk2('or,
  68. rl_arg2l f,rl_mk1('not,rl_arg2r f)));
  69. if op eq 'equiv then
  70. return cl_expand!-extbool(rl_mkn('and,{
  71. rl_mk2('impl,rl_arg2l f,rl_arg2r f),
  72. rl_mk2('repl,rl_arg2l f,rl_arg2r
  73. f)}));
  74. return f;
  75. end;
  76. procedure cl_nnf(f);
  77. % Common logic negation normal form. [f] is a formula. Returns a
  78. % formula equivalent to [f] that does not contain the operator
  79. % [not].
  80. cl_nnf1(f,T);
  81. procedure cl_nnfnot(f);
  82. % Common logic negation normal form not. [f] is a formula. Returns
  83. % a formula equivalent to $\lnot [f]$ that does not contain the
  84. % operator [not].
  85. cl_nnf1(f,nil);
  86. procedure cl_nnf1(f,flag);
  87. % Common logic negation normal form. [f] is a formula; [flag] is
  88. % bool. Returns a formula $\phi$ that does not contain the operator
  89. % [not]. In case $[flag]$ is non-[nil] we have $\phi$ equivalent to
  90. % [f], else we have $\phi$ equivalent to $\lnot [f]$.
  91. begin scalar op;
  92. op := rl_op f;
  93. if op eq 'not then
  94. return cl_nnf1(rl_arg1 f,not flag);
  95. if op eq 'impl then
  96. return rl_mkn(cl_cflip('or,flag),
  97. {cl_nnf1(rl_arg2l f,not flag),cl_nnf1(rl_arg2r f,flag)});
  98. if op eq 'repl then
  99. return rl_mkn(cl_cflip('or,flag),
  100. {cl_nnf1(rl_arg2l f,flag),cl_nnf1(rl_arg2r f,not flag)});
  101. if op eq 'equiv then
  102. return rl_mkn(cl_cflip('or,flag),{
  103. rl_mkn(cl_cflip('and,flag),{
  104. cl_nnf1(rl_arg2l f,flag),cl_nnf1(rl_arg2r f,flag)}),
  105. rl_mkn(cl_cflip('and,flag),{
  106. cl_nnf1(rl_arg2l f,not flag),cl_nnf1(rl_arg2r f,not flag)})});
  107. if rl_tvalp op then
  108. return cl_cflip(f,flag);
  109. if rl_quap op then
  110. return rl_mkq(cl_cflip(op,flag),rl_var f,cl_nnf1(rl_mat f,flag));
  111. if rl_junctp op then
  112. return rl_mkn(
  113. cl_cflip(op,flag),for each subf in rl_argn f collect
  114. cl_nnf1(subf,flag));
  115. return if flag then f else rl_negateat f
  116. end;
  117. procedure cl_pnf(phi);
  118. % Common logic prenex normal form. [phi] is a formula. Returns a
  119. % prenex formula equivalent to [phi]. The number of quantifier
  120. % changes in the result is minimal among all formulas that can be
  121. % obtained from [phi] by moving quantifiers to the outside.
  122. cl_pnf1 rl_nnf phi;
  123. procedure cl_pnf1(phi);
  124. % Common logic prenex normal form subroutine. [phi] is a positive
  125. % formula that does not contain any extended boolean operator.
  126. % Returns a prenex formula equivalent to [phi]. The number of
  127. % quantifier changes in the result is minimal among all formulas
  128. % that can be obtained from [phi] by moving quantifiers to the
  129. % outside.
  130. <<
  131. if null cdr erg or cl_qb car erg < cl_qb cadr erg then
  132. car erg
  133. else
  134. cadr erg
  135. >> where erg=cl_pnf2(cl_rename!-vars(phi));
  136. procedure cl_pnf2(phi);
  137. begin scalar op;
  138. op := rl_op phi;
  139. if rl_quap op then
  140. return cl_pnf2!-quantifier(phi);
  141. if rl_junctp op then
  142. return cl_pnf2!-junctor(phi);
  143. if rl_tvalp op then
  144. return {phi};
  145. if rl_cxp op then
  146. rederr{"cl_pnf2():",op,"invalid as operator"};
  147. return {phi}
  148. end;
  149. procedure cl_pnf2!-quantifier(phi);
  150. <<
  151. if (null cdr e) or (rl_op phi eq rl_op car e) then
  152. {rl_mkq(rl_op phi,rl_var phi,car e)}
  153. else
  154. {rl_mkq(rl_op phi,rl_var phi,cadr e)}
  155. >> where e=cl_pnf2 rl_mat phi;
  156. procedure cl_pnf2!-junctor(phi);
  157. begin scalar junctor,e,l1,l2,onlyex,onlyall,phi1,phi2; integer m,qb;
  158. junctor := rl_op phi;
  159. e := for each f in rl_argn phi collect cl_pnf2(f);
  160. onlyex := T; onlyall := T;
  161. for each ej in e do <<
  162. qb := cl_qb car ej;
  163. if qb > m then <<
  164. m := qb; onlyex := T; onlyall := T
  165. >>;
  166. if cdr ej then <<
  167. l1 := (car ej) . l1;
  168. l2 := (cadr ej) . l2
  169. >> else <<
  170. l1 := (car ej) . l1;
  171. l2 := (car ej) . l2
  172. >>;
  173. if eqn(m,qb) then <<
  174. if rl_op car l1 eq 'all then onlyex := nil;
  175. if rl_op car l2 eq 'ex then onlyall := nil
  176. >>;
  177. >>;
  178. l1 := reversip l1;
  179. l2 := reversip l2;
  180. if eqn(m,0) then return {phi};
  181. if onlyex neq onlyall then
  182. if onlyex then
  183. return {cl_interchange(l1,junctor,'ex)}
  184. else % [onlyall]
  185. return {cl_interchange(l2,junctor,'all)};
  186. phi1 := cl_interchange(l1,junctor,'ex);
  187. phi2 := cl_interchange(l2,junctor,'all);
  188. if car phi1 eq car phi2 then
  189. return {phi1}
  190. else
  191. return {phi1,phi2}
  192. end;
  193. procedure cl_qb(phi);
  194. begin scalar q,scan!-q; integer qb;
  195. while rl_quap(scan!-q := rl_op phi) do <<
  196. if scan!-q neq q then <<
  197. qb := qb + 1;
  198. q := scan!-q
  199. >>;
  200. phi := rl_mat phi
  201. >>;
  202. return qb
  203. end;
  204. procedure cl_interchange(l,junctor,a);
  205. begin scalar ql,b,result;
  206. while cl_contains!-quantifier(l) do <<
  207. l := for each f in l collect <<
  208. while rl_op f eq a do <<
  209. b := (rl_var f) . b;
  210. f := rl_mat f
  211. >>;
  212. f
  213. >>;
  214. ql := b . ql;
  215. b := nil;
  216. a := cl_flip a
  217. >>;
  218. a := cl_flip a;
  219. result := rl_mkn(junctor,l);
  220. for each b in ql do <<
  221. for each v in b do result := rl_mkq(a,v,result);
  222. a := cl_flip a
  223. >>;
  224. return result
  225. end;
  226. procedure cl_contains!-quantifier(l);
  227. l and (rl_quap rl_op car l or cl_contains!-quantifier(cdr l));
  228. procedure cl_rename!-vars(f);
  229. % Common logic rename variables. [f] is a formula. Returns an
  230. % equivalent formula in which each quantified variable is unique,
  231. % i.e., occurs neither boundly or freely elsewhere in [f].
  232. car cl_rename!-vars1(f,cl_replace!-varl f);
  233. procedure cl_replace!-varl(f);
  234. begin scalar a,d,all,replace;
  235. << a := car vl1; d := cdr vl1 >>
  236. where vl1=cl_varl1 f;
  237. all := a;
  238. for each x on d do <<
  239. if car x memq cdr x or car x memq a then
  240. replace := lto_insert((car x) . 0,replace);
  241. all := lto_insert(car x,all)
  242. >>;
  243. return all . replace
  244. end;
  245. procedure cl_fvarl(f);
  246. % Common logic free variable list. [f] is a formula. Returns the
  247. % list of variables occurring freely in [f] sorted wrt. [ordp].
  248. sort(cl_fvarl1 f,'ordp);
  249. procedure cl_fvarl1(f);
  250. % Common logic free variable list subroutine. [f] is a formula.
  251. % Returns the list of variables occurring freely in [f].
  252. car cl_varl1 f;
  253. procedure cl_bvarl(f);
  254. % Common logic bound variable list. [f] is a formula. Returns the
  255. % list of variables occurring boundly in [f] sorted wrt. [ordp].
  256. sort(cl_bvarl1 f,'ordp);
  257. procedure cl_bvarl1(f);
  258. % Common logic bound variable list subroutine. [f] is a formula.
  259. % Returns the list of variables occurring boundly in [f].
  260. cdr cl_varl1 f;
  261. procedure cl_varl(f);
  262. % Common logic variable lists. [f] is a formula. Returns a pair
  263. % $(V_f . V_b)$ of variable lists. $V_f$ contains the variables
  264. % occurring freely in [f], and $V_b$ contains the variables
  265. % occurring boundly in [f]. Both lists are sorted wrt. the current
  266. % kernel order [ordp].
  267. (sort(car w,'ordp) . sort(cdr w,'ordp)) where w = cl_varl1 f;
  268. procedure cl_varl1(f);
  269. % Common logic variable lists. [f] is a formula. Returns a pair
  270. % $(V_f . V_b)$ of variable lists. $V_f$ contains the variables
  271. % occurring freely in [f], and $V_b$ contains the variables
  272. % occurring boundly in [f].
  273. cl_varl2(f,nil,nil,nil);
  274. procedure cl_varl2(f,freevl,cboundvl,boundvl);
  275. begin scalar op;
  276. op := rl_op f;
  277. if rl_tvalp op then
  278. return freevl . boundvl;
  279. if rl_boolp op then <<
  280. for each s in rl_argn f do <<
  281. freevl := car vl;
  282. boundvl := cdr vl
  283. >> where vl=cl_varl2(s,freevl,cboundvl,boundvl);
  284. return freevl . boundvl
  285. >>;
  286. if rl_quap op then
  287. return cl_varl2(rl_mat f,freevl,
  288. lto_insertq(rl_var f,cboundvl),rl_var f . boundvl);
  289. % [f] is an atomic formula.
  290. for each v in rl_varlat(f) do
  291. if not (v memq cboundvl) then freevl := lto_insertq(v,freevl);
  292. return freevl . boundvl
  293. end;
  294. procedure cl_rename!-vars1(f,vl);
  295. begin scalar op,h,w,newid;
  296. op := rl_op f;
  297. if rl_boolp op then
  298. return rl_mkn(op,for each x in cdr f collect <<
  299. vl := cdr rnv;
  300. car rnv
  301. >> where rnv=cl_rename!-vars1(x,vl)) . vl;
  302. if rl_quap op then <<
  303. << h := car rnv; vl := cdr rnv >>
  304. where rnv=cl_rename!-vars1(rl_mat f,vl);
  305. if (w := assoc(cadr f,cdr vl)) then <<
  306. repeat <<
  307. newid := mkid(car w,cdr w);
  308. cdr w := cdr w + 1
  309. >> until not (newid memq car vl or get(newid,'avalue));
  310. car vl := lto_insertq(newid,car vl);
  311. return rl_mkq(op,newid,cl_apply2ats1(
  312. h,'rl_varsubstat,{newid,car w})) . vl
  313. >>;
  314. return rl_mkq(op,rl_var f,h) . vl
  315. >>;
  316. % [f] is a truth value or an atomic formula.
  317. return f . vl;
  318. end;
  319. procedure cl_apnf(phi);
  320. % Common logic anti-prenex normal form. [phi] is a positive
  321. % formula. Returns a positive formula equivalent to [phi], where
  322. % all quantifiers are moved to the inside as far as possible.
  323. begin scalar op;
  324. op := rl_op phi;
  325. if op eq 'ex then
  326. return cl_apnf1(rl_var phi,cl_apnf rl_mat phi);
  327. if op eq 'all then
  328. return rl_nnfnot cl_apnf1(rl_var phi,cl_apnf rl_mat rl_nnfnot phi);
  329. if rl_junctp op then
  330. return rl_mkn(op,for each subf in rl_argn phi collect cl_apnf subf);
  331. % [phi] is atomic.
  332. return phi
  333. end;
  334. procedure cl_apnf1(var,phi);
  335. % Common logic anti-prenex normal form subroutine. [var] is a
  336. % variable. [phi] is a positive formula with all quantifiers
  337. % already moved to the inside as far as possible. Returns a
  338. % positive formula equivalent to [phi] with the existentially
  339. % quantified [var] moved to the inside as far as possible.
  340. begin scalar op,nf,occurl,noccurl;
  341. op := rl_op phi;
  342. if rl_tvalp op then
  343. return phi;
  344. if op eq 'ex then
  345. return rl_mkq('ex,rl_var phi,cl_apnf1(var,rl_mat phi));
  346. if op eq 'all then
  347. return if cl_freevp(var,phi) then
  348. rl_mkq('ex,var,phi)
  349. else
  350. phi;
  351. if op eq 'or then <<
  352. nf := for each subf in rl_argn phi collect cl_apnf1(var,subf);
  353. return rl_mkn('or,nf)
  354. >>;
  355. if op eq 'and then <<
  356. for each subf in rl_argn phi do
  357. if cl_freevp(var,subf) then
  358. occurl := subf . occurl
  359. else
  360. noccurl := subf . noccurl;
  361. if occurl then <<
  362. nf := if cdr occurl then
  363. rl_mkq('ex,var,rl_mkn('and,reversip occurl))
  364. else
  365. cl_apnf1(var,car occurl);
  366. noccurl := nf . noccurl
  367. >>;
  368. return rl_smkn('and,reversip noccurl)
  369. >>;
  370. % [phi] is atomic.
  371. if var memq rl_varlat phi then
  372. return rl_mkq('ex,var,phi);
  373. return phi
  374. end;
  375. procedure cl_freevp(var,phi);
  376. % Common logic free variable predicate. [var] is a variable, [phi]
  377. % is a formula. Returns non-[nil] iff [var] occurs freely in [phi].
  378. begin scalar argl,flag;
  379. if rl_quap rl_op phi then <<
  380. if var eq rl_var phi then
  381. return nil;
  382. return cl_freevp(var,rl_mat phi)
  383. >>;
  384. if cl_atfp phi then
  385. return var memq rl_varlat phi;
  386. argl := rl_argn phi;
  387. while argl do
  388. if cl_freevp(var,car argl) then <<
  389. flag := T;
  390. argl := nil
  391. >> else
  392. argl := cdr argl;
  393. return flag
  394. end;
  395. procedure cl_tnf(f,terml);
  396. % Common logic tree normal form. [f] is a formula, [terml] is a
  397. % list of terms. Returns a big formula. Depends on the switch
  398. % [rltnft].
  399. if !*rltnft then cl_tnft(f,terml) else cl_tnff(f,terml);
  400. procedure cl_tnff(f,terml);
  401. % Common logic tree normal form flat. [f] is a formula, [terml] is
  402. % a list of terms. Returns a big formula.
  403. begin scalar w,theol,resl,dpth;
  404. theol := cl_bnf!-cartprod for each term in terml collect
  405. rl_t2cdl term;
  406. if !*rlverbose then dpth := length theol;
  407. for each theo in theol do <<
  408. if !*rlverbose then <<
  409. ioto_prin2 {"[",dpth};
  410. dpth := dpth - 1
  411. >>;
  412. w := rl_simpl(f,theo,-1);
  413. if w eq 'true then <<
  414. resl := rl_smkn('and,theo) . resl;
  415. if !*rlverbose then ioto_prin2 "+] "
  416. >> else if w eq 'inctheo then
  417. (if !*rlverbose then ioto_prin2 "!] ")
  418. else if w neq 'false then <<
  419. resl := rl_smkn('and,w . theo) . resl;
  420. if !*rlverbose then ioto_prin2 ".] "
  421. >> else if !*rlverbose then
  422. ioto_prin2 "-] "
  423. >>;
  424. return rl_smkn('or,resl)
  425. end;
  426. procedure cl_tnft(f,terml);
  427. % Common logic tree normal form tree. [f] is a formula, [terml] is
  428. % a list of terms. Returns a big formula.
  429. begin scalar w,cdl,cd,rvl;
  430. if null terml then return f;
  431. cdl := rl_t2cdl car terml;
  432. while cdl do <<
  433. cd := car cdl;
  434. cdl := cdr cdl;
  435. w := rl_simpl(rl_mk2('and,cd,f),nil,-1);
  436. if w eq 'true then <<
  437. rvl := '(true);
  438. cdl := nil
  439. >> else if w neq 'false then
  440. rvl := cl_tnft(w,cdr terml) . rvl
  441. >>;
  442. return rl_simpl(rl_smkn('or,rvl),nil,-1)
  443. end;
  444. endmodule; % [clnf]
  445. end; % of file