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.algorithms.refinement;
021    
022    import org.dllearner.utilities.owl.ConceptComparator;
023    
024    public class NodeComparator implements Heuristic {
025    
026            // Vergleich von Konzepten, falls alle anderen Kriterien fehlschlagen
027            ConceptComparator conceptComparator = new ConceptComparator();
028            
029            // implementiert einfach die Definition in der Diplomarbeit
030            public int compare(Node n1, Node n2) {
031                    
032                    // sicherstellen, dass Qualität ausgewertet wurde
033                    if(n1.isQualityEvaluated() && n2.isQualityEvaluated() && !n1.isTooWeak() && !n2.isTooWeak()) {
034                            if(n1.getCoveredNegativeExamples()<n2.getCoveredNegativeExamples()) 
035                                    return 1;
036                            else if(n1.getCoveredNegativeExamples()>n2.getCoveredNegativeExamples())
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 conceptComparator.compare(n1.getConcept(), 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                    
104                    throw new RuntimeException("Cannot compare nodes, which have no evaluated quality or are too weak.");
105            }
106    
107    
108            // alle NodeComparators führen zur gleichen Ordnung
109            @Override       
110            public boolean equals(Object o) {
111                    return (o instanceof NodeComparator);
112            }
113            
114    }