/**
* Author: Bettina Koenighofer <bettina.koenighofer@iaik.tugraz.at>
*/
package at.iaik.suraq.smtsolver;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import at.iaik.suraq.main.SuraqOptions;
import at.iaik.suraq.sexp.SExpressionConstants;
import at.iaik.suraq.smtlib.formula.Formula;
import at.iaik.suraq.util.ProcessResult;
import at.iaik.suraq.util.ProcessResultStreams;
import at.iaik.suraq.util.ProcessUtil;
import at.iaik.suraq.util.Util;
/**
* SMT-solver bindings for the Microsoft(TM) Z3 solver. Utilizes external calls
* to Z3 application and parses Z3 output.
*
* @author Bettina Koenighofer <bettina.koenighofer@iaik.tugraz.at>
*
*/
public class z3 extends SMTSolver {
/**
* Stores the path to the Z3 distribution.
*/
private String z3Path;
/**
* Constructs a new <code>z3</code> SMT-solver with the given base-path.
*
* @param solverBasePath
* base-path to the Z3 distribution.
*/
public z3(String solverBasePath) {
z3Path = solverBasePath;
}
/**
* @see at.iaik.suraq.smtsolver.SMTSolver#solveStr(String)
*/
@Override
@Deprecated
public void solve(String smtStr) {
String executionPath = z3Path;
if (System.getProperty("os.name").toLowerCase().contains("windows"))
executionPath = executionPath.concat(" /smt2 /in");
else
executionPath = executionPath.concat(" -smt2 -in");
ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
smtStr);
String[] lines = pResult.getOutputStream().split("\n");
StringBuffer proofBuffer = new StringBuffer();
for (String line : lines) {
if (!line.equals("success") && !line.equals("sat")
&& !line.equals("unsat")) {
proofBuffer.append(line + "\n");
}
if (line.equals("sat"))
state = SMTSolver.SAT;
else if (line.equals("unsat"))
state = SMTSolver.UNSAT;
}
if (state == SMTSolver.NOT_RUN)
state = SMTSolver.UNKNOWN;
if (state == SMTSolver.UNSAT)
this.proof = proofBuffer.toString();
if (pResult.getExitCode() != 0) {
System.out.println("EXIT CODE: " + pResult.getExitCode());
System.out.println("ERROR from Z3:" + pResult.getErrorStream());
System.out.println("OUTPUT from Z3: " + pResult.getOutputStream());
}
}
/**
* @see at.iaik.suraq.smtsolver.SMTSolver#solve(java.io.File)
*/
@Override
public void solve(File file) {
String executionPath = z3Path;
if (System.getProperty("os.name").toLowerCase().contains("windows"))
executionPath = executionPath.concat(" /smt2 /file:"
+ file.toString());
else
executionPath = executionPath.concat(" -smt2 -file:"
+ file.toString());
ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
"");
String[] lines = pResult.getOutputStream().split("\n");
StringBuffer proofBuffer = new StringBuffer();
for (String line : lines) {
if (!line.equals("success") && !line.equals("sat")
&& !line.equals("unsat")) {
proofBuffer.append(line + "\n");
}
if (line.equals("sat"))
state = SMTSolver.SAT;
else if (line.equals("unsat"))
state = SMTSolver.UNSAT;
}
if (state == SMTSolver.NOT_RUN)
state = SMTSolver.UNKNOWN;
if (state == SMTSolver.UNSAT)
this.proof = proofBuffer.toString();
if (pResult.getExitCode() != 0) {
System.out.println("EXIT CODE: " + pResult.getExitCode());
System.out.println("ERROR from Z3:" + pResult.getErrorStream());
System.out.println("OUTPUT from Z3: " + pResult.getOutputStream());
}
}
/**
* @see at.iaik.suraq.smtsolver.SMTSolver#solve2(String)
*/
public String solve2(String smtStr) {
String executionPath = z3Path;
if (System.getProperty("os.name").toLowerCase().contains("windows"))
executionPath = executionPath.concat(" /smt2 /in");
else
executionPath = executionPath.concat(" -smt2 -in");
ProcessResult pResult = ProcessUtil.runExternalProcess(executionPath,
smtStr);
if (pResult.getExitCode() != 0) {
System.out.println("EXIT CODE: " + pResult.getExitCode());
System.out.println("ERROR from Z3: " + pResult.getErrorStream());
System.out.println("OUTPUT from Z3: " + pResult.getOutputStream());
}
return pResult.getOutputStream();
}
/**
* Simplified the given formula.
*
* @param formula
* @return a reader with the output of the solver.
*/
public BufferedReader simplify(Formula formula) {
File tmpInFile = null;
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...
tmpInFile = File.createTempFile("z3-in-simplify", ".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");
Util.writeDeclarations(formula, writer);
writer.write("(" + SExpressionConstants.SIMPLIFY.toString() + " ");
// formula.writeTo(writer);
Util.writeFormulaUsingLetExpressions(formula, writer);
writer.write(" " + SExpressionConstants.ELIM_AND.toString() + " "
+ SExpressionConstants.TRUE + ")\n");
writer.write(SExpressionConstants.EXIT.toString());
writer.close();
fw.close();
System.out.println("Temporary z3 file: " + tmpInFile);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
assert (tmpInFile != null);
String executionPath = z3Path;
if (System.getProperty("os.name").toLowerCase().contains("windows"))
executionPath += " /smt2 /file:" + tmpInFile.toString();
else
executionPath += " -smt2 -file:" + tmpInFile.toString();
ProcessResultStreams pResult = ProcessUtil
.runExternalProcessWithStreamResult(executionPath);
if (pResult.getExitCode() != 0) {
System.out.println("EXIT CODE: " + pResult.getExitCode());
System.out.println("ERROR from Z3:");
String line;
try {
while ((line = pResult.getErrorStream().readLine()) != null)
System.out.println(line);
System.out.println();
System.out.println("OUTPUT from Z3:");
while ((line = pResult.getOutputStream().readLine()) != null)
System.out.println(line);
} catch (IOException exc) {
System.out
.println("IOException while trying to display Z3 output.");
throw new RuntimeException(exc);
}
}
return pResult.getOutputStream();
}
/**
* @see at.iaik.suraq.smtsolver.SMTSolver#solve(at.iaik.suraq.smtlib.formula.Formula)
*/
@Override
public void solve(Formula formula) {
File tmpInFile = null;
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...
tmpInFile = File.createTempFile("z3-in-solve", ".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");
Util.writeDeclarations(formula, writer);
writer.write("(" + SExpressionConstants.ASSERT.toString() + " ");
// formula.writeTo(writer);
Util.writeFormulaUsingLetExpressions(formula, writer);
writer.write(" )\n");
writer.write(SExpressionConstants.CHECK_SAT.toString());
writer.write(SExpressionConstants.EXIT.toString());
writer.close();
fw.close();
System.out.println("Temporary z3 file: " + tmpInFile);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
assert (tmpInFile != null);
String executionPath = z3Path;
if (System.getProperty("os.name").toLowerCase().contains("windows"))
executionPath += " /smt2 /file:" + tmpInFile.toString();
else
executionPath += " -smt2 -file:" + tmpInFile.toString();
ProcessResultStreams pResult = ProcessUtil
.runExternalProcessWithStreamResult(executionPath);
if (pResult.getExitCode() != 0) {
System.out.println("EXIT CODE: " + pResult.getExitCode());
System.out.println("ERROR from Z3:");
String line;
try {
while ((line = pResult.getErrorStream().readLine()) != null)
System.out.println(line);
System.out.println();
System.out.println("OUTPUT from Z3:");
while ((line = pResult.getOutputStream().readLine()) != null)
System.out.println(line);
} catch (IOException exc) {
System.out
.println("IOException while trying to display Z3 output.");
throw new RuntimeException(exc);
}
}
String line;
try {
while ((line = pResult.getOutputStream().readLine()) != null) {
if (line.equals("sat"))
state = SMTSolver.SAT;
else if (line.equals("unsat"))
state = SMTSolver.UNSAT;
}
pResult.getOutputStream().close();
pResult.getErrorStream().close();
} catch (IOException exc) {
throw new RuntimeException("IOException while reading z3 output",
exc);
}
if (state == SMTSolver.NOT_RUN)
state = SMTSolver.UNKNOWN;
}
}