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.accuracymethods;
020
021import org.dllearner.core.AbstractReasonerComponent;
022import org.dllearner.core.ComponentAnn;
023import org.dllearner.core.Reasoner;
024import org.dllearner.core.config.ConfigOption;
025import org.dllearner.learningproblems.Heuristics;
026import org.semanticweb.owlapi.model.OWLClassExpression;
027import org.semanticweb.owlapi.model.OWLIndividual;
028
029import java.util.Collection;
030
031@ComponentAnn(name = "FMeasure Approximate", shortName = "approx.fmeasure", version = 0)
032public class AccMethodFMeasureApprox extends AccMethodFMeasure implements AccMethodTwoValuedApproximate, AccMethodWithBeta {
033        @ConfigOption(description = "The Approximate Delta", defaultValue = "0.05", required = false)
034        private double approxDelta = 0.05;
035        @ConfigOption(description = "reasoner component (configured  by learning problem)")
036        private Reasoner reasoner;
037
038        public AccMethodFMeasureApprox(boolean init, AbstractReasonerComponent reasoner) {
039                this.setReasoner(reasoner);
040                if(init) {
041                        init();
042                }
043        }
044
045        public AccMethodFMeasureApprox() {
046        }
047
048        @Override
049        public double getAccApprox2(OWLClassExpression description,
050                        Collection<OWLIndividual> positiveExamples,
051                        Collection<OWLIndividual> negativeExamples, double noise) {
052                //              System.out.println("Testing " + description);
053
054                // we abort when there are too many uncovered positives
055                int maxNotCovered = (int) Math.ceil(noise*positiveExamples.size());
056                int instancesCovered = 0;
057                int instancesNotCovered = 0;
058
059                for(OWLIndividual ind : positiveExamples) {
060                        if(reasoner.hasType(description, ind)) {
061                                instancesCovered++;
062                        } else {
063                                instancesNotCovered ++;
064                                if(instancesNotCovered > maxNotCovered) {
065                                        return -1;
066                                }
067                        }
068                }
069
070                double recall = instancesCovered/(double)positiveExamples.size();
071
072                int testsPerformed = 0;
073                int instancesDescription = 0;
074
075                for(OWLIndividual ind : negativeExamples) {
076
077                        if(reasoner.hasType(description, ind)) {
078                                instancesDescription++;
079                        }
080                        testsPerformed++;
081
082                        // check whether approximation is sufficiently accurate
083                        double[] approx = Heuristics.getFScoreApproximation(instancesCovered, recall, (beta == 0 ? 1 : beta), negativeExamples.size(), testsPerformed, instancesDescription);
084                        if(approx[1]<approxDelta) {
085                                return approx[0];
086                        }
087
088                }
089
090                // standard computation (no approximation)
091                double precision = instancesCovered/(double)(instancesDescription+instancesCovered);
092                return Heuristics.getFScore(recall, precision, (beta == 0 ? 1 : beta));
093        }
094
095        @Override
096        public double getApproxDelta() {
097                return approxDelta;
098        }
099
100        @Override
101        public void setApproxDelta(double approxDelta) {
102                this.approxDelta = approxDelta;
103        }
104
105        @Override
106        public void setReasoner(Reasoner reasoner) {
107                this.reasoner = reasoner;
108        }
109
110}