clbnf.red 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. % ----------------------------------------------------------------------
  2. % $Id: clbnf.red,v 1.20 2003/12/08 15:30:00 dolzmann Exp $
  3. % ----------------------------------------------------------------------
  4. % Copyright (c) 1995-2003 A. Dolzmann, A. Seidl, and T. Sturm
  5. % ----------------------------------------------------------------------
  6. % $Log: clbnf.red,v $
  7. % Revision 1.20 2003/12/08 15:30:00 dolzmann
  8. % Renamed variable state to kstate, because hephys/physop.red defines
  9. % state as an stat function. This causes errors reading clbnf provided
  10. % physop is loaded.
  11. %
  12. % Revision 1.19 2003/06/11 08:45:23 dolzmann
  13. % Rewritten Quine simplification such that rl_simpl is not called by
  14. % default. Calling rl_simpl can cause male function due to unwanted
  15. % algebraic simplifications.
  16. % Added procedure for converting a bnf into set representation wrt. a
  17. % given operator.
  18. % Added black boxes rl_qssimpl and rl_qssiadd.
  19. % Added black box implementations cl_qssimpl and cl_qssibysimpl.
  20. %
  21. % Revision 1.18 2003/06/06 08:06:14 dolzmann
  22. % Added power set computation by enumeration.
  23. %
  24. % Revision 1.17 2003/06/04 07:23:04 dolzmann
  25. % Added CNF support to cl_quine by computing the minimal DNF of the negated
  26. % input formula.
  27. %
  28. % Revision 1.16 2003/06/04 06:08:09 dolzmann
  29. % Added procedure cl_qssusubytab as a generic implementation for
  30. % blackbox rl_qssubsumtion. It requires rl_qssusuat.
  31. % Improved procedure cl_qsimpltestccl.
  32. %
  33. % Revision 1.15 2003/06/03 16:09:40 dolzmann
  34. % Fixed a bug in cl_qsnconsens1: The return value nil of rl_qstrycons
  35. % entered the list of consensus.
  36. % Fixed a bug in cl_qssusubyit: The eq test to 'true was missing.
  37. %
  38. % Revision 1.14 2003/06/03 11:18:10 dolzmann
  39. % Completely overworked quine simplification. In particular: Removed
  40. % bugs during prime implicant computation. Added missing tautology test
  41. % for implication test. Added comments on use of black boxes. Moved and
  42. % sorted procedure definitions.
  43. %
  44. % Revision 1.13 2003/05/27 08:19:54 dolzmann
  45. % Procedure cl_qsconsens now returns a list of consensus. Adapted
  46. % procedure cl_qscpi accordingly.
  47. %
  48. % Revision 1.12 2003/05/27 07:27:51 dolzmann
  49. % Use cl_qssub instead of rl_subfof;
  50. % Added black box rl_qssubat.
  51. % Added default implementation cl_qssubat for black box rl_qssubat.
  52. % Added procedure cl_qssimplc as a future replacement for rl_simpl.
  53. % Changed cl_bnf2set. cl_quine can now deal with BNFs containing
  54. % identical clauses.
  55. %
  56. % Revision 1.11 2003/05/23 16:01:01 dolzmann
  57. % Added selection from all prime implicants as descibed in Quine 1955.
  58. % Fixed a bug in consensus computation: nil as an legal conses was not
  59. % recognized.
  60. %
  61. % Revision 1.10 2003/05/21 09:03:27 dolzmann
  62. % Added first experimental implementation of service rlquine for
  63. % simplifying Boolean normal forms in the style of W. V. Quine.
  64. %
  65. % Revision 1.9 2003/05/20 11:35:46 dolzmann
  66. % Moved procedures.
  67. %
  68. % Revision 1.8 1999/04/13 13:10:55 sturm
  69. % Updated comments for exported procedures.
  70. %
  71. % Revision 1.7 1999/04/01 11:26:47 dolzmann
  72. % Reformatted one procedure.
  73. %
  74. % Revision 1.6 1999/03/22 17:07:12 dolzmann
  75. % Changed copyright information.
  76. % Reformatted comments.
  77. %
  78. % Revision 1.5 1999/03/21 13:34:06 dolzmann
  79. % Corrected comments.
  80. %
  81. % Revision 1.4 1996/10/07 11:45:47 sturm
  82. % Added fluids for CVS and copyright information.
  83. %
  84. % Revision 1.3 1996/07/13 10:53:07 dolzmann
  85. % Added black box implementations cl_bnfsimpl, cl_sacatlp, and cl_sacat.
  86. %
  87. % Revision 1.2 1996/07/07 14:34:19 sturm
  88. % Turned some cl calls into service calls.
  89. %
  90. % Revision 1.1 1996/03/22 10:31:27 sturm
  91. % Moved and split.
  92. %
  93. % ----------------------------------------------------------------------
  94. lisp <<
  95. fluid '(cl_bnf_rcsid!* cl_bnf_copyright!*);
  96. cl_bnf_rcsid!* := "$Id: clbnf.red,v 1.20 2003/12/08 15:30:00 dolzmann Exp $";
  97. cl_bnf_copyright!* := "(c) 1995-2003 by A. Dolzmann, A. Seidl, and T. Sturm"
  98. >>;
  99. module clbnf;
  100. % Common logic boolean normal forms. Submodule of [cl]. This module
  101. % provides CNF and DNF computation.
  102. %DS
  103. % <SG-DNF> ::= <GOR> . <SGCL>
  104. % <SGCL> ::= (<SGCONJ>,...)
  105. % <SGCONJ> ::= <GAND> . <SATOTVL>
  106. % <GOR> ::= ['or] | ['and]
  107. % <GAND> ::= ['and] | ['or] "opposite to <GOR>"
  108. % <SATOTVL> ::= (<TRUTH VALUE>) | (<ATOMIC FORMULA>, ...)
  109. procedure cl_dnf(f);
  110. % Common logic disjunctive normal form. [f] is a formula. Returns a
  111. % DNF of [f].
  112. rl_simpl(cl_gdnf(f,'or),nil,-1);
  113. procedure cl_cnf(f);
  114. % Common logic conjunctive normal form. [f] is a formula. Returns a
  115. % CNF of [f].
  116. rl_simpl(cl_gdnf(f,'and),nil,-1);
  117. procedure cl_gdnf(f,gor);
  118. % Common logic generic disjunctive normal form. [f] is a formula;
  119. % [gor] is one of [and], [or]. Returns a G-DNF of [f].
  120. begin scalar strictgdnf,gdnf,svrlsiexpla;
  121. f := rl_simpl(rl_nnf f,nil,-1);
  122. svrlsiexpla := !*rlsiexpla;
  123. !*rlsiexpla := nil;
  124. (strictgdnf := cl_strict!-gdnf(f,gor)) where !*rlbnfsm=nil;
  125. if !*rlbnfsm then
  126. strictgdnf := gor . cl_subsume(rl_argn strictgdnf,gor);
  127. !*rlsiexpla := svrlsiexpla;
  128. gdnf := cl_unstrict(strictgdnf,gor);
  129. return gdnf
  130. end;
  131. procedure cl_strict!-gdnf(f,gor);
  132. % Common logic strict generic disjunctive normal form. [f] is a
  133. % formula; [gor] is one of [and], [or]. Returns a strict g-DNF,
  134. % i.e. a formula upto unary [and]'s and [or]'s, which is in g-DNF.
  135. begin scalar w;
  136. w := cl_mkstrict(rl_simpl(cl_strict!-gdnf1(f,gor),nil,-1),gor);
  137. return rl_bnfsimpl(w,gor)
  138. end;
  139. procedure cl_subsume(gcl,gor);
  140. % Common logic subsume. [gcl] is a generic conjunction list; [gor]
  141. % is one of [and], [or]. Returns a generic conjunction list
  142. % equivalent to [gcl]. Performs simplification by subsumption.
  143. begin scalar w;
  144. if null gcl or null cdr gcl then return gcl;
  145. w := cl_subsume1(gcl,gor);
  146. if car w then <<
  147. cddr w := cl_subsume(cddr w,gor);
  148. return cdr w
  149. >>;
  150. return cl_subsume(cdr w,gor)
  151. end;
  152. procedure cl_subsume1(gcl,gor);
  153. % Common logic subsume 1. [gcl] is a generic conjunction list;
  154. % [gor] is one of [and], [or]. A pair $(c,l)$ is returned, where
  155. % $c$ is [nil] or a list of atomic formulas and $l$ is a generic
  156. % conjunction list. [gcl] is modified. The subsumption relation
  157. % beween [car gcl] and all elements of [cdr gcl] is tested. If $c$
  158. % is nil, [car gcl] was suberflous. $l$ is the modified [gcl] in
  159. % which all superflous conjunctions are deleted. If $c$ is non-nil,
  160. % it is [car gcl] and [car gcl] cannot be dropped. If [cl_setrel]
  161. % is used this requires, that [!*rlsiso] and [!*rlidentify] are on.
  162. begin scalar a,w,x,scgcl,oscgcl;
  163. x := cdar gcl;
  164. oscgcl := gcl;
  165. scgcl := cdr gcl;
  166. while scgcl do <<
  167. a := car scgcl; scgcl := cdr scgcl;
  168. w := if !*rlbnfsm then
  169. rl_subsumption(x,cdr a,gor)
  170. else
  171. cl_setrel(x,cdr a,gor);
  172. if w eq 'keep1 then
  173. cdr oscgcl := scgcl
  174. else if w eq 'keep2 then
  175. x := scgcl := nil
  176. else
  177. oscgcl := cdr oscgcl
  178. >>;
  179. if null x then gcl := cdr gcl;
  180. return x . gcl
  181. end;
  182. procedure cl_setrel(l1,l2,gor);
  183. % Common logic set relation. [l1] and [l2] are list of atomic
  184. % formulas. [gor] is one of [and], [or]. Returns [nil], [keep1], or
  185. % [keep2]. If [l1] is a subset of [l2] [keep1] is returned; if [l2]
  186. % is a subset of [l1] [keep2] is returned otherwise [nil] is
  187. % returned.
  188. begin scalar kstate,a1,hlp;
  189. while l1 and l2 and car l1 eq car l2 do <<
  190. l1 := cdr l1;
  191. l2 := cdr l2
  192. >>;
  193. if null (l1 and l2) then <<
  194. if null (l1 or l2) then return 'keep1; % both equal.
  195. return l2 and 'keep1 or 'keep2
  196. >>;
  197. kstate := 'keep1;
  198. if rl_ordatp(car l1,car l2) then <<
  199. hlp := l1; l1 := l2; l2 := hlp;
  200. kstate := 'keep2
  201. >>;
  202. repeat <<
  203. a1 := car l1; l1 := cdr l1;
  204. l2 := memq(a1,l2);
  205. if null l2 then a1 := l1 := nil
  206. >> until null l1;
  207. return a1 and kstate
  208. end;
  209. procedure cl_strict!-gdnf1(f,gor);
  210. % Common logic disjunctive normal form in strict representation.
  211. % [f] is a formula containing no first-order operators but $\land$
  212. % and $\lor$; [gor] is one of ['and], ['or]. Returns a strict g-DNF
  213. % of [f], i.e. a g-disjunction of g-conjunctions of atomic formulas
  214. % including unary $\lor$ and $\land$ if necessary.
  215. begin scalar gand,op,subgdnfl,noop,noopgdnf;
  216. gand := if gor eq 'or then 'and else 'or;
  217. op := rl_op f;
  218. if op eq gor then
  219. return rl_mkn(gor,for each subf in rl_argn(f) join
  220. rl_argn(cl_strict!-gdnf(subf,gor)));
  221. if op eq gand then <<
  222. subgdnfl := for each subf in rl_argn(f) collect
  223. cl_strict!-gdnf(subf,gor);
  224. % Switch to noop form.
  225. noop := for each subf in subgdnfl collect
  226. for each gconj in rl_argn subf collect rl_argn gconj;
  227. % Computing the cartesian product of the conjunctive lists is
  228. % now equivalent to an application of the law of
  229. % distributivity, though the result is not flat yet.
  230. noopgdnf := cl_bnf!-cartprod noop;
  231. % Switch back to our normal representation.
  232. return rl_mkn(gor,for each gconj in noopgdnf collect
  233. rl_mkn(gand,for each x in gconj join append(x,nil)))
  234. >>;
  235. if rl_cxp op and not rl_tvalp op then
  236. rederr {"cl_strict!-gdnf: illegal operator",op,"in BNF computation"};
  237. return rl_mkn(gor,{rl_mkn(gand,{f})})
  238. end;
  239. procedure cl_mkstrict(f,gor);
  240. % Common logic make strict. [f] is a g-DNF. Returns a strict g-DNF,
  241. % possibly including one truth value.
  242. begin scalar op,gand;
  243. gand := cl_flip gor;
  244. op := rl_op f;
  245. if not rl_cxp op or rl_tvalp op then
  246. return rl_mkn(gor,{rl_mkn(gand,{f})});
  247. if op eq gand then
  248. return rl_mkn(gor,{f});
  249. if op neq gor then
  250. rederr {"BUG IN cl_mkstrict"};
  251. return rl_mkn(gor,for each subf in rl_argn f collect
  252. if rl_op subf eq gand then subf else rl_mkn(gand,{subf}))
  253. end;
  254. procedure cl_unstrict(sgdnf,gor);
  255. % Common logic unstrict, [sdnf] is a sg-DNF; [gor] is one of [and],
  256. % [or]. Returns a g-DNF.
  257. rl_smkn(gor,for each conj in rl_argn sgdnf collect
  258. % A unary g-and does not have a cddr, ignore it.
  259. if cdr rl_argn conj then conj else car rl_argn conj);
  260. procedure cl_bnf!-cartprod(s);
  261. % Common logic boolean normal form cartesian product. [s] is a list
  262. % $(s_1,...,s_n)$ of lists. Returns $s_1 \times ... \times s_n$ as
  263. % a list of $n$-element lists. The empty set and singletons are
  264. % their own cartesian product.
  265. if null s or null cdr s then s else cl_bnf!-cartprod1 s;
  266. procedure cl_bnf!-cartprod1(s);
  267. % Common logic boolean normal form cartesian product. [s] is a list
  268. % $(s_1,...,s_n)$ of lists with $n \geq 2$. Returns $s_1 \times ...
  269. % \times s_n$ as a list of $n$-element lists.
  270. begin scalar w;
  271. if null cdr s then
  272. return for each m in car s collect {m};
  273. w := cl_bnf!-cartprod1 cdr s;
  274. return for each m in car s join
  275. for each y in w collect m . y
  276. end;
  277. procedure cl_bnfsimpl(sgdnf,gor);
  278. % Common logic boolean normal form simplification. [sgdnf] is an
  279. % SG-DNF; [gor] is one of the operators [and], [or]. Returns an
  280. % SG-DNF equivalent to [sgdnf]. Performs simplification of [gcl].
  281. % Accesses switch [rlbnfsac].
  282. if !*rlbnfsac then cl_sac(sgdnf,gor) else sgdnf;
  283. procedure cl_sac(sgdnf,gor);
  284. % Common logic subsumption and cut. [sgdnf] is a sg-DNF; [gor] is
  285. % one of [or], [and]. Returns a sg-DNF equivalent to [sgdnf]. This
  286. % procedures performs simplifications based on order theoretical
  287. % subsumption and cut. There are no possible applications of order
  288. % theoretical subsumption and cut between subformulas of the
  289. % returned sg-DNF.
  290. begin scalar w,gand;
  291. if rl_tvalp car rl_argn car rl_argn sgdnf then return sgdnf;
  292. gand := cl_flip(gor);
  293. % switch to noop form
  294. w := for each x in rl_argn sgdnf collect
  295. rl_argn x;
  296. w := cl_applysac(w,gor);
  297. if w eq 'break then
  298. return rl_mkn(gor,{rl_mkn(gand,{cl_cflip('true,gor eq 'or)})});
  299. w := for each x in w join
  300. if x then
  301. {rl_mkn(gand,x)}
  302. else
  303. nil;
  304. if null w then
  305. return rl_mkn(gor,{rl_mkn(gand,{cl_cflip('true,gor eq 'or)})});
  306. return gor . w
  307. end;
  308. procedure cl_applysac(l,gor);
  309. % Common logic apply subsumption and cut. [l] is a list of lists of
  310. % atomic formulas; [gor] is one of [or], [and]. Returns ['break] or
  311. % a list $k$ of list of atomic formulas. If ['break] is returned
  312. % [l] is as a g-DNF equivalent to ['true] in case of ['gor eq 'or]
  313. % and equivalent to ['false] in case ['gor eq 'and]. The lists are
  314. % considered as generic disjunctive normal forms and are in this
  315. % sense equivalent. There is no possible application of order
  316. % theoretical subsumption or cut between elements of $k$.
  317. begin scalar w,ll,res;
  318. ll := l;
  319. while ll do <<
  320. w := cl_applysac1(car ll,res,gor);
  321. if w eq 'break then <<
  322. ll := nil;
  323. res := 'break
  324. >> else <<
  325. ll := cdr ll;
  326. if car w then
  327. res := cdar w . cdr w
  328. else
  329. res := cdr w
  330. >>
  331. >>;
  332. return res
  333. end;
  334. procedure cl_applysac1(c,l,gor);
  335. % Common logic apply subsumption and cut 1. [c] is a list of atomic
  336. % formulas; [l] is a list of list of atomic formulas; [gor] is one
  337. % of [or], [and]. Returns ['break] or a pair $(c' . \lambda)$. If
  338. % ['break] is returned [l] is as a g-DNF equivalent to ['true] in
  339. % case of ['gor eq 'or] and equivalent to ['false] in case ['gor eq
  340. % 'and]. $c'$ is either [nil] or a pair $(\tau . \gamma)$, where
  341. % $\tau$ is one of [T] and [nil] and $\gamma$ is a list of atomic
  342. % formulas. $\lambda$ is a list of list of atomic formulas. If $c'$
  343. % is [nil] then the conjunction over [c] is implied by a
  344. % conjunction over an element in [l]. If $\tau$ is [T] then
  345. % $\gamma$ is equal to $c$, otherwise $\gamma$ is the result of a
  346. % cut between $c$ and an element of $l$. In all cases there is no
  347. % possible application of subsumption or cut between $\gamma$ and
  348. % an arbitrary element of $\lambda$. [l] is modified.
  349. begin scalar w,flg;
  350. flg:=T;
  351. repeat <<
  352. w := cl_applysac2(c,l,gor);
  353. if w eq 'break then <<
  354. w := '(nil); % leave the loop
  355. flg := 'break
  356. >>;
  357. if car w and null caar w then <<
  358. flg:=nil;
  359. c := cdar w;
  360. l := cdr w
  361. >>;
  362. >> until null car w or caar w;
  363. if flg eq 'break then
  364. return 'break;
  365. if null car w then
  366. return w;
  367. return (flg . cdar w) . cdr w
  368. end;
  369. procedure cl_applysac2(c,l,gor);
  370. % Common logic apply subsumption and cut 1. [c] is a list of atomic
  371. % formulas; [l] is a list of list of atomic formulas; [gor] is one
  372. % of [or], [and]. Returns ['break] or a pair ($c'$ . $\lambda$). If
  373. % ['break] is returned [l] is as a g-DNF equivalent to ['true] in
  374. % case of ['gor eq 'or] and equivalent to ['false] in case ['gor eq
  375. % 'and]. $c'$ is either [nil] or a pair $(\tau . \gamma)$, where
  376. % $\tau$ is one of [T] and [nil] and $\gamma$ is a list of atomic
  377. % formulas. $\lambda$ is a list of list of atomic formulas. If $c'$
  378. % is [nil] then the conjunction over [c] is implied by a
  379. % conjunction over an element in [l]. If $\tau$ is [T] then
  380. % $\gamma$ is equal to $c$, otherwise $\gamma$ is the result of a
  381. % cut between $c$ and an element of $l$. [l] is modified. If
  382. % ['break] is returned then the formula $['gor]([c],\phi)$ is
  383. % equivalent to ['true] in the case ['gor eq 'or] or to ['false] in
  384. % the case ['gor eq 'and].
  385. begin scalar w,ll;
  386. if null l then return ( (T . c) . nil);
  387. ll := l;
  388. while ll and ((w := cl_subandcut(c, car ll,gor)) eq 'keep1) do
  389. ll := cdr ll;
  390. if null w then return 'break;
  391. if null ll then return ((T . c) . nil);
  392. if w eq 'keep2 then return (nil . ll);
  393. if w neq 'failed then % [w] is the result of the cut
  394. % between [c] and [car ll].
  395. return (nil . w) . cdr ll;
  396. % We know, that there is no interaction between [c] and [car ll]
  397. w := cl_applysac2(c,cdr ll,gor);
  398. if w eq 'break then
  399. return 'break;
  400. cdr ll := cdr w;
  401. return car w . ll;
  402. end;
  403. procedure cl_subandcut(l1,l2,gor);
  404. % Common logic subsumption and cut. [l1] and [l2] are sorted lists
  405. % of atomic formulas; [gor] is one of ['or], ['and]. Returns
  406. % ['failed], ['keep1], ['keep2] or a list of atomic formulas. Both
  407. % [l1] and [l2] are considered as conjunctions. ['keep1] is
  408. % returned if [l2] subsumes [l1]; ['keep2] is returned if [l1]
  409. % subsumes [l2]. If a list [l] of atomic formulas is returned then
  410. % [l] is the result of a cut between [l1] and [l2]. Both
  411. % subsumption and cut means order theoretical generalizations of
  412. % the respective notions of the propositional calculus.
  413. begin scalar kstate,w,x; integer c;
  414. x := l1; % Save one of [l1] and [l2] for computing a cut.
  415. % Determing the maximal common prefix of [l1] and [l2] and its length.
  416. while l1 and l2 and (car l1 equal car l2) do <<
  417. c := c+1;
  418. l1 := cdr l1; l2 := cdr l2
  419. >>;
  420. if null (l1 and l2) then << % on of [l1] and [l2] are empty
  421. if null (l1 or l2) then return 'keep1; % both equal.
  422. % [l1] is a ``subset'' of [l2] or vice versa.
  423. return (l2 and 'keep1) or 'keep2
  424. >>;
  425. % We have [l1 and l2] and [car l1 neq car l2].
  426. kstate := 'keep1;
  427. w := rl_sacat(car l1,car l2,gor); % [w neq 'keep]
  428. if w eq 'keep2 then <<
  429. kstate := 'keep2;
  430. % swap [l1] and [l2] upto the first element.
  431. w := cdr l1; l1 := cdr l2; l2 := w
  432. >> else if w eq 'keep1 then <<
  433. l1 := cdr l1; l2 := cdr l2
  434. >> else if w then
  435. return cl_trycut(x,c,w,cdr l1,cdr l2)
  436. else if rl_ordatp(car l1,car l2) then << % [car l1 neq car l2]
  437. kstate := 'keep2;
  438. w := l1; l1 := l2; l2 := w
  439. >>;
  440. % Now [l1] is ``shorter'' than [l2]; no cuts are possible.
  441. while l1 do <<
  442. w := cl_sacatl(car l1, l2,gor);
  443. l2 := cdr w; w := car w;
  444. l1 := cdr l1;
  445. if w neq 'keep1 then
  446. l1 := nil % Leave the loop.
  447. >>;
  448. if w eq 'keep1 then return kstate;
  449. return 'failed
  450. end;
  451. procedure cl_trycut(l,c,at,l1,l2);
  452. % Common logic try cut. [l], [l1], and [l2] are lists of atomic
  453. % formulas; [c] is an integer; [at] is an atomic formula or
  454. % ['drop]. Returns ['failed] or a sorted list $\lambda$ of atomic
  455. % formulas. If a cut beween [l1] and [l2] are possible then a list
  456. % of atomic formulas is returned, otherwise [nil] is returned. [l]
  457. % is a list $(a_1,...,a_n)$, [l1] is a list $(c_1,...,c_m)$.
  458. % $lambda$ is a list $(a_1,...,a_c,b,c_1,...,c_m)$, where $b$ is
  459. % the atomic formula [at] if [at] is not [drop], otherwise $b$ is
  460. % ommitted.
  461. begin scalar a;
  462. if null l1 and null l2 then <<
  463. l := for i := 1 : c collect <<
  464. a := car l; l := cdr l; a
  465. >>;
  466. if at eq 'drop then
  467. return sort(l,'rl_ordatp);
  468. return sort(at . l,'rl_ordatp)
  469. >>;
  470. if l1 neq l2 then return 'failed;
  471. % [l1] and [l2] are equal.
  472. for i:=1:c do << l1 := car l . l1; l := cdr l >>;
  473. if at neq 'drop then
  474. l1 := at . l1;
  475. return sort(l1,'rl_ordatp)
  476. end;
  477. % Generic black box implementations.
  478. procedure cl_sacatl(a,l,gor);
  479. % Common logic subsume and cut atomic formula list. [a] is an
  480. % atomic formula; [l] is a sorted list of atomic formulas; [gor] is
  481. % one of [or], [and]. Returns a pair $(\alpha . \lambda)$ where
  482. % $\alpha$ is a relation, ['keep1], or [nil]; [l] is a possibly
  483. % empty list of atomic formulas. $\alpha$ is [T] if [a] is implied
  484. % by an atomic formula from [l]; if $\alpha$ is [nil] then neither
  485. % [a] is implied by an atomic formula from [l] nor a cut between
  486. % [a] and an atomic formula from [l] is possible, otherwise
  487. % $\alpha$ is the result of such a cut. $\lambda$ is the rest of
  488. % [l] not involved in the computation of $\alpha$.
  489. begin scalar w;
  490. if null l then
  491. return '(nil . nil);
  492. if not rl_sacatlp(a,l) then
  493. return (nil . l);
  494. w := rl_sacat(a,car l,gor);
  495. if not w then
  496. return cl_sacatl(a,cdr l,gor);
  497. if w memq '(keep1 keep) then
  498. return ('keep1 . cdr l);
  499. if w eq 'keep2 then
  500. return (nil . cdr l);
  501. return (w . cdr l) % [w] is a relation or [drop]
  502. end;
  503. procedure cl_sacatlp(a,l);
  504. % Common logic subsumption and cut atomic formula list predicate.
  505. % [a] is an atomic formula; [l] is a list of atomic formulas.
  506. % Returns [T] a subsumption or cut beween [a] and an element of [l]
  507. % is possible.
  508. T;
  509. procedure cl_sacat(a1,a2,gor);
  510. % Common logic subsumption and cut atomic formula. [a1] and [a2]
  511. % are atomic formulas; [gor] is one of the operators [or], [and].
  512. % Returns [nil], one of the identifiers [keep], [keep1], [keep2],
  513. % [drop], or an atomic formula. The return value [nil] indicates
  514. % that neither a cut nor a subsumption can be applied. If [keep] is
  515. % returned, then the atomic formulas are identical. In the case of
  516. % [keep1] or [keep2] the corresponding atomic formula can be kept,
  517. % and the other one can be dropped. If an atomic formula $a$ is
  518. % returned, then this atomic formula is the result of the cut
  519. % beween [a1] and [a2]. If [drop] is returned, then a cut with
  520. % result [true] or [false] can be performed.
  521. if a1 = a2 then 'keep else nil;
  522. % ----------------------------------------------------------------------
  523. % Simplification of Boolean normal forms in the style of W. V. Quine.
  524. % ----------------------------------------------------------------------
  525. % The following services are required:
  526. % * rl_simpl
  527. % The following black boxes are required:
  528. % * rl_qscsaat(at) Default: cl_qscsa
  529. % * rl_qssubat(sl,at) Default: cl_qssubat (requires rl_negateat)
  530. % * rl_qsconsens Default: cl_qs1consens (requires rl_qstrycons)
  531. % Default; cl_qsnconsens (requires rl_qstrycons)
  532. % * rl_qsimpltestccl Default: cl_qsimpltestccl (req. rl_qscsa,
  533. % rl_qssubat, rl_qstautp
  534. % rl_qssimpl)
  535. % * rl_qstautp Default: cl_qstautp
  536. % * rl_qssubsumep Default: cl_qssusubymem
  537. % cl_qssusubysi
  538. % cl_qssusubyit (requires rl_simpl)
  539. % cl_qssusubytab (requires rl_qssusuat)
  540. % * rl_qstrycons Default cl_qstrycons (requires rl_negateat)
  541. % * rl_qssimpl Defualt cl_qssibysimpl
  542. % Default cl_qssimpl (requires rl_qssiadd)
  543. % * rl_qssiadd kein default
  544. % Warning: The blackboxes rl_qscsaat and rl_qssubat belong to each
  545. % other. They cannot be implemented independently.
  546. % For rapid prototyping, using only the relation betwen $alpha$ and
  547. % $\overline{\alpha}$ one can use the following assignment of generic
  548. % implementations to black boxes. We use the service rl_simpl and the
  549. % black boxes rl_negateat and rl_ordatp from the general context
  550. % environment.
  551. % * rl_qssubsumep -> cl_qssusubymem
  552. % * rl_qsconsens -> cl_qsnconsens
  553. % * rl_qstrycons -> cl_qstrycons
  554. % * rl_qsimpltestccl -> cl_qsimpltestccl
  555. % * rl_qscsaat -> cl_qscsaat
  556. % * rl_qssubat -> cl_qssubat
  557. % * rl_qstautp -> cl_qstautp
  558. % To gain maximal use of algebraic dependencies between relations one
  559. % have to implement at least the following black boxes in a context
  560. % specific manner: rl_qssubsumep rl_qstrycons rl_qssubat
  561. % TODO: Truth values in BNF
  562. % TODO: List2set vermeiden -> adjoin
  563. % TODO: CNF's
  564. % TODO: rl_simpl beschraenken oder eigenes.
  565. % TODO: Substituierende Simplifikation
  566. procedure cl_quine(f);
  567. % Common logic Quine simplification. [f] is a a formula in a BNF.
  568. % Returns a formula in BNF.
  569. begin scalar w,op,s;
  570. w := cl_bnf2set f;
  571. op := car w;
  572. if not op then
  573. return f;
  574. if op eq 'and then
  575. s := cl_qsnot cdr w
  576. else
  577. s := cdr w;
  578. s := cl_qs(s,'or); % Non generic
  579. if op eq 'and then
  580. s := cl_qsnot s;
  581. return cl_set2bnf(s,op)
  582. end;
  583. procedure cl_qsnot(s);
  584. for each c in s collect cl_qsnot1 c;
  585. procedure cl_qsnot1(c);
  586. for each a in c collect rl_negateat a;
  587. procedure cl_bnf2set(f);
  588. cl_bnf2set1(f,nil);
  589. procedure cl_bnf2set1(f,xop);
  590. % Common logic bnf to set representation. [f] is a formula in bnf.
  591. % Returns a pair $(\gamma,l)$ where $l$ is a list of list of atomic
  592. % formulas and $\gamma$ is [nil] or an operator. if $\gamma$ is
  593. % [or] then [f] is a DNF and $l$ is the set representation of $f$;
  594. % if it is [and] then f is a CNF and again $f$ is a set
  595. % representation of f; if $\gamma$ is [nil] then $l$ is identical
  596. % to [f].
  597. begin scalar op,w;
  598. if rl_tvalp f then
  599. return nil . f;
  600. if not cl_cxfp f then
  601. return nil . {{f}};
  602. op := rl_op f;
  603. if not(op memq '(and or)) then
  604. rederr {"cl_bnf2set: not in bnf: ",f};
  605. w := cl_bnf2set2(rl_argn f,op);
  606. if not car w then % List of atomic formulas, translated to singletons
  607. if op eq xop then
  608. return op . w
  609. else if cl_flip op eq xop then
  610. return op . {rl_argn f}
  611. else
  612. return nil . f;
  613. return op . cdr w
  614. end;
  615. procedure cl_bnf2set2(fl,op);
  616. % Common logic bnf to set representation subroutine. [fl] is a list
  617. % of atomic formulas or flat formulas not containing truth values.
  618. % Returns a pair $(\gamma,l)$ where l is a list of list of atomic
  619. % formulas; $\gamma$ is a flag. If it is [T] then fl contains a
  620. % non-atomic formula.
  621. begin scalar xop,flg,w;
  622. xop := cl_flip op;
  623. w := for each f in fl collect <<
  624. if not cl_cxfp f then
  625. {f}
  626. else if rl_op f eq xop then <<
  627. flg := T;
  628. sort(list2set rl_argn f,'rl_ordatp)
  629. >> else
  630. rederr {"cl_bnf2set1: not in bnf: ",f}
  631. >>;
  632. return flg . list2set w
  633. end;
  634. procedure cl_set2bnf(ll,op);
  635. begin scalar flop;
  636. flop := cl_flip(op);
  637. return rl_smkn(op,for each l in ll collect
  638. rl_smkn(flop,l))
  639. end;
  640. procedure cl_qs(s,op);
  641. % Common logic quine simplification. [s] is a set representation of
  642. % a BNF. [op] is one of [and], [or]. Returns a set representation.
  643. begin scalar w;
  644. if !*rlverbose then
  645. ioto_tprin2 {"[Quine: ",cl_qssize s,"/",length s};
  646. w := cl_qscpi(s,op);
  647. if w eq 'break then <<
  648. ioto_prin2t {" -> 0/0]"};
  649. return {{}} % True for DNF; False for CNF
  650. >>;
  651. if !*rlverbose then
  652. ioto_prin2 {" -> ",cl_qssize w,"/",length w};
  653. return cl_qsselect(w,op);
  654. end;
  655. procedure cl_qscpi(cl,op);
  656. % Common logic quine simplification compute prime implicants. [s]
  657. % is a set representation of a BNF. [op] is one of [and], [or].
  658. % Returns a set representation.
  659. begin scalar firstl,scfirstl,first,secondl,scsecondl,second,newl,w;
  660. newl := cl;
  661. while newl do <<
  662. newl := cl_qssisu(newl,op);
  663. firstl := cl_qssisutwo(firstl,newl,op);
  664. secondl := newl;
  665. newl := nil;
  666. scfirstl := firstl;
  667. while scfirstl do <<
  668. first := car scfirstl;
  669. scfirstl := cdr scfirstl;
  670. scsecondl := secondl;
  671. while scsecondl do <<
  672. second := car scsecondl;
  673. scsecondl := cdr scsecondl;
  674. if not(second eq first) then <<
  675. w := rl_qsconsens(first,second,op);
  676. if w eq 'break then
  677. newl := scsecondl := scfirstl := nil
  678. else
  679. foreach cs in w do
  680. if cs and not(cl_qssubsumelp(cs,firstl,op)) and
  681. not(cs member newl)
  682. then
  683. newl := cs . newl
  684. >>
  685. >> % while scsecondl
  686. >> % while scfirstl
  687. >>; % newl
  688. if (w eq 'break) then
  689. return 'break;
  690. return firstl
  691. end;
  692. procedure cl_qssisu(l,op);
  693. % Simplify by subsumtion. [l] is a list of clauses. Returns a list
  694. % of clauses.
  695. for each x in l join
  696. if not(cl_qssubsumelp(x,delq(x,l),op)) then
  697. {x};
  698. procedure cl_qssisutwo(l1,l2,op);
  699. % Neither to l1 nor to l2 subsumption can be applied. No clause of
  700. % l2 subsumes a clause of l1.
  701. begin scalar w;
  702. w := for each x in l1 join
  703. if not(cl_qssubsumelp(x,l2,op)) then
  704. {x};
  705. return nconc(w,l2)
  706. end;
  707. procedure cl_qssubsumelp(c,cl,op);
  708. % Returns [T] if [c] subsumes one of the clauses in cl.
  709. begin scalar r;
  710. while (cl and not(r)) do <<
  711. r := cl_qssubsumep(c,car cl,op);
  712. cl := cdr cl;
  713. >>;
  714. return r
  715. end;
  716. procedure cl_qssubsumep(c1,c2,op);
  717. if op eq 'or then
  718. rl_qssubsumep(c1,c2,op)
  719. else
  720. rl_qssubsumep(c2,c1,op);
  721. switch psen;
  722. on1 'psen;
  723. procedure cl_qsselect(s,op);
  724. begin scalar w,core,dcs; integer csize,wsize,clen,wlen;
  725. w := cl_qsspltcore(s,op);
  726. core := car w;
  727. dcs := cdr w;
  728. if !*rlverbose then <<
  729. csize := cl_qssize core;
  730. clen := length core;
  731. ioto_prin2 {" -> ",csize,"/",clen,"+",cl_qssize dcs,"/",length dcs}
  732. >>;
  733. dcs := cl_qsrmabsdisp(core,dcs,op);
  734. if !*rlverbose then
  735. ioto_prin2 {" -> ",csize,"/",clen,"+",cl_qssize dcs,"/",length dcs};
  736. if !*psen then
  737. w := cl_qsselect2(core,dcs,op)
  738. else
  739. w := cl_qsselect1(core,dcs,cl_subsets dcs,op);
  740. if !*rlverbose then <<
  741. wsize := cl_qssize w;
  742. wlen := length w;
  743. ioto_prin2t {" -> ",csize,"/",clen,"+",wsize,"/",wlen,
  744. " = ",csize+wsize,"/",clen+wlen,"]"}
  745. >>;
  746. w := nconc(w,core);
  747. return w;
  748. end;
  749. procedure cl_qsselect1(core,dcs,potdcs,op);
  750. begin scalar r,w;
  751. potdcs := cdr reversip potdcs;
  752. while potdcs and not(r) do <<
  753. w := setdiff(dcs,car potdcs);
  754. if cl_qsimpltestclcl(car potdcs,append(core,w),op) then
  755. r := w;
  756. potdcs := cdr potdcs;
  757. >>;
  758. return r
  759. end;
  760. procedure cl_qsselect2(core,dcs,op);
  761. begin scalar r,w,kstate,potdcs;
  762. kstate := dcs . nil;
  763. cl_ps kstate; % Remove leading nil;
  764. while (potdcs:=cl_ps kstate) neq 'final and not(r) do <<
  765. w := setdiff(dcs,potdcs);
  766. if cl_qsimpltestclcl(w,append(core,potdcs),op) then
  767. r := potdcs;
  768. >>;
  769. return r
  770. end;
  771. procedure cl_qsspltcore(s,op);
  772. begin scalar core,dcs;
  773. for each x in s do
  774. if rl_qsimpltestccl(x,delq(x,s),op) then
  775. dcs := x . dcs
  776. else
  777. core := x . core;
  778. return core . dcs;
  779. end;
  780. procedure cl_qsrmabsdisp(core,dcs,op);
  781. for each c in dcs join
  782. if not(rl_qsimpltestccl(c,core,op)) then
  783. {c};
  784. procedure cl_qsimpltestclcl(pl,cl,op);
  785. % quine simplification implication test clauses list clauses list.
  786. % [pl] is the list of all premise clauses; [cl] is the list of all
  787. % conclusion clauses; [op] is one of [and] or [or]. Returns [T] or
  788. % [nil].
  789. begin scalar r;
  790. r := T;
  791. while pl and r do <<
  792. r := rl_qsimpltestccl(car pl,cl,op);
  793. pl := cdr pl;
  794. >>;
  795. return r
  796. end;
  797. procedure cl_subsets(l);
  798. sort(cl_subsets1 l,'cl_lengthp);
  799. procedure cl_lengthp(l1,l2);
  800. length l1 < length l2;
  801. procedure cl_subsets1(l);
  802. begin scalar w,r,x;
  803. if null l then
  804. return {nil};
  805. w := cl_subsets1 cdr l;
  806. x := car l;
  807. for each y in w do
  808. r := (x . y) . r;
  809. return nconc(r,w)
  810. end;
  811. procedure cl_qssize(s);
  812. for each x in s sum length x;
  813. %------------------------------------------------------------------------
  814. % Generic Implementations of rl_qssubsumep
  815. %------------------------------------------------------------------------
  816. procedure cl_qssusubysi(c1,c2,op);
  817. % Subsumtion by Simplification.
  818. rederr "Out of order -> ueber rl_simpl";
  819. % cl_qssimplc1(c2,c1,op) eq 'true;
  820. procedure cl_qssusubyit(c1,c2,op);
  821. % Subsumtion by implication test.
  822. cl_qsimpltestcc(c1,c2,op) eq 'true;
  823. procedure cl_qssusubymem(c1,c2,op);
  824. % Subsumtion by member. Returns [T] is [c1] g-subsumes [c2] and
  825. % hence [c1] implies [c2].
  826. begin scalar l1,l2;
  827. l1 := length c1;
  828. l2 := length c2;
  829. if not(l1>=l2) then
  830. return nil;
  831. return cl_qssusubymem1(c1,c2)
  832. end;
  833. procedure cl_qssusubymem1(c1,c2);
  834. begin scalar r;
  835. r := T;
  836. while c2 and r do <<
  837. if not(car c2 member c1) then
  838. r := nil;
  839. c2 := cdr c2;
  840. >>;
  841. return r
  842. end;
  843. procedure cl_qssusubytab(c1,c2,op);
  844. % Subsumtion by table. Returns [T] is [c1] g-subsumes [c2] and
  845. % hence [c1] implies [c2].
  846. begin scalar l1,l2;
  847. l1 := length c1;
  848. l2 := length c2;
  849. if not(l1>=l2) then
  850. return nil;
  851. return cl_qssusubytab1(c1,c2,op)
  852. end;
  853. procedure cl_qssusubytab1(c1,c2,op);
  854. % Subsumtion by table. Returns [T] is [c1] g-subsumes [c2] and
  855. % hence [c1] implies [c2].
  856. begin scalar r;
  857. r := T;
  858. while c2 and r do <<
  859. r := cl_qssusubytab2(c1,car c2,op);
  860. c2 := cdr c2
  861. >>;
  862. return r
  863. end;
  864. procedure cl_qssusubytab2(c1,a,op);
  865. begin scalar r;
  866. while c1 and not(r) do <<
  867. r := rl_qssusuat(car c1,a,op);
  868. c1 := cdr c1
  869. >>;
  870. return r
  871. end;
  872. %------------------------------------------------------------------------
  873. % Generic implementations of rl_qssimpl
  874. %------------------------------------------------------------------------
  875. % Variant 1: Special simplifier
  876. procedure cl_qssimpl(s,theo,op);
  877. begin scalar r,a,w,ats;
  878. while s and not(rl_tvalp r) do <<
  879. a := car s;
  880. w := cl_qssimplc(a,theo,op);
  881. if w eq 'true then
  882. r := 'true
  883. else if w neq 'false then
  884. r := w . r;
  885. s := cdr s;
  886. >>;
  887. if r eq 'true then
  888. 'true;
  889. w := nconc(ats,r);
  890. return if null w then
  891. 'false
  892. else w
  893. end;
  894. procedure cl_qssimplc(c,theo,op);
  895. % simplification of one clause.
  896. begin scalar r,a;
  897. while c and r neq 'false do <<
  898. a := car c;
  899. if a eq 'false then
  900. r := 'false
  901. else if a neq 'true then
  902. r := rl_qssiadd(a,r,theo,op);
  903. c := cdr c;
  904. >>;
  905. return if null r then
  906. 'true
  907. else
  908. r
  909. end;
  910. % Variant 1: Using rl_simpl
  911. procedure cl_qssibysimpl(s,theo,op);
  912. begin scalar !*rlsiexpla,!*rlsiexpl,f,w;
  913. f := rl_simpl(cl_set2bnf(s,op),nil,-1);
  914. if rl_tvalp f then
  915. return f;
  916. w := cl_bnf2set1(f,'or);
  917. return cdr w
  918. end;
  919. %------------------------------------------------------------------------
  920. % Generic implementations of rl_qsimpltestccl
  921. %------------------------------------------------------------------------
  922. procedure cl_qsimpltestccl(cp,clc,op);
  923. % .. clause clauses list.
  924. begin scalar w,r,sl;
  925. sl := cl_qscsa cp;
  926. while clc and r neq 'true do <<
  927. w := cl_qsimpltestcc1(sl,cp,car clc,op);
  928. if w eq 'true then
  929. r := 'true
  930. else if w neq 'false then
  931. r := w . r;
  932. clc := cdr clc;
  933. >>;
  934. % w := cl_qssimplf(rl_smkn(op,r),nil);
  935. % if not rl_tvalp w and cl_qe(rl_all(w,nil)) eq 'true then
  936. % rederr {"cl_asimpltestcc: computed non-atomic formula:",w};
  937. return rl_qstautp r
  938. end;
  939. procedure cl_qsimpltestcc(cp,cc,op);
  940. cl_qsimpltestcc1(cl_qscsa cp,cp,cc,op);
  941. procedure cl_qsimpltestcc1(sl,cp,cc,op); % TODO
  942. begin scalar w;
  943. w := rl_qssimpl({cl_qssubc(sl,cc)},nil,op); % Warnung: Clause -> Clause
  944. return if rl_tvalp w then
  945. w
  946. else if cdr w then
  947. rederr {"cl_qssimpltestcc1: Unexpected complex formula",w}
  948. else
  949. car w
  950. end;
  951. procedure cl_qstautp(f);
  952. if f eq 'true then
  953. T
  954. else if f eq 'false then
  955. nil
  956. else
  957. (cl_qscpi(f,'or)) eq 'break;
  958. procedure cl_qscsa(c);
  959. % Compute satisfying assignment.
  960. for each a in c collect
  961. rl_qscsaat a;
  962. procedure cl_qssub(pl,s);
  963. for each c in s collect
  964. cl_qssubc(pl,c);
  965. procedure cl_qssubc(pl,c);
  966. for each a in c collect
  967. rl_qssubat(pl,a);
  968. %------------------------------------------------------------------------
  969. % Generic Implementations of rl_qscsaat
  970. %------------------------------------------------------------------------
  971. procedure cl_qscsaat(a);
  972. a;
  973. %------------------------------------------------------------------------
  974. % Generic Implementations of rl_qscsaat
  975. %------------------------------------------------------------------------
  976. procedure cl_qssubat(pl,a);
  977. if a member pl then
  978. 'true
  979. else if rl_negateat(a) member pl then
  980. 'false
  981. else
  982. a;
  983. %------------------------------------------------------------------------
  984. % Generic Implementations of rl_qsconsens
  985. %------------------------------------------------------------------------
  986. % First variant: Assume there is maximal one consens of two clauses.
  987. procedure cl_qs1consens(c1,c2,op);
  988. % consens computation of 1 consensus. [c1] and [c2] are clausels.
  989. % Computes the unique determined consenus of [c1] and [c2] provided
  990. % it exists.
  991. begin scalar l1,l2,w;
  992. l1 := length c1;
  993. l2 := length c2;
  994. w := if l1<l2 then
  995. cl_qs1consens1(c1,c2,op)
  996. else
  997. cl_qs1consens1(c2,c1,op);
  998. return if w eq 'break then 'break else {w};
  999. end;
  1000. procedure cl_qs1consens1(c1,c2,op);
  1001. begin scalar w,sc1;
  1002. sc1 := c1;
  1003. while sc1 and not(w) do <<
  1004. w := rl_qstrycons(car sc1,c1,c2,op);
  1005. sc1 := cdr sc1
  1006. >>;
  1007. return w
  1008. end;
  1009. % Second variant: Multiple consensus of two claues allowed.
  1010. procedure cl_qsnconsens(c1,c2,op);
  1011. % consens computation of n consensus. [c1] and [c2] are clausels.
  1012. % Computes the unique determined consenus of [c1] and [c2] provided
  1013. % it exists.
  1014. begin scalar l1,l2;
  1015. l1 := length c1;
  1016. l2 := length c2;
  1017. return if l1<l2 then
  1018. cl_qsnconsens1(c1,c2,op)
  1019. else
  1020. cl_qsnconsens1(c2,c1,op)
  1021. end;
  1022. procedure cl_qsnconsens1(c1,c2,op);
  1023. begin scalar w,r,sc1;
  1024. sc1 := c1;
  1025. while sc1 and w neq 'break do <<
  1026. w := rl_qstrycons(car sc1,c1,c2,op);
  1027. if w then
  1028. r := w . r;
  1029. sc1 := cdr sc1;
  1030. >>;
  1031. return if w eq 'break then 'break else r
  1032. end;
  1033. %------------------------------------------------------------------------
  1034. % Generic Implementations of rl_qstrycons
  1035. %------------------------------------------------------------------------
  1036. procedure cl_qstrycons(a,c1,c2,op);
  1037. % quine simplification try consensus. [a] is an atomic formula,
  1038. % [c1] and [c2] are clauses, op is one of ['and], ['or]. Returns
  1039. % [T], [nil] or [break].
  1040. begin scalar na,sc1,r,cc1;
  1041. cc1 := delete(a,c1); % Copy... % TODO: delq or delete?
  1042. na := rl_negateat a;
  1043. if not(na member c2) then
  1044. return nil;
  1045. sc1 := cc1;
  1046. r := T;
  1047. while sc1 and r do <<
  1048. if rl_negateat car sc1 member c2 then
  1049. r := nil;
  1050. sc1 := cdr sc1;
  1051. >>;
  1052. if not r then
  1053. return nil;
  1054. r := sort(list2set append(cc1,delete(na,c2)),'rl_ordatp); %TODO: nconc
  1055. if null r then
  1056. return 'break;
  1057. return r
  1058. end;
  1059. % ------------------------------------------------------------------------
  1060. % Enumeration of power set
  1061. % ------------------------------------------------------------------------
  1062. %DS
  1063. % <STATE> ::= l . [z_1,...,z_n]
  1064. % Der pointer $v_n$ steht immer vor $v_n-1$
  1065. procedure cl_ps(s);
  1066. % [s] is a STATE. Returns an element of thepower set. Modifies [s].
  1067. begin scalar v,w,r; integer i,n;
  1068. v := cdr s;
  1069. if cdr s eq 'final then
  1070. return 'final;
  1071. if null cdr s then
  1072. v := cdr s := mkvect (length car s-1);
  1073. n := upbv v;
  1074. while i<=n and (w:=getv(v,i)) do <<
  1075. r := car w . r;
  1076. i:=i+1;
  1077. >>;
  1078. cl_psnext s;
  1079. return r
  1080. end;
  1081. procedure cl_psnext(s);
  1082. cl_psnext1(s,0);
  1083. procedure cl_psnext1(s,n);
  1084. begin scalar w,v;
  1085. v := cdr s;
  1086. if n > upbv v then
  1087. return cdr s := 'final; % Mark and return;
  1088. w := getv(v,n);
  1089. if null w then % Introduce pointer
  1090. return putv(v,n,car s);
  1091. w := cdr w; % Try to move
  1092. if w then % Success
  1093. return putv(v,n,w);
  1094. % Overflow occurs.
  1095. repeat <<
  1096. w := cl_psnext1(s,n+1);
  1097. if w neq 'final then
  1098. w := cdr getv(v,n+1);
  1099. >> until w;
  1100. if w eq 'final then
  1101. return 'final;
  1102. putv(v,n,w)
  1103. end;
  1104. endmodule; % [clbnf]
  1105. end; % of file