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.utilities.split;
020
021import java.util.Collection;
022import java.util.Collections;
023import java.util.HashMap;
024import java.util.LinkedList;
025import java.util.List;
026import java.util.Map;
027import java.util.Set;
028import java.util.TreeSet;
029
030import org.dllearner.core.AbstractReasonerComponent;
031import org.dllearner.core.ComponentInitException;
032import org.semanticweb.owlapi.model.OWLDataFactory;
033import org.semanticweb.owlapi.model.OWLDataProperty;
034import org.semanticweb.owlapi.model.OWLLiteral;
035
036import com.google.common.collect.Lists;
037
038/**
039 * Abstract class for values splitting implementation.
040 * @author Lorenz Buehmann
041 *
042 */
043public abstract class AbstractValuesSplitter implements ValuesSplitter{
044        
045        protected AbstractReasonerComponent reasoner;
046        protected OWLDataFactory dataFactory;
047        
048        public AbstractValuesSplitter(AbstractReasonerComponent reasoner, OWLDataFactory dataFactory) {
049                this.reasoner = reasoner;
050                this.dataFactory = dataFactory;
051        }
052        
053        public AbstractValuesSplitter(AbstractReasonerComponent reasoner, OWLDataFactory dataFactory, int maxNrOfSplits) {
054                this.reasoner = reasoner;
055                this.dataFactory = dataFactory;
056        }
057
058        /* (non-Javadoc)
059         * @see org.dllearner.core.Component#init()
060         */
061        @Override
062        public void init() throws ComponentInitException {
063        }
064        
065        /**
066         * Computes a sorted list of split values for each appropriate data property.
067         * @return a map of data properties and its sorted list of split values
068         */
069        @Override
070        public Map<OWLDataProperty, List<OWLLiteral>> computeSplits() {
071                Map<OWLDataProperty, List<OWLLiteral>> result = new HashMap<>();
072                
073                for (OWLDataProperty dp : getDataProperties()) {
074                        List<OWLLiteral> splitValues = computeSplits(dp);
075                        result.put(dp, splitValues);
076                }
077                
078                return result;
079        }
080        
081        /**
082         * @return all applicable data properties.
083         */
084        protected abstract Set<OWLDataProperty> getDataProperties();
085
086        protected <T> T mixTwoValues(T value1, T value2) { return null; }
087
088        protected <T extends Comparable<? super T>> List<T> simpleListSplitter(
089                        Collection<T> allValues, int maxNrOfSplits) {
090                // convert set to a list where values are sorted
091                List<T> values = new LinkedList<>(allValues);
092                Collections.sort(values);
093
094                int nrOfValues = values.size();
095                int nrOfSplits = Math.min(maxNrOfSplits, nrOfValues + 1);
096
097                // create split set
098                Set<T> splitsDP = new TreeSet<>();
099
100                // add the first element
101                if (nrOfValues > 0) {
102                        splitsDP.add(values.get(0));
103                }
104
105                for (int splitNr = 1; splitNr < nrOfSplits; splitNr++) {
106                        int index;// = (int) ((splitNr * (double) (nrOfValues)/(nrOfSplits-1))-1);
107                        index = (int) Math.floor(splitNr * (double) nrOfValues / (nrOfSplits));
108                        index = Math.max(index, (int) Math.floor(splitNr * (double) nrOfValues / (nrOfSplits - 1) - 1));
109
110                        T number1 = values.get(index);
111                        T number2 = values.get(Math.min(nrOfValues - 1, index + 1));
112
113                        //                      System.out.println("Index:" + index + " v1=" + number1 + " v2=" + number2);
114
115                        T avg = mixTwoValues(number1, number2);
116
117                        splitsDP.add(avg);
118                }
119
120                // add the last element
121                if(nrOfValues > 1)
122                        splitsDP.add(values.get(nrOfValues - 1));
123
124                return Lists.newLinkedList(splitsDP);
125        }
126}