/* * Copyright (C) INRIA, 2012-2013 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package fr.inrialpes.tyrexmo.qcwrapper.lmu; import java.util.Collections; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.hp.hpl.jena.query.Query; import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.rdf.model.Model; import fr.inrialpes.tyrexmo.queryanalysis.CycleAnalysis; import fr.inrialpes.tyrexmo.queryanalysis.TransformAlgebra; import fr.inrialpes.tyrexmo.testqc.ContainmentTestException; import fr.inrialpes.tyrexmo.testqc.LegacyContainmentSolver; import fr.inrialpes.tyrexmo.testqc.simple.SimpleContainmentSolver; import fr.inrialpes.wam.treelogic.BottomUpSolver.FormulaSolver; public class TreeSolverWrapper implements LegacyContainmentSolver, SimpleContainmentSolver { final static Logger logger = LoggerFactory.getLogger( TreeSolverWrapper.class ); /*kripke restriction \varphi_r */ // JE: THIS FORMULA IS THE ONE FOR AFMU (but this was the original in Mel's program) private static String theta = "<-s>spr & <p>spr & <o>spr & !<s>true & !<-p>true & !<-o>true"; private static String eta = "!<-s>true & !<o>true & !<p>true & !<d>true & !<-d>true & !<s>spr & !<-p>spr & !<-o>spr"; private static String kappa = "[-s]("+eta+") & [p]("+eta+") & [o]("+eta+")"; private final static String phiR = "(let x1 = nu "+theta+" & "+kappa+" & (!<d>true | <d>x1) in x1 end)"; private FormulaSolver fs = null; // This is test #1 private String WarmupFormula = "((let $v1 = (_varx & <1>(_takesCourse & <2>_Course10)) | <1>$v1 | <2>$v1 in $v1) & (let $v0 = (_varx & <1>(_takesCourse & <2>_Course20)) | <1>$v0 | <2>$v0 in $v0)) & ~((let $v2 = (_varx & <1>(_takesCourse & <2>_Course10)) | <1>$v2 | <2>$v2 in $v2))"; public void warmup() { evaluateFormula( WarmupFormula ); }; public boolean entailed( Query q1, Query q2 ) throws ContainmentTestException { return entailedUnderSchema( (String)null, q1, q2 ); } public boolean entailedUnderSchema( Model schema, Query q1, Query q2 ) throws ContainmentTestException { throw new ContainmentTestException( "Cannot yet parse Jena Models" ); }; public boolean entailedUnderSchema( String schema, Query q1, Query q2 ) throws ContainmentTestException { //long start = System.currentTimeMillis(); TransformAlgebra ta1 = new TransformAlgebra( q1 ); TransformAlgebra ta2 = new TransformAlgebra( q2 ); // Encode formula String formulaLeft, formulaRight; if ( supportedTest( q1, ta1, q2, ta2 ) ) { if ( useSameEncoding( q1, q2 ) ){ logger.warn("BOTH QUERYS ARE EQUAL - THE IMPLEMENTATION MIGHT BE BUGGED"); formulaLeft = new EncodeLHSQuery( ta1 ).getFormula(); //System.out.println(formulaLeft); // JE : ??????? Fortunately, given the coding of useSameEncoding we barely go here! formulaRight = new EncodeLHSQuery( ta2 ).getFormula(); //System.out.println(formulaRight); } else { formulaLeft = new EncodeLHSQuery( ta1 ).getFormula(); //System.out.println(formulaLeft); formulaRight = new EncodeRHSQuery( ta2 ).getFormula(); //System.out.println(formulaRight); } } else { throw new ContainmentTestException( "Cannot deal with such a test" ); } // Create checker //XPathContainment pc = new XPathContainment(); // Test it String formula = "(" + formulaLeft + ") & ~("+ formulaRight + ")"; if ( schema != null ) { formula += " & "+new AxiomEncoder().encodeSchema( schema ); } ta1 = null; ta2 = null; // free memory formulaLeft = null; formulaRight = null; // free memory //long end = System.currentTimeMillis(); //System.err.println( "Ended encoding formulas ["+(end-start)+"ms]"); // This is useless because the Lmu solver only look for tree-shaped models //String formula = phiR +"& (" + formulaLeft + ") & ~("+ formulaRight + ")"; //logger.debug( "Encoded formula: {}", formula ); //start = System.currentTimeMillis(); //return !pc.checkSat( formula ); int res = evaluateFormula( formula ); //logger.debug( "Here is the result returned : {}", res ); //end = System.currentTimeMillis(); //System.err.println( "Ended testing containment ["+(end-start)+"ms]"); if ( res == FormulaSolver.ERROR ) throw new ContainmentTestException( "Solver error" ); else return (res==FormulaSolver.UNSATISFIABLE); }; protected int evaluateFormula( String formula ) { fs = new FormulaSolver(); //System.out.println("Formula: " + formula); int result = fs.solve_formula_int_result( formula, false, false, false, false, false, false, null ); return result; } public void cleanup() { fs = null; System.gc(); }; private boolean supportedTest( Query q1, TransformAlgebra ta1, Query q2, TransformAlgebra ta2 ) { if ( containsOptional( ta1, ta2 ) || isValidQueryType( q1, q2 ) || isCyclic( ta1, ta2 ) || haveSameDistVar( q1, q2 ) ) return false; else return true; } protected boolean containsOptional( TransformAlgebra left, TransformAlgebra right ) { return (left.containsOpt() || right.containsOpt()); } //TODO: add same number and type of variables /** * same left-hand and right-hand side query encoding */ protected boolean useSameEncoding( Query leftQuery, Query rightQuery ) { return leftQuery.equals(rightQuery); } /** * restrict query types to SELCET and ASK */ protected boolean isValidQueryType( Query leftQuery, Query rightQuery ) { return (leftQuery.isConstructType() || rightQuery.isConstructType() || leftQuery.isDescribeType() || rightQuery.isDescribeType()); } /** * check if there is a cycle in the queries among the non-distinguished * variables * * @return */ protected boolean isCyclic( TransformAlgebra left, TransformAlgebra right ) { CycleAnalysis l = new CycleAnalysis( left.getTriples() ); CycleAnalysis r = new CycleAnalysis( right.getTriples() ); if ( l.isCyclic() || r.isCyclic() ) return true; else { return false; } } /** * check if the left and right-hand side queries * have the same number and type of distinguished * variables. */ protected boolean haveSameDistVar( Query leftQuery, Query rightQuery ) { List <String> rightQueryDistVars = rightQuery.getResultVars(); Collections.sort( rightQueryDistVars ); List <String> leftQueryDistVars = leftQuery.getResultVars(); Collections.sort( leftQueryDistVars ); return !rightQueryDistVars.equals( leftQueryDistVars ); } @Override public boolean entailed(String queryStr1, String queryStr2) { Query q1 = QueryFactory.create(queryStr1); Query q2 = QueryFactory.create(queryStr2); boolean result; try { result = entailed(q1, q2); } catch (ContainmentTestException e) { throw new RuntimeException(e); } return result; } }