Creating a custom matrix class I implemented multiplication with ikj algorithm and now I'm trying to optimize it. The problem is that the version that should work better is about 5 times slower and I can't understand why.
This is the Matrix class with the "basic" algorithm:
class Matrix {
private double[][] m; // matrix
private int rows;
private int cols;
// other stuff...
// does some checks and returns requested matrix value
// I know this will slow down computation, but it's not the relevant part
public double get(int row, int col) {
if (row >= rows || col >= cols)
throw new IndexOutOfBoundsException(); // to catch block
else
return m[startRow + row][startCol + col];
}
public Matrix multiply(Matrix other) {
int n = rows;
int m = cols;
int p = other.cols;
double[][] prod = new double[n][p];
for (int i = 0; i < n; i++)
for (int k = 0; k < m; k++)
for (int j = 0; j < p; j++)
prod[i][j] += get(i,k) * other.get(k,j);
return new Matrix(prod);
}
}
And this is the modified algorithm:
public Matrix multiplyOpt(Matrix other) {
int n = rows;
int m = cols;
int p = other.cols;
double[][] prod = new double[n][p];
for (int i = 0; i < n; i++) {
for (int k = 0; k < m; k++) {
double aik = get(i,k);
for (int j = 0; j < p; j++) {
prod[i][j] += aik * other.get(k,j);
}
}
}
return new Matrix(prod);
}
My though was that moving that get call outside the loop it will be called n x m times instead of n x m x p.
These are the results of a random matrix multiplication (exception is never thrown):
multiply time = 0.599s
multiplyOpt time = 3.041s
Why this change makes it slower and not faster?
EDIT
Timings are obtained with:
double[][] m1 = new double[1000][750];
double[][] m2 = new double[750][1250];
for (int i = 0; i < m1.length; i++)
for (int j = 0; j < m1[0].length; j++)
m1[i][j] = new Double(Math.random());
for (int i = 0; i < m2.length; i++)
for (int j = 0; j < m2[0].length; j++)
m2[i][j] = new Double(Math.random());
Matrix a = new Matrix(m1);
Matrix b = new Matrix(m2);
long start = System.currentTimeMillis();
Matrix c = a.multiply(b);
long stop = System.currentTimeMillis();
double time = (stop - start) / 1000.0;
System.out.println("multiply time = "+time);
start = System.currentTimeMillis();
c = a.multiplyOpt(b);
stop = System.currentTimeMillis();
time = (stop - start) / 1000.0;
System.out.println("multiplyOpt time = "+time);
Related
Create a basics.Matrix class (using a two-dimensional array of real numbers as a matrix) that has the following operations: construct an M × N zero matrix, construct an M × N matrix using an M × N array, create an N × N dimensional unit matrix ( the result matrix should be a return value), the matrix transposed resp. calculating the sum and difference of two matrices, representing the matrix as a string (use java.lang.StringBuilder to generate the text).
Also create a main program (Main.java) that tests these operations!
My problem is in my basicsMatrixMain.java code, that I do not know how can I print out thre results I get from difference or transpone. Can anybody help me to solve it ?
public class basicsMatrix {
private final int N;
private final int M;
private final double[][] matrix;
public basicsMatrix(int M, int N) {
this.N = N;
this.M = M;
matrix = new double[M][N];
}
public basicsMatrix(double[][] matrix) {
M = matrix.length;
N = matrix[0].length;
this.matrix = new double[N][M];
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
this.matrix[i][j] = matrix[i][j];
}
public void transzponalas(double[][] matrix1){
double[][] transpose = new double[M][N];
for(int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
transpose[j][i] = matrix1[i][j];
}
}
}
public void add(double[][] matrix1,double[][] matrix2){
double[][] osszeadas = new double[N][M];
for(int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
osszeadas[i][j] = (matrix1[i][j] + matrix2[i][j]);
}
}
}
public void difference(int matrix1[][], int matrix2[][]){
double[][] kivonas = new double[N][M];
for(int i = 0; i <= N; i++){
for(int j = 0; j <= M; j++){
kivonas[i][j] = matrix1[i][j] - matrix2[i][j];
}
}
}
public String matrixtostring(double[][] matrix1){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
sb.append(matrix1);
}
}
return sb.toString();
}
}
public class basicsMatrixMain {
public static void main(String[] args) {
int N = 2;
int M = 3;
double[][] matrix1 = { {2, 3, 4}, {5, 2, 3} };
double[][] matrix2 = { {-4, 5, 3}, {5, 6, 3} };
System.out.println("\n");
System.out.print("Difference:");
for(int i = 0; i <= N; i++){
for(int j = 0; j <= M; j++){
System.out.println();
}
}
}
}
You have defined a lot of functions in basicsMatrix that you can use here.
However there are some changes that you need to make. In your add, difference and transpose methods, you define something but you never save the result. I would recommend something like this:
public double[][] transzponalas(double[][] matrix1){
double[][] transpose = new double[M][N];
for(int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
transpose[j][i] = matrix1[i][j];
}
}
return transpose;
}
public double[][] add(double[][] matrix1,double[][] matrix2){
double[][] osszeadas = new double[N][M];
for(int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
osszeadas[i][j] = (matrix1[i][j] + matrix2[i][j]);
}
}
return osszeadas;
}
public double[][] difference(int matrix1[][], int matrix2[][]){
double[][] kivonas = new double[N][M];
for(int i = 0; i <= N; i++){
for(int j = 0; j <= M; j++){
kivonas[i][j] = matrix1[i][j] - matrix2[i][j];
}
}
return kivonas;
}
All these functions now return a matrix that you can print out.
Now you just print you matrices. Something like this should work.
System.out.println(matrixtostring(transzponalas(matrix1)));
System.out.println(matrixtostring(add(matrix1,matrix2)));
System.out.println(matrixtostring(difference(matrix1,matrix2)));
Looking at the question description.
"Create a basics.Matrix class (using a two-dimensional array of real numbers as a matrix) that has the following operations: construct an M × N zero matrix, construct an M × N matrix using an M × N array, create an N × N dimensional unit matrix ( the result matrix should be a return value), the matrix transposed resp. calculating the sum and difference of two matrices, representing the matrix as a string (use java.lang.StringBuilder to generate the text).
Also create a main program (Main.java) that tests these operations!"
I suspect that you are supposed to create a class that calls functions on itself. In other words the basicsMatrix will become your matrix.
For example, the transzponalas method would become
public void transzponalas(){
double[][] transpose = new double[M][N];
for(int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
transpose[j][i] = this.matrix[i][j];
}
}
int tmp = this.M
this.M = this.N
this.N = tmp
this.matrix = transpose;
}
This way, you change the matrix that is inside your basicsMatrix. You should make sure that you understand the assignment correctly.
I have an array of size m rows n columns with each cell size is considered as 1x1.
Now I am removing a list of rows and columns from this array, next I want to know the biggest gap that can be formed after removing them.
Example:
Array of size 4 rows and 3 columns, now I am removing rows {1,2,3} and columns {1,2}
This results is an array having biggest gap of 12 cells.
Another Example:
Array of size 4 rows and 4 columns, now I am removing rows {2} and columns {2}
This results is an array having biggest gap of 4 cells.
I have come up with below code that works for this example:
static long process(int n, int m, int[] h, int[] v) {
ArrayList<ArrayList<Long>> array = new ArrayList<ArrayList<Long>>();
for (int r = 0; r <= n; r++) {
ArrayList<Long> temp = new ArrayList<Long>();
for (int c = 0; c <= m; c++) {
temp.add((long) 1);
}
array.add(temp);
}
int[] x = h;
int xnum = x.length;
Arrays.sort(x);
int[] y = v;
int ynum = y.length;
Arrays.sort(y);
// removing bar i means that list at i-1 and at i
for (int a = xnum - 1; a >= 0; a--) {
int i = x[a];
for (int cell = 0; cell < array.get(i).size(); cell++) {
array.get(i).set(cell, array.get(i).get(cell) + array.get(i - 1).get(cell));
}
array.remove(i - 1);
}
ArrayList<ArrayList<Long>> newarray = new ArrayList<ArrayList<Long>>();
for (int col = 0; col < array.get(0).size(); col++) {
ArrayList<Long> temp = new ArrayList<Long>();
for (int row = 0; row < array.size(); row++) {
temp.add(array.get(row).get(col));
}
newarray.add(temp);
}
for (int b = ynum - 1; b >= 0; b--) {
int i = y[b];
for (int cell = 0; cell < newarray.get(i).size(); cell++) {
newarray.get(i).set(cell, newarray.get(i).get(cell) + newarray.get(i - 1).get(cell));
}
newarray.remove(i - 1);
}
long max = 1;
for (ArrayList<Long> arr : newarray) {
for (long num : arr) {
if (num > max)
max = num;
}
}
return max;
}
How can we reduce the time complexity of this code, because the size of rows and columns is:
1 <= rows, columns <= 100000
Let's start by looking at your current solution, by using simple array instead of ArrayList we can reduce this code to:
static long process(int rows, int cols, int[] hor, int[] ver) {
final long[][] a = new long[rows][cols];
for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) a[i][j] = 1;
for (int h : hor) for (int j = 0; j < cols; j++) a[h - 1][j] = a[h][j] = a[h - 1][j] + a[h][j];
for (int v : ver) for (int i = 0; i < rows; i++) a[i][v - 1] = a[i][v] = a[i][v - 1] + a[i][v];
long max = 0;
for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) max = Math.max(max, a[i][j]);
return max;
}
this code has complexity O(N^2)
but, we should understand that biggest gap will be in place where biggest count of consecutive rows and columns are removed, thus we can simplify algorithm to:
static int maxConsecutive(int[] a) {
Arrays.sort(a);
int max = 0;
int start = 0;
for (int i = 0; i < a.length; i++)
if (a[i] - a[start] == i - start) max = Math.max(max, i - start + 1);
else start = i;
return max;
}
static long process(int rows, int cols, int[] hor, int[] ver) {
long maxH = maxConsecutive(hor);
long maxV = maxConsecutive(ver);
return (maxH + 1) * (maxV + 1);
}
which has complexity O(logN)
I try to run this, but it is very slow. Takes ages till it processes and finishes the calculating. Is there anyways I could improve it or make it work faster and more efficiently?
int n = 25;
int len = (int) Math.pow(2, n);
String[][] BinaryNumbers = new String[len][];
int[] DummyArray = new int[n];
int[][] BinaryNumbersInt = new int[len][];
for (int count = 0; count < len; count++) {
BinaryNumbers[count] = String.format("%" + n + "s",
Integer.toBinaryString(count)).replace((" "), ("0"))
.split("");
for (int i = 0; i < n; i++) {
DummyArray[i] = Integer.parseInt(BinaryNumbers[count][i]);
}
BinaryNumbersInt[count] = Arrays.copyOf(DummyArray, DummyArray.length);
}
thanks!
You're doing a lot of useless string manipulation. Try something like this:
for (int count = 0; count < len; count++) {
int[] DummyArray = new int[n];
int x = count;
for (int i = 0; i < n; i++) {
DummyArray[n-i-1] = x & 1;
x >>= 1;
}
BinaryNumbersInt[count] = DummyArray;
}
I'm trying to write a "Mastermind" AI program and at the moment I'm trying to implement a naive AI which searches all possible 1296 combination of 4 pegs with 6 colours.
I have written up the following for loop to print out all combinations:
int compguess[] = new int[4];
int a, b, c, d;
ArrayList<int[]> combination = new ArrayList<int[]>();
for (int z = 0; z < 6; z++) {
for (int x = 0; x < 6; x++) {
for (int i = 0; i < 6; i++) {
for (int k = 0; k < 6; k++) {
a = z;
b = x;
c = i;
d = k;
compguess[0] = a;
compguess[1] = b;
compguess[2] = c;
compguess[3] = d;
combination.add(compguess);
When I run this code with System.out.println("combination" + Arrays.toString(combination.get(k))); at the end. This displays the combinations properly, however when I try to do the following:
for(int i=0; i< height; i++){
int[] temp = combination.get(i);
for(int j = 0; j < 4 ; j++){
state[i][j] = temp[j];
}
guess.addActionListener(this);
}
It only displays the last element (4,4,4,4) 40 times, instead I want it to be (0,0,0,0), (0,0,0,1), (0,0,0,2), (0,0,0,3), (0,0,0,4), (0,0,0,5), (0,0,1,0), (0,0,1,1), (0,0,1,2), (0,0,1,3) only 10 which is the size of the height
The problem is that you are using the same array every time, causing a change to one of them to change all, as they are, in fact, the same. Just reinitialize the array in the innermost for loop:
for (int z = 0; z < 6; z++) {
for (int x = 0; x < 6; x++) {
for (int i = 0; i < 6; i++) {
for (int k = 0; k < 6; k++) {
compguess = new int[4];
// rest of your code
package msj;
import mpi.*;
public class HelloWorld2 {
public static final int N = 10;
public static void main(String[] args) {
MPI.Init(args);
long startTime = System.currentTimeMillis();
int rank = MPI.COMM_WORLD.Rank();
int size = MPI.COMM_WORLD.Size();
int tag = 10, peer = (rank==0) ? 1:0;
if(rank == 0) {
double [][] a = new double [N][N];
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
a[i][j] = 10.0;
Object[] sendObjectArray = new Object[1];
sendObjectArray[0] = (Object) a;
MPI.COMM_WORLD.Send(sendObjectArray, 0, 1, MPI.OBJECT, peer, tag);
} else if(rank == 1){
double [][] b = new double [N][N];
for(int i = 0; i < N; i++)
for(int j = 0; j < N; i++)
b[i][j] = 0;
Object[] recvObjectArray = new Object[1];
MPI.COMM_WORLD.Recv(recvObjectArray, 0, 1, MPI.OBJECT, peer, tag);
b = (double[][]) recvObjectArray[0];
for(int i = 0; i < 4; i++){
for(int j = 0; j < N; i++)
//long endTime = System.currentTimeMillis();
//long endTime = System.currentTimeMillis();
System.out.print(b[i][j]+"\t");
System.out.println("\n");
//System.out.println("Calculated in " +
// (endTime - startTime) + " milliseconds");
}
}
MPI.Finalize() ;
}
}
I couldn't run this program.
I get an error when I do not write an int before the variables in the for loop: for( int i = 0; i < N; i++).
Is the problem related to this ?
Do you have any idea, There is no problem in the code
You get "java.lang.ArrayIndexOutOfBoundsException: 10" if "rank ==1" becomes true. This is because in your nested for-loop you wrote
"for(int j = 0; j < N; i++)" instead of
"for(int j = 0; j < N; j++)".
You increment i twice. This Exceptions stops your method.
Mr.
Copy and Mr Paste send Greetings. ;o)