Need help modifying list based on comparison values (ConcurrentModification) - java

I am trying to see what possibility there is for something (don't tell me there isn't, this is my failed project) throughout an arrangement of points and their distances.
for (Point p1 : results) {
remove.clear();
for (Point p2 : results) {
if (Math.sqrt(
Math.pow(p1.getX() - p2.getX(), 2)
+ Math.pow(p1.getY() - p2.getY(), 2)
) % 1 > 0) {
results.remove(p2);
}
}
}
Basically, I am trying to check if two points have an integer distance, and, if not, remove it from the set, and do this for all points (that remain).
However, I am getting a ConcurrentModificationException and I am not certain how to refactor it to accomplish the same task without just provoking the error in another way.
Are there any ways around this or is it just a limitation of Java?
EDIT: While the duplicate suggested link offers insight, the answers' focus on single loops has berth of excess that is not applicable. If this question is duplicate, it's on premise of that using an Iterator is just the answer.

Some Collection implementations use a "fail-fast" iterator. When removing an item from a Collection directly (using Collection#remove) while iterating over it will cause that exception.
Enhanced for-loops uses the collection's iterator to iterate through the collection.
You could change your enhanced loops to regular for loops:
for(int i = 0; i < results.size(); i++) {
for(int j = 0; j < results.size(); j++) {
Point result = results.get(j);
if(...) {
//results.remove(j); or
//results.remove(result);
}
}
}
As mentioned in the comments, this will not work for Set. In that case, you could simply keep a reference to the collection's iterator, and use that to remove the item:
Iterator<Point> firstIter = results.iterator();
while(firstIter.hasNext()) {
Point p1 = iterator.next();
Iterator<Point> secondIter = results.iterator();
while(secondIter.hasNext()) {
Point p2 = secondIter.next();
if(...) {
secondIter.remove();
}
}
}

You could do this:
Iterator<Point> iterator = results.iterator();
while (iterator.hasNext()) {
Point p1 = iterator.next();
boolean shouldBeRemoved = false;
for(Point p2 : results) {
if (p2 != p1 && (Math.sqrt(Math.pow(p1.getX() - p2.getX(), 2)
+ Math.pow(p1.getY() - p2.getY(), 2))
% 1 > 0)) {
shouldBeRemoved = true;
break;
}
}
if (shouldBeRemoved) {
iterator.remove();
}
}
The difference is that obviously p1 gets removed instead of p2, but since we're dealing with a Set here...
remove it from the set
... the ordering isn't important, right?

This seems to be happening because you are trying to remove the same Point structure. Consider the case of the first point. Both p1 and p2 refer to the first point in results. The distance between p1 and p2 is zero because they refer to the same point. You are then trying to remove p2 which is actually p1 itself. Please refer to the link http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html for more on why you can get this exception even in the case when one thread is trying to access and modify some structure.
You could modify the above code like the following:-
boolean[] if_deleted = new boolean[results.size()];
for (int i = 0; i < results.size(); ++i) {
if_deleted[i] = false;
}
for (int i = 0; i < results.size(); ++i){
for(int j = i + 1; j < results.size(); ++j)
Point p1 = (Point)results.get(i);
Point p2 = (Point)results.get(j);
if (!if_deleted[i] && !if_deleted[j]) {
if (Math.sqrt(
Math.pow(p1.getX() - p2.getX(), 2)
+
Math.pow(p1.getY() - p2.getY(), 2))
% 1 > 0){
if_deleted[j] = true;
results.remove(p2);
}
}
}
}
for (int i = 0; i < results.size(); ++i) {
if (if_deleted[i]) {
results.remove(i);
}
}

I refactored to
for (int p1 = 0; p1 < results.size() ; p1++){
for (int p2 = p1; p2 < results.size() ; p2++){
if (Math.sqrt(
Math.pow(results.get(p1).getX() - results.get(p2).getX(), 2)
+
Math.pow(results.get(p1).getY() - results.get(p2).getY(), 2))
% 1 > 0){
results.remove(p2);
p2--;
}
}
}
But I'm not sure it's working as I expected it to.

Related

Advanced 2-D Array map generation for 2D Platformer game with Java (processing)

I'm trying to figure out a way to make my simple map generation better. So the question to be specific is, how do I make my random 2-D array platform generator, less random so it looks more like a platformer game level as well as adding a bit more variables to it for adding variation to each Map Generated. Explanation below.
Currently, I have this:
void GenerateMap() {
int x = width/30;
int y = height/28;
int[][] map = new int[x][y];
//println(map.length);
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
float val = random(0, 100);
float nv = noise(val);
println(nv);
if (j <= (int) (.5 * map.length)) {
map[i][j] = nv < .3 ? 0 : 1;
} else if (j >= (int) (.7 * map.length)) {
map[i][j] = nv < .6 ? 1 : 0;
} else {
map[i][j] = nv <= .3 ? 0 : 1;
}
println(i +"-" + j + " - rowcol: " + map[i][j]);
}
}
levelMap = map;
JSONArray saveArr = arrayToJson(levelMap);
saveJSONArray(saveArr, dataPath("./maps/Generation_" + mapGenerations + ".json"), "compact");
}
It builds a 2d array with 1s and 0s, I tried to make it less random so it looks like a playable terrain. the top-most section will be 0's (air), the bottom-most will be 1's (platform). Then the middle will have a mix to make floating platforms and such. So far I've got nothing.
The next Idea that popped up was to have the number go from 0-N. This works by:
0 will always be air,
1 will always be a platform,
2 can be a platform of a different image, let's say a diagonal platform to form a slope off the edge
3 can be a collectible or anything
...etc
My issue is I can't figure out how to generate the numbers in a way that will make the map not look like a mess. I came up with a setup for my variables:
public int[] toplayer = null, // [0,0,0,0,...,0]
bottomlayer = null, // [1,1,1,1,...,1]
variation = {0,1,2}, // the 0-N
variationRatios = {60, 30, 10}; // this would specify the frequency/probability of each variation show up, respectively, in a random() function
After all, that's done, then I run a function to replace all values with their respective "Sprite" and then display them on the screen.
void drawPlatform(int amt, PVector pos, PVector size) {
for (int i = 0; i < amt; i++) {
//new Platform(new PVector(abs(width-((pos.x+(size.x/2)) + (i * size.x))), pos.y+(size.y/2)), size);
Platform p = new Platform(new PVector(abs(((pos.x+(size.x/2)) + (i * size.x))), pos.y+(size.y/2)), size);
if (platforms.indexOf(p) % 5 == 0 && !p.bouncy) {
p.bouncy = true;
}
}
}
JSONArray arrayToJson(int[][] arr) {
JSONArray ja = new JSONArray();
for (int[] ar : arr) {
JSONArray j = new JSONArray();
ja.append(j);
for (int a : ar) {
j.append(a);
}
}
return ja;
}
void LoadMap(int[][] map) {
drawPlatform(width/30, new PVector(0, 0), new PVector(30, 30)); // top
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
if (map[i][j] == 0) {
new Platform(new PVector((i*30)+15, (j*30)+45), new PVector(30, 30));
//drawPlatform(1, new PVector(i+j*30, (i+j)*30), new PVector(30, 30));
}
}
}
drawPlatform(width/30, new PVector(0, height-30), new PVector(30, 30)); // bottom
println(gameObjects.size() + " GameObjects loaded");
println(platforms.size() + " Platforms loaded");
}
Overall, this is how it's used:
GenerateMap();
LoadMap(levelMap);
mapGenerations++;
This is how it would end up looking (obviously different each generation):
But right now, I have something like this:
I've looked everywhere for a couple of days now, for a solution and can't find anything as specific as my request. If you have any ideas, please let me know.
Quick Note: Of course, we could have the user write the array by hand but that's not time-effective enough. I could also have a visual map builder but that's a lot more code and more time than I have available. I am not opposed to this idea, however.

shorten bubble sort loop

I have change my bubble sort from implementing the application traverses the entire list during each step of the sort.
This is not necessary since after the first traversal the smallest item will be at the end of the list and after the second traversal, the second smallest item will be in its correct position (2nd last) and so on. i'm a little unsure on what needs to changed exactly.
I need to modify the bubble sort so it doesn't perform unnecessary comparisons.
private void bubbleSort() {
int currentCount = 0;
showStatus("Sorting ...");
boolean swap = true;
while (swap) {
swap = false;
for (int i = 0; i < items.length - 1; i++) {
if (greaterThan(items[i], items[i + 1])) {
swapItems(items[i], items[i + 1]);
swap = true;
currentCount++;
}
} // for
} // while
showStatus("Sort complete, number of swaps = " + currentCount);
} // bubbleSort private void bubbleSort() {
A bubble sort will perform unnecessary comparisons, that's why you don't use it in production for any dataset of any reasonable size. Regarding your code in particular. A simple look at the reference implementation on Rosettacode(because I don't feel like actually writing it again, you only do that in school) looks to show it doing exactly the same number of comparisons. If you want an actually good sorting algorithm for sufficiently large N try merge-sort.
Reference
public static <E extends Comparable<? super E>> void bubbleSort(E[] comparable) {
boolean changed = false;
do {
changed = false;
for (int a = 0; a < comparable.length - 1; a++) {
if (comparable[a].compareTo(comparable[a + 1]) > 0) {
E tmp = comparable[a];
comparable[a] = comparable[a + 1];
comparable[a + 1] = tmp;
changed = true;
}
}
} while (changed);
}
First of all, at the end of first iteration of the for loop the biggest element will be at the end of the array and not the smallest.
If you want to modify your code to save unneeded comparison you can check last comparison and use if as the end of the next for-loop.
Consider the following code: (I hope java allow while(int) - I'm not a java expert...)
integer swap = items.length - 1;
while (swap) {
swap = 0;
integer lastSwap = swap ;
for (int i = 0; i < lastSwap ; i++) {
if (greaterThan(items[i], items[i + 1])) {
swapItems(items[i], items[i + 1]);
swap = i;
currentCount++;
}
} // for
} // while

Java+CPLEX Unknown Object Exception in LazyConstraintCallback

I'm quite new to CPLEX+Java. I try to implement a variant of an Orienteering Problem and a Pickup and Delivery problem. I would like to use a LazyConstraintCallback to ensure Subtour Elimination in Integer Solutions.
Due to the orienteering component, I need an additional variable (z[q]) in for the Callback, which is so far not included in the model.
protected void main() throws IloException {
// first: test if more than one route exists
int[][] cycles = getCycles(getLongRoute());
int count = countCycles(cycles);
IloNumVar[] z = model.boolVarArray(count);
if (count > 1) {
// add connectivity constraints
int b = 1;
for (int q = 0;q<cycles.length; q++) {
IloLinearNumExpr expr1 = model.linearNumExpr();
int[] cycle = cycles[q];
int m = 0;
for (int p = 0; p<cycle.length; p++) {
int i = ArrayHandler.getIndex(allLocations_k, cycle[p]);
for (int l = 0; l<cycle.length; l++) {
int j = ArrayHandler.getIndex(allLocations_k, cycle[l]);
if (i!=j) {
expr1.addTerm(1.0, x[i][j]);
}
}
if (ArrayHandler.contains(deliveryLocation_k, allLocations_k[i])) {
expr1.addTerm(ak[i], 1.0);
} else {
m++;
expr1.addTerm(ak[i], -1.0);
}
}
for (int p = 0; p<loc_k; p++) {
int i = allLocations_k[p];
if (!ArrayHandler.contains(cycle, i)) {
IloLinearNumExpr expr2 = model.linearNumExpr();
if (ArrayHandler.contains(deliveryLocation_k, i)) {
expr2.addTerm(ak[p], 1.0);
expr2.addTerm(z[q],-1.0);
this.add(model.le(expr2,0.0));
//this.addLe(expr2, z[q]);
} else {
expr2.addTerm(ak[p], 1.0);
expr2.addTerm(z[q], 1.0);
this.add(model.ge(expr2,1.0));
//model.addLe(1.0,expr2);
}
}
}
expr1.setConstant(m);
expr1.addTerm(z[q], -1.0);
this.add(model.le(0.0, expr1));
}
}
}
It throws an "Unknown Object" Error after reading "this.add(model.ge(expr2,z[q]));", which is the first constraint it should add. I guess that this behavior is somehow connected to the unknown variable z[q]. Do I have to add this at another location? I don't know the final dimension of z[q], as I need a z[q] for every subtour found during the execution, this can grow exponentially large (that's why I hoped to be able to create it on the fly).
Maybe the error message helps:
ilog.cplex.IloCplex$UnknownObjectException: CPLEX Error: object is unknown to IloCplex
at ilog.cplex.CpxNumVar.getVarIndexValue(CpxNumVar.java:295)
at ilog.cplex.CpxLinearExpr.removeDuplicatesSafe(CpxLinearExpr.java:476)
at ilog.cplex.CpxCutCallback.addCut(CpxCutCallback.java:75)
at ilog.cplex.IloCplex$LazyConstraintCallback.add(IloCplex.java:14920)
at PDOP$IntegerCutCallback.main(PDOP.java:334)
at ilog.cplex.CpxCallback.callmain(CpxCallback.java:160)
at ilog.cplex.CpxLazyConstraintCallbackFunction.callIt(CpxLazyConstraintCallbackFunction.java:45)
at ilog.cplex.Cplex.CPXmipopt(Native Method)
at ilog.cplex.CplexI$SolveHandle.start(CplexI.java:2786)
at ilog.cplex.CplexI.solve(CplexI.java:2912)
at ilog.cplex.IloCplex.solve(IloCplex.java:10434)
at PDOP.solveIBR(PDOP.java:193)
at Application.main(Application.java:33)
I hope that this is no "too" stupid question, I've tried to find something on this behavior online, but did not find any examples in which an added variable was required.
I continued reading into it and it seems as if it is not possible at all to add additional variables in a LazyConstraint (https://www.or-exchange.org/questions/14311/adding-variables-or-modifying-existing-constraints-during-callbacks-with-cplex-c)
I was able to reformulate my problem (it is not as concise and easy to read, but works ...), it is faster than with directly including the subtour elimination constraint in the problem and still results in a feasible solution.
Thanks rkersh for your help :)

Java Insertion Sort with an Array List of objects?

I have a class Card which contains value (int), suit (String) and faceValue (String). It seems like a regular insertion sort on Card.value should work fine. I just use the whole object when moving things around. For some reason, this crashes and burns. It ends up duplicating the highest card into every element except for a random element that I can't understand.
value, suit, and faceValue are pulic, also.
This is my code:
public static void insertionSort(ArrayList<Card> Array) {
int i,j;
Card key = new Card(0, "","");
for (i = 1; i < Array.size(); i++) {
key.value = Array.get(i).value;
key.suit = Array.get(i).suit;
key.faceValue = Array.get(i).faceValue;
j = i;
while((j > 0) && (Array.get(j - 1).value > key.value)) {
Array.set(j,Array.get(j - 1));
j--;
}
Array.set(j,key);
}
}
I checked this against Wikipedia's pseudo code, and I can't find any fundamental difference. I've been through the debugger a dozen times, and I can't see any reason for the compiler to do what it's doing. Does anyone have an idea why it's not working?
Thanks.
I would like to extend ginz's answer.
Java objects are passed by reference.
So you are changing one object and setting it to multiple indexes.
To visualize (before and after):
For after: Please note that not all indexes must reference to same object. Some of them could remain unchanged.
Better approach would be to move objects, instead of trying to duplicate them.
Also, by Java standard, name of properties (variables) should always start with small letter.
Here is working code:
public static void insertionSort(ArrayList<Card> array) {
int i, j;
for (i = 1; i < array.size(); i++) {
Card tmp = array.get(i);
j = i;
while ((j > 0) && (array.get(j - 1).value > tmp.value)) {
array.set(j, array.get(j - 1));
j--;
}
array.set(j, tmp);
}
}
At every cycle, you insert the object "key" into the list (Array.set(j,key);). So, at the end your whole list will be made of references to the object "key". So when you set key.value, key.suit and key.faceValue at the end, you are setting the fields of every element of your list, because your list consists of references of the same object.
move Card key = new Card(0, "",""); inside the for cycle. Like this:
public static void insertionSort(ArrayList<Card> Array) {
int i,
j;
for (i = 1; i < Array.size(); i++) {
Card key = new Card(0, "","");
key.value = Array.get(i).value;
key.suit = Array.get(i).suit;
key.faceValue = Array.get(i).faceValue;
j = i;
while((j > 0) && (Array.get(j - 1).value > key.value)) {
Array.set(j,Array.get(j - 1));
j--;
}
Array.set(j,key);
}
}
gl with your studies :)
You're setting all the fields of Array(OMG, please rename it!) with the same element: key. So, all the elements would be the same.
The basic algorithm is
for each element
search for the first smaller element going downward
insert element right after that
So, in your case:
public static void insertionSort(ArrayList<Card> cards) {
for (int i = 1; i < cards.size(); i++) {
int value = cards.get(i).value;
j = i;
for (j = i-1; j >= 0; j--) {
if (cards.get(j).value <= key.value) {
break;
}
}
cards.add(j,cards.remove(i));
}
}
One important point here is that at no point does the array contains duplicated values (which happens when you use set)
Use Iterator for getting the elements.
public static void insertionSort(ArrayList<Integer> arrL) {
Iterator<Integer> it = arrL.iterator();
while(it.hasNext()){
int new_element = it.next();
int j = arrL.indexOf(new_element);
while(j>0 && arrL.get(j-1)>new_element){
arrL.set(j, arrL.get(j-1));
j--;
}
arrL.set(j, new_element);
}
}

Insertion sorting an endogenous list of cards

I have a method that sorts a hand of cards in an endogenous doubly linked list.
public void sort(Comparator<Card> cmp) {
// source code that I am adapting my code from
// for (int i=0; i < a.length; i++) {
// /* Insert a[i] into the sorted sublist */
// Object v = a[i];
// int j;
// for (j = i - 1; j >= 0; j--) {
// if (((Comparable)a[j]).compareTo(v) <= 0) break;
// a[j + 1] = a[j];
// }
// a[j + 1] = v;
// }
for(Card f = first; f!=null; f = f.next){
Card insert = f;
for(Card l = last; l!=null || l!= f; l = l.prev)
{
Card compare = l;
if(cmp.compare(compare, insert) <=0)
remove(insert);
this.add(insert);
break;
}
}
// Make sure to test invariant before and after
// You may find it helpful to use "remove" (but watch about size!)
}
When I run this code it is not sorting correctly. Any pointers?
At a quick glance, I see three bugs. There may be more.
Instead of l != null || l != f, I'm pretty sure you want && - the condition as you've written it is always true.
You should use {} to delimit the "true" branch of your if. Currently, this.add(insert); and break; will run whether the if condition is true or false - and your indentation suggests that this isn't what you're expecting.
In this.add(insert), you're not specifying where in the list to add the new node. I would expect to see something that specifies you'll be adding it at the position indicated by l.

Categories

Resources