23
23
import java .util .ArrayDeque ;
24
24
import java .util .ArrayList ;
25
25
import java .util .Collection ;
26
+ import java .util .Collections ;
26
27
import java .util .Deque ;
28
+ import java .util .LinkedHashSet ;
27
29
import java .util .List ;
28
30
import java .util .Optional ;
29
31
import java .util .Set ;
32
34
import org .sosy_lab .common .collect .PathCopyingPersistentTreeMap ;
33
35
import org .sosy_lab .common .collect .PersistentMap ;
34
36
import org .sosy_lab .java_smt .api .BooleanFormula ;
37
+ import org .sosy_lab .java_smt .api .Formula ;
35
38
import org .sosy_lab .java_smt .api .Model ;
36
39
import org .sosy_lab .java_smt .api .SolverContext .ProverOptions ;
37
40
import org .sosy_lab .java_smt .api .SolverException ;
@@ -46,6 +49,15 @@ abstract class PrincessAbstractProver<E> extends AbstractProverWithAllSat<E> {
46
49
protected final PrincessFormulaManager mgr ;
47
50
protected final Deque <Level > trackingStack = new ArrayDeque <>(); // symbols on all levels
48
51
52
+ /**
53
+ * Values returned by {@link Model#evaluate(Formula)}.
54
+ *
55
+ * <p>We need to record these to make sure that the values returned by the evaluator are
56
+ * consistant. Calling {@link #isUnsat()} will reset this list as the underlying model has been
57
+ * updated.
58
+ */
59
+ protected final Set <IFormula > evaluatedTerms = new LinkedHashSet <>();
60
+
49
61
// assign a unique partition number for eah added constraint, for unsat-core and interpolation.
50
62
protected final UniqueIdGenerator idGenerator = new UniqueIdGenerator ();
51
63
protected final Deque <PersistentMap <Integer , BooleanFormula >> partitions = new ArrayDeque <>();
@@ -76,9 +88,11 @@ protected PrincessAbstractProver(
76
88
public boolean isUnsat () throws SolverException {
77
89
Preconditions .checkState (!closed );
78
90
wasLastSatCheckSat = false ;
91
+ evaluatedTerms .clear ();
79
92
final Value result = api .checkSat (true );
80
93
if (result .equals (SimpleAPI .ProverStatus$ .MODULE$ .Sat ())) {
81
94
wasLastSatCheckSat = true ;
95
+ evaluatedTerms .add (api .partialModelAsFormula ());
82
96
return false ;
83
97
} else if (result .equals (SimpleAPI .ProverStatus$ .MODULE$ .Unsat ())) {
84
98
return true ;
@@ -121,14 +135,27 @@ protected void popImpl() {
121
135
// we have to recreate symbols on lower levels, because JavaSMT assumes "global" symbols.
122
136
Level level = trackingStack .pop ();
123
137
api .addBooleanVariables (asScala (level .booleanSymbols ));
124
- api .addConstants (asScala (level .intSymbols ));
138
+ api .addConstants (asScala (level .theorySymbols ));
125
139
level .functionSymbols .forEach (api ::addFunction );
126
140
if (!trackingStack .isEmpty ()) {
127
141
trackingStack .peek ().mergeWithHigher (level );
128
142
}
129
143
partitions .pop ();
130
144
}
131
145
146
+ /**
147
+ * Get all terms that have been evaluated in the current model. The formulas are assignments that
148
+ * extend the original model.
149
+ */
150
+ Collection <IFormula > getEvaluatedTerms () {
151
+ return Collections .unmodifiableCollection (evaluatedTerms );
152
+ }
153
+
154
+ /** Track an assignment `term == value` for an evaluated term and its value. */
155
+ void addEvaluatedTerm (IFormula pFormula ) {
156
+ evaluatedTerms .add (pFormula );
157
+ }
158
+
132
159
@ SuppressWarnings ("resource" )
133
160
@ Override
134
161
public Model getModel () throws SolverException {
@@ -138,6 +165,7 @@ public Model getModel() throws SolverException {
138
165
return new CachingModel (getEvaluatorWithoutChecks ());
139
166
}
140
167
168
+ @ SuppressWarnings ("resource" )
141
169
@ Override
142
170
protected PrincessModel getEvaluatorWithoutChecks () throws SolverException {
143
171
final PartialModel partialModel ;
@@ -146,7 +174,7 @@ protected PrincessModel getEvaluatorWithoutChecks() throws SolverException {
146
174
} catch (SimpleAPIException ex ) {
147
175
throw new SolverException (ex .getMessage (), ex );
148
176
}
149
- return new PrincessModel (this , partialModel , creator , api );
177
+ return registerEvaluator ( new PrincessModel (this , partialModel , creator , api ) );
150
178
}
151
179
152
180
/**
@@ -213,12 +241,12 @@ void addSymbol(IFormula f) {
213
241
}
214
242
}
215
243
216
- /** add external definition: integer variable. */
244
+ /** add external definition: theory variable (integer, rational, string, etc) . */
217
245
void addSymbol (ITerm f ) {
218
246
Preconditions .checkState (!closed );
219
247
api .addConstant (f );
220
248
if (!trackingStack .isEmpty ()) {
221
- trackingStack .peek ().intSymbols .add (f );
249
+ trackingStack .peek ().theorySymbols .add (f );
222
250
}
223
251
}
224
252
@@ -233,21 +261,21 @@ void addSymbol(IFunction f) {
233
261
234
262
static class Level {
235
263
final List <IFormula > booleanSymbols = new ArrayList <>();
236
- final List <ITerm > intSymbols = new ArrayList <>();
264
+ final List <ITerm > theorySymbols = new ArrayList <>();
237
265
final List <IFunction > functionSymbols = new ArrayList <>();
238
266
239
267
Level () {}
240
268
241
269
/** add higher level to current level, we keep the order of creating symbols. */
242
270
void mergeWithHigher (Level other ) {
243
271
this .booleanSymbols .addAll (other .booleanSymbols );
244
- this .intSymbols .addAll (other .intSymbols );
272
+ this .theorySymbols .addAll (other .theorySymbols );
245
273
this .functionSymbols .addAll (other .functionSymbols );
246
274
}
247
275
248
276
@ Override
249
277
public String toString () {
250
- return String .format ("{%s, %s, %s}" , booleanSymbols , intSymbols , functionSymbols );
278
+ return String .format ("{%s, %s, %s}" , booleanSymbols , theorySymbols , functionSymbols );
251
279
}
252
280
}
253
281
}
0 commit comments