2012-02-27 10 views
8

tengo este código:Error de Java: "¡El método de comparación infringe su contrato general!"

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; 
    } 
} 

Y cada vez que ejecute el código me sale este error:

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) 

utilizo OpenJDK7u3 y vuelvo 0 cuando los objetos son iguales. ¿Puede alguien explicarme este error?

+2

¿Su método 'fitness()' siempre devuelve el mismo valor sin importar cuántas veces se invoque en el mismo objeto? ¿Puedes compartir implementaciones con nosotros? –

Respuesta

8

Usted podría entrar en esa situación si usted tiene cualquiera de los valores NaN:

Por ejemplo:

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); 
    } 
} 

Todo de éstos de impresión false. Por lo tanto, podría terminar en una situación en la que dos valores distintos de NaN se consideraran "iguales" a NaN, pero uno era mayor que el otro. Básicamente, debes averiguar cómo quieres manejar los valores de NaN. También compruebe que ese es realmente el problema, por supuesto ... ¿realmente quiere valores de NaN para su estado físico?

+3

Probablemente no desee los valores 'NaN', pero FYI,' int Double.compare (double, double) 'hará una comparación que satisfaga el contrato de Comparator. Como se especifica en el Javadoc, los valores 'NaN' se compararán como iguales y mayores que todos los otros valores usando esta comparación. –

0

Debería intentar agregar if (this == o) return 0; porque el mismo objeto debe devolverse igual.

4

Lo más probable es que su función de aptitud se ha roto, en una de dos maneras:

  1. No siempre devuelve el mismo valor cuando se le llama en el mismo objeto.
  2. Podría devolver NaNs. Su compareTo() no es transitivo en presencia de NaN, como explica Jon Skeet.

Se puede reescribir su función de comparación utilizando Double.compare():

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

Esto requiere menos código y se encarga de los casos de esquina (NaNs, el cero negativo, etc.). Por supuesto, si estos casos de esquina deberían surgir en primer lugar es para que usted decida y dirija.

Cuestiones relacionadas