Finding neighbors to Points in an ArrayList - java

I've recently started learning Java and though doing a "Conway's Game of Life" style program would be a good thing to start out with. Everything works fine but I'm having some serious performance issues with this part:
static List<Point> coordList = new ArrayList<Point>();
public int neighbors(int x, int y){
int n = 0;
Point[] tempArray = { new Point(x-1, y-1), new Point(x, y-1), new Point(x+1, y-1),
new Point(x-1, y ), new Point(x+1, y ),
new Point(x-1, y+1), new Point(x, y+1), new Point(x+1, y+1)};
for (Point p : tempArray) {
if (coordList.contains(p))
n++;
}
return n;
}
The method is used when iterating the ArrayList coordList filled with Points and checking every element how many neighbors they have. When the list size gets to about 10000 Points every cycle takes about 1 seconds and for 20000 Points it takes 7 seconds.
My question is, what would be a more effective way to do this? I know there are several other programs of this kind with source code available too look at, but I wan't do do as much as I can by my self since the point of the project is me learning Java. Also, I don't want to use a regular array because of the limitations.

If your points are unique, you could store them in a HashSet instead of an ArrayList. The contains method will then become an O(1) operation vs. O(n) in your current setup. That should speed up that section significantly.
Apart from the declaration, your code should remain mostly unchanged as both implement the Collection interface, unless you call List-specific method such as get(i) for example.

Performance-wise, I think your best bet is to have a plain numeric (effectively Boolean) array representing the grid. Since this is a learning exercise, I'd start with a simple one-element-per-cell array, and then perhaps progress to packing eight adjacent cells into a single byte.
It is not entirely clear what you mean by "the limitations".
The following has some interesting pointers: Optimizing Conway's 'Game of Life'

Your current code scales in a quadratic manner O(n^2). You have only given part of the program. If you look at your whole program there will be a loop that calls neighbors() and you will see that neighbors() is called n times. Also the operation contains() is linear in n, so the time is proportional to their product n*n.
Quadratic scaling is a common problem but can often be reduced to linear by using indexed data structures such as HashSet.

Related

Efficient Intersection and Union of Lists of Strings

I need to efficiently find the ratio of (intersection size / union size) for pairs of Lists of strings. The lists are small (mostly about 3 to 10 items), but I have a huge number of them (~300K) and have to do this on every pair, so I need this actual computation to be as efficient as possible. The strings themselves are short unicode strings -- averaging around 5-10 unicode characters.
The accepted answer here Efficiently compute Intersection of two Sets in Java? looked extremely helpful but (likely because my sets are small (?)) I haven't gotten much improvement by using the approach suggested in the accepted answer.
Here's what I have so far:
protected double uuEdgeWeight(UVertex u1, UVertex u2) {
Set<String> u1Tokens = new HashSet<String>(u1.getTokenlist());
List<String> u2Tokens = u2.getTokenlist();
int intersection = 0;
int union = u1Tokens.size();
for (String s:u2Tokens) {
if (u1Tokens.contains(s)) {
intersection++;
} else {
union++;
}
}
return ((double) intersection / union);
My question is, is there anything I can do to improve this, given that I'm working with Strings which may be more time consuming to check equality than other data types.
I think because I'm comparing multiple u2's against the same u1, I could get some improvement by doing the cloning of u2 into a HashSet outside of the loop (which isn't shown -- meaning I'd pass in the HashSet instead of the object from which I could pull the list and then clone into a set)
Anything else I can do to squeak out even a small improvement here?
Thanks in advance!
Update
I've updated the numeric specifics of my problem above. Also, due to the nature of the data, most (90%?) of the intersections are going to be empty. My initial attempt at this used the clone the set and then retainAll the items in the other set approach to find the intersection, and then shortcuts out before doing the clone and addAll to find the union. That was about as efficient as the code posted above, presumably because of the trade of between it being a slower algorithm overall versus being able to shortcut out a lot of the time. So, I'm thinking about ways to take advantage of the infrequency of overlapping sets, and would appreciate any suggestions in that regard.
Thanks in advance!
You would get a large improvement by moving the HashSet outside of the loop.
If the HashSet really has only got a few entries in it then you are probably actually just as fast to use an Array - since traversing an array is much simpler/faster. I'm not sure where the threshold would lie but I'd measure both - and be sure that you do the measurements correctly. (i.e. warm up loops before timed loops, etc).
One thing to try might be using a sorted array for the things to compare against. Scan until you go past current and you can immediately abort the search. That will improve processor branch prediction and reduce the number of comparisons a bit.
If you want to optimize for this function (not sure if it actually works in your context) you could assign each unique String an Int value, when the String is added to the UVertex set that Int as a bit in a BitSet.
This function should then become a set.or(otherset) and a set.and(otherset). Depending on the number of unique Strings that could be efficient.

Finding Rectangle which contains a Point

In Java SE 7, I'm trying to solve a problem where I have a series of Rectangles. Through some user interaction, I get a Point. What I need to do is find the (first) Rectangle which contains the Point (if any).
Currently, I'm doing this via the very naieve solution of just storing the Rectangles in an ArrayList, and searching for the containing Rectangle by iterating over the list and using contains(). The problem is that, because this needs to be interactive for the user, this technique starts to be too slow for even a relatively small number of Rectangles (say, 200).
My current code looks something like this:
// Given rects is an ArrayList<Rectangle>, and p is a Point:
for(Rectangle r : rects)
{
if(r.contains(p))
{
return r;
}
}
return null;
Is there a more clever way to solve this problem (namely, in O(log n) instead of O(n), and/or with fewer calls to contains() by eliminating obviously bad candidates early)?
Yes, there is. Build 2 interval trees which will tell you if there is a rectangle between x1 to x2 and between y1 and y2. Then, when you have the co-ordinates of the point, perform O(log n) searches in both the trees.
That'll tell you if there are possibly rectangles around the point of interest. You still need to check if there is a common rectangle given by the two trees.

Java TSP Permute Points

Doing a project for school where we implement the Nearest Neighbor heuristic (which I have already done), and the Traveling Salesperson Problem where we do an exhaustive search (we then analyze the algorithms, their time complexity, etc). Our teacher said to look around for code to use (or modify) for the exhaustive search part instead of programming the whole thing as in the Nearest Neighbor portion. I have looked around, put only found stuff that does not pertain to how we were instructed to do our program.
As opposed to the typical problem where you use integers, we are using points (x, y).
My goal would be to calculate the shortest permutation and be able to know what that permutation was. So I'm thinking to have an array of array's (which contains the permutations).
If someone could help me out with the exhaustive search that would be nice.
Here is some excerpts from my code (member variables, function to calculate distance between two points, and where all the points are stored):
private int x;
private int y;
private boolean visited;
public double dist( point pt ){
int xdist = this.getX() - pt.getX();
int ydist = this.getY() - pt.getY();
double xsr = xdist*xdist;
double ysr = ydist*ydist;
return Math.sqrt( xsr + ysr );
}
point[] points = new point[n];
Any help is greatly appreciated.
A single TSP possible solution is essentially just an array of cities which represents the order in which to visit them, without the starting city.
So, presume n (the number of cities) = 5. Then a single possible solution is represented as an array of length 4. Now, how many ways can you order the cities [B, C, D, E]?
BCDE, BCED, BDCE, BDEC, ... That's 4! or 24 combinations. So for n cities you got (n-1)! combinations. For 10 cities that makes 362880 combinations. For 20 cities or 10^17 combinations you 'll run out of memory if you want to keep them all into memory.
An additional problem is that you 'll need n nested for loops, but it's impossible to just write those for loops, because there are n. (You can just start writing for() for() for() ....
So, your implementation will probably need some sort of walker approach, where you have a single loop that ticks through all combinations, much like a digital clock with each digit representing 1 index in the array.
You don't need (extra) memory for generating all permutations/solutions for a given instance. You can just write them on the screen...
Take a look at this implementation https://github.com/stardog-union/pellet/blob/master/core/src/main/java/org/mindswap/pellet/utils/PermutationGenerator.java.
It generates at each call of getNext() a new solution.
public void PermGen() {
int[] tour;
PermutationGenerator x = new PermutationGenerator(N);
System.out.println(x.getTotal());
while (x.hasMore()) {
tour = x.getNext();
System.out.println(Arrays.toString(tour));
}
}
The Java code above prints all TSP instance solutions...
But You can of course save them (in file(s) for example) but you'll need hundred of Terabytes to do it.

Collision Detection with MANY objects

I mainly focused on the Graphics aspects to create a little 2DGame. I've watched/looked at several tutorials but none of them were that pleasing. I already have a player(a square) moving and colliding with other squares on the screen. Gravity etc. Are also done.
If there are only that much objects as seen on the screen (30*20), everything works perfectly fine. But if I increase it to let's say 300*300 the program starts to run very slow since it has to check for so many objects.
I really don't get how games like Minecraft can work with ALL THOSE blocks and my program already gives up on 300*300 blocks.
I already tried to ONLY check for collisions when the objects are visible, but that leads to the program checking every single object for it's visibility leading to the same problem.
What am I doing wrong? Help appreciated.
I'll post some code on how I handle the collisions.
player.collision(player, wall);
public void collision(Tile object1, Tile[] object2){
collisionCheckUp(object1, object2);
collisionCheckDown(object1, object2);
collisionCheckLeft(object1, object2);
collisionCheckRight(object1, object2);
}
public void collisionCheckDown(Tile object1, Tile[] object2){
for (int i = 0; i < Map.tileAmount; i++){
if(object2[i] != null && object2[i].visible)
{
if(object1.isCollidingDown(object2[i])){
object1.collisionDown = true;
return;
}
}
}
object1.collisionDown = false;
}
public void compileHullDown(){
collisionHull = new Rectangle((int)x+3, (int)y+3, width-6, height);
}
int wallCount = 0;
for (int x=0;x<Map.WIDTH;x++) {
for (int y=0;y<Map.HEIGHT;y++) {
if (Map.data[x][y] == Map.BLOCKED) {
wall[wallCount] = new Tile(x * Map.TILE_SIZE, y * Map.TILE_SIZE);
wallCount++;
}
}
}
The usual approach to optimize collision detection is to use a space partition to classify/manage your objects.
The general idea of the approach is that you build a tree representing the space and put your objects into that tree, according to their positions. When you calculate the collisions, you traverse the tree. This way, you will have to perform significantly less calculations than using the brute force approach, because you will be ignoring all objects in branches other than the one you're traversing. Minecraft and similar probably use octrees for collision (and maybe for rendering too).
The most common space partition structures are BSP-Trees, kd-Trees (a special type of BSP-trees). The simpler approach would be to use a uniform space partition for the start - split your space in axis-aligned halves.
The best resource on collision that I have discovered is this book. It should clarify all your questions on the topic.
That's if you wanted to do it right. If you want to do it quick, you could just sample the color buffer around your character, or only in the movement direction to determine if an obstacle is close.
As Kostja mentioned, it will be useful for you to partition your space. However, you will need to use QuadTrees instead of Octrees as you are only in 2D not 3D.
Here are is a nice article to get you started on QuadTrees.
You can cut your overhead by a factor of 4 by, instead of calculating collisions for up/down/left/right, calculating collisions once and using the relative positions of the two objects to find out if you hit a floor, wall, or ceiling. Another good idea is to only pay attention to the objects that are nearby - maybe once every 0.25 seconds make a list of all objects that are probably close enough to collide with in the next 0.25 seconds?

Is it okay to iterate over a list within another iteration of the same list?

I have some objects in an ArrayList, and I want to perform collision detection and such. Is it okay to do something like:
List<Person> A;
iterA0 = A.iterator();
while (iterA0.hasNext()) {
Person A = iterA.next();
iterA1 = A.iterator();
while (iterA1.hasNext()){
Person B = iterA1.next();
A.getsDrunkAndRegretsHookingUpWith(B);
}
}
That's gotta be terrible coding, right? How would I perform this nested iteration appropriately?
You can iterate over the same list multiple times concurrently, as long as it's not being modified during any of the iterations. For example:
List<Person> people = ...;
for (Person a : people) {
for (Person b : people)
a.getsDrunkAndRegretsHookingUpWith(b);
}
As long as the getsDrunkAndRegretsHookingUpWith method doesn't change the people list, this is all fine.
This is an example of the classic handshake problem. In a room full of n people, there are n choose 2 different possible handshakes. You can't avoid the quadratic runtime.
#Chris' answer shows you a better way to code it.
Re: OP comment
What I've been cooking up is some code where an event causes a particle to explode, which causes all nearby particles to explode...chain reaction. The objects are stored in one list and the non-exploded particles only explode if they are within a defined radius of an exploding ones. So I could dish up some conditionals to make it a bit faster, but still need the n^2 traversal.
You should not use a list to store the particles. If you're modeling particles in 2 dimentions, use a quadtree. If 3 dimensions, an octree.
Number of iterations can be reduced if in you case:
A.getsDrunkAndRegretsHookingUpWith(B) implies B.getsDrunkAndRegretsHookingUpWith(A) too,
and A.getsDrunkAndRegretsHookingUpWith(A) will always be same for all elements
then instead of using iterator or foreach, you can take more traditional approach and exclude collision with itself and with the elements with withc comparison has already taken place.
List<Person> people;
for (int i=0; i<people.size(); i++){
a = people.get(i);
for (int j=i+1; j<people.size();j++){ // compare with next element and onwards in the list
a.getsDrunkAndRegretsHookingUpWith(people.get(j)); // call method
}
}
That's gotta be terrible coding, right?
Most people would probably agree that if you were using Java 5+, and there was no particular need to expose the iterator objects, then you should simplify the code by using a "for each" loop. However, this should make no difference to the performance, and certainly not to the complexity.
Exposing the iterators unnecessarily is certainly not terrible programming. On a scale of 1 to 10 of bad coding style, this is only a 1 or 2. (And anyone who tells you otherwise hasn't seen any truly terrible coding recently ... )
So how to do n^2 over oneself?
Your original question is too contrived to be able to give an answer to that question.
Depending on what the real relation is, you may be able to exploit symmetry / anti-symmetry, or associativity to reduce the amount of work.
However, without that information (or other domain information), you can't improve on this solution.
For your real example (involving particles), you can avoid the O(N^2) comparison problem by dividing the screen into regions; e.g. using quadtrees. Then you iterate over points in the same and adjacent regions.

Categories

Resources