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'm having trouble with this polynomial class, specifically the checkZero and differentiate methods. The checkZero class is supposed to see if there are any leading coefficients in the polynomial, and if so, it should resize the coefficient array. The differentiate method should find the derivative of a polynomial, but I keep getting ArrayIndexOutOfBounds errors.
public class Polynomial {
private float[] coefficients;
public static void main (String[] args){
float[] fa = {3, 2, 4};
Polynomial test = new Polynomial(fa);
}
public Polynomial() {
coefficients = new float[1];
coefficients[0] = 0;
}
public Polynomial(int degree) {
coefficients = new float[degree+1];
for (int i = 0; i <= degree; i++)
coefficients[i] = 0;
}
public Polynomial(float[] a) {
coefficients = new float[a.length];
for (int i = 0; i < a.length; i++)
coefficients[i] = a[i];
}
public int getDegree() {
return coefficients.length-1;
}
public float getCoefficient(int i) {
return coefficients[i];
}
public void setCoefficient(int i, float value) {
coefficients[i] = value;
}
public Polynomial add(Polynomial p) {
int n = getDegree();
int m = p.getDegree();
Polynomial result = new Polynomial(Polynomial.max(n, m));
int i;
for (i = 0; i <= Polynomial.min(n, m); i++)
result.setCoefficient(i, coefficients[i] + p.getCoefficient(i));
if (i <= n) {
//we have to copy the remaining coefficients from this object
for ( ; i <= n; i++)
result.setCoefficient(i, coefficients[i]);
} else {
// we have to copy the remaining coefficients from p
for ( ; i <= m; i++)
result.setCoefficient(i, p.getCoefficient(i));
}
return result;
}
public void displayPolynomial () {
for (int i=0; i < coefficients.length; i++)
System.out.print(" "+coefficients[i]);
System.out.println();
}
private static int max (int n, int m) {
if (n > m)
return n;
return m;
}
private static int min (int n, int m) {
if (n > m)
return m;
return n;
}
public Polynomial multiplyCon (double c){
int n = getDegree();
Polynomial results = new Polynomial(n);
for (int i =0; i <= n; i++){ // can work when multiplying only 1 coefficient
results.setCoefficient(i, (float)(coefficients[i] * c)); // errors ArrayIndexOutOfBounds for setCoefficient
}
return results;
}
public Polynomial multiplyPoly (Polynomial p){
int n = getDegree();
int m = p.getDegree();
Polynomial result = null;
for (int i = 0; i <= n; i++){
Polynomial tmpResult = p.multiByConstantWithDegree(coefficients[i], i); //Calls new method
if (result == null){
result = tmpResult;
} else {
result = result.add(tmpResult);
}
}
return result;
}
public void checkZero(){
int newDegree = getDegree();
int length = coefficients.length;
float testArray[] = coefficients;
for (int i = coefficients.length-1; i>0; i--){
if (coefficients[i] != 0){
testArray[i] = coefficients[i];
}
}
for (int j = 0; j < testArray.length; j++){
coefficients[j] = testArray[j];
}
}
public Polynomial differentiate(){
int n = getDegree();
int newPolyDegree = n - 1;
Polynomial newResult = new Polynomial();
if (n == 0){
newResult.setCoefficient(0, 0);
}
for (int i =0; i<= n; i++){
newResult.setCoefficient(i, coefficients[i+1] * (i+1));
}
return newResult;
}
}
There might be more problems, but one is a problem with your differentiate method:
int n = getDegree();
...
Polynomial newResult = new Polynomial();
...
for (int i = 0; i <= n; i++)
{
newResult.setCoefficient(i, coefficients[i + 1] * (i + 1)); //This line
}
Your paramaterless constructor initializes an array with length 1, so "newResult" will only have 1 index, and you try to put something into place i, which goes above 1 if the Polynomial you are in have an array of greater length than 1.
First, a few code notes:
New arrays are automatically initialized to 0 in Java. This is not needed.
coefficients = new float[degree+1];
for (int i = 0; i <= degree; i++)
coefficients[i] = 0;
I also see many lines which might become more readable and compact if you use the trinary operator, for example:
int i;
for (i = 0; i <= Polynomial.min(n, m); i++)
result.setCoefficient(i, coefficients[i] + p.getCoefficient(i));
if (i <= n) {
//we have to copy the remaining coefficients from this object
for ( ; i <= n; i++)
result.setCoefficient(i, coefficients[i]);
} else {
// we have to copy the remaining coefficients from p
for ( ; i <= m; i++)
result.setCoefficient(i, p.getCoefficient(i));
}
Could become something like
for (int i = 0; i <= result.getDegree(); i++)
result.setCoefficient(i,
i>n?0:coefficients[i] +
i>m?0:p.getCoefficient(i));
The one bug I did spot was here:
int n = getDegree();
....
for (int i =0; i<= n; i++){
newResult.setCoefficient(i, coefficients[i+1] * (i+1));
}
This will always call coefficients[coefficients.length] on the last iteration, which will always fail.
The stack trace of the exception when you ran this program should tell you exactly where the error is, by the way.
I am trying to calculate the determinant of a matrix (of any size), for self coding / interview practice. My first attempt is using recursion and that leads me to the following implementation:
import java.util.Scanner.*;
public class Determinant {
double A[][];
double m[][];
int N;
int start;
int last;
public Determinant (double A[][], int N, int start, int last){
this.A = A;
this.N = N;
this.start = start;
this.last = last;
}
public double[][] generateSubArray (double A[][], int N, int j1){
m = new double[N-1][];
for (int k=0; k<(N-1); k++)
m[k] = new double[N-1];
for (int i=1; i<N; i++){
int j2=0;
for (int j=0; j<N; j++){
if(j == j1)
continue;
m[i-1][j2] = A[i][j];
j2++;
}
}
return m;
}
/*
* Calculate determinant recursively
*/
public double determinant(double A[][], int N){
double res;
// Trivial 1x1 matrix
if (N == 1) res = A[0][0];
// Trivial 2x2 matrix
else if (N == 2) res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
// NxN matrix
else{
res=0;
for (int j1=0; j1<N; j1++){
m = generateSubArray (A, N, j1);
res += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * determinant(m, N-1);
}
}
return res;
}
}
So far it is all good and it gives me a correct result. Now I would like to optimise my code by making use of multiple threads to calculate this determinant value.
I tried to parallelize it using the Java Fork/Join model. This is my approach:
#Override
protected Double compute() {
if (N < THRESHOLD) {
result = computeDeterminant(A, N);
return result;
}
for (int j1 = 0; j1 < N; j1++){
m = generateSubArray (A, N, j1);
ParallelDeterminants d = new ParallelDeterminants (m, N-1);
d.fork();
result += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * d.join();
}
return result;
}
public double computeDeterminant(double A[][], int N){
double res;
// Trivial 1x1 matrix
if (N == 1) res = A[0][0];
// Trivial 2x2 matrix
else if (N == 2) res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
// NxN matrix
else{
res=0;
for (int j1=0; j1<N; j1++){
m = generateSubArray (A, N, j1);
res += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * computeDeterminant(m, N-1);
}
}
return res;
}
/*
* Main function
*/
public static void main(String args[]){
double res;
ForkJoinPool pool = new ForkJoinPool();
ParallelDeterminants d = new ParallelDeterminants();
d.inputData();
long starttime=System.nanoTime();
res = pool.invoke (d);
long EndTime=System.nanoTime();
System.out.println("Seq Run = "+ (EndTime-starttime)/100000);
System.out.println("the determinant valaue is " + res);
}
However after comparing the performance, I found that the performance of the Fork/Join approach is very bad, and the higher the matrix dimension, the slower it becomes (as compared to the first approach). Where is the overhead? Can anyone shed a light on how to improve this?
Using This class you can calculate the determinant of a matrix with any dimension
This class uses many different methods to make the matrix triangular and then, calculates the determinant of it. It can be used for matrix of high dimension like 500 x 500 or even more. the bright side of the this class is that you can get the result in BigDecimal so there is no infinity and you'll have always the accurate answer. By the way, using many various methods and avoiding recursion resulted in much faster way with higher performance to the answer. hope it would be helpful.
import java.math.BigDecimal;
public class DeterminantCalc {
private double[][] matrix;
private int sign = 1;
DeterminantCalc(double[][] matrix) {
this.matrix = matrix;
}
public int getSign() {
return sign;
}
public BigDecimal determinant() {
BigDecimal deter;
if (isUpperTriangular() || isLowerTriangular())
deter = multiplyDiameter().multiply(BigDecimal.valueOf(sign));
else {
makeTriangular();
deter = multiplyDiameter().multiply(BigDecimal.valueOf(sign));
}
return deter;
}
/* receives a matrix and makes it triangular using allowed operations
on columns and rows
*/
public void makeTriangular() {
for (int j = 0; j < matrix.length; j++) {
sortCol(j);
for (int i = matrix.length - 1; i > j; i--) {
if (matrix[i][j] == 0)
continue;
double x = matrix[i][j];
double y = matrix[i - 1][j];
multiplyRow(i, (-y / x));
addRow(i, i - 1);
multiplyRow(i, (-x / y));
}
}
}
public boolean isUpperTriangular() {
if (matrix.length < 2)
return false;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < i; j++) {
if (matrix[i][j] != 0)
return false;
}
}
return true;
}
public boolean isLowerTriangular() {
if (matrix.length < 2)
return false;
for (int j = 0; j < matrix.length; j++) {
for (int i = 0; j > i; i++) {
if (matrix[i][j] != 0)
return false;
}
}
return true;
}
public BigDecimal multiplyDiameter() {
BigDecimal result = BigDecimal.ONE;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix.length; j++) {
if (i == j)
result = result.multiply(BigDecimal.valueOf(matrix[i][j]));
}
}
return result;
}
// when matrix[i][j] = 0 it makes it's value non-zero
public void makeNonZero(int rowPos, int colPos) {
int len = matrix.length;
outer:
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if (matrix[i][j] != 0) {
if (i == rowPos) { // found "!= 0" in it's own row, so cols must be added
addCol(colPos, j);
break outer;
}
if (j == colPos) { // found "!= 0" in it's own col, so rows must be added
addRow(rowPos, i);
break outer;
}
}
}
}
}
//add row1 to row2 and store in row1
public void addRow(int row1, int row2) {
for (int j = 0; j < matrix.length; j++)
matrix[row1][j] += matrix[row2][j];
}
//add col1 to col2 and store in col1
public void addCol(int col1, int col2) {
for (int i = 0; i < matrix.length; i++)
matrix[i][col1] += matrix[i][col2];
}
//multiply the whole row by num
public void multiplyRow(int row, double num) {
if (num < 0)
sign *= -1;
for (int j = 0; j < matrix.length; j++) {
matrix[row][j] *= num;
}
}
//multiply the whole column by num
public void multiplyCol(int col, double num) {
if (num < 0)
sign *= -1;
for (int i = 0; i < matrix.length; i++)
matrix[i][col] *= num;
}
// sort the cols from the biggest to the lowest value
public void sortCol(int col) {
for (int i = matrix.length - 1; i >= col; i--) {
for (int k = matrix.length - 1; k >= col; k--) {
double tmp1 = matrix[i][col];
double tmp2 = matrix[k][col];
if (Math.abs(tmp1) < Math.abs(tmp2))
replaceRow(i, k);
}
}
}
//replace row1 with row2
public void replaceRow(int row1, int row2) {
if (row1 != row2)
sign *= -1;
double[] tempRow = new double[matrix.length];
for (int j = 0; j < matrix.length; j++) {
tempRow[j] = matrix[row1][j];
matrix[row1][j] = matrix[row2][j];
matrix[row2][j] = tempRow[j];
}
}
//replace col1 with col2
public void replaceCol(int col1, int col2) {
if (col1 != col2)
sign *= -1;
System.out.printf("replace col%d with col%d, sign = %d%n", col1, col2, sign);
double[][] tempCol = new double[matrix.length][1];
for (int i = 0; i < matrix.length; i++) {
tempCol[i][0] = matrix[i][col1];
matrix[i][col1] = matrix[i][col2];
matrix[i][col2] = tempCol[i][0];
}
} }
This Class Receives a matrix of n x n from the user then calculates it's determinant. It also shows the solution and the final triangular matrix.
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Scanner;
public class DeterminantTest {
public static void main(String[] args) {
String determinant;
//generating random numbers
/*int len = 300;
SecureRandom random = new SecureRandom();
double[][] matrix = new double[len][len];
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
matrix[i][j] = random.nextInt(500);
System.out.printf("%15.2f", matrix[i][j]);
}
}
System.out.println();*/
/*double[][] matrix = {
{1, 5, 2, -2, 3, 2, 5, 1, 0, 5},
{4, 6, 0, -2, -2, 0, 1, 1, -2, 1},
{0, 5, 1, 0, 1, -5, -9, 0, 4, 1},
{2, 3, 5, -1, 2, 2, 0, 4, 5, -1},
{1, 0, 3, -1, 5, 1, 0, 2, 0, 2},
{1, 1, 0, -2, 5, 1, 2, 1, 1, 6},
{1, 0, 1, -1, 1, 1, 0, 1, 1, 1},
{1, 5, 5, 0, 3, 5, 5, 0, 0, 6},
{1, -5, 2, -2, 3, 2, 5, 1, 1, 5},
{1, 5, -2, -2, 3, 1, 5, 0, 0, 1}
};
*/
double[][] matrix = menu();
DeterminantCalc deter = new DeterminantCalc(matrix);
BigDecimal det = deter.determinant();
determinant = NumberFormat.getInstance().format(det);
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix.length; j++) {
System.out.printf("%15.2f", matrix[i][j]);
}
System.out.println();
}
System.out.println();
System.out.printf("%s%s%n", "Determinant: ", determinant);
System.out.printf("%s%d", "sign: ", deter.getSign());
}
public static double[][] menu() {
Scanner scanner = new Scanner(System.in);
System.out.print("Matrix Dimension: ");
int dim = scanner.nextInt();
double[][] inputMatrix = new double[dim][dim];
System.out.println("Set the Matrix: ");
for (int i = 0; i < dim; i++) {
System.out.printf("%5s%d%n", "row", i + 1);
for (int j = 0; j < dim; j++) {
System.out.printf("M[%d][%d] = ", i + 1, j + 1);
inputMatrix[i][j] = scanner.nextDouble();
}
System.out.println();
}
scanner.close();
return inputMatrix;
}}
The main reason the ForkJoin code is slower is that it's actually serialized with some thread overhead thrown in. To benefit from fork/join, you need to 1) fork all instances first, then 2) wait for the results. Split your loop in "compute" into two loops: one to fork (storing instances of ParallelDeterminants in, say, an array) and another to collect the results.
Also, I suggest to only fork at the outermost level and not in any of the inner ones. You don't want to be creating O(N^2) threads.
There is a new method of calculating the determinant of the matrix you can read more from here
and I've implemented a simple version of this with no fancy optimization techniques or library in plain simple java and I've tested against methods described previously and it was faster on average by a factor of 10
public class Test {
public static double[][] reduce(int row , int column , double[][] mat){
int n=mat.length;
double[][] res = new double[n- 1][n- 1];
int r=0,c=0;
for (int i = 0; i < n; i++) {
c=0;
if(i==row)
continue;
for (int j = 0; j < n; j++) {
if(j==column)
continue;
res[r][c] = mat[i][j];
c++;
}
r++;
}
return res;
}
public static double det(double mat[][]){
int n = mat.length;
if(n==1)
return mat[0][0];
if(n==2)
return mat[0][0]*mat[1][1] - (mat[0][1]*mat[1][0]);
//TODO : do reduce more efficiently
double[][] m11 = reduce(0,0,mat);
double[][] m1n = reduce(0,n-1,mat);
double[][] mn1 = reduce(n-1 , 0 , mat);
double[][] mnn = reduce(n-1,n-1,mat);
double[][] m11nn = reduce(0,0,reduce(n-1,n-1,mat));
return (det(m11)*det(mnn) - det(m1n)*det(mn1))/det(m11nn);
}
public static double[][] randomMatrix(int n , int range){
double[][] mat = new double[n][n];
for (int i=0; i<mat.length; i++) {
for (int j=0; j<mat[i].length; j++) {
mat[i][j] = (Math.random()*range);
}
}
return mat;
}
public static void main(String[] args) {
double[][] mat = randomMatrix(10,100);
System.out.println(det(mat));
}
}
there is a little fault in the case of the determinant of m11nn if happen to be zero it will blow up and you should check for that. I've tested on 100 random samples it rarely happens but I think it worth mentioning and also using a better indexing scheme can also improve the efficiency
This is a part of my Matrix class which uses a double[][] member variable called data to store the matrix data.
The _determinant_recursivetask_impl() function uses a RecursiveTask<Double> object with the ForkJoinPool to try to use multiple threads for calculation.
This method performs very slow compared to matrix operations to get an upper/lower triangular matrix. Try to compute the determinant of a 13x13 matrix for example.
public class Matrix
{
// Dimensions
private final int I,J;
private final double[][] data;
private Double determinant = null;
static class MatrixEntry
{
public final int I,J;
public final double value;
private MatrixEntry(int i, int j, double value) {
I = i;
J = j;
this.value = value;
}
}
/**
* Calculates determinant of this Matrix recursively and caches it for future use.
* #return determinant
*/
public double determinant()
{
if(I!=J)
throw new IllegalStateException(String.format("Can't calculate determinant of (%d,%d) matrix, not a square matrix.", I,J));
if(determinant==null)
determinant = _determinant_recursivetask_impl(this);
return determinant;
}
private static double _determinant_recursivetask_impl(Matrix m)
{
class determinant_recurse extends RecursiveTask<Double>
{
private final Matrix m;
determinant_recurse(Matrix m) {
this.m = m;
}
#Override
protected Double compute() {
// Base cases
if(m.I==1 && m.J==1)
return m.data[0][0];
else if(m.I==2 && m.J==2)
return m.data[0][0]*m.data[1][1] - m.data[0][1]*m.data[1][0];
else
{
determinant_recurse[] tasks = new determinant_recurse[m.I];
for (int i = 0; i <m.I ; i++) {
tasks[i] = new determinant_recurse(m.getSubmatrix(0, i));
}
for (int i = 1; i <m.I ; i++) {
tasks[i].fork();
}
double ret = m.data[0][0]*tasks[0].compute();
for (int i = 1; i < m.I; i++) {
if(i%2==0)
ret += m.data[0][i]*tasks[i].join();
else
ret -= m.data[0][i]*tasks[i].join();
}
return ret;
}
}
}
return ForkJoinPool.commonPool().invoke(new determinant_recurse(m));
}
private static void _map_impl(Matrix ret, Function<Matrix.MatrixEntry, Double> operator)
{
for (int i = 0; i <ret.I ; i++) {
for (int j = 0; j <ret.J ; j++) {
ret.data[i][j] = operator.apply(new Matrix.MatrixEntry(i,j,ret.data[i][j]));
}
}
}
/**
* Returns a new Matrix that is sub-matrix without the given row and column.
* #param removeI row to remove
* #param removeJ col. to remove
* #return new Matrix.
*/
public Matrix getSubmatrix(int removeI, int removeJ)
{
if(removeI<0 || removeJ<0 || removeI>=this.I || removeJ>=this.J)
throw new IllegalArgumentException(String.format("Invalid element position (%d,%d) for matrix(%d,%d).", removeI,removeJ,this.I,this.J));
Matrix m = new Matrix(this.I-1, this.J-1);
_map_impl(m, (e)->{
int i = e.I, j = e.J;
if(e.I >= removeI) ++i;
if(e.J >= removeJ) ++j;
return this.data[i][j];
});
return m;
}
// Constructors
public Matrix(int i, int j) {
if(i<1 || j<1)
throw new IllegalArgumentException(String.format("Invalid array dimensions: (%d,%d)", i, j));
I = i;
J = j;
data = new double[I][J];
}
}
int det(int[][] mat) {
if (mat.length == 1)
return mat[0][0];
if (mat.length == 2)
return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
int sum = 0, sign = 1;
int newN = mat.length - 1;
int[][] temp = new int[newN][newN];
for (int t = 0; t < newN; t++) {
int q = 0;
for (int i = 0; i < newN; i++) {
for (int j = 0; j < newN; j++) {
temp[i][j] = mat[1 + i][q + j];
}
if (q == i)
q = 1;
}
sum += sign * mat[0][t] * det(temp);
sign *= -1;
}
return sum;
}