java - Solved: "Comparison method violates its general contract" - I cannot detect any intransitivity -
this question has answer here:
edit: why think not duplicate: biziclop wrote, problem here not intransitivity (a>b & b>c => a>c)
in other problems mentioned here, clause a>b => -(b>a)
violated, it's different problem.
i receiving following error message:
exception in thread "main" java.lang.illegalargumentexception: comparison method violates general contract! @ java.util.timsort.mergehi(unknown source) @ java.util.timsort.mergeat(unknown source) @ java.util.timsort.mergeforcecollapse(unknown source) @ java.util.timsort.sort(unknown source) @ java.util.arrays.sort(unknown source) @ construct.repair.regretrepair(repair.java:101) @ lns.one.repaired(one.java:122) @ lns.one.segment(one.java:68) @ lns.one.lnssolution(one.java:35) @ lns.all.lnssolutions(all.java:22) @ barter.genetic.initialpopulation(genetic.java:36) @ barter.genetic.run(genetic.java:26) @ program.main.main(main.java:22)
this happens:
arrays.sort(regretprofits, new comparator<regretprofit>(){ @override public int compare(regretprofit first, regretprofit second){ if (first.possibleroutes <= 0){ if (second.possibleroutes > 0){ return 1; } return 0; } if (first.possibleroutes < solution.schedule.size() - kay + 1){ if (first.possibleroutes < second.possibleroutes){ return -1; } if (first.possibleroutes > second.possibleroutes){ return 1; } if (first.profit > second.profit){ return -1; } if (first.profit < second.profit){ return 1; } } if (first.regret > second.regret){ return -1; } if (first.regret < second.regret){ return 1; } return 0; } ;});
and class object regretprofit defined:
public class regretprofit { public int[] order; public double regret; public double profit; public int possibleroutes; }
the error occurs every few thousand iterations. thankful if had ideas problem might be. i've read intransitivity can cause exception couldn't figure out possibly went wrong.
solved it, biziclop!
arrays.sort(regretprofits, new comparator<regretprofit>(){ @override public int compare(regretprofit first, regretprofit second){ if (first.possibleroutes <= 0 && second.possibleroutes > 0){ return 1; } if (first.possibleroutes <= 0 && second.possibleroutes <= 0){ return 0; } if (first.possibleroutes > 0 && second.possibleroutes <= 0){ return -1; } if (first.possibleroutes < solution.schedule.size() - kay + 1 || second.possibleroutes < solution.schedule.size() - kay + 1){ if (first.possibleroutes < second.possibleroutes){ return -1; } if (first.possibleroutes > second.possibleroutes){ return 1; } if (first.profit > second.profit){ return -1; } if (first.profit < second.profit){ return 1; } } if (first.regret > second.regret){ return -1; } if (first.regret < second.regret){ return 1; } return 0; } ;});
it isn't transitivity key problem here, part of contract violated sgn(compare(x, y)) == -sgn(compare(y, x))
if have these records example:
first.possibleroutes = -1; first.regret = 1 second.possibleroutes = 1; second.regret = -1
your comparator returns 1. if swap them:
first.possibleroutes = 1; first.regret = -1 second.possibleroutes = -1; second.regret = 1
your comparator still possibly returns 1.
looking @ code there 2 suspicious, non-symmetric constructs:
if (first.possibleroutes <= 0){ if (second.possibleroutes > 0){ return 1; } return 0; }
here there's no matching -1 return if first
, second
reversed. treat every item possibleroutes <= 0
equal, not want.
if (first.possibleroutes < solution.schedule.size() - kay + 1){
here enter branch based purely on value of first
, means branch can potentially lead sgn(compare(x, y)) != -sgn(compare(y, x))
.
of course possible under additional constraints of full system 2 problems cancel each other out (clearly don't in case), it's brittle way of designing comparators , i'd advise make sure branches symmetrical. makes lot easier reason correctness of code.
Comments
Post a Comment