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.learningproblems;
020
021import java.util.List;
022import java.util.Map;
023import java.util.Set;
024import java.util.SortedSet;
025import java.util.TreeMap;
026
027import org.dllearner.utilities.datastructures.SortedSetTuple;
028import org.semanticweb.owlapi.model.OWLClassExpression;
029import org.semanticweb.owlapi.model.OWLIndividual;
030import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
031import org.semanticweb.owlapi.model.OWLObjectUnionOf;
032
033import com.google.common.collect.Sets;
034
035/**
036 * Caches results of previous concept evaluation to speed up
037 * further evaluations. Implements a fast evaluation approach,
038 * which tries to infer the covered examples of a given concept
039 * from previous results.
040 * 
041 * TODO Under construction.
042 * @author Jens Lehmann
043 *
044 */
045public class EvaluationCache {
046
047        // maps a concept to a list of individuals it covers
048        private Map<OWLClassExpression,SortedSet<OWLIndividual>> cache;
049        private boolean checkForEqualConcepts = false;
050        
051        private SortedSet<OWLIndividual> examples;
052        
053        public EvaluationCache(SortedSet<OWLIndividual> examples) {
054                this.examples = examples;
055                cache = new TreeMap<>();
056        }
057        
058        public void put(OWLClassExpression concept, SortedSet<OWLIndividual> individuals) {
059                cache.put(concept, individuals);
060        }
061
062        /**
063         * Determines which examples are instances of a concept.
064         * @param concept the concept
065         * @return A tuple of two sets, where the first element is the
066         * set of individuals belonging to the class and the second element
067         * is the set of individuals not belonging to the class. For all
068         * elements, which are in neither of the sets, the cache cannot
069         * safely determine whether they are concept instances or not.
070         */
071        public SortedSetTuple<OWLIndividual> infer(OWLClassExpression concept) {
072                if(checkForEqualConcepts) {
073                        Set<OWLIndividual> pos = cache.get(concept);
074                        Set<OWLIndividual> neg = Sets.difference(examples, pos);
075                        return new SortedSetTuple<>(pos, neg);
076                } else {
077                        // for a negation NOT C we can only say which concepts are not in it
078                        // (those in C), but we cannot say which ones are in NOT C
079                        
080                        // for a conjunction we know that the intersection of instances
081                        // of all children belongs to the concept
082                        if(concept instanceof OWLObjectIntersectionOf) {
083                                handleMultiConjunction((OWLObjectIntersectionOf)concept);
084                        // disjunctions are similar to conjunctions but we use union here;
085                        // note that there can be instances which are neither in a concept
086                        // C nor in a concept D, but in (C OR D)
087                        } else if(concept instanceof OWLObjectUnionOf) {
088                                List<OWLClassExpression> operands = ((OWLObjectUnionOf) concept).getOperandsAsList();
089                                Set<OWLIndividual> pos = cache.get(operands.get(0));
090                                for (int i = 1; i < operands.size(); i++) {
091                                        pos = Sets.union(pos, cache.get(operands.get(i)));
092                                }
093                        // in all other cases we cannot infer anything, so we return an
094                        // empty tuple
095                        } else {
096                                return new SortedSetTuple<>();
097                        }
098                }
099                
100                return null;
101        }
102        
103        private SortedSetTuple<OWLIndividual> handleMultiConjunction(OWLObjectIntersectionOf mc) {
104                List<OWLClassExpression> operands = mc.getOperandsAsList();
105                Set<OWLIndividual> pos = cache.get(operands.get(0));
106                for (int i = 1; i < operands.size(); i++) {
107                        pos = Sets.intersection(pos, cache.get(operands.get(i)));
108                }
109                // TODO: handle the case that some children may not be in cache
110                return null;
111        }
112}