/**
* Author: Christoph Hillebold <c.hillebold@student.tugraz.at>
*/
package at.iaik.suraq.smtsolver;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import at.iaik.suraq.main.SuraqOptions;
import at.iaik.suraq.sexp.SExpressionConstants;
import at.iaik.suraq.smtlib.formula.AndFormula;
import at.iaik.suraq.smtlib.formula.Formula;
import at.iaik.suraq.util.DebugHelper;
import at.iaik.suraq.util.ProcessResult;
import at.iaik.suraq.util.ProcessUtil;
import at.iaik.suraq.util.Util;
/**
* Connection to the VeriTSolver in the path ./lib/veriT/veriT. You can get the
* State by calling ::getState() (NOT_RUN, UNSAT, SAT, UNKNOWN). This Class is
* by default ACTIVE, but you can disable it by calling
* VeriTSolver.setActive(false) . You may wish to modify the parameters for the
* VeriTSolver in method ::solve(String smt2). It would be possible to connect
* the veriT-Process by pipes, but for larger files the "pipe broke". In the
* current implementation a UNIQUE temporary input and output file is created.
*
* @author chillebold
*
*/
public class VeriTSolver extends SMTSolver {
/**
* Defines whether the method .solve(..) shall do anything or not (true =
* active)
*/
private static boolean isActive = true;
/**
* The Path of the executable veriT
*/
private static String path = "./lib/veriT/veriT";
/**
* The Path of the VeriT-Proof File, if it exists.
*/
private File lastFile = null;
/**
* The Path of the VeriT-Proof File (internal). This is also set if an error
* occured.
*/
private File proofFile = null;
/**
* Empty Constructor
*/
public VeriTSolver() {
//
}
/**
* Writes the given smt2-String in a temporary File in the "./"-Directory.
*
* @param smt2
*/
@Override
@Deprecated
public void solve(String smt2) {
// reset these variables
lastFile = null;
state = SMTSolver.NOT_RUN;
if (!VeriTSolver.isActive) {
System.err
.println("VeriTSolver didn't perform, because it was set inactive!");
return;
}
DebugHelper.getInstance().stringtoFile(smt2, "debug_before-verit.txt");
if (smt2.indexOf("(get-proof)") != -1) {
System.err.println("Unsupported elements in smt2: (get-proof)");
}
File tmpInFile;
try {
// in the following code, a temporary file in the root directory of
// the project is created.
// TODO: You may want to change the folder or overwrite the old
// files.
// To overwrite just call the constructor of File instead of
// createTempFile...
proofFile = File.createTempFile("veriT-proof", ".smt2", new File(
"./"));
if (!SuraqOptions.getInstance().getKeepTemFiles())
proofFile.deleteOnExit();
tmpInFile = File
.createTempFile("veriT-in", ".smt2", new File("./"));
if (!SuraqOptions.getInstance().getKeepTemFiles())
tmpInFile.deleteOnExit();
FileWriter fw = new FileWriter(tmpInFile);
fw.write(smt2);
fw.close();
System.out.println("Temporary Out file: " + proofFile);
System.out.println("Temporary In file: " + tmpInFile);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
String executionPath = VeriTSolver.path //
+ " --proof-version=1" // 0|1
+ " --proof=" + proofFile // temporary file
+ " --proof-with-sharing" //
+ " --proof-prune" //
+ " --proof-merge" //
+ " --input=smtlib2" //
+ " --output=smtlib2" //
+ " --disable-print-success" //
+ " --disable-banner" //
// + " --max-time=SECONDS" // max. execution time in seconds
// + " --disable-ackermann" // maybe?
+ " " + tmpInFile;
Util.printToSystemOutWithWallClockTimePrefix("starting veriT: "
+ executionPath);
// ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
// smt2);
ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
"");
Util.printToSystemOutWithWallClockTimePrefix("veriT is done.");
String output = pResult.getOutputStream();
String[] lines = output.split("\n");
// StringBuffer proofBuffer = new StringBuffer();
// parse the lines of the output:
for (String line : lines) {
if (line.equalsIgnoreCase("success")) {
// System.out.print(".");
continue;
} else if (line.equalsIgnoreCase("unsupported")) {
System.out.print("-");
continue;
} else if (line.equalsIgnoreCase("sat")) {
state = SMTSolver.SAT;
System.out.println("\nVeriT/SAT");
continue;
} else if (line.equalsIgnoreCase("unsat")) {
state = SMTSolver.UNSAT;
System.out.println("\nVeriT/UNSAT");
continue;
}
// for pipes this would be working:
// if (!line.equals("success") && !line.equals("sat") &&
// !line.equals("unsat")) {
// proofBuffer.append(line + "\n");
// }
}
if (state == SMTSolver.NOT_RUN)
state = SMTSolver.UNKNOWN;
if (pResult.getExitCode() != 0) {
System.out.println("EXIT CODE: " + pResult.getExitCode());
System.out.println("ERROR: " + pResult.getErrorStream());
System.out.println("OUTPUT: " + output);
}
// Code to view the proof (gedit required)
// ProcessUtil.runExternalProcess("gedit " + tmpOutFile);
if (proofFile.exists()) {
lastFile = proofFile;
}
}
/**
* @see at.iaik.suraq.smtsolver.SMTSolver#solve(java.io.File)
*/
@Override
public void solve(File file) {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtsolver.SMTSolver#solve(at.iaik.suraq.smtlib.formula.Formula)
*/
@Override
public void solve(Formula formula) {
List<Formula> formulas = new ArrayList<Formula>(1);
formulas.add(formula);
solve(formulas);
}
/**
* @see at.iaik.suraq.smtsolver.SMTSolver#solve(at.iaik.suraq.smtlib.formula.Formula)
*/
public void solve(Collection<? extends Formula> formulas) {
// reset these variables
lastFile = null;
state = SMTSolver.NOT_RUN;
if (!VeriTSolver.isActive) {
System.err
.println("VeriTSolver didn't perform, because it was set inactive!");
return;
}
File tmpInFile;
try {
// in the following code, a temporary file in the root directory of
// the project is created.
// TODO: You may want to change the folder or overwrite the old
// files.
// To overwrite just call the constructor of File instead of
// createTempFile...
proofFile = File.createTempFile("veriT-proof", ".smt2", new File(
"./"));
tmpInFile = File
.createTempFile("veriT-in", ".smt2", new File("./"));
if (!SuraqOptions.getInstance().getKeepTemFiles())
tmpInFile.deleteOnExit();
FileWriter fw = new FileWriter(tmpInFile);
BufferedWriter writer = new BufferedWriter(fw);
writer.write(SExpressionConstants.SET_LOGIC_QF_UF.toString());
writer.write("\n");
writer.write(SExpressionConstants.DECLARE_SORT_VALUE.toString());
writer.write("\n");
AndFormula conjunction = AndFormula
.generate(new ArrayList<Formula>(formulas));
Util.writeDeclarations(conjunction, writer);
for (Formula formula : formulas) {
writer.write("(" + SExpressionConstants.ASSERT.toString() + " ");
formula.writeTo(writer);
writer.write(" )\n");
}
writer.write(SExpressionConstants.CHECK_SAT.toString());
writer.write(SExpressionConstants.EXIT.toString());
writer.close();
fw.close();
System.out.println("Temporary Out file: " + proofFile);
System.out.println("Temporary In file: " + tmpInFile);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
String executionPath = VeriTSolver.path //
+ " --proof-version=1" // 0|1
+ " --proof=" + proofFile // temporary file
+ " --proof-with-sharing" //
+ " --proof-prune" //
+ " --proof-merge" //
+ " --input=smtlib2" //
+ " --output=smtlib2" //
+ " --disable-print-success" //
+ " --disable-banner" //
// + " --max-time=SECONDS" // max. execution time in seconds
// + " --disable-ackermann" // maybe?
+ " " + tmpInFile;
Util.printToSystemOutWithWallClockTimePrefix("starting veriT: "
+ executionPath);
// ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
// smt2);
ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
"");
Util.printToSystemOutWithWallClockTimePrefix("veriT is done.");
String output = pResult.getOutputStream();
String[] lines = output.split("\n");
// StringBuffer proofBuffer = new StringBuffer();
// parse the lines of the output:
for (String line : lines) {
if (line.equalsIgnoreCase("success")) {
// System.out.print(".");
continue;
} else if (line.equalsIgnoreCase("unsupported")) {
System.out.print("-");
continue;
} else if (line.equalsIgnoreCase("sat")) {
state = SMTSolver.SAT;
System.out.println("\nVeriT/SAT");
continue;
} else if (line.equalsIgnoreCase("unsat")) {
state = SMTSolver.UNSAT;
System.out.println("\nVeriT/UNSAT");
continue;
}
// for pipes this would be working:
// if (!line.equals("success") && !line.equals("sat") &&
// !line.equals("unsat")) {
// proofBuffer.append(line + "\n");
// }
}
if (state == SMTSolver.NOT_RUN)
state = SMTSolver.UNKNOWN;
if (pResult.getExitCode() != 0) {
System.out.println("EXIT CODE: " + pResult.getExitCode());
System.out.println("ERROR: " + pResult.getErrorStream());
System.out.println("OUTPUT: " + output);
}
// Code to view the proof (gedit required)
// ProcessUtil.runExternalProcess("gedit " + tmpOutFile);
if (proofFile.exists()) {
lastFile = proofFile;
}
}
/**
* Solves the given <code>dimacsFile</code>
*
* @param dimacsFile
* @throws IOException
*/
public void solveDimacs(File dimacsFile) throws IOException {
proofFile = File.createTempFile("veriT-proof-dimacs", ".smt2",
new File("./"));
if (!SuraqOptions.getInstance().getKeepTemFiles())
proofFile.deleteOnExit();
String executionPath = VeriTSolver.path //
+ " --proof-version=1" // 0|1
+ " --proof=" + proofFile // temporary file
+ " --proof-with-sharing" //
+ " --proof-prune" //
+ " --proof-merge" //
+ " --input=dimacs" //
+ " --output=smtlib2" //
+ " --disable-print-success" //
+ " --disable-banner" //
// + " --max-time=SECONDS" // max. execution time in seconds
// + " --disable-ackermann" // maybe?
+ " " + dimacsFile;
Util.printToSystemOutWithWallClockTimePrefix("starting veriT: "
+ executionPath);
// ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
// smt2);
ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
"");
Util.printToSystemOutWithWallClockTimePrefix("veriT is done.");
String output = pResult.getOutputStream();
String[] lines = output.split("\n");
// StringBuffer proofBuffer = new StringBuffer();
// parse the lines of the output:
for (String line : lines) {
if (line.equalsIgnoreCase("success")) {
// System.out.print(".");
continue;
} else if (line.equalsIgnoreCase("unsupported")) {
System.out.print("-");
continue;
} else if (line.equalsIgnoreCase("sat")) {
state = SMTSolver.SAT;
System.out.println("\nVeriT/SAT");
continue;
} else if (line.equalsIgnoreCase("unsat")) {
state = SMTSolver.UNSAT;
System.out.println("\nVeriT/UNSAT");
continue;
}
}
if (pResult.getExitCode() != 0) {
System.out.println("EXIT CODE: " + pResult.getExitCode());
System.out.println("ERROR: " + pResult.getErrorStream());
System.out.println("OUTPUT: " + output);
}
if (proofFile.exists()) {
lastFile = proofFile;
}
}
/**
* Reads the Proof-File and returns a BufferedReader. If the method
* solve(...) did not perform successfully, this method can throw a
* FileNotFoundException.
*
* @return
* @throws FileNotFoundException
*/
public BufferedReader getStream() throws FileNotFoundException {
if (lastFile != null) {
return new BufferedReader(new FileReader(lastFile));
}
throw new FileNotFoundException(
"You may not have called VeriTSolver::solve() first.");
}
/**
* Returns the Result of the VeriTProof.
*
* @return a constant of VeriTSolver (NOT_RUN, UNSAT, SAT, UNKNOWN)
*/
@Override
public int getState() {
return state;
}
/**
* Returns whether this Class shall be active or not.
*
* @return
*/
public static boolean isActive() {
return VeriTSolver.isActive;
}
/**
* You can disable the .solve(..) method of this class by calling
* .setActive(false)
*
* @param _isActive
* true if the .solve(..) method should do anything
*/
public static void setActive(boolean _isActive) {
VeriTSolver.isActive = _isActive;
}
/**
* Returns the Path of the VeriT-Proof-File
*
* @return Path of the VeriT-Proof-File
*/
public String getProofFile() {
return proofFile.getPath();
}
}