From 8679204a13b1f9135ef778abdb3b20db2ac53194 Mon Sep 17 00:00:00 2001
From: Utkarsh Upadhyay <musically.ut@gmail.com>
Date: Mon, 12 Jul 2010 18:16:17 +0000
Subject: [PATCH] Changelist:

1. Added isUnsat to Extensions.scala
2. Added a few more conditions to BinarySearchTree.scala
3. Made calls to underlying solvers (involving double negation, etc) from the unifier
4. Fixed a minor bug in Expression Parsing in Main.scala
---
 src/orderedsets/Main.scala        |  2 +-
 src/orderedsets/UnifierMain.scala | 30 ++++++++++++++++++++----------
 src/purescala/Extensions.scala    |  2 +-
 testcases/BinarySearchTree.scala  | 10 ++++++----
 4 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/src/orderedsets/Main.scala b/src/orderedsets/Main.scala
index 187d077f0..e20188413 100644
--- a/src/orderedsets/Main.scala
+++ b/src/orderedsets/Main.scala
@@ -208,7 +208,7 @@ object ExprToASTConverter {
     formulaRelaxed = false;
     expr match {
       case And(exprs) => AST.And((exprs map toRelaxedFormula).toList)
-      case _ => toFormula(expr)
+      case _ => toRelaxedFormula(expr)
     }
   }
 
diff --git a/src/orderedsets/UnifierMain.scala b/src/orderedsets/UnifierMain.scala
index f51e4a7fc..099d306ac 100644
--- a/src/orderedsets/UnifierMain.scala
+++ b/src/orderedsets/UnifierMain.scala
@@ -50,14 +50,9 @@ class UnifierMain(reporter: Reporter) extends Solver(reporter) {
           val (varMap, restFormula) = solve(conjunction)
           // TODO: Might contain multiple c_i ~= {} for a fixed i
           val noAlphas = And(restFormula flatMap expandAlphas(varMap))
-          //reporter.info("The resulting formula is\n" + rpp(noAlphas))
-          // OrdBAPA finds the formula satisfiable
-          if ((new Main(reporter)).solve(ExprToASTConverter(noAlphas))) {
-            throw (new SatException(null))
-          } else {
-            reporter.info("Conjunction " + counter + " is UNSAT, proved by BAPA<")
-          }
-        } catch {
+          reporter.info("The resulting formula is\n" + rpp(noAlphas))
+          tryAllSolvers(noAlphas)
+          } catch {
           case ex@ConversionException(badExpr, msg) =>
             reporter.info("Conjunction " + counter + " is UNKNOWN, could not be parsed")
             throw ex
@@ -68,7 +63,7 @@ class UnifierMain(reporter: Reporter) extends Solver(reporter) {
           case UnificationImpossible(msg) =>
             reporter.info("Conjunction " + counter + " is UNSAT, proved by Unifier") // (" + msg + ")")
           case ex@SatException(_) =>
-            reporter.info("Conjunction " + counter + " is SAT, proved by BAPA<")
+            reporter.info("Conjunction " + counter + " is SAT")
             throw ex
         }
       }
@@ -93,6 +88,21 @@ class UnifierMain(reporter: Reporter) extends Solver(reporter) {
     }
   }
 
+  def tryAllSolvers(f : Expr): Unit = {
+    for(solver <- Extensions.loadedSolverExtensions; if solver != this) {
+          reporter.info("Trying solver: " + solver.shortDescription + " from inside the unifier.")
+          solver.isUnsat(f) match {
+            case Some(true) => 
+                reporter.info("Solver: " + solver.shortDescription + " proved the formula unsatisfiable") 
+                return
+            case Some(false) => 
+                reporter.warning("Solver: " + solver.shortDescription + " proved the formula satisfiable")
+                throw (new SatException(null))
+            case None =>
+                reporter.info("Solver: " + solver.shortDescription + " was unable to conclusively determine the correctness of the formula") 
+          }
+    }; throw IncompleteException("All the solvers were unable to prove the formula unsatisfiable, giving up.") }
+
   def checkIsSupported(expr: Expr) {
     def check(ex: Expr): Option[Expr] = ex match {
       case Let(_, _, _) | MatchExpr(_, _) =>
@@ -229,7 +239,7 @@ class UnifierMain(reporter: Reporter) extends Solver(reporter) {
           //reporter.warning("Result:\n" + rpp(res))
           Some(res)
         }
-        case _ => error("Bad argument/substitution to catamorphism")
+        case _ => error("Bad argument/substitution to catamorphism: " + substArg(arg))
       }
       case None => // Not a catamorphism
         warning("Function " + fd.id + " is not a catamorphism.")
diff --git a/src/purescala/Extensions.scala b/src/purescala/Extensions.scala
index a7744567f..0a3732fde 100644
--- a/src/purescala/Extensions.scala
+++ b/src/purescala/Extensions.scala
@@ -19,7 +19,7 @@ object Extensions {
     // None if unknown.
     def solve(expression: Expr) : Option[Boolean]
 
-    def isSat(expression: Expr) : Option[Boolean] = solve(expression).map(!_)
+    def isUnsat(expression: Expr) : Option[Boolean] = solve(negate(expression))
   }
   
   abstract class Analyser(reporter: Reporter) extends Extension(reporter) {
diff --git a/testcases/BinarySearchTree.scala b/testcases/BinarySearchTree.scala
index c2e4566f4..859a5eb29 100644
--- a/testcases/BinarySearchTree.scala
+++ b/testcases/BinarySearchTree.scala
@@ -57,22 +57,24 @@ object BinarySearchTree {
     }
   
 
-  def treeMin(tree: Node): Int = tree match {
+  def treeMin(tree: Node): Int = {
+    require(isSorted(tree).sorted)
+    tree match {
     case Node(left, v, _) => left match {
       case Leaf() => v
       case n@Node(_, _, _) => treeMin(n)
     }
-  }
+  }} ensuring (_ == contents(tree).min)
 
   def treeMax(tree: Node): Int = {
-    // requires(isSorted(tree))
+    require(isSorted(tree).sorted)
     tree match {
       case Node(_, v, right) => right match {
         case Leaf() => v
         case n@Node(_, _, _) => treeMax(n)
       }
     }
-  } //ensuring (_ == contents(tree).max)
+  } ensuring (_ == contents(tree).max)
 
   def insert(tree: Tree, value: Int): Node = {
     require(isSorted(tree).sorted)
-- 
GitLab