## Description

## Algorithms and Data Structures for Object-Oriented Design

## 1 Objectives

A dense matrix is a matrix in which almost all matrix entries are non-zero. On the other hand, a sparse

matrix contains entries that are mostly zero. In this assignment, you will implement the Strassen’s algorithm

for multiplying two dense square matrices. With regular matrix multiplication, you can use three nested

loops and directly compute the product. The complexity of regular matrix multiplication is O(n

3

) where n

is the size of the square matrices that are being multiplied. As the size of the matrices grow, the processing

power required for computations also increases in a cubic manner.

Amongst all arithmetic operations,

multiplication is the most intensive and expensive operation. The Strassen’s algorithm was proposed by

Volker Strassen in the 1960s in an attempt to make dense matrix multiplication more efficient (i.e. entails less

multiplication operations). This algorithm has been proven to be more efficient than regular multiplication

and has an efficiency of approximately O(n

2.8).

Although many more efficient algorithms for dense matrix

multiplication have been proposed at recent times, we will focus on implementing the Strassen’s algorithm

for this assignment.

## 2 Strassen’s Algorithm

Following are assumptions made about the two matrices (A and B) which are operands of the dense matrix

multiplication operation:

• Both are square matrices with size 2n x 2n (i.e. A ∈ R

2

nx2n

, B ∈ R

2

nx2n

)

• Almost all entries in both matrices are non-zero

Since both matrices A and B are square matrices with size 2n x 2n, these can be divided into four equal

blocks as follows:

A =

A0,0 A0,1

A1,0 A1,1

B =

B0,0 B0,1

B1,0 B1,1

Suppose that the size of A is 4 x 4. Then all sub-matrices A0,0, A0,1, A1,0, A1,1, are 2 by 2 equally sized

blocks as illustrated in the following:

A =

a0,0 a0,1 a0,2 a0,3

a1,0 a1,1 a1,2 a1,3

a2,0 a2,1 a2,2 a2,3

a3,0 a3,1 a3,2 a3,3

A0,0 =

a0,0 a0,1

a1,0 a1,1

, A0,1 =

a0,2 a0,3

a1,2 a1,3

, A1,0 =

a2,0 a2,1

a3,0 a3,1

, A1,1 =

a2,2 a2,3

a3,2 a3,3

Sub-matrices of B which are B0,0, B0,1, B1,0, B1,1, can also be computed in a similar manner. Multiplying

matrices A and B results in matrix C.

A ∗ B = C

A0,0 A0,1

A1,0 A1,1

∗

B0,0 B0,1

B1,0 B1,1

=

C0,0 C0,1

C1,0 C1,1

Following are the set of computations performed when regular matrix multiplication is used to compute C:

C0,0 = A0,0B0,0 + A0,1B1,0

1

C0,1 = A0,0B0,1 + A0,1B1,1

C1,0 = A1,0B0,0 + A1,1B1,0

C1,1 = A1,0B0,1 + A1,1B1,1

As you can observe from the above, the computation of C via regular multiplication has required 8 multiplications for each matrix block. With the Strassen’s algorithm, only 7 multiplications will be required. In an

implementation of the Strassen’s algorithm, it is necessary to first compute 7 matrices M0 to M6 as follows:

M0 = (A0,0 + A1,1)(B0,0 + B1,1)

M1 = (A1,0 + A1,1)B0,0

M2 = A0,0(B0,1 − B1,1)

M3 = A1,1(B1,0 − B0,0)

M4 = (A0,0 + A0,1)B1,1

M5 = (A1,0 − A0,0)(B0,0 + B0,1)

M6 = (A0,1 − A1,1)(B1,0 + B1,1)

As you can observe from the above, there are a total of 7 matrix multiplication operations performed to

compute the above set of matrices. These matrices can be combined to obtain the resultant matrix C via

addition and subtraction operations as follows:

C0,0 = M0 + M3 − M4 + M6

C0,1 = M2 + M4

C1,0 = M1 + M3

C1,1 = M0 − M1 + M2 + M5

It is clear from the above that although fewer multiplication operations are required for the Strassen’s

algorithm in comparison to the regular multiplication method, more addition and subtraction operations are

necessary. However, since multiplication operations are more expensive than addition or subtraction, the

Strassen’s algorithm results in being more efficient than regular matrix multiplication.

The Strassen’s algorithm outlined above can be implemented recursively. Multiplications that are required to compute matrices M0 . . . M6 are also dense matrix multiplications. In order to compute these

matrices, the dense multiplication function can be called recursively. At each recursive call, the size of the

matrices that are multiplied is halved. For instance, suppose that the size of A and B is n x n. Matrix M0 is

computed by multiplying matrices that are half the size of the original set of matrices passed into the recursive function (i.e. size is n

2

x

n

2

).

The original problem is therefore halved and this simpler sub-problem is

of the same kind as the original multiplication problem. The base case of this multiplication problem occurs

when n = 1. At this point, two numbers (not matrices) are multiplied. Hence, the Strassen’s algorithm is a

perfect candidate for recursive implementation!

## 3 Implementation of the Strassen’s Algorithm

In order to implement the Strassen’s algorithm, you are required to expand and implement the following

functions:

• public int[][] denseMatrixMult(int[][] A, int[][] B, int size)

• public int[][] sum(int[][] A, int[][] B, int x1, int y1, int x2, int y2, int

n)

• public int[][] sub(int[][] A, int[][] B, int x1, int y1, int x2, int y2, int

n)

• public void printMatrix(int n, int[][] A)

2

• public int[][] readMatrix(String filename, int n) throws Exception

The first function implements the Strassen’s algorithm in a recursive manner (i.e. public int[][]

denseMatrixMult(int[][] A, int[][] B, int size)). All other functions serve as helper functions for the recursive function. The first argument to denseMatrixMult is A which is a two-dimensional

array representing one dense matrix. B is a two-dimensional array representing the second dense matrix.

This function will return the two-dimensional integer resultant matrix C of the product of A and B via the

Strassen’s algorithm. n is the size of matrices A and B.

In order to compute matrices M0 . . . M6, you will use the sum and sub functions. For instance, to

compute M0, it is necessary to compute the sum of sub-matrices A0,0 + A1,1 and B0,0 + B1,1. To compute

the first term A0,0 + A1,1, you can call the function sum(A, A, 0, 0, n/2, n/2, n/2) where n is the

size of A. Similarly to compute the second term B0,0 + B1,1, you can call the function sum(B, B, 0, 0,

n/2, n/2, n/2). Results from these two summations are multiplied via a recursive call to the original

function. All remaining matrices M1 . . . M6 can be computed in a similar manner.

After matrices M0 . . . M6 are computed, these can be combined to obtain C0,0, C0,1, C1,0, C1,1. This

requires two nested loops (to add columns and rows of matrices).

## 4 Materials Provided

You will download content in the folder SE2205B-LabAssignment1.zip which contains two folders (code

and expOutput) onto your local workspace. Folder code contains a skeleton of function implementations

and declarations. Your task is to expand these functions appropriately in Assignment1.java as required

for implementation.

Test.java evokes all the functions you will have implemented and is similar to the

file that will be used to test your implementations. Use Test.java file to test all your implementations.

matrix1.txt and matrix2.txt are sample files containing data that will be read by your program. Folder

expOutput contains outputs expected for the supplied data files matrix1.txt and matrix2.txt. Note

that we will NOT use the same sample files for grading your assignment. Do NOT change the name of

these files or functions.

## 5 Division of Assignment into Parts

## Part 1: Initializing and Printing Matrices

In this part, function implementations of initMatrix and printMatrix in Assignment1.java file will

be tested. In the initMatrix function, a 2D array of size n will be initialized. printMatrix prints the

content of the 2D array represented by the reference A. This part will be tested by executing the program

with the commands:

• javac Assignment1.java Test.java and

• java Test 1

The output resulting from this part must match the content of file expOutput/part1.txt.

## Part 2: Reading Matrix from Data File and Printing to the Console

In this part, function implementation of readMatrix in Assignment1.java file will be tested. The

readMatrix function will read the content of a data file called filename and store the content of this

file in a 2D array of size n. This array will then be returned by the function. This part will be tested by

executing the program with the commands:

• javac Assignment1.java Test.java

• java Test 2

The output resulting from this part must match the contents of the file Part2.txt.

3 SE2205 Lab Assignment 1

## Part 3: Adding and Subtracting Sub-Matrices

Here you will complete the implementation of two functions: sum and sub. Suppose that there are two

square matrices A and B of the same size. Suppose that these matrices are of size 8 (this can change).

The function sum will perform a matrix addition of two sub-matrices (one from matrix A and the other

from matrix B) of size n and return the reference to the added matrix. The sub-matrices are identified by

coordinates (xa, ya) and (xb, yb) which denote the indices at which a sub-matrix begins in the main matrix.

The arguments passed to these functions are A, B, xa, ya, xb, yb, n where A and B are references to

the main matrices. This part of the assignment will be tested via the following commands:

• javac Assignment1.java Test.java

• java Test 3 1

• javac Assignment1.java Test.java

• java Test 3 2

Outputs from these tests must match contents in Part3 1.txt and Part3 2.txt files resulting from the

provided matrix1.txt and matrix2.txt files.

## Part 4: Recursive Dense Matrix Multiplication

In this part, you will implement the Strassen’s algorithm introduced in Section 2 by expanding the function

denseMatrixMult. To this function, two two-dimensional arrays matrix1 and matrix2 representing

two dense matrices and n which is the size of these square matrices are passed as arguments. This function

will return the resultant matrix. This part of the assignment will be tested via the following commands:

• javac Assignment1.java Test.java

• java Test 4

Outputs from these tests must match the contents of Part4.txt which is the result of multiplying matrices

obtained from the provided matrix1.txt and matrix2.txt files.

## 6 Grading: Final Mark Composition

It is IMPORTANT that you follow all instructions provided in this assignment very closely. Otherwise,

you will lose a significant amount of marks as this assignment is auto-marked and relies heavily on you

accurately following the provided instructions. Following is the mark composition for this assignment (total

of 40 points):

• Successful compilation of all program files i.e. the following command results in no errors (3 points):

javac Assignment1.java Test.java

• Successful execution of the following commands: (5 points)

java Test 1

java Test 2

java Test 3 1

java Test 3 2

java Test 4

• Output from Part 1, 2, 3a and 3b exactly matches expected output (2 points each for a total of 8

points)

• Output from Part 4 exactly matches expected output (14 points)

• Code content (10 points)

Sample expected outputs are provided in folder expOutput. We will test your program with a set of

completely different data files. There is a 25% penalty for each late day up to 3 days. All submissions after

that will be assigned a grade of 0/40.

4 SE2205 Lab Assignment 1

## 7 Code Submission

You will use git to submit this assignment. Create a new repository for LabAssignment1:

• Download the lab1 file SE2205B-LabAssignment1.zip from OWL into your course folder say

SE2205B.

• Unzip this downloaded file which will create a folder in the same directory called SE2205B-LabAssignment1.

• Open GitHub Desktop.

• Run File → Add local repository.

• Click Choose and browse for the folder SE2205B-LabAssignment1.

• You will get the following warning: This directory does not appear to be a Git repository.

Would you like to create a repository here instead?

• Click on Create a Repository and then click on Create Repository.

• In the GitHub Desktop tool bar, click Publish repository, check the option Keep this code

private, choose your GitHub account, and then click Publish repository.

• Now a new repository called “SE2205B-LabAssignment1” should appear in your GitHub account.

• You will need to add the instructor and the TAs to this repository. For this,

– In the GitHub account click the repository SE2205B-LabAssignment1 and then click Setting

– Click Collaborators & teams option.

– At the bottom of the page and in the Collaborators section, enter the account id of the GitHub

user you would like to add and then click Add collaborator.

– You need to add the following accounts to your repo:

∗ psrikan

∗ LiYangHart

∗ jliu2325

## ENSURE that your work satisfies the following checklist:

• You submit before the deadline

• All files and functions retain the same original names

• Your code compiles without error (if it does not compile then your maximum grade will be 3/40)

5 SE2205 Lab Assignment 1