1 -- CLAUSIFY: Reducing Propositions to Clausal Form
2 -- Colin Runciman, University of York, 10/90
4 -- An excellent benchmark is: (a = a = a) = (a = a = a) = (a = a = a)
6 -- Optimised version: based on Runciman & Wakeling [1993]
7 -- Patrick Sansom, University of Glasgow, 2/94
9 module Main ( main ) where
11 -- the main program: reads stdin and writes stdout
12 main = _scc_ "CAF:main"
15 putStr (clausify input)
17 -- convert lines of propostions input to clausal forms
18 clausify input = _scc_ "clausify"
20 (interleave (repeat "prop> ")
21 (map clausifyline (lines input)))
23 clausifyline = _scc_ "CAF:clausifyline"
24 concat . map disp . clauses . parse
26 -- the main pipeline from propositional formulae to printed clauses
27 clauses = _scc_ "CAF:clauses" unicl . split . disin . negin . elim
29 -- clauses = (_scc_ "unicl" unicl) . (_scc_ "split" split) .
30 -- (_scc_ "disin" disin) . (_scc_ "negin" negin) .
31 -- (_scc_ "elim" elim)
33 -- clauses = (\x -> _scc_ "unicl" unicl x) .
34 -- (\x -> _scc_ "split" split x) .
35 -- (\x -> _scc_ "disin" disin x) .
36 -- (\x -> _scc_ "negin" negin x) .
37 -- (\x -> _scc_ "elim" elim x)
39 data StackFrame = Ast Formula | Lex Char
49 -- separate positive and negative literals, eliminating duplicates
50 clause p = _scc_ "clause"
52 clause' (Dis p q) x = clause' p (clause' q x)
53 clause' (Sym s) (c,a) = (insert s c , a)
54 clause' (Not (Sym s)) (c,a) = (c , insert s a)
58 conjunct p = _scc_ "conjunct"
63 -- shift disjunction within conjunction
64 disin p = _scc_ "disin"
66 (Con p q) -> Con (disin p) (disin q)
67 (Dis p q) -> disin' (disin p) (disin q)
70 -- auxilary definition encoding (disin . Dis)
71 disin' p r = _scc_ "disin'"
73 (Con p q) -> Con (disin' p r) (disin' q r)
75 (Con q r) -> Con (disin' p q) (disin' p r)
78 -- format pair of lists of propositional symbols as clausal axiom
81 (l,r) -> interleave l spaces ++ "<="
82 ++ interleave spaces r ++ "\n"
84 -- eliminate connectives other than not, disjunction and conjunction
88 (Not p) -> Not (elim p)
89 (Dis p q) -> Dis (elim p) (elim q)
90 (Con p q) -> Con (elim p) (elim q)
91 (Imp p q) -> Dis (Not (elim p)) (elim q)
92 (Eqv f f') -> Con (elim (Imp f f')) (elim (Imp f' f))
94 -- remove duplicates and any elements satisfying p
95 filterset p s = _scc_ "filterset"
98 filterset' res p l = _scc_ "filterset'"
101 (x:xs) -> if (notElem x res) && (p x) then
102 x : filterset' (x:res) p xs
106 -- insertion of an item into an ordered list
107 insert x l = _scc_ "insert"
110 (y:ys) -> if x < y then x:(y:ys)
111 else if x > y then y : insert x ys
114 interleave xs ys = _scc_ "interleave"
116 (x:xs) -> x : interleave ys xs
119 -- shift negation to innermost positions
120 negin f = _scc_ "negin"
122 (Not (Not p)) -> negin p
123 (Not (Con p q)) -> Dis (negin (Not p)) (negin (Not q))
124 (Not (Dis p q)) -> Con (negin (Not p)) (negin (Not q))
125 (Dis p q) -> Dis (negin p) (negin q)
126 (Con p q) -> Con (negin p) (negin q)
129 -- the priorities of symbols during parsing
130 opri c = _scc_ "opri"
139 -- parsing a propositional formula
140 parse t = _scc_ "parse"
141 let [Ast f] = parse' t []
144 parse' cs s = _scc_ "parse'"
147 (' ':t) -> parse' t s
148 ('(':t) -> parse' t (Lex '(' : s)
149 (')':t) -> let (x : Lex '(' : s') = redstar s
151 (c:t) -> if inRange ('a','z') c then
152 parse' t (Ast (Sym c) : s)
153 else if spri s > opri c then parse' (c:t) (red s)
154 else parse' t (Lex c : s)
156 -- reduction of the parse stack
159 (Ast p : Lex '=' : Ast q : s) -> Ast (Eqv q p) : s
160 (Ast p : Lex '>' : Ast q : s) -> Ast (Imp q p) : s
161 (Ast p : Lex '|' : Ast q : s) -> Ast (Dis q p) : s
162 (Ast p : Lex '&' : Ast q : s) -> Ast (Con q p) : s
163 (Ast p : Lex '~' : s) -> Ast (Not p) : s
165 -- iterative reduction of the parse stack
166 redstar = _scc_ "CAF:redstar"
167 while ((/=) 0 . spri) red
169 spaces = _scc_ "CAF:spaces"
172 -- split conjunctive proposition into a list of conjuncts
173 split p = _scc_ "split"
175 split' (Con p q) a = split' p (split' q a)
180 -- priority of the parse stack
181 spri s = _scc_ "spri"
183 (Ast x : Lex c : s) -> opri c
186 -- does any symbol appear in both consequent and antecedant of clause
187 tautclause p = _scc_ "tautclause"
189 (c,a) -> -- [x | x <- c, x `elem` a] /= []
190 any (\x -> x `elem` a) c
192 -- form unique clausal axioms excluding tautologies
193 unicl = _scc_ "CAF:unicl"
194 filterset (not . tautclause) . map clause
196 -- functional while loop
197 while p f x = _scc_ "while"
198 if p x then while p f (f x) else x