From 8f6204930a3f4194482cbcdfd573d4bff8542bc8 Mon Sep 17 00:00:00 2001
From: Etienne Kneuss <ekneuss@gmail.com>
Date: Fri, 4 Jan 2013 16:39:25 +0100
Subject: [PATCH] Improve search by making it more deterministic

---
 .../scala/leon/synthesis/SimpleSearch.scala   |  5 ++--
 .../synthesis/heuristics/ADTInduction.scala   |  2 +-
 .../scala/leon/synthesis/rules/ADTSplit.scala |  2 +-
 .../leon/synthesis/search/AndOrGraph.scala    | 23 ++++++++-----------
 .../synthesis/search/AndOrGraphSearch.scala   |  2 +-
 5 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/src/main/scala/leon/synthesis/SimpleSearch.scala b/src/main/scala/leon/synthesis/SimpleSearch.scala
index 393177e77..2b329ef70 100644
--- a/src/main/scala/leon/synthesis/SimpleSearch.scala
+++ b/src/main/scala/leon/synthesis/SimpleSearch.scala
@@ -42,14 +42,13 @@ class SimpleSearch(synth: Synthesizer,
   def expandAndTask(t: TaskRunRule): ExpandResult[TaskTryRules] = {
     val prefix = "[%-20s] ".format(Option(t.rule).getOrElse("?"))
 
+    info(prefix+"Got: "+t.problem)
     t.app.apply(sctx) match {
       case RuleSuccess(sol) =>
-        info(prefix+"Got: "+t.problem)
         info(prefix+"Solved with: "+sol)
 
         ExpandSuccess(sol)
       case RuleDecomposed(sub) =>
-        info(prefix+"Got: "+t.problem)
         info(prefix+"Decomposed into:")
         for(p <- sub) {
           info(prefix+" - "+p)
@@ -58,6 +57,8 @@ class SimpleSearch(synth: Synthesizer,
         Expanded(sub.map(TaskTryRules(_)))
 
       case RuleApplicationImpossible =>
+        info(prefix+"Failed")
+
         ExpandFailure()
     }
   }
diff --git a/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala b/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala
index 1c50c18c8..c9e5af133 100644
--- a/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala
+++ b/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala
@@ -40,7 +40,7 @@ case object ADTInduction extends Rule("ADT Induction") with Heuristic {
         val innerPhi = substAll(residualMap + (origId -> Variable(inductOn)), p.phi)
         val innerPC  = substAll(residualMap + (origId -> Variable(inductOn)), p.pc)
 
-        val subProblemsInfo = for (dcd <- cd.knownDescendents) yield dcd match {
+        val subProblemsInfo = for (dcd <- cd.knownDescendents.sortBy(_.id.name)) yield dcd match {
           case ccd : CaseClassDef =>
             var recCalls = Map[List[Identifier], List[Expr]]()
             var postFs   = List[Expr]()
diff --git a/src/main/scala/leon/synthesis/rules/ADTSplit.scala b/src/main/scala/leon/synthesis/rules/ADTSplit.scala
index 4680ca40b..61d3a9768 100644
--- a/src/main/scala/leon/synthesis/rules/ADTSplit.scala
+++ b/src/main/scala/leon/synthesis/rules/ADTSplit.scala
@@ -14,7 +14,7 @@ case object ADTSplit extends Rule("ADT Split.") {
     val candidates = p.as.collect {
       case IsTyped(id, AbstractClassType(cd)) =>
 
-        val optCases = for (dcd <- cd.knownDescendents) yield dcd match {
+        val optCases = for (dcd <- cd.knownDescendents.sortBy(_.id.name)) yield dcd match {
           case ccd : CaseClassDef =>
             val toSat = And(p.pc, Not(CaseClassInstanceOf(ccd, Variable(id))))
 
diff --git a/src/main/scala/leon/synthesis/search/AndOrGraph.scala b/src/main/scala/leon/synthesis/search/AndOrGraph.scala
index 48f38675a..251734160 100644
--- a/src/main/scala/leon/synthesis/search/AndOrGraph.scala
+++ b/src/main/scala/leon/synthesis/search/AndOrGraph.scala
@@ -77,11 +77,7 @@ class AndOrGraph[AT <: AOAndTask[S], OT <: AOOrTask[S], S](val root: OT, val cos
     }
 
     def expandLeaf(l: OrLeaf, succ: List[AT]) {
-      val n = new OrNode(this, Map(), l.task)
-      n.alternatives = succ.map(t => t -> new AndLeaf(n, t)).toMap
-      n.updateMin()
-
-      subProblems += l.task -> n
+      subProblems += l.task -> new OrNode(this, succ, l.task)
     }
 
     def notifySolution(sub: OrTree, sol: S) {
@@ -106,11 +102,7 @@ class AndOrGraph[AT <: AOAndTask[S], OT <: AOOrTask[S], S](val root: OT, val cos
   object RootNode extends OrLeaf(null, root) {
 
     override def expandWith(succ: List[AT]) {
-      val n = new OrNode(null, Map(), root)
-      n.alternatives = succ.map(t => t -> new AndLeaf(n, t)).toMap
-      n.updateMin()
-
-      tree = n
+      tree = new OrNode(null, succ, root)
     }
   }
 
@@ -122,10 +114,13 @@ class AndOrGraph[AT <: AOAndTask[S], OT <: AOOrTask[S], S](val root: OT, val cos
   }
 
 
-  class OrNode(val parent: AndNode, var alternatives: Map[AT, AndTree], val task: OT) extends OrTree with Node[AndTree] {
-    var triedAlternatives       = Map[AT, AndTree]()
-    var minAlternative: AndTree = _
-    var minCost                 = costModel.taskCost(task)
+  class OrNode(val parent: AndNode, val altTasks: List[AT], val task: OT) extends OrTree with Node[AndTree] {
+    var alternatives: Map[AT, AndTree] = altTasks.map(t => t -> new AndLeaf(this, t)).toMap
+    var triedAlternatives              = Map[AT, AndTree]()
+    var minAlternative: AndTree        = _
+    var minCost                        = costModel.taskCost(task)
+
+    updateMin()
 
     def updateMin() {
       if (!alternatives.isEmpty) {
diff --git a/src/main/scala/leon/synthesis/search/AndOrGraphSearch.scala b/src/main/scala/leon/synthesis/search/AndOrGraphSearch.scala
index e8d402b4f..79e70aecf 100644
--- a/src/main/scala/leon/synthesis/search/AndOrGraphSearch.scala
+++ b/src/main/scala/leon/synthesis/search/AndOrGraphSearch.scala
@@ -20,7 +20,7 @@ abstract class AndOrGraphSearch[AT <: AOAndTask[S],
           case l: g.Leaf =>
             collectLeaf(WL(l, newCosts.reverse)) 
           case a: g.AndNode =>
-            for (o <- (a.subProblems -- a.subSolutions.keySet).values) {
+            for (o <- a.subTasks.filterNot(a.subSolutions.keySet).map(a.subProblems)) {
               collectFromOr(o, newCosts)
             }
         }
-- 
GitLab