2012-02-27 15 views
8

Ho questo codice:Errore Java: "Il metodo di confronto viola il suo contratto generale!"

package org.optimization.geneticAlgorithm; 
import org.optimization.geneticAlgorithm.selection.Pair; 

public abstract class Chromosome implements Comparable<Chromosome> { 
    public abstract double fitness(); 
    public abstract Pair<Chromosome> crossover(Chromosome parent); 
    public abstract void mutation(); 
    public int compareTo(Chromosome o) { 
     int rv = 0; 
     if (this.fitness() > o.fitness()) { 
      rv = -1; 
     } else if (this.fitness() < o.fitness()) { 
      rv = 1; 
     } 
     return rv; 
    } 
} 

E ogni volta che corro questo codice ottengo questo errore:

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract! 
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:835) 
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:453) 
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376) 
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182) 
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146) 
at java.util.Arrays.sort(Arrays.java:472) 
at java.util.Collections.sort(Collections.java:155) 
at org.optimization.geneticAlgorithm.GeneticAlgorithm.nextGeneration(GeneticAlgorithm.java:74) 
at org.optimization.geneticAlgorithm.GeneticAlgorithm.execute(GeneticAlgorithm.java:40) 
at test.newData.InferenceModel.main(InferenceModel.java:134) 

Io uso OpenJDK7u3 e torno 0 quando gli oggetti sono uguali. Qualcuno può spiegarmi questo errore?

+2

Il metodo 'fitness()' restituisce sempre lo stesso valore indipendentemente dal numero di volte in cui viene chiamato sullo stesso oggetto? Puoi condividere le implementazioni con noi? –

risposta

8

si potrebbe ottenere in quella situazione se avete dei valori NaN:

Per esempio:

public class Test 
{ 
    public static void main(String[] args) { 
     double a = Double.NaN; 
     double b = Double.NaN; 
     double c = 5; 

     System.out.println(a < b); 
     System.out.println(a > b); 
     System.out.println(b < c); 
     System.out.println(c < b); 
    } 
} 

Tutti di questi stampa false. Quindi potresti finire in una situazione in cui due valori non NaN erano entrambi considerati "uguali" a NaN, ma uno era maggiore dell'altro. Fondamentalmente, dovresti capire come vuoi gestire i valori NaN. Verifica anche che questo sia davvero il problema, ovviamente ... vuoi davvero i valori NaN per la tua forma fisica?

+3

Probabilmente non vuoi i valori di 'NaN', ma FYI,' int Double.compare (double, double) 'eseguirà un confronto che soddisfa il contratto di Comparator. Come specificato nel Javadoc, i valori di 'NaN' verranno confrontati come uguali e maggiori di tutti gli altri valori usando questo confronto. –

0

Si dovrebbe provare ad aggiungere if (this == o) return 0; Perché lo stesso oggetto deve essere restituito uguale.

4

La maggior parte probabilmente la funzione di fitness è rotto, in uno dei due modi:

  1. Non restituisce sempre lo stesso valore quando viene chiamato sullo stesso oggetto.
  2. Potrebbe restituire NaN. Il tuo compareTo() non è transitivo in presenza di NaNs, come spiegato da Jon Skeet.

Si potrebbe riscrivere la funzione di confronto con Double.compare():

public int compareTo(Chromosome o) { 
    return Double.compare(o.fitness(), this.fitness()); 
} 

Questo richiede meno codice e si prende cura dei casi d'angolo (NaNs, il negativo pari a zero, ecc). Ovviamente, se questi casi angolari dovessero sorgere in primo luogo, devi decidere e indirizzarti.

Problemi correlati