-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathVCConstraintSimplification.java
More file actions
88 lines (76 loc) · 3.13 KB
/
Copy pathVCConstraintSimplification.java
File metadata and controls
88 lines (76 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package liquidjava.rj_language.opt;
import static liquidjava.rj_language.opt.VCSimplificationUtils.copyWithRefinement;
import static liquidjava.rj_language.opt.VCSimplificationUtils.isTrue;
import liquidjava.processor.VCImplication;
import liquidjava.processor.context.Context;
import liquidjava.rj_language.Predicate;
import liquidjava.rj_language.ast.LiteralBoolean;
import liquidjava.smt.SMTEvaluator;
import liquidjava.smt.SMTResult;
/**
* Simplifies antecedent constraints that are implied by stronger constraints later in the VC chain
*/
public class VCConstraintSimplification implements VCSimplificationPass {
/**
* Applies one constraint simplification in a VC chain
*/
@Override
public VCImplication apply(VCImplication implication) {
VCImplication cloned = implication.clone();
VCImplication simplified = simplify(cloned);
return simplified == null ? cloned : simplified;
}
/**
* Simplifies the first antecedent implied by a later antecedent
*/
private VCImplication simplify(VCImplication implication) {
if (implication == null || implication.getNext() == null)
return null;
if (!isTrue(implication.getRefinement().getExpression())) { // skip trivial constraints
VCImplication implying = findImplyingAntecedent(implication);
if (implying != null)
return simplifyConstraint(implication);
}
// continue searching for simplifications in the suffix
VCImplication next = simplify(implication.getNext());
if (next == null)
return null;
VCImplication result = copyWithRefinement(implication, implication.getRefinement().clone());
result.setNext(next);
return result;
}
/**
* Finds a later antecedent that implies the current constraint. The final node is the conclusion and is not a
* candidate
*/
private VCImplication findImplyingAntecedent(VCImplication implication) {
for (VCImplication candidate = implication.getNext(); candidate != null
&& candidate.getNext() != null; candidate = candidate.getNext()) {
// ∀x. x > 0 => x > 1 -> ∀x. true => x > 1
if (implies(candidate.getRefinement(), implication.getRefinement()))
return candidate;
}
return null;
}
/**
* Simplifies a redundant constraint to true
*/
private VCImplication simplifyConstraint(VCImplication implication) {
if (!implication.hasBinder())
return implication.getNext().clone();
VCImplication result = copyWithRefinement(implication, new Predicate(new LiteralBoolean(true)));
result.setNext(implication.getNext().clone());
return result;
}
/**
* Checks logical implication using the verifier's existing SMT context
*/
private boolean implies(Predicate stronger, Predicate weaker) {
try {
SMTResult result = new SMTEvaluator().verifySubtype(stronger, weaker, Context.getInstance(), true);
return result.isOk();
} catch (Exception e) {
return false;
}
}
}