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.reasoning;
020
021import com.clarkparsia.pellet.owlapiv3.PelletReasonerFactory;
022import org.dllearner.core.StringRenderer;
023import org.dllearner.core.StringRenderer.Rendering;
024import org.semanticweb.owlapi.apibinding.OWLManager;
025import org.semanticweb.owlapi.model.*;
026import org.semanticweb.owlapi.reasoner.OWLReasoner;
027import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
028import org.semanticweb.owlapi.search.EntitySearcher;
029import org.semanticweb.owlapi.util.OWLClassExpressionVisitorAdapter;
030
031import java.io.ByteArrayInputStream;
032import java.util.*;
033
034/**
035 * Materialize the existential restrictions, i.e. for all instances x_i that belong to a concept \exists.r.C,
036 * we add facts r(x_i, _:newID), C(_:newID), and this recursively.
037 *
038 * @author Lorenz Buehmann
039 *
040 */
041public class ExistentialRestrictionMaterialization {
042        
043        
044        private OWLOntology ontology;
045        private OWLReasoner reasoner;
046        private OWLDataFactory df;
047
048        public ExistentialRestrictionMaterialization(OWLOntology ontology) {
049                this.ontology = ontology;
050                
051                OWLReasonerFactory reasonerFactory = PelletReasonerFactory.getInstance();
052                reasoner = reasonerFactory.createNonBufferingReasoner(ontology);
053                
054                df = ontology.getOWLOntologyManager().getOWLDataFactory();
055        }
056        
057        private Set<OWLClassExpression> getSuperClasses(OWLClass cls){
058                return new SuperClassFinder().getSuperClasses(cls);
059        }
060        
061        public Set<OWLClassExpression> materialize(String classIRI){
062                return materialize(df.getOWLClass(IRI.create(classIRI)));
063        }
064        
065        public Set<OWLClassExpression> materialize(OWLClass cls){
066                return getSuperClasses(cls);
067        }
068        
069        class SuperClassFinder extends OWLClassExpressionVisitorAdapter{
070                
071                private Map<OWLClass, Set<OWLClassExpression>> map = new HashMap<>();
072                Stack<Set<OWLClassExpression>> stack = new Stack<>();
073                OWLDataFactory df;
074                boolean onlyIfExistentialOnPath = true;
075                
076                int indent = 0;
077
078                public SuperClassFinder() {
079                        df = ontology.getOWLOntologyManager().getOWLDataFactory();
080                }
081                
082                public Set<OWLClassExpression> getSuperClasses(OWLClass cls){
083//                      System.out.println("#################");
084                        map.clear();
085                        computeSuperClasses(cls);
086                        Set<OWLClassExpression> superClasses = map.get(cls);
087                        superClasses.remove(cls);
088                        
089                        // filter out non existential superclasses
090                        if(onlyIfExistentialOnPath){
091                                superClasses.removeIf(sup -> !(sup instanceof OWLObjectSomeValuesFrom || sup instanceof OWLDataAllValuesFrom));
092                        }
093                        return superClasses;
094                }
095                
096                private void computeSuperClasses(OWLClass cls){
097//                      StringBuilder s = new StringBuilder();
098//                      for(int i = 0; i < indent; i++){
099//                              s.append("   ");
100//                      }
101//                      System.out.println(s + cls);
102                        indent++;
103                        Set<OWLClassExpression> superClasses = new HashSet<>();
104                        superClasses.add(cls);
105                        
106                        //get the directly asserted super classes
107                        Collection<OWLClassExpression> superClassExpressions = EntitySearcher.getSuperClasses(cls, ontology);
108                        
109                        //omit trivial super class
110                        superClassExpressions.remove(cls);
111                        
112                        //go subsumption hierarchy up for each directly asserted super class
113                        for (OWLClassExpression sup : superClassExpressions) {
114                                sup.accept(this);
115                                superClasses.addAll(stack.pop());
116                        }
117                        
118                        stack.push(superClasses);
119                        map.put(cls, superClasses);
120                }
121
122                /* (non-Javadoc)
123                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLClass)
124                 */
125                @Override
126                public void visit(OWLClass ce) {
127                        computeSuperClasses(ce);
128                }
129
130                /* (non-Javadoc)
131                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectIntersectionOf)
132                 */
133                @Override
134                public void visit(OWLObjectIntersectionOf ce) {
135                        Set<OWLClassExpression> newIntersections = new HashSet<>();
136                        Set<OWLClassExpression> operands = ce.getOperands();
137                        for (OWLClassExpression op : operands) {
138                                op.accept(this);
139                                Set<OWLClassExpression> operandSuperClassExpressions = stack.pop();
140                                Set<OWLClassExpression> newOperands = new HashSet<>(operands);
141                                newOperands.remove(op);
142                                for (OWLClassExpression opSup : operandSuperClassExpressions) {
143                                        newOperands.add(opSup);
144                                        newIntersections.add(df.getOWLObjectIntersectionOf(newOperands));
145                                        newOperands.remove(opSup);
146                                }
147                        }
148                        stack.push(newIntersections);
149                }
150
151                /* (non-Javadoc)
152                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectUnionOf)
153                 */
154                @Override
155                public void visit(OWLObjectUnionOf ce) {
156                        Set<OWLClassExpression> operands = ce.getOperands();
157                        for (OWLClassExpression op : operands) {
158                                op.accept(this);
159                        }
160                }
161
162                /* (non-Javadoc)
163                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectComplementOf)
164                 */
165                @Override
166                public void visit(OWLObjectComplementOf ce) {
167                }
168
169                /* (non-Javadoc)
170                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom)
171                 */
172                @Override
173                public void visit(OWLObjectSomeValuesFrom ce) {
174                        Set<OWLClassExpression> newRestrictions = new HashSet<>();
175                        newRestrictions.add(ce);
176                        OWLClassExpression filler = ce.getFiller();
177                        filler.accept(this);
178                        Set<OWLClassExpression> fillerSuperClassExpressions = stack.pop();
179                        for (OWLClassExpression fillerSup : fillerSuperClassExpressions) {
180                                newRestrictions.add(df.getOWLObjectSomeValuesFrom(ce.getProperty(), fillerSup));
181                        }
182                        stack.push(newRestrictions);
183                }
184
185                /* (non-Javadoc)
186                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectAllValuesFrom)
187                 */
188                @Override
189                public void visit(OWLObjectAllValuesFrom ce) {
190                }
191
192                /* (non-Javadoc)
193                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectHasValue)
194                 */
195                @Override
196                public void visit(OWLObjectHasValue ce) {
197                }
198
199                /* (non-Javadoc)
200                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectMinCardinality)
201                 */
202                @Override
203                public void visit(OWLObjectMinCardinality ce) {
204                }
205
206                /* (non-Javadoc)
207                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectExactCardinality)
208                 */
209                @Override
210                public void visit(OWLObjectExactCardinality ce) {
211                }
212
213                /* (non-Javadoc)
214                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectMaxCardinality)
215                 */
216                @Override
217                public void visit(OWLObjectMaxCardinality ce) {
218                }
219
220                /* (non-Javadoc)
221                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectHasSelf)
222                 */
223                @Override
224                public void visit(OWLObjectHasSelf ce) {
225                }
226
227                /* (non-Javadoc)
228                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLObjectOneOf)
229                 */
230                @Override
231                public void visit(OWLObjectOneOf ce) {
232                }
233
234                /* (non-Javadoc)
235                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLDataSomeValuesFrom)
236                 */
237                @Override
238                public void visit(OWLDataSomeValuesFrom ce) {
239                }
240
241                /* (non-Javadoc)
242                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLDataAllValuesFrom)
243                 */
244                @Override
245                public void visit(OWLDataAllValuesFrom ce) {
246                }
247
248                /* (non-Javadoc)
249                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLDataHasValue)
250                 */
251                @Override
252                public void visit(OWLDataHasValue ce) {
253                }
254
255                /* (non-Javadoc)
256                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLDataMinCardinality)
257                 */
258                @Override
259                public void visit(OWLDataMinCardinality ce) {
260                }
261
262                /* (non-Javadoc)
263                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLDataExactCardinality)
264                 */
265                @Override
266                public void visit(OWLDataExactCardinality ce) {
267                }
268
269                /* (non-Javadoc)
270                 * @see org.semanticweb.owlapi.model.OWLClassExpressionVisitor#visit(org.semanticweb.owlapi.model.OWLDataMaxCardinality)
271                 */
272                @Override
273                public void visit(OWLDataMaxCardinality ce) {
274                }
275        }
276
277        
278        public static void main(String[] args) throws Exception{
279                StringRenderer.setRenderer(Rendering.DL_SYNTAX);
280                String s = "@prefix : <http://example.org/> ."
281                                + "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ."
282                                + "@prefix owl: <http://www.w3.org/2002/07/owl#> ."
283                                + "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> ."
284                                + ":A a owl:Class . "
285                                + ":B a owl:Class . "
286                                + ":C a owl:Class . "
287                                + ":D a owl:Class . "
288                                + ":r a owl:ObjectProperty . "
289                                + ":A rdfs:subClassOf [ a owl:Restriction; owl:onProperty :r; owl:someValuesFrom :B]."
290                                + ":B rdfs:subClassOf :C."
291                                + ":C rdfs:subClassOf [ a owl:Restriction; owl:onProperty :r; owl:someValuesFrom :D]."
292                                + ":a a :A.";
293                
294                OWLOntologyManager man = OWLManager.createOWLOntologyManager();
295                OWLOntology ontology = man.loadOntologyFromOntologyDocument(new ByteArrayInputStream(s.getBytes()));
296                ExistentialRestrictionMaterialization mat = new ExistentialRestrictionMaterialization(ontology);
297                Set<OWLClassExpression> superClassExpressions = mat.materialize("http://example.org/A");
298                for (OWLClassExpression sup : superClassExpressions) {
299                        System.out.println(sup);
300                }
301        }
302
303}