Simple SAT Solver
Written by Hossein Hojjat
object DPLL { case class Literal(val name: String, val pos: Boolean) def negate(l : Literal) = Literal(l.name, !l.pos) type Clause = Set[Literal] def DPLL(f : Set[Clause]) : (Boolean,Map[String,Boolean]) = { if(f.isEmpty) return (true,Map.empty[String,Boolean]) if(f.exists(clause => clause.isEmpty)) return (false,Map.empty[String,Boolean]) if(f.exists(clause => clause.size == 1)) { val unit_clause: Literal = f.find(clause => clause.size == 1) match { case Some(c) => c.toList.head} val nf = f.filter( clause => (!clause.contains(unit_clause))) .map( clause => if (clause.contains(negate(unit_clause))) (clause - negate(unit_clause)) else clause) val (ds,dm) = DPLL(nf) return (ds,dm + (if (unit_clause.pos) (unit_clause.name -> true) else (unit_clause.name -> false))) } val literals = f.reduceLeft((a,b) => a ++ b) var pures: Set[Literal] = Set.empty[Literal] literals.foreach(l => (if(pures.contains(negate(l))) pures --= Set(l,negate(l)) else pures += l)) if(pures.size != 0) { val pure = pures.toList.head val (ds,dm) = DPLL(f.filter( clause => (!clause.contains(pure)))) return (ds,dm + (if (pure.pos) (pure.name -> true) else (pure.name -> false))) } val literal_to_split = f.toList.head.toList.head val (ds,dm) = DPLL(f + Set(literal_to_split)) if(ds) (true, dm) else DPLL(f + Set(negate(literal_to_split))) } def main(args : Array[String]) : Unit = { var form = Set.empty[Clause] var clause = Set.empty[Literal] var tok:String = "" scala.io.Source.fromFile(new java.io.File(args(0))).getLines.foreach { line => if( !line.startsWith("c") && !line.startsWith("p")) { val scanner = new java.util.Scanner(line) while(scanner.hasNext) { tok = scanner.next if (tok != "0") {if( tok.startsWith("-")) clause += Literal(tok.drop(1), false) else clause += Literal(tok, true)} else { form += clause clause = Set.empty[Literal] }}}} if( clause.size != 0) form += clause val (rs,rm) = DPLL(form) if(rs) println("s SATISFIABLE\nv " + rm.map(m => (if( m._2) m._1 else "-" + m._1)).mkString(" ")) else println("s UNSATISFIABLE") } }