diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3AbstractProver.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3AbstractProver.java index 5f2fc0329c..d3c1992b96 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3AbstractProver.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3AbstractProver.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -264,10 +265,11 @@ public ImmutableMap getStatistics() { Preconditions.checkState(!closed); ImmutableMap.Builder builder = ImmutableMap.builder(); + Set seenKeys = new HashSet<>(); final long stats = Native.solverGetStatistics(z3context, z3solver); for (int i = 0; i < Native.statsSize(z3context, stats); i++) { - String key = Native.statsGetKey(z3context, stats, i); + String key = getUnusedKey(seenKeys, Native.statsGetKey(z3context, stats, i)); if (Native.statsIsUint(z3context, stats, i)) { builder.put(key, Integer.toString(Native.statsGetUintValue(z3context, stats, i))); } else if (Native.statsIsDouble(z3context, stats, i)) { @@ -283,6 +285,23 @@ public ImmutableMap getStatistics() { return builder.buildOrThrow(); } + /** + * In some cases, Z3 uses the same statistics key twice. In those cases, we append an index to the + * second usage. + */ + private String getUnusedKey(Set seenKeys, final String originalKey) { + if (seenKeys.add(originalKey)) { + return originalKey; + } + String key; + int index = 0; + do { + index++; + key = originalKey + " (" + index + ")"; + } while (!seenKeys.add(key)); + return key; + } + @Override public void close() { if (!closed) {