@@ -11,6 +11,7 @@ import org.edla.port.atp.Formulas.{And, Atom, False, Formula, Iff, Imp, Not, Or,
11
11
import org .edla .study .parsing .parboiled .PropositionalLogic
12
12
import org .parboiled2 .{ErrorFormatter , ParseError }
13
13
import org .parboiled2 .ParserInput .apply
14
+ import org .edla .port .atp .Lib ._
14
15
15
16
object Prop {
16
17
@@ -19,7 +20,7 @@ object Prop {
19
20
// Parsing of propositional formulas. //
20
21
// ------------------------------------------------------------------------- //
21
22
22
- def parse_prop_formula (s : String ) = {
23
+ def parse_prop_formula (s : String ): Formula = {
23
24
val parser = new PropositionalLogic (s)
24
25
val expr = parser.expr.run() match {
25
26
case Success (expr) => expr
@@ -52,7 +53,7 @@ object Prop {
52
53
// Return the set of propositional variables in a formula. //
53
54
// ------------------------------------------------------------------------- //
54
55
55
- def atoms (fm : Formula ) = atom_union((a : Atom ) => ( a :: Nil ) , fm) map (_.name)
56
+ def atoms (fm : Formula ): List [ String ] = atom_union((a : Atom ) => a :: Nil , fm) map (_.name)
56
57
57
58
// pg. 35
58
59
// ------------------------------------------------------------------------- //
@@ -62,22 +63,21 @@ object Prop {
62
63
def onallvaluations (subfn : (String => Boolean ) => Boolean , v : String => Boolean , ats : List [String ]): Boolean = {
63
64
ats match {
64
65
case Nil => subfn(v)
65
- case p :: ps => {
66
+ case p :: ps =>
66
67
def v_ (t : Boolean )(q : String ) = if (q == p) t else v(q)
67
68
onallvaluations(subfn, v_(false ), ps) && onallvaluations(subfn, v_(true ), ps)
68
- }
69
69
}
70
70
}
71
71
72
72
def print_truthtable (fm : Formula ): Unit = {
73
- val ats = atoms(fm)
74
- val width = ats.foldRight(0 )((x, y) => Math .max(x.length, y)) + 5 + 1
75
- def fixw (s : String ) = s """ ${s}${" " * (width - s.length)}"""
76
- def truthstring (p : Boolean ) = fixw(if (p) " true" else " false" )
73
+ val ats = atoms(fm)
74
+ val width = ats.foldRight(0 )((x, y) => Math .max(x.length, y)) + 5 + 1
75
+ def fixw (s : String ) = s """ ${s}${" " * (width - s.length)}"""
76
+ def truthstring (p : Boolean ) = fixw(if (p) " true" else " false" )
77
77
def lis (v : String => Boolean ) = ats.map(x => truthstring(v(x)))
78
78
def ans (v : String => Boolean ) = truthstring(eval(fm)(v))
79
79
def mk_row (v : String => Boolean ) = { println(lis(v).foldRight(" | " + ans(v))((x, y) => x + y)); true }
80
- val separator = " -" * (width * ats.length + 9 )
80
+ val separator = " -" * (width * ats.length + 9 )
81
81
println(ats.foldRight(" | formula" )((x, y) => fixw(x) + y))
82
82
println(separator)
83
83
onallvaluations(mk_row, (s : String ) => false , ats)
@@ -89,7 +89,7 @@ object Prop {
89
89
// Recognizing tautologies. //
90
90
// ------------------------------------------------------------------------- //
91
91
92
- def tautology (fm : Formula ) = onallvaluations(eval(fm) _ , (s : String ) => false , atoms(fm))
92
+ def tautology (fm : Formula ): Boolean = onallvaluations(eval(fm), (s : String ) => false , atoms(fm))
93
93
94
94
// pg. 48
95
95
// ------------------------------------------------------------------------- //
@@ -152,16 +152,16 @@ object Prop {
152
152
// Some operations on literals. //
153
153
// ------------------------------------------------------------------------- //
154
154
155
- def negative (fm : Formula ) = {
155
+ def negative (fm : Formula ): Boolean = {
156
156
fm match {
157
157
case Not (p) => true
158
158
case _ => false
159
159
}
160
160
}
161
161
162
- def positive (lit : Formula ) = ! negative(lit)
162
+ def positive (lit : Formula ): Boolean = ! negative(lit)
163
163
164
- def negate (fm : Formula ) = {
164
+ def negate (fm : Formula ): Formula = {
165
165
fm match {
166
166
case Not (p) => p
167
167
case p => Not (p)
@@ -224,12 +224,12 @@ object Prop {
224
224
// Disjunctive normal form (DNF) via truth tables. //
225
225
// ------------------------------------------------------------------------- //
226
226
227
- def list_conj (l : List [Formula ]) = {
228
- l.foldRight[Formula ](True )(And (_, _) )
227
+ def list_conj (l : List [Formula ]): Formula = {
228
+ l.foldRight[Formula ](True )(And )
229
229
}
230
230
231
- def list_dij (l : List [Formula ]) = {
232
- l.foldRight[Formula ](False )(Or (_, _) )
231
+ def list_disj (l : List [Formula ]): Formula = {
232
+ l.foldRight[Formula ](False )(Or )
233
233
}
234
234
235
235
// pg. 57
@@ -239,9 +239,9 @@ object Prop {
239
239
240
240
def distrib (fm : Formula ): Formula = {
241
241
fm match {
242
- case And (p, ( Or (q, r) )) => Or (distrib(And (p, q)), distrib(And (p, r)))
243
- case And (Or (p, q), r) => Or (distrib(And (p, r)), distrib(And (q, r)))
244
- case _ => fm
242
+ case And (p, Or (q, r)) => Or (distrib(And (p, q)), distrib(And (p, r)))
243
+ case And (Or (p, q), r) => Or (distrib(And (p, r)), distrib(And (q, r)))
244
+ case _ => fm
245
245
}
246
246
}
247
247
@@ -259,7 +259,7 @@ object Prop {
259
259
// ------------------------------------------------------------------------- //
260
260
261
261
// http://stackoverflow.com/questions/11803349/composing-a-list-of-all-pairs
262
- def distrib (s1 : List [List [Formula ]], s2 : List [List [Formula ]]) = {
262
+ def distrib (s1 : List [List [Formula ]], s2 : List [List [Formula ]]): List [ List [ Formula ]] = {
263
263
for (x <- s1; y <- s2) yield x.union(y)
264
264
}
265
265
@@ -278,8 +278,53 @@ object Prop {
278
278
// ------------------------------------------------------------------------- //
279
279
280
280
def trivial (lits : List [Formula ]): Boolean = {
281
- val (pos, neg) = lits.partition(positive(_))
282
- ! pos.intersect(neg.map(negate(_))).isEmpty
281
+ val (pos, neg) = lits.partition(positive)
282
+ pos.intersect(neg.map(negate)).nonEmpty
283
+ }
284
+
285
+ // pg. 59
286
+ // ------------------------------------------------------------------------- //
287
+ // With subsumption checking, done very naively (quadratic). //
288
+ // ------------------------------------------------------------------------- //
289
+
290
+ def simpdnf (fm : Formula ): List [List [Formula ]] = {
291
+ if (fm == False ) Nil
292
+ else if (fm == True ) List (Nil )
293
+ else {
294
+ val djs = purednf(nnf(fm)).filter((f : List [Formula ]) => ! trivial(f))
295
+ djs.filter(d => ! djs.exists(psubset(_, d)))
296
+ }
297
+ }
298
+
299
+ // pg. 59
300
+ // ------------------------------------------------------------------------- //
301
+ // Mapping back to a formula. //
302
+ // ------------------------------------------------------------------------- //
303
+
304
+ def dnf (fm : Formula ): Formula = {
305
+ list_disj(simpdnf(fm).map(list_conj))
306
+ }
307
+
308
+ // pg. 60
309
+ // ------------------------------------------------------------------------- //
310
+ // Conjunctive normal form (CNF) by essentially the same code. //
311
+ // ------------------------------------------------------------------------- //
312
+
313
+ def purecnf (fm : Formula ): List [List [Formula ]] = {
314
+ purednf(nnf(Not (fm))).map(_.map(negate))
315
+ }
316
+
317
+ def simpcnf (fm : Formula ): List [List [Formula ]] = {
318
+ if (fm == False ) List (Nil )
319
+ else if (fm == True ) Nil
320
+ else {
321
+ val cjs = purecnf(fm).filter((f : List [Formula ]) => ! trivial(f))
322
+ cjs.filter(c => ! cjs.exists(psubset(_, c)))
323
+ }
324
+ }
325
+
326
+ def cnf (fm : Formula ): Formula = {
327
+ list_conj(simpcnf(fm).map(list_disj))
283
328
}
284
329
285
330
}
0 commit comments