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.core; 020 021import org.aksw.jena_sparql_api.core.QueryExecutionFactory; 022import org.aksw.jena_sparql_api.model.QueryExecutionFactoryModel; 023import org.apache.jena.ontology.OntClass; 024import org.apache.jena.query.ParameterizedSparqlString; 025import org.apache.jena.query.Query; 026import org.apache.jena.query.QueryExecution; 027import org.apache.jena.query.ResultSet; 028import org.apache.jena.rdf.model.Literal; 029import org.apache.jena.rdf.model.Model; 030import org.apache.jena.rdf.model.ModelFactory; 031import org.apache.jena.rdf.model.RDFNode; 032import org.apache.jena.sparql.engine.http.QueryExceptionHTTP; 033import org.apache.jena.sparql.resultset.ResultSetMem; 034import org.apache.jena.vocabulary.OWL2; 035import org.apache.jena.vocabulary.RDF; 036import org.apache.jena.vocabulary.RDFS; 037import org.dllearner.algorithms.properties.ObjectPropertyCharacteristicsAxiomLearner; 038import org.dllearner.core.annotations.NoConfigOption; 039import org.dllearner.core.annotations.Unused; 040import org.dllearner.core.config.ConfigOption; 041import org.dllearner.core.owl.ClassHierarchy; 042import org.dllearner.kb.LocalModelBasedSparqlEndpointKS; 043import org.dllearner.kb.SparqlEndpointKS; 044import org.dllearner.kb.sparql.SPARQLTasks; 045import org.dllearner.learningproblems.AxiomScore; 046import org.dllearner.learningproblems.Heuristics; 047import org.dllearner.reasoning.SPARQLReasoner; 048import org.dllearner.utilities.OWLAPIUtils; 049import org.semanticweb.owlapi.model.*; 050import org.slf4j.Logger; 051import org.slf4j.LoggerFactory; 052import org.springframework.beans.factory.annotation.Autowired; 053import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl; 054 055import java.math.RoundingMode; 056import java.net.SocketTimeoutException; 057import java.text.DecimalFormat; 058import java.text.NumberFormat; 059import java.util.*; 060import java.util.Map.Entry; 061import java.util.function.Predicate; 062import java.util.stream.Collectors; 063 064//import org.apache.jena.util.iterator.Filter; 065 066/** 067 * @author Lorenz Bühmann 068 * @author Jens Lehmann 069 */ 070public abstract class AbstractAxiomLearningAlgorithm<T extends OWLAxiom, S extends OWLObject, E extends OWLEntity> extends AbstractComponent implements AxiomLearningAlgorithm<T>{ 071 072 @Unused 073 protected LearningProblem learningProblem; 074 protected final Logger logger; 075 076 protected NumberFormat format = DecimalFormat.getPercentInstance(Locale.ROOT); 077 078 @ConfigOption(defaultValue="10", description="maximum execution of the algorithm in seconds (abstract)") 079 protected int maxExecutionTimeInSeconds = 10; 080 @ConfigOption(defaultValue="false", description="omit axioms already existing in the knowledge base") 081 protected boolean returnOnlyNewAxioms; 082 @ConfigOption(description="The maximum number of rows fetched from the endpoint to approximate the result.") 083 protected int maxFetchedRows; 084 085 @ConfigOption(description = "the sparql endpoint knowledge source") 086 protected SparqlEndpointKS ks; 087 088 // the instances which are set 089 private SPARQLReasoner ksReasoner; 090 private QueryExecutionFactory ksQef; 091 092 // the instances on which the algorithms are really applied 093 @ConfigOption(description = "The sparql reasoner instance to use", defaultValue = "SPARQLReasoner") 094 protected SPARQLReasoner reasoner; 095 protected QueryExecutionFactory qef; 096 097 098 protected SortedSet<EvaluatedAxiom<T>> currentlyBestAxioms; 099 protected SortedSet<T> existingAxioms; 100 101 protected long startTime; 102 103 protected boolean timeout = true; 104 105 @Unused 106 protected boolean forceSPARQL_1_0_Mode = false; 107 108 protected int chunkCount = 0; 109 protected int chunkSize = 1000; 110 protected int offset = 0; 111 protected int lastRowCount = 0; 112 113 protected boolean fullDataLoaded = false; 114 115 protected List<String> allowedNamespaces = new ArrayList<>(); 116 117 protected ParameterizedSparqlString iterativeQueryTemplate; 118 119 protected Model sample; 120 121 protected ParameterizedSparqlString posExamplesQueryTemplate; 122 protected ParameterizedSparqlString negExamplesQueryTemplate; 123 protected ParameterizedSparqlString existingAxiomsTemplate; 124 125 protected OWLDataFactory df = new OWLDataFactoryImpl(); 126 127 @NoConfigOption 128// protected AxiomLearningProgressMonitor progressMonitor = new SilentAxiomLearningProgressMonitor(); 129 protected AxiomLearningProgressMonitor progressMonitor = new ConsoleAxiomLearningProgressMonitor(); 130 131 protected AxiomType<T> axiomType; 132 133 @ConfigOption(description = "the OWL entity to learn about") 134 protected E entityToDescribe; 135 136 @Unused 137 protected boolean useSampling = true; 138 protected int popularity; 139 140 public AbstractAxiomLearningAlgorithm() { 141 existingAxioms = new TreeSet<>(); 142 143 logger = LoggerFactory.getLogger(this.getClass()); 144 } 145 146 @NoConfigOption 147 public void setQueryExecutionFactory(QueryExecutionFactory qef) { 148 this.ksQef = qef; 149 } 150 151 @Override 152 public LearningProblem getLearningProblem() { 153 return learningProblem; 154 } 155 156 @Autowired 157 @Override 158 public void setLearningProblem(LearningProblem learningProblem) { 159 this.learningProblem = learningProblem; 160 } 161 162 /** 163 * @param entityToDescribe the entity for which axioms will be computed 164 */ 165 public void setEntityToDescribe(E entityToDescribe) { 166 this.entityToDescribe = entityToDescribe; 167 } 168 169 /** 170 * @return the entity for which axioms will be computed 171 */ 172 public E getEntityToDescribe() { 173 return entityToDescribe; 174 } 175 176 public void setUseSampling(boolean useSampling) { 177 this.useSampling = useSampling; 178 } 179 180 public boolean isUseSampling() { 181 return useSampling; 182 } 183 184 /** 185 * @return the axiomType 186 */ 187 public AxiomType<T> getAxiomType() { 188 return axiomType; 189 } 190 191 public int getMaxExecutionTimeInSeconds() { 192 return maxExecutionTimeInSeconds; 193 } 194 195 public void setMaxExecutionTimeInSeconds(int maxExecutionTimeInSeconds) { 196 this.maxExecutionTimeInSeconds = maxExecutionTimeInSeconds; 197 } 198 199 public SPARQLReasoner getReasoner() { 200 return reasoner; 201 } 202 203 public void setReasoner(SPARQLReasoner reasoner) { 204 this.ksReasoner = reasoner; 205 } 206 207 public boolean isReturnOnlyNewAxioms() { 208 return returnOnlyNewAxioms; 209 } 210 211 public void setReturnOnlyNewAxioms(boolean returnOnlyNewAxioms) { 212 this.returnOnlyNewAxioms = returnOnlyNewAxioms; 213 } 214 215 public int getMaxFetchedRows() { 216 return maxFetchedRows; 217 } 218 219 public void setMaxFetchedRows(int maxFetchedRows) { 220 this.maxFetchedRows = maxFetchedRows; 221 } 222 223 public void setForceSPARQL_1_0_Mode(boolean forceSPARQL_1_0_Mode) { 224 this.forceSPARQL_1_0_Mode = forceSPARQL_1_0_Mode; 225 } 226 227 @Override 228 public void start() { 229 logger.info("Started learning of " + axiomType.getName() + " axioms for " + 230 OWLAPIUtils.getPrintName(entityToDescribe.getEntityType()) + " " + entityToDescribe.toStringID() + "..."); 231 startTime = System.currentTimeMillis(); 232 233 currentlyBestAxioms = new TreeSet<>(); 234 235 // check whether the knowledge base contains information about the entity, if not terminate 236 popularity = reasoner.getPopularity(entityToDescribe); 237 if(popularity == 0){ 238 logger.warn("Cannot make " + axiomType.getName() + " axiom suggestions for empty " + OWLAPIUtils.getPrintName(entityToDescribe.getEntityType()) + " " + entityToDescribe.toStringID()); 239 return; 240 } 241 242 // if enabled, we check for existing axioms that will filtered out in the final result 243 if(returnOnlyNewAxioms){ 244 getExistingAxioms(); 245 } 246 247 // if enabled, we generated a sample of the knowledge base and do the rest of the compuatation locally 248 if(useSampling){ 249 generateSample(); 250 } else { 251 qef = ksQef; 252 reasoner = ksReasoner; 253 } 254 255 // compute the axiom type specific popularity of the entity to describe 256 popularity = getPopularity(); 257 258 // start the real learning algorithm 259 progressMonitor.learningStarted(axiomType); 260 try { 261 learnAxioms(); 262 } catch (Exception e) { 263 progressMonitor.learningFailed(axiomType); 264 throw e; 265 } finally { 266 progressMonitor.learningStopped(axiomType); 267 } 268 269 logger.info("...finished learning of " + axiomType.getName() 270 + " axioms for " + OWLAPIUtils.getPrintName(entityToDescribe.getEntityType()) 271 + " " + entityToDescribe.toStringID() + " in {}ms.", (System.currentTimeMillis() - startTime)); 272 273 showResult(); 274 275 } 276 277 protected void showResult() { 278 DecimalFormat format = new DecimalFormat("0.0000"); 279 format.setRoundingMode(RoundingMode.DOWN); 280 if(this instanceof ObjectPropertyCharacteristicsAxiomLearner){ 281 logger.info("Suggested axiom: " + currentlyBestAxioms.first()); 282 } else { 283 logger.info("Found " + currentlyBestAxioms.size() + " axiom candidates. " + 284 (returnOnlyNewAxioms 285 ? currentlyBestAxioms.size() - existingAxioms.size() + 286 " out of them do not already exists in the knowledge base." 287 : "")); 288 if(!currentlyBestAxioms.isEmpty()){ 289 EvaluatedAxiom<T> bestAxiom = currentlyBestAxioms.last(); 290 String s = "Best axiom candidate is " + bestAxiom.hypothesis + " with an accuracy of " + 291 format.format(bestAxiom.getAccuracy()); 292 if(returnOnlyNewAxioms) { 293 if(existingAxioms.contains(bestAxiom.hypothesis)) { 294 s += ", but it's already contained in the knowledge base."; 295 if(existingAxioms.size() != currentlyBestAxioms.size()) { 296 Optional<EvaluatedAxiom<T>> bestNewAxiom = currentlyBestAxioms.stream().filter( 297 ax -> !existingAxioms.contains(ax.hypothesis)).findFirst(); 298 if(bestNewAxiom.isPresent()) { 299 s += " The best new one is " + bestNewAxiom.get().hypothesis + " with an accuracy of " + 300 format.format(bestNewAxiom.get().getAccuracy()); 301 } 302 } 303 } 304 } 305 logger.info(s); 306 } 307 } 308 } 309 310 /** 311 * Compute the popularity of the entity to describe. This depends on the axiom type, thus, the mehtod might 312 * be overwritten in the corresponding algorithm classes. 313 * @return the populairty of the entity to describe 314 */ 315 protected int getPopularity() { 316 return reasoner.getPopularity(entityToDescribe); 317 } 318 319 private void generateSample(){ 320 logger.info("Generating sample..."); 321 sample = ModelFactory.createDefaultModel(); 322 323 // we have to set up a new query execution factory working on our local model 324 qef = new QueryExecutionFactoryModel(sample); 325 reasoner = new SPARQLReasoner(qef); 326 327 // get the page size 328 //TODO put to base class 329 long pageSize = 10000;//PaginationUtils.adjustPageSize(globalQef, 10000); 330 331 ParameterizedSparqlString sampleQueryTemplate = getSampleQuery(); 332 sampleQueryTemplate.setIri("p", entityToDescribe.toStringID()); 333 Query query = sampleQueryTemplate.asQuery(); 334 query.setLimit(pageSize); 335 336 boolean isEmpty = false; 337 int i = 0; 338 while(!isTimeout() && !isEmpty){ 339 // get next sample 340 logger.debug("Extending sample..."); 341 query.setOffset(i++ * pageSize); 342 QueryExecution qe = ksQef.createQueryExecution(query); 343 Model tmp = qe.execConstruct(); 344 sample.add(tmp); 345 346 // if last call returned empty model, we can leave loop 347 isEmpty = tmp.isEmpty(); 348 } 349 logger.info("...done. Sample size: " + sample.size() + " triples"); 350 } 351 352 /** 353 * @param progressMonitor the progressMonitor to set 354 */ 355 public void setProgressMonitor(AxiomLearningProgressMonitor progressMonitor) { 356 this.progressMonitor = progressMonitor; 357 } 358 359 @Override 360 public void init() throws ComponentInitException { 361 if(ks.isRemote()){ 362 ksQef = ks.getQueryExecutionFactory(); 363 } else { 364 ksQef = new QueryExecutionFactoryModel(((LocalModelBasedSparqlEndpointKS)ks).getModel()); 365 } 366 if(ksReasoner == null){ 367 ksReasoner = new SPARQLReasoner(ksQef); 368 } 369// ksReasoner.supportsSPARQL1_1(); 370 reasoner = ksReasoner; 371 372 initialized = true; 373 } 374 375 /** 376 * Compute the defined axioms in the knowledge base. 377 */ 378 protected abstract void getExistingAxioms(); 379 380 /** 381 * Learn new OWL axioms based on instance data. 382 */ 383 protected abstract void learnAxioms(); 384 385 /** 386 * The SPARQL CONSTRUCT query used to generate a sample for the given axiom type and entity. 387 * @return the SPARQL query 388 */ 389 protected abstract ParameterizedSparqlString getSampleQuery(); 390 391 @Override 392 public List<T> getCurrentlyBestAxioms() { 393 return getCurrentlyBestAxioms(Integer.MAX_VALUE); 394 } 395 396 @Override 397 public List<T> getCurrentlyBestAxioms(int nrOfAxioms) { 398 return getCurrentlyBestAxioms(nrOfAxioms, 0.0); 399 } 400 401 public boolean wasTimeout() { 402 return timeout; 403 } 404 405 public boolean isTimeout(){ 406 return maxExecutionTimeInSeconds != 0 && getRemainingRuntimeInMilliSeconds() <= 0; 407 } 408 409 public List<T> getCurrentlyBestAxioms(int nrOfAxioms, 410 double accuracyThreshold) { 411 return getCurrentlyBestEvaluatedAxioms(nrOfAxioms, accuracyThreshold) 412 .stream() 413 .map(EvaluatedAxiom<T>::getAxiom) 414 .collect(Collectors.toList()); 415 } 416 417 public List<T> getCurrentlyBestAxioms(double accuracyThreshold) { 418 return getCurrentlyBestEvaluatedAxioms(accuracyThreshold) 419 .stream() 420 .map(EvaluatedAxiom<T>::getAxiom) 421 .collect(Collectors.toList()); 422 } 423 424 public EvaluatedAxiom<T> getCurrentlyBestEvaluatedAxiom() { 425 if(currentlyBestAxioms.isEmpty()) { 426 return null; 427 } 428 return currentlyBestAxioms.last(); 429 } 430 431 @Override 432 public List<EvaluatedAxiom<T>> getCurrentlyBestEvaluatedAxioms() { 433 ArrayList<EvaluatedAxiom<T>> axioms = new ArrayList<>(currentlyBestAxioms); 434 435 // revert because highest element in tree set is last 436 Collections.reverse(axioms); 437 438 return axioms; 439 } 440 441 @Override 442 public List<EvaluatedAxiom<T>> getCurrentlyBestEvaluatedAxioms(int nrOfAxioms) { 443 return getCurrentlyBestEvaluatedAxioms(nrOfAxioms, 0.0); 444 } 445 446 public List<EvaluatedAxiom<T>> getCurrentlyBestEvaluatedAxioms(double accuracyThreshold) { 447 return getCurrentlyBestEvaluatedAxioms(Integer.MAX_VALUE, accuracyThreshold); 448 } 449 450 @Override 451 public List<EvaluatedAxiom<T>> getCurrentlyBestEvaluatedAxioms(int nrOfAxioms, 452 double accuracyThreshold) { 453 List<EvaluatedAxiom<T>> returnList = new ArrayList<>(); 454 455 //get the currently best evaluated axioms 456 List<EvaluatedAxiom<T>> currentlyBestEvAxioms = getCurrentlyBestEvaluatedAxioms(); 457 458 for(EvaluatedAxiom<T> evAx : currentlyBestEvAxioms){ 459 if(evAx.getScore().getAccuracy() >= accuracyThreshold && returnList.size() < nrOfAxioms){ 460 if(returnOnlyNewAxioms){ 461 if(!existingAxioms.contains(evAx.getAxiom())){ 462 returnList.add(evAx); 463 } 464 } else { 465 returnList.add(evAx); 466 } 467 } 468 } 469 470 return returnList; 471 } 472 473 public EvaluatedAxiom<T> getBestEvaluatedAxiom(){ 474 if(!currentlyBestAxioms.isEmpty()){ 475 return new TreeSet<>(currentlyBestAxioms).last(); 476 } 477 return null; 478 } 479 480 protected Set<OWLClass> getAllClasses() { 481 if(ks.isRemote()){ 482 return new SPARQLTasks(ks.getEndpoint()).getAllClasses(); 483 } else { 484 return ((LocalModelBasedSparqlEndpointKS) ks).getModel().listClasses() 485 .filterDrop(new OWLFilter()) 486 .filterDrop(new RDFSFilter()) 487 .filterDrop(new RDFFilter()) 488 .toList().stream() 489 .filter(cls -> !cls.isAnon()) 490 .map(cls -> df.getOWLClass(IRI.create(cls.getURI()))) 491 .collect(Collectors.toCollection(TreeSet::new)); 492 } 493 494 } 495 496 protected Model executeConstructQuery(String query) { 497 logger.trace("Sending query\n{} ...", query); 498 QueryExecution qe = qef.createQueryExecution(query); 499 try { 500 Model model = qe.execConstruct(); 501 timeout = false; 502 if(model.size() == 0){ 503 fullDataLoaded = true; 504 } 505 logger.debug("Got " + model.size() + " triples."); 506 return model; 507 } catch (QueryExceptionHTTP e) { 508 if(e.getCause() instanceof SocketTimeoutException){ 509 logger.warn("Got timeout"); 510 } else { 511 logger.error("Exception executing query", e); 512 } 513 return ModelFactory.createDefaultModel(); 514 } 515 } 516 517 protected ResultSet executeSelectQuery(String query) { 518 logger.trace("Sending query\n{} ...", query); 519 520 QueryExecution qe = qef.createQueryExecution(query); 521 try { 522 ResultSet rs = qe.execSelect(); 523 timeout = false; 524 return rs; 525 } catch (QueryExceptionHTTP e) { 526 if(e.getCause() instanceof SocketTimeoutException){ 527 if(timeout){ 528 logger.warn("Got timeout"); 529 throw e; 530 } else { 531 logger.trace("Got local timeout"); 532 } 533 534 } else { 535 logger.error("Exception executing query", e); 536 } 537 return new ResultSetMem(); 538 } 539 } 540 541 protected ResultSet executeSelectQuery(String query, Model model) { 542 logger.trace("Sending query on local model\n{} ...", query); 543 QueryExecutionFactory qef = new QueryExecutionFactoryModel(model); 544 QueryExecution qexec = qef.createQueryExecution(query); 545 return qexec.execSelect(); 546 } 547 548 protected boolean executeAskQuery(String query){ 549 logger.trace("Sending query\n{} ...", query); 550 return qef.createQueryExecution(query).execAsk(); 551 } 552 553 protected <K, V extends Comparable<V>> List<Entry<K, V>> sortByValues(Map<K, V> map){ 554 List<Entry<K, V>> entries = new ArrayList<>(map.entrySet()); 555 Collections.sort(entries, (o1, o2) -> o2.getValue().compareTo(o1.getValue())); 556 return entries; 557 } 558 559 protected long getRemainingRuntimeInMilliSeconds(){ 560 return Math.max(0, (maxExecutionTimeInSeconds * 1000) - (System.currentTimeMillis() - startTime)); 561 } 562 563 protected boolean terminationCriteriaSatisfied(){ 564 return maxExecutionTimeInSeconds != 0 && getRemainingRuntimeInMilliSeconds() <= 0; 565 } 566 567 protected List<Entry<OWLClassExpression, Integer>> sortByValues(Map<OWLClassExpression, Integer> map, final boolean useHierachy){ 568 List<Entry<OWLClassExpression, Integer>> entries = new ArrayList<>(map.entrySet()); 569 final ClassHierarchy hierarchy = reasoner.getClassHierarchy(); 570 571 Collections.sort(entries, (o1, o2) -> { 572 int ret = o2.getValue().compareTo(o1.getValue()); 573 //if the score is the same, than we optionally also take into account the subsumption hierarchy 574 if(ret == 0 && useHierachy){ 575 if(hierarchy != null){ 576 if(hierarchy.contains(o1.getKey()) && hierarchy.contains(o2.getKey())){ 577 if(hierarchy.isSubclassOf(o1.getKey(), o2.getKey())){ 578 ret = -1; 579 } else if(hierarchy.isSubclassOf(o2.getKey(), o1.getKey())){ 580 ret = 1; 581 } else { 582 //we use the depth in the class hierarchy as third ranking property 583// int depth1 = hierarchy.getDepth2Root(o1.getKey()); 584// int depth2 = hierarchy.getDepth2Root(o2.getKey()); 585// ret = depth1 - depth2; 586 } 587 } 588 } 589 } 590 591 return ret; 592 }); 593 return entries; 594 } 595 596 protected AxiomScore computeScore(int total, int success){ 597 return computeScore(total, success, false); 598 } 599 600 protected AxiomScore computeScore(int total, int success, boolean sample){ 601 if(success > total){ 602 logger.warn("success value > total value"); 603 } 604 double[] confidenceInterval = Heuristics.getConfidenceInterval95Wald(total, success); 605 606 double accuracy = Heuristics.getConfidenceInterval95WaldAverage(total, success); 607 608 double confidence = confidenceInterval[1] - confidenceInterval[0]; 609 610 return new AxiomScore(accuracy, confidence, success, total-success, sample); 611 } 612// 613// protected double accuracy(int total, int success){ 614// double[] confidenceInterval = Heuristics.getConfidenceInterval95Wald(total, success); 615// return (confidenceInterval[0] + confidenceInterval[1]) / 2; 616// } 617// 618// protected double fMEasure(double precision, double recall){ 619// return 2 * precision * recall / (precision + recall); 620// } 621 622 623 public void addFilterNamespace(String namespace){ 624 allowedNamespaces.add(namespace); 625 } 626 627 @SuppressWarnings("unchecked") 628 public Set<S> getPositiveExamples(EvaluatedAxiom<T> evAxiom) { 629 return getExamples(posExamplesQueryTemplate, evAxiom); 630 } 631 632 @SuppressWarnings("unchecked") 633 public Set<S> getNegativeExamples(EvaluatedAxiom<T> evAxiom) { 634 return getExamples(negExamplesQueryTemplate, evAxiom); 635 } 636 637 @SuppressWarnings("unchecked") 638 protected Set<S> getExamples(ParameterizedSparqlString queryTemplate, EvaluatedAxiom<T> evAxiom) { 639 ResultSet rs = executeSelectQuery(queryTemplate.toString()); 640 641 Set<OWLObject> negExamples = new TreeSet<>(); 642 643 while(rs.hasNext()){ 644 RDFNode node = rs.next().get("s"); 645 if(node.isResource()){ 646 negExamples.add(df.getOWLNamedIndividual(IRI.create(node.asResource().getURI()))); 647 } else if(node.isLiteral()){ 648 negExamples.add(convertLiteral(node.asLiteral())); 649 } 650 } 651 return (Set<S>) negExamples; 652 } 653 654 public void explainScore(EvaluatedAxiom<T> evAxiom){ 655 AxiomScore score = evAxiom.getScore(); 656 int posExampleCnt = score.getNrOfPositiveExamples(); 657 int negExampleCnt = score.getNrOfNegativeExamples(); 658 int total = posExampleCnt + negExampleCnt; 659 StringBuilder sb = new StringBuilder(); 660 String lb = "\n"; 661 sb.append("######################################").append(lb); 662 sb.append("Explanation:").append(lb); 663 sb.append("Score(").append(evAxiom.getAxiom()).append(") = ").append(evAxiom.getScore().getAccuracy()).append(lb); 664 sb.append("Total number of resources:\t").append(total).append(lb); 665 sb.append("Number of positive examples:\t").append(posExampleCnt).append(lb); 666 sb.append("Number of negative examples:\t").append(negExampleCnt).append(lb); 667 sb.append("Based on sample: \t").append(score.isSampleBased()).append(lb); 668 if(sample != null){ 669 sb.append("Sample size(#triples): \t").append(sample.size()).append(lb); 670 } 671 sb.append("######################################"); 672 System.out.println(sb.toString()); 673 } 674 675 public long getEvaluatedFramentSize(){ 676 return sample.size(); 677 } 678 679 /** 680 * Converts a JENA API Literal object into an OWL API OWLLiteral object. 681 * 682 * @param lit the JENA API literal 683 * @return the OWL API literal 684 */ 685 protected OWLLiteral convertLiteral(Literal lit) { 686 String datatypeURI = lit.getDatatypeURI(); 687 OWLLiteral owlLiteral; 688 if (datatypeURI == null) {// rdf:PlainLiteral 689 owlLiteral = df.getOWLLiteral(lit.getLexicalForm(), lit.getLanguage()); 690 } else { 691 owlLiteral = df.getOWLLiteral(lit.getLexicalForm(), df.getOWLDatatype(IRI.create(datatypeURI))); 692 } 693 return owlLiteral; 694 } 695 696 public static <E> void printSubset(Collection<E> collection, int maxSize){ 697 StringBuilder sb = new StringBuilder(); 698 int i = 0; 699 Iterator<E> iter = collection.iterator(); 700 while(iter.hasNext() && i < maxSize){ 701 sb.append(iter.next().toString()).append(", "); 702 i++; 703 } 704 if(iter.hasNext()){ 705 sb.append("...(").append(collection.size()-i).append(" more)"); 706 } 707 System.out.println(sb.toString()); 708 } 709 710 protected <K,J extends Set<V>, V> void addToMap(Map<K, J> map, K key, V value ){ 711 J values = map.get(key); 712 if(values == null){ 713 try { 714 values = (J) value.getClass().newInstance(); 715 values.add(value); 716 } 717 catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();return;} 718 } 719 values.add(value); 720 } 721 722 protected <K,J extends Set<V>, V> void addToMap(Map<K, J> map, K key, Collection<V> newValues ){ 723 J values = map.get(key); 724 if(values == null){ 725 try { 726 values = (J) newValues.getClass().newInstance(); 727 } catch (InstantiationException | IllegalAccessException e) { 728 e.printStackTrace(); 729 } 730 map.put(key, values); 731 } 732 values.addAll(newValues); 733 } 734 735 @Autowired 736 public void setKs(SparqlEndpointKS ks) { 737 this.ks = ks; 738 } 739 740 class OWLFilter implements Predicate<OntClass> { 741 742 @Override 743 public boolean test(OntClass cls) { 744 if(!cls.isAnon()){ 745 return cls.getURI().startsWith(OWL2.getURI()); 746 } 747 return false; 748 } 749 } 750 751 class RDFSFilter implements Predicate<OntClass>{ 752 753 @Override 754 public boolean test(OntClass cls) { 755 if(!cls.isAnon()){ 756 return cls.getURI().startsWith(RDFS.getURI()); 757 } 758 return false; 759 } 760 761 } 762 763 class RDFFilter implements Predicate<OntClass>{ 764 765 @Override 766 public boolean test(OntClass cls) { 767 if(!cls.isAnon()){ 768 return cls.getURI().startsWith(RDF.getURI()); 769 } 770 return false; 771 } 772 773 } 774 775 776}