From 25803b6f9bf8231b069b1d7aa685cd692cc39227 Mon Sep 17 00:00:00 2001
From: Philippe Suter <philippe.suter@gmail.com>
Date: Sat, 21 Aug 2010 21:33:45 +0000
Subject: [PATCH] some cleaning up, and a now correct handling of singletons
 etc.

---
 src/purescala/Reporter.scala                  |   2 +-
 src/purescala/Z3Solver.scala                  |   2 +-
 src/purescala/z3plugins/bapa/AST.scala        |  63 +----
 src/purescala/z3plugins/bapa/BAPATheory.scala |  95 ++------
 .../z3plugins/bapa/BapaToPaTranslator.scala   | 222 ------------------
 .../z3plugins/bapa/NormalForms.scala          |  10 +-
 .../z3plugins/bapa/PrettyPrinter.scala        |   4 -
 .../z3plugins/bapa/VennRegions.scala          |   9 +-
 vmcai2011-testcases/CADE07.scala              |  48 ----
 vmcai2011-testcases/JustFormulas.scala        |   5 +-
 vmcai2011-testcases/Nasty.scala               |   2 +-
 11 files changed, 45 insertions(+), 417 deletions(-)
 delete mode 100644 src/purescala/z3plugins/bapa/BapaToPaTranslator.scala

diff --git a/src/purescala/Reporter.scala b/src/purescala/Reporter.scala
index 7261d1121..a9bb02141 100644
--- a/src/purescala/Reporter.scala
+++ b/src/purescala/Reporter.scala
@@ -27,7 +27,7 @@ class DefaultReporter extends Reporter {
   protected val fatalPfx   = "[ Fatal ] "
 
   def output(msg: String) : Unit = {
-    Console.err.println(msg)
+    /*Console.err.*/println(msg)
   }
 
   protected def reline(pfx: String, msg: String) : String = {
diff --git a/src/purescala/Z3Solver.scala b/src/purescala/Z3Solver.scala
index f502ffd3d..d9697d291 100644
--- a/src/purescala/Z3Solver.scala
+++ b/src/purescala/Z3Solver.scala
@@ -394,7 +394,7 @@ class Z3Solver(reporter: Reporter) extends Solver(reporter) {
         z3.mkSetDifference(rec(s1), rec(s2))
       }
       case f @ FiniteSet(elems) => if(f.getType == IntSetType) {
-        throw new CantTranslateException
+        elems.map(e => bapa.mkSingleton(rec(e))).reduceLeft(bapa.mkUnion(_,_))
       } else {
         elems.foldLeft(z3.mkEmptySet(typeToSort(f.getType.asInstanceOf[SetType].base)))((ast,el) => z3.mkSetAdd(ast,rec(el)))
       }
diff --git a/src/purescala/z3plugins/bapa/AST.scala b/src/purescala/z3plugins/bapa/AST.scala
index 44bad9a9e..2f2a328f3 100644
--- a/src/purescala/z3plugins/bapa/AST.scala
+++ b/src/purescala/z3plugins/bapa/AST.scala
@@ -5,10 +5,8 @@ import z3.scala._
 object AST {
   
   /* AST */
-
   case class IllegalTerm(tree: Tree) extends Exception(tree + " should not be present in the formula.")
 
-
   sealed abstract class Tree {
     override def toString = PrettyPrinter(this)
     def ||(tree: Tree) = Op(OR, Seq(this, tree))
@@ -24,7 +22,7 @@ object AST {
     def seteq(tree: Tree) = Op(SETEQ, Seq(this, tree))
     def subseteq(tree: Tree) = Op(SUBSETEQ, Seq(this, tree))
     def +(tree: Tree) = Op(ADD, Seq(this, tree))
-    def ifThenElse(then: Tree, elze: Tree) = Op(ITE, Seq(this, then, elze))
+//    def ifThenElse(then: Tree, elze: Tree) = Op(ITE, Seq(this, then, elze))
     def card = Op(CARD, Seq(this))
     def ++(tree: Tree) = Op(UNION, Seq(this, tree))
     def **(tree: Tree) = Op(INTER, Seq(this, tree))
@@ -35,34 +33,7 @@ object AST {
   case class Lit(lit: Literal) extends Tree
   case class Var(sym: Symbol) extends Tree
  
-  /* AST extractors */
-
-  // Seems to be broken (scala bug ?)
-  /*
-  object UnOp {
-    def unapply(tree: Tree): Option[(Operand, Tree)] = tree match {
-      case Op(op, Seq(t)) => Some(op, t)
-      case _ => None
-    }
-  }
-
-  object BinOp {
-    def unapply(tree: Tree): Option[(Operand, Tree, Tree)] = tree match {
-      case Op(op, Seq(t1, t2)) => Some(op, t1, t2)
-      case _ => None
-    }
-  }
-
-  object TernOp {
-    def unapply(tree: Tree): Option[(Operand, Tree, Tree, Tree)] = tree match {
-      case Op(op, Seq(t1, t2, t3)) => Some(op, t1, t2, t3)
-      case _ => None
-    }
-  }
-  */
-
   /* Literals */
-
   sealed abstract class Literal
   case object TrueLit extends Literal
   case object FalseLit extends Literal
@@ -91,16 +62,11 @@ object AST {
   case object IFF extends Operand("<=>")
   case object EQ extends Operand("==")
   case object LT extends Operand("<")
-  case object LESS extends Operand("<<") // less-than for min / max
   case object SETEQ extends Operand("seteq")
   case object SUBSETEQ extends Operand("subseteq")
   // return integers
   case object ADD extends Operand("+")
-  case object ITE extends Operand("IF-THEN-ELSE")
   case object CARD extends Operand("CARD")
-//  case object CARD_PRED extends Operand("CARD-predicate")
-  case object MIN extends Operand("MIN")
-  case object MAX extends Operand("MAX")
   // return sets
   case object UNION extends Operand("++")
   case object INTER extends Operand("**")
@@ -125,36 +91,9 @@ object AST {
         that.asInstanceOf[Symbol].ast.ptr == this.ast.ptr )
   }
 
-
-//   object Symbol {
-    /*
-    def apply(typ: Type, z3: Z3Context, ast: Z3AST): Symbol = z3.getASTKind(ast) match {
-      case Z3AppAST(decl, Nil) =>
-//         val name = z3sym2string(z3, z3.getDeclName(decl))
-        new Symbol(typ, z3.getDeclName(decl).toString, ast)
-      case Z3AppAST(decl, Seq(set)) =>
-        //val name = "Z3_TH_" + z3.getDeclName(decl) + "(" + set + ")"
-        new Symbol(typ, decl(set).toString, ast)
-      case bad => error("Z3AST is not a variable : " + bad)
-    }
-    */
-//     def apply(typ: Type, z3: Z3Context, ast: Z3AST): Symbol =
-//       new Symbol(typ, ast)
-    /*
-    def unapply(sym: Symbol): Option[(Type,Z3AST)] =
-      Some(sym.typ, sym.ast)
-    */
-//   }
-
-//   private def z3sym2string(z3: Z3Context, sym: Z3Symbol): String = z3.getSymbolKind(sym) match {
-//     case Z3IntSymbol(i) => i.toString
-//     case Z3StringSymbol(s) => s
-//   }
-
   implicit def sym2tree(sym: Symbol): Tree = Var(sym)
 
   def BoolSymbol(ast: Z3AST) = new Symbol(BoolType, ast)
   def IntSymbol(ast: Z3AST) = new Symbol(IntType, ast)
   def SetSymbol(ast: Z3AST) = new Symbol(SetType, ast)
-
 }
diff --git a/src/purescala/z3plugins/bapa/BAPATheory.scala b/src/purescala/z3plugins/bapa/BAPATheory.scala
index 089e5f646..7baf60c7d 100644
--- a/src/purescala/z3plugins/bapa/BAPATheory.scala
+++ b/src/purescala/z3plugins/bapa/BAPATheory.scala
@@ -9,10 +9,7 @@ import AST._
 import NormalForms.{simplify, rewriteSetRel, setVariables, purify}
 
 class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with VennRegions {
-  // def this() = this(new Z3Context(new Z3Config("MODEL" -> true)))
-  //def this() = this(new Z3Context(new Z3Config("MODEL" -> true, "RELEVANCY" -> 0)))
   setCallbacks(
-//     initSearch = true,
     reduceApp = true,
     finalCheck = true,
     push = true,
@@ -25,33 +22,32 @@ class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with Venn
     restart = true
   )
 
-// This makes the Theory Proxy print out all calls that are forwarded to the theory.
-  //showCallbacks(true)
+  // This makes the Theory Proxy print out all calls that are
+  // forwarded to the theory.
+  showCallbacks(true)
 
   /* Theory constructs */
-  
   val mkSetSort = mkTheorySort(z3.mkStringSymbol("SetSort"))
   val mkEmptySet = mkTheoryValue(z3.mkStringSymbol("EmptySet"), mkSetSort)
-  val mkIsSingleton = mkUnarySetfun("IsSingleton", z3.mkBoolSort)
+  val mkSingleton = mkTheoryFuncDecl(z3.mkStringSymbol("Singleton"), Seq(z3.mkIntSort), mkSetSort)
   val mkCard = mkUnarySetfun("Cardinality", z3.mkIntSort)
-  // val mkCardPred = mkTheoryFuncDecl(z3.mkStringSymbol("HasCardinality"), Seq(mkSetSort, z3.mkIntSort), z3.mkBoolSort)
-  val mkElementOf = mkTheoryFuncDecl(z3.mkStringSymbol("IsElementOf"), Seq(z3.mkIntSort, mkSetSort), z3.mkBoolSort)
-  val mkAsSingleton = mkTheoryFuncDecl(z3.mkStringSymbol("AsSingleton"), Seq(z3.mkIntSort), mkSetSort)
-  val mkAsElement = mkUnarySetfun("AsElement", z3.mkIntSort)
   val mkSubsetEq = mkBinarySetfun("SubsetEq", z3.mkBoolSort)
+  val mkElementOf = mkTheoryFuncDecl(z3.mkStringSymbol("IsElementOf"), Seq(z3.mkIntSort, mkSetSort), z3.mkBoolSort)
   val mkUnion = mkBinarySetfun("Union", mkSetSort)
   val mkIntersect = mkBinarySetfun("Intersect", mkSetSort)
   val mkComplement = mkUnarySetfun("Complement", mkSetSort)
-  val mkDomainSize = z3.mkFreshConst("DomainSize", z3.mkIntSort)
+
+  private[bapa] val mkDomainSize = z3.mkFreshConst("DomainSize", z3.mkIntSort)
+  private[bapa] val mkAsElement = mkUnarySetfun("AsElement", z3.mkIntSort)
 
   def mkDisjoint(set1: Z3AST, set2: Z3AST) =
     z3.mkEq(mkIntersect(set1, set2), mkEmptySet)
 
   private var freshCounter = 0
-  def mkConst(name: String) = mkTheoryConstant(z3.mkStringSymbol(name), mkSetSort)
+  def mkSetConst(name: String) = mkTheoryConstant(z3.mkStringSymbol(name), mkSetSort)
   def mkFreshConst(name: String) = {
     freshCounter += 1
-    mkConst(name + "." + freshCounter)
+    mkSetConst(name + "." + freshCounter)
   }
   
   private def mkUnarySetfun(name: String, rType: Z3Sort) =
@@ -60,14 +56,13 @@ class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with Venn
     mkTheoryFuncDecl(z3.mkStringSymbol(name), Seq(mkSetSort, mkSetSort), rType)
 
   /* Theory stack */
-  
   private val stack = new Stack[Universe]
   stack push new EmptyUniverse(mkDomainSize)
 
   /* Callbacks */
 
   def assertAxiom2(ast: Z3AST) {
-    //println("Asserting: " + ast)
+    println("Asserting: " + ast)
     assertAxiom(ast)
   }
 
@@ -93,13 +88,11 @@ class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with Venn
   }
 
   override def reset {
-    knownSetExprs = Nil
     axiomsToAssert.clear
     stack.clear
   }
 
   override def restart {
-    knownSetExprs = Nil
     axiomsToAssert.clear
     stack.clear
   }
@@ -232,24 +225,15 @@ class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with Venn
         val paTree = NaiveBapaToPaTranslator(bapaTree)
         assertAxiomEventually(z3.mkEq(treeToZ3(paTree), ast))
         assertAxiomEventually(z3.mkIff(z3.mkEq(ast, z3.mkInt(0, z3.mkIntSort)), z3.mkEq(args(0), mkEmptySet)))
+      case Z3AppAST(decl, args) if decl == mkSingleton =>
+        //XXXX
+        assertAxiomEventually(z3.mkEq(mkAsElement(ast), args(0)))
+        assertAxiomEventually(z3.mkEq(mkCard(ast), z3.mkInt(1, z3.mkIntSort)))
       case _ =>
      // ignore other functions
     }
   }
 
-  override def initSearch : Unit = {
-    // Indicates that mkUnion is commutative
-    // val b1 = z3.mkBound(0, mkSetSort)
-    // val b2 = z3.mkBound(1, mkSetSort)
-    // val pattern = z3.mkPattern(mkUnion(b1, b2))
-    // val axiomTree = z3.mkEq(mkUnion(b1,b2),mkUnion(b2,b1))
-    // // TODO: make sure these symbols are unique.
-    // val bn1 = z3.mkIntSymbol(0)
-    // val bn2 = z3.mkIntSymbol(1)
-    // val axiom = z3.mkForAll(0, List(pattern), List((bn1, mkSetSort), (bn2, mkSetSort)), axiomTree)
-    // z3.assertCnstr(axiom)
-  }
-
   // TODO: add reductions for union & inter (empty set) and compl (nnf ?)
   override def reduceApp(fd: Z3FuncDecl, args: Z3AST*) : Option[Z3AST] = {
     if (fd == mkCard) {
@@ -266,25 +250,19 @@ class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with Venn
       } else {
         None
       }
-    } else if (fd == mkIsSingleton) {
-      if (args(0) == mkEmptySet) {
-        Some(z3.mkFalse)
-      } else {
-        None
-      }
+//    } else if (fd == mkIsSingleton) {
+//      if (args(0) == mkEmptySet) {
+//        Some(z3.mkFalse)
+//      } else {
+//        None
+//      }
     } else if (fd == mkElementOf) {
       val elem = args(0)
       val set  = args(1)
       if (set == mkEmptySet) {
         Some(z3.mkFalse)
       } else {
-        val singleton = z3.mkFreshConst("singleton", mkSetSort)
-        Some(z3.mkAnd(
-          mkIsSingleton(singleton),
-          z3.mkEq(mkAsSingleton(elem), singleton),
-          z3.mkEq(mkAsElement(singleton), elem),
-          mkSubsetEq(singleton, set)
-        ))
+        Some(mkSubsetEq(mkSingleton(elem), set))
       }
     } else {
       None
@@ -309,14 +287,12 @@ class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with Venn
     case Op(OR, ts) => z3.mkOr((ts map treeToZ3_rec):_*)
     case Op(NOT, Seq(t)) => z3.mkNot(treeToZ3_rec(t))
     case Op(IFF, Seq(t1, t2)) => z3.mkIff(treeToZ3_rec(t1), treeToZ3_rec(t2))
-    case Op(EQ, Seq(Op(CARD, Seq(t)), Lit(IntLit(1)))) => mkIsSingleton(treeToZ3_rec(t))
-    case Op(EQ, Seq(Lit(IntLit(1)), Op(CARD, Seq(t)))) => mkIsSingleton(treeToZ3_rec(t))
+//    case Op(EQ, Seq(Op(CARD, Seq(t)), Lit(IntLit(1)))) => mkIsSingleton(treeToZ3_rec(t))
+//    case Op(EQ, Seq(Lit(IntLit(1)), Op(CARD, Seq(t)))) => mkIsSingleton(treeToZ3_rec(t))
     case Op(EQ, Seq(t1, t2)) => z3.mkEq(treeToZ3_rec(t1), treeToZ3_rec(t2))
     case Op(LT, Seq(t1, t2)) => z3.mkLT(treeToZ3_rec(t1), treeToZ3_rec(t2))
     case Op(ADD, ts) => z3.mkAdd((ts map treeToZ3_rec):_*)
-    case Op(ITE, Seq(t1, t2, t3)) => z3.mkITE(treeToZ3_rec(t1), treeToZ3_rec(t2), treeToZ3_rec(t3))
     case Op(CARD, Seq(t)) => mkCard(treeToZ3_rec(t))
-//    case Op(CARD_PRED, Seq(s, t)) => mkCardPred(treeToZ3_rec(s), treeToZ3_rec(t))
     case Op(SETEQ, Seq(t1, t2)) => z3.mkEq(treeToZ3_rec(t1), treeToZ3_rec(t2))
     case Op(SUBSETEQ, Seq(t1, t2)) => mkSubsetEq(treeToZ3_rec(t1), treeToZ3_rec(t2))
     case Op(UNION, ts) => mkUnion((ts map treeToZ3_rec):_*)
@@ -326,26 +302,7 @@ class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with Venn
     case _ => error("Unsupported conversion from BAPA-tree to Z3AST :\n" + tree)
   }
 
-  private var knownSetExprs: List[Z3AST] = Nil
-  private def knownRepresentative(set: Z3AST) : Z3AST = {
-    // This can get slow in theory. I'd use a Set for inClass, but the hashing
-    // of Z3AST does not seem to work like it should. We need to check whether
-    // we can trust the C pointer to be a valid hash.
-    var inClass: List[Z3AST] = getEqClassMembers(set).toList
-   // println(" -- Equivalence class contains " + getEqClassMembers(set).toList)
-   // println(" -- List is " + knownSetExprs)
-
-    val result = knownSetExprs.find(inClass.contains(_)) match {
-      case Some(repr) => repr
-      case None => {
-        knownSetExprs = knownSetExprs ::: List(set)
-        set
-      }
-    }
-
-    // println("  -- Known representative for : " + set + " is : " + result)
-    result
-  }
+  def knownRepresentative(ast: Z3AST) : Z3AST = ast
 
   def z3ToTree(ast: Z3AST): Tree = z3.getASTKind(ast) match {
     case _ if ast == mkEmptySet => EmptySet
@@ -354,7 +311,7 @@ class BAPATheory(val z3: Z3Context) extends Z3Theory(z3, "BAPATheory") with Venn
     case Z3AppAST(decl, args) if decl == mkUnion => Op(UNION, args map z3ToTree)
     case Z3AppAST(decl, args) if decl == mkIntersect => Op(INTER, args map z3ToTree)
     case Z3AppAST(decl, args) if decl == mkComplement => Op(COMPL, args map z3ToTree)
-    case Z3AppAST(decl, args) if decl == mkIsSingleton => z3ToTree(args(0)).card === 1
+//    case Z3AppAST(decl, args) if decl == mkIsSingleton => z3ToTree(args(0)).card === 1
 //    case Z3AppAST(decl, args) if decl == mkCardPred => Op(EQ, Seq(Op(CARD, Seq(z3ToTree(args(0)))), IntSymbol(args(1))))
     case Z3AppAST(decl, args) if decl == mkCard => Op(CARD, Seq(z3ToTree(args(0))))
     case _ =>
diff --git a/src/purescala/z3plugins/bapa/BapaToPaTranslator.scala b/src/purescala/z3plugins/bapa/BapaToPaTranslator.scala
deleted file mode 100644
index ea8afcfaa..000000000
--- a/src/purescala/z3plugins/bapa/BapaToPaTranslator.scala
+++ /dev/null
@@ -1,222 +0,0 @@
-package purescala.z3plugins.bapa
-
-import scala.math.{log, min}
-import AST._
-import NormalForms.{setVariables, rewriteSetRel, simplify}
-import z3.scala.Z3Context
-
-class BapaToPaTranslator(z3: Z3Context) {
-  //private implicit def rangeToSeq[T](r: IndexedSeq[T]): Seq[T] = r.toSeq
-
-  // returns a PA formula and the number of Venn regions
-  def apply(formula: Tree): (Tree, Int) = {
-    val setvars = setVariables(formula)
-    val formula1 = simplify(rewriteSetRel(formula))
-    val (atoms, zeroes, ones) = countCardinalityExpressions(formula1)
-    val n0 = findSparsenessBound(atoms - zeroes - ones)
-    val n = if (setvars.size <= 30) min(n0 + ones, 1 << setvars.size)
-            else (n0 + ones)
-    val body = reduce(n)(formula1)
-    /*
-    println("In QFBAPAtoPATranslator:")
-    f1.print
-    println("** Set variables    : " + setvars)
-    println("** #atoms           : " + atoms)
-    println("** #cards = 0       : " + zeroes)
-    println("** #cards <= 1      : " + ones)
-    println("** d                : " + (atoms - zeroes - ones))
-    println("** sparseness bound : " + n0)
-    println("** body             : ")
-    body.print
-*/
-    /*
-    println("** Set variables    : " + setvars)
-    println("** sparseness bound : " + n0 +" (+ " + ones + ")")
-    println("** n                : " + n)
-      */
-    /* if (setvars.isEmpty)
-(True, 0)
-else        */
-    val buf = new scala.collection.mutable.ArrayBuffer[Tree]
-    buf += body
-    buf ++= nonNegativeCards(n)
-    buf ++=  breakSymmetry(n, setvars.toSeq)
-    (simplify(Op(AND, buf.toSeq)), n)
-  }
-
-  // Create / cache fresh variables
-  private val cache = new scala.collection.mutable.HashMap[String,Var]
-
-  private def lookup(varName: String, typ: Type) = cache getOrElse(varName, {
-    val freshVar = typ match {
-      case BoolType => Var(BoolSymbol(z3.mkFreshConst(varName, z3.mkBoolSort)))
-      case IntType => Var(IntSymbol(z3.mkFreshConst(varName, z3.mkIntSort)))
-      case SetType => error("no new set variables allowed")
-    }
-    cache(varName) = freshVar
-    freshVar
-  })
-
-  private def propVar(k: Int, sym: Symbol): Tree = lookup(sym.name + "_" + k, BoolType) //Symbol.beta(k, id)
-
-  private def intVar(k: Int): Tree = lookup("venn_" + k, IntType)//Symbol.vennSize(k, i)
-
-
-  // translate BA to PA expression
-  // Generate formula of the form
-  //    (if st0 then l_k else 0)
-  //  where st0 is the result of replacing, in setTerm, the set variables with k-family
-  //  of propositional variables, as given by set2prop.
-  def ba2pa(setTree: Tree, k: Int): Tree = {
-    def set2prop(stree: Tree): Tree = stree match {
-      case Var(sym) => propVar(k, sym)
-      case Lit(EmptySetLit) => False
-      case Lit(FullSetLit) => True
-      case Op(COMPL, Seq(set)) => !set2prop(set)
-      case Op(UNION, sets) => Op(OR, sets map set2prop)
-      case Op(INTER, sets) => Op(AND, sets map set2prop)
-      case _ => throw IllegalTerm(setTree)
-    }
-    set2prop(setTree) ifThenElse (intVar(k), 0)
-    //Op(ITE(set2prop(setTerm)), List(intVar(k), 0))
-  }
-
-  // reduce QFBAPA formula f to QFPA formula,
-  //  introducing only n generic partition cardinality variables
-  // pre: formula is in nnf
-  def reduce(n: Int) = {
-    /*
-    def reduceFormula(form: Formula): Formula = form match {
-      case True | False | PropVar(_) => form
-      case Not(f) => !reduceFormula(f)
-      case And(fs) => And(fs map reduceFormula)
-      case Or(fs) => Or(fs map reduceFormula)
-      case Predicate(c: IntLogical, ts) => Predicate(c, ts map reduceTerm)
-      case _ => throw IllegalTerm(form)
-    }
-    def reduceTerm(term: Term): Term = term match {
-      case Op(CARD, List(set)) =>
-        if (n == 0) 0 else Op(ADD, for (k <- 1 to n) yield ba2pa(set, k, eqClassNum))
-      case Op(c, ts) =>
-        Op(c, ts map reduceTerm)
-      case Lit(_) | TermVar(_) => term
-    }
-    */
-    def reduceTree(tree: Tree): Tree = tree match {
-      case Op(CARD, Seq(set)) =>
-        if (n == 0) 0
-        else Op(ADD, for (k <- 1 to n) yield ba2pa(set, k))
-      case Op(op, args) =>
-        Op(op, args map reduceTree)
-      case _ => tree
-    }
-    reduceTree _
-  }
-
-  // Extractor for countCardinalityExpressions
-  private object ExCardLessEqual {
-    def unapply(tree: Tree): Option[(Tree, Int)] = tree match {
-      case Op(EQ, Seq(Lit(IntLit(card)), Op(CARD, Seq(set)))) => Some((set, card))
-      case Op(EQ, Seq(Op(CARD, Seq(set)), Lit(IntLit(card)))) => Some((set, card))
-/*GE*/case Op(NOT, Seq(Op(LT, Seq(Lit(IntLit(card)), Op(CARD, Seq(set)))))) => Some((set, card))
-//    case Op(LE, Seq(Op(CARD, Seq(set)), Lit(IntLit(card)))) => Some((set, card))
-//    case Op(GT, Seq(Lit(IntLit(card)), Op(CARD, Seq(set)))) => Some((set, card - 1))
-/*LT*/case Op(LT, Seq(Op(CARD, Seq(set)), Lit(IntLit(card)))) => Some((set, card - 1))
-      case _ => None
-    }
-  }
-
-  def countCardinalityExpressions(tree0: Tree): (Int, Int, Int) = {
-    var atoms = 0
-    var cardIs0 = 0
-    var cardIs1 = 0
-    /*
-    def countFormula(form: Formula): Unit = form match {
-      case And(fs) => fs foreach countFormula
-      case Or(fs) => fs foreach countFormula
-      case ExCardLessEqual(_, 0) => cardIs0 += 1; atoms += 1
-      case ExCardLessEqual(_, 1) => cardIs1 += 1; atoms += 1
-      case Predicate(c: IntLogical, ts) => ts foreach countTerm
-      case True | False | PropVar(_) => ()
-      case _ => IllegalTerm(form)
-    }
-    def countTerm(term: Term): Unit = term match {
-      case Op(CARD, List(Lit(_))) => ()
-      case Op(CARD, _) => atoms += 1
-      case Op(_, ts) => ts foreach countTerm
-      case _ => ()
-    }
-    */
-    def countTree(tree: Tree): Unit = tree match {
-      case ExCardLessEqual(_, 0) => cardIs0 += 1; atoms += 1
-      case ExCardLessEqual(_, 1) => cardIs1 += 1; atoms += 1
-      case Op(CARD, Seq(Lit(_))) => ()
-      case Op(CARD, _) => atoms += 1
-      case Op(_, ts) => ts foreach countTree
-      case _ => ()
-    }
-    countTree(tree0)
-    (atoms, cardIs0, cardIs1)
-  }
-
-  // symmetry_breaking predicate says that
-  // propositional variables denote a strictly
-  // increasing sequence of regions (lexical ordering)
-  private val BREAK_SYMMETRY = true
-
-  def breakSymmetry(n: Int, svars: Seq[Symbol]): Seq[Tree] =
-    if (BREAK_SYMMETRY)
-      Seq.tabulate(n - 1)(i => mkIndexLess(i + 1)(svars))
-    else Nil
-
-  private def mkIndexLess(i: Int) = {
-    def rec(sets: Seq[Symbol]): Tree = sets match {
-      case Nil => True
-      case Seq(s) =>
-        // prop less
-        val varI = propVar(i, s)
-        val varI_1 = propVar(i + 1, s)
-        !varI && varI_1
-      case s :: ss =>
-        // prop equal
-        val varI = propVar(i, s)
-        val varI_1 = propVar(i + 1, s)
-        // TODO: looks like if-and-only-if constraint
-//         val equal = (!varI && !varI_1) || (varI && varI_1)
-//         rec(Seq(s)) || (equal && rec(ss))
-        rec(Seq(s)) || ((varI iff varI_1) && rec(ss))
-    }
-    rec _
-  }
-
-  // Imposes non-negativity for cardinalities of venn regions
-  private def nonNegativeCards(n: Int): Seq[Tree] =
-    for (i <- 1 to n) yield 0 <= intVar(i)
-
-  // compute the largest n such that 2^n <= (n+1)^d
-  def findSparsenessBound(d: Int) = {
-    // Check if 2^n <= (n+1)^d by taking log of both sides
-    def small_n(n: Int) = n * log(2) <= d * log(n + 1)
-    def binSearch(low: Int, high: Int): Int = {
-      if (high <= low + 1) {
-        if (small_n(high))
-          high
-        else
-          low
-      } else {
-        val mid = (high + low) / 2
-        if (small_n(mid))
-          binSearch(mid, high)
-        else
-          binSearch(low, mid)
-      }
-    }
-    if (d <= 3)
-      d
-    else {
-      val a0 = d * log(d)
-      val b0 = 2 * d * (1 + log(d))
-      binSearch(a0.toInt, b0.toInt)
-    }
-  }
-}
diff --git a/src/purescala/z3plugins/bapa/NormalForms.scala b/src/purescala/z3plugins/bapa/NormalForms.scala
index 26d732e14..1dbb597cf 100644
--- a/src/purescala/z3plugins/bapa/NormalForms.scala
+++ b/src/purescala/z3plugins/bapa/NormalForms.scala
@@ -57,11 +57,11 @@ object NormalForms {
     case Op(COMPL, Seq(Op(INTER, ts))) => simplify(Op(UNION, ts map {~_}))
     case Op(COMPL, Seq(Op(UNION, ts))) => simplify(Op(INTER, ts map {~_}))
     case Op(CARD, Seq(Lit(EmptySetLit))) => 0
-    case Op(ITE, Seq(c, t, e)) => simplify(c) match {
-      case Lit(TrueLit) => simplify(t)
-      case Lit(FalseLit) => simplify(e)
-      case cond => cond ifThenElse (simplify(t), simplify(e))
-    }
+//    case Op(ITE, Seq(c, t, e)) => simplify(c) match {
+//      case Lit(TrueLit) => simplify(t)
+//      case Lit(FalseLit) => simplify(e)
+//      case cond => cond ifThenElse (simplify(t), simplify(e))
+//    }
     case Op(ADD, ts) =>
       var intPart = 0
       val acc = new scala.collection.mutable.ListBuffer[Tree]
diff --git a/src/purescala/z3plugins/bapa/PrettyPrinter.scala b/src/purescala/z3plugins/bapa/PrettyPrinter.scala
index 9c05a918a..62a2c7ab8 100644
--- a/src/purescala/z3plugins/bapa/PrettyPrinter.scala
+++ b/src/purescala/z3plugins/bapa/PrettyPrinter.scala
@@ -105,10 +105,6 @@ object PrettyPrinter {
     case Op(SETEQ, ts) => op(_SEQ, ts map pp)
     case Op(SUBSETEQ, ts) => op(_SSEQ, ts map pp)
     case Op(ADD, ts) => op("+", ts map pp)
-    case Op(ITE, Seq(c, t, e)) =>
-      g(gn("if" :/: pp(c)) :/:
-      gn("then" :/: bp(t)) :/:
-      gn("else" :/: bp(e)))
     case Op(CARD, Seq(t)) => "|" :: pp(t) :: "|"
     case Op(UNION, ts) => op(_UNION, ts map pp)
     case Op(INTER, ts) => op(_INTER, ts map pp)
diff --git a/src/purescala/z3plugins/bapa/VennRegions.scala b/src/purescala/z3plugins/bapa/VennRegions.scala
index 601b70fca..dc2e1fa87 100644
--- a/src/purescala/z3plugins/bapa/VennRegions.scala
+++ b/src/purescala/z3plugins/bapa/VennRegions.scala
@@ -55,8 +55,13 @@ trait VennRegions {
 
     def addSet(symbol: Symbol) = {
       val name = mkName(symbol)
-      if (setVariables contains name) this
-      else new ExtendedUniverse(name, this)
+      if (setVariables contains name) {
+        this
+      } else {
+        println("Adding set: " + symbol)
+        println("AKA       : " + name)
+        new ExtendedUniverse(name, this)
+      }
     }
     
     def addSets(symbols: Iterable[Symbol]) = {
diff --git a/vmcai2011-testcases/CADE07.scala b/vmcai2011-testcases/CADE07.scala
index f6f47f72f..aa18c20d7 100644
--- a/vmcai2011-testcases/CADE07.scala
+++ b/vmcai2011-testcases/CADE07.scala
@@ -10,11 +10,6 @@ object CADE07 {
     listContent ++ Set(x)
   } ensuring(_.size == listContent.size + 1)
 
-  def vc2r(x: Set[Int], listContent: Set[Int]) : Set[Int] = {
-    require(x.size == 1 && !x.subsetOf(listContent))
-    listContent ++ x
-  } ensuring(_.size == listContent.size + 1)
-
   def vc2a(listRoot: Int, list: Set[Int], x: Int, listContent: Set[Int], objectAlloc: Set[Int], objct: Set[Int]) : Set[Int] = {
     require(
       list.contains(listRoot)
@@ -26,19 +21,6 @@ object CADE07 {
     listContent ++ Set(x)
   } ensuring(_.size == listContent.size + 1)
 
-  def vc2ar(listRoot: Set[Int], list: Set[Int], x: Set[Int], listContent: Set[Int], objectAlloc: Set[Int], objct: Set[Int]) : Set[Int] = {
-    require(
-      listRoot.size == 1
-   && listRoot.subsetOf(list)
-   && x.size == 1
-   && !x.subsetOf(listContent)
-   && listContent.subsetOf(objectAlloc)
-   && x.subsetOf(objct)
-   && x.subsetOf(objectAlloc))
-
-    listContent ++ x
-  } ensuring(_.size == listContent.size + 1)
-
   def vc2b(listRoot: Int, list: Set[Int], x: Int, listContent: Set[Int], objectAlloc: Set[Int], objct: Set[Int]) : Set[Int] = {
     require(
       list.contains(listRoot)
@@ -49,28 +31,10 @@ object CADE07 {
     listContent ++ Set(x)
   } ensuring(_.size == listContent.size + 1)
 
-  def vc2br(listRoot: Set[Int], list: Set[Int], x: Set[Int], listContent: Set[Int], objectAlloc: Set[Int], objct: Set[Int]) : Set[Int] = {
-    require(
-      listRoot.size == 1
-   && listRoot.subsetOf(list)
-   && x.size == 1
-   && listContent.subsetOf(objectAlloc)
-   && x.subsetOf(objct)
-   && x.subsetOf(objectAlloc)
-    )
-
-    listContent ++ x
-  } ensuring(_.size == listContent.size + 1)
-
   def vc3(x: Int, listContent: Set[Int]) : Set[Int] = {
     listContent ++ Set(x)
   } ensuring(_.size <= listContent.size + 1)
 
-  def vc3r(x: Set[Int], listContent: Set[Int]) : Set[Int] = {
-    require(x.size == 1)
-    listContent ++ x
-  } ensuring(_.size <= listContent.size + 1)
-
   def vc6(x: Int, c: Set[Int], c1: Set[Int], alloc0: Set[Int], alloc1: Set[Int], alloc2: Set[Int]) : Set[Int] = {
     require(
       c.contains(x)
@@ -81,16 +45,4 @@ object CADE07 {
 
     alloc2 -- alloc0
   } ensuring(_.size <= c.size)
-
-  def vc6r(x: Set[Int], c: Set[Int], c1: Set[Int], alloc0: Set[Int], alloc1: Set[Int], alloc2: Set[Int]) : Set[Int] = {
-    require(
-      x.size == 1
-   && x.subsetOf(c)
-   && c1 == c -- x
-   && (alloc1 -- alloc0).size <= 1
-   && (alloc2 -- alloc1).size <= c1.size
-    )
-
-    alloc2 -- alloc0
-  } ensuring(_.size <= c.size)
 }
diff --git a/vmcai2011-testcases/JustFormulas.scala b/vmcai2011-testcases/JustFormulas.scala
index 731cc8270..7a046abc3 100644
--- a/vmcai2011-testcases/JustFormulas.scala
+++ b/vmcai2011-testcases/JustFormulas.scala
@@ -27,7 +27,7 @@ object JustFormulas {
   def vc5_V(x: Int, y: Int, a: Set[Int], b: Set[Int]) : Boolean = {
     require(
       a.contains(f1(x))
-   && b.contains(f1(x))
+   && b.contains(f1(y))
    && x < y + 1
    && 2*y - 1 < 2*x
     )
@@ -36,7 +36,8 @@ object JustFormulas {
 
   def vc6_V(x: Int, y: Int, a: Set[Int], b: Set[Int]) : Boolean = {
     require(
-      f2(a).contains(x)
+      (!((a -- b).size == 0 && (b -- a).size == 0) || a == b)
+   && f2(a).contains(x)
    && f2(b).contains(y)
    && (a -- b) == Set.empty[Int]
    && (b -- a) == Set.empty[Int]
diff --git a/vmcai2011-testcases/Nasty.scala b/vmcai2011-testcases/Nasty.scala
index e317f7ae7..b9c3d9024 100644
--- a/vmcai2011-testcases/Nasty.scala
+++ b/vmcai2011-testcases/Nasty.scala
@@ -103,5 +103,5 @@ object Nasty {
    && (objAlloc16 -- objAlloc30).size <= s241.size
     )
     objAlloc16 -- objAlloc
-  } ensuring(_.size < s142.size)
+  } ensuring(_.size <= s142.size)
 }
-- 
GitLab