Skip to content

Commit f523621

Browse files
committed
Improve Counterexamples
1 parent 2a8f9b7 commit f523621

File tree

4 files changed

+28
-18
lines changed

4 files changed

+28
-18
lines changed

liquidjava-verifier/src/main/java/liquidjava/diagnostics/Colors.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ public class Colors {
66
public static final String GREY = "\u001B[90m";
77
public static final String BOLD_RED = "\u001B[1;31m";
88
public static final String BOLD_YELLOW = "\u001B[1;33m";
9+
public static final String CYAN = "\u001B[36m";
910
}

liquidjava-verifier/src/main/java/liquidjava/diagnostics/LJDiagnostic.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public String toString() {
7777
// details
7878
String details = getDetails();
7979
if (!details.isEmpty()) {
80-
sb.append(" --> ").append(String.join("\n ", details.split("\n"))).append("\n");
80+
sb.append(Colors.CYAN).append(" --> ").append(String.join("\n ", details.split("\n"))).append(Colors.RESET).append("\n");
8181
}
8282

8383
// location

liquidjava-verifier/src/main/java/liquidjava/diagnostics/errors/RefinementError.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,22 @@ public RefinementError(SourcePosition position, ValDerivationNode expected, ValD
2727

2828
@Override
2929
public String getDetails() {
30-
return "Counterexample: " + getCounterExampleString();
30+
String counterexampleString = getCounterExampleString();
31+
if (counterexampleString == null)
32+
return "";
33+
return "Counterexample: " + counterexampleString;
3134
}
3235

3336
public String getCounterExampleString() {
3437
if (counterexample == null || counterexample.assignments().isEmpty())
35-
return "";
38+
return null;
3639

37-
// filter fresh variables and join assignements with &&
38-
String counterexampleExp = counterexample.assignments().stream().filter(a -> !a.startsWith("#fresh_"))
39-
.reduce((a, b) -> a + " && " + b).orElse("");
40+
// join assignements with &&
41+
String counterexampleExp = String.join(" && ", counterexample.assignments());
4042

4143
// check if counterexample is trivial (same as the found value)
4244
if (counterexampleExp.equals(found.getValue().toString()))
43-
return "";
45+
return null;
4446

4547
return counterexampleExp;
4648
}

liquidjava-verifier/src/main/java/liquidjava/smt/TranslatorToZ3.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
import java.util.ArrayList;
1919
import java.util.Arrays;
2020
import java.util.HashMap;
21+
import java.util.HashSet;
2122
import java.util.List;
2223
import java.util.Map;
24+
import java.util.Set;
2325
import java.util.stream.Collectors;
2426

2527
import liquidjava.diagnostics.errors.LJError;
@@ -40,13 +42,15 @@ public class TranslatorToZ3 implements AutoCloseable {
4042
private final Map<String, FuncDecl<?>> funcTranslation = new HashMap<>();
4143
private final Map<String, Expr<?>> funcAppTranslation = new HashMap<>();
4244
private final Map<Expr<?>, String> exprToNameTranslation = new HashMap<>();
45+
private final Set<String> instanceVariableRefinements;
4346

44-
public TranslatorToZ3(liquidjava.processor.context.Context c) {
45-
TranslatorContextToZ3.translateVariables(z3, c.getContext(), varTranslation);
46-
TranslatorContextToZ3.storeVariablesSubtypes(z3, c.getAllVariablesWithSupertypes(), varSuperTypes);
47-
TranslatorContextToZ3.addAliases(c.getAliases(), aliasTranslation);
48-
TranslatorContextToZ3.addGhostFunctions(z3, c.getGhosts(), funcTranslation);
49-
TranslatorContextToZ3.addGhostStates(z3, c.getGhostStates(), funcTranslation);
47+
public TranslatorToZ3(liquidjava.processor.context.Context context) {
48+
TranslatorContextToZ3.translateVariables(z3, context.getContext(), varTranslation);
49+
TranslatorContextToZ3.storeVariablesSubtypes(z3, context.getAllVariablesWithSupertypes(), varSuperTypes);
50+
TranslatorContextToZ3.addAliases(context.getAliases(), aliasTranslation);
51+
TranslatorContextToZ3.addGhostFunctions(z3, context.getGhosts(), funcTranslation);
52+
TranslatorContextToZ3.addGhostStates(z3, context.getGhostStates(), funcTranslation);
53+
instanceVariableRefinements = context.getCtxInstanceVars().stream().map(v -> v.getRefinement().toString()).collect(Collectors.toSet());
5054
}
5155

5256
@SuppressWarnings("unchecked")
@@ -66,18 +70,21 @@ public Counterexample getCounterexample(Model model) {
6670
if (decl.getArity() == 0) {
6771
Symbol name = decl.getName();
6872
Expr<?> value = model.getConstInterp(decl);
73+
String assignment = name + " == " + value;
6974
// Skip values of uninterpreted sorts
70-
if (value.getSort().getSortKind() != Z3_sort_kind.Z3_UNINTERPRETED_SORT)
71-
assignments.add(name + " == " + value);
75+
if (value.getSort().getSortKind() != Z3_sort_kind.Z3_UNINTERPRETED_SORT && !instanceVariableRefinements.contains(assignment))
76+
assignments.add(assignment);
7277
}
7378
}
7479
// Extract function application values
7580
for (Map.Entry<String, Expr<?>> entry : funcAppTranslation.entrySet()) {
76-
String label = entry.getKey();
81+
String name = entry.getKey();
7782
Expr<?> application = entry.getValue();
7883
Expr<?> value = model.eval(application, true);
79-
assignments.add(label + " = " + value);
80-
}
84+
String assignment = name + " == " + value;
85+
if (!instanceVariableRefinements.contains(assignment))
86+
assignments.add(assignment);
87+
}
8188
return new Counterexample(assignments);
8289
}
8390

0 commit comments

Comments
 (0)