Multithreaded matrix multiplication in Java - java

I'm writing a Java program that uses threads to multiply two matrices. I have the following code:
public class MatrixMultiplication {
//Declare matrices
public static int[][] matrix1 = new int[][]{
{1,2,3,4},{3,2,1,4}
};
public static int[][] matrix2 = new int[][]{
{2,1,3,4},{4,2,5,3}
};
public static int[][] result = new int[4][4];
//Threads
public static Thread[][] threads = new Thread[4][4];
public static void main(String[] args){
//create worker threads with M and N hard-coded
for(int i = 0; i < threads.length; i++) {
for (int l = 0; l < threads[i].length; l++) {
threads[i][l] = new Thread(new Worker(matrix1, matrix2, result, i, l));
}
}
for(int i = 0; i < threads.length; i++){
for(int l = 0; l < threads[i].length; i++){
try {
threads[i][l].start();
threads[i][l].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Contents of result matrix");
for(int i = 0; i < 4; i++)
for(int l = 0; l < 4; l++){
System.out.println("["+i+","+l+"] = "+result[i][l]);
}
}
}
class Worker implements Runnable{
int[][] m1;
int[][] m2;
int[][] result;
int row;
int col;
public Worker(int[][]m1, int[][] m2, int[][] result, int row, int col){
this.m1 = m1;
this.m2 = m2;
this.result = result;
this.row = row;
this.col = col;
}
public void run(){result[row][col] = (m1[row][col] * m2[col][col]) + (m1[row][col+1] * m2[col+1][col]);}
}
The programming is throwing an ArrayIndexOutOfBoundsException on multiple lines, notable lines 21 and in the run method of the Worker thread class. I have tried several variations to no avail and am looking for guidance on this. Thank you very much.

There is several points of problem. On line 21 you use I+1 instead of L+1. Also, matrix are two-dimensional arrays with only two lines, not four.

Related

Whats wrong with this array?

public class lab {
public static void main (String args[]){
double[][] g = {RandomArray(3)};
printArray(g);
}
private static void printArray(double[][] g) {
System.out.println(Arrays.deepToString(g));
}
public static double[][] RandomArray(int n) {
double[] [] RandomArray = new double[n] [n];
Random randomNumberCreator = new Random();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
RandomArray[i][j] = randomNumberCreator.nextDouble() * 100;
}
}
return RandomArray;
}
}
I am not sure what is wrong with my RandomArray method, i want it to work for 2-dimensional arrays but i have clearly made a mistake as the line below is receiving an error and I am unsure as to why this is happening. If you could explain to me the error that I have made i would be grateful.
double[][] g = {RandomArray(3)};
remove the curly brace around the function Call of "RandomArray"
public static void main (String args[]){
double[][] g = RandomArray(3);
printArray(g);
}
private static void printArray(double[][] g) {
System.out.println(Arrays.deepToString(g));
}
public static double[][] RandomArray(int n) {
double[] [] RandomArray = new double[n] [n];
Random randomNumberCreator = new Random();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
RandomArray[i][j] = randomNumberCreator.nextDouble() * 100;
}
}
return RandomArray;
}
You are initializing the array incorrectly....
you dont need the { } when calling the method RandomArray
just doing double[][] g = RandomArray(3); will do the job

calculate the minimum value for each column in 2D array

I have a 2D array , iam trying to calculate the minimum value for each column and put the result in the result array.
the code bellow is calculating the minimum value for each row , how can i get the min value for each column.
import java.util.*;
class Test20 {
public static void main ( String [] args) {
int[][] array = {{6,3,9},
{0,8,2},
{3,7,5}};
Test20 test = new Test20();
System.out.print(Arrays.toString(test.mincol(array)));
}
public static int[] mincol (int[][] n) {
int[] result = new int[n.length];
for (int i = 0; i < n.length; i++) {
int min = n[0][i];
for (int j = 0; j < n[0].length; j++) {
if (n[j][i] < min) {
min = n[j][i];
}
}
result[i] = min;
}
return result;
}
}
Just change the loop the following way:
min = 0;
for(int i=0;i<n.length;i++){
for(int j=0;j<n[0].length;j++){
if(n[j][i]<n[j][min]){
min=j;
}
result[i]=n[min][i];
}
Be aware that you instantiate your result array by the length of the first dimension in your array but later use the n[][] param for looping and access the length of the second dimension in your loop.
If your two dim array is for example 4x5, this will cause ArrayOutOfBoundsExceptions.
You only need to do the same thing but inverting the variables
for(int i=0;i<n.length;i++){
for(int j=0;j<n[0].length;j++){
if(n[j][i]<n[min][j]){
min=i;
}
result[j]=n[min][j];
}
}
If your code is correct just change:
if(n[i][j]<n[i][min]){
min=j;
}
with
if(n[i][j]<n[result[i]][j]){
result[i]=i;
}
finally
for(int i=0;i<n.length;i++) result[i]=n[result[i][j];
you don't need min. But change
int [] result = new int[n.length];
to
int [] result = new int[n[0].length];
How about you transpose your two dimensional array like:
public static int[][] transpose (int[][] original) {
int[][] array = new int[original.length][];
// transpose
if (original.length > 0) {
for (int i = 0; i < original[0].length; i++) {
array[i] = new int[original[i].length];
for (int j = 0; j < original.length; j++) {
array[i][j] = original[j][i];
}
}
}
return array;
}
and then call it as:
System.out.print(Arrays.toString(test.minrow(transpose(array))));
Or, if you want to go without transpose, this is how you can do:
public static int[] mincol (int[][] n) {
int[] result = new int[n.length];
for (int i = 0; i < n.length; i++) {
int min = n[0][i];
for (int j = 0; j < n[0].length; j++) {
if (n[j][i] < min) {
min = n[j][i];
}
}
result[i] = min;
}
return result;
}
Your for loop looks ok. Check the code below I fixed some minor issues.
Based on your code replace Class code with below:
public class Test {
public static void main(String[] args) {
int[][]array={{6,1,9}, {0,1,2}, {3,7,5}};
int[] test;
test = minrow(array);
for(int i=0; i<test.length; i++){
System.out.println(test[i]);
}
}
public static int[] minrow(int[][] n){
int [] result = new int[n.length];
int min;
for(int i=0;i<n.length;i++){
min=0;
for(int j=0;j<n[i].length;j++){
if(n[i][j]<n[i][min]){
min=j;
}
}
result[i]=n[i][min];
}
return result;
}
}

How can sort a 2D array with the use of thread pools and the Callable interface?

Hi guys i am trying to sort a 2D array using thread pools to measure execution time and compare it when I increase the number of threads and the total number of elements in the array. I've done some coding but apparently it is running very slow and i am getting null pointer exceptions for some reason. I think the reason lies in the use of the Integer array since Callable cant work with primitive int[] arrays. Help will be much appreciated
public class MatrixBubbleSort {
public static void main(String[] args) throws InterruptedException, ExecutionException {
MatrixBubbleSort obj = new MatrixBubbleSort();
String resultMatrix = "";
resultMatrix = obj.sort2D();
System.out.println(resultMatrix);
}
public String sort2D() throws InterruptedException, ExecutionException {
long start = 0;
long end = 0;
int rows = 5;
int cols = 5;
Integer[][] matrix = new Integer[rows][cols];
Future<Integer[]>[] returned;
returned = new Future[rows];
Sorter[] tasks = new Sorter[rows];
ExecutorService executer = Executors.newFixedThreadPool(5);
for(int r = 0; r< rows; r++ ){
for(int c = 0; c < cols; cols++){
matrix[r][c] = (int) (Math.random() * (rows*cols));
}
}
System.out.print(printArr(matrix) + "\n");
start = System.currentTimeMillis();
for(int r = 0; r< rows; r++ ){
tasks[r] = new Sorter(matrix[r]);
returned[r] = executer.submit(tasks[r]);
}
executer.shutdown();
executer.awaitTermination(1, TimeUnit.DAYS);
end = System.currentTimeMillis();
for(int r = 0; r< rows; r++ ){
matrix[r] = returned[r].get();
}
System.out.print("Time taken = " + (end - start) + "\n");
return printArr(matrix);
}
public static String printArr(Integer[][] arr){
String out = "";
for(int i = 0; i < arr.length;i++ ){
for(int c = 0; c < arr[i].length;c++ ){
out += arr[i][c].intValue();
}
out += "\n";
}
return out;
}
}
class Sorter implements Callable{
private final Integer[] array;
Sorter(Integer[] array){
this.array = array.clone();
}
#Override
public Integer[] call() throws Exception {
boolean swap = true;
int buffer = 0;
while(swap){
swap = false;
for(int i = 0; i < array.length -1; i++){
if(array[i].intValue() > array[i+1].intValue()){
buffer = array[i].intValue();
array[i]= array[i+1].intValue();
array[i+1] = buffer;
swap = true;
}
}
}
return array;
}
}
Your code appears to run OK, after a small change:
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) { // instead of cols++
matrix[r][c] = (int) (Math.random() * (rows * cols));
}
}
Pretty fast and no null pointer exceptions so far - care to double check?

Java Matrices - Transpose & Sum

I am working on a Matrix program on eclipse and I am currently stuck on 2 methods in which I thought were the most simplest of all. The first method that I am working on is to take the sum of 2 different 2D arrays from the #Test cases and returning the sum in a new 2D array. I already have an 2D array instance variable. The reason I am stuck is because the of the parameter in the method. The parameter doesn't give any variable other than the class (Matrix) and the variable (other). So I was wondering how to go about getting this method started and most importantly returning the sum array.
The other method I am stuck on is the transpose method where you must flip the rows and columns of the given 2D array. I know I must create a temp 2D array in order to store the content back into the original 2D array but for some reason it is not passing the test cases. If someone could please help me with these two methods, it would be much appreciated.
import java.util.Arrays;
public class Matrix {
private int[][] array;
private int[][] array2;
private int theRow;
private int theCol;
public Matrix(int[][] arrayOfArrays) {
// TODO Auto-generated constructor stub
array = new int[arrayOfArrays.length][arrayOfArrays[0].length];
for (int r = 0; r < arrayOfArrays.length; r++) {
for (int c = 0; c < arrayOfArrays[r].length; c++) {
array[r][c] = arrayOfArrays[r][c];
}
}
}
public int get(int row, int column) {
return array[row][column];
}
public int getNumberOfRows() {
int nRows = array.length;
return nRows;
}
public int getNumberOfColumns() {
int nCols = array[0].length;
return nCols;
}
public String toString() {
String res = "";
for (int r = 0; r < array.length; r++) {
for (int c = 0; c < array[r].length; c++)
res = res + array[r][c];
}
return res;
}
public Matrix sum(Matrix other) {
return sum;
}
public void scalarMultiply(int scalar) {
for (int r = 0; r < array.length; r++) {
for (int c = 0; c < array[0].length; c++) {
array[r][c] = array[r][c] * scalar;
}
}
}
public void transpose() {
int m = array.length;
int n = array[0].length;
int[][] transpose = new int [n][m];
int temp;
for (int r = 0; r < m; r++) {
for (int c = 0; c < n; c++) {
transpose[c][r] = array[r][c];
array[r][c] = array[c][r];
array[c][r] = transpose[c][r];
}
}
}
//The test cases for sum method and transpose method
#Test
public void testSum() {
int[][] a1 = { { 1, 2, 3 },
{ 5, 6, 7 } };
Matrix a = new Matrix(a1);
int[][] a2 = { { -2, -2, -2 },
{ 4, 4, 4 } };
Matrix b = new Matrix(a2);
Matrix c = a.sum(b);
assertEquals(-1, c.get(0, 0));
assertEquals(0, c.get(0, 1));
assertEquals(1, c.get(0, 2));
assertEquals(9, c.get(1, 0));
assertEquals(10, c.get(1, 1));
assertEquals(11, c.get(1, 2));
}
#Test
public void testTranspose() {
int[][] a1 = { { 1, 3, 5 },
{ 2, 4, 6 } };
Matrix a = new Matrix(a1);
a.transpose();
assertEquals(1, a.get(0, 0));
assertEquals(2, a.get(0, 1));
assertEquals(3, a.get(1, 0));
assertEquals(4, a.get(1, 1));
assertEquals(5, a.get(2, 0));
assertEquals(6, a.get(2, 1));
}
You need change the dimensions, for example, 2x3 -> 3x2.
import java.util.Arrays;
public class Matrix {
private int[][] array;
private int[][] array2;// remove this
private int theRow;// remove this
private int theCol;// remove this
public void transpose() {
int m = array.length;
int n = array[0].length;
int[][] transpose = new int [n][m];
for (int r = 0; r < m; r++) {
for (int c = 0; c < n; c++) {
transpose[c][r] = array[r][c];
}
}
array = transpose;
}
}

Enum Type 2Darray maze

I am making a maze game with enumerated types to hold the values of walls, open spaces (etc) and i am not sure why this code does not work, i am trying to create a new board and set everything to open, then go through and randomly set values to the spots in the array.
maze = new Cell[row][col];
for (int r = 0; r < maze.length; r++) {
for (int c = 0; c < maze.length; c++)
maze[r][c].setType(CellType.OPEN);
}
Random randomMaze = new Random();
for (int ran = 0; ran <= numWalls ; ran++){
maze[randomMaze.nextInt(maze.length)][randomMaze.nextInt(maze.length)].setType(CellType.WALL);
}
this will do what you said. not sure you will get the kind of maze you want:
import java.util.Random;
class Maze {
enum CellType {
open,wall;
}
Maze(int n) {
this.n=n;
maze=new CellType[n][n];
init();
}
private void init() {
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
maze[i][j]=CellType.open;
}
void randomize(int walls) {
init();
Random random=new Random();
for(int i=0;i<=walls;i++)
maze[random.nextInt(n)][random.nextInt(n)]=CellType.wall;
}
public String toString() {
StringBuffer sb=new StringBuffer();
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++)
switch(maze[i][j]) {
case open:
sb.append(' ');
break;
case wall:
sb.append('|');
break;
}
sb.append('\n');
}
return sb.toString();
}
final int n;
CellType[][] maze;
}
public class Main {
public static void main(String[] args) {
Maze maze=new Maze(5);
System.out.println(maze);
maze.randomize(4);
System.out.println(maze);
}
}
I think, your inner loop should be something like
for (int c = 0; c < maze[r].length; c++)
... with the [r].
I have not tried it though.
I think that your maze would be a good candidate for a class. Something like this should work:
import java.util.Random;
public class Maze {
private int[][] mMaze;
private int mRows;
private int mCols;
//enums here:
public static int CELL_TYPE_OPEN = 0;
public static int CELL_TYPE_WALL = 1;
public Maze(int rows, int cols){
mRows = rows;
mCols = cols;
mMaze = new int[mRows][mCols];
for (int r = 0; r < mRows; r++) {
for (int c = 0; c < mCols; c++) {
mMaze[r][c] = Maze.CELL_TYPE_OPEN;
}
}
}
public void RandomizeMaze(int numWalls){
Random randomMaze = new Random();
for (int ran = 0; ran <= numWalls ; ran++){
mMaze[randomMaze.nextInt(mRows)][randomMaze.nextInt(mCols)]=(Maze.CELL_TYPE_WALL);
}
}
}

Categories