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.kb.sparql; 020 021import java.net.URI; 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.List; 025import java.util.Random; 026import java.util.Set; 027import java.util.TreeSet; 028import java.util.stream.Collectors; 029 030import org.dllearner.algorithms.el.ELLearningAlgorithm; 031import org.dllearner.core.StringRenderer; 032import org.dllearner.kb.OWLAPIOntology; 033import org.dllearner.kb.OWLOntologyKnowledgeSource; 034import org.dllearner.kb.SparqlEndpointKS; 035import org.dllearner.learningproblems.ClassLearningProblem; 036import org.dllearner.reasoning.ClosedWorldReasoner; 037import org.dllearner.reasoning.OWLAPIReasoner; 038import org.dllearner.reasoning.ReasonerImplementation; 039import org.dllearner.utilities.examples.AutomaticNegativeExampleFinderSPARQL2; 040import org.mindswap.pellet.PelletOptions; 041import org.openrdf.model.vocabulary.RDF; 042import org.semanticweb.owlapi.apibinding.OWLManager; 043import org.semanticweb.owlapi.model.*; 044 045import org.semanticweb.owlapi.owlxml.renderer.OWLXMLObjectRenderer; 046import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl; 047import uk.ac.manchester.cs.owl.owlapi.OWLNamedIndividualImpl; 048 049import com.google.common.collect.Sets; 050import org.apache.jena.query.QueryExecution; 051import org.apache.jena.query.QuerySolution; 052import org.apache.jena.query.ResultSet; 053 054/** 055 * Computes a sample fragment of the knowledge base given an OWL class. 056 * @author Lorenz Buehmann 057 * 058 */ 059public class ClassBasedSampleGenerator extends InstanceBasedSampleGenerator{ 060 061 private Random rnd = new Random(12345); 062 063 private int maxNrOfPosExamples = 20; 064 private int maxNrOfNegExamples = 20; 065 066 private boolean useNegExamples = true; 067 068 private AutomaticNegativeExampleFinderSPARQL2 negExamplesFinder; 069 070 private Set<OWLIndividual> posExamples; 071 private Set<OWLIndividual> negExamples; 072 073 public ClassBasedSampleGenerator(SparqlEndpointKS ks) { 074 super(ks); 075 076 negExamplesFinder = new AutomaticNegativeExampleFinderSPARQL2(qef); 077 } 078 079 /** 080 * Computes a sample fragment of the knowledge base by using instances of the 081 * given OWL class and also, if enabled, use some instances that do not belong to the class. 082 * @param cls the OWL class 083 * @return a sample fragment 084 */ 085 public OWLOntology getSample(OWLClass cls) { 086 // get positive examples 087 posExamples = computePosExamples(cls); 088 089 // get negative examples if enabled 090 negExamples = computeNegExamples(cls, posExamples); 091 092 // compute sample based on positive (and negative) examples 093 return getSample(Sets.union(posExamples, negExamples)); 094 } 095 096 /** 097 * @param maxNrOfPosExamples the max. number of pos. examples used for sampling 098 */ 099 public void setMaxNrOfPosExamples(int maxNrOfPosExamples) { 100 this.maxNrOfPosExamples = maxNrOfPosExamples; 101 } 102 103 /** 104 * @param maxNrOfNegExamples the max. number of neg. examples used for sampling 105 */ 106 public void setMaxNrOfNegExamples(int maxNrOfNegExamples) { 107 this.maxNrOfNegExamples = maxNrOfNegExamples; 108 } 109 110 /** 111 * @param useNegExamples whether to use negative examples or not 112 */ 113 public void setUseNegExamples(boolean useNegExamples) { 114 this.useNegExamples = useNegExamples; 115 } 116 117 /** 118 * @return the positive examples, i.e. instances of the class used to 119 * generate the sample 120 */ 121 public Set<OWLIndividual> getPositiveExamples() { 122 return posExamples; 123 } 124 125 /** 126 * @return the negative examples, i.e. individuals that do not belong to the class and are used to 127 * generate the sample 128 */ 129 public Set<OWLIndividual> getNegativeExamples() { 130 return negExamples; 131 } 132 133 /** 134 * The examples for the sample are chosen randomly, thus, the seed for shuffling can be set here. 135 * @see Random#setSeed(long) 136 * @param seed the seed 137 */ 138 public void setSeed(long seed) { 139 rnd.setSeed(seed); 140 } 141 142 private Set<OWLIndividual> computePosExamples(OWLClass cls) { 143 List<OWLIndividual> posExamples = new ArrayList<>(); 144 145 String query = String.format("SELECT ?s WHERE {?s a <%s>}", cls.toStringID()); 146 147 try(QueryExecution qe = qef.createQueryExecution(query)) { 148 ResultSet rs = qe.execSelect(); 149 while(rs.hasNext()) { 150 QuerySolution qs = rs.next(); 151 posExamples.add(new OWLNamedIndividualImpl(IRI.create(qs.getResource("s").getURI()))); 152 } 153 } 154 155 Collections.shuffle(posExamples, rnd); 156 157 return new TreeSet<>(posExamples.subList(0, Math.min(posExamples.size(), maxNrOfPosExamples))); 158 } 159 160 private Set<OWLIndividual> computeNegExamples(OWLClass cls, Set<OWLIndividual> posExamples) { 161 Set<OWLIndividual> negExamples = new TreeSet<>(); 162 163 if(useNegExamples && maxNrOfPosExamples > 0) { 164 negExamples = negExamplesFinder.getNegativeExamples(cls, posExamples, maxNrOfNegExamples); 165 } 166 167 return negExamples; 168 } 169 170 public static void main(String[] args) throws Exception{ 171 StringRenderer.setRenderer(StringRenderer.Rendering.DL_SYNTAX); 172 173 SparqlEndpoint endpoint = SparqlEndpoint.create("http://dbpedia.org/sparql", "http://dbpedia.org"); 174 SparqlEndpointKS ks = new SparqlEndpointKS(endpoint); 175 ks.setUseCache(false); 176 ks.setRetryCount(0); 177 ks.init(); 178 OWLOntologyManager man = OWLManager.createOWLOntologyManager(); 179// OWLOntology schema = man.createOntology();//man.loadOntology(IRI.create("http://downloads.dbpedia.org/2016-10/dbpedia_2016-10.nt")); 180 OWLOntology schema = man.loadOntology(IRI.create("http://downloads.dbpedia.org/2016-10/dbpedia_2016-10.nt")); 181 182 ClassBasedSampleGenerator sampleGenerator = new ClassBasedSampleGenerator(ks); 183 sampleGenerator.setUseNegExamples(false); 184 sampleGenerator.setSampleDepth(2); 185 sampleGenerator.addAllowedPropertyNamespaces(Sets.newHashSet("http://dbpedia.org/ontology/")); 186 sampleGenerator.addAllowedObjectNamespaces(Sets.newHashSet("http://dbpedia.org/ontology/", "http://dbpedia.org/resource/")); 187 188 PelletOptions.INVALID_LITERAL_AS_INCONSISTENCY = false; 189 OWLClass cls = new OWLClassImpl(IRI.create("http://dbpedia.org/ontology/Book")); 190 191 // generate a class based sample 192 OWLOntology sample = sampleGenerator.getSample(cls); 193 man.addAxioms(sample, schema.getLogicalAxioms()); 194 195 Set<String> ignoredProperties = Sets.newHashSet( 196 "http://dbpedia.org/ontology/abstract","http://dbpedia.org/ontology/birthName", 197 "http://dbpedia.org/ontology/wikiPageID", 198 "http://dbpedia.org/ontology/wikiPageRevisionID", 199 "http://dbpedia.org/ontology/wikiPageID"); 200 OWLOntology ont = man.createOntology(schema.getAxioms()); 201 man.addAxioms(ont, sample.getLogicalAxioms().stream().filter(ax -> { 202 if(ax.getAxiomType() == AxiomType.OBJECT_PROPERTY_ASSERTION) { 203 return true; 204 } else if(ax.getAxiomType() == AxiomType.DATA_PROPERTY_ASSERTION) { 205 return !ignoredProperties.contains(((OWLDataPropertyAssertionAxiom)ax).getProperty().asOWLDataProperty().toStringID()); 206 } 207 return true; 208 }).collect(Collectors.toSet())); 209 210// System.out.println("|Sample|=" + sample.getLogicalAxiomCount()); 211// sample.getLogicalAxioms().forEach(System.out::println); 212 213 OWLOntologyKnowledgeSource sampleKS = new OWLAPIOntology(ont); 214 sampleKS.init(); 215 216 OWLAPIReasoner baseReasoner = new OWLAPIReasoner(sampleKS); 217 baseReasoner.setReasonerImplementation(ReasonerImplementation.STRUCTURAL); 218 baseReasoner.init(); 219 220 ClosedWorldReasoner reasoner = new ClosedWorldReasoner(baseReasoner); 221// reasoner.setReasonerComponent(baseReasoner); 222 reasoner.init(); 223 224 ClassLearningProblem lp = new ClassLearningProblem(reasoner); 225 lp.setClassToDescribe(cls); 226 lp.setEquivalence(false); 227 lp.setCheckConsistency(false); 228 lp.init(); 229 230 ELLearningAlgorithm la = new ELLearningAlgorithm(lp, reasoner); 231 la.setClassToDescribe(cls); 232 la.setNoisePercentage(90); 233 la.setMaxNrOfResults(50); 234 la.setMaxExecutionTimeInSeconds(10); 235// la.setStartClass(cls); 236 la.init(); 237 238 la.start(); 239 } 240}