Skip to content

Commit

Permalink
Added an more in-depth check whether FILTER NOT EXISTS statements mig…
Browse files Browse the repository at this point in the history
…ht be nested and, hence, shouldn't be created.
  • Loading branch information
MichaelRoeder committed Oct 2, 2024
1 parent 2faae5b commit 4e903ba
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 26 deletions.
52 changes: 29 additions & 23 deletions src/main/java/org/dice_research/cel/PruneCEL.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import org.dice_research.cel.refine.suggest.ExtendedSuggestor;
import org.dice_research.cel.refine.suggest.SelectionScores;
import org.dice_research.cel.refine.suggest.sparql.SparqlBasedSuggestor;
import org.dice_research.cel.score.AccuracyCalculator;
import org.dice_research.cel.score.AvoidingPickySolutionsDecorator;
import org.dice_research.cel.score.BalancedAccuracyCalculator;
import org.dice_research.cel.score.LengthBasedRefinementScorer;
import org.dice_research.cel.score.ScoreCalculator;
import org.dice_research.cel.score.ScoreCalculatorFactory;
Expand Down Expand Up @@ -82,7 +82,7 @@ public List<ScoredClassExpression> findClassExpression(Collection<String> positi
if (iResultPrinter != null) {
iResultPrinter.setStartTime(startTime);
}
long timeToStop = maxTime > 0 ? startTime + maxTime : 0;
long timeToStop = maxTime > 0 ? startTime + maxTime : 0;
return findClassExpression(positive, negative, logStream, iResultPrinter, startTime, timeToStop);
}

Expand Down Expand Up @@ -235,14 +235,17 @@ public static void main(String[] args) throws Exception {
// String endpoint = "http://localhost:9080/sparql";
// String endpoint = "http://localhost:3030/exp-bench/sparql";
// String endpoint = "http://localhost:3030/family/sparql";
String endpoint = "http://dice-quan.cs.uni-paderborn.de:9050/sparql";
// String endpoint = "http://dice-quan.cs.uni-paderborn.de:9050/sparql";
// QALD9-plus-wikidata
String endpoint = "http://dice-quan.cs.uni-paderborn.de:9070/sparql";
// XXX Set description logic
DescriptionLogic logic = DescriptionLogic.parse("ALC");

ScoreCalculatorFactory factory = null;
// XXX Choose either F1 or balanced accuracy
// factory = new F1MeasureCalculator.Factory();
factory = new BalancedAccuracyCalculator.Factory();
//factory = new BalancedAccuracyCalculator.Factory();
factory = new AccuracyCalculator.Factory();

// Punish long expressions
factory = new LengthBasedRefinementScorer.Factory(factory);
Expand All @@ -267,7 +270,7 @@ public static void main(String[] args) throws Exception {
// XXX Max iterations of the refinement
// cel.setMaxIterations(1000);
// XXX Maximum time (in ms)
cel.setMaxTime(60000);
cel.setMaxTime(600000);
// XXX (Optional) try to avoid refining expressions that have not been created
// in a promising way (i.e., just added a class to an existing expression
// without changing the accuracy of the expression)
Expand All @@ -279,8 +282,10 @@ public static void main(String[] args) throws Exception {
// XXX Choose the learning problem (as JSON file)
JSONLearningProblemReader reader = new JSONLearningProblemReader();
// Collection<LearningProblem> problems = reader.readProblems("LPs/Family/lps.json");
//Collection<LearningProblem> problems = reader.readProblems("/home/micha/Downloads/TandF_MST5_reverse.json");
Collection<LearningProblem> problems = reader.readProblems("/home/micha/Downloads/TandF_MST5.json");
// Collection<LearningProblem> problems = reader.readProblems("/home/micha/Downloads/TandF_MST5_reverse.json");
//Collection<LearningProblem> problems = reader.readProblems("/home/micha/Downloads/TandF_MST5.json");
Collection<LearningProblem> problems = reader.readProblems("/home/micha/Downloads/TandF_deeppavlov_reverse.json");
//Collection<LearningProblem> problems = reader.readProblems("/home/micha/Downloads/TandF_ganswer_reverse.json");
// Collection<LearningProblem> problems =
// reader.readProblems("LPs/QA/TandF_MST5_reverse.json");

Expand All @@ -289,9 +294,15 @@ public static void main(String[] args) throws Exception {
// ClassExpression ce = new SimpleQuantifiedRole(false, "http://w3id.org/dice-research/qa-bench#hasNlpParseTreeRoot", false,
// new Junction(false, Suggestor.CONTEXT_POSITION_MARKER, new SimpleQuantifiedRole(false, "https://nlp.stanford.edu/nlp#obj", false,
// NamedClass.BOTTOM)));
// ce = new Junction(true,
//// new SimpleQuantifiedRole(false, "http://w3id.org/dice-research/qa-bench#hasLiteralAnswer", false,
//// NamedClass.BOTTOM),
// ce = new Junction(false,
// new SimpleQuantifiedRole(false, "http://w3id.org/dice-research/qa-bench#hasQuestionWord", false,
// NamedClass.BOTTOM),
// new Junction(true,
// new SimpleQuantifiedRole(false, "http://w3id.org/dice-research/qa-bench#hasLiteralAnswer", false,
// NamedClass.BOTTOM),
// new SimpleQuantifiedRole(false, "http://w3id.org/dice-research/qa-bench#hasIRIAnswer", false,
// NamedClass.BOTTOM)
// ),Suggestor.CONTEXT_POSITION_MARKER);
// new SimpleQuantifiedRole(true, "http://w3id.org/dice-research/qa-bench#hasQuestionWord", false,
// NamedClass.TOP),
// new SimpleQuantifiedRole(true, "http://w3id.org/dice-research/qa-bench#hasQuery", false,
Expand All @@ -305,20 +316,15 @@ public static void main(String[] args) throws Exception {
// NamedClass.TOP),
// new NamedClass("http://www.w3.org/2004/02/skos/core#Concept"),
// new NamedClass("http://dbpedia.org/ontology/Agent"))))));
// ⊓
// ∃.∃.(
// http://dbpedia.org/ontology/Company
// ⊔
// http://dbpedia.org/ontology/Location
// ⊔
// http://dbpedia.org/ontology/MusicGenre
// ⊔
// (∃http://xmlns.com/foaf/0.1/name.⊤⊓http://www.w3.org/2004/02/skos/core#Concept⊓http://dbpedia.org/ontology/Agent)
// ⊔
// http://dbpedia.org/ontology/Currency
// )
// ∀http://w3id.org/dice-research/qa-bench#hasQuestionWord.⊥
// ⊔
// (
// ∀http://w3id.org/dice-research/qa-bench#hasLiteralAnswer.⊥
// ⊓
// ∀http://w3id.org/dice-research/qa-bench#hasIRIAnswer.⊥
// )
// LearningProblem prob = problems.iterator().next();
// System.out.println(suggestor.suggestProperty(prob.getPositiveExamples(), prob.getNegativeExamples(), ce));
// System.out.println(suggestor.suggestClass(prob.getPositiveExamples(), prob.getNegativeExamples(), ce));
// System.out.println(suggestor.scoreExpression(ce, prob.getPositiveExamples(), prob.getNegativeExamples()));
// System.out.println(ce);
// ce = (new NegatingVisitor()).negateExpression(ce);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.dice_research.cel.refine.suggest.sparql;

import org.dice_research.cel.expression.ClassExpression;
import org.dice_research.cel.expression.ClassExpressionVisitingCreator;
import org.dice_research.cel.expression.Junction;
import org.dice_research.cel.expression.NamedClass;
import org.dice_research.cel.expression.SimpleQuantifiedRole;

/**
* This class is a visitor that returns {@code true} if the given class
* expression should not be put into a {@code FILTER NOT EXISTS} (FNE) statement
* since the statement itself will consist of one (or several) FNE statements.
* Instead, such an expression should be simply negated.
*
* For example, trying to add an FNE statement with the expression ∀r.⊥ leads to
* an FNE statement within an FNE, without any additional triple pattern in the
* outer filter. That means that the variables within the filter and outside of
* the filter are not connected, anymore. Hence, it is easier to add ∃r.⊤
* instead. The same holds for negated, named classes (¬A) or a conjunction of
* these two types of statements.
*
* Note that the given statement should already have been preprocessed for being
* transformed into a SPARQL query.
*
* @author Michael R&ouml;der ([email protected])
*
*/
public class FilterNotExistsChecker implements ClassExpressionVisitingCreator<Boolean> {

@Override
public Boolean visitNamedClass(NamedClass node) {
return node.isNegated();
}

@Override
public Boolean visitJunction(Junction node) {
for (ClassExpression child : node.getChildren()) {
if (!child.accept(this)) {
return Boolean.FALSE;
}
}
return Boolean.TRUE;
}

@Override
public Boolean visitSimpleQuantificationRole(SimpleQuantifiedRole node) {
return !node.isExists();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class SparqlBuildingVisitor implements ClassExpressionVisitor {
protected Function<String, String> variableToStmtOnMarkedPosition;
protected NegatingVisitor negator = new NegatingVisitor();
protected DisjunctionCheckingVisitor checker = new DisjunctionCheckingVisitor();
protected FilterNotExistsChecker fneChecker = new FilterNotExistsChecker();
protected ExpressionPreProcessor preprocessor = new ExpressionPreProcessor();

/**
Expand Down Expand Up @@ -206,9 +207,7 @@ public void visitNotExistsFilter(ClassExpression filterExpression) {
isRoot = false;
for (ClassExpression expression : expressions) {
// If this is an expression would create a FILTER NON EXISTS statement
if (((expression instanceof NamedClass) && (((NamedClass) expression).isNegated()))
|| ((expression instanceof SimpleQuantifiedRole)
&& (!((SimpleQuantifiedRole) expression).isExists()))) {
if (expression.accept(fneChecker)) {
// Simply negate the statement and add it
ClassExpression negated = negator.negateExpression(expression);
negated = preprocessor.preprocess(negated);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.dice_research.cel.refine.suggest.sparql;

import java.util.ArrayList;
import java.util.List;

import org.dice_research.cel.expression.ClassExpression;
import org.dice_research.cel.expression.Junction;
import org.dice_research.cel.expression.NamedClass;
import org.dice_research.cel.expression.SimpleQuantifiedRole;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class FilterNotExistsCheckerTest {

private ClassExpression givenExpression;
private Boolean expectedResult;

public FilterNotExistsCheckerTest(ClassExpression givenExpression, Boolean expectedResult) {
super();
this.givenExpression = givenExpression;
this.expectedResult = expectedResult;
}

@Test
public void test() {
FilterNotExistsChecker checker = new FilterNotExistsChecker();
if (expectedResult) {
Assert.assertTrue(givenExpression.accept(checker));
} else {
Assert.assertFalse(givenExpression.accept(checker));
}
}

@Parameters
public static List<Object[]> parameters() {
List<Object[]> testCases = new ArrayList<>();

testCases.add(new Object[] { new NamedClass("A"), Boolean.FALSE });
testCases.add(new Object[] { new NamedClass("A", true), Boolean.TRUE });
testCases.add(new Object[] { new SimpleQuantifiedRole(true, "r", false, new NamedClass("A")), Boolean.FALSE });
testCases.add(new Object[] { new SimpleQuantifiedRole(false, "r", false, new NamedClass("A")), Boolean.TRUE });

testCases.add(new Object[] { new Junction(true, new NamedClass("A"), new NamedClass("B")), Boolean.FALSE });
testCases.add(
new Object[] { new Junction(true, new NamedClass("A", true), new NamedClass("B")), Boolean.FALSE });
testCases.add(
new Object[] { new Junction(true, new NamedClass("A"), new NamedClass("B", true)), Boolean.FALSE });
testCases.add(new Object[] { new Junction(true, new NamedClass("A", true), new NamedClass("B", true)),
Boolean.TRUE });
testCases
.add(new Object[] {
new Junction(true, new NamedClass("A", true),
new Junction(true, new NamedClass("B", true),
new SimpleQuantifiedRole(false, "r", false, new NamedClass("A")))),
Boolean.TRUE });

return testCases;
}

}

0 comments on commit 4e903ba

Please sign in to comment.