diff --git a/.gitignore b/.gitignore
index 942867a445..22a15a143a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ target
deptree.txt
cache
log
+*.idea
+*.iml
diff --git a/components-core/pom.xml b/components-core/pom.xml
index e155e86014..3e991156e3 100644
--- a/components-core/pom.xml
+++ b/components-core/pom.xml
@@ -10,113 +10,114 @@
org.dllearner
dllearner-parent
- 1.1
+ 1.2
-
+
-
- release
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
-
-
-
-
- org/dllearner/test/*
- org/dllearner/test/junit/TestOntologies.java
- org/dllearner/test/junit/PropertyLearningTest.java
- org/dllearner/test/junit/DisjointClassesLearningTest.java
-
- **/*$*
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
-
- test-jar
-
-
-
-
-
-
-
-
-
-
-
-
- org.codehaus.mojo
- license-maven-plugin
- 1.8
-
- gpl_v3
- AKSW
- 2007
-
- src/main/java
- src/test/java
-
- true
-
-
-
- download-licenses
-
- download-licenses
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
-
-
- public
- true
- doc/javadoc
- DL-Learner Javadoc
- true
- false
- false
- false
- false
- false
- src/etc/overview.html
-
- src/main/java
- true
- src/etc/javadoc2.css
-
- true
- true
- <img style='float:right'
- src='https://raw.githubusercontent.com/github/media/master/octocats/blacktocat-16.png'
- border='0' alt='Github.com Logo' /> DL-Learner is licenced
- under the terms of the GNU General Public License.<br
- />Copyright © 2007-2015 Jens Lehmann
- ISO-8859-1
- DL-Learner Javadoc
- -Xdoclint:none
-
-
-
-
-
-
+
+ release
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+
+
+
+ org/dllearner/test/*
+ org/dllearner/test/junit/TestOntologies.java
+ org/dllearner/test/junit/PropertyLearningTest.java
+ org/dllearner/test/junit/DisjointClassesLearningTest.java
+
+ **/*$*
+
+ -Dlog4j.configuration=log4j.properties
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ license-maven-plugin
+ 1.8
+
+ gpl_v3
+ AKSW
+ 2007
+
+ src/main/java
+ src/test/java
+
+ true
+
+
+
+ download-licenses
+
+ download-licenses
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+ public
+ true
+ doc/javadoc
+ DL-Learner Javadoc
+ true
+ false
+ false
+ false
+ false
+ false
+ src/etc/overview.html
+
+ src/main/java
+ true
+ src/etc/javadoc2.css
+
+ true
+ true
+ <img style='float:right'
+ src='https://raw.githubusercontent.com/github/media/master/octocats/blacktocat-16.png'
+ border='0' alt='Github.com Logo' /> DL-Learner is licenced
+ under the terms of the GNU General Public License.<br
+ />Copyright © 2007-2015 Jens Lehmann
+ ISO-8859-1
+ DL-Learner Javadoc
+ -Xdoclint:none
+
+
+
+
+
+
@@ -137,6 +138,7 @@
**/*$*
+ -Dlog4j.configuration=log4j.properties
+ com.github.github
+ site-maven-plugin
+ 0.12
+
+
+
+ site
+
+
+ site-deploy
+
+
+
+ github
+
+
+ Creating site for ${project.name} ${project.version}
+
+ ${project.version}
+
+ true
+ true
+
+
+
+
@@ -160,17 +200,17 @@
org.ini4j
ini4j
-
+
mysql
mysql-connector-java
-
+
net.sourceforge.owlapi
owlapi-distribution
-
+
net.sourceforge.owlapi
owlapi-api
@@ -182,6 +222,10 @@
net.sourceforge.owlapi
owlapi-impl
+
+ net.sourceforge.owlapi
+ owlapitools-concurrentimpl
+
com.clarkparsia.pellet
@@ -189,35 +233,35 @@
pom
-
+
-
-
+
+
org.json
json
-
+
com.google.code.factplusplus
@@ -230,10 +274,32 @@
- org.semanticweb.hermit
- hermit
+ net.sourceforge.owlapi
+ org.semanticweb.hermit
+
+ org.semanticweb.elk
+ elk-owlapi
+
+
+
+ de.tudresden.inf.lat.cel
+ reasoner
+ 0.5.1
+
+
+
+
net.sourceforge.owlapi
jfact
@@ -256,17 +322,17 @@
1.0
-
-
-
-
-
+
+
+
+
+
- org.fuzzy
- fuzzyowl
- 1.0
-
+ org.fuzzy
+ fuzzyowl
+ 1.0
+
-
- org.semanticweb.elk
- elk-owlapi
-
-
- de.tudresden.inf.lat.cel
- reasoner
- 0.5.1
-
-
-
- eu.trowl
- trowl-core
-
+
-
- uk.ac.shef.wit
- simmetrics
- 1.6.2
-
-
- com.thoughtworks.xstream
- xstream
- 1.4.3
-
-
+
+ uk.ac.shef.wit
+ simmetrics
+ 1.6.2
+
+
+ com.thoughtworks.xstream
+ xstream
+ 1.4.3
+
+
-
- com.google.guava
- guava
-
+
+ com.google.guava
+ guava
+
-
- org.aksw.jena-sparql-api
- jena-sparql-api-core
-
-
- slf4j-ext
- org.slf4j
-
-
-
-
- org.aksw.jena-sparql-api
- jena-sparql-api-cache-h2
-
+
+ org.aksw.jena-sparql-api
+ jena-sparql-api-core
+
+
+ slf4j-ext
+ org.slf4j
+
+
+
+
+ org.aksw.jena-sparql-api
+ jena-sparql-api-cache-h2
+
org.apache.commons
commons-math3
-
+
+
+
+
+ org.aksw
+ semlibsvm
+
+
+
+ edu.berkeley.compbio
+ jlibsvm
+
+
+
+ com.martiansoftware
+ jsap
+ 2.1
+
+
+
+
+ org.reflections
+ reflections
+ 0.9.9-RC1
+
+
+
- com.h2database
- h2
+ net.sf.jopt-simple
+ jopt-simple
+ test
-
- -->
-
-
- org.aksw
- semlibsvm
+ org.apache.commons
+ commons-email
+ 1.4
+ test
- org.reflections
- reflections
- 0.9.9-RC1
+ com.panayotis.gnuplot
+ javaplot
+ 0.5.0
+ test
+
diff --git a/components-core/src/main/java/org/dllearner/algorithms/CELOEWrapper.java b/components-core/src/main/java/org/dllearner/algorithms/CELOEWrapper.java
index 2291345c7a..fc299f7da0 100644
--- a/components-core/src/main/java/org/dllearner/algorithms/CELOEWrapper.java
+++ b/components-core/src/main/java/org/dllearner/algorithms/CELOEWrapper.java
@@ -1,13 +1,29 @@
/**
- *
+ * Copyright (C) 2007 - 2016, Jens Lehmann
+ *
+ * This file is part of DL-Learner.
+ *
+ * DL-Learner is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DL-Learner is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package org.dllearner.algorithms;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.util.Set;
-import java.util.SortedSet;
-
+import com.google.common.collect.Sets;
+import com.hp.hpl.jena.query.ParameterizedSparqlString;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.Statement;
+import com.hp.hpl.jena.rdf.model.StmtIterator;
import org.aksw.jena_sparql_api.pagination.core.QueryExecutionFactoryPaginated;
import org.dllearner.algorithms.celoe.CELOE;
import org.dllearner.core.AbstractAxiomLearningAlgorithm;
@@ -21,30 +37,23 @@
import org.dllearner.reasoning.ClosedWorldReasoner;
import org.dllearner.utilities.OwlApiJenaUtils;
import org.dllearner.utilities.owl.OWLEntityTypeAdder;
-import org.semanticweb.owlapi.io.RDFXMLOntologyFormat;
-//import org.dllearner.utilities.OwlApiJenaUtils;
-import org.semanticweb.owlapi.model.IRI;
-import org.semanticweb.owlapi.model.OWLClass;
-import org.semanticweb.owlapi.model.OWLClassAxiom;
-import org.semanticweb.owlapi.model.OWLClassExpression;
-import org.semanticweb.owlapi.model.OWLIndividual;
-import org.semanticweb.owlapi.model.OWLOntology;
-import org.semanticweb.owlapi.model.OWLOntologyStorageException;
-
+import org.semanticweb.owlapi.formats.RDFXMLDocumentFormat;
+import org.semanticweb.owlapi.model.*;
import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl;
-import com.google.common.collect.Sets;
-import com.hp.hpl.jena.query.ParameterizedSparqlString;
-import com.hp.hpl.jena.query.QueryExecution;
-import com.hp.hpl.jena.rdf.model.Model;
-import com.hp.hpl.jena.rdf.model.Statement;
-import com.hp.hpl.jena.rdf.model.StmtIterator;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.Set;
+import java.util.SortedSet;
+
+//import org.dllearner.utilities.OwlApiJenaUtils;
/**
* A wrapper class for CELOE that allows for returning the result in forms of OWL axioms.
* @author Lorenz Buehmann
*
*/
+// not for conf
public class CELOEWrapper extends AbstractAxiomLearningAlgorithm {
private boolean equivalence = true;
@@ -104,7 +113,7 @@ protected void learnAxioms() {
OWLOntology fragment = buildFragment(posExamples, negExamples);
try {
- fragment.getOWLOntologyManager().saveOntology(fragment, new RDFXMLOntologyFormat(), new FileOutputStream("/tmp/ont.owl"));
+ fragment.getOWLOntologyManager().saveOntology(fragment, new RDFXMLDocumentFormat(), new FileOutputStream("/tmp/ont.owl"));
} catch (OWLOntologyStorageException | FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
diff --git a/components-core/src/main/java/org/dllearner/algorithms/DisjointClassesLearner.java b/components-core/src/main/java/org/dllearner/algorithms/DisjointClassesLearner.java
index b3c57e3025..2dc211fe84 100644
--- a/components-core/src/main/java/org/dllearner/algorithms/DisjointClassesLearner.java
+++ b/components-core/src/main/java/org/dllearner/algorithms/DisjointClassesLearner.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2007-2011, Jens Lehmann
+ * Copyright (C) 2007 - 2016, Jens Lehmann
*
* This file is part of DL-Learner.
*
@@ -16,11 +16,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
package org.dllearner.algorithms;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -35,6 +33,8 @@
import org.dllearner.core.EvaluatedAxiom;
import org.dllearner.core.EvaluatedDescription;
import org.dllearner.core.Score;
+import org.dllearner.core.annotations.Unused;
+import org.dllearner.core.config.ConfigOption;
import org.dllearner.core.owl.ClassHierarchy;
import org.dllearner.kb.LocalModelBasedSparqlEndpointKS;
import org.dllearner.kb.SparqlEndpointKS;
@@ -57,9 +57,6 @@
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFactory;
import com.hp.hpl.jena.query.ResultSetRewindable;
-import com.hp.hpl.jena.rdf.model.Model;
-import com.hp.hpl.jena.rdf.model.ModelFactory;
-import com.hp.hpl.jena.rdf.model.Resource;
/**
* Learns disjoint classes using SPARQL queries.
@@ -82,13 +79,16 @@ public class DisjointClassesLearner extends AbstractAxiomLearningAlgorithm> currentlyBestEvaluatedDescriptions;
private SortedSet subClasses;
+ @Unused
private boolean useWordNetDistance = false;
+ @ConfigOption(description = "only keep most general classes in suggestions", defaultValue = "true")
private boolean suggestMostGeneralClasses = true;
+ @ConfigOption(description = "include instance count / popularity when computing scores", defaultValue = "true")
private boolean useClassPopularity = true;
private Set allClasses;
@@ -162,14 +162,14 @@ private void run() {
int nrOfNegExamples = popularity - nrOfPosExamples;
currentlyBestAxioms.add(
- new EvaluatedAxiom(
- df.getOWLDisjointClassesAxiom(entityToDescribe, cls),
+ new EvaluatedAxiom<>(
+ df.getOWLDisjointClassesAxiom(entityToDescribe, cls),
new AxiomScore(score, score, nrOfPosExamples, nrOfNegExamples, useSampling)));
}
}
/**
- * In this method we try to compute the overlap with each property in one single SPARQL query.
+ * In this method we try to compute the overlap with each class in one single SPARQL query.
* This method might be much slower as the query is much more complex.
*/
protected void runBatched() {
@@ -198,20 +198,20 @@ protected void runBatched() {
int nrOfNegExamples = popularity - nrOfPosExamples;
currentlyBestAxioms.add(
- new EvaluatedAxiom(
- df.getOWLDisjointClassesAxiom(entityToDescribe, candidate),
+ new EvaluatedAxiom<>(
+ df.getOWLDisjointClassesAxiom(entityToDescribe, candidate),
new AxiomScore(score, score, nrOfPosExamples, nrOfNegExamples, useSampling)));
}
}
/**
- * Returns the candidate properties for comparison.
- * @return
+ * Returns the candidate classes for comparison.
+ * @return the candidate classes
*/
private SortedSet getCandidates(){
SortedSet candidates;
- if (strictOWLMode) {
+ if (strictOWLMode) {
candidates = reasoner.getOWLClasses();
} else {
candidates = reasoner.getClasses();
@@ -225,7 +225,7 @@ private SortedSet getCandidates(){
return candidates;
}
- public double computeScore(int candidatePopularity, int popularity, int overlap){
+ private double computeScore(int candidatePopularity, int popularity, int overlap){
// compute the estimated precision
double precision = Heuristics.getConfidenceInterval95WaldAverage(candidatePopularity, overlap);
@@ -254,6 +254,14 @@ public void setSuggestMostGeneralClasses(boolean suggestMostGeneralClasses) {
this.suggestMostGeneralClasses = suggestMostGeneralClasses;
}
+ public boolean isUseClassPopularity() {
+ return useClassPopularity;
+ }
+
+ public void setUseClassPopularity(boolean useClassPopularity) {
+ this.useClassPopularity = useClassPopularity;
+ }
+
/* (non-Javadoc)
* @see org.dllearner.core.AbstractAxiomLearningAlgorithm#getSampleQuery()
*/
@@ -284,131 +292,9 @@ protected void getExistingAxioms() {
}
}
- private void runSingleQueryMode() {
- //compute the overlap if exist
- Map class2Overlap = new HashMap();
- String query = String.format("SELECT ?type (COUNT(*) AS ?cnt) WHERE {?s a <%s>. ?s a ?type.} GROUP BY ?type",
- entityToDescribe.toStringID());
- ResultSet rs = executeSelectQuery(query);
- QuerySolution qs;
- while (rs.hasNext()) {
- qs = rs.next();
- OWLClass cls = df.getOWLClass(IRI.create(qs.getResource("type").getURI()));
- int cnt = qs.getLiteral("cnt").getInt();
- class2Overlap.put(cls, cnt);
- }
- //for each class in knowledge base
- for (OWLClass cls : allClasses) {
- //get the popularity
- int otherPopularity = reasoner.getPopularity(cls);
- if (otherPopularity == 0) {//skip empty properties
- continue;
- }
- System.out.println(cls);
- //get the overlap
- int overlap = class2Overlap.containsKey(cls) ? class2Overlap.get(cls) : 0;
- //compute the estimated precision
- // compute the estimated precision
- double precision = Heuristics.getConfidenceInterval95WaldAverage(otherPopularity, overlap);
-
- // compute the estimated recall
- double recall = Heuristics.getConfidenceInterval95WaldAverage(popularity, overlap);
-
- // compute the final score
- double score = 1 - Heuristics.getFScore(recall, precision);
-
- currentlyBestEvaluatedDescriptions.add(new EvaluatedDescription(cls, new AxiomScore(score)));
- }
- }
-
- private void runSPARQL1_0_Mode() {
- Model model = ModelFactory.createDefaultModel();
- int limit = 1000;
- int offset = 0;
- String baseQuery = "CONSTRUCT {?s a <%s>. ?s a ?type.} WHERE {?s a <%s>. ?s a ?type.} LIMIT %d OFFSET %d";
- String query = String.format(baseQuery, entityToDescribe.toStringID(), entityToDescribe.toStringID(), limit,
- offset);
- Model newModel = executeConstructQuery(query);
- Map result = new HashMap();
- OWLClass cls;
- while (!terminationCriteriaSatisfied() && newModel.size() != 0) {
- model.add(newModel);
- //get total number of distinct instances
- query = "SELECT (COUNT(DISTINCT ?s) AS ?count) WHERE {?s a ?type.}";
- ResultSet rs = executeSelectQuery(query, model);
- int total = rs.next().getLiteral("count").getInt();
-
- // get number of instances of s with
- query = "SELECT ?type (COUNT(?s) AS ?count) WHERE {?s a ?type.}" + " GROUP BY ?type";
- rs = executeSelectQuery(query, model);
- QuerySolution qs;
- while (rs.hasNext()) {
- qs = rs.next();
- if (qs.getResource("type") != null && !qs.getResource("type").isAnon()) {
- cls = df.getOWLClass(IRI.create(qs.getResource("type").getURI()));
- int newCnt = qs.getLiteral("count").getInt();
- result.put(cls, newCnt);
- }
-
- }
-
- if (!result.isEmpty()) {
- currentlyBestEvaluatedDescriptions = buildEvaluatedClassDescriptions(result, allClasses, total);
- }
-
- offset += limit;
- query = String.format(baseQuery, entityToDescribe.toStringID(), entityToDescribe.toStringID(), limit, offset);
- newModel = executeConstructQuery(query);
- }
-
- }
-
- private void runSPARQL1_1_Mode() {
- int limit = 1000;
- int offset = 0;
- String queryTemplate = "PREFIX owl: SELECT ?type (COUNT(?s) AS ?count) WHERE {?s a ?type. ?type a owl:Class"
- + "{SELECT ?s WHERE {?s a <%s>.} LIMIT %d OFFSET %d} " + "} GROUP BY ?type";
- String query;
- Map result = new HashMap();
- OWLClass cls;
- Integer oldCnt;
- boolean repeat = true;
-
- while (!terminationCriteriaSatisfied() && repeat) {
- query = String.format(queryTemplate, entityToDescribe, limit, offset);
- ResultSet rs = executeSelectQuery(query);
- QuerySolution qs;
- repeat = false;
- Resource res;
- while (rs.hasNext()) {
- qs = rs.next();
- res = qs.getResource("type");
- if (res != null && !res.isAnon()) {
- cls = df.getOWLClass(IRI.create(qs.getResource("type").getURI()));
- int newCnt = qs.getLiteral("count").getInt();
- oldCnt = result.get(cls);
- if (oldCnt == null) {
- oldCnt = Integer.valueOf(newCnt);
- } else {
- oldCnt += newCnt;
- }
-
- result.put(cls, oldCnt);
- repeat = true;
- }
-
- }
- if (!result.isEmpty()) {
- currentlyBestEvaluatedDescriptions = buildEvaluatedClassDescriptions(result, allClasses,
- result.get(entityToDescribe));
- offset += 1000;
- }
- }
- }
-
@Override
public List getCurrentlyBestDescriptions(int nrOfDescriptions) {
- List bestDescriptions = new ArrayList();
+ List bestDescriptions = new ArrayList<>();
for (EvaluatedDescription extends Score> evDesc : getCurrentlyBestEvaluatedDescriptions(nrOfDescriptions)) {
bestDescriptions.add(evDesc.getDescription());
}
@@ -421,36 +307,6 @@ public List extends EvaluatedDescription extends Score>> getCurrentlyBestEva
return currentlyBestEvaluatedDescriptions.subList(0, max);
}
- @Override
- public List getCurrentlyBestAxioms(int nrOfAxioms) {
- List bestAxioms = new ArrayList();
-
- for (EvaluatedAxiom evAx : getCurrentlyBestEvaluatedAxioms(nrOfAxioms)) {
- bestAxioms.add(evAx.getAxiom());
- }
-
- return bestAxioms;
- }
-
- @Override
- public List> getCurrentlyBestEvaluatedAxioms() {
- return getCurrentlyBestEvaluatedAxioms(currentlyBestEvaluatedDescriptions.size());
- }
-
- @Override
- public List> getCurrentlyBestEvaluatedAxioms(int nrOfAxioms) {
- List> axioms = new ArrayList>();
- Set descriptions;
- for (EvaluatedDescription extends Score> ed : getCurrentlyBestEvaluatedDescriptions(nrOfAxioms)) {
- descriptions = new TreeSet();
- descriptions.add(entityToDescribe);
- descriptions.add(ed.getDescription());
- axioms.add(new EvaluatedAxiom(df.getOWLDisjointClassesAxiom(descriptions),
- new AxiomScore(ed.getAccuracy())));
- }
- return axioms;
- }
-
private List> buildEvaluatedClassDescriptions(Map class2Count,
Set allClasses, int total) {
List> evalDescs = new ArrayList<>();
@@ -460,7 +316,7 @@ private List> buildEvaluatedClassDescripti
class2Count.remove(entityToDescribe);
//get complete disjoint classes
- Set completeDisjointclasses = new TreeSet(allClasses);
+ Set completeDisjointclasses = new TreeSet<>(allClasses);
completeDisjointclasses.removeAll(class2Count.keySet());
// we remove the asserted subclasses here
@@ -507,7 +363,7 @@ private List> buildEvaluatedClassDescripti
evalDescs.add(evalDesc);
}
- //secondly, create disjoint classexpressions with score 1 - (#occurence/#all)
+ //secondly, create disjoint class expressions with score 1 - (#occurence/#all)
OWLClass cls;
for (Entry entry : sortByValues(class2Count)) {
cls = entry.getKey();
@@ -551,7 +407,7 @@ private void keepMostGeneralClasses(Set classes) {
if (ks.isRemote()) {
if (reasoner.isPrepared()) {
ClassHierarchy h = reasoner.getClassHierarchy();
- for (OWLClass nc : new HashSet(classes)) {
+ for (OWLClass nc : new HashSet<>(classes)) {
classes.removeAll(h.getSubClasses(nc));
}
}
@@ -561,14 +417,14 @@ private void keepMostGeneralClasses(Set classes) {
// Set topClasses = new HashSet();
// for(OntClass cls : model.listOWLClasses().toSet()){
// Set superClasses = cls.listSuperClasses().toSet();
- // if(superClasses.isEmpty() ||
+ // if(superClasses.isEmpty() ||
// (superClasses.size() == 1 && superClasses.contains(model.getOntClass(com.hp.hpl.jena.vocabulary.OWL.Thing.getURI())))){
// topClasses.add(df.getOWLClass(IRI.create(cls.getURI()));
// }
- //
+ //
// }
// classes.retainAll(topClasses);
- for (OWLClass nc : new HashSet(classes)) {//System.out.print(nc + "::");
+ for (OWLClass nc : new HashSet<>(classes)) {//System.out.print(nc + "::");
for (OntClass cls : model.getOntClass(nc.toStringID()).listSubClasses().toSet()) {//System.out.print(cls + "|");
classes.remove(df.getOWLClass(IRI.create(cls.getURI())));
}
@@ -595,7 +451,7 @@ private void computeAllDisjointClassAxiomsOptimized() {
}
private Set computeDisjointessOfSiblings(OWLClass cls) {
- Set evaluatedDescriptions = new HashSet();
+ Set evaluatedDescriptions = new HashSet<>();
//get number of instances of A
int instanceCountA = reasoner.getPopularity(cls);
@@ -635,17 +491,15 @@ public EvaluatedAxiom computeDisjointess(OWLClass clsA,
//if clsA = clsB
if (clsA.equals(clsB)) {
- return new EvaluatedAxiom(df.getOWLDisjointClassesAxiom(clsA, clsB),
+ return new EvaluatedAxiom<>(df.getOWLDisjointClassesAxiom(clsA, clsB),
new AxiomScore(0d, 1d));
}
- ;
- //if the classes are connected via subsumption we assume that they are not disjoint
+ //if the classes are connected via subsumption we assume that they are not disjoint
if (reasoner.isSuperClassOf(clsA, clsB) || reasoner.isSuperClassOf(clsB, clsA)) {
- return new EvaluatedAxiom(df.getOWLDisjointClassesAxiom(clsA, clsB),
+ return new EvaluatedAxiom<>(df.getOWLDisjointClassesAxiom(clsA, clsB),
new AxiomScore(0d, 1d));
}
- ;
double scoreValue = 0;
@@ -672,11 +526,11 @@ public EvaluatedAxiom computeDisjointess(OWLClass clsA,
AxiomScore score = new AxiomScore(scoreValue);
- return new EvaluatedAxiom(df.getOWLDisjointClassesAxiom(clsA, clsB), score);
+ return new EvaluatedAxiom<>(df.getOWLDisjointClassesAxiom(clsA, clsB), score);
}
public Set> computeSchemaDisjointness() {
- Set> axioms = new HashSet>();
+ Set> axioms = new HashSet<>();
Set classes = reasoner.getOWLClasses("http://dbpedia.org/ontology/");
computeDisjointness(classes);
@@ -693,7 +547,7 @@ public Set> computeSchemaDisjointness()
}
public Set> computeDisjointness(Set classes) {
- Set> axioms = new HashSet>();
+ Set> axioms = new HashSet<>();
for (OWLClass clsA : classes) {
for (OWLClass clsB : classes) {
@@ -705,7 +559,7 @@ public Set> computeDisjointness(Set asOWLClasses(Set descriptions) {
- Set classes = new TreeSet();
+ Set classes = new TreeSet<>();
for (OWLClassExpression description : descriptions) {
if (!description.isAnonymous()) {
classes.add(description.asOWLClass());
@@ -715,10 +569,16 @@ public static Set asOWLClasses(Set descriptions) {
}
public static void main(String[] args) throws Exception {
- DisjointClassesLearner la = new DisjointClassesLearner(new SparqlEndpointKS(SparqlEndpoint.getEndpointDBpedia()));
+ SparqlEndpointKS ks = new SparqlEndpointKS(SparqlEndpoint.create("http://sake.informatik.uni-leipzig.de:8890/sparql", "http://dbpedia.org"));
+ ks.init();
+
+ DisjointClassesLearner la = new DisjointClassesLearner(ks);
la.setEntityToDescribe(new OWLClassImpl(IRI.create("http://dbpedia.org/ontology/Actor")));
la.setUseSampling(false);
la.init();
+
la.start();
+
+ la.getCurrentlyBestAxioms(10);
}
}
\ No newline at end of file
diff --git a/components-core/src/main/java/org/dllearner/algorithms/NaiveALLearner.java b/components-core/src/main/java/org/dllearner/algorithms/NaiveALLearner.java
index 3b0e5e51fe..596d46fb0a 100644
--- a/components-core/src/main/java/org/dllearner/algorithms/NaiveALLearner.java
+++ b/components-core/src/main/java/org/dllearner/algorithms/NaiveALLearner.java
@@ -1,3 +1,21 @@
+/**
+ * Copyright (C) 2007 - 2016, Jens Lehmann
+ *
+ * This file is part of DL-Learner.
+ *
+ * DL-Learner is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DL-Learner is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.dllearner.algorithms;
import java.util.ArrayList;
@@ -12,6 +30,7 @@
import org.dllearner.core.ComponentAnn;
import org.dllearner.core.ComponentInitException;
import org.dllearner.core.EvaluatedDescription;
+import org.dllearner.core.config.ConfigOption;
import org.dllearner.core.owl.OWLObjectIntersectionOfImplExt;
import org.dllearner.learningproblems.EvaluatedDescriptionPosNeg;
import org.dllearner.learningproblems.ScorePosNeg;
@@ -28,6 +47,7 @@ public class NaiveALLearner extends AbstractCELA{
private Map> generatedDescriptions;
private boolean running = false;
+ @ConfigOption(defaultValue = "4", description = "maximum length of class expression")
private int maxLength = 4;
private OWLClassExpression bestDescription;
@@ -60,7 +80,7 @@ public void start() {
@Override
public void init() throws ComponentInitException {
- generatedDescriptions = new HashMap>();
+ generatedDescriptions = new HashMap<>();
// start with owl:Thing
bestDescription = OWL_THING;
@@ -104,7 +124,7 @@ public EvaluatedDescription getCurrentlyBestEvaluatedDescription() {
* - all concepts of length `length`-2 are extended by limited
* existential quantification/value restriction
*
- * @param length
+ * @param length the length
*/
private void generateDescriptions(int length) {
generatedDescriptions.put(length, new ArrayList());
diff --git a/components-core/src/main/java/org/dllearner/algorithms/SimpleSubclassLearner.java b/components-core/src/main/java/org/dllearner/algorithms/SimpleSubclassLearner.java
index 33b5a7b975..be54c7c17e 100644
--- a/components-core/src/main/java/org/dllearner/algorithms/SimpleSubclassLearner.java
+++ b/components-core/src/main/java/org/dllearner/algorithms/SimpleSubclassLearner.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2007-2011, Jens Lehmann
+ * Copyright (C) 2007 - 2016, Jens Lehmann
*
* This file is part of DL-Learner.
*
@@ -16,7 +16,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
package org.dllearner.algorithms;
import java.util.ArrayList;
@@ -70,7 +69,7 @@ public List> getCurrentlyBestEvaluatedAxioms(
@Override
public List getCurrentlyBestDescriptions(int nrOfDescriptions) {
- List bestDescriptions = new ArrayList();
+ List bestDescriptions = new ArrayList<>();
for (EvaluatedDescription extends Score> evDesc : getCurrentlyBestEvaluatedDescriptions(nrOfDescriptions)) {
bestDescriptions.add(evDesc.getDescription());
}
@@ -85,7 +84,7 @@ public List extends EvaluatedDescription extends Score>> getCurrentlyBestEva
@Override
public List getCurrentlyBestAxioms(int nrOfAxioms) {
- List bestAxioms = new ArrayList();
+ List bestAxioms = new ArrayList<>();
for (EvaluatedAxiom evAx : getCurrentlyBestEvaluatedAxioms(nrOfAxioms)) {
bestAxioms.add(evAx.getAxiom());
@@ -96,12 +95,12 @@ public List getCurrentlyBestAxioms(int nrOfAxioms) {
@Override
public List> getCurrentlyBestEvaluatedAxioms(int nrOfAxioms) {
- currentlyBestAxioms = new TreeSet>();
+ currentlyBestAxioms = new TreeSet<>();
for (EvaluatedDescription extends Score> ed : getCurrentlyBestEvaluatedDescriptions(nrOfAxioms)) {
- currentlyBestAxioms.add(new EvaluatedAxiom(df.getOWLSubClassOfAxiom(entityToDescribe,
+ currentlyBestAxioms.add(new EvaluatedAxiom<>(df.getOWLSubClassOfAxiom(entityToDescribe,
ed.getDescription()), new AxiomScore(ed.getAccuracy())));
}
- return new ArrayList>(currentlyBestAxioms);
+ return new ArrayList<>(currentlyBestAxioms);
}
@Override
@@ -129,7 +128,7 @@ protected void getExistingAxioms() {
//get existing super classes
SortedSet existingSuperClasses = reasoner.getSuperClasses(entityToDescribe);
if (!existingSuperClasses.isEmpty()) {
- SortedSet inferredSuperClasses = new TreeSet();
+ SortedSet inferredSuperClasses = new TreeSet<>();
for (OWLClassExpression assertedSup : existingSuperClasses) {
if (reasoner.isPrepared()) {
if (reasoner.getClassHierarchy().contains(assertedSup)) {
@@ -214,7 +213,7 @@ private boolean addIndividualsWithTypes(Map();
+ types = new TreeSet<>();
ind2Types.put(ind, types);
}
types.add(newType);
@@ -235,7 +234,7 @@ private boolean addIndividualsWithTypes(Map> individual2Types) {
currentlyBestEvaluatedDescriptions.clear();
- Map result = new HashMap();
+ Map result = new HashMap<>();
for (Entry> entry : individual2Types.entrySet()) {
for (OWLClassExpression nc : entry.getValue()) {
Integer cnt = result.get(nc);
diff --git a/components-core/src/main/java/org/dllearner/algorithms/celoe/CELOE.java b/components-core/src/main/java/org/dllearner/algorithms/celoe/CELOE.java
index f28086ae51..08e9663ded 100644
--- a/components-core/src/main/java/org/dllearner/algorithms/celoe/CELOE.java
+++ b/components-core/src/main/java/org/dllearner/algorithms/celoe/CELOE.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2007-2011, Jens Lehmann
+ * Copyright (C) 2007 - 2016, Jens Lehmann
*
* This file is part of DL-Learner.
*
@@ -16,27 +16,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
package org.dllearner.algorithms.celoe;
-import java.io.File;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import org.dllearner.core.AbstractCELA;
-import org.dllearner.core.AbstractClassExpressionLearningProblem;
-import org.dllearner.core.AbstractHeuristic;
-import org.dllearner.core.AbstractKnowledgeSource;
-import org.dllearner.core.AbstractReasonerComponent;
-import org.dllearner.core.ComponentAnn;
-import org.dllearner.core.ComponentInitException;
-import org.dllearner.core.EvaluatedDescription;
-import org.dllearner.core.Score;
+import com.google.common.collect.Sets;
+import com.jamonapi.Monitor;
+import com.jamonapi.MonitorFactory;
+import org.dllearner.core.*;
import org.dllearner.core.config.ConfigOption;
import org.dllearner.core.owl.ClassHierarchy;
import org.dllearner.core.owl.DatatypePropertyHierarchy;
@@ -50,70 +35,53 @@
import org.dllearner.reasoning.OWLAPIReasoner;
import org.dllearner.reasoning.ReasonerImplementation;
import org.dllearner.reasoning.SPARQLReasoner;
-import org.dllearner.refinementoperators.CustomHierarchyRefinementOperator;
-import org.dllearner.refinementoperators.CustomStartRefinementOperator;
-import org.dllearner.refinementoperators.LengthLimitedRefinementOperator;
-import org.dllearner.refinementoperators.OperatorInverter;
-import org.dllearner.refinementoperators.ReasoningBasedRefinementOperator;
-import org.dllearner.refinementoperators.RhoDRDown;
+import org.dllearner.refinementoperators.*;
import org.dllearner.utilities.Files;
import org.dllearner.utilities.Helper;
import org.dllearner.utilities.OWLAPIUtils;
-import org.dllearner.utilities.owl.ConceptTransformation;
-import org.dllearner.utilities.owl.EvaluatedDescriptionSet;
-import org.dllearner.utilities.owl.OWLAPIRenderers;
-import org.dllearner.utilities.owl.OWLClassExpressionMinimizer;
-import org.dllearner.utilities.owl.OWLClassExpressionUtils;
-import org.dllearner.utilities.owl.PropertyContext;
+import org.dllearner.utilities.TreeUtils;
+import org.dllearner.utilities.datastructures.SearchTree;
+import org.dllearner.utilities.owl.*;
import org.semanticweb.owlapi.apibinding.OWLManager;
-import org.semanticweb.owlapi.model.IRI;
-import org.semanticweb.owlapi.model.OWLClass;
-import org.semanticweb.owlapi.model.OWLClassExpression;
-import org.semanticweb.owlapi.model.OWLDataFactory;
-import org.semanticweb.owlapi.model.OWLIndividual;
-import org.semanticweb.owlapi.model.OWLNaryBooleanClassExpression;
-import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-
import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl;
-import com.google.common.collect.Sets;
-import com.jamonapi.Monitor;
-import com.jamonapi.MonitorFactory;
+import java.io.File;
+import java.util.*;
/**
* The CELOE (Class Expression Learner for Ontology Engineering) algorithm.
* It adapts and extends the standard supervised learning algorithm for the
- * ontology engineering use case.
+ * ontology engineering use case.
*
* @author Jens Lehmann
*
*/
+@SuppressWarnings("CloneDoesntCallSuperClone")
@ComponentAnn(name="CELOE", shortName="celoe", version=1.0, description="CELOE is an adapted and extended version of the OCEL algorithm applied for the ontology engineering use case. See http://jens-lehmann.org/files/2011/celoe.pdf for reference.")
public class CELOE extends AbstractCELA implements Cloneable{
- private static Logger logger = LoggerFactory.getLogger(CELOE.class);
- private static Marker sparql_debug = MarkerFactory.getMarker("SD");
+ private static final Logger logger = LoggerFactory.getLogger(CELOE.class);
+ private static final Marker sparql_debug = MarkerFactory.getMarker("SD");
private boolean isRunning = false;
- private boolean stop = false;
+ private boolean stop = false;
// private OEHeuristicStable heuristicStable = new OEHeuristicStable();
// private OEHeuristicRuntime heuristicRuntime = new OEHeuristicRuntime();
+ @ConfigOption(description = "the refinement operator instance to use")
private LengthLimitedRefinementOperator operator;
-
- // all nodes in the search tree (used for selecting most promising node)
- private TreeSet nodes;
+
+ private SearchTree searchTree;
@ConfigOption(name="heuristic", defaultValue="celoe_heuristic")
private AbstractHeuristic heuristic; // = new OEHeuristicRuntime();
- // root of search tree
- private OENode startNode;
// the class with which we start the refinement process
@ConfigOption(
name = "startClass",
@@ -146,7 +114,7 @@ public class CELOE extends AbstractCELA implements Cloneable{
// important parameters (non-config options but internal)
private double noise;
- private boolean filterFollowsFromKB = false;
+ private boolean filterFollowsFromKB = false;
// less important parameters
// forces that one solution cannot be subexpression of another expression; this option is useful to get diversity
@@ -176,7 +144,7 @@ public class CELOE extends AbstractCELA implements Cloneable{
@ConfigOption(name = "replaceSearchTree", defaultValue="false", description="specifies whether to replace the search tree in the log file after each run or append the new search tree")
private boolean replaceSearchTree = false;
- @ConfigOption(name = "maxNrOfResults", defaultValue="10", description="Sets the maximum number of results one is interested in. (Setting this to a lower value may increase performance as the learning algorithm has to store/evaluate/beautify less descriptions).")
+ @ConfigOption(name = "maxNrOfResults", defaultValue="10", description="Sets the maximum number of results one is interested in. (Setting this to a lower value may increase performance as the learning algorithm has to store/evaluate/beautify less descriptions).")
private int maxNrOfResults = 10;
@ConfigOption(name = "noisePercentage", defaultValue="0.0", description="the (approximated) percentage of noise within the examples")
@@ -194,9 +162,6 @@ public class CELOE extends AbstractCELA implements Cloneable{
@ConfigOption(name = "maxClassExpressionTestsAfterImprovement", defaultValue="0", description = "The maximum number of candidate hypothesis the algorithm is allowed after an improvement in accuracy (0 = no limit). The algorithm will stop afterwards. (The real number of tests can be slightly higher, because this criterion usually won't be checked after each single test.)")
private int maxClassExpressionTestsAfterImprovement = 0;
- @ConfigOption(defaultValue = "10", name = "maxExecutionTimeInSeconds", description = "maximum execution of the algorithm in seconds")
- private int maxExecutionTimeInSeconds = 10;
-
@ConfigOption(defaultValue = "0", name = "maxExecutionTimeInSecondsAfterImprovement", description = "maximum execution of the algorithm in seconds")
private int maxExecutionTimeInSecondsAfterImprovement = 0;
@@ -214,6 +179,7 @@ public class CELOE extends AbstractCELA implements Cloneable{
@SuppressWarnings("unused")
private long timeLastImprovement = 0;
+ @ConfigOption(defaultValue = "false", description = "whether to try and refine solutions which already have accuracy value of 1")
private boolean expandAccuracy100Nodes = false;
private double currentHighestAccuracy;
@@ -239,12 +205,12 @@ public CELOE(CELOE celoe){
setMaxClassExpressionTests(celoe.maxClassExpressionTests);
setMaxClassExpressionTestsAfterImprovement(celoe.maxClassExpressionTestsAfterImprovement);
setMaxDepth(celoe.maxDepth);
- setMaxExecutionTimeInSeconds(celoe.maxExecutionTimeInSeconds);
+ setMaxExecutionTimeInSeconds(celoe.getMaxExecutionTimeInSeconds());
setMaxExecutionTimeInSecondsAfterImprovement(celoe.maxExecutionTimeInSecondsAfterImprovement);
setMaxNrOfResults(celoe.maxNrOfResults);
setNoisePercentage(celoe.noisePercentage);
- RhoDRDown op = new RhoDRDown((RhoDRDown)celoe.operator);
+ LengthLimitedRefinementOperator op = new RhoDRDown((RhoDRDown)celoe.operator);
try {
op.init();
} catch (ComponentInitException e) {
@@ -269,7 +235,7 @@ public CELOE(AbstractClassExpressionLearningProblem problem, AbstractReasonerCom
}
public static Collection> supportedLearningProblems() {
- Collection> problems = new LinkedList>();
+ Collection> problems = new LinkedList<>();
problems.add(AbstractClassExpressionLearningProblem.class);
return problems;
}
@@ -277,22 +243,17 @@ public static Collection
public static String getName() {
return "CELOE";
}
-
+
@Override
public void init() throws ComponentInitException {
baseURI = reasoner.getBaseURI();
- prefixes = reasoner.getPrefixes();
+ prefixes = reasoner.getPrefixes();
if(maxExecutionTimeInSeconds != 0 && maxExecutionTimeInSecondsAfterImprovement != 0) {
maxExecutionTimeInSeconds = Math.min(maxExecutionTimeInSeconds, maxExecutionTimeInSecondsAfterImprovement);
}
- // compute used concepts/roles from allowed/ignored
- // concepts/roles
-
-
- // copy class hierarchy and modify it such that each class is only
- // reachable via a single path
+ // TODO add comment
ClassHierarchy classHierarchy = initClassHierarchy();
ObjectPropertyHierarchy objectPropertyHierarchy = initObjectPropertyHierarchy();
DatatypePropertyHierarchy datatypePropertyHierarchy = initDataPropertyHierarchy();
@@ -300,13 +261,22 @@ public void init() throws ComponentInitException {
// if no one injected a heuristic, we use a default one
if(heuristic == null) {
heuristic = new OEHeuristicRuntime();
+ heuristic.init();
}
minimizer = new OWLClassExpressionMinimizer(dataFactory, reasoner);
+ if (writeSearchTree) {
+ File f = new File(searchTreeFile);
+ if (f.getParentFile() != null) {
+ f.getParentFile().mkdirs();
+ }
+ Files.clearFile(f);
+ }
+
// start at owl:Thing by default
- if(startClass == null) {
- startClass = dataFactory.getOWLThing();
+ if (startClass == null) {
+ startClass = computeStartClass();
} else {
try {
this.startClass = OWLAPIUtils.classExpressionPropertyExpander(this.startClass, reasoner, dataFactory);
@@ -314,34 +284,7 @@ public void init() throws ComponentInitException {
logger.warn("Error parsing start class.", e);
logger.warn("Using owl:Thing instead.");
this.startClass = dataFactory.getOWLThing();
- }
- }
-
- // create a refinement operator and pass all configuration
- // variables to it
- if(operator == null) {
- // we use a default operator and inject the class hierarchy for now
- operator = new RhoDRDown();
- if(operator instanceof CustomStartRefinementOperator) {
- ((CustomStartRefinementOperator)operator).setStartClass(startClass);
- }
- if(operator instanceof ReasoningBasedRefinementOperator) {
- ((ReasoningBasedRefinementOperator)operator).setReasoner(reasoner);
- }
- operator.init();
- }
- if(operator instanceof CustomHierarchyRefinementOperator) {
- ((CustomHierarchyRefinementOperator)operator).setClassHierarchy(classHierarchy);
- ((CustomHierarchyRefinementOperator)operator).setObjectPropertyHierarchy(objectPropertyHierarchy);
- ((CustomHierarchyRefinementOperator)operator).setDataPropertyHierarchy(datatypePropertyHierarchy);
- }
-
- if(writeSearchTree) {
- File f = new File(searchTreeFile );
- if(f.getParentFile() != null){
- f.getParentFile().mkdirs();
}
- Files.clearFile(f);
}
bestEvaluatedDescriptions = new EvaluatedDescriptionSet(maxNrOfResults);
@@ -350,18 +293,11 @@ public void init() throws ComponentInitException {
// we put important parameters in class variables
noise = noisePercentage/100d;
-// System.out.println("noise " + noise);
-// maxDepth = configurator.getMaxDepth();
+
// (filterFollowsFromKB is automatically set to false if the problem
// is not a class learning problem
filterFollowsFromKB = filterDescriptionsFollowingFromKB && isClassLearningProblem;
-// Set concepts = operator.refine(Thing.instance, 5);
-// for(OWLClassExpression concept : concepts) {
-// System.out.println(concept);
-// }
-// System.out.println("refinements of thing: " + concepts.size());
-
// actions specific to ontology engineering
if(isClassLearningProblem) {
ClassLearningProblem problem = (ClassLearningProblem) learningProblem;
@@ -369,10 +305,100 @@ public void init() throws ComponentInitException {
isEquivalenceProblem = problem.isEquivalenceProblem();
examples = reasoner.getIndividuals(classToDescribe);
+ } else if(learningProblem instanceof PosOnlyLP) {
+ examples = ((PosOnlyLP)learningProblem).getPositiveExamples();
+ } else if(learningProblem instanceof PosNegLP) {
+ examples = Sets.union(((PosNegLP)learningProblem).getPositiveExamples(),((PosNegLP)learningProblem).getNegativeExamples());
+ }
+
+ // create a refinement operator and pass all configuration
+ // variables to it
+ if (operator == null) {
+ // we use a default operator and inject the class hierarchy for now
+ operator = new RhoDRDown();
+ ((CustomStartRefinementOperator) operator).setStartClass(startClass);
+ ((ReasoningBasedRefinementOperator) operator).setReasoner(reasoner);
+ operator.init();
+ }
+ if (operator instanceof CustomHierarchyRefinementOperator) {
+ ((CustomHierarchyRefinementOperator) operator).setClassHierarchy(classHierarchy);
+ ((CustomHierarchyRefinementOperator) operator).setObjectPropertyHierarchy(objectPropertyHierarchy);
+ ((CustomHierarchyRefinementOperator) operator).setDataPropertyHierarchy(datatypePropertyHierarchy);
+ }
+ }
+
+ @Override
+ public void start() {
+ stop = false;
+ isRunning = true;
+ reset();
+ nanoStartTime = System.nanoTime();
+
+ currentHighestAccuracy = 0.0;
+ OENode nextNode;
+
+ logger.info("start class:" + startClass);
+ addNode(startClass, null);
+
+ while (!terminationCriteriaSatisfied()) {
+ showIfBetterSolutionsFound();
+
+ // chose best node according to heuristics
+ nextNode = getNextNodeToExpand();
+ int horizExp = nextNode.getHorizontalExpansion();
+
+ // apply refinement operator
+ TreeSet refinements = refineNode(nextNode);
+
+ while(!refinements.isEmpty() && !terminationCriteriaSatisfied()) {
+ // pick element from set
+ OWLClassExpression refinement = refinements.pollFirst();
+
+ // get length of class expression
+ int length = OWLClassExpressionUtils.getLength(refinement);
+
+ // we ignore all refinements with lower length and too high depth
+ // (this also avoids duplicate node children)
+ if(length > horizExp && OWLClassExpressionUtils.getDepth(refinement) <= maxDepth) {
+ // add node to search tree
+ addNode(refinement, nextNode);
+ }
+ }
+
+ showIfBetterSolutionsFound();
- // start class: intersection of super classes for definitions (since it needs to
- // capture all instances), but owl:Thing for learning subclasses (since it is
- // superfluous to add super classes in this case)
+ // update the global min and max horizontal expansion values
+ updateMinMaxHorizExp(nextNode);
+
+ // write the search tree (if configured)
+ if (writeSearchTree) {
+ writeSearchTree(refinements);
+ }
+ }
+
+ if(singleSuggestionMode) {
+ bestEvaluatedDescriptions.add(bestDescription, bestAccuracy, learningProblem);
+ }
+
+ // print some stats
+ printAlgorithmRunStats();
+
+ // print solution(s)
+ logger.info("solutions:\n" + getSolutionString());
+
+ isRunning = false;
+ }
+
+ /*
+ * Compute the start class in the search space from which the refinement will start.
+ * We use the intersection of super classes for definitions (since it needs to
+ * capture all instances), but owl:Thing for learning subclasses (since it is
+ * superfluous to add super classes in this case)
+ */
+ private OWLClassExpression computeStartClass() {
+ OWLClassExpression startClass = dataFactory.getOWLThing();
+
+ if(isClassLearningProblem) {
if(isEquivalenceProblem) {
Set existingDefinitions = reasoner.getAssertedDefinitions(classToDescribe);
if(reuseExistingDescription && (existingDefinitions.size() > 0)) {
@@ -389,13 +415,13 @@ public void init() throws ComponentInitException {
}
}
- LinkedList startClassCandidates = new LinkedList();
+ LinkedList startClassCandidates = new LinkedList<>();
startClassCandidates.add(existingDefinition);
// hack for RhoDRDown
if(operator instanceof RhoDRDown) {
((RhoDRDown)operator).setDropDisjuncts(true);
}
- LengthLimitedRefinementOperator upwardOperator = (LengthLimitedRefinementOperator) new OperatorInverter(operator);
+ LengthLimitedRefinementOperator upwardOperator = new OperatorInverter(operator);
// use upward refinement until we find an appropriate start class
boolean startClassFound = false;
@@ -406,7 +432,7 @@ public void init() throws ComponentInitException {
// add upward refinements to list
Set refinements = upwardOperator.refine(candidate, OWLClassExpressionUtils.getLength(candidate));
// System.out.println("ref: " + refinements);
- LinkedList refinementList = new LinkedList(refinements);
+ LinkedList refinementList = new LinkedList<>(refinements);
// Collections.reverse(refinementList);
// System.out.println("list: " + refinementList);
startClassCandidates.addAll(refinementList);
@@ -423,10 +449,6 @@ public void init() throws ComponentInitException {
logger.info("Generalised existing class expression " + OWLAPIRenderers.toManchesterOWLSyntax(existingDefinition) + " to " + OWLAPIRenderers.toManchesterOWLSyntax(startClass) + ", which is used as start class for the learning algorithm.");
}
-// System.out.println("start class: " + startClass);
-// System.out.println("existing def: " + existingDefinition);
-// System.out.println(reasoner.getIndividuals(existingDefinition));
-
if(operator instanceof RhoDRDown) {
((RhoDRDown)operator).setDropDisjuncts(false);
}
@@ -441,92 +463,27 @@ public void init() throws ComponentInitException {
startClass = dataFactory.getOWLThing();
logger.warn(classToDescribe + " is equivalent to owl:Thing. Usually, it is not " +
"sensible to learn a class expression in this case.");
- }
- }
- }
- } else if(learningProblem instanceof PosOnlyLP) {
- examples = ((PosOnlyLP)learningProblem).getPositiveExamples();
- } else if(learningProblem instanceof PosNegLP) {
- examples = Helper.union(((PosNegLP)learningProblem).getPositiveExamples(),((PosNegLP)learningProblem).getNegativeExamples());
- }
- }
-
- @Override
- public void start() {
- stop = false;
- isRunning = true;
- reset();
- nanoStartTime = System.nanoTime();
-
- currentHighestAccuracy = 0.0;
- OENode nextNode;
-
- logger.info("start class:" + startClass);
- addNode(startClass, null);
-
- while (!terminationCriteriaSatisfied()) {
- showIfBetterSolutionsFound();
-
- // chose best node according to heuristics
- nextNode = getNextNodeToExpand();
- int horizExp = nextNode.getHorizontalExpansion();
-
- // apply refinement operator
- TreeSet refinements = refineNode(nextNode);
-
- while(!refinements.isEmpty() && !terminationCriteriaSatisfied()) {
- // pick element from set
- OWLClassExpression refinement = refinements.pollFirst();
-
- // get length of class expression
- int length = OWLClassExpressionUtils.getLength(refinement);
-
- // we ignore all refinements with lower length and too high depth
- // (this also avoids duplicate node children)
- if(length > horizExp && OWLClassExpressionUtils.getDepth(refinement) <= maxDepth) {
- // add node to search tree
- addNode(refinement, nextNode);
+ }
}
}
-
- showIfBetterSolutionsFound();
-
- // update the global min and max horizontal expansion values
- updateMinMaxHorizExp(nextNode);
-
- // write the search tree (if configured)
- if (writeSearchTree) {
- writeSearchTree(refinements);
- }
}
-
- if(singleSuggestionMode) {
- bestEvaluatedDescriptions.add(bestDescription, bestAccuracy, learningProblem);
- }
-
- // print some stats
- printAlgorithmRunStats();
-
- // print solution(s)
- logger.info("solutions:\n" + getSolutionString());
-
- isRunning = false;
+ return startClass;
}
private OENode getNextNodeToExpand() {
// we expand the best node of those, which have not achieved 100% accuracy
// already and have a horizontal expansion equal to their length
// (rationale: further extension is likely to add irrelevant syntactical constructs)
- Iterator it = nodes.descendingIterator();
- if (logger.isDebugEnabled()) {
- for (OENode N:nodes) {
- logger.debug(sparql_debug,"`getnext:"+N);
+ Iterator it = searchTree.descendingIterator();
+ if (logger.isTraceEnabled()) {
+ for (OENode N:searchTree.getNodeSet()) {
+ logger.trace(sparql_debug,"`getnext:"+N);
}
}
while(it.hasNext()) {
OENode node = it.next();
- logger.debug(sparql_debug,"``"+node+node.getAccuracy());
+ logger.trace(sparql_debug,"``"+node+node.getAccuracy());
if (isExpandAccuracy100Nodes() && node.getHorizontalExpansion() < OWLClassExpressionUtils.getLength(node.getDescription())) {
return node;
} else {
@@ -538,24 +495,24 @@ private OENode getNextNodeToExpand() {
// this should practically never be called, since for any reasonable learning
// task, we will always have at least one node with less than 100% accuracy
- return null;//nodes.last();
+ throw new RuntimeException("CELOE could not find any node with lesser accuracy.");
}
// expand node horizontically
private TreeSet refineNode(OENode node) {
- logger.debug(sparql_debug,"REFINE NODE " + node);
+ logger.trace(sparql_debug,"REFINE NODE " + node);
MonitorFactory.getTimeMonitor("refineNode").start();
// we have to remove and add the node since its heuristic evaluation changes through the expansion
// (you *must not* include any criteria in the heuristic which are modified outside of this method,
// otherwise you may see rarely occurring but critical false ordering in the nodes set)
- nodes.remove(node);
+ searchTree.updatePrepare(node);
int horizExp = node.getHorizontalExpansion();
TreeSet refinements = (TreeSet) operator.refine(node.getDescription(), horizExp+1);
// System.out.println("refinements: " + refinements);
node.incHorizontalExpansion();
node.setRefinementCount(refinements.size());
// System.out.println("refined node: " + node);
- nodes.add(node);
+ searchTree.updateDone(node);
MonitorFactory.getTimeMonitor("refineNode").stop();
return refinements;
}
@@ -566,33 +523,33 @@ private TreeSet refineNode(OENode node) {
*/
private boolean addNode(OWLClassExpression description, OENode parentNode) {
String sparql_debug_out = "";
- if (logger.isDebugEnabled()) sparql_debug_out = "DESC: " + description;
+ if (logger.isTraceEnabled()) sparql_debug_out = "DESC: " + description;
MonitorFactory.getTimeMonitor("addNode").start();
// redundancy check (return if redundant)
boolean nonRedundant = descriptions.add(description);
if(!nonRedundant) {
- logger.debug(sparql_debug, sparql_debug_out + "REDUNDANT");
+ logger.trace(sparql_debug, sparql_debug_out + "REDUNDANT");
return false;
}
// check whether the class expression is allowed
if(!isDescriptionAllowed(description, parentNode)) {
- logger.debug(sparql_debug, sparql_debug_out + "NOT ALLOWED");
+ logger.trace(sparql_debug, sparql_debug_out + "NOT ALLOWED");
return false;
}
// quality of class expression (return if too weak)
Monitor mon = MonitorFactory.start("lp");
- logger.debug(sparql_debug, sparql_debug_out);
+ logger.trace(sparql_debug, sparql_debug_out);
double accuracy = learningProblem.getAccuracyOrTooWeak(description, noise);
- logger.debug(sparql_debug, "`acc:"+accuracy);
+ logger.trace(sparql_debug, "`acc:"+accuracy);
mon.stop();
// issue a warning if accuracy is not between 0 and 1 or -1 (too weak)
if(accuracy > 1.0 || (accuracy < 0.0 && accuracy != -1)) {
- logger.warn("Invalid accuracy value " + accuracy + " for class expression " + description + ". This could be caused by a bug in the heuristic measure and should be reported to the DL-Learner bug tracker.");
- System.exit(0);
+ throw new RuntimeException("Invalid accuracy value " + accuracy + " for class expression " + description +
+ ". This could be caused by a bug in the heuristic measure and should be reported to the DL-Learner bug tracker.");
}
expressionTests++;
@@ -602,15 +559,8 @@ private boolean addNode(OWLClassExpression description, OENode parentNode) {
return false;
}
- OENode node = new OENode(parentNode, description, accuracy);
-
- // link to parent (unless start node)
- if(parentNode == null) {
- startNode = node;
- } else {
- parentNode.addChild(node);
- }
- nodes.add(node);
+ OENode node = new OENode(description, accuracy);
+ searchTree.addNode(parentNode, node);
// in some cases (e.g. mutation) fully evaluating even a single class expression is too expensive
// due to the high number of examples -- so we just stick to the approximate accuracy
@@ -618,37 +568,35 @@ private boolean addNode(OWLClassExpression description, OENode parentNode) {
if(accuracy > bestAccuracy) {
bestAccuracy = accuracy;
bestDescription = description;
- logger.info("more accurate (" + dfPercent.format(bestAccuracy) + ") class expression found: " + descriptionToString(bestDescription)); // + getTemporaryString(bestDescription));
+ logger.info("more accurate (" + dfPercent.format(bestAccuracy) + ") class expression found: " + descriptionToString(bestDescription)); // + getTemporaryString(bestDescription));
}
return true;
- }
+ }
// maybe add to best descriptions (method keeps set size fixed);
// we need to make sure that this does not get called more often than
// necessary since rewriting is expensive
boolean isCandidate = !bestEvaluatedDescriptions.isFull();
if(!isCandidate) {
- EvaluatedDescription worst = bestEvaluatedDescriptions.getWorst();
+ EvaluatedDescription extends Score> worst = bestEvaluatedDescriptions.getWorst();
double accThreshold = worst.getAccuracy();
- isCandidate =
+ isCandidate =
(accuracy > accThreshold ||
(accuracy >= accThreshold && OWLClassExpressionUtils.getLength(description) < worst.getDescriptionLength()));
}
if(isCandidate) {
OWLClassExpression niceDescription = rewrite(node.getExpression());
- ConceptTransformation.transformToOrderedForm(niceDescription);
-
+
if(niceDescription.equals(classToDescribe)) {
return false;
}
-// System.err.println(node);System.out.println(niceDescription);
if(!isDescriptionAllowed(niceDescription, node)) {
return false;
}
- // another test: none of the other suggested descriptions should be
+ // another test: none of the other suggested descriptions should be
// a subdescription of this one unless accuracy is different
// => comment: on the one hand, this appears to be too strict, because once A is a solution then everything containing
// A is not a candidate; on the other hand this suppresses many meaningless extensions of A
@@ -660,7 +608,7 @@ private boolean addNode(OWLClassExpression description, OENode parentNode) {
shorterDescriptionExists = true;
break;
}
- }
+ }
}
// System.out.println("shorter description? " + shorterDescriptionExists + " nice: " + niceDescription);
@@ -680,7 +628,7 @@ private boolean addNode(OWLClassExpression description, OENode parentNode) {
}
return true;
- }
+ }
// checks whether the class expression is allowed
private boolean isDescriptionAllowed(OWLClassExpression description, OENode parentNode) {
@@ -696,7 +644,7 @@ private boolean isDescriptionAllowed(OWLClassExpression description, OENode pare
} else {
// none of the superclasses of the class to learn must appear on the
// outermost property level
- TreeSet toTest = new TreeSet();
+ TreeSet toTest = new TreeSet<>();
toTest.add(classToDescribe);
while(!toTest.isEmpty()) {
OWLClassExpression d = toTest.pollFirst();
@@ -705,13 +653,13 @@ private boolean isDescriptionAllowed(OWLClassExpression description, OENode pare
}
toTest.addAll(reasoner.getClassHierarchy().getSuperClasses(d));
}
- }
+ }
} else if (learningProblem instanceof ClassAsInstanceLearningProblem) {
return true;
}
// perform forall sanity tests
- if (parentNode != null &&
+ if (parentNode != null &&
(ConceptTransformation.getForallOccurences(description) > ConceptTransformation.getForallOccurences(parentNode.getDescription()))) {
// we have an additional \forall construct, so we now fetch the contexts
// in which it occurs
@@ -745,7 +693,7 @@ private boolean isDescriptionAllowed(OWLClassExpression description, OENode pare
return false;
}
}
- }
+ }
// we do not want to have negations of sibling classes on the outermost level
// (they are expressed more naturally by saying that the siblings are disjoint,
@@ -759,14 +707,10 @@ private boolean isDescriptionAllowed(OWLClassExpression description, OENode pare
// determine whether a named class occurs on the outermost level, i.e. property depth 0
// (it can still be at higher depth, e.g. if intersections are nested in unions)
private boolean occursOnFirstLevel(OWLClassExpression description, OWLClassExpression cls) {
- if(cls.isOWLThing()) {
- return false;
- }
- return (description instanceof OWLNaryBooleanClassExpression &&
- ((OWLNaryBooleanClassExpression)description).getOperands().contains(cls));
+ return !cls.isOWLThing() && (description instanceof OWLNaryBooleanClassExpression && ((OWLNaryBooleanClassExpression) description).getOperands().contains(cls));
// return description.containsConjunct(cls) ||
// (description instanceof OWLObjectUnionOf && ((OWLObjectUnionOf) description).getOperands().contains(cls));
- }
+ }
// determine whether a named class occurs on the outermost level, i.e. property depth 0
// (it can still be at higher depth, e.g. if intersections are nested in unions)
@@ -774,9 +718,9 @@ private boolean occursOnSecondLevel(OWLClassExpression description, OWLClassExpr
// SortedSet superClasses = reasoner.getSuperClasses(cls);
// if(description instanceof OWLObjectIntersectionOf) {
// List operands = ((OWLObjectIntersectionOf) description).getOperandsAsList();
-//
+//
// for (OWLClassExpression op : operands) {
-// if(superClasses.contains(op) ||
+// if(superClasses.contains(op) ||
// (op instanceof OWLObjectUnionOf && !Sets.intersection(((OWLObjectUnionOf)op).getOperands(),superClasses).isEmpty())) {
// for (OWLClassExpression op2 : operands) {
// if((op2 instanceof OWLObjectUnionOf && ((OWLObjectUnionOf)op2).getOperands().contains(cls))) {
@@ -785,7 +729,7 @@ private boolean occursOnSecondLevel(OWLClassExpression description, OWLClassExpr
// }
// }
// }
-//
+//
// for (OWLClassExpression op1 : operands) {
// for (OWLClassExpression op2 : operands) {
// if(!op1.isAnonymous() && op2 instanceof OWLObjectUnionOf) {
@@ -809,12 +753,12 @@ private boolean occursOnSecondLevel(OWLClassExpression description, OWLClassExpr
}
private boolean terminationCriteriaSatisfied() {
- return
- stop ||
+ return
+ stop ||
(maxClassExpressionTestsAfterImprovement != 0 && (expressionTests - expressionTestCountLastImprovement >= maxClassExpressionTestsAfterImprovement)) ||
(maxClassExpressionTests != 0 && (expressionTests >= maxClassExpressionTests)) ||
- (maxExecutionTimeInSecondsAfterImprovement != 0 && ((System.nanoTime() - nanoStartTime) >= (maxExecutionTimeInSecondsAfterImprovement*1000000000l))) ||
- (maxExecutionTimeInSeconds != 0 && ((System.nanoTime() - nanoStartTime) >= (maxExecutionTimeInSeconds*1000000000l))) ||
+ (maxExecutionTimeInSecondsAfterImprovement != 0 && ((System.nanoTime() - nanoStartTime) >= (maxExecutionTimeInSecondsAfterImprovement* 1000000000L))) ||
+ (maxExecutionTimeInSeconds != 0 && ((System.nanoTime() - nanoStartTime) >= (maxExecutionTimeInSeconds* 1000000000L))) ||
(terminateOnNoiseReached && (100*getCurrentlyBestAccuracy()>=100-noisePercentage)) ||
(stopOnFirstDefinition && (getCurrentlyBestAccuracy() >= 1));
}
@@ -822,18 +766,18 @@ private boolean terminationCriteriaSatisfied() {
private void reset() {
// set all values back to their default values (used for running
// the algorithm more than once)
- nodes = new TreeSet(heuristic);
- descriptions = new TreeSet();
+ searchTree = new SearchTree<>(heuristic);
+ descriptions = new TreeSet<>();
bestEvaluatedDescriptions.getSet().clear();
expressionTests = 0;
}
private void printAlgorithmRunStats() {
if (stop) {
- logger.info("Algorithm stopped ("+expressionTests+" descriptions tested). " + nodes.size() + " nodes in the search tree.\n");
+ logger.info("Algorithm stopped ("+expressionTests+" descriptions tested). " + searchTree.size() + " nodes in the search tree.\n");
} else {
totalRuntimeNs = System.nanoTime()-nanoStartTime;
- logger.info("Algorithm terminated successfully (time: " + Helper.prettyPrintNanoSeconds(totalRuntimeNs) + ", "+expressionTests+" descriptions tested, " + nodes.size() + " nodes in the search tree).\n");
+ logger.info("Algorithm terminated successfully (time: " + Helper.prettyPrintNanoSeconds(totalRuntimeNs) + ", "+expressionTests+" descriptions tested, " + searchTree.size() + " nodes in the search tree).\n");
logger.info(reasoner.toString());
}
}
@@ -857,7 +801,7 @@ private void writeSearchTree(TreeSet refinements) {
treeString.append(" ").append(ref).append("\n");
}
}
- treeString.append(startNode.toTreeString(baseURI, prefixes)).append("\n");
+ treeString.append(TreeUtils.toTreeString(searchTree, baseURI, prefixes)).append("\n");
// replace or append
if (replaceSearchTree) {
@@ -877,13 +821,13 @@ private void updateMinMaxHorizExp(OENode node) {
// we need to check whether it was the last one
if(minHorizExp == newHorizExp - 1) {
- // the best accuracy that a node can achieve
+ // the best accuracy that a node can achieve
double scoreThreshold = heuristic.getNodeScore(node) + 1 - node.getAccuracy();
- for(OENode n : nodes.descendingSet()) {
+ for(OENode n : searchTree.descendingSet()) {
if(n != node) {
if(n.getHorizontalExpansion() == minHorizExp) {
- // we can stop instantly when another node with min.
+ // we can stop instantly when another node with min.
return;
}
if(heuristic.getNodeScore(n) < scoreThreshold) {
@@ -912,14 +856,14 @@ public List getCurrentlyBestDescriptions() {
}
@Override
- public EvaluatedDescription getCurrentlyBestEvaluatedDescription() {
+ public EvaluatedDescription extends Score> getCurrentlyBestEvaluatedDescription() {
return bestEvaluatedDescriptions.getBest();
- }
+ }
@Override
- public TreeSet extends EvaluatedDescription extends Score>> getCurrentlyBestEvaluatedDescriptions() {
+ public NavigableSet extends EvaluatedDescription extends Score>> getCurrentlyBestEvaluatedDescriptions() {
return bestEvaluatedDescriptions.getSet();
- }
+ }
public double getCurrentlyBestAccuracy() {
return bestEvaluatedDescriptions.getBest().getAccuracy();
@@ -928,21 +872,13 @@ public double getCurrentlyBestAccuracy() {
@Override
public boolean isRunning() {
return isRunning;
- }
+ }
@Override
public void stop() {
stop = true;
}
- public OENode getSearchTreeRoot() {
- return startNode;
- }
-
- public TreeSet getNodes() {
- return nodes;
- }
-
public int getMaximumHorizontalExpansion() {
return maxHorizExp;
}
@@ -1023,22 +959,6 @@ public void setReplaceSearchTree(boolean replaceSearchTree) {
this.replaceSearchTree = replaceSearchTree;
}
- public int getMaxClassDescriptionTests() {
- return maxClassExpressionTests;
- }
-
- public void setMaxClassDescriptionTests(int maxClassDescriptionTests) {
- this.maxClassExpressionTests = maxClassDescriptionTests;
- }
-
- public int getMaxExecutionTimeInSeconds() {
- return maxExecutionTimeInSeconds;
- }
-
- public void setMaxExecutionTimeInSeconds(int maxExecutionTimeInSeconds) {
- this.maxExecutionTimeInSeconds = maxExecutionTimeInSeconds;
- }
-
public boolean isTerminateOnNoiseReached() {
return terminateOnNoiseReached;
}
@@ -1064,15 +984,6 @@ public void setHeuristic(AbstractHeuristic heuristic) {
this.heuristic = heuristic;
}
- public int getMaxClassExpressionTestsWithoutImprovement() {
- return maxClassExpressionTestsAfterImprovement;
- }
-
- public void setMaxClassExpressionTestsWithoutImprovement(
- int maxClassExpressionTestsWithoutImprovement) {
- this.maxClassExpressionTestsAfterImprovement = maxClassExpressionTestsWithoutImprovement;
- }
-
public int getMaxExecutionTimeInSecondsAfterImprovement() {
return maxExecutionTimeInSecondsAfterImprovement;
}
@@ -1080,7 +991,7 @@ public int getMaxExecutionTimeInSecondsAfterImprovement() {
public void setMaxExecutionTimeInSecondsAfterImprovement(
int maxExecutionTimeInSecondsAfterImprovement) {
this.maxExecutionTimeInSecondsAfterImprovement = maxExecutionTimeInSecondsAfterImprovement;
- }
+ }
public boolean isSingleSuggestionMode() {
return singleSuggestionMode;
@@ -1196,7 +1107,7 @@ public static void main(String[] args) throws Exception{
df.getOWLThing())
),
df.getOWLObjectAllValuesFrom(
- df.getOWLObjectProperty(IRI.create("http://example.com/father#hasChild")),
+ df.getOWLObjectProperty(IRI.create("http://example.com/father#hasChild")),
df.getOWLThing()
)
);
diff --git a/components-core/src/main/java/org/dllearner/algorithms/celoe/OEHeuristicRuntime.java b/components-core/src/main/java/org/dllearner/algorithms/celoe/OEHeuristicRuntime.java
index 8fba820f61..ccfbe6301d 100644
--- a/components-core/src/main/java/org/dllearner/algorithms/celoe/OEHeuristicRuntime.java
+++ b/components-core/src/main/java/org/dllearner/algorithms/celoe/OEHeuristicRuntime.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2007-2011, Jens Lehmann
+ * Copyright (C) 2007 - 2016, Jens Lehmann
*
* This file is part of DL-Learner.
*
@@ -16,7 +16,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
package org.dllearner.algorithms.celoe;
import org.dllearner.core.AbstractHeuristic;
@@ -36,12 +35,12 @@
public class OEHeuristicRuntime extends AbstractHeuristic{
- // strong penalty for long descriptions
+ @ConfigOption(description = "penalty for long descriptions (horizontal expansion) (strong by default)", defaultValue = "0.1")
private double expansionPenaltyFactor = 0.1;
- // bonus for being better than parent node
+ @ConfigOption(description = "bonus for being better than parent node", defaultValue = "0.3")
private double gainBonusFactor = 0.3;
- // penalty if a node OWLClassExpression has very many refinements since exploring
- // such a node is computationally very expensive
+ @ConfigOption(description = "penalty if a node OWLClassExpression has very many refinements since exploring such a node is computationally very expensive",
+ defaultValue = "0.0001")
private double nodeRefinementPenalty = 0.0001;
@ConfigOption(name = "startNodeBonus", defaultValue="0.1")
@@ -54,8 +53,9 @@ public OEHeuristicRuntime() {
@Override
public void init() throws ComponentInitException {
- }
+ }
+ @Override
public double getNodeScore(OENode node) {
// accuracy as baseline
double score = node.getAccuracy();
@@ -106,5 +106,4 @@ public void setStartNodeBonus(double startNodeBonus) {
this.startNodeBonus = startNodeBonus;
}
-
}
\ No newline at end of file
diff --git a/components-core/src/main/java/org/dllearner/algorithms/celoe/OENode.java b/components-core/src/main/java/org/dllearner/algorithms/celoe/OENode.java
index 0882c76f61..82d5b2f3a5 100644
--- a/components-core/src/main/java/org/dllearner/algorithms/celoe/OENode.java
+++ b/components-core/src/main/java/org/dllearner/algorithms/celoe/OENode.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2007-2011, Jens Lehmann
+ * Copyright (C) 2007 - 2016, Jens Lehmann
*
* This file is part of DL-Learner.
*
@@ -16,15 +16,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
package org.dllearner.algorithms.celoe;
import java.text.DecimalFormat;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
-import org.dllearner.algorithms.SearchTreeNode;
+import org.dllearner.core.AbstractSearchTreeNode;
+import org.dllearner.utilities.datastructures.SearchTreeNode;
import org.dllearner.utilities.owl.OWLAPIRenderers;
import org.dllearner.utilities.owl.OWLClassExpressionUtils;
import org.semanticweb.owlapi.model.OWLClassExpression;
@@ -38,23 +36,20 @@
* - only evaluated nodes are stored
* - too weak nodes are not stored
* - redundant nodes are not stored (?)
- * - only accuracy is stored to make the node structure reusable for different
+ * - only accuracy is stored to make the node structure reusable for different
* learning problems and -algorithms
*
* @author Jens Lehmann
*
*/
-public class OENode implements SearchTreeNode {
+public class OENode extends AbstractSearchTreeNode implements SearchTreeNode {
protected OWLClassExpression description;
protected double accuracy;
protected int horizontalExpansion;
-
- protected OENode parent;
- protected List children = new LinkedList();
-
+
// the refinement count corresponds to the number of refinements of the
// OWLClassExpression in this node - it is a better heuristic indicator than child count
// (and avoids the problem that adding children changes the heuristic value)
@@ -62,16 +57,16 @@ public class OENode implements SearchTreeNode {
private static DecimalFormat dfPercent = new DecimalFormat("0.00%");
- public OENode(OENode parentNode, OWLClassExpression description, double accuracy) {
- this.parent = parentNode;
+ public OENode(OWLClassExpression description, double accuracy) {
this.description = description;
this.accuracy = accuracy;
- horizontalExpansion = OWLClassExpressionUtils.getLength(description) - 1;
- }
-
- public void addChild(OENode node) {
- children.add(node);
+ this.horizontalExpansion = OWLClassExpressionUtils.getLength(description) - 1;
}
+
+// public OENode(OENode parentNode, OWLClassExpression description, double accuracy) {
+// this(description, accuracy);
+// this.setParent(parentNode);
+// }
public void incHorizontalExpansion() {
horizontalExpansion++;
@@ -88,9 +83,10 @@ public OWLClassExpression getDescription() {
return description;
}
+ @Override
public OWLClassExpression getExpression() {
return getDescription();
- }
+ }
/**
* @return the accuracy
@@ -99,20 +95,6 @@ public double getAccuracy() {
return accuracy;
}
- /**
- * @return the parent
- */
- public OENode getParent() {
- return parent;
- }
-
- /**
- * @return the children
- */
- public List getChildren() {
- return children;
- }
-
/**
* @return the horizontalExpansion
*/
@@ -139,44 +121,6 @@ public String getShortDescription(String baseURI, Map prefixes)
public String toString() {
return getShortDescription(null);
}
-
- public String toTreeString() {
- return toTreeString(0, null).toString();
- }
-
- public String toTreeString(String baseURI) {
- return toTreeString(0, baseURI).toString();
- }
-
- public String toTreeString(String baseURI, Map prefixes) {
- return toTreeString(0, baseURI, prefixes).toString();
- }
-
- private StringBuilder toTreeString(int depth, String baseURI) {
- StringBuilder treeString = new StringBuilder();
- for(int i=0; i ");
- treeString.append(getShortDescription(baseURI)+"\n");
- for(OENode child : children) {
- treeString.append(child.toTreeString(depth+1,baseURI));
- }
- return treeString;
- }
-
- private StringBuilder toTreeString(int depth, String baseURI, Map prefixes) {
- StringBuilder treeString = new StringBuilder();
- for(int i=0; i ");
- treeString.append(getShortDescription(baseURI, prefixes)+"\n");
- for(OENode child : children) {
- treeString.append(child.toTreeString(depth+1,baseURI,prefixes));
- }
- return treeString;
- }
/**
* @return the refinementCount
diff --git a/components-core/src/main/java/org/dllearner/algorithms/celoe/PCELOE.java b/components-core/src/main/java/org/dllearner/algorithms/celoe/PCELOE.java
new file mode 100644
index 0000000000..760a40ec8d
--- /dev/null
+++ b/components-core/src/main/java/org/dllearner/algorithms/celoe/PCELOE.java
@@ -0,0 +1,1221 @@
+/**
+ * Copyright (C) 2007 - 2016, Jens Lehmann
+ *
+ * This file is part of DL-Learner.
+ *
+ * DL-Learner is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DL-Learner is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.dllearner.algorithms.celoe;
+
+import com.google.common.collect.Sets;
+import com.jamonapi.Monitor;
+import com.jamonapi.MonitorFactory;
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.dllearner.core.*;
+import org.dllearner.core.config.ConfigOption;
+import org.dllearner.core.owl.ClassHierarchy;
+import org.dllearner.core.owl.DatatypePropertyHierarchy;
+import org.dllearner.core.owl.ObjectPropertyHierarchy;
+import org.dllearner.kb.OWLFile;
+import org.dllearner.learningproblems.ClassAsInstanceLearningProblem;
+import org.dllearner.learningproblems.ClassLearningProblem;
+import org.dllearner.learningproblems.PosNegLP;
+import org.dllearner.learningproblems.PosOnlyLP;
+import org.dllearner.reasoning.ClosedWorldReasoner;
+import org.dllearner.reasoning.SPARQLReasoner;
+import org.dllearner.refinementoperators.*;
+import org.dllearner.utilities.Files;
+import org.dllearner.utilities.Helper;
+import org.dllearner.utilities.OWLAPIUtils;
+import org.dllearner.utilities.TreeUtils;
+import org.dllearner.utilities.datastructures.SynchronizedSearchTree;
+import org.dllearner.utilities.owl.*;
+import org.semanticweb.owlapi.model.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl;
+
+import java.io.File;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * The PCELOE is an experimental, parallel implementation of the CELOE algorithm.
+ *
+ * @author Lorenz Buehmann
+ *
+ */
+@ComponentAnn(name="PCELOE", shortName="pceloe", version=1.0, description="PCELOE is an experimental, parallel implementation of the CELOE algorithm.")
+public class PCELOE extends AbstractCELA {
+
+ private static Logger logger = Logger.getLogger(PCELOE.class);
+
+ private boolean isRunning = false;
+ private boolean stop = false;
+
+ @ConfigOption(description = "the refinement operator instance to use")
+ private LengthLimitedRefinementOperator operator;
+
+ private SynchronizedSearchTree searchTree;
+ @ConfigOption(name="heuristic", defaultValue="celoe_heuristic")
+ private AbstractHeuristic heuristic;
+ // the class with which we start the refinement process
+ @ConfigOption(name = "startClass", defaultValue="owl:Thing", description="You can specify a start class for the algorithm. To do this, you have to use Manchester OWL syntax without using prefixes.")
+ private OWLClassExpression startClass;
+
+ // all descriptions in the search tree plus those which were too weak (for fast redundancy check)
+// private TreeSet descriptions;
+ private SortedSet descriptions;
+
+
+ // if true, then each solution is evaluated exactly instead of approximately
+ // private boolean exactBestDescriptionEvaluation = false;
+ @ConfigOption(name = "singleSuggestionMode", defaultValue="false", description="Use this if you are interested in only one suggestion and your learning problem has many (more than 1000) examples.")
+ private boolean singleSuggestionMode;
+ private OWLClassExpression bestDescription;
+ private double bestAccuracy = Double.MIN_VALUE;
+
+ private OWLClass classToDescribe;
+ // examples are either 1.) instances of the class to describe 2.) positive examples
+ // 3.) union of pos.+neg. examples depending on the learning problem at hand
+ private Set examples;
+
+ // CELOE was originally created for learning classes in ontologies, but also
+ // works for other learning problem types
+ private boolean isClassLearningProblem;
+ private boolean isEquivalenceProblem;
+
+ private long nanoStartTime;
+
+ // important parameters (non-config options but internal)
+ private double noise;
+
+ private boolean filterFollowsFromKB;
+
+ // less important parameters
+ // forces that one solution cannot be subexpression of another expression; this option is useful to get diversity
+ // but it can also suppress quite useful expressions
+ private boolean forceMutualDifference = false;
+
+
+ // statistical variables
+ private int expressionTests = 0;
+ private int minHorizExp = 0;
+ private int maxHorizExp = 0;
+ private long totalRuntimeNs = 0;
+
+ // TODO: turn those into config options
+
+ // important: do not initialise those with empty sets
+ // null = no settings for allowance / ignorance
+ // empty set = allow / ignore nothing (it is often not desired to allow no class!)
+ Set allowedConcepts = null;
+ Set ignoredConcepts = null;
+
+ // important: do not initialise those with empty sets
+ // null = no settings for allowance / ignorance
+ // empty set = allow / ignore nothing (it is often not desired to allow no class!)
+ @ConfigOption(name = "writeSearchTree", defaultValue="false", description="specifies whether to write a search tree")
+ private boolean writeSearchTree = false;
+
+ @ConfigOption(name = "searchTreeFile", defaultValue="log/searchTree.txt", description="file to use for the search tree")
+ private String searchTreeFile = "log/searchTree.txt";
+
+ @ConfigOption(name = "replaceSearchTree", defaultValue="false", description="specifies whether to replace the search tree in the log file after each run or append the new search tree")
+ private boolean replaceSearchTree = false;
+
+ @ConfigOption(name = "maxNrOfResults", defaultValue="10", description="Sets the maximum number of results one is interested in. (Setting this to a lower value may increase performance as the learning algorithm has to store/evaluate/beautify less descriptions).")
+ private int maxNrOfResults = 10;
+
+ @ConfigOption(name = "noisePercentage", defaultValue="0.0", description="the (approximated) percentage of noise within the examples")
+ private double noisePercentage = 0.0;
+
+ @ConfigOption(name = "filterDescriptionsFollowingFromKB", defaultValue="false", description="If true, then the results will not contain suggestions, which already follow logically from the knowledge base. Be careful, since this requires a potentially expensive consistency check for candidate solutions.")
+ private boolean filterDescriptionsFollowingFromKB = false;
+
+ @ConfigOption(name = "reuseExistingDescription", defaultValue="false", description="If true, the algorithm tries to find a good starting point close to an existing definition/super class of the given class in the knowledge base.")
+ private boolean reuseExistingDescription = false;
+
+ @ConfigOption(name = "maxClassExpressionTests", defaultValue="0", description="The maximum number of candidate hypothesis the algorithm is allowed to test (0 = no limit). The algorithm will stop afterwards. (The real number of tests can be slightly higher, because this criterion usually won't be checked after each single test.)")
+ private int maxClassExpressionTests = 0;
+
+ @ConfigOption(name = "maxClassExpressionTestsAfterImprovement", defaultValue="0", description = "The maximum number of candidate hypothesis the algorithm is allowed after an improvement in accuracy (0 = no limit). The algorithm will stop afterwards. (The real number of tests can be slightly higher, because this criterion usually won't be checked after each single test.)")
+ private int maxClassExpressionTestsAfterImprovement = 0;
+
+ @ConfigOption(defaultValue = "10", name = "maxExecutionTimeInSeconds", description = "maximum execution of the algorithm in seconds")
+ private int maxExecutionTimeInSeconds = 10;
+
+ @ConfigOption(defaultValue = "0", name = "maxExecutionTimeInSecondsAfterImprovement", description = "maximum execution of the algorithm in seconds")
+ private int maxExecutionTimeInSecondsAfterImprovement = 0;
+
+ @ConfigOption(name = "terminateOnNoiseReached", defaultValue="false", description="specifies whether to terminate when noise criterion is met")
+ private boolean terminateOnNoiseReached = false;
+
+ @ConfigOption(name = "maxDepth", defaultValue="7", description="maximum depth of description")
+ private double maxDepth = 7;
+
+ @ConfigOption(name = "stopOnFirstDefinition", defaultValue="false", description="algorithm will terminate immediately when a correct definition is found")
+ private boolean stopOnFirstDefinition = false;
+
+
+ @ConfigOption(defaultValue = "false", description = "whether to try and refine solutions which already have accuracy value of 1")
+ private boolean expandAccuracy100Nodes = false;
+ private double currentHighestAccuracy;
+
+ @ConfigOption(name = "nrOfThreads", defaultValue="2", description="number of threads running in parallel")
+ private int nrOfThreads = 2;
+
+ private int expressionTestCountLastImprovement;
+ private long timeLastImprovement = 0;
+
+ private Set currentlyProcessedNodes = Collections.synchronizedSet(new HashSet());
+ private volatile double highestAccuracy = 0.0;
+
+ public PCELOE() {}
+
+ public PCELOE(PCELOE celoe){
+ setReasoner(celoe.reasoner);
+ setLearningProblem(celoe.learningProblem);
+
+ setAllowedConcepts(celoe.getAllowedConcepts());
+ setAllowedObjectProperties(celoe.getAllowedObjectProperties());
+ setAllowedDataProperties(celoe.getAllowedDataProperties());
+
+ setIgnoredConcepts(celoe.ignoredConcepts);
+ setIgnoredObjectProperties(celoe.getIgnoredObjectProperties());
+ setIgnoredDataProperties(celoe.getIgnoredDataProperties());
+
+ setExpandAccuracy100Nodes(celoe.expandAccuracy100Nodes);
+ setFilterDescriptionsFollowingFromKB(celoe.filterDescriptionsFollowingFromKB);
+ setHeuristic(celoe.heuristic);
+
+ setMaxClassExpressionTests(celoe.maxClassExpressionTests);
+ setMaxClassExpressionTestsAfterImprovement(celoe.maxClassExpressionTestsAfterImprovement);
+ setMaxDepth(celoe.maxDepth);
+ setMaxExecutionTimeInSeconds(celoe.maxExecutionTimeInSeconds);
+ setMaxExecutionTimeInSecondsAfterImprovement(celoe.maxExecutionTimeInSecondsAfterImprovement);
+ setMaxNrOfResults(celoe.maxNrOfResults);
+ setNoisePercentage(celoe.noisePercentage);
+
+ RhoDRDown op = new RhoDRDown((RhoDRDown)celoe.operator);
+ try {
+ op.init();
+ } catch (ComponentInitException e) {
+ e.printStackTrace();
+ }
+ setOperator(op);
+
+
+ setReuseExistingDescription(celoe.reuseExistingDescription);
+ setSingleSuggestionMode(celoe.singleSuggestionMode);
+ setStartClass(celoe.startClass);
+ setStopOnFirstDefinition(celoe.stopOnFirstDefinition);
+ setTerminateOnNoiseReached(celoe.terminateOnNoiseReached);
+ setUseMinimizer(celoe.isUseMinimizer());
+
+ setWriteSearchTree(celoe.writeSearchTree);
+ setReplaceSearchTree(celoe.replaceSearchTree);
+ }
+
+ public PCELOE(AbstractClassExpressionLearningProblem problem, AbstractReasonerComponent reasoner) {
+ super(problem, reasoner);
+ }
+
+ public static String getName() {
+ return "PCELOE";
+ }
+
+ @Override
+ public void init() throws ComponentInitException {
+ baseURI = reasoner.getBaseURI();
+ prefixes = reasoner.getPrefixes();
+
+ if(maxExecutionTimeInSeconds != 0 && maxExecutionTimeInSecondsAfterImprovement != 0) {
+ maxExecutionTimeInSeconds = Math.min(maxExecutionTimeInSeconds, maxExecutionTimeInSecondsAfterImprovement);
+ }
+
+ // TODO add comment
+ ClassHierarchy classHierarchy = initClassHierarchy();
+ ObjectPropertyHierarchy objectPropertyHierarchy = initObjectPropertyHierarchy();
+ DatatypePropertyHierarchy datatypePropertyHierarchy = initDataPropertyHierarchy();
+
+ // if no one injected a heuristic, we use a default one
+ if(heuristic == null) {
+ heuristic = new OEHeuristicRuntime();
+ heuristic.init();
+ }
+
+ minimizer = new OWLClassExpressionMinimizer(dataFactory, reasoner);
+
+ if (writeSearchTree) {
+ File f = new File(searchTreeFile);
+ if (f.getParentFile() != null) {
+ f.getParentFile().mkdirs();
+ }
+ Files.clearFile(f);
+ }
+
+ // start at owl:Thing by default
+ if (startClass == null) {
+ startClass = computeStartClass();
+ } else {
+ try {
+ this.startClass = OWLAPIUtils.classExpressionPropertyExpander(this.startClass, reasoner, dataFactory);
+ } catch (Exception e) {
+ logger.warn("Error parsing start class.", e);
+ logger.warn("Using owl:Thing instead.");
+ this.startClass = dataFactory.getOWLThing();
+ }
+ }
+
+ bestEvaluatedDescriptions = new EvaluatedDescriptionSet(maxNrOfResults);
+
+ isClassLearningProblem = (learningProblem instanceof ClassLearningProblem);
+
+ // we put important parameters in class variables
+ noise = noisePercentage/100d;
+
+ // (filterFollowsFromKB is automatically set to false if the problem
+ // is not a class learning problem
+ filterFollowsFromKB = filterDescriptionsFollowingFromKB && isClassLearningProblem;
+
+ // actions specific to ontology engineering
+ if(isClassLearningProblem) {
+ ClassLearningProblem problem = (ClassLearningProblem) learningProblem;
+ classToDescribe = problem.getClassToDescribe();
+ isEquivalenceProblem = problem.isEquivalenceProblem();
+
+ examples = reasoner.getIndividuals(classToDescribe);
+ } else if(learningProblem instanceof PosOnlyLP) {
+ examples = ((PosOnlyLP)learningProblem).getPositiveExamples();
+ } else if(learningProblem instanceof PosNegLP) {
+ examples = Sets.union(((PosNegLP)learningProblem).getPositiveExamples(),((PosNegLP)learningProblem).getNegativeExamples());
+ }
+
+ // create a refinement operator and pass all configuration
+ // variables to it
+ if (operator == null) {
+ // we use a default operator and inject the class hierarchy for now
+ operator = new RhoDRDown();
+ if (operator instanceof CustomStartRefinementOperator) {
+ ((CustomStartRefinementOperator) operator).setStartClass(startClass);
+ }
+ if (operator instanceof ReasoningBasedRefinementOperator) {
+ ((ReasoningBasedRefinementOperator) operator).setReasoner(reasoner);
+ }
+ operator.init();
+ }
+ if (operator instanceof CustomHierarchyRefinementOperator) {
+ ((CustomHierarchyRefinementOperator) operator).setClassHierarchy(classHierarchy);
+ ((CustomHierarchyRefinementOperator) operator).setObjectPropertyHierarchy(objectPropertyHierarchy);
+ ((CustomHierarchyRefinementOperator) operator).setDataPropertyHierarchy(datatypePropertyHierarchy);
+ }
+
+ reasoner.setSynchronized();
+ operator = new SynchronizedRefinementOperator(operator);
+ }
+
+ @Override
+ public void start() {
+ logger.info("starting PCELOE with " + nrOfThreads + " threads");
+// System.out.println(configurator.getMaxExecutionTimeInSeconds());
+
+ stop = false;
+ isRunning = true;
+ reset();
+ nanoStartTime = System.nanoTime();
+
+
+
+ addNode(startClass, null);
+
+ int nrOfWorkers = nrOfThreads;
+ if(nrOfWorkers == 0){
+ nrOfWorkers = Runtime.getRuntime().availableProcessors();
+ }
+ ExecutorService service = Executors.newFixedThreadPool(nrOfWorkers);
+
+ List tasks = new ArrayList<>();
+
+ boolean shareRefinementOperator = false;
+
+ for(int i = 0; i < nrOfWorkers; i++){
+ PCELOEWorker worker;
+ if(shareRefinementOperator) {
+ ClosedWorldReasoner reasonerCopy = new ClosedWorldReasoner();
+ reasonerCopy.setSources(reasoner.getSources());
+ try {
+ reasonerCopy.init();
+ } catch (ComponentInitException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ if(operator instanceof SynchronizedRefinementOperator) {
+ operator = ((SynchronizedRefinementOperator) operator).getDelegate();
+ }
+ RhoDRDown op = new RhoDRDown((RhoDRDown) operator);
+ op.setReasoner(reasonerCopy);
+ try {
+ op.init();
+ } catch (ComponentInitException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ worker = new PCELOEWorker(op);
+ } else {
+ worker = new PCELOEWorker();
+
+ }
+ tasks.add(worker);
+ }
+ nanoStartTime = System.nanoTime();
+
+ //needed to block until all threads have been finished, because otherwise the main thread outputs the result to early
+ List futures = new ArrayList<>();
+ for(Runnable task : tasks){
+ futures.add(service.submit(task));
+ }
+ for(Future future : futures){
+ try {
+ future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (stop) {
+ logger.info("Algorithm stopped ("+expressionTests+" descriptions tested). " + searchTree.size() + " nodes in the search tree.\n");
+ } else {
+ logger.info("Algorithm terminated successfully (time: " + Helper.prettyPrintNanoSeconds(System.nanoTime()-nanoStartTime) + ", "+expressionTests+" descriptions tested, " + searchTree.size() + " nodes in the search tree).\n");
+ logger.info(reasoner.toString());
+ }
+
+ if(singleSuggestionMode) {
+ bestEvaluatedDescriptions.add(bestDescription, bestAccuracy, learningProblem);
+ }
+
+ // print solution(s)
+ logger.info("solutions:\n" + getSolutionString());
+
+// System.out.println(startNode.toTreeString(baseURI));
+
+ isRunning = false;
+ service.shutdown();
+// System.out.println("isRunning: " + isRunning);
+ }
+
+ /*
+ * Compute the start class in the search space from which the refinement will start.
+ * We use the intersection of super classes for definitions (since it needs to
+ * capture all instances), but owl:Thing for learning subclasses (since it is
+ * superfluous to add super classes in this case)
+ */
+ private OWLClassExpression computeStartClass() {
+ OWLClassExpression startClass = dataFactory.getOWLThing();
+
+ if(isClassLearningProblem) {
+ if(isEquivalenceProblem) {
+ Set existingDefinitions = reasoner.getAssertedDefinitions(classToDescribe);
+ if(reuseExistingDescription && (existingDefinitions.size() > 0)) {
+ // the existing definition is reused, which in the simplest case means to
+ // use it as a start class or, if it is already too specific, generalise it
+
+ // pick the longest existing definition as candidate
+ OWLClassExpression existingDefinition = null;
+ int highestLength = 0;
+ for(OWLClassExpression exDef : existingDefinitions) {
+ if(OWLClassExpressionUtils.getLength(exDef) > highestLength) {
+ existingDefinition = exDef;
+ highestLength = OWLClassExpressionUtils.getLength(exDef);
+ }
+ }
+
+ LinkedList startClassCandidates = new LinkedList<>();
+ startClassCandidates.add(existingDefinition);
+ // hack for RhoDRDown
+ if(operator instanceof RhoDRDown) {
+ ((RhoDRDown)operator).setDropDisjuncts(true);
+ }
+ LengthLimitedRefinementOperator upwardOperator = new OperatorInverter(operator);
+
+ // use upward refinement until we find an appropriate start class
+ boolean startClassFound = false;
+ OWLClassExpression candidate;
+ do {
+ candidate = startClassCandidates.pollFirst();
+ if(((ClassLearningProblem)learningProblem).getRecall(candidate)<1.0) {
+ // add upward refinements to list
+ Set refinements = upwardOperator.refine(candidate, OWLClassExpressionUtils.getLength(candidate));
+// System.out.println("ref: " + refinements);
+ LinkedList refinementList = new LinkedList<>(refinements);
+// Collections.reverse(refinementList);
+// System.out.println("list: " + refinementList);
+ startClassCandidates.addAll(refinementList);
+// System.out.println("candidates: " + startClassCandidates);
+ } else {
+ startClassFound = true;
+ }
+ } while(!startClassFound);
+ startClass = candidate;
+
+ if(startClass.equals(existingDefinition)) {
+ logger.info("Reusing existing class expression " + OWLAPIRenderers.toManchesterOWLSyntax(startClass) + " as start class for learning algorithm.");
+ } else {
+ logger.info("Generalised existing class expression " + OWLAPIRenderers.toManchesterOWLSyntax(existingDefinition) + " to " + OWLAPIRenderers.toManchesterOWLSyntax(startClass) + ", which is used as start class for the learning algorithm.");
+ }
+
+ if(operator instanceof RhoDRDown) {
+ ((RhoDRDown)operator).setDropDisjuncts(false);
+ }
+
+ } else {
+ Set superClasses = reasoner.getClassHierarchy().getSuperClasses(classToDescribe, true);
+ if(superClasses.size() > 1) {
+ startClass = dataFactory.getOWLObjectIntersectionOf(superClasses);
+ } else if(superClasses.size() == 1){
+ startClass = (OWLClassExpression) superClasses.toArray()[0];
+ } else {
+ startClass = dataFactory.getOWLThing();
+ logger.warn(classToDescribe + " is equivalent to owl:Thing. Usually, it is not " +
+ "sensible to learn a class expression in this case.");
+ }
+ }
+ }
+ }
+ return startClass;
+ }
+
+ private OENode getNextNodeToExpand() {
+ // we expand the best node of those, which have not achieved 100% accuracy
+ // already and have a horizontal expansion equal to their length
+ // (rationale: further extension is likely to add irrelevant syntactical constructs)
+ synchronized (searchTree) {
+ Iterator it = searchTree.descendingIterator();
+
+ while(it.hasNext()) {
+ OENode node = it.next();
+ if (currentlyProcessedNodes.contains(node)) continue;
+
+ if (isExpandAccuracy100Nodes() && node.getHorizontalExpansion() < OWLClassExpressionUtils.getLength(node.getDescription())) {
+ currentlyProcessedNodes.add(node);
+ return node;
+ } else {
+ if(node.getAccuracy() < 1.0 || node.getHorizontalExpansion() < OWLClassExpressionUtils.getLength(node.getDescription())) {
+ currentlyProcessedNodes.add(node);
+ return node;
+ }
+ }
+ }
+ }
+
+ // this should practically never be called, since for any reasonable learning
+ // task, we will always have at least one node with less than 100% accuracy
+ return null;//nodes.last();
+ }
+
+ // expand node horizontically
+ private TreeSet refineNode(LengthLimitedRefinementOperator operator, OENode node) {
+ MonitorFactory.getTimeMonitor("refineNode").start();
+ // we have to remove and add the node since its heuristic evaluation changes through the expansion
+ // (you *must not* include any criteria in the heuristic which are modified outside of this method,
+ // otherwise you may see rarely occurring but critical false ordering in the nodes set)
+ searchTree.updatePrepare(node);
+ int horizExp = node.getHorizontalExpansion();
+ TreeSet refinements = (TreeSet) operator.refine(node.getDescription(), horizExp+1);
+// System.out.println("refinements: " + refinements);
+ node.incHorizontalExpansion();
+ node.setRefinementCount(refinements.size());
+// System.out.println("refined node: " + node);
+ searchTree.updateDone(node);
+ MonitorFactory.getTimeMonitor("refineNode").stop();
+ return refinements;
+ }
+
+ /**
+ * Add node to search tree if it is not too weak.
+ * @return TRUE if node was added and FALSE otherwise
+ */
+ private boolean addNode(OWLClassExpression description, OENode parentNode) {
+ MonitorFactory.getTimeMonitor("addNode").start();
+
+ // redundancy check (return if redundant)
+ boolean nonRedundant = descriptions.add(description);
+ if(!nonRedundant) {
+ return false;
+ }
+
+ // check whether the class expression is allowed
+ if(!isDescriptionAllowed(description, parentNode)) {
+ return false;
+ }
+
+ // quality of class expression (return if too weak)
+ Monitor mon = MonitorFactory.start("lp");
+ double accuracy = learningProblem.getAccuracyOrTooWeak(description, noise);
+ mon.stop();
+
+ // issue a warning if accuracy is not between 0 and 1 or -1 (too weak)
+ if(accuracy > 1.0 || (accuracy < 0.0 && accuracy != -1)) {
+ throw new RuntimeException("Invalid accuracy value " + accuracy + " for class expression " + description +
+ ". This could be caused by a bug in the heuristic measure and should be reported to the DL-Learner bug tracker.");
+ }
+
+ expressionTests++;
+
+ // return FALSE if 'too weak'
+ if(accuracy == -1) {
+ return false;
+ }
+
+ OENode node = new OENode(description, accuracy);
+
+ // link to parent (unless start node)
+ searchTree.addNode(parentNode, node);
+
+ // in some cases (e.g. mutation) fully evaluating even a single class expression is too expensive
+ // due to the high number of examples -- so we just stick to the approximate accuracy
+ if(singleSuggestionMode) {
+ if(accuracy > bestAccuracy) {
+ bestAccuracy = accuracy;
+ bestDescription = description;
+ logger.info("more accurate (" + dfPercent.format(bestAccuracy) + ") class expression found: " + descriptionToString(bestDescription)); // + getTemporaryString(bestDescription));
+ }
+ return true;
+ }
+
+ // maybe add to best descriptions (method keeps set size fixed);
+ // we need to make sure that this does not get called more often than
+ // necessary since rewriting is expensive
+ boolean isCandidate = !bestEvaluatedDescriptions.isFull();
+ if(!isCandidate) {
+ EvaluatedDescription worst = bestEvaluatedDescriptions.getWorst();
+ double accThreshold = worst.getAccuracy();
+ isCandidate =
+ (accuracy > accThreshold ||
+ (accuracy >= accThreshold && OWLClassExpressionUtils.getLength(description) < worst.getDescriptionLength()));
+ }
+
+ if(isCandidate) {
+ OWLClassExpression niceDescription = node.getExpression();//rewrite(node.getExpression());
+
+ if(niceDescription.equals(classToDescribe)) {
+ return false;
+ }
+
+ if(!isDescriptionAllowed(niceDescription, node)) {
+ return false;
+ }
+
+ // another test: none of the other suggested descriptions should be
+ // a subdescription of this one unless accuracy is different
+ // => comment: on the one hand, this appears to be too strict, because once A is a solution then everything containing
+ // A is not a candidate; on the other hand this suppresses many meaningless extensions of A
+ boolean shorterDescriptionExists = false;
+ if(forceMutualDifference) {
+ for(EvaluatedDescription extends Score> ed : bestEvaluatedDescriptions.getSet()) {
+ if(Math.abs(ed.getAccuracy()-accuracy) <= 0.00001 && ConceptTransformation.isSubdescription(niceDescription, ed.getDescription())) {
+// System.out.println("shorter: " + ed.getDescription());
+ shorterDescriptionExists = true;
+ break;
+ }
+ }
+ }
+
+// System.out.println("shorter description? " + shorterDescriptionExists + " nice: " + niceDescription);
+
+ if(!shorterDescriptionExists) {
+ if(!filterFollowsFromKB || !((ClassLearningProblem)learningProblem).followsFromKB(niceDescription)) {
+// System.out.println(node + "->" + niceDescription);
+ bestEvaluatedDescriptions.add(niceDescription, accuracy, learningProblem);
+// System.out.println("acc: " + accuracy);
+// System.out.println(bestEvaluatedDescriptions);
+ }
+ }
+
+// bestEvaluatedDescriptions.add(node.getDescription(), accuracy, learningProblem);
+
+// System.out.println(bestEvaluatedDescriptions.getSet().size());
+ }
+
+ return true;
+ }
+
+ // checks whether the class expression is allowed
+ private boolean isDescriptionAllowed(OWLClassExpression description, OENode parentNode) {
+ if(isClassLearningProblem) {
+ if(isEquivalenceProblem) {
+ // the class to learn must not appear on the outermost property level
+ if(occursOnFirstLevel(description, classToDescribe)) {
+ return false;
+ }
+ if(occursOnSecondLevel(description, classToDescribe)) {
+ return false;
+ }
+ } else {
+ // none of the superclasses of the class to learn must appear on the
+ // outermost property level
+ TreeSet toTest = new TreeSet<>();
+ toTest.add(classToDescribe);
+ while(!toTest.isEmpty()) {
+ OWLClassExpression d = toTest.pollFirst();
+ if(occursOnFirstLevel(description, d)) {
+ return false;
+ }
+ toTest.addAll(reasoner.getClassHierarchy().getSuperClasses(d));
+ }
+ }
+ } else if (learningProblem instanceof ClassAsInstanceLearningProblem) {
+ return true;
+ }
+
+ // perform forall sanity tests
+ if (parentNode != null &&
+ (ConceptTransformation.getForallOccurences(description) > ConceptTransformation.getForallOccurences(parentNode.getDescription()))) {
+ // we have an additional \forall construct, so we now fetch the contexts
+ // in which it occurs
+ SortedSet contexts = ConceptTransformation.getForallContexts(description);
+ SortedSet parentContexts = ConceptTransformation.getForallContexts(parentNode.getDescription());
+ contexts.removeAll(parentContexts);
+// System.out.println("parent description: " + parentNode.getDescription());
+// System.out.println("description: " + description);
+// System.out.println("contexts: " + contexts);
+ // we now have to perform sanity checks: if \forall is used, then there
+ // should be at least on class instance which has a filler at the given context
+ for(PropertyContext context : contexts) {
+ // transform [r,s] to \exists r.\exists s.\top
+ OWLClassExpression existentialContext = context.toExistentialContext();
+ boolean fillerFound = false;
+ if(reasoner.getClass().isAssignableFrom(SPARQLReasoner.class)) {
+ SortedSet individuals = reasoner.getIndividuals(existentialContext);
+ fillerFound = !Sets.intersection(individuals, examples).isEmpty();
+ } else {
+ for(OWLIndividual instance : examples) {
+ if(reasoner.hasType(existentialContext, instance)) {
+ fillerFound = true;
+ break;
+ }
+ }
+ }
+
+ // if we do not find a filler, this means that putting \forall at
+ // that position is not meaningful
+ if(!fillerFound) {
+ return false;
+ }
+ }
+ }
+
+ // we do not want to have negations of sibling classes on the outermost level
+ // (they are expressed more naturally by saying that the siblings are disjoint,
+ // so it is reasonable not to include them in solutions)
+// Set siblingClasses = reasoner.getClassHierarchy().getSiblingClasses(classToDescribe);
+// for now, we just disable negation
+
+ return true;
+ }
+
+ // determine whether a named class occurs on the outermost level, i.e. property depth 0
+ // (it can still be at higher depth, e.g. if intersections are nested in unions)
+ private boolean occursOnFirstLevel(OWLClassExpression description, OWLClassExpression cls) {
+ if(cls.isOWLThing()) {
+ return false;
+ }
+ return (description instanceof OWLNaryBooleanClassExpression &&
+ ((OWLNaryBooleanClassExpression)description).getOperands().contains(cls));
+// return description.containsConjunct(cls) ||
+// (description instanceof OWLObjectUnionOf && ((OWLObjectUnionOf) description).getOperands().contains(cls));
+ }
+
+ // determine whether a named class occurs on the outermost level, i.e. property depth 0
+ // (it can still be at higher depth, e.g. if intersections are nested in unions)
+ private boolean occursOnSecondLevel(OWLClassExpression description, OWLClassExpression cls) {
+// SortedSet superClasses = reasoner.getSuperClasses(cls);
+// if(description instanceof OWLObjectIntersectionOf) {
+// List operands = ((OWLObjectIntersectionOf) description).getOperandsAsList();
+//
+// for (OWLClassExpression op : operands) {
+// if(superClasses.contains(op) ||
+// (op instanceof OWLObjectUnionOf && !Sets.intersection(((OWLObjectUnionOf)op).getOperands(),superClasses).isEmpty())) {
+// for (OWLClassExpression op2 : operands) {
+// if((op2 instanceof OWLObjectUnionOf && ((OWLObjectUnionOf)op2).getOperands().contains(cls))) {
+// return true;
+// }
+// }
+// }
+// }
+//
+// for (OWLClassExpression op1 : operands) {
+// for (OWLClassExpression op2 : operands) {
+// if(!op1.isAnonymous() && op2 instanceof OWLObjectUnionOf) {
+// for (OWLClassExpression op3 : ((OWLObjectUnionOf)op2).getOperands()) {
+// if(!op3.isAnonymous()) {// A AND B with Disj(A,B)
+// if(reasoner.isDisjoint(op1.asOWLClass(), op3.asOWLClass())) {
+// return true;
+// }
+// } else {// A AND NOT A
+// if(op3 instanceof OWLObjectComplementOf && ((OWLObjectComplementOf)op3).getOperand().equals(op1)) {
+// return true;
+// }
+// }
+// }
+// }
+// }
+// }
+// }
+
+ return false;
+ }
+
+
+ private boolean terminationCriteriaSatisfied() {
+ return
+ stop ||
+ (maxClassExpressionTestsAfterImprovement != 0 && (expressionTests - expressionTestCountLastImprovement >= maxClassExpressionTestsAfterImprovement)) ||
+ (maxClassExpressionTests != 0 && (expressionTests >= maxClassExpressionTests)) ||
+ (maxExecutionTimeInSecondsAfterImprovement != 0 && ((System.nanoTime() - nanoStartTime) >= (maxExecutionTimeInSecondsAfterImprovement* 1000000000L))) ||
+ (maxExecutionTimeInSeconds != 0 && ((System.nanoTime() - nanoStartTime) >= (maxExecutionTimeInSeconds* 1000000000L))) ||
+ (terminateOnNoiseReached && (100*getCurrentlyBestAccuracy()>=100-noisePercentage)) ||
+ (stopOnFirstDefinition && (getCurrentlyBestAccuracy() >= 1));
+ }
+
+ private void reset() {
+ // set all values back to their default values (used for running
+ // the algorithm more than once)
+// nodes = new TreeSet(heuristic);
+ searchTree = new SynchronizedSearchTree(heuristic);
+ //Sets.synchronizedNavigableSet(new TreeSet(Collections.reverseOrder(heuristic)));
+ descriptions = Collections.synchronizedSortedSet(new TreeSet());
+ bestEvaluatedDescriptions.getSet().clear();
+ expressionTests = 0;
+ highestAccuracy = 0.0;
+ }
+
+ private void printAlgorithmRunStats() {
+ if (stop) {
+ logger.info("Algorithm stopped ("+expressionTests+" descriptions tested). " + searchTree.size() + " nodes in the search tree.\n");
+ } else {
+ totalRuntimeNs = System.nanoTime()-nanoStartTime;
+ logger.info("Algorithm terminated successfully (time: " + Helper.prettyPrintNanoSeconds(totalRuntimeNs) + ", "+expressionTests+" descriptions tested, " + searchTree.size() + " nodes in the search tree).\n");
+ logger.info(reasoner.toString());
+ }
+ }
+
+ private void showIfBetterSolutionsFound() {
+ if(!singleSuggestionMode && bestEvaluatedDescriptions.getBestAccuracy() > currentHighestAccuracy) {
+ currentHighestAccuracy = bestEvaluatedDescriptions.getBestAccuracy();
+ expressionTestCountLastImprovement = expressionTests;
+ timeLastImprovement = System.nanoTime();
+ long durationInMillis = getCurrentRuntimeInMilliSeconds();
+ String durationStr = getDurationAsString(durationInMillis);
+ logger.info("more accurate (" + dfPercent.format(currentHighestAccuracy) + ") class expression found after " + durationStr + ": " + descriptionToString(bestEvaluatedDescriptions.getBest().getDescription()));
+ }
+ }
+
+ private void writeSearchTree(TreeSet refinements) {
+ StringBuilder treeString = new StringBuilder("best node: ").append(bestEvaluatedDescriptions.getBest()).append("\n");
+ if (refinements.size() > 1) {
+ treeString.append("all expanded nodes:\n");
+ for (OWLClassExpression ref : refinements) {
+ treeString.append(" ").append(ref).append("\n");
+ }
+ }
+ treeString.append(TreeUtils.toTreeString(searchTree, baseURI, prefixes)).append("\n");
+
+ // replace or append
+ if (replaceSearchTree) {
+ Files.createFile(new File(searchTreeFile), treeString.toString());
+ } else {
+ Files.appendToFile(new File(searchTreeFile), treeString.toString());
+ }
+ }
+
+ private void updateMinMaxHorizExp(OENode node) {
+ int newHorizExp = node.getHorizontalExpansion();
+
+ // update maximum value
+ maxHorizExp = Math.max(maxHorizExp, newHorizExp);
+
+ // we just expanded a node with minimum horizontal expansion;
+ // we need to check whether it was the last one
+ if(minHorizExp == newHorizExp - 1) {
+
+ // the best accuracy that a node can achieve
+ double scoreThreshold = heuristic.getNodeScore(node) + 1 - node.getAccuracy();
+
+ for(OENode n : searchTree.descendingSet()) {
+ if(n != node) {
+ if(n.getHorizontalExpansion() == minHorizExp) {
+ // we can stop instantly when another node with min.
+ return;
+ }
+ if(heuristic.getNodeScore(n) < scoreThreshold) {
+ // we can stop traversing nodes when their score is too low
+ break;
+ }
+ }
+ }
+
+ // inc. minimum since we found no other node which also has min. horiz. exp.
+ minHorizExp++;
+
+// System.out.println("minimum horizontal expansion is now " + minHorizExp);
+ }
+ }
+
+ @Override
+ public OWLClassExpression getCurrentlyBestDescription() {
+ EvaluatedDescription extends Score> ed = getCurrentlyBestEvaluatedDescription();
+ return ed == null ? null : ed.getDescription();
+ }
+
+ @Override
+ public List getCurrentlyBestDescriptions() {
+ return bestEvaluatedDescriptions.toDescriptionList();
+ }
+
+ @Override
+ public EvaluatedDescription getCurrentlyBestEvaluatedDescription() {
+ return bestEvaluatedDescriptions.getBest();
+ }
+
+ @Override
+ public NavigableSet extends EvaluatedDescription extends Score>> getCurrentlyBestEvaluatedDescriptions() {
+ return bestEvaluatedDescriptions.getSet();
+ }
+
+ public double getCurrentlyBestAccuracy() {
+ return bestEvaluatedDescriptions.getBest().getAccuracy();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return isRunning;
+ }
+
+ @Override
+ public void stop() {
+ stop = true;
+ }
+
+ public int getMaximumHorizontalExpansion() {
+ return maxHorizExp;
+ }
+
+ public int getMinimumHorizontalExpansion() {
+ return minHorizExp;
+ }
+
+ /**
+ * @return the expressionTests
+ */
+ public int getClassExpressionTests() {
+ return expressionTests;
+ }
+
+ public LengthLimitedRefinementOperator getOperator() {
+ return operator;
+ }
+
+ @Autowired(required=false)
+ public void setOperator(LengthLimitedRefinementOperator operator) {
+ this.operator = operator;
+ }
+
+ public OWLClassExpression getStartClass() {
+ return startClass;
+ }
+
+ public void setStartClass(OWLClassExpression startClass) {
+ this.startClass = startClass;
+ }
+
+ public boolean isWriteSearchTree() {
+ return writeSearchTree;
+ }
+
+ public void setWriteSearchTree(boolean writeSearchTree) {
+ this.writeSearchTree = writeSearchTree;
+ }
+
+ public String getSearchTreeFile() {
+ return searchTreeFile;
+ }
+
+ public void setSearchTreeFile(String searchTreeFile) {
+ this.searchTreeFile = searchTreeFile;
+ }
+
+ public int getMaxNrOfResults() {
+ return maxNrOfResults;
+ }
+
+ public void setMaxNrOfResults(int maxNrOfResults) {
+ this.maxNrOfResults = maxNrOfResults;
+ }
+
+ public double getNoisePercentage() {
+ return noisePercentage;
+ }
+
+ public void setNoisePercentage(double noisePercentage) {
+ this.noisePercentage = noisePercentage;
+ }
+
+ public boolean isFilterDescriptionsFollowingFromKB() {
+ return filterDescriptionsFollowingFromKB;
+ }
+
+ public void setFilterDescriptionsFollowingFromKB(boolean filterDescriptionsFollowingFromKB) {
+ this.filterDescriptionsFollowingFromKB = filterDescriptionsFollowingFromKB;
+ }
+
+ public boolean isReplaceSearchTree() {
+ return replaceSearchTree;
+ }
+
+ public void setReplaceSearchTree(boolean replaceSearchTree) {
+ this.replaceSearchTree = replaceSearchTree;
+ }
+
+ @Deprecated
+ public int getMaxClassDescriptionTests() {
+ return maxClassExpressionTests;
+ }
+
+ @Deprecated
+ public void setMaxClassDescriptionTests(int maxClassDescriptionTests) {
+ this.maxClassExpressionTests = maxClassDescriptionTests;
+ }
+
+ @Override
+ public int getMaxExecutionTimeInSeconds() {
+ return maxExecutionTimeInSeconds;
+ }
+
+ @Override
+ public void setMaxExecutionTimeInSeconds(int maxExecutionTimeInSeconds) {
+ this.maxExecutionTimeInSeconds = maxExecutionTimeInSeconds;
+ }
+
+ public boolean isTerminateOnNoiseReached() {
+ return terminateOnNoiseReached;
+ }
+
+ public void setTerminateOnNoiseReached(boolean terminateOnNoiseReached) {
+ this.terminateOnNoiseReached = terminateOnNoiseReached;
+ }
+
+ public boolean isReuseExistingDescription() {
+ return reuseExistingDescription;
+ }
+
+ public void setReuseExistingDescription(boolean reuseExistingDescription) {
+ this.reuseExistingDescription = reuseExistingDescription;
+ }
+
+ public AbstractHeuristic getHeuristic() {
+ return heuristic;
+ }
+
+ @Autowired(required=false)
+ public void setHeuristic(AbstractHeuristic heuristic) {
+ this.heuristic = heuristic;
+ }
+
+ @Deprecated
+ public int getMaxClassExpressionTestsWithoutImprovement() {
+ return maxClassExpressionTestsAfterImprovement;
+ }
+
+ @Deprecated
+ public void setMaxClassExpressionTestsWithoutImprovement(
+ int maxClassExpressionTestsWithoutImprovement) {
+ this.maxClassExpressionTestsAfterImprovement = maxClassExpressionTestsWithoutImprovement;
+ }
+
+ public int getMaxExecutionTimeInSecondsAfterImprovement() {
+ return maxExecutionTimeInSecondsAfterImprovement;
+ }
+
+ public void setMaxExecutionTimeInSecondsAfterImprovement(
+ int maxExecutionTimeInSecondsAfterImprovement) {
+ this.maxExecutionTimeInSecondsAfterImprovement = maxExecutionTimeInSecondsAfterImprovement;
+ }
+
+ public boolean isSingleSuggestionMode() {
+ return singleSuggestionMode;
+ }
+
+ public void setSingleSuggestionMode(boolean singleSuggestionMode) {
+ this.singleSuggestionMode = singleSuggestionMode;
+ }
+
+ public int getMaxClassExpressionTests() {
+ return maxClassExpressionTests;
+ }
+
+ public void setMaxClassExpressionTests(int maxClassExpressionTests) {
+ this.maxClassExpressionTests = maxClassExpressionTests;
+ }
+
+ public int getMaxClassExpressionTestsAfterImprovement() {
+ return maxClassExpressionTestsAfterImprovement;
+ }
+
+ public void setMaxClassExpressionTestsAfterImprovement(
+ int maxClassExpressionTestsAfterImprovement) {
+ this.maxClassExpressionTestsAfterImprovement = maxClassExpressionTestsAfterImprovement;
+ }
+
+ public double getMaxDepth() {
+ return maxDepth;
+ }
+
+ public void setMaxDepth(double maxDepth) {
+ this.maxDepth = maxDepth;
+ }
+
+ public boolean isStopOnFirstDefinition() {
+ return stopOnFirstDefinition;
+ }
+
+ public void setStopOnFirstDefinition(boolean stopOnFirstDefinition) {
+ this.stopOnFirstDefinition = stopOnFirstDefinition;
+ }
+
+ public long getTotalRuntimeNs() {
+ return totalRuntimeNs;
+ }
+
+ /**
+ * @return the expandAccuracy100Nodes
+ */
+ public boolean isExpandAccuracy100Nodes() {
+ return expandAccuracy100Nodes;
+ }
+
+ /**
+ * @param expandAccuracy100Nodes the expandAccuracy100Nodes to set
+ */
+ public void setExpandAccuracy100Nodes(boolean expandAccuracy100Nodes) {
+ this.expandAccuracy100Nodes = expandAccuracy100Nodes;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return new PCELOE(this);
+ }
+
+ public int getNrOfThreads() {
+ return nrOfThreads;
+ }
+
+ public void setNrOfThreads(int nrOfThreads) {
+ this.nrOfThreads = nrOfThreads;
+ }
+
+ private synchronized double getHighestAccuracy(){
+ return highestAccuracy;
+ }
+
+ class PCELOEWorker implements Runnable{
+
+ private LengthLimitedRefinementOperator operator;
+
+ public PCELOEWorker() {
+ operator = PCELOE.this.operator;
+ }
+
+ public PCELOEWorker(LengthLimitedRefinementOperator operator) {
+ this.operator = operator;
+ }
+
+ @Override
+ public void run() {
+ OENode nextNode;
+ while (!terminationCriteriaSatisfied()) {
+// String threadName = Thread.currentThread().getName();
+
+ nextNode = getNextNodeToExpand();
+// System.out.println(threadName + " processing " + nextNode);
+
+ if(nextNode != null){
+ int horizExp = nextNode.getHorizontalExpansion();
+
+ // apply refinement operator
+ TreeSet refinements = refineNode(operator, nextNode);
+
+ while(!refinements.isEmpty() && !terminationCriteriaSatisfied()) {
+ // pick element from set
+ OWLClassExpression refinement = refinements.pollFirst();
+// System.out.println(threadName + " analysing " + refinement);
+
+ // get length of class expression
+ int length = OWLClassExpressionUtils.getLength(refinement);
+
+ // we ignore all refinements with lower length and too high depth
+ // (this also avoids duplicate node children)
+ if(length > horizExp && OWLClassExpressionUtils.getDepth(refinement) <= maxDepth) {
+ // add node to search tree
+ boolean added = addNode(refinement, nextNode);
+ if(added) {
+// System.out.println(threadName + " put " + refinement);
+ }
+ }
+ }
+ currentlyProcessedNodes.remove(nextNode);
+// showIfBetterSolutionsFound();
+ }
+
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception{
+// StringRenderer.setRenderer(Rendering.DL_SYNTAX);
+ Logger.getRootLogger().setLevel(Level.INFO);
+ Logger.getLogger(PCELOE.class).setLevel(Level.DEBUG);
+ Logger.getLogger(PCELOE.class).addAppender(new FileAppender(new PatternLayout( "[%t] %c: %m%n" ), "log/parallel_run.txt", false));
+
+
+ AbstractKnowledgeSource ks = new OWLFile("../examples/family/father_oe.owl");
+ ks.init();
+
+ AbstractReasonerComponent rc = new ClosedWorldReasoner(ks);
+ rc.init();
+
+ ClassLearningProblem lp = new ClassLearningProblem(rc);
+ lp.setClassToDescribe(new OWLClassImpl(IRI.create("http://example.com/father#father")));
+ lp.setCheckConsistency(false);
+ lp.init();
+
+ PCELOE alg = new PCELOE(lp, rc);
+ alg.setMaxExecutionTimeInSeconds(10);
+ alg.setNrOfThreads(4);
+// alg.setMaxClassDescriptionTests(200);
+ alg.init();
+
+ alg.start();
+ }
+
+}
diff --git a/components-core/src/main/java/org/dllearner/algorithms/decisiontrees/dsttdt/DSTTDTClassifier.java b/components-core/src/main/java/org/dllearner/algorithms/decisiontrees/dsttdt/DSTTDTClassifier.java
index f756bb09ee..800c4e09b5 100644
--- a/components-core/src/main/java/org/dllearner/algorithms/decisiontrees/dsttdt/DSTTDTClassifier.java
+++ b/components-core/src/main/java/org/dllearner/algorithms/decisiontrees/dsttdt/DSTTDTClassifier.java
@@ -1,45 +1,37 @@
+/**
+ * Copyright (C) 2007 - 2016, Jens Lehmann
+ *
+ * This file is part of DL-Learner.
+ *
+ * DL-Learner is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DL-Learner is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package org.dllearner.algorithms.decisiontrees.dsttdt;
import java.util.ArrayList;
+//import knowledgeBasesHandler.KnowledgeBase;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.Stack;
-
-//import knowledgeBasesHandler.KnowledgeBase;
-
-
-
-
-
-
-
-
-
-
-
-
import java.util.TreeSet;
-
-
-
-
-
-
-
-
-
-
-
-
import org.dllearner.algorithms.decisiontrees.dsttdt.dst.MassFunction;
import org.dllearner.algorithms.decisiontrees.dsttdt.models.DSTDLTree;
import org.dllearner.algorithms.decisiontrees.dsttdt.models.EvidentialModel;
import org.dllearner.algorithms.decisiontrees.heuristics.TreeInductionHeuristics;
-import org.dllearner.algorithms.decisiontrees.refinementoperators.*;
-import org.dllearner.algorithms.decisiontrees.tdt.model.DLTree;
+import org.dllearner.algorithms.decisiontrees.refinementoperators.DLTreesRefinementOperator;
import org.dllearner.algorithms.decisiontrees.utils.Couple;
import org.dllearner.algorithms.decisiontrees.utils.Npla;
import org.dllearner.algorithms.decisiontrees.utils.Split;
@@ -49,13 +41,15 @@
import org.dllearner.core.ComponentAnn;
import org.dllearner.core.ComponentInitException;
import org.dllearner.core.EvaluatedDescription;
+import org.dllearner.core.annotations.OutVariable;
+import org.dllearner.core.annotations.Unused;
import org.dllearner.core.config.ConfigOption;
+import org.dllearner.learningproblems.PosNegUndLP;
import org.dllearner.refinementoperators.RefinementOperator;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.dllearner.learningproblems.PosNegUndLP;
@@ -63,15 +57,20 @@
public class DSTTDTClassifier extends AbstractCELA{
//static final double THRESHOLD = 0.05;
- //static final double M = 3;
+ //static final double M = 3;
private static Logger logger= LoggerFactory.getLogger(DSTTDTClassifier.class);
+
+ @OutVariable
private DSTDLTree currentmodel; // model induced from the procedure
private boolean stop;
+ @Unused
protected OWLClassExpression classToDescribe; //target concept
- protected TreeInductionHeuristics heuristic; // heuristic
+ @ConfigOption(description = "instance of heuristic to use", defaultValue = "TreeInductionHeuristics")
+ protected TreeInductionHeuristics heuristic; // heuristic
//protected LengthLimitedRefinementOperator operator ;// refinement operator
+ @ConfigOption(description = "refinement operator instance to use", defaultValue = "DLTreesRefinementOperator")
protected RefinementOperator operator;
//private KnowledgeBase kb;
@@ -109,7 +108,7 @@ public void setNonSpecifityControl(boolean nonSpecifityControl) {
protected double prPos;
protected double prNeg;
//protected OWLClassExpression classToDescribe; //target concept
- //protected DLTreeHeuristics heuristic; // heuristic
+ //protected DLTreeHeuristics heuristic; // heuristic
//protected LengthLimitedRefinementOperator operator ;// refinement operator
//protected RefinementOperator operator;
@@ -176,12 +175,13 @@ public void setOperator(RefinementOperator operator) {
+ @Override
public void init() throws ComponentInitException{
- //inizialization
+ //inizialization
// TODO Auto-generated method stub
- baseURI = reasoner.getBaseURI();
- prefixes = reasoner.getPrefixes();
+ baseURI = reasoner.getBaseURI();
+ prefixes = reasoner.getPrefixes();
// if no one injected a heuristic, we use a default one
if(heuristic == null) {
@@ -193,9 +193,9 @@ public void init() throws ComponentInitException{
}
if(operator == null) {
- // default operator
+ // default operator
operator= new DLTreesRefinementOperator((PosNegUndLP)super.learningProblem, getReasoner(), 4);
- //operator = new DLTreesRefinementOperator( this.learningProblem,reasoner,4);
+ //operator = new DLTreesRefinementOperator( this.learningProblem,reasoner,4);
((DLTreesRefinementOperator)operator).setReasoner(reasoner);
((DLTreesRefinementOperator)operator).setBeam(4); // default value
//System.out.println("Refinement operator"+operator);
@@ -222,19 +222,19 @@ public void init() throws ComponentInitException{
@SuppressWarnings({ "unchecked", "rawtypes" })
public DSTDLTree induceDSTDLTree
- (SortedSet posExs, SortedSet negExs, SortedSet undExs) {
+ (SortedSet posExs, SortedSet negExs, SortedSet undExs) {
- Npla,SortedSet,SortedSet, Integer, Double, Double> examples = new Npla,SortedSet,SortedSet, Integer, Double, Double>(posExs, negExs, undExs, beam, prPos, prNeg);
+ Npla,SortedSet,SortedSet, Integer, Double, Double> examples = new Npla<>(posExs, negExs, undExs, beam, prPos, prNeg);
DSTDLTree tree = new DSTDLTree(); // new (sub)tree
- Stack,SortedSet,SortedSet, Integer, Double, Double>>> stack= new Stack,SortedSet,SortedSet, Integer, Double, Double>>>();
- Couple,SortedSet,SortedSet, Integer, Double, Double>> toInduce= new Couple,SortedSet,SortedSet, Integer, Double, Double>>();
+ Stack,SortedSet,SortedSet, Integer, Double, Double>>> stack= new Stack<>();
+ Couple,SortedSet,SortedSet, Integer, Double, Double>> toInduce= new Couple<>();
toInduce.setFirstElement(tree);
toInduce.setSecondElement(examples);
stack.push(toInduce);
- Stack lastTrees= new Stack(); // for refine hierarchically a concept
+ Stack lastTrees= new Stack<>(); // for refine hierarchically a concept
while (!stack.isEmpty()){
@@ -250,24 +250,24 @@ public void init() throws ComponentInitException{
int psize = posExs.size();
int nsize = negExs.size();
int usize = undExs.size();
- System.out.printf("Learning problem\t p:%d\t n:%d\t u:%d\t prPos:%4f\t prNeg:%4f\n",
+ System.out.printf("Learning problem\t p:%d\t n:%d\t u:%d\t prPos:%4f\t prNeg:%4f\n",
psize, nsize, usize, prPos, prNeg);
//build the BBA for the current node
- ArrayList frame = new ArrayList();
+ ArrayList frame = new ArrayList<>();
frame.add(-1);
frame.add(1);
MassFunction mass= new MassFunction(frame);
- ArrayList positive= new ArrayList();
+ ArrayList positive= new ArrayList<>();
positive.add(1);
double positiveValue = (double)psize/(psize+ nsize+usize);
if( (psize+ nsize+usize)==0){
positiveValue= prPos;
}
mass.setValues(positive, positiveValue);
- ArrayList negative= new ArrayList();
+ ArrayList negative= new ArrayList<>();
negative.add(-1);
double negativeValue = (double)nsize/(psize+ nsize+usize);
if( (psize+ nsize+usize)==0){
@@ -307,11 +307,11 @@ public void init() throws ComponentInitException{
currentTree.setRoot(dataFactory.getOWLThing(), mass); // set positive lea
// return tree;
}
- else if (perPos==0 && perNeg > puritythreshold) { // no positive
+ else if (perPos==0 && perNeg > puritythreshold) { // no positive
// System.out.println("NoThing as leaf");
currentTree.setRoot(dataFactory.getOWLNothing(), mass); // set negative leaf
// return tree;
- }
+ }
else{
//System.out.println("Non specificity: "+nonSpecifityControl);
if (!nonSpecifityControl){
@@ -330,7 +330,7 @@ else if (perPos==0 && perNeg > puritythreshold) { // no positive
// dlTreesRefinementOperator.refine(dataFactory.getOWLThing(), posExs, negExs);
System.out.println("Refinement:"+refine);
- ArrayList generateNewConcepts = new ArrayList(refine); // a generic refinement operator
+ ArrayList generateNewConcepts = new ArrayList<>(refine); // a generic refinement operator
OWLClassExpression[] cConcepts = new OWLClassExpression[generateNewConcepts.size()];
cConcepts= generateNewConcepts.toArray(cConcepts);
@@ -344,19 +344,19 @@ else if (perPos==0 && perNeg > puritythreshold) { // no positive
else
newRootConcept= heuristic.selectWorstConceptDST(cConcepts, posExs, negExs, undExs, prPos, prNeg); MassFunction refinementMass = newRootConcept.getSecondElement();
- //System.out.println(newRootConcept.getFirstElement()+"----"+refinementMass);
- SortedSet posExsT = new TreeSet();;
- SortedSet negExsT =new TreeSet();;
- SortedSet undExsT =new TreeSet();
- SortedSet posExsF =new TreeSet();
- SortedSet negExsF =new TreeSet();
- SortedSet undExsF = new TreeSet();
+ //System.out.println(newRootConcept.getFirstElement()+"----"+refinementMass);
+ SortedSet posExsT = new TreeSet<>();
+ SortedSet negExsT = new TreeSet<>();
+ SortedSet undExsT = new TreeSet<>();
+ SortedSet posExsF = new TreeSet<>();
+ SortedSet negExsF = new TreeSet<>();
+ SortedSet undExsF = new TreeSet<>();
Split.split(newRootConcept.getFirstElement(), dataFactory, reasoner, posExs, negExs, undExs, posExsT, negExsT, undExsT, posExsF, negExsF, undExsF);
// select node concept
- currentTree.setRoot(newRootConcept.getFirstElement(), refinementMass);
+ currentTree.setRoot(newRootConcept.getFirstElement(), refinementMass);
// undExsT = union(undExsT,
// tree.setPosTree(induceDSTDLTree(posExsT, negExsT, undExsT, dim, prPos, prNeg));
@@ -366,13 +366,13 @@ else if (perPos==0 && perNeg > puritythreshold) { // no positive
DSTDLTree negTree= new DSTDLTree(); // recursive calls simulation
currentTree.setPosTree(posTree);
currentTree.setNegTree(negTree);
- Npla, SortedSet, SortedSet, Integer, Double, Double> npla1 = new Npla, SortedSet,SortedSet, Integer, Double, Double>(posExsT, negExsT, undExsT, beam, perPos, perNeg);
- Npla, SortedSet,SortedSet