From b629f6bd33042904cb4e977b6c7791af20ae1e44 Mon Sep 17 00:00:00 2001 From: Manos Koukoutos <emmanouil.koukoutos@epfl.ch> Date: Fri, 29 Apr 2016 16:39:13 +0200 Subject: [PATCH] Work on ExamplesBank All map* -> flatMap* Add evalIns which evaluates all inputs All QualifiedExamplesBank methods now return QEBs Problem.qebFiltered evaluates first --- .../scala/leon/evaluators/Evaluator.scala | 34 +++++++++++-------- .../scala/leon/synthesis/ExamplesBank.scala | 19 +++++++---- src/main/scala/leon/synthesis/Problem.scala | 2 +- .../scala/leon/synthesis/rules/ADTSplit.scala | 4 +-- .../leon/synthesis/rules/DetupleInput.scala | 2 +- .../synthesis/rules/EquivalentInputs.scala | 2 +- 6 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/main/scala/leon/evaluators/Evaluator.scala b/src/main/scala/leon/evaluators/Evaluator.scala index 9f7f0fbe2..e5e6fd1a7 100644 --- a/src/main/scala/leon/evaluators/Evaluator.scala +++ b/src/main/scala/leon/evaluators/Evaluator.scala @@ -53,25 +53,29 @@ trait DeterministicEvaluator extends Evaluator { override def eval(expr: Expr, mapping: Map[Identifier, Expr]) : EvaluationResult = { if(mapping.forall{ case (key, value) => purescala.ExprOps.isValue(value) }) { super.eval(expr, mapping.toMap) - } else (_evalEnv(mapping) match { - case Left(m) => super.eval(expr, m) - case Right(errorMessage) => - val m = mapping.filter{ case (k, v) => purescala.ExprOps.isValue(v) }.toMap - super.eval(expr, m) match { - case res @ evaluators.EvaluationResults.Successful(result) => res - case _ => evaluators.EvaluationResults.EvaluatorError(errorMessage) - } - }) + } else { + _evalEnv(mapping) match { + case Left(m) => super.eval(expr, m) + case Right(errorMessage) => + val m = mapping.filter { case (k, v) => purescala.ExprOps.isValue(v) } + super.eval(expr, m) match { + case res@evaluators.EvaluationResults.Successful(result) => res + case _ => evaluators.EvaluationResults.EvaluatorError(errorMessage) + } + } + } } /** Returns an evaluated environment. If it fails, removes all non-values from the environment. */ def evalEnv(mapping: Iterable[(Identifier, Expr)]): Map[Identifier, Value] = { if(mapping.forall{ case (key, value) => purescala.ExprOps.isValue(value) }) { mapping.toMap - } else (_evalEnv(mapping) match { - case Left(m) => m - case Right(msg) => mapping.filter(x => purescala.ExprOps.isValue(x._2)).toMap - }) + } else { + _evalEnv(mapping) match { + case Left(m) => m + case Right(msg) => mapping.filter(x => purescala.ExprOps.isValue(x._2)).toMap + } + } } /** From a not yet well evaluated context with dependencies between variables, returns a head where all exprs are values (as a Left()) @@ -158,10 +162,10 @@ object Evaluator { /* Status of the invariant checking for `cc` */ def invariantCheck(cc: CaseClass): CheckStatus = synchronized { if (!cc.ct.classDef.hasInvariant) Complete(true) - else checkCache.get(cc).getOrElse { + else checkCache.getOrElse(cc, { checkCache(cc) = Pending NoCheck - } + }) } /* Update the cache with the invariant check result for `cc` */ diff --git a/src/main/scala/leon/synthesis/ExamplesBank.scala b/src/main/scala/leon/synthesis/ExamplesBank.scala index ed22fa0ec..9d48defd5 100644 --- a/src/main/scala/leon/synthesis/ExamplesBank.scala +++ b/src/main/scala/leon/synthesis/ExamplesBank.scala @@ -70,13 +70,13 @@ case class ExamplesBank(valids: Seq[Example], invalids: Seq[Example]) { } } - def map(f: Example => List[Example]) = { + def flatMap(f: Example => List[Example]) = { ExamplesBank(valids.flatMap(f), invalids.flatMap(f)) } /** Expands each input example through the function f */ def flatMapIns(f: Seq[Expr] => List[Seq[Expr]]) = { - map { + flatMap { case InExample(in) => f(in).map(InExample) @@ -87,7 +87,7 @@ case class ExamplesBank(valids: Seq[Example], invalids: Seq[Example]) { /** Expands each output example through the function f */ def flatMapOuts(f: Seq[Expr] => List[Seq[Expr]]) = { - map { + flatMap { case InOutExample(in, out) => f(out).map(InOutExample(in, _)) @@ -97,7 +97,7 @@ case class ExamplesBank(valids: Seq[Example], invalids: Seq[Example]) { } def stripOuts = { - map { + flatMap { case InOutExample(in, out) => List(InExample(in)) case e => @@ -190,6 +190,11 @@ case class QualifiedExamplesBank(as: List[Identifier], xs: List[Identifier], eb: filterIns(m => evaluator.eval(expr, m).result.contains(BooleanLiteral(true))) } + def evalIns: QualifiedExamplesBank = flatMapIns { mapping => + val evalAs = evaluator.evalEnv(mapping) + List(as map evalAs) + } + /** Filters inputs through the predicate pred, with an assignment of input variables to expressions. */ def filterIns(pred: Map[Identifier, Expr] => Boolean): QualifiedExamplesBank = { QualifiedExamplesBank(as, xs, @@ -207,14 +212,14 @@ case class QualifiedExamplesBank(as: List[Identifier], xs: List[Identifier], eb: /** Maps inputs through the function f * * @return A new ExampleBank */ - def mapIns(f: Seq[(Identifier, Expr)] => List[Seq[Expr]]) = { - eb map { + def flatMapIns(f: Seq[(Identifier, Expr)] => List[Seq[Expr]]): QualifiedExamplesBank = { + copy(eb = eb flatMap { case InExample(in) => f(as zip in).map(InExample) case InOutExample(in, out) => f(as zip in).map(InOutExample(_, out)) - } + }) } } diff --git a/src/main/scala/leon/synthesis/Problem.scala b/src/main/scala/leon/synthesis/Problem.scala index 46d01ece1..8d7677d32 100644 --- a/src/main/scala/leon/synthesis/Problem.scala +++ b/src/main/scala/leon/synthesis/Problem.scala @@ -52,7 +52,7 @@ case class Problem(as: List[Identifier], ws: Expr, pc: Path, phi: Expr, xs: List copy(ws = andJoin(wsList ++ es)) } - def qebFiltered(implicit sctx: SearchContext) = qeb.filterIns(pc.fullClause) + def qebFiltered(implicit sctx: SearchContext) = qeb.evalIns.filterIns(pc.fullClause) // Qualified example bank, allows us to perform operations (e.g. filter) with expressions def qeb(implicit sctx: SearchContext) = QualifiedExamplesBank(this.as, this.xs, eb) diff --git a/src/main/scala/leon/synthesis/rules/ADTSplit.scala b/src/main/scala/leon/synthesis/rules/ADTSplit.scala index 5b5070124..379eaf59f 100644 --- a/src/main/scala/leon/synthesis/rules/ADTSplit.scala +++ b/src/main/scala/leon/synthesis/rules/ADTSplit.scala @@ -91,7 +91,7 @@ case object ADTSplit extends Rule("ADT Split.") { if (isInputVar) { // Filter out examples where id has the wrong type, and fix input variables // Note: It is fine to filter here as no evaluation is required - p.qeb.mapIns { inInfo => + p.qeb.flatMapIns { inInfo => inInfo.toMap.apply(id) match { case CaseClass(`cct`, vs) => List(vs ++ inInfo.filter(_._1 != id).map(_._2)) @@ -100,7 +100,7 @@ case object ADTSplit extends Rule("ADT Split.") { } } } else { - p.eb + p.qeb } } val newAs = if (isInputVar) args ::: oas else p.as diff --git a/src/main/scala/leon/synthesis/rules/DetupleInput.scala b/src/main/scala/leon/synthesis/rules/DetupleInput.scala index a08f10479..73bd53363 100644 --- a/src/main/scala/leon/synthesis/rules/DetupleInput.scala +++ b/src/main/scala/leon/synthesis/rules/DetupleInput.scala @@ -103,7 +103,7 @@ case object DetupleInput extends NormalizingRule("Detuple In") { } }.toMap - val eb = p.qeb.mapIns { info => + val eb = p.qeb.flatMapIns { info => List(info.flatMap { case (id, v) => ebMapInfo.get(id) match { case Some(m) => diff --git a/src/main/scala/leon/synthesis/rules/EquivalentInputs.scala b/src/main/scala/leon/synthesis/rules/EquivalentInputs.scala index 65e5dd1ac..74abe6721 100644 --- a/src/main/scala/leon/synthesis/rules/EquivalentInputs.scala +++ b/src/main/scala/leon/synthesis/rules/EquivalentInputs.scala @@ -79,7 +79,7 @@ case object EquivalentInputs extends NormalizingRule("EquivalentInputs") { // XXX: must take place in this order!! obsolete & free is typically non-empty val newAs = (p.as ++ free).distinct.filterNot(obsolete) - val newBank = p.eb.map { ex => + val newBank = p.eb.flatMap { ex => val mapping = (p.as zip ex.ins).toMap val newIns = newAs.map(a => mapping.getOrElse(a, replaceFromIDs(mapping, reverseSubst(a)))) List(ex match { -- GitLab