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 com.google.common.collect.Sets;
022import org.dllearner.core.AbstractReasonerComponent;
023import org.dllearner.learningproblems.PosNegLP;
024import org.dllearner.utilities.OWLAPIUtils;
025import org.semanticweb.owlapi.model.OWLDataFactory;
026import org.semanticweb.owlapi.model.OWLDataProperty;
027import org.semanticweb.owlapi.model.OWLIndividual;
028import org.semanticweb.owlapi.model.OWLLiteral;
029
030import java.text.NumberFormat;
031import java.text.ParseException;
032import java.util.*;
033
034/**
035 * @author Lorenz Buehmann
036 *
037 */
038public class OptimizedNumericValuesSplitter extends AbstractNumericValuesSplitter{
039
040        private PosNegLP lp;
041//      private Class<T> clazz;
042
043        public OptimizedNumericValuesSplitter(AbstractReasonerComponent reasoner, OWLDataFactory dataFactory, PosNegLP lp) {
044                super(reasoner, dataFactory);
045                this.lp = lp;
046                
047//              clazz = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), OptimizedValuesSplitter.class);
048        }
049        
050        /* (non-Javadoc)
051         * @see org.dllearner.utilities.split.AbstractValuesSplitter#computeSplits(org.semanticweb.owlapi.model.OWLDataProperty)
052         */
053        @Override
054        public List<OWLLiteral> computeSplits(OWLDataProperty dp) {
055                List<OWLLiteral> splitLiterals = new ArrayList<>();
056                
057                List<? extends Number> splitValues = computeSplitValues(dp);
058
059                for (Number value : splitValues) {
060                        OWLLiteral literal = dataFactory.getOWLLiteral(value.toString(), reasoner.getDatatype(dp));
061                        splitLiterals.add(literal);
062                }
063                
064                return splitLiterals;
065        }
066
067        public <T extends Number & Comparable<T>> List<T> computeSplitValues(OWLDataProperty dp) {
068                List<T> splitsDP = new LinkedList<>();
069                NumberFormat numberFormat = NumberFormat.getInstance(Locale.ROOT);
070                
071                SortedSet<T> posRelatedValues = new TreeSet<>();
072                
073                for (OWLIndividual ex : lp.getPositiveExamples()) {
074                        Set<OWLLiteral> relatedValues = reasoner.getRelatedValues(ex, dp);
075                        for (OWLLiteral lit : relatedValues) {
076                                if(OWLAPIUtils.isIntegerDatatype(lit)) {
077                                        posRelatedValues.add((T) Integer.valueOf(lit.parseInteger()));
078                                } else {
079                                        try {
080                                                Number number = numberFormat.parse(lit.getLiteral());
081                                                if(number instanceof Long) {
082                                                        number = Double.valueOf(number.toString());
083                                                }
084                                                posRelatedValues.add((T) (number) );
085                                        } catch (ParseException e) {
086                                                e.printStackTrace();
087                                        }
088                                }
089                                
090                        }
091                }
092                
093                SortedSet<T> negRelatedValues = new TreeSet<>();
094                
095                for (OWLIndividual ex : lp.getNegativeExamples()) {
096                        Set<OWLLiteral> relatedValues = reasoner.getRelatedValues(ex, dp);
097                        for (OWLLiteral lit : relatedValues) {
098                                if(OWLAPIUtils.isIntegerDatatype(lit)) {
099                                        negRelatedValues.add((T) Integer.valueOf(lit.parseInteger()));
100                                } else {
101                                        try {
102                                                Number number = numberFormat.parse(lit.getLiteral());
103                                                if(number instanceof Long) {
104                                                        number = Double.valueOf(number.toString());
105                                                }
106                                                negRelatedValues.add((T) (number) );
107                                        } catch (ParseException e) {
108                                                e.printStackTrace();
109                                        }
110                                }
111                                
112                        }
113                }
114                
115                SortedSet<T> allRelatedValues = Sets.newTreeSet(posRelatedValues);
116                allRelatedValues.addAll(negRelatedValues);
117                
118                boolean posBefore = false;
119                boolean negBefore = false;
120                for (T val : allRelatedValues) {
121                        boolean pos = posRelatedValues.contains(val);
122                        boolean neg = negRelatedValues.contains(val);
123                        
124                        if(pos && !posBefore) {
125                                splitsDP.add(val);
126                        }
127                        
128                        if(neg && !negBefore) {
129                                splitsDP.add(val);
130                        }
131                        
132                        if(pos && neg) {
133                                splitsDP.add(val);
134                        }
135                        
136                        posBefore = pos;
137                        negBefore = neg;
138                }
139                
140                return splitsDP;
141        }
142
143}