diff --git a/demo/Maps.scala b/demo/Maps.scala
index 25ca9627eff5c2508f3d2274576012457966e5a4..79554aa5d72dcf5d0cefc09e053c92bbbf7e9fe9 100644
--- a/demo/Maps.scala
+++ b/demo/Maps.scala
@@ -44,4 +44,8 @@ object Maps {
     else
       true
   } holds
+
+  def findModel(m : Map[Int,Int]) : Boolean = {
+    m != Map.empty[Int,Int].updated(0, 42)
+  } holds
 }
diff --git a/src/funcheck/CodeExtraction.scala b/src/funcheck/CodeExtraction.scala
index ad8de4eca2716133a15df539fdb1f06fb44e504a..2b89efb9abbf96111e68338256399569a075027f 100644
--- a/src/funcheck/CodeExtraction.scala
+++ b/src/funcheck/CodeExtraction.scala
@@ -531,11 +531,9 @@ trait CodeExtraction extends Extractors {
         val rf = rec(f)
         val rt = rec(t)
         val newSingleton = SingletonMap(rf, rt).setType(rm.getType)
-        println("singleton: " + newSingleton)
         rm.getType match {
           case MapType(ft, tt) =>
-            println("extracted maptype: " + MapType(ft, tt))
-            MapUnion(rm, newSingleton).setType(rm.getType)
+            MapUnion(rm, FiniteMap(Seq(newSingleton)).setType(rm.getType)).setType(rm.getType)
           case _ => {
             if (!silent) unit.error(tree.pos, "updated can only be applied to maps.")
             throw ImpureCodeEncounteredException(tree)
diff --git a/src/purescala/AbstractZ3Solver.scala b/src/purescala/AbstractZ3Solver.scala
index b0ae4af3b747aea8e9ba0cfe7fd2b47ee8948516..6d95da313ca2f5fe4529889d4628dec1956b0fc4 100644
--- a/src/purescala/AbstractZ3Solver.scala
+++ b/src/purescala/AbstractZ3Solver.scala
@@ -7,6 +7,9 @@ import Extensions._
 import Trees._
 import TypeTrees._
 
+import scala.collection.mutable.{Map => MutableMap}
+import scala.collection.mutable.{Set => MutableSet}
+
 // This is just to factor out the things that are common in "classes that deal
 // with a Z3 instance"
 trait AbstractZ3Solver {
@@ -24,6 +27,13 @@ trait AbstractZ3Solver {
   protected[purescala] var adtConstructors: Map[CaseClassDef, Z3FuncDecl]
   protected[purescala] var adtFieldSelectors: Map[Identifier, Z3FuncDecl]
 
+  protected[purescala] val mapRangeSorts: MutableMap[TypeTree, Z3Sort]
+  protected[purescala] val mapRangeSomeConstructors: MutableMap[TypeTree, Z3FuncDecl]
+  protected[purescala] val mapRangeNoneConstructors: MutableMap[TypeTree, Z3FuncDecl]
+  protected[purescala] val mapRangeSomeTesters: MutableMap[TypeTree, Z3FuncDecl]
+  protected[purescala] val mapRangeNoneTesters: MutableMap[TypeTree, Z3FuncDecl]
+  protected[purescala] val mapRangeValueSelectors: MutableMap[TypeTree, Z3FuncDecl]
+
   protected[purescala] var exprToZ3Id : Map[Expr,Z3AST]
   protected[purescala] def fromZ3Formula(tree : Z3AST) : Expr
 
diff --git a/src/purescala/Evaluator.scala b/src/purescala/Evaluator.scala
index 3a9ab97acf8d4cb6948ae69c1a83a599bc2e6f48..55c9cf7467cf4452d7ef21ad8f26ce6fe3e638d4 100644
--- a/src/purescala/Evaluator.scala
+++ b/src/purescala/Evaluator.scala
@@ -128,6 +128,7 @@ object Evaluator {
 
           (lv,rv) match {
             case (FiniteSet(el1),FiniteSet(el2)) => BooleanLiteral(el1.toSet == el2.toSet)
+            case (FiniteMap(el1),FiniteMap(el2)) => BooleanLiteral(el1.toSet == el2.toSet)
             case _ => BooleanLiteral(lv == rv)
           }
         }
@@ -228,6 +229,34 @@ object Evaluator {
         case i @ IntLiteral(_) => i
         case b @ BooleanLiteral(_) => b
 
+        case f @ FiniteMap(ss) => FiniteMap(ss.map(rec(ctx,_)).distinct.asInstanceOf[Seq[SingletonMap]]).setType(f.getType)
+        case e @ EmptyMap(_,_) => e
+        case s @ SingletonMap(f,t) => SingletonMap(rec(ctx,f), rec(ctx,t)).setType(s.getType)
+        case g @ MapGet(m,k) => (rec(ctx,m), rec(ctx,k)) match {
+          case (FiniteMap(ss), e) => ss.find(_.from == e) match {
+            case Some(v) => v
+            case None => throw RuntimeErrorEx("key not found: " + e)
+          }
+          case (EmptyMap(ft,tt), e) => throw RuntimeErrorEx("key not found: " + e)
+          // case (SingletonMap(f,t), e) => if (f == e) t else throw RuntimeErrorEx("key not found: " + e)
+          case (l,r) => throw TypeErrorEx(TypeError(l, MapType(r.getType, g.getType)))
+        }
+        case u @ MapUnion(m1,m2) => (rec(ctx,m1), rec(ctx,m2)) match {
+          case (EmptyMap(_,_), r) => r
+          case (l, EmptyMap(_,_)) => l
+          case (f1@FiniteMap(ss1), FiniteMap(ss2)) => {
+            val filtered1 = ss1.filterNot(s => ss2.contains(s))
+            val newSs = filtered1 ++ ss2
+            FiniteMap(newSs).setType(f1.getType)
+          }
+          case (l, r) => throw TypeErrorEx(TypeError(l, m1.getType))
+        }
+        case i @ MapIsDefinedAt(m,k) => (rec(ctx,m), rec(ctx,k)) match {
+          case (EmptyMap(_,_),_) => BooleanLiteral(false)
+          case (FiniteMap(ss), e) => BooleanLiteral(ss.exists(_.from == e))
+          case (l, r) => throw TypeErrorEx(TypeError(l, m.getType))
+        }
+
         case Distinct(args) => {
           val newArgs = args.map(rec(ctx, _))
           BooleanLiteral(newArgs.distinct.size == newArgs.size)
diff --git a/src/purescala/FairZ3Solver.scala b/src/purescala/FairZ3Solver.scala
index 4822702df8c803a4a5b3b236bb663c41c66b4dd8..e6320c2c729b5ba201b55cf79aa3009bf88be044 100644
--- a/src/purescala/FairZ3Solver.scala
+++ b/src/purescala/FairZ3Solver.scala
@@ -100,12 +100,12 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac
   private var reverseADTConstructors: Map[Z3FuncDecl, CaseClassDef] = Map.empty
   private var reverseADTFieldSelectors: Map[Z3FuncDecl, (CaseClassDef,Identifier)] = Map.empty
 
-  private val mapRangeSorts: MutableMap[TypeTree, Z3Sort] = MutableMap.empty
-  private val mapRangeSomeConstructors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
-  private val mapRangeNoneConstructors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
-  private val mapRangeSomeTesters: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
-  private val mapRangeNoneTesters: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
-  private val mapRangeValueSelectors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeSorts: MutableMap[TypeTree, Z3Sort] = MutableMap.empty
+  protected[purescala] val mapRangeSomeConstructors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeNoneConstructors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeSomeTesters: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeNoneTesters: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeValueSelectors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
 
   private def mapRangeSort(toType : TypeTree) : Z3Sort = mapRangeSorts.get(toType) match {
     case Some(z3sort) => z3sort
@@ -391,7 +391,7 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac
     val validatingStopwatch     = new Stopwatch("validating",         false)
     val decideTopLevelSw        = new Stopwatch("top-level",          false).start
 
-    println("Deciding : " + vc)
+    // println("Deciding : " + vc)
 
     initializationStopwatch.start
 
@@ -504,8 +504,6 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac
           }
         }
         case (Some(true), m) => { // SAT
-          println("the model is ")
-          println(m)
           validatingStopwatch.start
           val (trueModel, model) = validateAndDeleteModel(m, toCheckAgainstModels, varsInVC, evaluator)
           validatingStopwatch.stop
@@ -1003,8 +1001,13 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac
               assert(argsSize == 2)
               Division(rargs(0), rargs(1))
             }
+            // case OpAsArray => {
+            //   assert(argsSize == 0)
+            //   
+            // }
             case other => {
               System.err.println("Don't know what to do with this declKind : " + other)
+              System.err.println("The arguments are : " + args)
               throw new CantTranslateException(t)
             }
           }
diff --git a/src/purescala/Trees.scala b/src/purescala/Trees.scala
index e5259abd796b466e584f2a6a561785e4839475bf..a24b4c5c7ca79e934f7c3ef238d1956b3e2462ff 100644
--- a/src/purescala/Trees.scala
+++ b/src/purescala/Trees.scala
@@ -395,6 +395,7 @@ object Trees {
       case And(args) => Some((args, And.apply))
       case Or(args) => Some((args, Or.apply))
       case FiniteSet(args) => Some((args, FiniteSet))
+      case FiniteMap(args) => Some((args, (as : Seq[Expr]) => FiniteMap(as.asInstanceOf[Seq[SingletonMap]])))
       case FiniteMultiset(args) => Some((args, FiniteMultiset))
       case Distinct(args) => Some((args, Distinct))
       case _ => None
@@ -1169,7 +1170,8 @@ object Trees {
     case CaseClassType(ccd) =>
       val fields = ccd.fields
       CaseClass(ccd, fields.map(f => simplestValue(f.getType)))
-    case SetType(baseType) => FiniteSet(Nil)
+    case SetType(baseType) => FiniteSet(Nil).setType(tpe)
+    case MapType(fromType, toType) => EmptyMap(fromType, toType).setType(tpe)
     case _ => throw new Exception("I can't choose simplest value for type " + tpe)
   }
 }
diff --git a/src/purescala/Z3ModelReconstruction.scala b/src/purescala/Z3ModelReconstruction.scala
index 74f85812d6ff3309fc48b25c5c39d5f26f342d23..0d42c6aaa27f426c04f81b7e46da17920e12fb21 100644
--- a/src/purescala/Z3ModelReconstruction.scala
+++ b/src/purescala/Z3ModelReconstruction.scala
@@ -24,6 +24,21 @@ trait Z3ModelReconstruction {
       expectedType match {
         case BooleanType => model.evalAs[Boolean](z3ID).map(BooleanLiteral(_))
         case Int32Type => model.evalAs[Int](z3ID).map(IntLiteral(_))
+        case MapType(kt,vt) => model.eval(z3ID) match {
+          case None => None
+          case Some(t) => model.getArrayValue(t) match {
+            case None => None
+            case Some((map, elseValue)) => 
+              assert(elseValue == mapRangeNoneConstructors(vt)())
+              val singletons = for ((index, value) <- map if z3.getASTKind(value) != mapRangeNoneConstructors(vt)()) yield {
+                z3.getASTKind(value) match {
+                  case Z3AppAST(someCons, List(arg)) if someCons == mapRangeSomeConstructors(vt) => SingletonMap(fromZ3Formula(index), fromZ3Formula(arg))
+                  case _ => scala.Predef.error("unexpected value in map: " + value)
+                }
+              }
+              if (singletons.isEmpty) Some(EmptyMap(kt, vt)) else Some(FiniteMap(singletons.toSeq))
+          }
+        }
         case other => model.eval(z3ID) match {
           case None => None
           case Some(t) => softFromZ3Formula(t)
diff --git a/src/purescala/Z3Solver.scala b/src/purescala/Z3Solver.scala
index f6f9a424fd2fa6c17d873e9d69e5b7eb5b7c959e..9c9e89894c11853ffafc8515ef48e0a9d3fc2df7 100644
--- a/src/purescala/Z3Solver.scala
+++ b/src/purescala/Z3Solver.scala
@@ -11,6 +11,8 @@ import z3plugins.bapa.{BAPATheory, BAPATheoryEqc, BAPATheoryBubbles}
 import z3plugins.instantiator.{AbstractInstantiator,Instantiator}
 
 import scala.collection.mutable.{HashMap => MutableHashMap}
+import scala.collection.mutable.{Map => MutableMap}
+import scala.collection.mutable.{Set => MutableSet}
 
 class Z3Solver(val reporter: Reporter) extends Solver(reporter) with AbstractZ3Solver with Z3ModelReconstruction {
   import Settings.useBAPA
@@ -94,6 +96,13 @@ class Z3Solver(val reporter: Reporter) extends Solver(reporter) with AbstractZ3S
   private var reverseADTConstructors: Map[Z3FuncDecl, CaseClassDef] = Map.empty
   private var reverseADTFieldSelectors: Map[Z3FuncDecl, (CaseClassDef,Identifier)] = Map.empty
 
+  protected[purescala] val mapRangeSorts: MutableMap[TypeTree, Z3Sort] = MutableMap.empty
+  protected[purescala] val mapRangeSomeConstructors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeNoneConstructors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeSomeTesters: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeNoneTesters: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+  protected[purescala] val mapRangeValueSelectors: MutableMap[TypeTree, Z3FuncDecl] = MutableMap.empty
+
   case class UntranslatableTypeException(msg: String) extends Exception(msg)
   private def prepareSorts: Unit = {
     import Z3Context.{ADTSortReference, RecursiveType, RegularSort}