0

Disclaimer: I saw the thread about transitivity of comparison functions, but I don't think mine are bad/I dont see mistake in them

So I wrote a simulation of rabbits and wolfs - there is a set amount of wolves and rabbits in the beginning, rabbits run away from wolfs and wolfs chase rabbits, when they meet in the same block rabbit gets killed and simulation ends when there are no rabbits left.

For small boards, up till about 32x32 all is ok, but for 64+ I get the following error while running.

Also, here are my 3 comparison functions:

lBlocks are JLabels, hare/wolf/killer are icons

public  synchronized boolean isEmpty(int x, int y){
    if(!(lBlocks[x][y].getIcon() instanceof Icon)) return true;
    return false;
}


public  synchronized boolean isWolf(int x, int y){
    if(!(lBlocks[x][y].getIcon() instanceof Icon)) return false;
    if(lBlocks[x][y].getIcon().equals(hare)||lBlocks[x][y].getText().equals("h")||isEmpty(x,y)) return false;
    return true;
}

public  synchronized boolean isHare(int x, int y){
    if(!(lBlocks[x][y].getIcon() instanceof Icon)) return false;
    if(isEmpty(x,y)||isWolf(x,y)) return false;
    return true;
}

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeLo(TimSort.java:747)
    at java.util.TimSort.mergeAt(TimSort.java:483)
    at java.util.TimSort.mergeCollapse(TimSort.java:410)
    at java.util.TimSort.sort(TimSort.java:214)
    at java.util.TimSort.sort(TimSort.java:173)
    at java.util.Arrays.sort(Arrays.java:659)
    at java.util.Collections.sort(Collections.java:217)
    at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTraversalPolicy.java:136)
    at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(SortingFocusTraversalPolicy.java:110)
    at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversalPolicy.java:435)
    at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(LayoutFocusTraversalPolicy.java:166)
    at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTraversalPolicy.java:515)
    at javax.swing.SortingFocusTraversalPolicy.getComponentDownCycle(SortingFocusTraversalPolicy.java:204)
    at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversalPolicy.java:447)
    at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(LayoutFocusTraversalPolicy.java:166)
    at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTraversalPolicy.java:515)
    at java.awt.FocusTraversalPolicy.getInitialComponent(FocusTraversalPolicy.java:169)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:380)
    at java.awt.Component.dispatchEventImpl(Component.java:4731)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at java.awt.SequencedEvent.dispatch(SequencedEvent.java:128)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

The thing is, it does not do absolutely anything - code is working and simulation is going on, but I want to fix it. The worst fact is that there is no line where the error is ocurring and I have a lot of .equals (code is about 400 lines altogether) - I don't know where to find my mistake :(

edit: I found out that if both x and y of board are more than 57 this problem occurs, if they are smaller (or atleast one of them) it does not, lol.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
user3369008
  • 105
  • 11
  • Which line is `TimSort.java:747`? Also, is it time to refactor that large class? – Hovercraft Full Of Eels May 03 '14 at 16:49
  • TimSort.java:747 is not something I wrote, it's a library or something, but I have not used any sort whatsoever. I just wrote this program and it's pretty well written I'd say. I have 5 classes: 90 lines, 63, 152, 79 and 80. – user3369008 May 03 '14 at 16:53
  • Sounds like timsort, one of the most efficient sorting algorithms, is trying to use the `Comparable` interface, which requires that you implement `compareTo( other)` such that `< other` returns -1, equal returns 0 and `> other` returns 1. – Aarowaim May 03 '14 at 17:15
  • I don't quite understand what you just said :( I never used a compare method and I don't sort anything, why would I implement a compare method? – user3369008 May 03 '14 at 17:16
  • I don't know. I think the code you have provided is insufficient to spot the problem, because from what I can see, it appears fine. Try following the path your code takes. Start at main, and follow each line of code. Step-by-step debugging can show you exactly when the code stops working (which appears to be when it calls a new Thread or Runnable class). – Aarowaim May 03 '14 at 17:24
  • The thing is, I did it already. I System.exit'ed after about 50 different lines that could provide the bug, but none of them did. I don't know what to look for, especially that it occurs ONLY when both height and width of the board are > 58, like wtf. I tried to find out why, but there is nothing that could produce such bug. Would you please care to look at the code if I post it somewhere? – user3369008 May 03 '14 at 17:27
  • http://stackoverflow.com/questions/16078578/comparison-method-violates-its-general-contract-exception – Aarowaim May 03 '14 at 17:29
  • Yeah, but I don't have any method that returns -1/1 or 0.. so i guess that's not it. – user3369008 May 03 '14 at 17:33
  • Since your problem is size related, then this must have something to do with it. You may be running out of some resource or another. I agree that your current code is insufficient to allow us to diagnose your problem. Consider using a debugger to try to isolate the problem. – Hovercraft Full Of Eels May 03 '14 at 17:37
  • 1
    As far as I can tell, this bug is the result of java 7 using a new sort method by default. The solution is either to use JRE 6, or to update all your libraries (to the latest version) so that they are compatible with java 7. If neither of those work, please post more code. – Aarowaim May 03 '14 at 17:40

1 Answers1

2

The quick solution appears to be: System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); According to this answer.

Community
  • 1
  • 1
Aarowaim
  • 801
  • 4
  • 10
  • 1
    It doesn't exactly 'work' because there are still problems with comparison code somewhere. It does work in the sense that it makes java more lenient to those mistakes. Don't be surprised if somehow, your code randomly decides that `1 < 1 == true`, or `10 < 1 && 1 < 10 == true` – Aarowaim May 03 '14 at 18:11
  • Well, then I guess it just have to with libraries, which I'll update as soon as I learn how to do that on linux, because I have like no numerical comparisons in my code. – user3369008 May 03 '14 at 18:21
  • 1
    Yeah, it's a pretty serious problem. Thankfully, it won't affect numerical comparisons. It will affect code like `cardQueen.compareTo(cardOne)`, making the theoretical card game believe that a queen is worth less than a 1. – Aarowaim May 03 '14 at 18:26