package org.dllearner.tools.protege;
import static org.semanticweb.owlapi.model.AxiomType.DATA_PROPERTY_DOMAIN;
import static org.semanticweb.owlapi.model.AxiomType.EQUIVALENT_CLASSES;
import static org.semanticweb.owlapi.model.AxiomType.OBJECT_PROPERTY_DOMAIN;
import static org.semanticweb.owlapi.model.AxiomType.OBJECT_PROPERTY_RANGE;
import static org.semanticweb.owlapi.model.AxiomType.SUBCLASS_OF;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.List;
import java.util.SortedSet;
import org.dllearner.algorithms.celoe.CELOE;
import org.dllearner.algorithms.properties.AxiomAlgorithms;
import org.dllearner.core.AbstractAxiomLearningAlgorithm;
import org.dllearner.core.ComponentInitException;
import org.dllearner.core.EvaluatedAxiom;
import org.dllearner.core.EvaluatedDescription;
import org.dllearner.core.KnowledgeSource;
import org.dllearner.kb.LocalModelBasedSparqlEndpointKS;
import org.dllearner.kb.OWLAPIOntology;
import org.dllearner.kb.SparqlEndpointKS;
import org.dllearner.learningproblems.ClassLearningProblem;
import org.dllearner.learningproblems.EvaluatedDescriptionClass;
import org.dllearner.reasoning.ClosedWorldReasoner;
import org.dllearner.reasoning.OWLAPIReasoner;
import org.dllearner.refinementoperators.RhoDRDown;
import org.dllearner.utilities.OWLAPIUtils;
import org.dllearner.utilities.OwlApiJenaUtils;
import org.protege.editor.core.Disposable;
import org.protege.editor.owl.OWLEditorKit;
import org.protege.editor.owl.model.event.EventType;
import org.protege.editor.owl.model.event.OWLModelManagerChangeEvent;
import org.protege.editor.owl.model.event.OWLModelManagerListener;
import org.protege.editor.owl.model.selection.OWLSelectionModelListener;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.reasoner.ReasonerProgressMonitor;
import com.hp.hpl.jena.rdf.model.Model;
public class Manager implements OWLModelManagerListener, OWLSelectionModelListener, Disposable{
private static final int MIN_NR_OF_INDIVIDUALS = 0;
private static Manager instance;
private OWLEditorKit editorKit;
private ReasonerProgressMonitor progressMonitor;
private boolean reinitNecessary = true;
private ClassLearningProblem lp;
private CELOE la;
private ClosedWorldReasoner reasoner;
private KnowledgeSource ks;
private LearningType learningType;
private int maxExecutionTimeInSeconds;
private double noisePercentage;
private double threshold;
private int maxNrOfResults;
private boolean useAllConstructor;
private boolean useExistsConstructor;
private boolean useHasValueConstructor;
private boolean useNegation;
private boolean useCardinalityRestrictions;
private int cardinalityLimit;
private volatile boolean isPreparing = false;
private AbstractAxiomLearningAlgorithm alg;
private OWLEntity entity;
private AxiomType axiomType;
public static synchronized Manager getInstance(OWLEditorKit editorKit){
if(instance == null){
instance = new Manager(editorKit);
}
return instance;
}
public static synchronized Manager getInstance(){
return instance;
}
private Manager(OWLEditorKit editorKit){
this.editorKit = editorKit;
}
public void setOWLEditorKit(OWLEditorKit editorKit){
this.editorKit = editorKit;
}
public boolean isReinitNecessary(){
return reinitNecessary;
}
public void init() throws Exception{
initKnowledgeSource();
if(reinitNecessary){
initReasoner();
}
initLearningProblem();
initLearningAlgorithm();
reinitNecessary = false;
}
/**
* @param axiomType the axiomType to set
*/
public void setAxiomType(AxiomType axiomType) {
this.axiomType = axiomType;
}
/**
* @param entity the entity to set
*/
public void setEntity(OWLEntity entity) {
this.entity = entity;
}
public List<EvaluatedAxiom<OWLAxiom>> computeAxioms(OWLEntity entity, AxiomType axiomType) {
System.out.print("Started learning of " +
axiomType.getName() + " axioms for " +
OWLAPIUtils.getPrintName(entity.getEntityType())
+ " " + editorKit.getOWLModelManager().getRendering(entity) + "...");
try {
Class<? extends AbstractAxiomLearningAlgorithm<? extends OWLAxiom, ? extends OWLObject, ? extends OWLEntity>> algorithmClass = AxiomAlgorithms.getAlgorithmClass(axiomType);
OWLOntology ontology = editorKit.getWorkspace().getOWLModelManager().getActiveOntology();
Model model = OwlApiJenaUtils.getModel(ontology);
LocalModelBasedSparqlEndpointKS ks = new LocalModelBasedSparqlEndpointKS(model);
alg = algorithmClass.getConstructor(SparqlEndpointKS.class).newInstance(ks);
alg.setEntityToDescribe(entity);
alg.setUseSampling(false);
// alg.setProgressMonitor(progressMonitor);
alg.init();
alg.start();
System.out.println("done.");
return alg.getCurrentlyBestEvaluatedAxioms();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
e.printStackTrace();
} catch (ComponentInitException e) {
e.printStackTrace();
} catch(Error e) {
e.printStackTrace();
}
return null;
}
public List<EvaluatedAxiom<OWLAxiom>> getCurrentlyBestEvaluatedAxioms() {
return alg.getCurrentlyBestEvaluatedAxioms();
}
public void initLearningAlgorithm() throws Exception {
try {
System.out.print("Initializing learning algorithm...");
long startTime = System.currentTimeMillis();
la = new CELOE(lp, reasoner);
RhoDRDown op = new RhoDRDown();
op.setReasoner(reasoner);
op.setUseNegation(useNegation);
op.setUseHasValueConstructor(useAllConstructor);
op.setUseCardinalityRestrictions(useCardinalityRestrictions);
if(useCardinalityRestrictions){
op.setCardinalityLimit(cardinalityLimit);
}
op.setUseExistsConstructor(useExistsConstructor);
op.setUseHasValueConstructor(useHasValueConstructor);
op.init();
la.setOperator(op);
la.setMaxExecutionTimeInSeconds(maxExecutionTimeInSeconds);
la.setNoisePercentage(noisePercentage);
la.setMaxNrOfResults(maxNrOfResults);
la.init();
System.out.println("done in " + (System.currentTimeMillis()-startTime) + "ms.");
} catch (Error e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void initLearningProblem() throws Exception {
System.out.print("Initializing learning problem...");
long startTime = System.currentTimeMillis();
lp = new ClassLearningProblem(reasoner);
lp.setClassToDescribe(editorKit.getOWLWorkspace().getOWLSelectionModel().getLastSelectedClass());
lp.setEquivalence(axiomType.equals(EQUIVALENT_CLASSES));
lp.setCheckConsistency(DLLearnerPreferences.getInstance().isCheckConsistencyWhileLearning());
lp.init();
System.out.println("done in " + (System.currentTimeMillis()-startTime) + "ms.");
}
public void initKnowledgeSource() throws Exception{
ks = new OWLAPIOntology(editorKit.getOWLModelManager().getActiveOntology());
ks.init();
}
public void initReasoner() throws Exception{
System.out.print("Initializing DL-Learner internal reasoner...");
long startTime = System.currentTimeMillis();
// base reasoner
OWLAPIReasoner baseReasoner = new OWLAPIReasoner(editorKit.getOWLModelManager().getReasoner());
baseReasoner.init();
// closed world reasoner
reasoner = new ClosedWorldReasoner(Collections.singleton(ks));
reasoner.setReasonerComponent(baseReasoner);
// reasoner.setProgressMonitor(progressMonitor);TODO integrate progress monitor
reasoner.init();
reinitNecessary = false;
System.out.println("done in " + (System.currentTimeMillis()-startTime) + "ms.");
}
public void initReasonerAsynchronously(){
reasoner = new ClosedWorldReasoner(Collections.singleton(ks));
OWLAPIReasoner baseReasoner = new OWLAPIReasoner(editorKit.getOWLModelManager().getReasoner());
reasoner.setReasonerComponent(baseReasoner);
// reasoner.setProgressMonitor(progressMonitor);TODO integrate progress monitor
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
reasoner.init();
} catch (ComponentInitException e) {
e.printStackTrace();
}
}
});
t.start();
}
public void addAxiom(OWLAxiom axiom) {
OWLOntology ontology = editorKit.getOWLModelManager().getActiveOntology();
editorKit.getOWLModelManager().applyChange(new AddAxiom(ontology, axiom));
}
public void addAxiom(EvaluatedDescription<? extends OWLClassExpression> evaluatedDescription){
OWLClass selectedClass = editorKit.getOWLWorkspace().getOWLSelectionModel().getLastSelectedClass();
OWLDataFactory df = editorKit.getOWLModelManager().getOWLDataFactory();
OWLAxiom axiom;
if(axiomType.equals(SUBCLASS_OF)) {
axiom = df.getOWLSubClassOfAxiom(selectedClass, evaluatedDescription.getDescription());
} else if(axiomType.equals(EQUIVALENT_CLASSES)) {
axiom = df.getOWLEquivalentClassesAxiom(selectedClass, evaluatedDescription.getDescription());
} else if(axiomType.equals(OBJECT_PROPERTY_DOMAIN)) {
axiom = df.getOWLObjectPropertyDomainAxiom(entity.asOWLObjectProperty(), selectedClass);
} else if(axiomType.equals(OBJECT_PROPERTY_RANGE)) {
axiom = df.getOWLObjectPropertyRangeAxiom(entity.asOWLObjectProperty(), selectedClass);
} else if(axiomType.equals(DATA_PROPERTY_DOMAIN)) {
axiom = df.getOWLDataPropertyDomainAxiom(entity.asOWLDataProperty(), selectedClass);
}
}
public void setProgressMonitor(ReasonerProgressMonitor progressMonitor){
this.progressMonitor = progressMonitor;
}
public void startLearning(){
reasoner.resetStatistics();
System.out.print("Started learning of " +
axiomType.getName() + " axioms for " +
OWLAPIUtils.getPrintName(entity.getEntityType())
+ " " + editorKit.getOWLModelManager().getRendering(entity) + "...");
try {
la.start();
} catch (Error e) {
e.printStackTrace();
}
System.out.println("done.");
}
public void stopLearning(){
System.out.println("Stopped learning algorithm.");
la.stop();
}
public boolean isLearning(){
return la != null && la.isRunning();
}
public LearningType getLearningType() {
return learningType;
}
public void setLearningType(LearningType learningType) {
this.learningType = learningType;
}
public int getMaxExecutionTimeInSeconds() {
return maxExecutionTimeInSeconds;
}
public void setMaxExecutionTimeInSeconds(int maxExecutionTimeInSeconds) {
this.maxExecutionTimeInSeconds = maxExecutionTimeInSeconds;
}
public void setNoisePercentage(double noisePercentage) {
this.noisePercentage = noisePercentage;
}
public void setThreshold(double threshold) {
this.threshold = threshold;
}
public int getMaxNrOfResults() {
return maxNrOfResults;
}
public void setMaxNrOfResults(int maxNrOfResults) {
this.maxNrOfResults = maxNrOfResults;
}
public void setUseAllConstructor(boolean useAllConstructor) {
this.useAllConstructor = useAllConstructor;
}
public void setUseExistsConstructor(boolean useExistsConstructor) {
this.useExistsConstructor = useExistsConstructor;
}
public void setUseHasValueConstructor(boolean useHasValueConstructor) {
this.useHasValueConstructor = useHasValueConstructor;
}
public void setUseNegation(boolean useNegation) {
this.useNegation = useNegation;
}
public void setUseCardinalityRestrictions(boolean useCardinalityRestrictions) {
this.useCardinalityRestrictions = useCardinalityRestrictions;
}
public void setCardinalityLimit(int cardinalityLimit) {
this.cardinalityLimit = cardinalityLimit;
}
@SuppressWarnings("unchecked")
public synchronized List<EvaluatedDescriptionClass> getCurrentlyLearnedDescriptions() {
List<EvaluatedDescriptionClass> result;
if (la != null) {
result = Collections.unmodifiableList((List<EvaluatedDescriptionClass>) la
.getCurrentlyBestEvaluatedDescriptions(maxNrOfResults, threshold, true));
} else {
result = Collections.emptyList();
}
return result;
}
public int getMinimumHorizontalExpansion(){
return ((CELOE)la).getMinimumHorizontalExpansion();
}
public int getMaximumHorizontalExpansion(){
return ((CELOE)la).getMaximumHorizontalExpansion();
}
public boolean isConsistent(){
return reasoner.isSatisfiable();
}
public SortedSet<OWLIndividual> getIndividuals(){
OWLClass selectedClass = editorKit.getOWLWorkspace().getOWLSelectionModel().getLastSelectedClass();
return reasoner.getIndividuals(selectedClass);
}
public boolean canLearn(){
// get the selected entity
OWLEntity entity = editorKit.getOWLWorkspace().getOWLSelectionModel().getSelectedEntity();
// check if number of examples is above min number
if(entity.isOWLClass()) {
return reasoner.getIndividuals(entity.asOWLClass()).size() > MIN_NR_OF_INDIVIDUALS;
} else if(entity.isOWLObjectProperty()) {
return reasoner.getPropertyMembers(entity.asOWLObjectProperty()).size() > MIN_NR_OF_INDIVIDUALS;
} else if(entity.isOWLDataProperty()) {
return reasoner.getDatatypeMembers(entity.asOWLDataProperty()).size() > MIN_NR_OF_INDIVIDUALS;
}
return false;
}
public String getRendering(OWLObject owlObject){
String rendering = editorKit.getModelManager().getRendering(owlObject);
return rendering;
}
public ClosedWorldReasoner getReasoner(){
return reasoner;
}
public OWLOntology getActiveOntology(){
return editorKit.getOWLModelManager().getActiveOntology();
}
public OWLClass getCurrentlySelectedClass(){
return editorKit.getOWLWorkspace().getOWLSelectionModel().getLastSelectedClass();
}
public String getCurrentlySelectedClassRendered(){
return getRendering(getCurrentlySelectedClass());
}
public synchronized void setIsPreparing(boolean isPreparing){
this.isPreparing = isPreparing;
}
public synchronized boolean isPreparing(){
return isPreparing;
}
@Override
public void handleChange(OWLModelManagerChangeEvent event) {
if(event.isType(EventType.REASONER_CHANGED) || event.isType(EventType.ACTIVE_ONTOLOGY_CHANGED)){
reinitNecessary = true;
}
}
@Override
public void selectionChanged() throws Exception {
}
@Override
public void dispose() throws Exception {
alg = null;
entity = null;
axiomType = null;
// reasoner.releaseKB();
editorKit.getOWLModelManager().removeListener(this);
editorKit.getOWLWorkspace().getOWLSelectionModel().removeListener(this);
}
}