001package org.dllearner.utilities; 002 003import com.google.common.collect.Sets; 004import org.apache.jena.query.ParameterizedSparqlString; 005import org.apache.jena.query.QueryExecution; 006import org.dllearner.core.AbstractReasonerComponent; 007import org.dllearner.accuracymethods.AccMethodApproximate; 008import org.dllearner.accuracymethods.AccMethodThreeValued; 009import org.dllearner.learningproblems.ClassLearningProblem; 010import org.dllearner.reasoning.SPARQLReasoner; 011import org.dllearner.utilities.owl.OWLClassExpressionToSPARQLConverter; 012import org.semanticweb.owlapi.model.OWLClassExpression; 013import org.semanticweb.owlapi.model.OWLDataFactory; 014import org.semanticweb.owlapi.model.OWLIndividual; 015import org.semanticweb.owlapi.model.OWLObjectIntersectionOf; 016import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl; 017 018import java.util.Collection; 019import java.util.Set; 020 021/** 022 * Extension of ReasoningUtils for ClassLearningProblem 023 */ 024public class ReasoningUtilsCLP extends ReasoningUtils { 025 final private ClassLearningProblem problem; 026 private OWLDataFactory df = new OWLDataFactoryImpl(); 027 private OWLClassExpressionToSPARQLConverter converter = new OWLClassExpressionToSPARQLConverter(); 028 029 030 /** 031 * @param problem class learning problem 032 * @param reasoner reasoner component 033 */ 034 public ReasoningUtilsCLP(ClassLearningProblem problem, AbstractReasonerComponent reasoner) { 035 super(reasoner); 036 this.problem = problem; 037 } 038 039 /** 040 * specialisation to indicate that calculation needs to be interrupted 041 * @return 042 */ 043 @Override 044 protected boolean interrupted() { 045 return problem.terminationTimeExpired(); 046 } 047 048 /** 049 * get coverage result for class learning problem. currently this is specialised for SPARQL reasoner and uses generic getCoverage otherwise 050 * @param description the description to test 051 * @param classInstances instances of the target class 052 * @param superClassInstances instaces of the superclass 053 * @return array of coverage data 054 */ 055 public Coverage[] getCoverageCLP(OWLClassExpression description, Collection<OWLIndividual> classInstances, 056 Collection<OWLIndividual> superClassInstances) { 057 if (reasoner instanceof SPARQLReasoner) { 058 SPARQLReasoner reasoner2 = (SPARQLReasoner)reasoner; 059 Coverage[] ret = new Coverage[2]; 060 ret[0] = new Coverage(); 061 ret[1] = new Coverage(); 062 063 // R(C) 064 String query = "SELECT (COUNT(DISTINCT ?s) AS ?cnt) WHERE {" 065 + "?s a ?sup . ?classToDescribe <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?sup . " 066 + converter.convert("?s", description) 067 + "FILTER NOT EXISTS {?s a ?classToDescribe}}"; 068 ParameterizedSparqlString template = new ParameterizedSparqlString(query); 069 //System.err.println(converter.convert("?s", description)); 070 //template.setIri("cls", description.asOWLClass().toStringID()); 071 template.setIri("classToDescribe", problem.getClassToDescribe().toStringID()); 072 073 QueryExecution qe = reasoner2.getQueryExecutionFactory().createQueryExecution(template.toString()); 074 ret[1].trueCount = qe.execSelect().next().getLiteral("cnt").getInt(); 075 ret[1].falseCount = superClassInstances.size() - ret[1].trueCount; 076 077 // R(A) 078 OWLObjectIntersectionOf ce = df.getOWLObjectIntersectionOf(problem.getClassToDescribe(), description); 079 ret[0].trueCount = reasoner2.getPopularityOf(ce); 080 ret[0].falseCount = classInstances.size() - ret[0].trueCount; 081 082 return ret; 083 } else { 084 return getCoverage(description, classInstances, superClassInstances); 085 } 086 087 } 088 089 /** 090 * Implementations of accuracy calculation for generalised measures according to method in A Note on the Evaluation of Inductive Concept Classification Procedures 091 * @param accuracyMethod method to use 092 * @param description description to test 093 * @param classInstances class instances. will be converted to set 094 * @param superClassInstances superclass instances. will be converted to set 095 * @param negatedClassInstances negated class instances. will be converted to set 096 * @param noise problem noise 097 * @return accuracy or -1 098 */ 099 public double getAccuracyOrTooWeak3(AccMethodThreeValued accuracyMethod, OWLClassExpression description, Collection<OWLIndividual> classInstances, Collection<OWLIndividual> superClassInstances, Collection<OWLIndividual> negatedClassInstances, double noise) { 100 if (accuracyMethod instanceof AccMethodApproximate) { 101 throw new RuntimeException(); 102 } else { 103 return getAccuracyOrTooWeakExact3(accuracyMethod, description, classInstances, superClassInstances, negatedClassInstances, noise); 104 } 105 } 106 107 /** 108 * @see #getAccuracyOrTooWeak3(AccMethodThreeValued, OWLClassExpression, Collection, Collection, Collection, double) 109 */ 110 public double getAccuracyOrTooWeakExact3(AccMethodThreeValued accuracyMethod, OWLClassExpression description, Collection<OWLIndividual> classInstances, Collection<OWLIndividual> superClassInstances, Collection<OWLIndividual> negatedClassInstances, double noise) { 111 return getAccuracyOrTooWeakExact3(accuracyMethod, description, 112 makeSet(classInstances), makeSet(superClassInstances), makeSet(negatedClassInstances), 113 noise); 114 } 115 116 /** 117 * @see #getAccuracyOrTooWeakExact3(AccMethodThreeValued, OWLClassExpression, Collection, Collection, Collection, double) 118 */ 119 public double getAccuracyOrTooWeakExact3(AccMethodThreeValued accuracyMethod, OWLClassExpression description, Set<OWLIndividual> classInstances, Set<OWLIndividual> superClassInstances, Set<OWLIndividual> negatedClassInstances, double noise) { 120 // implementation is based on: 121 // http://sunsite.informatik.rwth-aachen.de/Publications/CEUR-WS/Vol-426/swap2008_submission_14.pdf 122 // default negation should be turned off when using fast instance checker 123 // compute I_C (negated and non-negated concepts separately) 124 ReasoningUtils.Coverage3[] cc = getCoverage3(description, df.getOWLObjectComplementOf(description), Sets.union(classInstances, superClassInstances)); 125 // trueSet = icPos, falseSet = icNeg 126 if (cc == null) { // timeout 127 return 0; 128 } 129 // semantic precision 130 // first compute I_C \cap Cn(DC) 131 // it seems that in our setting, we can ignore Cn, because the examples (class instances) 132 // are already part of the background knowledge 133 Set<OWLIndividual> tmp1Pos = Sets.intersection(cc[0].trueSet, classInstances); 134 Set<OWLIndividual> tmp1Neg = Sets.intersection(cc[0].falseSet, negatedClassInstances); 135 // icPos + icNeg <===> all returned results 136 // --> precision = tmp1size / (icpos + icneg) 137 // classInstances + negatedClassInstances <==> all results that should be returned 138 // -> recall = tmp1size / (cI + ncI) 139 140 // F_beta = true positives / (true positives + false negatives + false positives) 141 142 // Cn(I_C) \cap D_C is the same set if we ignore Cn ... 143 // ---> @@@@ AccMethodGenFMeasure 144 return accuracyMethod.getAccOrTooWeak3(tmp1Pos.size(), tmp1Neg.size(), cc[0].trueCount, cc[0].falseCount, classInstances.size(), negatedClassInstances.size(), noise); 145 } 146}