Skip to content

Commit

Permalink
Generate All Minimal Inductive Validity Cores (MIVCs)
Browse files Browse the repository at this point in the history
Add option to generate all minimal inductive validity cores.

Co-authored-by: Elaheh <[email protected]>
Co-authored-by: Mike Whalen <[email protected]>
Co-authored-by: porw1492 <[email protected]>
Co-authored-by: jar-ben <[email protected]>
Co-authored-by: jar-ben <[email protected]>
Co-authored-by: jliu29 <[email protected]>
  • Loading branch information
7 people authored Jun 6, 2020
1 parent d39784b commit a7c848c
Show file tree
Hide file tree
Showing 240 changed files with 9,541 additions and 3,749 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,19 @@ as its underlying SMT solver. Advanced users may wish to install alternative sol
[Yices 2](http://yices.csl.sri.com/index.shtml),
[CVC4](http://cvc4.cs.nyu.edu/web/), or
[MathSAT](http://mathsat.fbk.eu/).

Minimal IVCs enumeration (optional)
-----------------------------------
JKind supports enumeration of All Minimal Inductive Validity Cores (All-MIVCs) to provide a full enumeration of all minimal set of model elements necessary for the inductive proofs of a safety property.
Both the offline enumeration (as described in [1]) and the online enumeration (as described in [2]) have been implemented, and the offline enumeration is the algorithm made available for general use.
To use the MIVC enumeration, run JKind with the following arguments:
```
-all_ivcs -solver z3
```
In addition, use the -timeout argument to limit the time for the enumeration, e.g.,
```
-timeout 1800
```

[1] E. Ghassabani, M. W. Whalen, and A. Gacek. Efficient generation of all minimal inductive validity cores. 2017 Formal Methods in Computer Aided Design (FMCAD), pages 31–38, 2017.
[2] J. Bendik, E. Ghassabani, M. Whalen, and I. Cerna. Online enumeration of all minimal inductive validity cores. In International Conference on Software Engineering and Formal Methods, pages 189–204. Springer, 2018.
16 changes: 7 additions & 9 deletions jkind-api/src/jkind/api/ApiUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public static File writeTempFile(String fileName, String fileExt, String content
}
}

public static void execute(Function<File, ProcessBuilder> runCommand, File lustreFile,
JKindResult result, IProgressMonitor monitor, DebugLogger debug) {
public static void execute(Function<File, ProcessBuilder> runCommand, File lustreFile, JKindResult result,
IProgressMonitor monitor, DebugLogger debug) {
File xmlFile = null;
try {
xmlFile = getXmlFile(lustreFile);
Expand Down Expand Up @@ -68,9 +68,8 @@ private static File getXmlFile(File lustreFile) {
return new File(lustreFile.toString() + ".xml");
}

private static void callJKind(Function<File, ProcessBuilder> runCommand, File lustreFile,
File xmlFile, JKindResult result, IProgressMonitor monitor, DebugLogger debug)
throws IOException, InterruptedException {
private static void callJKind(Function<File, ProcessBuilder> runCommand, File lustreFile, File xmlFile,
JKindResult result, IProgressMonitor monitor, DebugLogger debug) throws IOException, InterruptedException {
ProcessBuilder builder = runCommand.apply(lustreFile);
debug.println("JKind command: " + ApiUtil.getQuotedCommand(builder.command()));
Process process = null;
Expand Down Expand Up @@ -106,8 +105,8 @@ private static void callJKind(Function<File, ProcessBuilder> runCommand, File lu
monitor.done();

if (code != 0 && !monitor.isCanceled()) {
throw new JKindException("Abnormal termination, exit code " + code
+ System.lineSeparator() + result.getText());
throw new JKindException(
"Abnormal termination, exit code " + code + System.lineSeparator() + result.getText());
}
}

Expand Down Expand Up @@ -207,8 +206,7 @@ public static String readAll(InputStream inputStream) throws IOException {
}

public static String getQuotedCommand(List<String> pieces) {
return pieces.stream().map(p -> p.contains(" ") ? "\"" + p + "\"" : p)
.collect(joining(" "));
return pieces.stream().map(p -> p.contains(" ") ? "\"" + p + "\"" : p).collect(joining(" "));
}

public static void addEnvironment(ProcessBuilder builder, Map<String, String> environment) {
Expand Down
2 changes: 1 addition & 1 deletion jkind-api/src/jkind/api/Backend.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package jkind.api;

public enum Backend {
JKIND, KIND2, SALLY
JKIND, KIND2, SALLY
}
29 changes: 20 additions & 9 deletions jkind-api/src/jkind/api/JKindApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;

import jkind.JKindException;
import jkind.SolverOption;
import jkind.api.results.JKindResult;

import org.eclipse.core.runtime.IProgressMonitor;

/**
* The primary interface to JKind.
*/
Expand All @@ -26,11 +26,11 @@ public class JKindApi extends KindApi {
protected Integer pdrMax = null;
protected boolean inductiveCounterexamples = false;
protected boolean ivcReduction = false;
protected boolean allIvcs = false;
protected boolean smoothCounterexamples = false;
protected boolean slicing = true;

protected List<String> vmArgs = Collections.emptyList();

protected SolverOption solver = null;

protected String jkindJar;
Expand All @@ -40,7 +40,7 @@ public class JKindApi extends KindApi {

/**
* Set the maximum depth for BMC and k-induction
*
*
* @param n
* A non-negative integer
*/
Expand All @@ -65,7 +65,7 @@ public void disableInvariantGeneration() {

/**
* Set the maximum number of PDR instances to run
*
*
* @param pdrMax
* A non-negative integer
*/
Expand Down Expand Up @@ -97,6 +97,13 @@ public void setIvcReduction() {
ivcReduction = true;
}

/**
* Find all inductive validity cores for valid properties
*/
public void setAllIvcs() {
allIvcs = true;
}

/**
* Post-process counterexamples to have minimal input value changes
*/
Expand All @@ -110,7 +117,7 @@ public void setSmoothCounterexamples() {
public void disableSlicing() {
slicing = false;
}

/**
* Set VM args
*/
Expand Down Expand Up @@ -151,7 +158,7 @@ public void setWriteAdviceFile(String fileName) {

/**
* Run JKind on a Lustre program
*
*
* @param lustreFile
* File containing Lustre program
* @param result
Expand Down Expand Up @@ -197,6 +204,10 @@ private ProcessBuilder getJKindProcessBuilder(File lustreFile) {
if (ivcReduction) {
args.add("-ivc");
}
if (allIvcs) {
args.add("-all_ivcs");
}

if (smoothCounterexamples) {
args.add("-smooth");
}
Expand Down Expand Up @@ -232,7 +243,7 @@ protected String[] getJKindCommand() {
args.add("-jar");
args.add(getOrFindJKindJar());
args.add("-jkind");

return args.toArray(new String[args.size()]);
}

Expand Down
3 changes: 1 addition & 2 deletions jkind-api/src/jkind/api/JLustre2ExcelApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ public File execute(File lustreFile) {
try {
process = pb.start();
String output = ApiUtil.readOutput(process, new NullProgressMonitor());
debug.println("JLustre2Excel output",
debug.saveFile("jlustre2excel-output-", ".txt", output));
debug.println("JLustre2Excel output", debug.saveFile("jlustre2excel-output-", ".txt", output));
return new File(lustreFile.getPath() + ".xls");
} catch (IOException e) {
throw new JKindException("Error running JLustre2Excel", e);
Expand Down
8 changes: 4 additions & 4 deletions jkind-api/src/jkind/api/JRealizabilityApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class JRealizabilityApi {
private boolean extendCounterexample = false;
private boolean reduce = false;
private DebugLogger debug = new DebugLogger();

private List<String> vmArgs = Collections.emptyList();

private String jkindJar;
Expand Down Expand Up @@ -104,13 +104,13 @@ public void setJKindJar(String jkindJar) {
public void setEnvironment(String key, String value) {
environment.put(key, value);
}

/**
* Set VM args
*/
public void setVmArgs(List<String> args) {
vmArgs = new ArrayList<>(args);
}
}

/**
* Run JRealizability on a Lustre program
Expand Down Expand Up @@ -197,7 +197,7 @@ protected String[] getJRealizabilityCommand() {
args.add("-jar");
args.add(getOrFindJKindJar());
args.add("-jrealizability");

return args.toArray(new String[args.size()]);
}

Expand Down
4 changes: 2 additions & 2 deletions jkind-api/src/jkind/api/examples/Kind2WebExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public static void main(String[] args) throws Exception {
URI uri = new URI(args[0]);
String filename = args[1];

try (LineInputStream lines = new LineInputStream(new Kind2WebInputStream(uri,
getKindArgs(), getLustre(filename)))) {
try (LineInputStream lines = new LineInputStream(
new Kind2WebInputStream(uri, getKindArgs(), getLustre(filename)))) {
String line;
while ((line = lines.readLine()) != null) {
System.out.print(line);
Expand Down
22 changes: 10 additions & 12 deletions jkind-api/src/jkind/api/examples/coverage/CoverageReporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@
import jkind.results.ValidProperty;

public class CoverageReporter {
public static void writeHtml(String filename, Program program,
Map<String, ELocation> locationMap, JKindResult result) throws Exception {
public static void writeHtml(String filename, Program program, Map<String, ELocation> locationMap,
JKindResult result) throws Exception {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename + ".html"))) {
writer.write("<html>\n");
writeHeader(writer);
writer.write("<body>\n");

for (PropertyResult pr : result.getPropertyResults()) {
if (!(pr.getProperty() instanceof ValidProperty)) {
writer.write("<p class='not-valid'>" + pr.getProperty().getName()
+ " is invalid/unknown</p>\n");
writer.write("<p class='not-valid'>" + pr.getProperty().getName() + " is invalid/unknown</p>\n");
}
}

Expand All @@ -41,13 +40,12 @@ public static void writeHtml(String filename, Program program,
ValidProperty vp = (ValidProperty) pr.getProperty();
List<String> allIvcs = getAllIvcs(program);

List<ELocation> locations = getUnusedLocations(locationMap, allIvcs,
vp.getIvc());
List<ELocation> locations = getUnusedLocations(locationMap, allIvcs, vp.getIvc());

int total = allIvcs.size();
int covered = total - locations.size();
String stats = String.format("%s: %.1f%% (%d of %d covered)", vp.getName(),
100.0 * covered / total, covered, total);
String stats = String.format("%s: %.1f%% (%d of %d covered)", vp.getName(), 100.0 * covered / total,
covered, total);
writer.write("<div class='valid'>\n");
writer.write("<div class='stats'>" + stats + "</div>\n");
displayLocations(writer, filename, locations);
Expand All @@ -60,8 +58,8 @@ public static void writeHtml(String filename, Program program,
}
}

private static List<ELocation> getUnusedLocations(Map<String, ELocation> locationMap,
List<String> allIvcs, Set<String> usedIvcs) {
private static List<ELocation> getUnusedLocations(Map<String, ELocation> locationMap, List<String> allIvcs,
Set<String> usedIvcs) {
Set<String> baseUsedIvcs = new HashSet<>();
Pattern pattern = Pattern.compile(".*(" + ExtractorVisitor.PREFIX + "\\d+).*");
for (String ivc : usedIvcs) {
Expand Down Expand Up @@ -101,8 +99,8 @@ private static void writeHeader(BufferedWriter writer) throws IOException {
writer.write("</head>\n");
}

private static void displayLocations(BufferedWriter writer, String filename,
List<ELocation> locations) throws Exception {
private static void displayLocations(BufferedWriter writer, String filename, List<ELocation> locations)
throws Exception {
int i = 0;

writer.write("<div class='lustre'>");
Expand Down
4 changes: 2 additions & 2 deletions jkind-api/src/jkind/api/examples/coverage/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ public static void main(String[] args) throws Exception {
}
String filename = args[0];
Program program = parseLustre(new ANTLRFileStream(filename));

ExtractorVisitor visitor = new ExtractorVisitor();
program = visitor.visit(program);
program = SubrangeFixVisitor.fix(program);

Util.writeToFile(program.toString(), new File(filename + ".coverage"));
JKindResult result = runJKind(program);
CoverageReporter.writeHtml(filename, program, visitor.getLocationMap(), result);
Expand Down
12 changes: 6 additions & 6 deletions jkind-api/src/jkind/api/results/AnalysisResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@
public abstract class AnalysisResult {
protected final String name;
protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
protected AnalysisResult parent;
protected AnalysisResult parent;

public AnalysisResult(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setParent(AnalysisResult parent) {
pcs.firePropertyChange("parent", this.parent, this.parent = parent);
}

public AnalysisResult getParent() {
return parent;
}

public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
Expand Down
6 changes: 3 additions & 3 deletions jkind-api/src/jkind/api/results/CompositeAnalysisResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ private void addMultiStatus(MultiStatus other) {
multiStatus.add(other);
pcs.firePropertyChange("multiStatus", null, other);
}

public List<AnalysisResult> getChildren() {
return Collections.unmodifiableList(children);
}
Expand All @@ -43,14 +43,14 @@ public void propertyChange(PropertyChangeEvent evt) {
multiStatus.add((Status) evt.getNewValue());
pcs.firePropertyChange("status", evt.getOldValue(), evt.getNewValue());
}

if ("multiStatus".equals(evt.getPropertyName()) && children.contains(evt.getSource())) {
multiStatus.remove((MultiStatus) evt.getOldValue());
multiStatus.add((MultiStatus) evt.getNewValue());
pcs.firePropertyChange("multiStatus", evt.getOldValue(), evt.getNewValue());
}
}

@Override
public String toString() {
return name + children;
Expand Down
9 changes: 3 additions & 6 deletions jkind-api/src/jkind/api/results/JKindResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ public JKindResult(String name, List<String> properties, List<Boolean> invertSta
* @param renaming
* Renaming to apply to properties
*/
public JKindResult(String name, List<String> properties, List<Boolean> invertStatus,
Renaming renaming) {
public JKindResult(String name, List<String> properties, List<Boolean> invertStatus, Renaming renaming) {
super(name);
this.renaming = renaming;
addProperties(properties, invertStatus);
Expand Down Expand Up @@ -151,8 +150,7 @@ public PropertyResult addProperty(String property, boolean invertStatus) {
PropertyResult propertyResult = new PropertyResult(property, renaming, invertStatus);
propertyResults.add(propertyResult);
propertyResult.setParent(this);
pcs.fireIndexedPropertyChange("propertyResults", propertyResults.size() - 1, null,
propertyResult);
pcs.fireIndexedPropertyChange("propertyResults", propertyResults.size() - 1, null, propertyResult);
addStatus(propertyResult.getStatus());
propertyResult.addPropertyChangeListener(this);
return propertyResult;
Expand Down Expand Up @@ -353,8 +351,7 @@ public void propertyChange(PropertyChangeEvent evt) {
pcs.firePropertyChange("status", evt.getOldValue(), evt.getNewValue());
}

if ("multiStatus".equals(evt.getPropertyName())
&& propertyResults.contains(evt.getSource())) {
if ("multiStatus".equals(evt.getPropertyName()) && propertyResults.contains(evt.getSource())) {
multiStatus.remove((MultiStatus) evt.getOldValue());
multiStatus.add((MultiStatus) evt.getNewValue());
pcs.firePropertyChange("multiStatus", evt.getOldValue(), evt.getNewValue());
Expand Down
Loading

0 comments on commit a7c848c

Please sign in to comment.