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