001    /**
002     * Copyright (C) 2007-2011, 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     */
019    
020    package org.dllearner.learningproblems;
021    
022    import java.util.Collection;
023    import java.util.SortedSet;
024    import java.util.TreeSet;
025    
026    import org.dllearner.core.EvaluatedDescription;
027    import org.dllearner.core.AbstractReasonerComponent;
028    import org.dllearner.core.configurators.PosNegLPStrictConfigurator;
029    import org.dllearner.core.options.BooleanConfigOption;
030    import org.dllearner.core.options.ConfigEntry;
031    import org.dllearner.core.options.ConfigOption;
032    import org.dllearner.core.options.DoubleConfigOption;
033    import org.dllearner.core.options.InvalidConfigOptionValueException;
034    import org.dllearner.core.owl.Description;
035    import org.dllearner.core.owl.Individual;
036    import org.dllearner.core.owl.Negation;
037    import org.dllearner.reasoning.ReasonerType;
038    import org.dllearner.utilities.Helper;
039    import org.dllearner.utilities.datastructures.SortedSetTuple;
040    
041    /**
042     * @author Jens Lehmann
043     *
044     */
045    public class PosNegLPStrict extends PosNegLP {
046    
047            private SortedSet<Individual> neutralExamples;
048            private boolean penaliseNeutralExamples = false;
049            
050            private static final double defaultAccuracyPenalty = 1;
051            private double accuracyPenalty = defaultAccuracyPenalty;
052            private static final double defaultErrorPenalty = 3;
053            private double errorPenalty = defaultErrorPenalty;
054            
055            private PosNegLPStrictConfigurator configurator;
056            @Override
057            public PosNegLPStrictConfigurator getConfigurator(){
058                    return configurator;
059            }
060            
061            public PosNegLPStrict(AbstractReasonerComponent reasoningService) {
062                    super(reasoningService);
063                    this.configurator = new PosNegLPStrictConfigurator(this);
064            }
065            
066            /* (non-Javadoc)
067             * @see org.dllearner.core.Component#getName()
068             */
069            public static String getName() {
070                    return "three valued definition learning problem";
071            }
072    
073            public static Collection<ConfigOption<?>> createConfigOptions() {
074                    Collection<ConfigOption<?>> options = PosNegLP.createConfigOptions();
075                    options.add(new BooleanConfigOption("penaliseNeutralExamples", "if set to true neutral examples are penalised"));
076                    options.add(new DoubleConfigOption("accuracyPenalty", "penalty for pos/neg examples which are classified as neutral", defaultAccuracyPenalty));
077                    options.add(new DoubleConfigOption("errorPenalty", "penalty for pos. examples classified as negative or vice versa", defaultErrorPenalty));
078                    return options;
079            }
080            
081            /*
082             * (non-Javadoc)
083             * 
084             * @see org.dllearner.core.Component#applyConfigEntry(org.dllearner.core.ConfigEntry)
085             */
086            @Override
087            public <T> void applyConfigEntry(ConfigEntry<T> entry) throws InvalidConfigOptionValueException {
088                    super.applyConfigEntry(entry);
089                    String name = entry.getOptionName();
090                    if(name.equals("penaliseNeutralExamples"))
091                            penaliseNeutralExamples = (Boolean) entry.getValue();
092                    else if(name.equals("accuracyPenalty"))
093                            accuracyPenalty = (Double) entry.getValue();
094                    else if(name.equals("errorPenalty"))
095                            errorPenalty = (Double) entry.getValue();
096            }
097            
098            /* (non-Javadoc)
099             * @see org.dllearner.core.Component#init()
100             */
101            @Override
102            public void init() {
103                    super.init();
104                    // compute neutral examples, i.e. those which are neither positive
105                    // nor negative (we have to take care to copy sets instead of 
106                    // modifying them)
107                    neutralExamples = Helper.intersection(reasoner.getIndividuals(),positiveExamples);
108                    neutralExamples.retainAll(negativeExamples);
109            }
110    
111            /* (non-Javadoc)
112             * @see org.dllearner.learningproblems.DefinitionLP#computeScore(org.dllearner.core.dl.Concept)
113             */
114            @Override
115            public ScorePosNeg computeScore(Description concept) {
116                    if(useRetrievalForClassification) {
117                    if(reasoner.getReasonerType() == ReasonerType.FAST_RETRIEVAL) {
118                            SortedSetTuple<Individual> tuple = reasoner.doubleRetrieval(concept);
119                            // this.defPosSet = tuple.getPosSet();
120                            // this.defNegSet = tuple.getNegSet();  
121                            SortedSet<Individual> neutClassified = Helper.intersectionTuple(reasoner.getIndividuals(),tuple);
122                            return new ScoreThreeValued(concept.getLength(),accuracyPenalty, errorPenalty, penaliseNeutralExamples, percentPerLengthUnit, tuple.getPosSet(),neutClassified,tuple.getNegSet(),positiveExamples,neutralExamples,negativeExamples);
123                    } else if(reasoner.getReasonerType() == ReasonerType.KAON2) {
124                            SortedSet<Individual> posClassified = reasoner.getIndividuals(concept);
125                            SortedSet<Individual> negClassified = reasoner.getIndividuals(new Negation(concept));
126                            SortedSet<Individual> neutClassified = Helper.intersection(reasoner.getIndividuals(),posClassified);
127                            neutClassified.retainAll(negClassified);
128                            return new ScoreThreeValued(concept.getLength(), accuracyPenalty, errorPenalty, penaliseNeutralExamples, percentPerLengthUnit, posClassified,neutClassified,negClassified,positiveExamples,neutralExamples,negativeExamples);                           
129                    } else
130                            throw new Error("score cannot be computed in this configuration");
131            } else {
132                    if(reasoner.getReasonerType() == ReasonerType.KAON2) {
133                            if(penaliseNeutralExamples)
134                                    throw new Error("It does not make sense to use single instance checks when" +
135                                                    "neutral examples are penalized. Use Retrievals instead.");
136                                    
137                            // TODO: umschreiben in instance checks
138                            SortedSet<Individual> posClassified = new TreeSet<Individual>();
139                            SortedSet<Individual> negClassified = new TreeSet<Individual>();
140                            // Beispiele durchgehen
141                            // TODO: Implementierung ist ineffizient, da man hier schon in Klassen wie
142                            // posAsNeut, posAsNeg etc. einteilen k�nnte; so wird das extra in der Score-Klasse
143                            // gemacht; bei wichtigen Benchmarks des 3-wertigen Lernproblems m�sste man das
144                            // umstellen
145                            // pos => pos
146                            for(Individual example : positiveExamples) {
147                                    if(reasoner.hasType(concept, example))
148                                            posClassified.add(example);
149                            }
150                            // neg => pos
151                            for(Individual example: negativeExamples) {
152                                    if(reasoner.hasType(concept, example))
153                                            posClassified.add(example);
154                            }
155                            // pos => neg
156                            for(Individual example : positiveExamples) {
157                                    if(reasoner.hasType(new Negation(concept), example))
158                                            negClassified.add(example);
159                            }
160                            // neg => neg
161                            for(Individual example : negativeExamples) {
162                                    if(reasoner.hasType(new Negation(concept), example))
163                                            negClassified.add(example);
164                            }                       
165                            
166                            SortedSet<Individual> neutClassified = Helper.intersection(reasoner.getIndividuals(),posClassified);
167                            neutClassified.retainAll(negClassified);
168                            return new ScoreThreeValued(concept.getLength(), accuracyPenalty, errorPenalty, penaliseNeutralExamples, percentPerLengthUnit, posClassified,neutClassified,negClassified,positiveExamples,neutralExamples,negativeExamples);           
169                    } else
170                            throw new Error("score cannot be computed in this configuration");
171            }
172            }
173    
174            /* (non-Javadoc)
175             * @see org.dllearner.learningproblems.DefinitionLP#coveredNegativeExamplesOrTooWeak(org.dllearner.core.dl.Concept)
176             */
177            @Override
178            public int coveredNegativeExamplesOrTooWeak(Description concept) {
179                    throw new UnsupportedOperationException("Method not implemented for three valued definition learning problem.");
180            }
181    
182            public SortedSet<Individual> getNeutralExamples() {
183                    return neutralExamples;
184            }
185    
186            /**
187             * @return the accuracyPenalty
188             */
189            public double getAccuracyPenalty() {
190                    return accuracyPenalty;
191            }
192    
193            /**
194             * @return the errorPenalty
195             */
196            public double getErrorPenalty() {
197                    return errorPenalty;
198            }
199    
200            /**
201             * @return the penaliseNeutralExamples
202             */
203            public boolean isPenaliseNeutralExamples() {
204                    return penaliseNeutralExamples;
205            }
206    
207            /* (non-Javadoc)
208             * @see org.dllearner.core.LearningProblem#getAccuracy(org.dllearner.core.owl.Description)
209             */
210            @Override
211            public double getAccuracy(Description description) {
212                    // TODO Auto-generated method stub
213                    return 0;
214            }
215    
216            /* (non-Javadoc)
217             * @see org.dllearner.core.LearningProblem#getAccuracyOrTooWeak(org.dllearner.core.owl.Description, double)
218             */
219            @Override
220            public double getAccuracyOrTooWeak(Description description, double minAccuracy) {
221                    // TODO Auto-generated method stub
222                    return 0;
223            }
224    
225            /* (non-Javadoc)
226             * @see org.dllearner.core.LearningProblem#evaluate(org.dllearner.core.owl.Description)
227             */
228            @Override
229            public EvaluatedDescription evaluate(Description description) {
230                    // TODO Auto-generated method stub
231                    return null;
232            }
233    }