Daa Lab 4
Daa Lab 4
algorithm
Name :- Mugdha
Registration Number :- 20BPS1095
CODE:
#include <iostream>
using namespace std;
int main(){
int p,q,r;
cout<<"Enter the dimensions of matrix A: "<<" ";
cin>>p>>q;
cout<<"Enter the dimensions of matrix B: "<<" ";
cin>>q>>r;
int A[p][q], B[q][r], C[p][r];
cout<<"Enter elements for matrix A: "<<endl;
for(int i = 0; i < p ;i++){
for(int j = 0; j < q ;j++){
cin>>A[i][j];
}
}
cout<<"Enter elements for matrix B: "<<endl;
for(int i = 0; i < p ;i++){
for(int j = 0; j < q ;j++){
cin>>B[i][j];
}
}
for(int i = 0; i < p; i++){
for(int j = 0; j < q ;j++){
C[i][j] = 0;
for(int k = 0; k < r ;k++){
C[i][j] += A[i][j] * B[j][k];
}
}
}
cout<<"After Multiplication, The elements for matrix C: "<<endl;
for(int i = 0; i < p ;i++){
for(int j = 0; j < r ;j++){
cout<<C[i][j]<<" ";
}
cout<<"\n";
}
}
OUTPUT:
Questions for Lab Practice Sheet (LPS)
1. For the program in question 1 assume that both the matrices are of same
dimension, having n rows and n columns. Compute the running time T1(P) of the
brute force program for matrix multiplication for different values of n and record
it in a table. Here T1(n) is the complexity of the naive (brute force) matrix
multiplication algorithm. T1(n)=n^3
CODE:
#include <iostream>
#include <bits/stdc++.h>
#include <cstdlib>
#include <sys/time.h>
using namespace std;
void multiplicationbfp(int n){
int Q[n][n], W[n][n], C[n][n];
for(int i = 0; i < n ;i++){
for(int j = 0; j < n ;j++){
Q[i][j] = 1;
}
}
for(int i = 0; i < n ;i++){
for(int j = 0; j < n ;j++){
W[i][j] = 1;
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n ;j++){
C[i][j] = 0;
for(int k = 0; k < n ;k++){
C[i][j] += Q[i][j] * W[j][k];
}
}
}
}
int main(){
srand((unsigned) time(NULL));
int n = 1, count;
int size[5];
int tn[5];
float tp[5];
for(count = 1; count <= 5 ; count++){
n = 10 * count;
size[count-1] = n;
tn[count-1] = n * n * n;
//naive problem
struct timeval start1, end1;
// start timer.
gettimeofday(&start1, NULL);
// unsync the I/O of C++.
ios_base::sync_with_stdio(false);
multiplicationbfp(n);
// stop timer.
gettimeofday(&end1, NULL);
// Calculating total time taken by the program.
double time_taken1;
time_taken1 = (end1.tv_sec - start1.tv_sec) * 1e6;
time_taken1 = (time_taken1 + (end1.tv_usec - start1.tv_usec)) * 1e-6;
tp[count-1] = time_taken1;
}
cout<<"S.No."<<"\t"<<"Size(n)"<<"\t\t"<<"T1(n)"<<"\t\t"<<"T1(p)"<<endl;
for(int i = 0 ; i < 5 ;i++){
printf("%d\t%d\t\t%d\t\t%f\n",(i+1),size[i], tn[i], tp[i]);
}
}
OUTPUT:
2. Translate the Strassen’s divide and conquer algorithm for multiplying two
matrices into a C++ program. For simplicity, assume the two matrices are square
matrices having the same dimensions i.e. each having n rows and n columns.
Also assume that n is a power of 2.
CODE:
#include <bits/stdc++.h>
using namespace std;
typedef long long lld;
inline lld** MatrixMultiply(lld** a, lld** b, int n,
int l, int m)
{
lld** c = new lld*[n];
for (int i = 0; i < n; i++)
c[i] = new lld[m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
c[i][j] = 0;
for (int k = 0; k < l; k++) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
return c;
}
inline lld** Strassen(lld** a, lld** b, int n,
int l, int m)
{
if (n == 1 || l == 1 || m == 1)
return MatrixMultiply(a, b, n, l, m);
lld** c = new lld*[n];
for (int i = 0; i < n; i++)
c[i] = new lld[m];
int adjN = (n >> 1) + (n & 1);
int adjL = (l >> 1) + (l & 1);
int adjM = (m >> 1) + (m & 1);
lld**** As = new lld***[2];
for (int x = 0; x < 2; x++) {
As[x] = new lld**[2];
for (int y = 0; y < 2; y++) {
As[x][y] = new lld*[adjN];
for (int i = 0; i < adjN; i++) {
As[x][y][i] = new lld[adjL];
for (int j = 0; j < adjL; j++) {
int I = i + (x & 1) * adjN;
int J = j + (y & 1) * adjL;
As[x][y][i][j] = (I < n && J < l) ? a[I][J] : 0;
}
}
}
}
lld**** Bs = new lld***[2];
for (int x = 0; x < 2; x++) {
Bs[x] = new lld**[2];
for (int y = 0; y < 2; y++) {
Bs[x][y] = new lld*[adjN];
for (int i = 0; i < adjL; i++) {
Bs[x][y][i] = new lld[adjM];
for (int j = 0; j < adjM; j++) {
int I = i + (x & 1) * adjL;
int J = j + (y & 1) * adjM;
Bs[x][y][i][j] = (I < l && J < m) ? b[I][J] : 0;
}
}
}
}
lld*** s = new lld**[10];
for (int i = 0; i < 10; i++) {
switch (i) {
case 0:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[0][1][j][k] - Bs[1][1][j][k];
}
}
break;
case 1:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[0][0][j][k] + As[0][1][j][k];
}
}
break;
case 2:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[1][0][j][k] + As[1][1][j][k];
}
}
break;
case 3:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[1][0][j][k] - Bs[0][0][j][k];
}
}
break;
case 4:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[0][0][j][k] + As[1][1][j][k];
}
}
break;
case 5:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[0][0][j][k] + Bs[1][1][j][k];
}
}
break;
case 6:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[0][1][j][k] - As[1][1][j][k];
}
}
break;
case 7:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[1][0][j][k] + Bs[1][1][j][k];
}
}
break;
case 8:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[0][0][j][k] - As[1][0][j][k];
}
}
break;
case 9:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[0][0][j][k] + Bs[0][1][j][k];
}
}
break;
}
}
lld*** p = new lld**[7];
p[0] = Strassen(As[0][0], s[0], adjN, adjL, adjM);
p[1] = Strassen(s[1], Bs[1][1], adjN, adjL, adjM);
p[2] = Strassen(s[2], Bs[0][0], adjN, adjL, adjM);
p[3] = Strassen(As[1][1], s[3], adjN, adjL, adjM);
p[4] = Strassen(s[4], s[5], adjN, adjL, adjM);
p[5] = Strassen(s[6], s[7], adjN, adjL, adjM);
p[6] = Strassen(s[8], s[9], adjN, adjL, adjM);
for (int i = 0; i < adjN; i++) {
for (int j = 0; j < adjM; j++) {
c[i][j] = p[4][i][j] + p[3][i][j] - p[1][i][j] + p[5][i][j];
if (j + adjM < m)
c[i][j + adjM] = p[0][i][j] + p[1][i][j];
if (i + adjN < n)
c[i + adjN][j] = p[2][i][j] + p[3][i][j];
if (i + adjN < n && j + adjM < m)
c[i + adjN][j + adjM] = p[4][i][j] + p[0][i][j] - p[2][i][j] - p[6][i][j];
}
}
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
for (int i = 0; i < adjN; i++) {
delete[] As[x][y][i];
}
delete[] As[x][y];
}
delete[] As[x];
}
delete[] As;
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
for (int i = 0; i < adjL; i++) {
delete[] Bs[x][y][i];
}
delete[] Bs[x][y];
}
delete[] Bs[x];
}
delete[] Bs;
for (int i = 0; i < 10; i++) {
switch (i) {
case 0:
case 3:
case 5:
case 7:
case 9:
for (int j = 0; j < adjL; j++) {
delete[] s[i][j];
}
break;
case 1:
case 2:
case 4:
case 6:
case 8:
for (int j = 0; j < adjN; j++) {
delete[] s[i][j];
}
break;
}
delete[] s[i];
}
delete[] s;
for (int i = 0; i < 7; i++) {
for (int j = 0; j < (n >> 1); j++) {
delete[] p[i][j];
}
delete[] p[i];
}
delete[] p;
return c;
}
int main()
{
lld** matA;
matA = new lld*[2];
for (int i = 0; i < 2; i++)
matA[i] = new lld[3];
matA[0][0] = 10;
matA[0][1] = 20;
matA[0][2] = 30;
matA[1][0] = 40;
matA[1][1] = 50;
matA[1][2] = 60;
lld** matB;
matB = new lld*[3];
for (int i = 0; i < 3; i++)
matB[i] = new lld[2];
matB[0][0] = 5;
matB[0][1] = 10;
matB[1][0] = 15;
matB[1][1] = 20;
matB[2][0] = 30;
matB[2][1] = 40;
lld** matC = Strassen(matA, matB, 2, 3, 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("%lld ", matC[i][j]);
}
printf("\n");
}
return 0;
}
OUTPUT:
3. Compute the running time T2(P) of the program in question 2 for different
values of n and record it in a table. Here T2(n) is the complexity of the Strassen’s
algorithm. T2(n) = n^2.81.
CODE:
#include <iostream>
#include <bits/stdc++.h>
#include <cstdlib>
#include <sys/time.h>
#include <cmath>
using namespace std;
double a[4][4];
double b[4][4];
void insert(double x[4][4])
{
double val;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
x[i][j]=1;
}
}
}
double cal11(double x[4][4])
{
return (x[1][1] * x[1][2])+ (x[1][2] * x[2][1]);
}
double cal21(double x[4][4])
{
return (x[3][1] * x[4][2])+ (x[3][2] * x[4][1]);
}
double cal12(double x[4][4])
{
return (x[1][3] * x[2][4])+ (x[1][4] * x[2][3]);
}
double cal22(double x[4][4])
{
return (x[2][3] * x[1][4])+ (x[2][4] * x[1][3]);
}
int main()
{
srand((unsigned) time(NULL));
int n = 1, count;
int size[5];
float tn[5];
float tp[5];
for(count = 1; count <= 5 ; count++){
n = pow(2,count);
size[count-1] = n;
tn[count-1] = pow(n,2.81);
//naive problem
struct timeval start1, end1;
// start timer.
gettimeofday(&start1, NULL);
// unsync the I/O of C++.
ios_base::sync_with_stdio(false);
double a11,a12,a22,a21,b11,b12,b21,b22,a[4][4],b[4][4];
double p,q,r,s,t,u,v,c11,c12,c21,c22;
//insert values in the matrix a
insert(a);
//insert values in the matrix a
insert(b);
//dividing single 4x4 matrix into four 2x2 matrices
a11=cal11(a);
a12=cal12(a);
a21=cal21(a);
a22=cal22(a);
b11=cal11(b);
b12=cal12(b);
b21=cal21(b);
b22=cal22(b);
//assigning variables acc. to strassen's algo
p=(a11+a22)*(b11+b22);
q=(a21+a22)*b11;
r=a11*(b12-b22);
s=a22*(b21-b11);
t=(a11+a12)*b22;
u=(a11-a21)*(b11+b12);
v=(a12-a22)*(b21+b22);
// stop timer.
gettimeofday(&end1, NULL);
// Calculating total time taken by the program.
double time_taken1;
time_taken1 = (end1.tv_sec - start1.tv_sec) * 1e6;
time_taken1 = (time_taken1 + (end1.tv_usec - start1.tv_usec)) * 1e-6;
tp[count-1] = time_taken1;
}
cout<<"S.No."<<"\t"<<"Size(n)"<<"\t\t"<<"T2(n)"<<"\t\t\t"<<"T2(p)"<<endl;
for(int i = 0 ; i < 5 ;i++){
printf("%d\t%d\t\t%f\t\t%f\n",(i+1),size[i], tn[i], tp[i]);
}
return 0;
}
OUTPUT:
9. Draw a graph T2(n) versus T2(P). Based on the above graphs, record your
inferences related to the behaviour of T2(n) as n increases.
CODE:
#include <bits/stdc++.h>
using namespace std;
typedef long long lld;
inline lld** MatrixMultiply(lld** a, lld** b, int n,
int l, int m)
{
lld** c = new lld*[n];
for (int i = 0; i < n; i++)
c[i] = new lld[m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
c[i][j] = 0;
for (int k = 0; k < l; k++) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
return c;
}
inline lld** Strassen(lld** a, lld** b, int n,
int l, int m)
{
if (n == 1 || l == 1 || m == 1)
return MatrixMultiply(a, b, n, l, m);
lld** c = new lld*[n];
for (int i = 0; i < n; i++)
c[i] = new lld[m];
int adjN = (n >> 1) + (n & 1);
int adjL = (l >> 1) + (l & 1);
int adjM = (m >> 1) + (m & 1);
lld**** As = new lld***[2];
for (int x = 0; x < 2; x++) {
As[x] = new lld**[2];
for (int y = 0; y < 2; y++) {
As[x][y] = new lld*[adjN];
for (int i = 0; i < adjN; i++) {
As[x][y][i] = new lld[adjL];
for (int j = 0; j < adjL; j++) {
int I = i + (x & 1) * adjN;
int J = j + (y & 1) * adjL;
As[x][y][i][j] = (I < n && J < l) ? a[I][J] : 0;
}
}
}
}
lld**** Bs = new lld***[2];
for (int x = 0; x < 2; x++) {
Bs[x] = new lld**[2];
for (int y = 0; y < 2; y++) {
Bs[x][y] = new lld*[adjN];
for (int i = 0; i < adjL; i++) {
Bs[x][y][i] = new lld[adjM];
for (int j = 0; j < adjM; j++) {
int I = i + (x & 1) * adjL;
int J = j + (y & 1) * adjM;
Bs[x][y][i][j] = (I < l && J < m) ? b[I][J] : 0;
}
}
}
}
lld*** s = new lld**[10];
for (int i = 0; i < 10; i++) {
switch (i) {
case 0:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[0][1][j][k] - Bs[1][1][j][k];
}
}
break;
case 1:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[0][0][j][k] + As[0][1][j][k];
}
}
break;
case 2:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[1][0][j][k] + As[1][1][j][k];
}
}
break;
case 3:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[1][0][j][k] - Bs[0][0][j][k];
}
}
break;
case 4:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[0][0][j][k] + As[1][1][j][k];
}
}
break;
case 5:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[0][0][j][k] + Bs[1][1][j][k];
}
}
break;
case 6:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[0][1][j][k] - As[1][1][j][k];
}
}
break;
case 7:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[1][0][j][k] + Bs[1][1][j][k];
}
}
break;
case 8:
s[i] = new lld*[adjN];
for (int j = 0; j < adjN; j++) {
s[i][j] = new lld[adjL];
for (int k = 0; k < adjL; k++) {
s[i][j][k] = As[0][0][j][k] - As[1][0][j][k];
}
}
break;
case 9:
s[i] = new lld*[adjL];
for (int j = 0; j < adjL; j++) {
s[i][j] = new lld[adjM];
for (int k = 0; k < adjM; k++) {
s[i][j][k] = Bs[0][0][j][k] + Bs[0][1][j][k];
}
}
break;
}
}
lld*** p = new lld**[7];
p[0] = Strassen(As[0][0], s[0], adjN, adjL, adjM);
p[1] = Strassen(s[1], Bs[1][1], adjN, adjL, adjM);
p[2] = Strassen(s[2], Bs[0][0], adjN, adjL, adjM);
p[3] = Strassen(As[1][1], s[3], adjN, adjL, adjM);
p[4] = Strassen(s[4], s[5], adjN, adjL, adjM);
p[5] = Strassen(s[6], s[7], adjN, adjL, adjM);
p[6] = Strassen(s[8], s[9], adjN, adjL, adjM);
for (int i = 0; i < adjN; i++) {
for (int j = 0; j < adjM; j++) {
c[i][j] = p[4][i][j] + p[3][i][j] - p[1][i][j] + p[5][i][j];
if (j + adjM < m)
c[i][j + adjM] = p[0][i][j] + p[1][i][j];
if (i + adjN < n)
c[i + adjN][j] = p[2][i][j] + p[3][i][j];
if (i + adjN < n && j + adjM < m)
c[i + adjN][j + adjM] = p[4][i][j] + p[0][i][j] - p[2][i][j] - p[6][i][j];
}
}
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
for (int i = 0; i < adjN; i++) {
delete[] As[x][y][i];
}
delete[] As[x][y];
}
delete[] As[x];
}
delete[] As;
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
for (int i = 0; i < adjL; i++) {
delete[] Bs[x][y][i];
}
delete[] Bs[x][y];
}
delete[] Bs[x];
}
delete[] Bs;
for (int i = 0; i < 10; i++) {
switch (i) {
case 0:
case 3:
case 5:
case 7:
case 9:
for (int j = 0; j < adjL; j++) {
delete[] s[i][j];
}
break;
case 1:
case 2:
case 4:
case 6:
case 8:
for (int j = 0; j < adjN; j++) {
delete[] s[i][j];
}
break;
}
delete[] s[i];
}
delete[] s;
for (int i = 0; i < 7; i++) {
for (int j = 0; j < (n >> 1); j++) {
delete[] p[i][j];
}
delete[] p[i];
}
delete[] p;
return c;
}
int main()
{
int p,q,r;
//now taking input
cout<<"Enter a, b, c :"<<" ";
cin>>p>>q>>r;
//now making everything dimensions equal
int m = max(p,q);
m = max(m,r);
if (m > 2 && m < 4){
m = 4;
p = p + (m - p);
q = q + (m - q);
}
else if (m >= 4 && m < 8){
m = 8;
p = p + (m - p);
q = q + (m - q);
}
else if (m >= 8 && m < 16){
m = 16;
p = p + (m - p);
q = q + (m - q);
}
lld** matA;
matA = new lld*[p];
for (int i = 0; i < p; i++)
matA[i] = new lld[q];
for(int i = 0; i < p; i++){
for(int j = 0 ;j < q; j++){
matA[i][j] = 1;
}
}
lld** matB;
matB = new lld*[q];
for (int i = 0; i < q; i++)
matB[i] = new lld[r];
for(int i = 0; i < q; i++){
for(int j = 0 ;j < r; j++){
matB[i][j] = 1;
}
}
lld** matC = Strassen(matA, matB, p, q, r);
cout<<"The matrix after multiplication is ="<<endl;
for (int i = 0; i < p; i++) {
for (int j = 0; j < r; j++) {
printf("%lld ", matC[i][j]);
}
printf("\n");
}
return 0;
}
OUTPUT: