i'm currently working on a small towerdefense project in Java and i got stuck with the pathfinding.
I read a lot about A* dijkstra and such things but i decided that it is probably the best to use Floyd-Warshall for pathfinding (at least it seems to me as its solving the all pair shortest path problem).
Anyway i tried to implement it on my own but it doesn't exactly work as it should.
i used the code on wikipedia as a start http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
So here's my Code:
public class MyMap {
public class MyMapNode {
// list of neighbour nodes
public List<MyMapNode> neighbours;
// Currently no need for this :)
public int cellX, cellY;
// NodeIndex for pathreconstruction
public int index;
// this value is checked by units on map to decide wether path needs
// reconstruction
public boolean isFree = true;
public MyMapNode(int cellX, int cellY, int index) {
this.cellX = cellX;
this.cellY = cellY;
this.index = index;
neighbours = new ArrayList<MyMapNode>();
}
public void addNeighbour(MyMapNode neighbour) {
neighbours.add(neighbour);
}
public void removeNeighbour(MyMapNode neighbour) {
neighbours.remove(neighbour);
}
public boolean isNeighbour(MyMapNode node) {
return neighbours.contains(node);
}
}
//MapSize
public static final int CELLS_X = 10;
public static final int CELLS_Y = 10;
public MyMapNode[][] map;
public MyMap() {
//Fill Map with Nodes
map = new MyMapNode[CELLS_X][CELLS_Y];
for (int i = 0; i < CELLS_X; i++) {
for (int j = 0; j < CELLS_Y; j++) {
map[i][j] = new MyMapNode(i, j, j + i * CELLS_Y);
}
}
//-------------------------------------------------
initNeighbours();
recalculatePath();
}
public void initNeighbours() {
//init neighbourhood without diagonals
for (int i = 0; i < CELLS_X; i++) {
for (int j = 0; j < CELLS_Y; j++) {
int x, y;// untere Grenze
if (j == 0)
y = 0;
else
y = -1;
if (i == 0)
x = 0;
else
x = -1;
int v, w;// obere Grenze
if (j == CELLS_Y - 1)
w = 0;
else
w = 1;
if (i == CELLS_X - 1)
v = 0;
else
v = 1;
for (int h = x; h <= v; h++) {
if (h != 0)
map[i][j].addNeighbour(map[i + h][j]);
}
for (int g = y; g <= w; g++) {
if (g != 0)
map[i][j].addNeighbour(map[i][j + g]);
}
}
}
}
//AdjacencyMatrix
public int[][] path = new int[CELLS_X * CELLS_Y][CELLS_X * CELLS_Y];
//for pathreconstruction
public MyMapNode[][] next = new MyMapNode[CELLS_X * CELLS_Y][CELLS_X
* CELLS_Y];
public void initAdjacency() {
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
path[i][j] = 1000;
List<MyMapNode> tmp = map[i][j].neighbours;
for (MyMapNode m : tmp) {
path[m.index][map[i][j].index] = 1;
path[map[i][j].index][m.index] = 1;
}
}
}
}
public void floydWarshall() {
int n = CELLS_X * CELLS_Y;
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (path[i][k] + path[k][j] < path[i][j]) {
path[i][j] = path[i][k] + path[k][j];
next[i][j] = getNodeWithIndex(k);
}
}
}
}
}
public void recalculatePath() {
initAdjacency();
floydWarshall();
}
public MyMapNode getNextWayPoint(MyMapNode i, MyMapNode j) {
if (path[i.index][j.index] >=1000)
return null;
MyMapNode intermediate = next[i.index][j.index];
if (intermediate == null)
return j; /* there is an edge from i to j, with no vertices between */
else
return getNextWayPoint(i, intermediate);
}
public MyMapNode getNodeWithIndex(int k) {
//for testing purpose,this can be done faster
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
if (map[i][j].index == k)
return map[i][j];
}
}
return null;
}
public void removeMapNode(MyMapNode m) {
//for testing purpose,this can be done faster
m.isFree = false;
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
if (map[i][j].neighbours.contains(m)) {
map[i][j].neighbours.remove(m);
}
}
}
}
}
the Floyd-Warshall algorithm is designed to work on a graph so i create one where every node knows its neighbours (which are the nodes it is connected to).
I actually don't now where it goes wrong but it somehow does.
but at least it looks like the initialization of the adjacency matrix works.
in the floydwarshall function i hoped to get the index of the next node in the next[][] but i only get null or 10/11;
So my question is what am i doing wrong or is my approach wrong at all?
i hope someone can help me.
if you need any further information please ask
p.S. sorry for my bad english ;)
I don't have Java available but it seems like your initAdjacency() function is flawed. path[][] is of dimension [CELL_X * CELLS_Y][CELLS_X * CELLS_Y] while you're iterating over the dimensions of map which are [CELL_X][CELL_Y] so you're not setting all the elements without edges to the default value of 1000 and they end up being 0.
Try adding
for (int i = 0; i < CELLS_X * CELLS_Y; i++)
for (int j = 0; j < CELLS_X * CELLS_Y; j++)
path[i][j] = 1000;
to the beginning of the initAdjacency() function, before your loop, to initialize it properly.
You may also want to do
for (int i = 0; i < CELLS_X * CELLS_Y) path[i][i] = 0;
after that just in case, I'm not sure this affects the algorithm.
Related
I want to calculoate the determinant of a given NxN Matrix using the Laplace-Method. I already tried differnt approaches which always return a 0.
The class I used:
package Matrix;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
public class Matrix
{
double[][] array;
public static void init(Matrix a,int row , int column)
{
a.array = new double [row] [column];
for (int i = 0; i < row; i++)
{
for(int k = 0; k < column; k++)
{
a.array[i][k] = 0;
}
}
}
public static int getNRows(Matrix a)
{
return a.array.length;
}
public static int getNColumns(Matrix a)
{
return a.array[0].length;
}
public static void print(Matrix a)
{
for(int i = 0; i < getNRows(a);i++ )
{
for (int k = 0; k < getNColumns(a); k++)
{
System.out.print(a.array[i][k] + "\t");
}
System.out.println();
}
}
public static double det(Matrix a)
{
double det = 0;
det = a.array[0][0] * a.array[1][1] * a.array[2][2] + a.array[1][0] * a.array[2][1] * a.array[0][2] + a.array[2][0] * a.array[0][1] * a.array[1][2] - a.array[2][0] * a.array[1][1] * a.array[0][2] - a.array[1][0] * a.array[0][1] * a.array[2][2] - a.array[0][0] * a.array[2][1] * a.array[1][2];
return det;
public static Matrix transpose(Matrix a)
{
Matrix transposed = new Matrix();
Matrix.init(transposed, getNRows(a), getNColumns(a));
for(int i = 0; i < getNRows(a); i++)
{
for(int j = 0; j < getNColumns(a); j++)
{
transposed.array[j][i] = a.array[i][j];
}
}
return transposed;
}
public static Matrix subMatrix(Matrix a, int exclRow, int exclCol)
{
Matrix subMatrix = new Matrix();
Matrix.init(subMatrix, getNRows(a) - 1, getNColumns(a) - 1);
for(int i = 0; i < getNRows(a) - 1; i++)
{
for(int j = 0; j < getNColumns(a) - 1; j++)
{
if(i != exclRow && j != exclCol)
{
subMatrix.array[i][j] = a.array[i][j];
}
}
}
return subMatrix;
}
public static Matrix loadMatrix(String filename) throws Exception
{
Scanner sc = new Scanner(new BufferedReader(new FileReader(filename)));
Matrix result = new Matrix();
int row = 0;
int col = 0;
String[] line = sc.nextLine().trim().split("\t");
row = Integer.parseInt(line[0]);
col = Integer.parseInt(line[1]);
init(result, row, col);
int currentRow = 0;
while(sc.hasNextLine())
{
String[] line2 =sc.nextLine().trim().split("\t");
for(int i = 0; i < col; i++)
{
result.array[currentRow][i] = Double.parseDouble(line2[i]);
}
currentRow++;
}
return result;
}
/*public static double detN(Matrix a)
{
int colOfA = getNColumns(a);
int rowOfA = getNRows(a);
double value = 1;
if(colOfA != rowOfA)
{
return 0;
}
if(colOfA == 1 && rowOfA == 1)
{
return a.array[0][0];
}
else
{
for(int row = 0; row < rowOfA; row++)
{
value += Math.pow(-1, row) * a.array[row][0] * detN(subMatrix(a, row, 0));
}
}
return value;
}*/
public static double detN(Matrix a)
{
int colOfA = getNColumns(a);
int rowOfA = getNRows(a);
if(colOfA != rowOfA)
{
return 0;
}
if(rowOfA <= 3)
{
return det(a);
}
double value = 0;
for(int row = 0; row < rowOfA; row++)
{
if(row % 2 == 0)
{
value += a.array[row][0] * detN(subMatrix(a, row, 0));
}
else
{
value -= a.array[row][0] * detN(subMatrix(a, row, 0));
}
}
return value;
}
public static Matrix adjointN(Matrix a)
{
int rowOfA = getNRows(a);
int colOfA = getNColumns(a);
Matrix ret = new Matrix();
Matrix.init(ret, rowOfA, colOfA);
for(int row = 0; row < rowOfA; row++)
{
for(int col = 0; col < colOfA; col++)
{
ret.array[row][col] = detN(subMatrix(a, row, col));
}
ret = transpose(ret);
return ret;
}
return ret;
}
public static Matrix inverseN(Matrix a)
{
Matrix inverse = new Matrix();
Matrix.init(inverse, getNRows(a), getNColumns(a));
double pre = 1/detN(a);
inverse = adjointN(a);
for(int i = 0; i < getNRows(a); i++)
{
for(int j = 0; j < getNColumns(a); j++)
{
inverse.array[j][i] = inverse.array[i][j] * pre;
}
}
return inverse;
}
}
I have two versions for detN, which both yield the same result.
This isn't the entire class, because there are some functions that don't belong to this particular question
Here is an approach you could consider(the code is not fully debugged so take with a grain of salt). Finding the determinant is a recursive concept since you are always finding the determinant of a smaller matrix to get the final answer.
//Recursive base function
public static double det(int[][] matrix) {
if(matrix.length == 2)
return ((matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]));
double determinant = 0;
int mlength = matrix.length - 1;
int[][] newM = new int[mlength][mlength];
for(int i = 0; i < mlength + 1; i++) {
newM = newMatrix(matrix, i);
determinant = determinant + (Math.pow(-1, i) * matrix[0][i]) * det(newM);
}
return determinant;
}
//Format smaller matrix to use in further iteration of above det(int[][]) function
public static int[][] newMatrix(int[][] m, int column) {
int length = m.length - 1;
int[][] newMat = new int[length][length];
for(int i = 1; i < m.length; i++) {
for(int j = 0; j < column; j++)
newMat[i - 1][j] = m[i][j];
for(int k = column + 1; k < m.length; k++)
newMat[i - 1][k - 1] = m[i][k];
}
return newMat;
}
You can adapt to however your Matrix class works.
subMatrix is not really excluding the given row and column - it is just making them zero (not copying) and removing the last row and column...
Printing the matrix will help debug that.
one way: use additional indices for the destination matrix (the sub matrix). Only increment this if a value is really copied. Example: sub.array[k++][l++] = a.array[i][j] inside the if
loop over original matrix
Alternative: if one index is greater than or equal to the index that must be skipped, add 1 to the reading index:
var k = (i>=exclRow) ? i+1 : i;
var l = (j>=exclCol) ? j+1 : j;
sub.array[i][j = a.array[k][l];
code not intended to be complete, just ideas how to solve the problem
I tried to code the naive solution for that, which tries to match a first index and then go deeper.
But I get true when I shouldn't and I cant find why.
this is my code (Java):
boolean contains(BufferedImage img, BufferedImage subImg, int[] coordinates){
boolean result = false;
int verticalLimit = img.getWidth() - subImg.getWidth();
int horizontalLimit =img.getHeight() - subImg.getHeight();
for (int i = 0; i <= horizontalLimit; i++) {
for (int j = 0; j <= verticalLimit; j++) {
if(img.getRGB(j, i) == subImg.getRGB(0, 0)){
result = true;
coordinates[0] = j; // stores the first indices for self use
coordinates[1] = i;
for (int k = i; k < subImg.getHeight() && result; k++) {
for (int l = j; l < subImg.getWidth() && result; l++) {
if(img.getRGB(l, k) != subImg.getRGB(l, k)){
result = false;
}
}
}
if(result) return result;
}
}
}
return result;
}
your search for the sub image is off. you jump way far into the sub image by indexing with k,l i've changed to 0 and using k,l as offsets from i,j. also use a labeled break from having to hold "found" state. if all of the pixels match it reaches the end of the loop and returns true otherwise it breaks and tries again until all possible locations are tried and returns false if none found.
static boolean contains(BufferedImage img, BufferedImage subImg, int[] coordinates) {
int verticalLimit = img.getWidth() - subImg.getWidth();
int horizontalLimit = img.getHeight() - subImg.getHeight();
for (int i = 0; i <= horizontalLimit; i++) {
for (int j = 0; j <= verticalLimit; j++) {
subSearch:
for (int k = 0; k < subImg.getHeight(); k++) {
for (int l = 0; l < subImg.getWidth(); l++) {
if (img.getRGB(l + j, k + i) != subImg.getRGB(l, k)) {
break subSearch;
}
}
if (k==subImg.getHeight()-1){
coordinates[0] = j;
coordinates[1] = i;
return true;
}
}
}
}
return false;
}
I'm currently working on implementing the Floyd Warshall algorithm from pseudocode to java. I felt like I had it correct, but anytime I ran it on a graph, I was getting an output of large negative number and I feel that it was probably the way I implemented my algorithm. After looking I realized I may have missed something. I haven't implemented the k-1 part of the pseudocode and I'm not sure how to implement this. Im hoping this will correct the issue.
Here it the code i have written.
public static int[][] floyd(int n, int[][] W, int[][] P, int[][] D) {
D = W;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
P[i][j] = 0;
for (int k = 0; k < n; k++)
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if ((D[i][j] == Integer.MAX_VALUE) && (D[i][k] + D[k][j] == Integer.MAX_VALUE)) { // add
continue;
} else if (D[i][j] <= D[i][k] + D[k][j]) {
D[i][j] = D[i][j];
} else {
D[i][j] = D[i][k] + D[k][j];
}
}
return D;
}
And here is the pseudocode im writing based off of.
Floyd-Warshall(W)
n = W.rows
D(0) = W
for (k = 1 to n)
for ( i = 1 to n )
for ( j = 1 to n )
if (dij(k-1) == INF) && (dik(k-1) + dkj(k-1)) == INF)
continue
else if (dij(k-1) ≤ dik(k-1) + dkj(k-1))
dij(k) = dij(k-1) // add
else
dij(k) = dik(k-1) + dkj(k-1) // add
return (D(n))
EDIT
Heres all of my code thats relevant with some corrections
int V = g.nodeList.size();
int W[][] = new int[V][V];
int P[][] = new int[V][V];
// Adding wights to graph
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
W[j][i] = Integer.parseInt(g.edgeList.get((j * V) + i).label);
if (W[j][i] == 0) {
W[i][j] = Integer.MAX_VALUE;
}
}
}
System.out.println("Matrix to find the shortest path of.");
printMatrix(W, V, g);
System.out.println("Shortest Path Matrix.");
printMatrix(floyd(V, W, P), V, g);
System.out.println("Path Matrix");
printPredMatrix(P, V, g);
}
public static int[][] floyd(int n, int[][] W, int[][] P) {
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
P[i][j] = 0;
for (int k = 0; k < n; k++)
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if ((W[i][j] == Integer.MAX_VALUE) && (W[i][k] + W[k][j] == Integer.MAX_VALUE)) { // add
continue;
} else if (W[i][j] <= W[i][k] + W[k][j]) {
W[i][j] = W[i][j];
} else {
W[i][j] = W[i][k] + W[k][j];
}
}
return W;
}
public static int min(int i, int j) {
if (i > j) {
return j;
}
return i;
}
public static void printMatrix(int[][] Matrix, int V, Graph g) {
System.out.print("\n\t");
for (int j = 0; j < V; j++) {
System.out.print(g.nodeList.get(j).name + "\t");
}
System.out.println();
for (int j = 0; j < 35; j++) {
System.out.print("-");
}
System.out.println();
for (int i = 0; i < V; i++) {
System.out.print(g.nodeList.get(i).name + " |\t");
for (int j = 0; j < V; j++) {
if ((Matrix[i][j] == Integer.MAX_VALUE)||(Matrix[i][j] == Integer.MIN_VALUE)) {
System.out.print("~");
} else {
System.out.print(Matrix[i][j]);
}
System.out.print("\t");
}
System.out.println("\n");
}
System.out.println("\n");
}
public static void printPredMatrix(int[][] Matrix, int V, Graph g) {
System.out.print("\n\t");
for (int j = 0; j < V; j++) {
System.out.print(g.nodeList.get(j).name + "\t");
}
System.out.println();
for (int j = 0; j < V * 3; j++) {
System.out.print("-");
}
System.out.println();
for (int i = 0; i < V; i++) {
System.out.print(g.nodeList.get(i).name + " |\t");
for (int j = 0; j < V; j++) {
System.out.print(Matrix[i][j]);
System.out.print("\t");
}
System.out.println("\n");
}
System.out.println("\n");
}
}```
I've written code for a 100 x 100 adjacency matrix that represents the following directed graph:
I'm attempting to use a Floyd-Warshall algorithm to find the shortest path for all pairs of blue nodes in the graph. How do you only find the all pairs shortest path for the selected nodes? Here's the code I've written thus far:
public class AdjacencyMatrix
{
public static final int NUM_NODES = 100;
public static final int INF = Integer.MAX_VALUE;
public static boolean even(int num)
{
return num%2==0;
}
public static boolean odd(int num)
{
return num%2==1;
}
public static void initialize(int [][] adjMat, int N)
{
for(int i = 0; i < N; i++)
for(int j = 0; j <N; j++)
adjMat[i][j]=INF;
for(int x = 0; x<N; x++)
{
int row = x/10;
int column = x%10;
if (even(row)) {
if (column!=9)
adjMat[x][x+1]=1;
}
if (odd(row)) {
if (column!=0)
adjMat[x][x-1]=1;
}
if (even(column)){
if (row!=9)
adjMat[x][x+10]=1;
}
if (odd(column)) {
if (row!=0)
adjMat[x][x-10]=1;
}
}
}
public void floydWarshall(int[][] adjMat, int N)
{
adjMat = new int[N][N];
initialize(adjMat, NUM_NODES);
for(int k = 0; k < N; ++k) {
for(int i = 0; i < N; ++i) {
for(int j = 0; j < N; ++j) {
adjMat[i][j] = Math.min(adjMat[i][j], adjMat[i][k] + adjMat[k][j]);
}
}
}
}
public static void main(String[] args)
{
int adjMat[][] = new int[NUM_NODES][NUM_NODES];
initialize(adjMat, NUM_NODES);
int A,B,C,D,E,F,G,H,I,W;
A = 20;
B = 18;
C = 47;
D = 44;
E = 53;
F = 67;
G = 95;
H = 93;
I = 88;
W = 66;
System.out.println(adjMat[A][B]);
System.out.println();
}
}
First of all, you should not assign new value to adjMat parameter in floydWarshall(), because the value will not be saved after exiting the method.
The next step is to check adjMat[i][k] and adjMat[k][j] for equality to INF and continue the loop if so:
for(int k = 0; k < N; ++k) {
for(int i = 0; i < N; ++i) {
for(int j = 0; j < N; ++j) {
if (adjMat[i][k] != INF && adjMat[k][j] != INF) {
adjMat[i][j] = Math.min(adjMat[i][j], adjMat[i][k] + adjMat[k][j]);
}
Shortest Floyd-Warshall algo implemenation:
for(int k = 0; k < N; ++k) {
for(int i = 0; i < N; ++i) {
for(int j = 0; j < N; ++j) {
adjMat[i][j] = Math.min(adjMat[i][j], adjMat[i][k] + adjMat[k][j]);
}
}
}
After running this piece of cade adjMat will contain shortest distances between every pair of nodes.
Update: to avoid integer overflow, fill the matrix with Integer.MAX_VALUE / 2. In general case, it's dangerous to set the maximum possible value to variable as infinity, because you can't perform addition operation with it.
I am trying to create a method that calculates (N choose R) using dynamic programming but I get an array out of bounds exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 7
at BinomialCoefficients.method5(BinomialCoefficients.java:127)
at BinomialCoefficients.main(BinomialCoefficients.java:50)
I am using a 2 dimensional array. Here is my code,
protected static long method5(long lN, long lR)
{
long lArray[][] = new long[(int) (lN+1)][(int) (lR+1)];
for(int i = 0; i <= lN; i++)
{
lArray[i][0] = 1;
}
for(int i = 0; i <= lN; i++)
{
lArray[i][i] = 1;
}
for(int i = 0; i <= lN; i++)
{
for(int j = i; j <= i; j++)
{
lArray[i][j] = lArray[i-1][j-1] + lArray[i-1][j];
}
}
/*for(int i = 0; i <= lN; i++)
{
for(int j = 0; j <= i; j++)
{
System.out.print(String.format("%5d", lArray[i][j]));
}
System.out.println();
}*/
return lArray[(int) lN][(int) lR];
}
Can somebody tell me what is wrong with it?
This code looks suspicious
for(int i = 0; i <= lN; i++)
{
lArray[i][i] = 1;
}
considering lArray was initialized using two potentially different values:
long lArray[][] = new long[(int) (lN+1)][(int) (lR+1)];
I think you should have an inner loop here, such as:
for(int i = 0; i <= lN; i++) {
for (int j=0; j<=lR; j++) {
lArray[i][j] = 1;
}
}
I see the indexing error has already been corrected. But will point out that you're allocating a square array when you only need one row. You're also not taking advantage of symmetry. Consider something like this:
public class Binomial {
public static long n_choose_r(int n, int r) {
r = Math.min(r, n - r);
long [] a = new long[r + 1];
a[0] = 1;
for (int i = 1; i <= n; ++i) {
if (i <= r) {
a[i] = 1;
}
for (int j = Math.min(r, i - 1); j > 0; --j) {
a[j] += a[j - 1];
}
}
return a[r];
}
public static void main(String [] args) {
System.out.println(n_choose_r(6, 4));
}
}