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;
020
021import com.google.common.base.StandardSystemProperty;
022import com.google.common.collect.Sets;
023import org.apache.jena.query.ParameterizedSparqlString;
024import org.apache.jena.query.QueryExecution;
025import org.apache.jena.rdf.model.Model;
026import org.apache.jena.rdf.model.Statement;
027import org.apache.jena.rdf.model.StmtIterator;
028import org.aksw.jena_sparql_api.pagination.core.QueryExecutionFactoryPaginated;
029import org.dllearner.algorithms.celoe.CELOE;
030import org.dllearner.core.AbstractAxiomLearningAlgorithm;
031import org.dllearner.core.AbstractClassExpressionLearningProblem;
032import org.dllearner.core.AbstractReasonerComponent;
033import org.dllearner.core.ComponentInitException;
034import org.dllearner.kb.OWLAPIOntology;
035import org.dllearner.kb.SparqlEndpointKS;
036import org.dllearner.kb.sparql.SparqlEndpoint;
037import org.dllearner.learningproblems.PosNegLPStandard;
038import org.dllearner.reasoning.ClosedWorldReasoner;
039import org.dllearner.utilities.OwlApiJenaUtils;
040import org.dllearner.utilities.owl.OWLEntityTypeAdder;
041import org.semanticweb.owlapi.formats.RDFXMLDocumentFormat;
042import org.semanticweb.owlapi.model.*;
043import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl;
044
045import java.io.File;
046import java.io.FileNotFoundException;
047import java.io.FileOutputStream;
048import java.util.Set;
049import java.util.SortedSet;
050
051//import org.dllearner.utilities.OwlApiJenaUtils;
052
053/**
054 * A wrapper class for CELOE that allows for returning the result in forms of OWL axioms.
055 * @author Lorenz Buehmann
056 *
057 */
058// not for conf
059public class CELOEWrapper extends AbstractAxiomLearningAlgorithm<OWLClassAxiom, OWLIndividual, OWLClass> {
060        
061        private boolean equivalence = true;
062
063        private int maxClassExpressionDepth = 2;
064        
065        private int maxNrOfPosExamples = 10;
066        private int maxNrOfNegExamples = 20;
067        
068        private static final ParameterizedSparqlString SAMPLE_QUERY = new ParameterizedSparqlString(
069                        "CONSTRUCT {?s a ?entity . ?s a ?cls . ?cls a <http://www.w3.org/2002/07/owl#Class> .} "
070                        + "WHERE {?s a ?entity . OPTIONAL {?s a ?cls . ?cls a <http://www.w3.org/2002/07/owl#Class> . FILTER(!sameTerm(?cls, ?entity))}}");
071        
072        public CELOEWrapper(SparqlEndpointKS ks) {
073                super.ks = ks;
074                useSampling = false;
075                
076        }
077
078        /* (non-Javadoc)
079         * @see org.dllearner.core.AbstractAxiomLearningAlgorithm#getExistingAxioms()
080         */
081        @Override
082        protected void getExistingAxioms() {
083                if(equivalence){
084                        SortedSet<OWLClassExpression> equivalentClasses = reasoner.getEquivalentClasses(entityToDescribe);
085                        for (OWLClassExpression equivCls : equivalentClasses) {
086                                existingAxioms.add(df.getOWLEquivalentClassesAxiom(entityToDescribe, equivCls));
087                        }
088                } else {
089                        SortedSet<OWLClassExpression> superClasses = reasoner.getSuperClasses(entityToDescribe);
090                        for (OWLClassExpression supCls : superClasses) {
091                                existingAxioms.add(df.getOWLSubClassOfAxiom(entityToDescribe, supCls));
092                        }
093                }
094        }
095
096        /* (non-Javadoc)
097         * @see org.dllearner.core.AbstractAxiomLearningAlgorithm#learnAxioms()
098         */
099        @Override
100        protected void learnAxioms() {
101                // get the popularity of the class
102                int popularity = reasoner.getPopularity(entityToDescribe);
103
104                // we have to skip here if there are not instances for the given class
105                if (popularity == 0) {
106                        logger.warn("Cannot compute statements for empty class " + entityToDescribe);
107                        return;
108                }
109                
110                // get positive examples
111                SortedSet<OWLIndividual> posExamples = reasoner.getIndividuals(entityToDescribe, maxNrOfPosExamples );
112                
113                // get negative examples
114                SortedSet<OWLIndividual> negExamples = Sets.newTreeSet();
115                
116                OWLOntology fragment = buildFragment(posExamples, negExamples);
117                try {
118                        fragment.getOWLOntologyManager().saveOntology(fragment, new RDFXMLDocumentFormat(), new FileOutputStream(System.getProperty("java.io.tmpdir") + File.separator + "ont.owl"));
119                } catch (OWLOntologyStorageException | FileNotFoundException e1) {
120                        // TODO Auto-generated catch block
121                        e1.printStackTrace();
122                }
123                try {
124                        AbstractReasonerComponent rc = new ClosedWorldReasoner(new OWLAPIOntology(fragment));
125                        rc.init();
126                        
127                        AbstractClassExpressionLearningProblem lp = new PosNegLPStandard(rc, posExamples, negExamples);
128                        lp.init();
129                        
130                        CELOE la = new CELOE(lp, rc);
131                        la.init();
132                        
133                        la.start();
134                } catch (ComponentInitException e) {
135                        logger.error("CELOE execution failed.", e);
136                }
137        }
138        
139        private OWLOntology buildFragment(Set<OWLIndividual> posExamples, Set<OWLIndividual> negExamples){
140                StringBuilder filter = new StringBuilder("VALUES ?s0 {");
141                for (OWLIndividual ind : Sets.union(posExamples, negExamples)) {
142                        filter.append(ind).append(" ");
143                }
144                filter.append("}");
145                
146                StringBuilder sb = new StringBuilder("CONSTRUCT {");
147                sb.append("?s0 ?p0 ?o0 . ?p0 a ?p_type0 .");
148                for (int i = 1; i < maxClassExpressionDepth; i++) {
149                        sb.append("?o").append(i-1).append(" ?p").append(i).append(" ?o").append(i).append(" .");
150                        sb.append("?p").append(i).append(" a ").append(" ?p_type").append(i).append(" .");
151                }
152                sb.append("} WHERE {");
153                sb.append("?s0 ?p0 ?o0 . OPTIONAL{?p0 a ?p_type0 .}");
154                
155                for (int i = 1; i < maxClassExpressionDepth; i++) {
156                        sb.append("OPTIONAL {");
157                        sb.append("?o").append(i-1).append(" ?p").append(i).append(" ?o").append(i).append(" .");
158                        sb.append("OPTIONAL{").append("?p").append(i).append(" a ").append(" ?p_type").append(i).append(" .}");
159                }
160                for (int i = 1; i < maxClassExpressionDepth; i++) {
161                        sb.append("}");
162                }
163                sb.append(filter);
164                sb.append("}");
165                
166                QueryExecutionFactoryPaginated qef = new QueryExecutionFactoryPaginated(super.qef, 10000);
167                QueryExecution qe = qef.createQueryExecution(sb.toString());
168                Model sample = qe.execConstruct();
169                qe.close();
170                
171                StmtIterator iter = sample.listStatements();
172                while(iter.hasNext()){
173                        Statement st = iter.next();
174                        if(st.getObject().isLiteral() && st.getObject().asLiteral().getDatatype() != null){
175                                try {
176                                        st.getObject().asLiteral().getValue();
177                                } catch (Exception e) {
178                                        iter.remove();
179                                }
180                        }
181                }
182                
183//              org.dllearner.utilities.owl.
184                OWLEntityTypeAdder.addEntityTypes(sample);
185                return OwlApiJenaUtils.getOWLOntology(sample);
186        }
187        
188
189        /* (non-Javadoc)
190         * @see org.dllearner.core.AbstractAxiomLearningAlgorithm#getSampleQuery()
191         */
192        @Override
193        protected ParameterizedSparqlString getSampleQuery() {
194                return SAMPLE_QUERY;
195        }
196        
197        public static void main(String[] args) throws Exception{
198                CELOEWrapper la = new CELOEWrapper(new SparqlEndpointKS(SparqlEndpoint.getEndpointDBpediaLiveAKSW()));
199                la.setEntityToDescribe(new OWLClassImpl(IRI.create("http://dbpedia.org/ontology/Book")));
200                la.init();
201                la.start();
202//              new CELOEWrapper(new SparqlEndpointKS(SPARqlend))
203        }
204
205}