diff --git a/testcases/SatFun.scala b/testcases/SatFun.scala index 8dc7995c17f63c141052ec630c79b19b2d5b7997..6bc9ed4e259e0acbc478d989cee163423f6eb910 100644 --- a/testcases/SatFun.scala +++ b/testcases/SatFun.scala @@ -8,7 +8,7 @@ object SatFun { case class Not(f: Formula) extends Formula case class Var(i: Int) extends Formula - //vars are numbered from 1 to n, and Not(Var(n)) is represented as -n + //vars are numbered from 2 to n+1, and Not(Var(n)) is represented as -n. 1 is true and -1 is false sealed abstract class VarList case class VarCons(head: Int, tail: VarList) extends VarList case class VarNil() extends VarList @@ -47,44 +47,40 @@ object SatFun { case VarLit(b) => b } - def vars(formula: Formula): Set[Int] = formula match { - case Var(n) => Set(n) - case Not(f) => vars(f) - case And(f1, f2) => vars(f1) ++ vars(f2) - case Or(f1, f2) => vars(f1) ++ vars(f2) - } - def concatClauses(cll1: ClauseList, cll2: ClauseList): ClauseList = cll1 match { case ClauseCons(cl, tail) => ClauseCons(cl, concatClauses(tail, cll2)) case ClauseNil() => cll2 - case cl@ClauseLit(_) => ClauseCons(cl, clls) + case ClauseLit(b) => ClauseCons(VarLit(b), cll2) } def concatVars(l1: VarList, l2: VarList): VarList = l1 match { case VarCons(v, vs) => VarCons(v, concatVars(vs, l2)) case VarNil() => l2 - case v@VarLit(_) => VarCons(v, vs) + case VarLit(b) => if(b) VarCons(1, l2) else VarCons(-1, l2) } def distributeClause(cl: VarList, cll: ClauseList): ClauseList = cll match { case ClauseCons(cl2, cl2s) => ClauseCons(concatVars(cl, cl2), distributeClause(cl, cl2s)) case ClauseNil() => ClauseNil() - case cl@ClauseLit(b) => ClauseCons(cl, clls) + case ClauseLit(b) => if(b) ClauseCons(VarCons(1, cl), ClauseNil()) else ClauseCons(VarCons(-1, cl), ClauseNil()) } def distribute(cll1: ClauseList, cll2: ClauseList): ClauseList = cll1 match { case ClauseCons(cl, cls) => concatClauses(distributeClause(cl, cll2), distribute(cls, cll2)) case ClauseNil() => cll2 + case ClauseLit(b) => distributeClause(VarLit(b), cll2) } def negateClauses(cll: ClauseList): ClauseList = cll match { case ClauseCons(cl, cls) => ClauseCons(negateVars(cl), negateClauses(cls)) case ClauseNil() => ClauseNil() + case ClauseLit(b) => ClauseLit(!b) } def negateVars(lst: VarList): VarList = lst match { case VarCons(v, vs) => VarCons(-v, negateVars(vs)) case VarNil() => VarNil() + case VarLit(b) => VarLit(!b) } def cnfNaive(formula: Formula): ClauseList = formula match { @@ -104,7 +100,6 @@ object SatFun { case Not(Var(n)) => ClauseCons(VarCons(-n, VarNil()), ClauseNil()) case Var(n) => ClauseCons(VarCons(n, VarNil()), ClauseNil()) } - def dnfNaive(formula: Formula): ClauseList = formula match { case And(f1, f2) => { val dnf1 = dnfNaive(f1) @@ -122,47 +117,80 @@ object SatFun { case Not(Var(n)) => ClauseCons(VarCons(-n, VarNil()), ClauseNil()) case Var(n) => ClauseCons(VarCons(n, VarNil()), ClauseNil()) } + def property1(formula: Formula, assignment: Map[Int, Boolean]): Boolean = { + val dnfFormula = dnfNaive(formula) + eval(formula, assignment) == evalDnf(dnfFormula, assignment) + } ensuring(_ == true) + + def vars(formula: Formula): Set[Int] = formula match { + case Var(n) => Set(n) + case Not(f) => vars(f) + case And(f1, f2) => vars(f1) ++ vars(f2) + case Or(f1, f2) => vars(f1) ++ vars(f2) + } def isContradictory(clause: VarList, vars: Set[Int]): Boolean = clause match { - case VarCons(v, vs) => vars.contains(-v) || isContradictory(vs, vars ++ Set(v)) + case VarCons(v, vs) => vars.contains(-v) || vars.contains(-1) || isContradictory(vs, vars ++ Set(v)) case VarNil() => false + case VarLit(b) => !b } - def isSatDnf(clauses: ClauseList): Boolean = clauses match { case ClauseCons(cl, cls) => !isContradictory(cl, Set.empty) || isSatDnf(cls) case ClauseNil() => false + case ClauseLit(b) => b } - + //for substitute we assume we are dealing with a cnf formula def substitute(formula: ClauseList, variable: Int, value: Boolean): ClauseList = formula match { case ClauseNil() => ClauseNil() - case ClauseCons(cl, cls) => + case ClauseCons(cl, cls) => ClauseCons(substitute(cl, variable, value), substitute(cls, variable, value)) + case ClauseLit(b) => ClauseLit(b) } def substitute(vars: VarList, variable: Int, value: Boolean): VarList = vars match { case VarNil() => VarNil() - case VarCons(v, vs) => if(v == variable) - } - - def choose(formula: ClauseList): Int = { - formula.head.head + case VarLit(b) => VarLit(b) + case VarCons(v, vs) => + if (v == variable && value) VarLit(true) + else if(v == variable && !value) substitute(vs, variable, value) + else if(v == -variable && value) substitute(vs, variable, value) + else if(v == -variable && !value) VarLit(true) + else VarCons(v, substitute(vs, variable, value)) + } + + def choose(formula: ClauseList): Int = formula match { + case ClauseCons(varList, cls) => varList match { + case VarCons(head, vs) => head + case VarNil() => 0 + case VarLit(b) => 0 + } + case ClauseNil() => 0 + case ClauseLit(b) => 0 } - def dpll(formula: ClauseList): Boolean = { - + def dpll(formula: ClauseList): Boolean = formula match { + case ClauseNil() => true + case ClauseLit(b) => b + case _ => { + val chosenVar = choose(formula) + val lhs = dpll(substitute(formula, chosenVar, true)) + val rhs = dpll(substitute(formula, chosenVar, false)) + lhs || rhs + } } - def main(args: Array[String]) { - val f1 = And(Var(1), Or(Var(1), Not(Var(2)), Var(3)), Var(2), Not(Var(3))) - val dnff1 = clauses2list(dnfNaive(f1)) - val vars1 = vars(f1) - vars.foreach(v => { - - }) - println(f1 + " translated in dnf as:\n\t" + dnff1.mkString("\n\t")) - } +// def main(args: Array[String]) { +// val f1 = And(Var(1), Or(Var(1), Not(Var(2)), Var(3)), Var(2), Not(Var(3))) +// val dnff1 = clauses2list(dnfNaive(f1)) +// val vars1 = vars(f1) +// vars.foreach(v => { +// +// +// }) +// println(f1 + " translated in dnf as:\n\t" + dnff1.mkString("\n\t")) +// } //some non-leon functions to test the program with scala object False { @@ -188,9 +216,11 @@ object SatFun { def clause2list(cl: VarList): List[Int] = cl match { case VarCons(v, vs) => v :: clause2list(vs) case VarNil() => Nil + case VarLit(b) => if(b) List(1) else List(-1) } def clauses2list(cll: ClauseList): List[List[Int]] = cll match { case ClauseCons(cl, cls) => clause2list(cl) :: clauses2list(cls) case ClauseNil() => Nil + case ClauseLit(b) => if(b) List(List(1)) else List(List(-1)) } }