Skip to content

Commit 0660019

Browse files
committed
Simplify Redundant Constraints to true
1 parent 2900bf1 commit 0660019

4 files changed

Lines changed: 37 additions & 40 deletions

File tree

liquidjava-verifier/src/main/java/liquidjava/rj_language/opt/VCConstraintElimination.java renamed to liquidjava-verifier/src/main/java/liquidjava/rj_language/opt/VCConstraintSimplification.java

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
package liquidjava.rj_language.opt;
22

33
import static liquidjava.rj_language.opt.VCSimplificationUtils.copyWithRefinement;
4+
import static liquidjava.rj_language.opt.VCSimplificationUtils.isTrue;
45

56
import liquidjava.processor.VCImplication;
67
import liquidjava.processor.context.Context;
78
import liquidjava.rj_language.Predicate;
9+
import liquidjava.rj_language.ast.LiteralBoolean;
810
import liquidjava.smt.SMTEvaluator;
911
import liquidjava.smt.SMTResult;
1012

1113
/**
12-
* Removes antecedent constraints that are implied by stronger constraints later in the VC chain
14+
* Simplifies antecedent constraints that are implied by stronger constraints later in the VC chain
1315
*/
14-
public class VCConstraintElimination implements VCSimplificationPass {
16+
public class VCConstraintSimplification implements VCSimplificationPass {
1517

1618
/**
17-
* Applies one constraint elimination in a VC chain
19+
* Applies one constraint simplification in a VC chain
1820
*/
1921
@Override
2022
public VCImplication apply(VCImplication implication) {
@@ -24,16 +26,19 @@ public VCImplication apply(VCImplication implication) {
2426
}
2527

2628
/**
27-
* Removes the first antecedent implied by a later antecedent
29+
* Simplifies the first antecedent implied by a later antecedent
2830
*/
2931
private VCImplication simplify(VCImplication implication) {
3032
if (implication == null || implication.getNext() == null)
3133
return null;
3234

33-
VCImplication implying = findImplyingAntecedent(implication);
34-
if (implying != null)
35-
return eliminate(implication, implying);
35+
if (!isTrue(implication.getRefinement().getExpression())) { // skip trivial constraints
36+
VCImplication implying = findImplyingAntecedent(implication);
37+
if (implying != null)
38+
return simplifyConstraint(implication);
39+
}
3640

41+
// continue searching for simplifications in the suffix
3742
VCImplication next = simplify(implication.getNext());
3843
if (next == null)
3944
return null;
@@ -50,33 +55,22 @@ private VCImplication simplify(VCImplication implication) {
5055
private VCImplication findImplyingAntecedent(VCImplication implication) {
5156
for (VCImplication candidate = implication.getNext(); candidate != null
5257
&& candidate.getNext() != null; candidate = candidate.getNext()) {
58+
// ∀x. x > 0 => x > 1 -> ∀x. true => x > 1
5359
if (implies(candidate.getRefinement(), implication.getRefinement()))
5460
return candidate;
5561
}
5662
return null;
5763
}
5864

5965
/**
60-
* Eliminates one redundant constraint while preserving any binder attached to it
66+
* Simplifies a redundant constraint to true
6167
*/
62-
private VCImplication eliminate(VCImplication implication, VCImplication implying) {
68+
private VCImplication simplifyConstraint(VCImplication implication) {
6369
if (!implication.hasBinder())
6470
return implication.getNext().clone();
6571

66-
VCImplication result = copyWithRefinement(implication, implying.getRefinement().clone());
67-
result.setNext(remove(implication.getNext(), implying));
68-
return result;
69-
}
70-
71-
/**
72-
* Removes one node from a suffix
73-
*/
74-
private VCImplication remove(VCImplication implication, VCImplication target) {
75-
if (implication == target)
76-
return implication.getNext() == null ? null : implication.getNext().clone();
77-
78-
VCImplication result = copyWithRefinement(implication, implication.getRefinement().clone());
79-
result.setNext(remove(implication.getNext(), target));
72+
VCImplication result = copyWithRefinement(implication, new Predicate(new LiteralBoolean(true)));
73+
result.setNext(implication.getNext().clone());
8074
return result;
8175
}
8276

liquidjava-verifier/src/main/java/liquidjava/rj_language/opt/VCSimplification.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class VCSimplification {
1111

1212
private static final List<VCSimplificationPass> PASSES = List.of(new VCSubstitution(), new VCBinderSimplification(),
1313
new VCFolding(), new VCArithmeticSimplification(), new VCLogicalSimplification(),
14-
new VCConstraintElimination());
14+
new VCConstraintSimplification());
1515

1616
/**
1717
* Applies all available simplification steps to a VC chain until a fixed point is reached

liquidjava-verifier/src/test/java/liquidjava/rj_language/opt/VCConstraintEliminationTest.java renamed to liquidjava-verifier/src/test/java/liquidjava/rj_language/opt/VCConstraintSimplificationTest.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
import liquidjava.processor.context.Context;
1515
import liquidjava.utils.TestUtils;
1616

17-
class VCConstraintEliminationTest {
17+
class VCConstraintSimplificationTest {
1818

19-
private final VCConstraintElimination constraintElimination = new VCConstraintElimination();
19+
private final VCConstraintSimplification simplification = new VCConstraintSimplification();
2020

2121
@BeforeEach
2222
void setUpContext() {
@@ -31,42 +31,45 @@ void resetContext() {
3131
}
3232

3333
@Test
34-
void removesConstraintImpliedByLaterAntecedent() {
35-
assertSimplificationSteps(constraintElimination,
34+
void simplifiesConstraintImpliedByLaterAntecedent() {
35+
assertSimplificationSteps(simplification,
3636
vc("∀x:int. x > 0", "∀cond:boolean. x > 1", "∀y:int. y == x + 1", "y < 0"),
37-
step("x > 1", "y == x + 1", "y < 0"));
37+
step("true", "x > 1", "y == x + 1", "y < 0"));
3838
}
3939

4040
@Test
41-
void preservesBinderOnStrongerConstraint() {
42-
VCImplication simplified = constraintElimination
41+
void preservesBothBindersWhenSimplifyingConstraint() {
42+
VCImplication simplified = simplification
4343
.apply(vc("∀x:int. x > 0", "∀cond:boolean. x > 1", "∀y:int. y == x + 1", "y < 0"));
4444

4545
assertTrue(simplified.hasBinder());
4646
assertEquals("x", simplified.getName());
4747
assertEquals("int", simplified.getType().getQualifiedName());
48+
assertTrue(simplified.getNext().hasBinder());
49+
assertEquals("cond", simplified.getNext().getName());
50+
assertEquals("boolean", simplified.getNext().getType().getQualifiedName());
4851
}
4952

5053
@Test
5154
void keepsConstraintThatIsNotImpliedByLaterAntecedent() {
52-
assertSimplificationSteps(constraintElimination, vc("∀x:int. x > 1", "x > 0", "y > 0"),
55+
assertSimplificationSteps(simplification, vc("∀x:int. x > 1", "x > 0", "y > 0"),
5356
step("x > 1", "x > 0", "y > 0"));
5457
}
5558

5659
@Test
5760
void ignoresUnrelatedLaterAntecedent() {
58-
assertSimplificationSteps(constraintElimination, vc("∀x:int. x > 0", "y > 1", "x + y > 0"),
61+
assertSimplificationSteps(simplification, vc("∀x:int. x > 0", "y > 1", "x + y > 0"),
5962
step("x > 0", "y > 1", "x + y > 0"));
6063
}
6164

6265
@Test
63-
void doesNotUseConclusionToEliminateConstraint() {
64-
assertSimplificationSteps(constraintElimination, vc("∀x:int. x > 0", "x > 1"), step("x > 0", "x > 1"));
66+
void doesNotUseConclusionToSimplifyConstraint() {
67+
assertSimplificationSteps(simplification, vc("∀x:int. x > 0", "x > 1"), step("x > 0", "x > 1"));
6568
}
6669

6770
@Test
68-
void removesOnlyFirstImpliedConstraint() {
69-
assertSimplificationSteps(constraintElimination, vc("∀x:int. x > 0", "x > 1", "x > 2", "y > 0"),
70-
step("x > 1", "x > 2", "y > 0"), step("x > 2", "y > 0"));
71+
void simplifiesOnlyFirstImpliedConstraint() {
72+
assertSimplificationSteps(simplification, vc("∀x:int. x > 0", "x > 1", "x > 2", "y > 0"),
73+
step("true", "x > 1", "x > 2", "y > 0"), step("true", "x > 2", "y > 0"));
7174
}
7275
}

liquidjava-verifier/src/test/java/liquidjava/rj_language/opt/VCSimplificationTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,10 @@ void simplifyLeavesUnchangedVcAsPlainPredicates() {
174174
}
175175

176176
@Test
177-
void simplifyEliminatesConstraintImpliedByLaterAntecedent() {
177+
void simplifyNeutralizesConstraintImpliedByLaterAntecedent() {
178178
TestUtils.addIntVariableToContext("x");
179179
TestUtils.addIntVariableToContext("y");
180180
assertSimplificationSteps(vc("∀x:int. x > 0", "∀cond:boolean. x > 1", "∀y:int. y == x + 1", "y < 0"),
181-
step("x > 0", "x > 1", "x + 1 < 0"), step("x > 1", "x + 1 < 0"));
181+
step("x > 0", "x > 1", "x + 1 < 0"), step("true", "x > 1", "x + 1 < 0"));
182182
}
183183
}

0 commit comments

Comments
 (0)