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.algorithms.ocel;
020
021import org.apache.commons.lang3.NotImplementedException;
022import org.dllearner.core.ComponentAnn;
023import org.dllearner.core.ComponentInitException;
024
025@ComponentAnn(name = "Lexicographic Heuristic", shortName = "lexheuristic", version = 0.1)
026public class LexicographicHeuristic implements ExampleBasedHeuristic {
027
028        // implementiert einfach die Definition in der Diplomarbeit
029        @Override
030        public int compare(ExampleBasedNode n1, ExampleBasedNode n2) {
031
032                // sicherstellen, dass Qualität ausgewertet wurde
033                if(n1.isQualityEvaluated() && n2.isQualityEvaluated() && !n1.isTooWeak() && !n2.isTooWeak()) {
034                        if(n1.getCoveredNegatives().size()<n2.getCoveredNegatives().size())
035                                return 1;
036                        else if(n1.getCoveredNegatives().size()>n2.getCoveredNegatives().size())
037                                return -1;
038                        else {
039                                //TODO: es wäre geringfügig effizienter die Länge nicht mehrfach zu berechnen
040                                // Besser: Länge wird einfach ignoriert und stattdessen horizontal expansion
041                                // genommen => das ist günstiger, da so verhindert wird, dass das gleiche
042                                // Konzept lange ausgeschlachtet wird, obwohl es ein gleich gutes Element gibt,
043                                // was vielleicht nur um 1 länger ist;
044                                // => damit trotzdem die jeweils besten gefundenen Elemente ermittelt werden
045                                // können (da fällt die horizontal expansion dann natürlich als Kriterium
046                                // weg, da die nur während des Algorithmus eine Rolle spielt) wird zusätzlich
047                                // ein separator NodeComparator genutzt
048                                // if(n1.getConcept().getLength()<n2.getConcept().getLength())
049                                //      return 1;
050                                // else if(n1.getConcept().getLength()>n2.getConcept().getLength())
051                                //      return -1;
052                                // else {
053                                        if(n1.getHorizontalExpansion()<n2.getHorizontalExpansion())
054                                                return 1;
055                                        else if(n1.getHorizontalExpansion()>n2.getHorizontalExpansion())
056                                                return -1;
057                                        //else
058                                        //      return 0;
059
060                                        // Vorsicht: es darf nur 0 zurückgegeben werden, wenn die Konzepte identisch sind,
061                                        // in dem Fall werden sie vom Algorithmus ignoriert
062                                        // TODO: hier müsste also gleich eine Vergleichsfunktion für Konzepte in
063                                        // ordered negation normal form einbringen und hätte damit sofort den redundancy
064                                        // check erledigt (??) => horizontalExpansion könnte allerdings bei gleichen
065                                        // Konzepten unterschiedlich sein, also ev. doch keine so gute Idee
066
067                                        else {
068
069                                                //if(n1.getConcept().hashCode()<n2.getConcept().hashCode())
070                                                //      return 1;
071                                                //else if(n1.getConcept().hashCode()>n2.getConcept().hashCode())
072                                                //      return -1;
073
074                                                // throw new RuntimeException("Current implementation cannot cope with candidate concepts with equal hash codes");
075
076                                                // TODO: es ist nicht sehr gut nur Strings zu vergleichen
077                                                // int test = n1.getConcept().toString().compareTo(n2.getConcept().toString());
078                                                return n1.getConcept().compareTo(n2.getConcept());
079                                                //if(test>0)
080                                                //      return 1;
081                                                //else if(test<0)
082                                                //      return -1;
083
084                                                // dieser Fall sollte eigentlich nicht eintreten, außer wenn
085                                                // node entfernt wird => das ist notwendig, wenn horiz. exp.
086                                                // eines Knotens geändert wird; der muss dann gelöscht und
087                                                // wieder eingefügt werden
088
089                                                // System.out.println("equal nodes:");
090                                                // System.out.println(n1 + " chain: " + n1.getRefinementChainString());
091                                                // System.out.println(n2 + " chain: " + n2.getRefinementChainString());
092
093                                                // throw new RuntimeException("same node twice");
094                                                // return 0;
095                                                // Absicherung das keine gleichen Konzepte vorkommen
096                                                // throw new RuntimeException("Current implementation cannot cope with concepts with equal string representations.");
097                                        }
098
099                                //}
100                        }
101                }
102
103                throw new RuntimeException("Cannot compare nodes, which have no evaluated quality or are too weak.");
104        }
105
106        // alle NodeComparators führen zur gleichen Ordnung
107        @Override       
108        public boolean equals(Object o) {
109                return (o instanceof LexicographicHeuristic);
110        }
111
112        @Override
113        public void init() throws ComponentInitException {
114                // nothing to do
115        }
116
117        @Override
118        public double getNodeScore(ExampleBasedNode node) {
119                throw new NotImplementedException("Lexicographic Score not implemented");
120        }
121}