From 83c4f8367c67603a2c0ed7815b054e902da67f51 Mon Sep 17 00:00:00 2001 From: Solal Pirelli <solal.pirelli@gmail.com> Date: Wed, 12 Jan 2022 17:13:12 +0100 Subject: [PATCH] Minimizer: prefer smaller ADT fields --- .../smtlib/optimization/Z3Minimizer.scala | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/scala/inox/solvers/smtlib/optimization/Z3Minimizer.scala b/src/main/scala/inox/solvers/smtlib/optimization/Z3Minimizer.scala index f9e7499ad..4d59540be 100644 --- a/src/main/scala/inox/solvers/smtlib/optimization/Z3Minimizer.scala +++ b/src/main/scala/inox/solvers/smtlib/optimization/Z3Minimizer.scala @@ -27,6 +27,19 @@ trait Z3Minimizer extends Z3Optimizer { case _ => Seq() } + /** + * Gets the "size" of the given type. + * We arbitrarily decide that a BV is "smaller" than an int which is "smaller" than an ADT; + * one could choose a policy to decide the exact size of a BV, but this then gets into questions such as + * "at which point does a BV become bigger than an int" which have no clear answer anyway. + */ + private def sizeOf(t: Type): Int = t match { + case BVType(_, size) => 1 + case IntegerType() => 5 + case adt @ ADTType(_, _) => 10 + case _ => 0 + } + /** * Gets the expressions that should be minimized for the given expr, * given the types of "parents" of the expr to avoid an infinite recursion. @@ -54,9 +67,8 @@ trait Z3Minimizer extends Z3Optimizer { def fieldSizer(field: ValDef)(ctor: TypedADTConstructor): Seq[Expr] = { if (ctor.fields.contains(field)) sizersOf(ADTSelector(e, field.id), parentTypes + field.tpe) else getZeroLiterals(field, parentTypes) } - // BV32 for the size, because the number of fields can't be larger anyway (since fields.length is a Scala int), - // let's not force the use of integers if it's not necessary - val adtSize = rec(ctors, Seq(BVLiteral(false, 0, 32)), c => Seq(BVLiteral(false, c.fields.length, 32))) + // BV64 for the size, let's not force the use of integers if it's not necessary + val adtSize = rec(ctors, Seq(BVLiteral(false, 0, 32)), c => Seq(BVLiteral(false, c.fields.map(f => sizeOf(f.tpe)).sum, 64))) val fieldSizes = ctors.flatMap(_.fields).distinct.filter(f => !parentTypes.contains(f.tpe)).flatMap(f => rec(ctors, getZeroLiterals(f, parentTypes), fieldSizer(f))) adtSize ++ fieldSizes } -- GitLab