001/** 002 * Copyright (C) 2007 - 2016, Jens Lehmann 003 * 004 * This file is part of DL-Learner. 005 * 006 * DL-Learner is free software; you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation; either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * DL-Learner is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.dllearner.algorithms.pattern; 020 021import com.google.common.collect.HashMultiset; 022import com.google.common.collect.Multiset; 023import org.apache.jena.query.*; 024import org.apache.jena.rdf.model.Model; 025import org.apache.jena.rdf.model.ModelFactory; 026import org.apache.jena.rdf.model.Resource; 027import org.apache.jena.vocabulary.RDF; 028import org.dllearner.core.AbstractAxiomLearningAlgorithm; 029import org.dllearner.core.ComponentAnn; 030import org.dllearner.core.Score; 031import org.dllearner.kb.SparqlEndpointKS; 032import org.dllearner.kb.sparql.SparqlEndpoint; 033import org.dllearner.utilities.owl.OWLClassExpressionToSPARQLConverter; 034import org.semanticweb.owlapi.model.*; 035import org.semanticweb.owlapi.util.DefaultPrefixManager; 036import org.semanticweb.owlapi.util.OWLObjectDuplicator; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl; 040 041import java.io.ByteArrayInputStream; 042import java.io.InputStream; 043import java.util.*; 044import java.util.Map.Entry; 045import java.util.concurrent.TimeUnit; 046 047/** 048 * @author Lorenz Buehmann 049 * 050 */ 051@ComponentAnn(name = "pattern-based learner", shortName = "patla", version = 0.1, description = "Pattern-based algorithm uses OWL axioms as pattern.") 052public class PatternBasedAxiomLearningAlgorithm extends AbstractAxiomLearningAlgorithm<OWLAxiom, OWLObject, OWLEntity>{ 053 054 private static final Logger logger = LoggerFactory.getLogger(PatternBasedAxiomLearningAlgorithm.class); 055 056 057 private OWLAxiom pattern; 058 private OWLClass cls; 059 060 private FragmentExtractor fragmentExtractor; 061 private OWLClassExpressionToSPARQLConverter converter = new OWLClassExpressionToSPARQLConverter(); 062 private OWLDataFactory dataFactory = new OWLDataFactoryImpl(); 063 064 private OWLAnnotationProperty confidenceProperty = dataFactory.getOWLAnnotationProperty(IRI.create("http://dl-learner.org/pattern/confidence")); 065 066 private double threshold = 0.4; 067 068 public PatternBasedAxiomLearningAlgorithm(SparqlEndpointKS ks, FragmentExtractionStrategy extractionStrategy) { 069 this.ks = ks; 070 071 if(extractionStrategy == FragmentExtractionStrategy.TIME){ 072 fragmentExtractor = new TimeBasedFragmentExtractor(ks, 20, TimeUnit.SECONDS); 073 } else if(extractionStrategy == FragmentExtractionStrategy.INDIVIDUALS){ 074 fragmentExtractor = new IndividualBasedFragmentExtractor(ks, 20); 075 } 076 } 077 078 public PatternBasedAxiomLearningAlgorithm(SparqlEndpointKS ks, String cacheDir, FragmentExtractionStrategy extractionStrategy) { 079 080 } 081 082 /** 083 * @param pattern the pattern to set 084 */ 085 public void setPattern(OWLAxiom pattern) { 086 this.pattern = pattern; 087 } 088 089 /** 090 * @param cls the cls to set 091 */ 092 public void setClass(OWLClass cls) { 093 this.cls = cls; 094 } 095 096 /* (non-Javadoc) 097 * @see org.dllearner.core.AbstractAxiomLearningAlgorithm#getExistingAxioms() 098 */ 099 @Override 100 protected void getExistingAxioms() { 101 } 102 103 /* (non-Javadoc) 104 * @see org.dllearner.core.AbstractAxiomLearningAlgorithm#getSampleQuery() 105 */ 106 @Override 107 protected ParameterizedSparqlString getSampleQuery() { 108 return null; 109 } 110 111 /* (non-Javadoc) 112 * @see org.dllearner.core.AbstractAxiomLearningAlgorithm#learnAxioms() 113 */ 114 @Override 115 protected void learnAxioms() { 116 logger.info("Pattern: " + pattern); 117 118 //get the maximum modal depth in the pattern axioms 119 int modalDepth = MaximumModalDepthDetector.getMaxModalDepth(pattern);modalDepth++; 120 logger.info("Modal depth: " + modalDepth); 121 122 //extract fragment 123 Model fragment = fragmentExtractor.extractFragment(cls, modalDepth); 124 125 //try to find instantiation of the pattern with confidence above threshold 126 Set<OWLAxiom> instantiations = applyPattern(pattern, dataFactory.getOWLClass(IRI.create(cls.toStringID())), fragment); 127 for (OWLAxiom instantiation : instantiations) { 128 System.out.println(instantiation); 129 } 130 } 131 132 private Set<OWLAxiom> applyPattern(OWLAxiom pattern, OWLClass cls, Model fragment) { 133 Map<OWLAxiom, Score> axioms2Score = new HashMap<>(); 134 135 OWLClassExpression patternSubClass = null; 136 OWLClassExpression patternSuperClass = null; 137 138 if(pattern.isOfType(AxiomType.EQUIVALENT_CLASSES)){ 139 Set<OWLSubClassOfAxiom> subClassOfAxioms = ((OWLEquivalentClassesAxiom)pattern).asOWLSubClassOfAxioms(); 140 for (OWLSubClassOfAxiom axiom : subClassOfAxioms) { 141 if(!axiom.getSubClass().isAnonymous()){ 142 patternSubClass = axiom.getSubClass(); 143 patternSuperClass = axiom.getSuperClass(); 144 break; 145 } 146 } 147 } else if(pattern.isOfType(AxiomType.SUBCLASS_OF)){ 148 patternSubClass = ((OWLSubClassOfAxiom) pattern).getSubClass(); 149 patternSuperClass = ((OWLSubClassOfAxiom) pattern).getSuperClass(); 150 } else { 151 logger.warn("Pattern " + pattern + " not supported yet."); 152 return Collections.emptySet(); 153 } 154 155 Set<OWLEntity> signature = patternSuperClass.getSignature(); 156 signature.remove(patternSubClass.asOWLClass()); 157 Query query = converter.asQuery("?x", dataFactory.getOWLObjectIntersectionOf(cls, patternSuperClass), signature); 158 logger.info("Running query\n" + query); 159 Map<OWLEntity, String> variablesMapping = converter.getVariablesMapping(); 160 org.apache.jena.query.ResultSet rs = QueryExecutionFactory.create(query, fragment).execSelect(); 161 QuerySolution qs; 162 Set<String> resources = new HashSet<>(); 163 Multiset<OWLAxiom> instantiations = HashMultiset.create(); 164 while (rs.hasNext()) { 165 qs = rs.next(); 166 resources.add(qs.getResource("x").getURI()); 167 // get the IRIs for each variable 168 Map<OWLEntity, IRI> entity2IRIMap = new HashMap<>(); 169 entity2IRIMap.put(patternSubClass.asOWLClass(), cls.getIRI()); 170 boolean skip = false; 171 for (OWLEntity entity : signature) { 172 String var = variablesMapping.get(entity); 173 if(qs.get(var) == null){ 174 logger.warn("Variable " + var + " is not bound."); 175 skip = true; 176 break; 177 } 178 if(qs.get(var).isLiteral()){ 179 skip = true; 180 break; 181 } 182 Resource resource = qs.getResource(var); 183 if(entity.isOWLObjectProperty() && resource.hasURI(RDF.type.getURI())){ 184 skip = true; 185 break; 186 } 187 entity2IRIMap.put(entity, IRI.create(resource.getURI())); 188 } 189 if(!skip){ 190 // instantiate the pattern 191 OWLObjectDuplicator duplicator = new OWLObjectDuplicator(entity2IRIMap, dataFactory); 192 OWLAxiom patternInstantiation = duplicator.duplicateObject(pattern); 193 instantiations.add(patternInstantiation); 194 } 195 } 196 // compute the score 197 int total = resources.size(); 198 for (OWLAxiom axiom : instantiations.elementSet()) { 199 int frequency = instantiations.count(axiom); 200// System.out.println(axiom + ":" + frequency); 201 Score score = computeScore(total, Math.min(total, frequency)); 202 axioms2Score.put(axiom, score); 203 } 204 205 return asAnnotatedAxioms(axioms2Score); 206 } 207 208 private Set<OWLAxiom> asAnnotatedAxioms(Map<OWLAxiom, Score> axioms2Score){ 209 Set<OWLAxiom> annotatedAxioms = new HashSet<>(); 210 for (Entry<OWLAxiom, Score> entry : axioms2Score.entrySet()) { 211 OWLAxiom axiom = entry.getKey(); 212 Score score = entry.getValue(); 213 if(score.getAccuracy() >= threshold){ 214 annotatedAxioms.add(axiom.getAnnotatedAxiom( 215 Collections.singleton(dataFactory.getOWLAnnotation(confidenceProperty, dataFactory.getOWLLiteral(score.getAccuracy()))))); 216 217 } 218 } 219 return annotatedAxioms; 220 } 221 222 public static void main(String[] args) throws Exception { 223 OWLDataFactoryImpl df = new OWLDataFactoryImpl(); 224 PrefixManager pm = new DefaultPrefixManager(); 225 pm.setDefaultPrefix("http://dllearner.org/pattern#"); 226 227 Model model = ModelFactory.createDefaultModel(); 228 String triples = 229 "<http://ex.org/a> a <http://ex.org/A>."+ 230 "<http://ex.org/a> <http://ex.org/p> <http://ex.org/y1>."+ 231 "<http://ex.org/y1> a <http://ex.org/B>."+ 232 233 "<http://ex.org/b> a <http://ex.org/A>."+ 234 "<http://ex.org/b> <http://ex.org/p> <http://ex.org/y2>."+ 235 "<http://ex.org/y2> a <http://ex.org/B>."+ 236 237 "<http://ex.org/c> a <http://ex.org/A>." 238 ; 239 InputStream is = new ByteArrayInputStream( triples.getBytes("UTF-8")); 240 model.read(is, null, "TURTLE"); 241 242 String query = "SELECT DISTINCT ?x WHERE { " 243 + "?x a <http://ex.org/A> .}"; 244 245 ResultSet rs = QueryExecutionFactory.create(query, model).execSelect(); 246 System.out.println(ResultSetFormatter.asText(rs)); 247 248 query = "SELECT DISTINCT ?p0 ?cls0 ?x WHERE { " 249 + "?x a <http://ex.org/A> ." 250 + "?x ?p0 ?s0 " 251 + " { SELECT ?x ?p0 ?cls0 (count(?s1) AS ?cnt1)" 252 + " WHERE" 253 + " { ?x ?p0 ?s1 ." 254 + " ?s1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?cls0" 255 + " }" 256 + " GROUP BY ?x ?cls0 ?p0" 257 + " }" 258 + " { SELECT ?x ?p0 (count(?s2) AS ?cnt2)" 259 + " WHERE" 260 + " { ?x ?p0 ?s2 }" 261 + " GROUP BY ?x ?p0" 262 + " }" 263 + " FILTER ( ?cnt1 = ?cnt2 ) }"; 264 265 query = "SELECT ?x WHERE {?x a <http://ex.org/A>. FILTER NOT EXISTS{?x <http://ex.org/p> ?s1. FILTER NOT EXISTS{?s1 a <http://ex.org/B>.}}} "; 266 267 rs = QueryExecutionFactory.create(query, model).execSelect(); 268 System.out.println(ResultSetFormatter.asText(rs)); 269 270 SparqlEndpoint endpoint = SparqlEndpoint.getEndpointDBpedia(); 271// endpoint = SparqlEndpoint.getEndpointDBpediaLOD2Cloud(); 272// endpoint = SparqlEndpoint.getEndpointDBpediaLiveAKSW(); 273 OWLClass cls = df.getOWLClass(IRI.create("http://dbpedia.org/ontology/SoccerPlayer")); 274 OWLAxiom pattern = df.getOWLSubClassOfAxiom(df.getOWLClass("A", pm), 275 df.getOWLObjectAllValuesFrom(df.getOWLObjectProperty("p", pm), df.getOWLClass("B", pm))); 276 277 PatternBasedAxiomLearningAlgorithm la = new PatternBasedAxiomLearningAlgorithm(new SparqlEndpointKS(endpoint), "cache", FragmentExtractionStrategy.INDIVIDUALS); 278 la.setClass(cls); 279 la.setPattern(pattern); 280 la.start(); 281 } 282}