package querying; import java.io.FileNotFoundException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashSet; import java.util.Scanner; import java.util.regex.Pattern; import parser.ASTatom; import parser.TokenMgrError; import configuration.ASPSolver; import configuration.Settings; import externaltools.ClingoSolver; import externaltools.DLVSolver; import externaltools.ExternalSolver; import querying.parsing.AnswerSets.AnswerSet; import querying.parsing.AnswerSets.AnswerSetParser; import querying.parsing.AnswerSets.ClingoAnswerSetParser; import querying.parsing.AnswerSets.DLVAnswerSetParser; import querying.parsing.query.ParseException; import querying.parsing.query.QASTatom; import querying.parsing.query.QASTliteral; import querying.parsing.query.QueryParser; import typechecking.TypeChecker; import utilities.Pair; import warnings.StringListUtils; public class QueryEngine { Scanner sc; QueryParser parser; ArrayList<AnswerSet> answerSets; private ExternalSolver solver; private AnswerSetParser answerSetParser; private HashSet<String> queryVars; TypeChecker tc; public QueryEngine(ArrayList<AnswerSet> answerSets, TypeChecker tc) { sc = new Scanner(System.in); this.tc = tc; this.answerSets = answerSets; try { if (Settings.getSolver() == ASPSolver.DLV) { solver = new DLVSolver(); answerSetParser = new DLVAnswerSetParser(); } else if (Settings.getSolver() == ASPSolver.Clingo) { solver = new ClingoSolver(); answerSetParser = new ClingoAnswerSetParser(); } } catch (FileNotFoundException ex) { ex.printStackTrace(); } } public void run() { QASTliteral query; if(answerSets.size() == 0 ) { System.err.println("ERROR: Your program is inconsistent"); return; } while (true) { try { query = readQuery(); if (query == null || query.toString().equals("exit") || query.toString().equals("exit.")) { break; } answerQuery(query); } catch (ParseException ex) { System.err .println("your query must have syntax [-]p(t1,t2...,tn) (where the list of terms may be omitted)"); } catch (TokenMgrError ex) { System.err .println("your query must have syntax [-]p(t1,t2...,tn) (where the list of terms may be omitted)"); } } } public void answerGroundQuery(String query) { QASTliteral queryTree = null; try { queryTree = parseQuery(query); } catch (ParseException e) { System.err.println(e.getMessage()); } if(!queryTree.isGround()) { System.err .println("non-ground queries are not supported in command line mode"); } queryVars = new HashSet<String>(); answerGroundQuery(queryTree); } private QASTliteral parseQuery(String query) throws ParseException,TokenMgrError { StringReader sr = new StringReader(query); parser = new QueryParser(sr); return parser.parseQuery(); } private QASTliteral readQuery() throws ParseException,TokenMgrError { System.out.print("?- "); String query = sc.nextLine(); return parseQuery(query); } private void answerQuery(QASTliteral query) { queryVars = query.fetchVariables(); // check the query: try { query.evaluateAllArithmetics(); tc.ignoreLineNumbers = true; tc.checkAtom(new ASTatom((QASTatom)query.jjtGetChild(0))); } catch (parser.ParseException e) { // TODO Auto-generated catch block System.err.println(e.getMessage()); return; } catch (ParseException e) { // TODO Auto-generated catch block System.err.println(e.getMessage()); return; } if (query.isGround()) { answerGroundQuery(query); } else { answerNonGroundQuery(query); } } private void answerNonGroundQuery(QASTliteral query) { AnswerSet theOnlyAnswerSet = getAnswerSetOfCorrespondingASPProgram((QASTatom)query.jjtGetChild(0)); boolean answerFound = false; for (String atom : theOnlyAnswerSet.literals) { if (atom.startsWith("true_in_all_models") && !query.negated || atom.startsWith("false_in_all_models") && query.negated) { answerFound = true; Pair<String, ArrayList<String>> recordContent = StringListUtils .splitTerm(atom); System.out.print(buildAnswer(recordContent.second)); if(!Settings.isWebMode()) { String response = sc.nextLine(); while (!response.equals("") && !response.toLowerCase().equals("q")) { System.err .print("Press Enter to continue or input \'q\' to interrupt the query"); response = sc.nextLine(); } if (response.toLowerCase().equals("q")) { break; } } else{ System.out.println(); } } } if (!answerFound) { System.out.println("unknown"); } } private String buildAnswer(ArrayList<String> terms) { StringBuilder answer = new StringBuilder(); int index = 0; for (String var : queryVars) { if (index != 0) answer.append(" "); answer.append(var + " = " + terms.get(index)); ++index; } return answer.toString(); } private void answerGroundQuery(QASTliteral query) { AnswerSet theOnlyAnswerSet = getAnswerSetOfCorrespondingASPProgram((QASTatom)(query.jjtGetChild(0))); // if there is an atom "true_in_all_models, it is yes" // if there is an atom "false_in_all_models, it is no" for (String atom : theOnlyAnswerSet.literals) { if (atom.startsWith("true_in_all_models") && !query.negated || atom.startsWith("false_in_all_models") && query.negated) { System.out.println("yes"); return; } if (atom.startsWith("false_in_all_models") && !query.negated || atom.startsWith("true_in_all_models") && query.negated) { System.out.println("no"); return; } } System.out.println("unknown"); } private AnswerSet getAnswerSetOfCorrespondingASPProgram(QASTatom query) { String program = constructASPProgram(query); solver.setProgram(program); String solverOutPut = solver.run(true); ArrayList<AnswerSet> answerSets = answerSetParser .getAnswerSets(solverOutPut); // should be exactly oonstructASPProgramPrefix(query);ne answer set: if(answerSets.size()<1) { return null; } else { AnswerSet theOnlyAnswerSet = answerSets.get(0); return theOnlyAnswerSet; } } private String constructASPProgram(QASTatom query) { int answerSetIndex = 1; StringBuilder prefix = new StringBuilder(); for (AnswerSet aSet : answerSets) { for (String atom : aSet.literals) { // System.out.println(atom.toString()); boolean negative = false; if (atom.startsWith("-")) { negative = true; atom = atom.substring(1); } if (negative) { prefix.append("neg("); } else { prefix.append("pos("); } prefix.append(atom + "," + answerSetIndex + ")."); prefix.append(System.getProperty("line.separator")); } ++answerSetIndex; } StringBuilder bodyForTrueInAllModels = new StringBuilder(); StringBuilder bodyForFalseInAllModels = new StringBuilder(); Pair<QASTatom, ArrayList<QASTatom>> movedOutArithmetics = query .moveOutArithmetics(); for (int i = 1; i <= answerSets.size(); i++) { bodyForFalseInAllModels.append(((i > 1) ? "," : "") + "neg(" + movedOutArithmetics.first.toString() + "," + i + ")"); bodyForTrueInAllModels.append(((i > 1) ? "," : "") + "pos(" + movedOutArithmetics.first.toString() + "," + i + ")"); } if (answerSets.size() > 0) { for (int i = 0; i < movedOutArithmetics.second.size(); i++) { bodyForFalseInAllModels.append("," + movedOutArithmetics.second.get(i).toString()); bodyForTrueInAllModels.append("," + movedOutArithmetics.second.get(i).toString()); } } prefix.append("true_in_all_models" + ((queryVars.size() > 0) ? "(" + StringListUtils.getSeparatedList(queryVars, ",") + ")" : "") + ":-" + bodyForTrueInAllModels + "."); prefix.append("false_in_all_models" + ((queryVars.size() > 0) ? "(" + StringListUtils.getSeparatedList(queryVars, ",") + ")" : "") + ":-" + bodyForFalseInAllModels + "."); return prefix.toString(); } boolean isNumber(String s) { Pattern isInteger = Pattern.compile("[1-9]\\d*"); return isInteger.matcher(s).matches(); } }