|
14 | 14 | import static org.sosy_lab.java_smt.solvers.princess.PrincessEnvironment.toSeq; |
15 | 15 | import static scala.collection.JavaConverters.asJava; |
16 | 16 | import static scala.collection.JavaConverters.asJavaCollection; |
| 17 | +import static scala.collection.JavaConverters.asScala; |
17 | 18 |
|
18 | 19 | import ap.basetypes.IdealInt; |
19 | 20 | import ap.parser.IAtom; |
|
38 | 39 | import ap.parser.ITermITE; |
39 | 40 | import ap.parser.ITimes; |
40 | 41 | import ap.parser.IVariable; |
41 | | -import ap.terfor.conjunctions.Quantifier; |
42 | 42 | import ap.terfor.preds.Predicate; |
43 | 43 | import ap.theories.arrays.ExtArray; |
44 | 44 | import ap.theories.bitvectors.ModuloArithmetic; |
|
53 | 53 | import com.google.common.collect.ImmutableSet; |
54 | 54 | import com.google.common.collect.Table; |
55 | 55 | import java.lang.reflect.InvocationTargetException; |
56 | | -import java.util.ArrayList; |
57 | 56 | import java.util.HashMap; |
58 | 57 | import java.util.List; |
59 | 58 | import java.util.Map; |
60 | 59 | import java.util.Set; |
| 60 | +import org.sosy_lab.common.UniqueIdGenerator; |
61 | 61 | import org.sosy_lab.common.rationals.Rational; |
62 | 62 | import org.sosy_lab.java_smt.api.ArrayFormula; |
63 | 63 | import org.sosy_lab.java_smt.api.BitvectorFormula; |
|
66 | 66 | import org.sosy_lab.java_smt.api.FormulaType; |
67 | 67 | import org.sosy_lab.java_smt.api.FunctionDeclarationKind; |
68 | 68 | import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; |
| 69 | +import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; |
69 | 70 | import org.sosy_lab.java_smt.api.visitors.FormulaVisitor; |
70 | 71 | import org.sosy_lab.java_smt.basicimpl.FormulaCreator; |
71 | 72 | import org.sosy_lab.java_smt.basicimpl.FunctionDeclarationImpl; |
@@ -184,6 +185,9 @@ class PrincessFormulaCreator |
184 | 185 | */ |
185 | 186 | private final Table<Sort, Sort, Sort> arraySortCache = HashBasedTable.create(); |
186 | 187 |
|
| 188 | + // Keeps track of the bound/free variables created when visiting quantified terms. |
| 189 | + private final UniqueIdGenerator boundVariablesId = new UniqueIdGenerator(); |
| 190 | + |
187 | 191 | PrincessFormulaCreator(PrincessEnvironment pEnv) { |
188 | 192 | super( |
189 | 193 | pEnv, |
@@ -398,19 +402,7 @@ public <R> R visit(FormulaVisitor<R> visitor, final Formula f, final IExpression |
398 | 402 | return visitor.visitConstant(f, convertValue(input)); |
399 | 403 |
|
400 | 404 | } else if (input instanceof IQuantified) { |
401 | | - // this is a quantifier |
402 | | - |
403 | | - BooleanFormula body = encapsulateBoolean(((IQuantified) input).subformula()); |
404 | | - return visitor.visitQuantifier( |
405 | | - (BooleanFormula) f, |
406 | | - ((IQuantified) input).quan().equals(Quantifier.apply(true)) ? FORALL : EXISTS, |
407 | | - |
408 | | - // Princess does not hold any metadata about bound variables, |
409 | | - // so we can't get meaningful list here. |
410 | | - // HOWEVER, passing this list to QuantifiedFormulaManager#mkQuantifier |
411 | | - // works as expected. |
412 | | - new ArrayList<>(), |
413 | | - body); |
| 405 | + return visitQuantifier(visitor, (BooleanFormula) f, (IQuantified) input); |
414 | 406 |
|
415 | 407 | } else if (input instanceof IVariable) { |
416 | 408 | // variable bound by a quantifier |
@@ -539,6 +531,29 @@ public <R> R visit(FormulaVisitor<R> visitor, final Formula f, final IExpression |
539 | 531 | getName(input), kind, argTypes.build(), getFormulaType(f), solverDeclaration)); |
540 | 532 | } |
541 | 533 |
|
| 534 | + private <R> R visitQuantifier(FormulaVisitor<R> visitor, BooleanFormula f, IQuantified input) { |
| 535 | + Quantifier quantifier = |
| 536 | + input.quan().equals(ap.terfor.conjunctions.Quantifier.apply(true)) ? FORALL : EXISTS; |
| 537 | + IFormula body = input.subformula(); |
| 538 | + |
| 539 | + // Princess uses de-Bruijn indices, so we have index 0 here for the most outer quantified scope |
| 540 | + IVariable boundVariable = input.sort().boundVariable(0); |
| 541 | + String boundVariableName = "__JAVASMT__BOUND_VARIABLE_" + boundVariablesId.getFreshId(); |
| 542 | + // Currently, Princess supports only non-boolean bound variables, so we can cast to ITerm. |
| 543 | + ITerm substitutionVariable = (ITerm) makeVariable(boundVariable.sort(), boundVariableName); |
| 544 | + |
| 545 | + // substitute the bound variable with a new variable, |
| 546 | + // and un-shift the remaining de-Bruijn indices. |
| 547 | + IFormula substitutedBody = |
| 548 | + IFormula.subst(body, asScala(List.of(substitutionVariable)).toList(), -1); |
| 549 | + |
| 550 | + return visitor.visitQuantifier( |
| 551 | + f, |
| 552 | + quantifier, |
| 553 | + List.of(encapsulateWithTypeOf(substitutionVariable)), |
| 554 | + encapsulateBoolean(substitutedBody)); |
| 555 | + } |
| 556 | + |
542 | 557 | private boolean isBitvectorOperationWithAdditionalArgument(FunctionDeclarationKind kind) { |
543 | 558 | switch (kind) { |
544 | 559 | case BV_NOT: |
|
0 commit comments