88
99package org .sosy_lab .java_smt .solvers .princess ;
1010
11+ import static com .google .common .base .Preconditions .checkNotNull ;
1112import static scala .collection .JavaConverters .asJava ;
1213
1314import ap .api .PartialModel ;
2829import ap .terfor .preds .Predicate ;
2930import ap .theories .arrays .ExtArray ;
3031import ap .theories .arrays .ExtArray .ArraySort ;
32+ import ap .theories .arrays .ExtArray .Select$ ;
33+ import ap .theories .arrays .ExtArray .Store$ ;
3134import ap .theories .rationals .Rationals ;
3235import ap .types .Sort ;
3336import ap .types .Sort$ ;
3437import com .google .common .collect .ArrayListMultimap ;
3538import com .google .common .collect .ImmutableList ;
3639import com .google .common .collect .ImmutableSet ;
40+ import com .google .common .collect .ImmutableSet .Builder ;
3741import com .google .common .collect .Iterables ;
3842import com .google .common .collect .Multimap ;
3943import java .util .ArrayList ;
4044import java .util .LinkedHashSet ;
4145import java .util .List ;
42- import java .util .Map ;
46+ import java .util .Map . Entry ;
4347import java .util .Set ;
4448import org .checkerframework .checker .nullness .qual .Nullable ;
4549import 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