Skip to content

Commit 669743f

Browse files
committed
simplify model tracking for Princess.
1 parent 1b4ff68 commit 669743f

File tree

2 files changed

+50
-37
lines changed

2 files changed

+50
-37
lines changed

src/org/sosy_lab/java_smt/solvers/princess/PrincessAbstractProver.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
import java.util.ArrayDeque;
2424
import java.util.ArrayList;
2525
import java.util.Collection;
26+
import java.util.Collections;
2627
import java.util.Deque;
28+
import java.util.LinkedHashSet;
2729
import java.util.List;
2830
import java.util.Optional;
2931
import java.util.Set;
@@ -54,7 +56,7 @@ abstract class PrincessAbstractProver<E> extends AbstractProverWithAllSat<E> {
5456
* consistant. Calling {@link #isUnsat()} will reset this list as the underlying model has been
5557
* updated.
5658
*/
57-
protected final List<IFormula> evaluatedTerms = new ArrayList<>();
59+
protected final Set<IFormula> evaluatedTerms = new LinkedHashSet<>();
5860

5961
// assign a unique partition number for eah added constraint, for unsat-core and interpolation.
6062
protected final UniqueIdGenerator idGenerator = new UniqueIdGenerator();
@@ -142,15 +144,14 @@ protected void popImpl() {
142144
}
143145

144146
/**
145-
* Get a list of all terms that have been evaluated in the current model.
146-
*
147-
* <p>The formulas in this list are assignments that extend the original model.
147+
* Get all terms that have been evaluated in the current model. The formulas are assignments that
148+
* extend the original model.
148149
*/
149-
List<IFormula> getEvaluatedTerms() {
150-
return evaluatedTerms;
150+
Collection<IFormula> getEvaluatedTerms() {
151+
return Collections.unmodifiableCollection(evaluatedTerms);
151152
}
152153

153-
/** Add a new term to the list of evaluated terms. */
154+
/** Track an assignment `term == value` for an evaluated term and its value. */
154155
void addEvaluatedTerm(IFormula pFormula) {
155156
evaluatedTerms.add(pFormula);
156157
}

src/org/sosy_lab/java_smt/solvers/princess/PrincessModel.java

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
package org.sosy_lab.java_smt.solvers.princess;
1010

11+
import static com.google.common.base.Preconditions.checkNotNull;
1112
import static scala.collection.JavaConverters.asJava;
1213

1314
import ap.api.PartialModel;
@@ -28,18 +29,21 @@
2829
import ap.terfor.preds.Predicate;
2930
import ap.theories.arrays.ExtArray;
3031
import ap.theories.arrays.ExtArray.ArraySort;
32+
import ap.theories.arrays.ExtArray.Select$;
33+
import ap.theories.arrays.ExtArray.Store$;
3134
import ap.theories.rationals.Rationals;
3235
import ap.types.Sort;
3336
import ap.types.Sort$;
3437
import com.google.common.collect.ArrayListMultimap;
3538
import com.google.common.collect.ImmutableList;
3639
import com.google.common.collect.ImmutableSet;
40+
import com.google.common.collect.ImmutableSet.Builder;
3741
import com.google.common.collect.Iterables;
3842
import com.google.common.collect.Multimap;
3943
import java.util.ArrayList;
4044
import java.util.LinkedHashSet;
4145
import java.util.List;
42-
import java.util.Map;
46+
import java.util.Map.Entry;
4347
import java.util.Set;
4448
import org.checkerframework.checker.nullness.qual.Nullable;
4549
import org.sosy_lab.java_smt.basicimpl.AbstractModel;
@@ -51,6 +55,9 @@ class PrincessModel extends AbstractModel<IExpression, Sort, PrincessEnvironment
5155
private final PartialModel model;
5256
private final SimpleAPI api;
5357

58+
// Keeps track of the temporary variables created for explicit term evaluations in the model.
59+
private static int counter = 0;
60+
5461
PrincessModel(
5562
PrincessAbstractProver<?> pProver,
5663
PartialModel partialModel,
@@ -77,8 +84,8 @@ public ImmutableList<ValueAssignment> asList() {
7784
Multimap<IFunApp, ITerm> arrays = getArrays(interpretation);
7885

7986
// then iterate over the model and generate the assignments
80-
ImmutableSet.Builder<ValueAssignment> assignments = ImmutableSet.builder();
81-
for (Map.Entry<IExpression, IExpression> entry : asJava(interpretation).entrySet()) {
87+
Builder<ValueAssignment> assignments = ImmutableSet.builder();
88+
for (Entry<IExpression, IExpression> entry : asJava(interpretation).entrySet()) {
8289
if (!entry.getKey().toString().equals("Rat_denom") && !isAbbrev(abbrevs, entry.getKey())) {
8390
assignments.addAll(getAssignments(entry.getKey(), entry.getValue(), arrays));
8491
}
@@ -116,13 +123,13 @@ private boolean isAbbrev(Set<Predicate> abbrevs, IExpression var) {
116123
private Multimap<IFunApp, ITerm> getArrays(
117124
scala.collection.Map<IExpression, IExpression> interpretation) {
118125
Multimap<IFunApp, ITerm> arrays = ArrayListMultimap.create();
119-
for (Map.Entry<IExpression, IExpression> entry : asJava(interpretation).entrySet()) {
126+
for (Entry<IExpression, IExpression> entry : asJava(interpretation).entrySet()) {
120127
if (entry.getKey() instanceof IConstant) {
121128
ITerm maybeArray = (IConstant) entry.getKey();
122129
IExpression value = entry.getValue();
123130
if (creator.getEnv().hasArrayType(maybeArray)
124131
&& value instanceof IFunApp
125-
&& ExtArray.Store$.MODULE$.unapply(((IFunApp) value).fun()).isDefined()) {
132+
&& Store$.MODULE$.unapply(((IFunApp) value).fun()).isDefined()) {
126133
// It is value -> variables, hence if 2+ vars have the same value we need a list
127134
arrays.put((IFunApp) value, maybeArray);
128135
}
@@ -147,7 +154,7 @@ private ImmutableList<ValueAssignment> getAssignments(
147154
return ImmutableList.of();
148155
}
149156
Sort sort = Sort$.MODULE$.sortOf(cKey);
150-
if (ExtArray.Select$.MODULE$.unapply(cKey.fun()).isDefined()) {
157+
if (Select$.MODULE$.unapply(cKey.fun()).isDefined()) {
151158
return getAssignmentsFromArraySelect(value, cKey, pArrays);
152159
} else if (sort instanceof ArraySort) {
153160
ExtArray arrayTheory = ((ArraySort) sort).theory();
@@ -281,35 +288,40 @@ private ITerm simplifyRational(ITerm pTerm) {
281288

282289
@Override
283290
protected @Nullable IExpression evalImpl(IExpression expr) {
291+
// TODO creating our own utility variables might eb unexpected from the user.
292+
// We might need to exclude such variables in models and formula traversal.
293+
String newVariable = "__JAVASMT__MODEL_EVAL_" + counter++;
294+
284295
// Extending the partial model does not seem to work in Princess if the formula uses rational
285296
// variables. To work around this issue we (temporarily) add the formula to the assertion
286297
// stack and then repeat the sat-check to get the value.
287-
if (expr instanceof ITerm) {
288-
ITerm term = (ITerm) expr;
289-
api.push();
290-
for (IFormula fixed : prover.getEvaluatedTerms()) {
291-
api.addAssertion(fixed);
292-
}
293-
ITerm var = api.createConstant("__tmp_", getSort(term));
294-
api.addAssertion(var.$eq$eq$eq(term));
295-
api.checkSat(true);
296-
ITerm value = simplifyRational(api.evalToTerm(var));
297-
api.pop();
298-
prover.addEvaluatedTerm(value.$eq$eq$eq(term));
299-
return value;
300-
} else {
301-
IFormula formula = (IFormula) expr;
302-
api.push();
303-
for (IFormula fixed : prover.getEvaluatedTerms()) {
304-
api.addAssertion(fixed);
298+
api.push();
299+
for (IFormula fixed : prover.getEvaluatedTerms()) {
300+
api.addAssertion(fixed);
301+
}
302+
303+
IFormula modelAssignment = null;
304+
try {
305+
if (expr instanceof ITerm) {
306+
ITerm term = (ITerm) expr;
307+
ITerm var = api.createConstant(newVariable, getSort(term));
308+
api.addAssertion(var.$eq$eq$eq(term));
309+
api.checkSat(true);
310+
ITerm value = simplifyRational(api.evalToTerm(var));
311+
modelAssignment = value.$eq$eq$eq(term);
312+
return value;
313+
} else {
314+
IFormula formula = (IFormula) expr;
315+
IFormula var = api.createBooleanVariable(newVariable);
316+
api.addAssertion(var.$less$eq$greater(formula));
317+
api.checkSat(true);
318+
IFormula value = IBoolLit$.MODULE$.apply(api.eval(var));
319+
modelAssignment = value.$less$eq$greater(formula);
320+
return value;
305321
}
306-
IFormula var = api.createBooleanVariable("__tmp_");
307-
api.addAssertion(var.$less$eq$greater(formula));
308-
api.checkSat(true);
309-
IFormula value = IBoolLit$.MODULE$.apply(api.eval(var));
322+
} finally {
310323
api.pop();
311-
prover.addEvaluatedTerm(value.$less$eq$greater(formula));
312-
return value;
324+
prover.addEvaluatedTerm(checkNotNull(modelAssignment));
313325
}
314326
}
315327
}

0 commit comments

Comments
 (0)