package at.iaik.suraq.test; import java.io.File; import java.io.FileWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import at.iaik.suraq.exceptions.ParseError; import at.iaik.suraq.main.Ackermann; import at.iaik.suraq.main.SuraqOptions; import at.iaik.suraq.parser.LogicParser; import at.iaik.suraq.parser.SExpParser; import at.iaik.suraq.sexp.SExpression; import at.iaik.suraq.sexp.SExpressionConstants; import at.iaik.suraq.sexp.Token; import at.iaik.suraq.smtlib.SMTLibObject; import at.iaik.suraq.smtlib.formula.AndFormula; import at.iaik.suraq.smtlib.formula.DomainVariable; import at.iaik.suraq.smtlib.formula.Formula; import at.iaik.suraq.smtlib.formula.FunctionMacro; import at.iaik.suraq.smtlib.formula.ImpliesFormula; import at.iaik.suraq.smtlib.formula.NotFormula; import at.iaik.suraq.smtlib.formula.PropositionalVariable; import at.iaik.suraq.smtlib.formula.UninterpretedFunction; import at.iaik.suraq.smtsolver.SMTSolver; /** * This class tests if the Ackermann's reduction works. It is not possible to * perform all tests, only: * the given formula is unsatisfiable * the given * formula is valid * * @author chillebold * */ public class AckermannTest { // SuraqOptions options; protected Formula consequent; public AckermannTest() { // options = SuraqOptions.getInstance(); } // AckermannPredicatesTest has better testfunction!!!! @Before public void setUp() { Ackermann.setActive(true); SuraqOptions.kill(); SuraqOptions.reset(); // Z3Proof.setInstanceCounter(0); } // Live: Staendig zum Herumprobieren @Test public void liveTest() { System.out .println("****************************************************"); System.out.println("Testcase: Live: " + "./rsc/test/live.smt2"); boolean result = testFile("./rsc/test/live.smt2", "./rsc/test/~live-acker.smt2", "./rsc/test/~live-unsat.smt2"); System.out .println(" live: " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // Ackermann Example aus dem Buch: 3.4 auf Seite 66 - normal @Test public void example0Test() { System.out .println("****************************************************"); System.out.println("Testcase: Example 3.4 (pg. 66): " + "./rsc/test/ex34.smt2"); boolean result = testFile("./rsc/test/ex34.smt2", "./rsc/test/~ex34-acker.smt2", "./rsc/test/~ex34-unsat.smt2"); System.out.println(" Example 3.4 (pg. 66): " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // Ackermann Example aus dem Buch: 3.4 auf Seite 66 - mit AND statt OR ganz // aussen. @Test public void example1Test() { System.out .println("****************************************************"); System.out.println("Testcase: Unsatisfiable with one function: " + "./rsc/test/a01.smt2"); boolean result = testFile("./rsc/test/a01.smt2", "./rsc/test/~a01-acker.smt2", "./rsc/test/~a01-unsat.smt2"); System.out.println(" Example 3.4 (pg. 66) mit AND statt OR: " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // Bsp erweitert um eine zusaetzliche Funktion @Test public void twoFunctions() { System.out .println("****************************************************"); System.out.println("Testcase: 2 different Functions, unsatisfiable: " + "./rsc/test/a02.smt2"); boolean result = testFile("./rsc/test/a02.smt2", "./rsc/test/~a02-acker.smt2", "./rsc/test/~a02-unsat.smt2"); System.out.println(" 2 Functions: " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // Bsp erweitert um eine zusaetzliche Funktion @Test public void recursiveFunctions() { System.out .println("****************************************************"); System.out .println("Testcase: 2 different Functions, recursively, valid: " + "./rsc/test/a03.smt2"); boolean result = testFile("./rsc/test/a03.smt2", "./rsc/test/~a03-acker.smt2", "./rsc/test/~a03-unsat.smt2"); System.out.println(" 2 Functions recursively: " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // Bsp erweitert um eine zusaetzliche Funktion @Test public void largerRecursiveFunctions() { System.out .println("****************************************************"); System.out.println("Testcase: larger recursive functions, valid: " + "./rsc/test/a04.smt2"); boolean result = testFile("./rsc/test/a04.smt2", "./rsc/test/~a04-acker.smt2", "./rsc/test/~a04-unsat.smt2"); System.out.println(" larger recursive functions: " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // Bsp erweitert um eine zusaetzliche Funktion @Test public void twoParameters() { System.out .println("****************************************************"); System.out.println("Testcase: two Parameters, valid: " + "./rsc/test/a05.smt2"); boolean result = testFile("./rsc/test/a05.smt2", "./rsc/test/~a05-acker.smt2", "./rsc/test/~a05-unsat.smt2"); System.out.println(" 2 Parameters: " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // Bsp erweitert um eine zusaetzliche Funktion @Test public void threeParametersWithInnerFunction() { System.out .println("****************************************************"); System.out .println("Testcase: three Parameters with inner function, valid: " + "./rsc/test/a06.smt2"); boolean result = testFile("./rsc/test/a06.smt2", "./rsc/test/~a06-acker.smt2", "./rsc/test/~a06-unsat.smt2"); System.out.println(" three Parameters with inner function: " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // Bsp erweitert um eine zusaetzliche Funktion @Test public void functionParameterOrderTest() { System.out .println("****************************************************"); System.out .println("Testcase: testing correct order of parameters, valid: " + "./rsc/test/a07.smt2"); boolean result = testFile("./rsc/test/a07.smt2", "./rsc/test/~a07-acker.smt2", "./rsc/test/~a07-unsat.smt2"); System.out.println(" testing correct order of parameters: " + (result ? "Success :-)" : "Failed :-(")); Assert.assertTrue(result); } // ///////////////////////////////////////////////////////////////////////////// private void handleParseError(ParseError exc) { System.err.println("PARSE ERROR!"); System.err.println(exc.getMessage()); System.err.println("Line: " + (exc.getLineNumber() > 0 ? exc.getLineNumber() : "unknown")); System.err.println("Column: " + (exc.getColumnNumber() > 0 ? exc.getColumnNumber() : "unknown")); System.err .println("Context: " + (exc.getContext() != "" ? exc.getContext() : "not available")); } protected String makeDeclarationsAndDefinitions(Formula formula) { Set<SExpression> outputExpressions = new HashSet<SExpression>(); Set<PropositionalVariable> propVars = new HashSet<PropositionalVariable>(); Set<SMTLibObject> done = new HashSet<SMTLibObject>(); formula.getPropositionalVariables(propVars, done); done.clear(); for (PropositionalVariable var : propVars) outputExpressions .add(SExpression.makeDeclareFun((Token) var.toSmtlibV2(), SExpressionConstants.BOOL_TYPE, 0)); Set<DomainVariable> domainVars = new HashSet<DomainVariable>(); formula.getDomainVariables(domainVars, done); done.clear(); for (DomainVariable var : domainVars) outputExpressions.add(SExpression.makeDeclareFun( (Token) var.toSmtlibV2(), SExpressionConstants.VALUE_TYPE, 0)); Set<UninterpretedFunction> ufs = new HashSet<UninterpretedFunction>(); formula.getUninterpretedFunctions(ufs, done); done.clear(); for (UninterpretedFunction function : ufs) outputExpressions.add(SExpression.makeDeclareFun( function.getName(), function.getType(), function.getNumParams())); Set<FunctionMacro> macros = new HashSet<FunctionMacro>(); this.consequent.getFunctionMacros(macros, done); done.clear(); for (FunctionMacro macro : macros) outputExpressions.add(macro.toSmtlibV2()); String declarationsStr = ""; for (SExpression declaration : outputExpressions) declarationsStr += declaration.toString(); return declarationsStr; } protected String buildSMTDescription(String declarationStr, String formulaStr) { String smtStr = ""; smtStr += SExpressionConstants.SET_LOGIC_QF_UF.toString(); smtStr += SExpressionConstants.DECLARE_SORT_VALUE.toString(); smtStr += declarationStr; smtStr += "(assert" + formulaStr + ")"; smtStr += SExpressionConstants.CHECK_SAT.toString(); smtStr += SExpressionConstants.EXIT.toString(); return smtStr; } protected Formula getFormulaOfFile(String filename) { File input = new File(filename); // String z3InputStr = inputTransformations(sourceFile); try { SExpParser sExpParser = new SExpParser(input); try { sExpParser.parse(); assert (sExpParser.wasParsingSuccessfull()); } catch (ParseError exc) { handleParseError(exc); return null; } LogicParser logicParser = new LogicParser(sExpParser.getRootExpr()); logicParser.parse(); assert (logicParser.wasParsingSuccessfull()); Formula mainFormula = logicParser.getMainFormula(); Formula formula = mainFormula.flatten(); consequent = formula; return formula; } catch (ParseError ex) { handleParseError(ex); throw new RuntimeException("Unable to parse proof!"); } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException("Other Exception"); } } protected String transformFormulaToString(Formula mainFormula) { String declarationStr = makeDeclarationsAndDefinitions(mainFormula); String formulaSmtStr = buildSMTDescription(declarationStr, mainFormula.toString()); return formulaSmtStr; } protected void writeFile(String filename, String content) { try { File outputFile = new File(filename); FileWriter fstream = new FileWriter(outputFile); fstream.write(content); fstream.close(); } catch (Exception ex) { System.err.println("Datei konnte nicht geschrieben werden: " + filename); } } protected boolean testFile(String filename, String outputFileName1, String outputFileName2) { Formula formula = getFormulaOfFile(filename); SMTSolver z3 = SMTSolver.create(SMTSolver.z3_type, SuraqOptions.getZ3_4Path()); if (formula == null) { System.err.println("formula == null"); return false; } Formula old_formula = formula.deepFormulaCopy(); // Ackermann Ackermann ack = new Ackermann(); HashSet<Token> t = new HashSet<Token>(); formula = ack.performAckermann(formula, t); // ArrayList<PropositionalTerm> col = new ArrayList(); // col.add(old_formula.); // Debug output of Ackermann's result to Filesystem String ackermannstr = transformFormulaToString(formula); writeFile(outputFileName1, ackermannstr); Formula x = formula; z3.solve(transformFormulaToString(x)); int state_acker = z3.getState(); z3.solve(transformFormulaToString(formula)); int state_old = z3.getState(); if (state_acker == state_old) { System.out.println(" Z3 tells us for before and after: " + state_old + " (1=sat, 2=unsat) "); } else { System.err.println(" Z3 tells us for before: " + state_old + " and after: " + state_acker + " (1=sat, 2=unsat) "); } // PropositionalEq equiv = new PropositionalEq(col, false); // false for // inequality ImpliesFormula f1 = ImpliesFormula.create(old_formula, x); ImpliesFormula f2 = ImpliesFormula.create(x, old_formula); ArrayList<Formula> f12 = new ArrayList<Formula>(); f12.add(f1); f12.add(f2); AndFormula equiv = AndFormula.generate(f12); NotFormula whole = NotFormula.create(equiv); Formula toShow = whole; String z3InputStr = transformFormulaToString(toShow); writeFile(outputFileName2, z3InputStr); z3.solve(z3InputStr); switch (z3.getState()) { case SMTSolver.UNSAT: System.out.println(" Z3 tells us UNSAT. Good :-)"); return true; case SMTSolver.SAT: System.err.println(" Z3 tells us SAT. Bad :-("); return false; default: System.err .println(" Z3 OUTCOME ----> UNKNOWN! CHECK ERROR STREAM."); throw (new RuntimeException( "Z3 tells us UNKOWN STATE. CHECK ERROR STREAM.")); } } }