001/**
002 * Copyright (C) 2007 - 2016, Jens Lehmann
003 *
004 * This file is part of DL-Learner.
005 *
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package org.dllearner.algorithms.schema;
020
021import com.google.common.collect.Sets;
022import org.apache.jena.ontology.OntModel;
023import org.apache.jena.ontology.OntModelSpec;
024import org.apache.jena.rdf.model.Model;
025import org.apache.jena.rdf.model.ModelFactory;
026import org.apache.jena.rdf.model.Statement;
027import org.aksw.jena_sparql_api.core.QueryExecutionFactory;
028import org.aksw.jena_sparql_api.model.QueryExecutionFactoryModel;
029import org.dllearner.algorithms.properties.AxiomAlgorithms;
030import org.dllearner.core.AbstractAxiomLearningAlgorithm;
031import org.dllearner.core.AxiomLearningProgressMonitor;
032import org.dllearner.core.SilentAxiomLearningProgressMonitor;
033import org.dllearner.kb.SparqlEndpointKS;
034import org.dllearner.reasoning.SPARQLReasoner;
035import org.dllearner.utilities.OwlApiJenaUtils;
036import org.semanticweb.owlapi.model.*;
037import org.semanticweb.owlapi.profiles.OWL2DLProfile;
038import org.semanticweb.owlapi.profiles.OWLProfile;
039import org.semanticweb.owlapi.profiles.Profiles;
040
041import java.util.*;
042import java.util.stream.Collectors;
043import java.util.stream.Stream;
044
045/**
046 * 
047 * @author Lorenz Buehmann
048 *
049 */
050public abstract class AbstractSchemaGenerator implements SchemaGenerator{
051        
052        protected QueryExecutionFactory qef;
053        protected OWLProfile owlProfile = new OWL2DLProfile();
054        protected SPARQLReasoner reasoner;
055        
056//      protected AxiomLearningProgressMonitor progressMonitor = new ConsoleAxiomLearningProgressMonitor();
057        protected AxiomLearningProgressMonitor progressMonitor = new SilentAxiomLearningProgressMonitor();
058        
059        // the types of axioms to be processed
060        protected Set<AxiomType<? extends OWLAxiom>> axiomTypes = AxiomAlgorithms.TBoxAndRBoxAxiomTypes;
061        
062        // the types of entities to be processed
063        protected Set<EntityType<? extends OWLEntity>> entityTypes = Sets.<EntityType<? extends OWLEntity>>newHashSet(
064                        EntityType.CLASS, EntityType.OBJECT_PROPERTY, EntityType.DATA_PROPERTY);
065        
066        // the minimum accuracy threshold for generated axioms to be accepted
067        private double accuracyThreshold = 0.3;
068        
069        // the entities which are processed
070        protected SortedSet<OWLEntity> entities;
071        
072        // the knowledge base
073        private OntModel model;
074        
075        // the profile used for rule based inferencing
076        private OntModelSpec reasoningProfile = OntModelSpec.RDFS_MEM_RDFS_INF;
077        
078        public AbstractSchemaGenerator(QueryExecutionFactory qef) {
079                this.qef = qef;
080                this.reasoner = new SPARQLReasoner(qef);
081                this.model = ModelFactory.createOntologyModel(reasoningProfile);
082        }
083        
084        public AbstractSchemaGenerator(Model model) {
085                // enable reasoning on model
086                this.model = ModelFactory.createOntologyModel(reasoningProfile, model);
087                this.qef = new QueryExecutionFactoryModel(this.model);
088                this.reasoner = new SPARQLReasoner(qef);
089        }
090        
091        /**
092         * Set the types of axioms that are generated.
093         * @param axiomTypes the axiom types to set
094         */
095        public void setAxiomTypes(Set<AxiomType<? extends OWLAxiom>> axiomTypes) {
096                this.axiomTypes = axiomTypes;
097        }
098        
099        /**
100         * Set the types of axioms that are generated by giving an OWL profile.
101         * @param owlProfile the OWL profile
102         */
103        public void setAxiomTypes(OWLProfile owlProfile) {
104                if(owlProfile.equals(Profiles.OWL2_EL.getOWLProfile())){
105                        
106                } else if(owlProfile.equals(Profiles.OWL2_RL.getOWLProfile())){
107
108                } else if(owlProfile.equals(Profiles.OWL2_QL.getOWLProfile())){
109
110                } else if(owlProfile.equals(Profiles.OWL2_DL.getOWLProfile())){
111                        
112                } else {
113                        throw new IllegalArgumentException("OWL profile " + owlProfile.getName() + " not supported.");
114                }
115        }
116        
117        public void setEntityTypes(Set<EntityType<? extends OWLEntity>> entityTypes) {
118                this.entityTypes = entityTypes;
119        }
120        
121        /**
122         * @param entities the entities to set
123         */
124        public void setEntities(SortedSet<OWLEntity> entities) {
125                this.entities = entities;
126        }
127        
128        /**
129         * Return the entities contained in the current knowledge base.
130         */
131        protected SortedSet<OWLEntity> getEntities(){
132                if(entities == null){
133                        entities = new TreeSet<>();
134                        for (EntityType<? extends OWLEntity> entityType : entityTypes) {
135                                if(entityType == EntityType.CLASS){
136                                        entities.addAll(reasoner.getOWLClasses());
137                                } else if(entityType == EntityType.OBJECT_PROPERTY){
138                                        entities.addAll(reasoner.getOWLObjectProperties());
139                                } else if(entityType == EntityType.DATA_PROPERTY){
140                                        entities.addAll(reasoner.getOWLDataProperties());
141                                } else {
142                                        throw new IllegalArgumentException("Entity type " + entityType.getName() + " not supported.");
143                                }
144                        }
145                }
146                return entities;
147        }
148
149        /**
150         * Return the entities contained in the current knowledge base for the given entity type.
151         *
152         * @param entityType the entity type
153         */
154        protected <T extends OWLEntity> SortedSet<T> getEntities(EntityType<T> entityType) {
155                SortedSet<T> entitiesForType = new TreeSet<>();
156                for (OWLEntity entity : getEntities()) {
157                        if (entity.isType(entityType)) {
158                                entitiesForType.add((T) entity);
159                        }
160                }
161                return entitiesForType;
162//              Stream<T> s = entities.stream().filter(e -> e.isType(entityType)).map(e -> (T) e);
163//              return s.collect(Collectors.toList());
164        }
165        
166        /**
167         * @param accuracyThreshold the accuracyThreshold to set
168         */
169        public void setAccuracyThreshold(double accuracyThreshold) {
170                this.accuracyThreshold = accuracyThreshold;
171        }
172        
173        protected Set<OWLAxiom> applyLearningAlgorithm(OWLEntity entity, AxiomType<? extends OWLAxiom> axiomType) throws Exception{
174                // get the algorithm class
175                Class<? extends AbstractAxiomLearningAlgorithm<? extends OWLAxiom, ? extends OWLObject, ? extends OWLEntity>> algorithmClass = AxiomAlgorithms.getAlgorithmClass(axiomType);
176                
177                // create learning algorithm object
178                AbstractAxiomLearningAlgorithm learner = null;
179                try {
180                        learner = (AbstractAxiomLearningAlgorithm)algorithmClass.getConstructor(
181                                        SparqlEndpointKS.class).newInstance(new SparqlEndpointKS(qef));
182                } catch (Exception e) {
183                        e.printStackTrace();
184                }
185                
186                learner.setEntityToDescribe(entity);
187                learner.setUseSampling(false);
188                learner.setProgressMonitor(progressMonitor);
189                
190                
191                try {
192                        // initialize the learning algorithm
193                        learner.init();
194                        
195                        // run the learning algorithm
196                        learner.start();
197                        
198                        // return the result
199                        return new TreeSet<>(learner.getCurrentlyBestAxioms(accuracyThreshold));
200                } catch (Exception e) {
201                        throw new Exception("Generation of " + axiomType.getName() + " axioms failed.", e);
202                }
203        }
204        
205        /**
206         * Add the axioms to the running knowledge base.
207         * @param axioms the axioms
208         */
209        protected void addToKnowledgebase(Set<OWLAxiom> axioms) {
210                Set<Statement> statements = OwlApiJenaUtils.asStatements(axioms);
211                model.add(new ArrayList<>(statements));
212        }
213
214}