From f37f0bd4df0dbdbc139844ae98ca0487313c064f Mon Sep 17 00:00:00 2001 From: Manos Koukoutos <emmanouil.koukoutos@epfl.ch> Date: Fri, 12 Feb 2016 18:35:07 +0100 Subject: [PATCH] Rerwiting of integer/comparison rules. Cleaning up. terminatingCalls now returns calls with integers too. IntInduction and all integer comparison rules are phased out. Instead there is a single InequalitySplit rules which splits into (up to) 3 branches, taking pc into account. No more EqualitySplit for any other type, except generic types. Isolate unused rules. Clean up Rules. Improve QualifiedExamplesBank API --- src/main/scala/leon/repair/rules/Focus.scala | 2 +- .../scala/leon/synthesis/ExamplesBank.scala | 36 +++-- src/main/scala/leon/synthesis/Rules.scala | 31 +---- .../leon/synthesis/rules/EqualitySplit.scala | 61 --------- .../rules/GenericTypeEqualitySplit.scala | 72 ++++++++++ .../synthesis/rules/InequalitySplit.scala | 126 +++++++++++------- .../rules/{ => unused}/ADTInduction.scala | 2 +- .../rules/{ => unused}/ADTLongInduction.scala | 2 +- .../rules/{ => unused}/AsChoose.scala | 6 +- .../rules/{ => unused}/BottomUpTegis.scala | 2 +- .../rules/{ => unused}/DetupleOutput.scala | 2 +- .../rules/{ => unused}/IntInduction.scala | 12 +- .../rules/{ => unused}/IntegerEquation.scala | 2 +- .../{ => unused}/IntegerInequalities.scala | 2 +- .../{ => unused}/OptimisticInjection.scala | 2 +- .../{ => unused}/SelectiveInlining.scala | 6 +- .../rules/{ => unused}/SygusCVC4.scala | 4 +- .../synthesis/rules/{ => unused}/TEGIS.scala | 2 +- .../rules/{ => unused}/TEGISLike.scala | 2 +- .../rules/{ => unused}/TEGLESS.scala | 3 +- .../scala/leon/synthesis/utils/Helpers.scala | 11 +- .../synthesis/StablePrintingSuite.scala | 2 - synthesis-collective.txt | 2 +- .../current/RunLength/RunLength.scala | 8 -- 24 files changed, 214 insertions(+), 186 deletions(-) delete mode 100644 src/main/scala/leon/synthesis/rules/EqualitySplit.scala create mode 100644 src/main/scala/leon/synthesis/rules/GenericTypeEqualitySplit.scala rename src/main/scala/leon/synthesis/rules/{ => unused}/ADTInduction.scala (99%) rename src/main/scala/leon/synthesis/rules/{ => unused}/ADTLongInduction.scala (99%) rename src/main/scala/leon/synthesis/rules/{ => unused}/AsChoose.scala (79%) rename src/main/scala/leon/synthesis/rules/{ => unused}/BottomUpTegis.scala (99%) rename src/main/scala/leon/synthesis/rules/{ => unused}/DetupleOutput.scala (98%) rename src/main/scala/leon/synthesis/rules/{ => unused}/IntInduction.scala (95%) rename src/main/scala/leon/synthesis/rules/{ => unused}/IntegerEquation.scala (99%) rename src/main/scala/leon/synthesis/rules/{ => unused}/IntegerInequalities.scala (99%) rename src/main/scala/leon/synthesis/rules/{ => unused}/OptimisticInjection.scala (98%) rename src/main/scala/leon/synthesis/rules/{ => unused}/SelectiveInlining.scala (90%) rename src/main/scala/leon/synthesis/rules/{ => unused}/SygusCVC4.scala (90%) rename src/main/scala/leon/synthesis/rules/{ => unused}/TEGIS.scala (94%) rename src/main/scala/leon/synthesis/rules/{ => unused}/TEGISLike.scala (99%) rename src/main/scala/leon/synthesis/rules/{ => unused}/TEGLESS.scala (96%) diff --git a/src/main/scala/leon/repair/rules/Focus.scala b/src/main/scala/leon/repair/rules/Focus.scala index 943a5a67f..7ce3fd261 100644 --- a/src/main/scala/leon/repair/rules/Focus.scala +++ b/src/main/scala/leon/repair/rules/Focus.scala @@ -164,7 +164,7 @@ case object Focus extends PreprocessingRule("Focus") { val eb3 = if (vars.nonEmpty) { eb2.mapIns(ebF) } else { - eb2 + eb2.eb } val newPc = andJoin(cond +: vars.map { id => equality(id.toVariable, map(id)) }) diff --git a/src/main/scala/leon/synthesis/ExamplesBank.scala b/src/main/scala/leon/synthesis/ExamplesBank.scala index 1da37b350..35a698686 100644 --- a/src/main/scala/leon/synthesis/ExamplesBank.scala +++ b/src/main/scala/leon/synthesis/ExamplesBank.scala @@ -160,38 +160,44 @@ case class ExamplesBank(valids: Seq[Example], invalids: Seq[Example]) { object ExamplesBank { def empty = ExamplesBank(Nil, Nil) + } /** Same as an ExamplesBank, but with identifiers corresponding to values. This * allows us to evaluate expressions. */ case class QualifiedExamplesBank(as: List[Identifier], xs: List[Identifier], eb: ExamplesBank)(implicit hctx: SearchContext) { - def removeOuts(toRemove: Set[Identifier]) = { + def removeOuts(toRemove: Set[Identifier]): QualifiedExamplesBank = { + val nxs = xs.filterNot(toRemove) val toKeep = xs.zipWithIndex.filterNot(x => toRemove(x._1)).map(_._2) - eb mapOuts { out => List(toKeep.map(out)) } + QualifiedExamplesBank(as, nxs, eb mapOuts { out => List(toKeep.map(out)) }) } def removeIns(toRemove: Set[Identifier]) = { + val nas = as.filterNot(toRemove) val toKeep: List[Int] = as.zipWithIndex.filterNot(a => toRemove(a._1)).map(_._2) - eb mapIns { (in: Seq[Expr]) => List(toKeep.map(in)) } + + QualifiedExamplesBank(nas, xs, eb mapIns { (in: Seq[Expr]) => List(toKeep.map(in)) }) } /** Filter inputs throught expr which is an expression evaluating to a boolean */ - def filterIns(expr: Expr): ExamplesBank = { + def filterIns(expr: Expr): QualifiedExamplesBank = { filterIns(m => hctx.defaultEvaluator.eval(expr, m).result == Some(BooleanLiteral(true))) } /** Filters inputs through the predicate pred, with an assignment of input variables to expressions. */ - def filterIns(pred: Map[Identifier, Expr] => Boolean): ExamplesBank = { - eb mapIns { in => - val m = (as zip in).toMap - if(pred(m)) { - List(in) - } else { - Nil + def filterIns(pred: Map[Identifier, Expr] => Boolean): QualifiedExamplesBank = { + QualifiedExamplesBank(as, xs, + eb mapIns { in => + val m = (as zip in).toMap + if(pred(m)) { + List(in) + } else { + Nil + } } - } + ) } /** Maps inputs through the function f @@ -206,3 +212,9 @@ case class QualifiedExamplesBank(as: List[Identifier], xs: List[Identifier], eb: } } } + +import scala.language.implicitConversions + +object QualifiedExamplesBank { + implicit def qebToEb(qeb: QualifiedExamplesBank): ExamplesBank = qeb.eb +} diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala index f55c670f4..ff92b251e 100644 --- a/src/main/scala/leon/synthesis/Rules.scala +++ b/src/main/scala/leon/synthesis/Rules.scala @@ -51,26 +51,15 @@ object Rules { UnusedInput, EquivalentInputs, UnconstrainedOutput, + if(naiveGrammar) NaiveCEGIS else CEGIS, OptimisticGround, - EqualitySplit, + GenericTypeEqualitySplit, InequalitySplit, IntroduceRecCalls, - if(naiveGrammar) NaiveCEGIS else CEGIS, - //TEGIS, - //BottomUpTEGIS, rules.Assert, - //DetupleOutput, // Subsumed by IndependentSplit DetupleInput, ADTSplit, - //IntegerEquation, - //IntegerInequalities, - IntInduction, InnerCaseSplit - //new OptimisticInjection(_), - //new SelectiveInlining(_), - //ADTLongInduction, - //ADTInduction - //AngelicHoles // @EK: Disabled now as it is explicit with withOracle { .. } ) } @@ -212,20 +201,4 @@ trait RuleDSL { case _ => None } - - /** Straightforward combination of solutions, where expression is reconstructed according to a combiner. - * If combiner fails, no solution will be returned. - * - * @param combiner The combiner of synthesized subterms which reconstructs the term of the solution from the subterms. - */ - def simpleCombine(combiner: PartialFunction[List[Expr], Expr]): List[Solution] => Option[Solution] = { ls => - combiner.lift(ls map (_.term)).map{ combined => - Solution( - orJoin(ls map (_.pre)), - ls.flatMap (_.defs).toSet, - combined, - ls.forall(_.isTrusted) - ) - } - } } diff --git a/src/main/scala/leon/synthesis/rules/EqualitySplit.scala b/src/main/scala/leon/synthesis/rules/EqualitySplit.scala deleted file mode 100644 index 6f6eea54f..000000000 --- a/src/main/scala/leon/synthesis/rules/EqualitySplit.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright 2009-2016 EPFL, Lausanne */ - -package leon -package synthesis -package rules - -import purescala.Common.Identifier -import purescala.Expressions._ -import purescala.Extractors._ -import purescala.Constructors._ - -/** For every pair of input variables of the same type, - * checks equality and output an If-Then-Else statement with the two new branches. */ -case object EqualitySplit extends Rule("Eq. Split") { - def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { - // We approximate knowledge of equality based on facts found at the top-level - // we don't care if the variables are known to be equal or not, we just - // don't want to split on two variables for which only one split - // alternative is viable. This should be much less expensive than making - // calls to a solver for each pair. - var facts = Set[Set[Identifier]]() - - def addFacts(e: Expr): Unit = e match { - case Not(e) => addFacts(e) - case LessThan(Variable(a), Variable(b)) => facts += Set(a,b) - case LessEquals(Variable(a), Variable(b)) => facts += Set(a,b) - case GreaterThan(Variable(a), Variable(b)) => facts += Set(a,b) - case GreaterEquals(Variable(a), Variable(b)) => facts += Set(a,b) - case Equals(Variable(a), Variable(b)) => facts += Set(a,b) - case _ => - } - - val TopLevelAnds(as) = and(p.pc, p.phi) - for (e <- as) { - addFacts(e) - } - - val candidates = p.as.groupBy(_.getType).mapValues{ as => - as.combinations(2).filterNot(facts contains _.toSet) - }.values.flatten - - candidates.flatMap { - case List(a1, a2) => - - val sub1 = p.copy( - pc = and(Equals(Variable(a1), Variable(a2)), p.pc), - eb = p.qeb.filterIns( (m: Map[Identifier, Expr]) => m(a1) == m(a2)) - ) - val sub2 = p.copy( - pc = and(not(Equals(Variable(a1), Variable(a2))), p.pc), - eb = p.qeb.filterIns( (m: Map[Identifier, Expr]) => m(a1) != m(a2)) - ) - - val onSuccess = simpleCombine { case List(s1, s2) => IfExpr(Equals(Variable(a1), Variable(a2)), s1, s2) } - - Some(decomp(List(sub1, sub2), onSuccess, s"Eq. Split on '$a1' and '$a2'")) - case _ => - None - } - } -} diff --git a/src/main/scala/leon/synthesis/rules/GenericTypeEqualitySplit.scala b/src/main/scala/leon/synthesis/rules/GenericTypeEqualitySplit.scala new file mode 100644 index 000000000..8dce44d68 --- /dev/null +++ b/src/main/scala/leon/synthesis/rules/GenericTypeEqualitySplit.scala @@ -0,0 +1,72 @@ +/* Copyright 2009-2016 EPFL, Lausanne */ + +package leon +package synthesis +package rules + +import leon.purescala.Common.Identifier +import purescala.Constructors._ +import purescala.Expressions._ +import leon.purescala.Extractors.{IsTyped, TopLevelAnds} +import purescala.Types._ + +/** For every pair of input variables of the same generic type, + * checks equality and output an If-Then-Else statement with the two new branches. + */ +case object GenericTypeEqualitySplit extends Rule("Eq. Split") { + def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { + // We approximate knowledge of equality based on facts found at the top-level + // we don't care if the variables are known to be equal or not, we just + // don't want to split on two variables for which only one split + // alternative is viable. This should be much less expensive than making + // calls to a solver for each pair. + def getFacts(e: Expr): Set[Set[Identifier]] = e match { + case Not(e) => getFacts(e) + case Equals(Variable(a), Variable(b)) => Set(Set(a,b)) + case _ => Set() + } + + val TopLevelAnds(as) = and(p.pc, p.phi) + + val facts = as.flatMap(getFacts).toSet + + val candidates = p.as.combinations(2).collect { + case List(IsTyped(a1, TypeParameter(t1)), IsTyped(a2, TypeParameter(t2))) + if t1 == t2 && !facts(Set(a1, a2)) => + (a1, a2) + }.toList + + candidates.flatMap { + case (a1, a2) => + val v1 = Variable(a1) + val v2 = Variable(a2) + val subProblems = List( + p.copy(as = p.as.diff(Seq(a1)), + pc = subst(a1 -> v2, p.pc), + ws = subst(a1 -> v2, p.ws), + phi = subst(a1 -> v2, p.phi), + eb = p.qeb.filterIns(Equals(v1, v2)).removeIns(Set(a1))), + + p.copy(pc = and(p.pc, not(Equals(v1, v2))), + eb = p.qeb.filterIns(not(Equals(v1, v2)))) + ) + + val onSuccess: List[Solution] => Option[Solution] = { + case sols @ List(sEQ, sNE) => + val pre = or( + and(Equals(v1, v2), sEQ.pre), + and(not(Equals(v1, v2)), sNE.pre) + ) + + val term = IfExpr(Equals(v1, v2), sEQ.term, sNE.term) + + Some(Solution(pre, sols.flatMap(_.defs).toSet, term, sols.forall(_.isTrusted))) + } + + Some(decomp(subProblems, onSuccess, s"Eq. Split on '$v1' and '$v2'")) + + case _ => + None + } + } +} diff --git a/src/main/scala/leon/synthesis/rules/InequalitySplit.scala b/src/main/scala/leon/synthesis/rules/InequalitySplit.scala index db41c6c3b..54445a5d4 100644 --- a/src/main/scala/leon/synthesis/rules/InequalitySplit.scala +++ b/src/main/scala/leon/synthesis/rules/InequalitySplit.scala @@ -8,65 +8,99 @@ import purescala.Expressions._ import purescala.Types._ import purescala.Constructors._ import purescala.Extractors._ -import purescala.Common._ +/** For every pair of variables of an integer type plus 0 of that type, + * splits for inequality between these variables + * and reconstructs the subproblems with a (nested) if-then-else. + * + * Takes into account knowledge about equality/inequality in the path condition. + * + */ case object InequalitySplit extends Rule("Ineq. Split.") { + + // Represents NEGATIVE knowledge + private abstract class Fact { + val l: Expr + val r: Expr + } + private case class LT(l: Expr, r: Expr) extends Fact + private case class EQ(l: Expr, r: Expr) extends Fact + def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { - // We approximate knowledge of equality based on facts found at the top-level - // we don't care if the variables are known to be equal or not, we just - // don't want to split on two variables for which only one split - // alternative is viable. This should be much less expensive than making - // calls to a solver for each pair. val TopLevelAnds(as) = and(p.pc, p.phi) - def addFacts(e: Expr): Set[Identifier] = e match { - case Not(e) => addFacts(e) - case LessThan(Variable(a), Variable(b)) => Set(a,b) - case LessEquals(Variable(a), Variable(b)) => Set(a,b) - case GreaterThan(Variable(a), Variable(b)) => Set(a,b) - case GreaterEquals(Variable(a), Variable(b)) => Set(a,b) - case Equals(Variable(a), Variable(b)) => Set(a,b) + + def getFacts(e: Expr): Set[Fact] = e match { + case LessThan(a, b) => Set(LT(b,a), EQ(a,b)) + case LessEquals(a, b) => Set(LT(b,a)) + case GreaterThan(a, b) => Set(LT(a,b), EQ(a,b)) + case GreaterEquals(a, b) => Set(LT(a,b)) + case Equals(a, b) => Set(LT(a,b), LT(b,a)) + case Not(LessThan(a, b)) => Set(LT(a,b)) + case Not(LessEquals(a, b)) => Set(LT(a,b), EQ(a,b)) + case Not(GreaterThan(a, b)) => Set(LT(b,a)) + case Not(GreaterEquals(a, b)) => Set(LT(b,a), EQ(a,b)) + case Not(Equals(a, b)) => Set(EQ(a,b)) case _ => Set() } - val facts = as map addFacts - - val argsPairs = p.as.filter(_.getType == IntegerType).combinations(2) ++ - p.as.filter(_.getType == Int32Type).combinations(2) - - val candidates = argsPairs.toList.filter { case List(a1, a2) => !(facts contains Set(a1, a2)) } - - candidates.collect { - case List(a1, a2) => - val onSuccess = simpleCombine { - case sols@List(sLT, sEQ, sGT) => - IfExpr( - LessThan(Variable(a1), Variable(a2)), - sLT, - IfExpr( - Equals(Variable(a1), Variable(a2)), - sEQ, - sGT - ) - ) - } - val subTypes = List(p.outType, p.outType, p.outType) + val facts = as flatMap getFacts + + val candidates = + (p.as.map(_.toVariable).filter(_.getType == Int32Type) :+ IntLiteral(0)).combinations(2).toList ++ + (p.as.map(_.toVariable).filter(_.getType == IntegerType) :+ InfiniteIntegerLiteral(0)).combinations(2).toList - new RuleInstantiation(s"Ineq. Split on '$a1' and '$a2'", - SolutionBuilderDecomp(subTypes, onSuccess)) { + candidates.flatMap { + case List(v1, v2) => - def apply(hctx: SearchContext) = { - implicit val _ = hctx + val lt = if (!facts.contains(LT(v1, v2))) { + val pc = LessThan(v1, v2) + Some(pc, p.copy(pc = and(p.pc, pc), eb = p.qeb.filterIns(pc))) + } else None - val subLT = p.copy(pc = and(LessThan(Variable(a1), Variable(a2)), p.pc), - eb = p.qeb.filterIns(LessThan(Variable(a1), Variable(a2)))) - val subEQ = p.copy(pc = and(Equals(Variable(a1), Variable(a2)), p.pc), - eb = p.qeb.filterIns(Equals(Variable(a1), Variable(a2)))) - val subGT = p.copy(pc = and(GreaterThan(Variable(a1), Variable(a2)), p.pc), - eb = p.qeb.filterIns(GreaterThan(Variable(a1), Variable(a2)))) + val gt = if (!facts.contains(LT(v2, v1))) { + val pc = GreaterThan(v1, v2) + Some(pc, p.copy(pc = and(p.pc, pc), eb = p.qeb.filterIns(pc))) + } else None - RuleExpanded(List(subLT, subEQ, subGT)) + val eq = if (!facts.contains(EQ(v1, v2)) && !facts.contains(EQ(v2,v1))) { + val pc = Equals(v1, v2) + // One of v1, v2 will be an input variable + val a1 = (v1, v2) match { + case (Variable(a), _) => a + case (_, Variable(a)) => a } + val newP = p.copy( + as = p.as.diff(Seq(a1)), + pc = subst(a1 -> v2, p.pc), + ws = subst(a1 -> v2, p.ws), + phi = subst(a1 -> v2, p.phi), + eb = p.qeb.filterIns(Equals(v1, v2)).removeIns(Set(a1)) + ) + Some(pc, newP) + } else None + + val (pcs, subProblems) = List(eq, lt, gt).flatten.unzip + + if (pcs.size < 2) None + else { + + val onSuccess: List[Solution] => Option[Solution] = { sols => + val pre = orJoin(pcs.zip(sols).map { case (pc, sol) => + and(pc, sol.pre) + }) + + val term = pcs.zip(sols) match { + case Seq((pc1, s1), (_, s2)) => + IfExpr(pc1, s1.term, s2.term) + case Seq((pc1, s1), (pc2, s2), (_, s3)) => + IfExpr(pc1, s1.term, IfExpr(pc2, s2.term, s3.term)) + } + + Some(Solution(pre, sols.flatMap(_.defs).toSet, term, sols.forall(_.isTrusted))) + } + + Some(decomp(subProblems, onSuccess, s"Ineq. Split on '$v1' and '$v2'")) } } } diff --git a/src/main/scala/leon/synthesis/rules/ADTInduction.scala b/src/main/scala/leon/synthesis/rules/unused/ADTInduction.scala similarity index 99% rename from src/main/scala/leon/synthesis/rules/ADTInduction.scala rename to src/main/scala/leon/synthesis/rules/unused/ADTInduction.scala index 90738c698..ab2720fb0 100644 --- a/src/main/scala/leon/synthesis/rules/ADTInduction.scala +++ b/src/main/scala/leon/synthesis/rules/unused/ADTInduction.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Common._ import purescala.Expressions._ diff --git a/src/main/scala/leon/synthesis/rules/ADTLongInduction.scala b/src/main/scala/leon/synthesis/rules/unused/ADTLongInduction.scala similarity index 99% rename from src/main/scala/leon/synthesis/rules/ADTLongInduction.scala rename to src/main/scala/leon/synthesis/rules/unused/ADTLongInduction.scala index d14c2b0f8..4ffd1a8c2 100644 --- a/src/main/scala/leon/synthesis/rules/ADTLongInduction.scala +++ b/src/main/scala/leon/synthesis/rules/unused/ADTLongInduction.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Common._ import purescala.Expressions._ diff --git a/src/main/scala/leon/synthesis/rules/AsChoose.scala b/src/main/scala/leon/synthesis/rules/unused/AsChoose.scala similarity index 79% rename from src/main/scala/leon/synthesis/rules/AsChoose.scala rename to src/main/scala/leon/synthesis/rules/unused/AsChoose.scala index 7f231b85d..06270b939 100644 --- a/src/main/scala/leon/synthesis/rules/AsChoose.scala +++ b/src/main/scala/leon/synthesis/rules/unused/AsChoose.scala @@ -1,8 +1,8 @@ /* Copyright 2009-2016 EPFL, Lausanne */ -package leon -package synthesis -package rules +package leon.synthesis.rules.unused + +import leon.synthesis._ case object AsChoose extends Rule("As Choose") { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { diff --git a/src/main/scala/leon/synthesis/rules/BottomUpTegis.scala b/src/main/scala/leon/synthesis/rules/unused/BottomUpTegis.scala similarity index 99% rename from src/main/scala/leon/synthesis/rules/BottomUpTegis.scala rename to src/main/scala/leon/synthesis/rules/unused/BottomUpTegis.scala index 5dbcbb3a1..8f82395a5 100644 --- a/src/main/scala/leon/synthesis/rules/BottomUpTegis.scala +++ b/src/main/scala/leon/synthesis/rules/unused/BottomUpTegis.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Expressions._ import purescala.Common._ diff --git a/src/main/scala/leon/synthesis/rules/DetupleOutput.scala b/src/main/scala/leon/synthesis/rules/unused/DetupleOutput.scala similarity index 98% rename from src/main/scala/leon/synthesis/rules/DetupleOutput.scala rename to src/main/scala/leon/synthesis/rules/unused/DetupleOutput.scala index a1d219340..18067e952 100644 --- a/src/main/scala/leon/synthesis/rules/DetupleOutput.scala +++ b/src/main/scala/leon/synthesis/rules/unused/DetupleOutput.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Expressions._ import purescala.Common._ diff --git a/src/main/scala/leon/synthesis/rules/IntInduction.scala b/src/main/scala/leon/synthesis/rules/unused/IntInduction.scala similarity index 95% rename from src/main/scala/leon/synthesis/rules/IntInduction.scala rename to src/main/scala/leon/synthesis/rules/unused/IntInduction.scala index bfebd3929..6ef209fcb 100644 --- a/src/main/scala/leon/synthesis/rules/IntInduction.scala +++ b/src/main/scala/leon/synthesis/rules/unused/IntInduction.scala @@ -2,14 +2,14 @@ package leon package synthesis -package rules +package rules.unused -import purescala.Common._ -import purescala.Expressions._ -import purescala.Extractors._ +import purescala.Common.FreshIdentifier import purescala.Constructors._ -import purescala.Types._ -import purescala.Definitions._ +import purescala.Definitions.{FunDef, ValDef} +import purescala.Expressions._ +import purescala.Extractors.IsTyped +import purescala.Types.IntegerType case object IntInduction extends Rule("Int Induction") { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { diff --git a/src/main/scala/leon/synthesis/rules/IntegerEquation.scala b/src/main/scala/leon/synthesis/rules/unused/IntegerEquation.scala similarity index 99% rename from src/main/scala/leon/synthesis/rules/IntegerEquation.scala rename to src/main/scala/leon/synthesis/rules/unused/IntegerEquation.scala index f51d90075..fdb59b00d 100644 --- a/src/main/scala/leon/synthesis/rules/IntegerEquation.scala +++ b/src/main/scala/leon/synthesis/rules/unused/IntegerEquation.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Common._ import purescala.Expressions._ diff --git a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala b/src/main/scala/leon/synthesis/rules/unused/IntegerInequalities.scala similarity index 99% rename from src/main/scala/leon/synthesis/rules/IntegerInequalities.scala rename to src/main/scala/leon/synthesis/rules/unused/IntegerInequalities.scala index dfb1fa8d6..602a7e61b 100644 --- a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala +++ b/src/main/scala/leon/synthesis/rules/unused/IntegerInequalities.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Common._ import purescala.Expressions._ diff --git a/src/main/scala/leon/synthesis/rules/OptimisticInjection.scala b/src/main/scala/leon/synthesis/rules/unused/OptimisticInjection.scala similarity index 98% rename from src/main/scala/leon/synthesis/rules/OptimisticInjection.scala rename to src/main/scala/leon/synthesis/rules/unused/OptimisticInjection.scala index 599fbd5df..b3d35f8a0 100644 --- a/src/main/scala/leon/synthesis/rules/OptimisticInjection.scala +++ b/src/main/scala/leon/synthesis/rules/unused/OptimisticInjection.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Expressions._ import purescala.Extractors._ diff --git a/src/main/scala/leon/synthesis/rules/SelectiveInlining.scala b/src/main/scala/leon/synthesis/rules/unused/SelectiveInlining.scala similarity index 90% rename from src/main/scala/leon/synthesis/rules/SelectiveInlining.scala rename to src/main/scala/leon/synthesis/rules/unused/SelectiveInlining.scala index 446938213..9dd4e68e0 100644 --- a/src/main/scala/leon/synthesis/rules/SelectiveInlining.scala +++ b/src/main/scala/leon/synthesis/rules/unused/SelectiveInlining.scala @@ -2,11 +2,11 @@ package leon package synthesis -package rules +package rules.unused -import purescala.Expressions._ -import purescala.Extractors._ import purescala.Constructors._ +import purescala.Expressions.{Equals, Expr, FunctionInvocation} +import purescala.Extractors.TopLevelAnds case object SelectiveInlining extends Rule("Sel. Inlining") { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { diff --git a/src/main/scala/leon/synthesis/rules/SygusCVC4.scala b/src/main/scala/leon/synthesis/rules/unused/SygusCVC4.scala similarity index 90% rename from src/main/scala/leon/synthesis/rules/SygusCVC4.scala rename to src/main/scala/leon/synthesis/rules/unused/SygusCVC4.scala index d458de88c..800d1e5f8 100644 --- a/src/main/scala/leon/synthesis/rules/SygusCVC4.scala +++ b/src/main/scala/leon/synthesis/rules/unused/SygusCVC4.scala @@ -2,9 +2,9 @@ package leon package synthesis -package rules +package rules.unused -import solvers.sygus._ +import leon.solvers.sygus.CVC4SygusSolver case object SygusCVC4 extends Rule("SygusCVC4") { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { diff --git a/src/main/scala/leon/synthesis/rules/TEGIS.scala b/src/main/scala/leon/synthesis/rules/unused/TEGIS.scala similarity index 94% rename from src/main/scala/leon/synthesis/rules/TEGIS.scala rename to src/main/scala/leon/synthesis/rules/unused/TEGIS.scala index 242502a16..7b08304dc 100644 --- a/src/main/scala/leon/synthesis/rules/TEGIS.scala +++ b/src/main/scala/leon/synthesis/rules/unused/TEGIS.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Types._ import grammars._ diff --git a/src/main/scala/leon/synthesis/rules/TEGISLike.scala b/src/main/scala/leon/synthesis/rules/unused/TEGISLike.scala similarity index 99% rename from src/main/scala/leon/synthesis/rules/TEGISLike.scala rename to src/main/scala/leon/synthesis/rules/unused/TEGISLike.scala index a085ad436..cd6382864 100644 --- a/src/main/scala/leon/synthesis/rules/TEGISLike.scala +++ b/src/main/scala/leon/synthesis/rules/unused/TEGISLike.scala @@ -2,7 +2,7 @@ package leon package synthesis -package rules +package rules.unused import purescala.Expressions._ import purescala.Types._ diff --git a/src/main/scala/leon/synthesis/rules/TEGLESS.scala b/src/main/scala/leon/synthesis/rules/unused/TEGLESS.scala similarity index 96% rename from src/main/scala/leon/synthesis/rules/TEGLESS.scala rename to src/main/scala/leon/synthesis/rules/unused/TEGLESS.scala index f87968ea3..a58a0b138 100644 --- a/src/main/scala/leon/synthesis/rules/TEGLESS.scala +++ b/src/main/scala/leon/synthesis/rules/unused/TEGLESS.scala @@ -2,11 +2,10 @@ package leon package synthesis -package rules +package rules.unused import purescala.Types._ import purescala.Extractors._ -import utils._ import Witnesses._ import grammars._ diff --git a/src/main/scala/leon/synthesis/utils/Helpers.scala b/src/main/scala/leon/synthesis/utils/Helpers.scala index 87d9c587c..a0b940958 100644 --- a/src/main/scala/leon/synthesis/utils/Helpers.scala +++ b/src/main/scala/leon/synthesis/utils/Helpers.scala @@ -61,9 +61,19 @@ object Helpers { case _ => None } + val z = InfiniteIntegerLiteral(0) + val one = InfiniteIntegerLiteral(1) val knownSmallers = clauses.collect { case Equals(v: Variable, s@CaseClassSelector(cct, r, _)) => subExprsOf(s, v) case Equals(s@CaseClassSelector(cct, r, _), v: Variable) => subExprsOf(s, v) + case GreaterThan(v: Variable, `z`) => + Some(v -> Minus(v, one)) + case LessThan(`z`, v: Variable) => + Some(v -> Minus(v, one)) + case LessThan(v: Variable, `z`) => + Some(v -> Plus(v, one)) + case GreaterThan(`z`, v: Variable) => + Some(v -> Plus(v, one)) }.flatten.groupBy(_._1).mapValues(v => v.map(_._2)) def argsSmaller(e: Expr, tpe: TypeTree): Seq[Expr] = e match { @@ -74,7 +84,6 @@ object Helpers { }.flatten case v: Variable => knownSmallers.getOrElse(v, Seq()) - case _ => Nil } diff --git a/src/test/scala/leon/regression/synthesis/StablePrintingSuite.scala b/src/test/scala/leon/regression/synthesis/StablePrintingSuite.scala index da7f51f4f..6ab235dd5 100644 --- a/src/test/scala/leon/regression/synthesis/StablePrintingSuite.scala +++ b/src/test/scala/leon/regression/synthesis/StablePrintingSuite.scala @@ -42,10 +42,8 @@ class StablePrintingSuite extends LeonRegressionSuite { OptimisticGround, InequalitySplit, rules.Assert, - DetupleOutput, DetupleInput, ADTSplit, - IntInduction, InnerCaseSplit ) diff --git a/synthesis-collective.txt b/synthesis-collective.txt index 5085e1dcc..f2cbedc5d 100644 --- a/synthesis-collective.txt +++ b/synthesis-collective.txt @@ -6,7 +6,7 @@ F = Timeout/failed to synth. ============================================================================ -Name | FDefs| Size | O-O-5 | O-O-7 |<current> | +Name | FDefs| Size | O-O-5 | O-O-7 | 0515ff9 | ============================================================================ List.insert | 59 | 3 | ✓ | 0.8 | ✓ | 1.0 | ✓ | 0.7 | List.delete | 61 | 0 | ✓ | 4.5 | F | 30.1 | ✓ | 3.2 | diff --git a/testcases/synthesis/current/RunLength/RunLength.scala b/testcases/synthesis/current/RunLength/RunLength.scala index fd886180e..8813b97f7 100644 --- a/testcases/synthesis/current/RunLength/RunLength.scala +++ b/testcases/synthesis/current/RunLength/RunLength.scala @@ -5,7 +5,6 @@ import leon.collection._ object RunLength { - def decode[A](l: List[(BigInt, A)]): List[A] = { def fill[A](i: BigInt, a: A): List[A] = { if (i > 0) a :: fill(i - 1, a) @@ -18,7 +17,6 @@ object RunLength { } } - def legal[A](l: List[(BigInt, A)]): Boolean = l match { case Cons((i, x), tl) => i > 0 && (tl match { @@ -28,12 +26,6 @@ object RunLength { case _ => true } - /*def unique[A](l1: List[A], l2: List[A]) => { - require(encode(l1) == encode(l2)) - l1 == l2 - }.holds*/ - - // Solvable with --manual=2,0,0,1,0,0,3,0,1,1,0,0,1,0,0,0,1,1,1 def encode[A](l: List[A]): List[(BigInt, A)] = { // Solution /*l match { -- GitLab