Printing shortest path of Floyd Warshall - java

I'm struggling with finishing my Floyd-Warshall algorithm, I've tried to write my program based on wikipedia pseudocode, but it doesn't work as suposed. I create second matrix to store changes in route so that's my code:
for (int w = 0; w < wierzcholki; w++)
{
for (int i = 0; i < wierzcholki; i++)
{
for (int j = 0; j < wierzcholki; j++)
{
if (tablica[i][w] + tablica[w][j] < tablica[i][j]) {
tablica[i][j] = tablica[i][w]
+ tablica[w][j];
next[i][j] = next[i][w];
}
}
}
}
This is my method to print shortest path
List<Double> Path(double i, double j) {
if (next[(int) i][(int) j] == Double.POSITIVE_INFINITY) {
return null;
}
List<Double> Wynik = new ArrayList<Double>();
while (i != j) {
i = next[(int) i][(int) j];
Wynik.add(i);
return Path(i, j);
}
return Wynik;
}
and then I call it out to find a route between all the nodes
Path(0, wierzcholki);
I've posted yesterday similar question (https://stackoverflow.com/questions/34828364/java-floyd-warshall-algorithm), but I think I've gotten closer to the solution so I decided to create new one. I hope it is allowed.

Related

How to get data slice in matrix

I want to take slices of data from the "MatrixEgoNetwork" matrix with "MatrixIndirectNode", but here I find difficulties, can you help me?
I tried to use retainAll() but I still couldn't
public double countSimilarity(double[][] matrixEgoNetwork, double[][] matrixIndirectNode, int index) {
if (matrixIndirectNode == null) {
return this.countDirectSimilarity(matrixEgoNetwork, index);
}
double sim = 0;
for (int i = 0; i < matrixEgoNetwork.length; i++) {
for (int j = 0; j < matrixEgoNetwork[0].length ; j++) {
matrixEgoNetwork[i][j].retainAll(matrixIndirectNode[i][index]) //"I tried to Use retainAll() but an error appeared Cannot resolve method"
if (matrixEgoNetwork[i][0] == matrixEgoNetwork[i][index] && matrixEgoNetwork[i][j]!=0) {
sim++;
}
}
}
return sim;
}
private double countDirectSimilarity(double[][] matrixEgoNetwork, int index) {
double sim = 0;
for (int i = 0; i < matrixEgoNetwork.length; i++) {
for (int j = 0; j < matrixEgoNetwork[0].length ; j++) {
if (matrixEgoNetwork[i][0]== matrixEgoNetwork[i][index] && matrixEgoNetwork[i][j]!=0) {
sim++;
}
}
}
return sim;
}
the output I want to produce is the amount of data obtained from the slice between the matrices, the error is Cannot resolve method when i use a retainAll to get data slice between the matrix, can you help me fix that?

Saving the shortest paths in a graph using the Floyd Warshall algorithm in java

I am trying to write a Betweeness Centrality method for a undirected, unweighted (weight = 1) Graph in Java. The way I have gone about it is by finding all of the shortest paths in the graph, and then iterating through those paths and counting how often a vertex is a step in that path. I have used the Floyd Warshall algorithm to find the shortest paths, and used another array to reconstruct the paths, similar to the pseudo code on the Wikipedia.
However, my results are not correct, and I have tried figuring out where the problem lies but I can't. I will just post the whole code in here for completeness sake, however it is messy so I apologize. I will comment the bits where I think the problems would occur.
public void calculateBetweenessCentrality() {
// Floyd warshall algorithm, storing paths with R
int noPath = Integer.MAX_VALUE / 4;
int[][] adjMatrix = getAdjacencyMatrix();
int distances[][] = new int[numVertices][numVertices];
int[][] R = new int[numVertices][numVertices];
// Initialize the arrays, setting "-5000" as null instead. Possible error here?
for (int i = 0; i < numVertices; i++) {
for (int j = 0; j < numVertices; j++) {
if (adjMatrix[i][j] == 0) {
distances[i][j] = noPath;
R[i][j] = -5000; // null
}
else {
distances[i][j] = adjMatrix[i][j];
R[i][j] = j;
}
}
}
// Do the algorithm, and save in R, possible error here?
for (int k = 0; k < numVertices; k++) {
for (int i = 0; i < numVertices; i++) {
for (int j = 0; j < numVertices; j++) {
if (distances[i][j] > distances[i][k] + distances[k][j]) {
distances[i][j] = distances[i][k] + distances[k][j];
R[i][j] = R[i][k];
}
}
}
}
// Go through R and construct the shortest paths, record the frequency for each node (indexs). Possible error here?
HashMap<Integer, Integer> frequencies = new HashMap<>(); // Key = index, Value = frequency
for (int i = 0; i < numVertices; i++) {
for (int j = 0; j < numVertices; j++) {
ArrayList<Integer> path = findShortestPath(R, i, j);
for (int p : path) {
int freq = frequencies.containsKey(p) ? frequencies.get(p) : 0;
frequencies.put(p, freq + 1);
}
}
}
HashMap<Integer, Integer> temp = new HashMap<Integer, Integer>(); // Instead of printing the vertex's adjacency matrix index value, get the actual value for displaying purposes.
for (Entry<Integer, Integer> freq : frequencies.entrySet()) {
temp.put(verticesIndexValue.get(freq.getKey()), freq.getValue());
}
System.out.println("Top 5 nodes: \nNode - Count");
frequencies.entrySet().stream().sorted(Map.Entry.comparingByValue(Collections.reverseOrder())).limit(5)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new))
.forEach((node, frequency) -> System.out.println(node + " - " + frequency));
}
private ArrayList<Integer> findShortestPath(int[][] R, int u, int v) {
ArrayList<Integer> paths = new ArrayList<>();
if(R[u][v] == -5000)
return paths;
paths.add(u);
while(u != v) {
u = R[u][v];
paths.add(u);
}
return paths;
}
The graph that I am testing this on is from this input here, where each line is an edge. The graph in that pastebin creates two connected components. The output I get for the first component is as follows:
Top 5 nodes:
Node - Count
11336782 - 11393
50393960 - 9047
627363 - 4079
849131 - 3799
5676102 - 3351
The answer is actually that 50393960 is the top node. If anybody could please guide me to where I am going wrong, I'd appreciate it massively. Thanks =)
Your code contains mistake in the place where it calculates frequencies - according to definition of Betweenness centrality when calculating it for particular vertex V you should exclude shortest paths which start or end with vertex V. Basically it means that when iterating over shortest paths you shoud not add start and end vertexes to frequencies. Try this instead:
HashMap<Integer, Integer> frequencies = new HashMap<>(); // Key = index, Value = frequency
for (int i = 0; i < numVertices; i++) {
for (int j = 0; j < numVertices; j++) {
ArrayList<Integer> path = findShortestPath(R, i, j);
for (int p : path) {
if (p == i || p == j) {
continue;
}
int freq = frequencies.containsKey(p) ? frequencies.get(p) : 0;
frequencies.put(p, freq + 1);
}
}
}

Can't generate right graph for bellman-ford algorithm

I have an implementation of the algorithm of Bellman - Ford.
The input program supplied a list of edges.
Without optimization it looks like this:
int i, j;
for (i = 0; i < number_of_vertices; i++) {
distances[i] = MAX;
}
distances[source] = 0;
for (i = 1; i < number_of_vertices - 1; ++i) {
for (j = 0; j < e; ++j) { //here i am calculating the shortest path
if (distances[edges.get(j).source] + edges.get(j).weight < distances[edges.get(j).destination]) {
distances[edges.get(j).destination] = distances[edges.get(j).source] + edges.get(j).weight;
}
}
}
it has the complexity of O(V * E)
But with optimization his works very fast. it looks like
while (true) {
boolean any = false;
for (j = 0; j < e; ++j) { //here i am calculating the shortest path
if (distances[edges.get(j).source] + edges.get(j).weight < distances[edges.get(j).destination]) {
distances[edges.get(j).destination] = distances[edges.get(j).source] + edges.get(j).weight;
any = true;
}
}
if (!any) break;
}
In practice, if the number of vertices , for example ten thousand , in the outer loop had only 10-12 passes iterations instead of 10 thousand, and the algorithm completes its work .
This is my generate code:
//q - vertices
for (int q = 100; q <= 20000; q += 100) {
List<Edge> edges = new ArrayList();
for (int i = 0; i < q; i++) {
for (int j = 0; j < q; j++) {
if (i == j) {
continue;
}
double random = Math.random();
if (random < 0.005) {
int x = ThreadLocalRandom.current().nextInt(1, 100000);
edges.add(new Edge(i, j, x));
edges++;
}
}
}
//write edges to file edges
}
But I need to generate a graph on which it will not be so fast to finish his work. That can be changed in the generator?
The complexity of Bellman Ford algorithm like you said is O(|E|*|V|). In your generator, the probability of adding an edge is negligible (0.005) which is why according to me the code works fast.
Increase the probability, there shall be more edges and consequently the Bellman Ford shall then take longer time.

Initialize the Columns of an Array in Java

I have three arrays of equal lengths that I combine (as I will sort them on column c later):
double abc[][] = {
Arrays.copyOf(a, a.length),
Arrays.copyOf(b, a.length),
Arrays.copyOf(c, a.length)
};
When I call
System.out.println(Arrays.deepToString(abc));
I receieve:
[[4.0, 2.0, 1.3333333333333333, 5.0, 2.5, 1.6666666666666667 ....
However, I would prefer something like:
[[1.0, 1.0, 4.0], [2.0, 2.0, 5.0], [3.0, 3.0, 7.0]]
This is possible using double singlets
double test[][] = {{1,1,4},{2,2,5},{3,3,7}};
How can I populate/initialize three columns using three double[ ]?
EDIT:
Solution based on vojta's answer:
double abcT[][] = new double[abc[0].length][abc.length];
for (int i = 0; i < abc.length; i++) {
for (int j = 0; j < abc[0].length; j++) {
abcT[j][i] = abc[i][j];
}
}
System.out.println(Arrays.deepToString(abcT));
I think there is no one-line solution of your problem, unfortunately. You will have to use some homemade code:
static <T> T[][] createMatrix(T[]... columns) {
if (columns== null || columns.length == 0)
return new T[0][0];
int wid = columns.length;
int ht = columns[0].length;
T[][] result = new T[ht][wid];
for (int x = 0; x < wid; x++) {
for (int y = 0; y < ht; y++) {
result[y][x] = columns[x][y];
}
}
return result;
}
I hope it was useful.
I finally reached this more elegant solution:
for (int i = 0; i < a.length; i++){
abc[0][i] = a[i];
abc[1][i] = b[i];
abc[2][i] = c[i];
}
Although it is not a general solution for n[], this avoids the need to make intermediate copies of the original arrays. And then I just swap the for-loops for row and column:
for (int j = 0; j < abc[0].length; j++) {
for (int i = 0; i < abc.length; i++) {
System.out.print(abc[i][j] + " ");
}
System.out.print("\n");
}
Note: This solution does not store in the intended R:C format, but retrieves in C:R.

Game of Life Matrix copy

I'm working on a version of Conway's Game of Life and I've created the method for creating a new Generation, where I copy a matrix and look for nearby neighbors. I would however like to split this method in to two seperate methods. A copy method of the matrix and then the original newGeneration would call on copy() for help. This is how my newGeneration method looks like right now.
public void newGeneration() {
temp = new boolean[board.getRows()][board.getCols()];
for (int i = 0; i < board.getRows(); i++) {
for (int j = 0; j < board.getCols(); j++) {
if (board.get(i, j)==true) {
if (getNeighbours(board, i, j) > 3) {
temp[i][j] = false;
} else if (getNeighbours(board, i, j) < 2) {
temp[i][j] = false;
} else{
temp[i][j] = true;
}
} else if (board.get(i, j) == false) {
if (getNeighbours(board, i, j) == 3) {
temp[i][j] = true;
}
}
}
}
for (int i = 0; i < board.getRows(); i++) {
for (int j = 0; j < board.getCols(); j++) {
board.put(i, j, temp[i][j]);
}
}
I want to split this in to two methods, newGeneration() and copy(). I've been working on it for a while now but I seem to screw up with the variables i and j because theyre locally set in the loops. Any help with splitting this method up in to two will be appreciated, thanks!
EDIT:
From some sage advice recommending me of this post, I made something like this
public void newGeneration() {
boolean[][] tempCells = new boolean [board.getRows()][board.getCols()];
for (int row = 0; row < board.getRows(); row++) {
for (int col = 0; col < board.getCols(); col++) {
int n = getNeighbours(board,row,col);
if (n > 3 || n < 2)
tempCells[row][col] = false;
else if (n == 3)
tempCells[row][col] = true;
else
tempCells[row][col] = temp[board.getRows()][board.getCols()];
}
}
}
But it doesn't seem to work properly.
A simple way to get a copy of an array is to clone it. Since clone gives just a shallow copy, it requires explicit cloning for each additional dimension for multidimensional arrays:
public static boolean[][] copy(boolean[][] source) {
boolean[][] copy = source.clone();
for (int i=0; i<copy.length; ++i) {
copy[i] = copy[i].clone();
}
return copy;
}

Categories

Resources