Practica Multiplicacion Matrices

Preview:

DESCRIPTION

Programación de operaciones con matrices. Análisis y de Algoritmos.

Citation preview

INSTITUTO POLITÉCNICO NACIONAL

ESCUELA SUPERIOR

DE

CÓMPUTO

UNIDAD DE APRENDIZAJE:

ANALISIS DE ALGORITMOS

PROFESORA: GARCIA MENDOZA CONSUELO VARINIA

ALUMNOS: BENITEZ CRUZ DANIELA

OLIVARES REYES CARLOS ALBERTO SAAVEDRA PALESTINA ROBERTO

PRACTICA 3:

Multiplicación de Matrices

GRUPO: 3CM4

Introducción

Producto de matrices

Dadas dos matrices A y B, su producto es otra matriz P cuyos elementos se obtienen multiplicando las filas de A por las columnas de B. De Es evidente que el número de columnas de A debe coincidir con el número de filas de B. Si A tiene dimensión m x n y B dimensión n x p, la matriz P será de orden m x p:

La división en submatrices sugiere una estrategia recursiva de divide y vencerás, que puede ser especialmente ventajoso en sistemas de memoria compartida. La ventaja de esta estrategia es que en cada paso de recursión, los datos transmitidos son más pequeños y están más localizados.

Algoritmo de StrassenEn la disciplina matemática del álgebra lineal, el algoritmo de Strassen, llamado así por Volker Strassen, es un algoritmo usado para la multiplicación de matrices. Es asintóticamente más rápido que el algoritmo de multiplicación de matrices estándar, pero más lento que el algoritmo más rápido conocido, y es útil en la práctica para matrices grandes.

Dadas dos matrices:

Podemos poner……

Entonces el producto queda:

Este procedimiento requiere 7 multiplicaciones para calcular el producto de A y B (pero más sumas que el método tradicional).

Algoritmo de multiplicación de StrassenSi reemplazamos cada elemento de A y B por una matriz de n x n, las fórmulas anteriores nos dan una forma de multiplicar dos 2n X 2n matrices.

A partir de esto tenemos un método recursivo para calcular el producto de matrices con n Algoritmo de multiplicación de Strassen potencia de 2.

Este método se puede generalizar también a matrices cuyas dimensiones no sean de la forma 2n

Objetivos

Realizar un programa para dar solución al problema de la multiplicación de matrices, mediante el método divide y vencerás, y por medio de Strassen.

Programa

MULTIPLICACION DE MATRICES CON DIVIDE Y VENCERAS.

CODIGO:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

int max(int,int);

int **multiplicamatriz(int **,int **,int); // Funci?n recursiva que multiplica matrices

int **suma(int **,int **,int); // suma de matrices

int **resta(int **,int **,int);// Resta de matrices

void libera(int **,int); // Libera memoria

int max(int a,int b)

{

return((a>b)?a:b);

}

int **multiplicamatriz(int **mapa1,int **mapa2,int num)

{

int **sol,**M[8],**f1,**f2,**f3,**f4,**f5,**f6,**f7,**f8,**f9,**f10,**aux,**aux2;

int **A[2][2],**B[2][2],**C[2][2];

int a,q,w,r,b;

sol=(int **)malloc(sizeof(int *)*num);

for(a=0;a<num;a++){

sol[a]=(int *)malloc(sizeof(int)*num);

}

if(num==1)

{

sol[0][0]=mapa1[0][0]*mapa2[0][0];

return(sol);

}

else{

// Crear las submatrices de A y B.

for(q=0;q<2;q++)

{

for(w=0;w<2;w++)

{

A[q][w]=(int **)malloc(sizeof(int *)*(num/2));

for(a=0;a<num/2;a++)

{

A[q][w][a]=(int *)malloc(sizeof(int)*(num/2));

for(r=0;r<num/2;r++){

A[q][w][a][r]=mapa1[a+(num/2)*q][r+(num/2)*w];

}

}

B[q][w]=(int **)malloc(sizeof(int *)*(num/2));

for(a=0;a<num/2;a++)

{

B[q][w][a]=(int *)malloc(sizeof(int)*(num/2));

for(r=0;r<num/2;r++){

B[q][w][a][r]=mapa2[a+(num/2)*q][r+(num/2)*w];

}

}

}

}

// Hallar las matrices M.

f1=resta(B[0][1],B[1][1],num/2);

f2=suma(A[0][0],A[0][1],num/2);

f3=suma(A[1][0],A[1][1],num/2);

f4=resta(B[1][0],B[0][0],num/2);

f5=suma(A[0][0],A[1][1], num/2);

f6=suma(B[0][0],B[1][1],num/2);

f7=resta(A[0][1],A[1][1],num/2);

f8=suma(B[1][0],B[1][1],num/2);

f9=resta(A[0][0],A[1][0],num/2);

f10=suma(B[0][0],B[0][1],num/2);

M[1]=multiplicamatriz(A[0][0],f1,num/2);

M[2]=multiplicamatriz(f2,B[1][1],num/2);

M[3]=multiplicamatriz(f3,B[0][0],num/2);

M[4]=multiplicamatriz(A[1][1],f4,num/2);

M[5]=multiplicamatriz(f5,f6,num/2);

M[6]=multiplicamatriz(f7,f8,num/2);

M[7]=multiplicamatriz(f9,f10,num/2);

// Hallar las submatrices de C.

C[0][0]=suma(M[5],M[4],num/2);

aux=C[0][0];

C[0][0]=resta(C[0][0],M[2],num/2);

aux2=C[0][0];

C[0][0]=suma(C[0][0],M[6],num/2);

libera(aux,num/2);

libera(aux2,num/2);

C[0][1]=suma(M[1],M[2],num/2);

C[1][0]=suma(M[3],M[4],num/2);

C[1][1]=suma(M[1],M[5],num/2);

aux=C[1][1];

C[1][1]=resta(C[1][1],M[3],num/2);

aux2=C[1][1];

C[1][1]=resta(C[1][1],M[7],num/2);

libera(aux,num/2);

libera(aux2,num/2);

for(a=1;a<=7;a++){

libera(M[a],num/2);

}

// Unir las submatrices de matrices C en sol.

for(q=0;q<num;q++){

for(w=0;w<num;w++){

sol[q][w]=C[q/(num/2)][w/(num/2)][q%(num/2)][w%(num/2)];

}

}

// Liberar las submatrices de A, B y C.

/*for(q=0;q<2;q++){

for(w=0;w<2;w++)

{

libera(A[q][w],num/2);

libera(B[q][w],num/2);

libera(C[q][w],num/2);

}

}*/

}

return(sol);

}

int **multiplicaDyV(int **mapa1,int **mapa2,int num)

{

int **sol,**M[8],**f1,**f2,**aux,**aux2;

int **A[2][2],**B[2][2],**C[2][2];

int a,q,w,r,b;

sol=(int **)malloc(sizeof(int *)*num);

for(a=0;a<num;a++){

sol[a]=(int *)malloc(sizeof(int)*num);

}

if(num==1)

{

sol[0][0]=mapa1[0][0]*mapa2[0][0];

return(sol);

}

// Crear las submatrices de A y B.

for(q=0;q<2;q++)

{

for(w=0;w<2;w++)

{

A[q][w]=(int **)malloc(sizeof(int *)*(num/2));

for(a=0;a<num/2;a++)

{

A[q][w][a]=(int *)malloc(sizeof(int)*(num/2));

for(r=0;r<num/2;r++){

A[q][w][a][r]=mapa1[a+(num/2)*q][r+(num/2)*w];

}

}

B[q][w]=(int **)malloc(sizeof(int *)*(num/2));

for(a=0;a<num/2;a++)

{

B[q][w][a]=(int *)malloc(sizeof(int)*(num/2));

for(r=0;r<num/2;r++){

B[q][w][a][r]=mapa2[a+(num/2)*q][r+(num/2)*w];

}

}

}

}

// Hallar las matrices M.

M[0]=multiplicaDyV(A[0][0],B[0][0],num/2);

M[1]=multiplicaDyV(A[0][1],B[1][0],num/2);

M[2]=multiplicaDyV(A[0][0],B[0][1],num/2);

M[3]=multiplicaDyV(A[0][1],B[1][1],num/2);

M[4]=multiplicaDyV(A[1][0],B[0][0],num/2);

M[5]=multiplicaDyV(A[1][1],B[1][0],num/2);

M[6]=multiplicaDyV(A[1][0],B[0][1],num/2);

M[7]=multiplicaDyV(A[1][1],B[1][1],num/2);

// Hallar las submatrices de C.

C[0][0]=suma(M[0],M[1],num/2);

C[0][1]=suma(M[2],M[3],num/2);

C[1][0]=suma(M[4],M[5],num/2);

C[1][1]=suma(M[6],M[7],num/2);

for(a=0;a<=7;a++){

libera(M[a],num/2);

}

// Unir las submatrices de matrices C en sol.

for(q=0;q<num;q++){

for(w=0;w<num;w++){

sol[q][w]=C[q/(num/2)][w/(num/2)][q%(num/2)][w%(num/2)];

}

}

// Liberar las submatrices de A, B y C.

/*for(q=0;q<2;q++){

for(w=0;w<2;w++)

{

libera(A[q][w],num/2);

libera(B[q][w],num/2);

libera(C[q][w],num/2);

}

}*/

return(sol);

}

int **suma(int **mapa1,int **mapa2,int num)

{ // sumar mapa1 y mapa2.

int a,b;

int **sol;

sol=(int **)malloc(sizeof(int *)*num);

for(a=0;a<num;a++)

{

sol[a]=(int *)malloc(sizeof(int)*num);

for(b=0;b<num;b++){

sol[a][b]=mapa1[a][b]+mapa2[a][b];

//printf("suma sol : %d\n", sol[a][b]);

}

}

return(sol);

}

int **resta(int **mapa1,int **mapa2,int num)

{ // Restar mapa2 de mapa1.

int **sol;

int a,b;

sol=(int **)malloc(sizeof(int *)*num);

for(a=0;a<num;a++)

{

sol[a]=(int *)malloc(sizeof(int)*num);

for(b=0;b<num;b++){

sol[a][b]=mapa1[a][b]-mapa2[a][b];

//printf("resta sol : %d\n", sol[a][b]);

}

}

return(sol);

}

void libera(int **mapa,int num)

{

int a;

for(a=0;a<num;a++) // Liberar la tabla din?mica de 2D.

free(mapa[a]);

free(mapa);

}

int main()

{

int **mapa1,**mapa2,**sol, **sol1;

int f1,c1,f2,c2,a,b,m,m1;

printf("Introduce el tama?o de la columna de la primer matriz:\n");

scanf("%d",&f1);

printf("Introduce el tama?o de la fila de la primer matriz:\n");

scanf("%d",&c1);

//scanf(" %d %d",&f1,&c1); // Tama?o de la primera matriz

printf("Introduce el tama?o de la columna de la segunda matriz:\n");

scanf("%d",&f2);

printf("Introduce el tama?o de la fila de la segunda fila:\n");

scanf("%d",&c2);

//scanf(" %d %d",&f2,&c2); // Tama?o de la segunda matriz

m1=max(f1,max(c1,max(f2,c2)));

for(m=1;m<m1;m*=2); // El tama?o de las matrices cuadradas a multiplicar

//debe ser de la forma 2k, si no se completan con ceros.

mapa1=(int **)malloc(sizeof(int *)*m); // Se crea la primera matriz

for(a=0;a<m;a++)

{

mapa1[a]=(int *)malloc(sizeof(int)*m);

memset(mapa1[a],0,sizeof(int)*m);

}

puts("Datos primer matriz\n");

for(a=0;a<f1;a++){ // Se cogen los datos de la primera matriz.

for(b=0;b<c1;b++){

//printf("Introduce los valores del elemento (%d , %d) de la primera matriz:", a+1 , b+1);

scanf(" %d",&mapa1[b][a]);

//printf("valor %d , %d = %d\n",b,a,mapa1[b][a]);

}

}

for(a=0;a<m;a++){

for(b=0;b<m;b++){

printf("%d", mapa1[a][b]);

}printf("\n");

}

mapa2=(int **)malloc(sizeof(int *)*m); // Se crea la sedunda matriz.

for(a=0;a<m;a++)

{

mapa2[a]=(int *)malloc(sizeof(int)*m);

memset(mapa2[a],0,sizeof(int)*m);

}

puts("Datos segunda matriz\n");

for(a=0;a<f2;a++){ // Se cogen los datos de la segunda matriz.

for(b=0;b<c2;b++){

//printf("Introduce los valores del elemento (%d , %d) de la segunda matriz:", a+1 , b+1);

scanf(" %d",&mapa2[b][a]);

//printf("valor %d , %d = %d\n",b,a,mapa2[b][a]);

}

}

for(a=0;a<m;a++){

for(b=0;b<m;b++){

printf("%d", mapa2[a][b]);

}printf("\n");

}

sol=multiplicaDyV(mapa1,mapa2,m); // Se multiplican.

sol1=multiplicamatriz(mapa1,mapa2,m);

printf("Solucion DyV: \n");

for(a=0;a<m;a++) // Se imprime el resultado.

{ for(b=0;b<m;b++){

printf(" %d ",sol[a][b]);

} printf("\n");

}

printf("Solucion Strassen: \n");

for(a=0;a<m;a++) // Se imprime el resultado.

{ for(b=0;b<m;b++){

printf(" %d ",sol1[a][b]);

} printf("\n");

}

system("pause");

return(0);

}

Conclusiones

Con esta práctica observamos que el problema de multiplicación de matrices se puede resolver de diferentes formas, por medio de divide y vencerás y el método de Strassen, con esto aprendimos que para este problema en particular la técnica divide y vencerás es más lenta, aunque no quedo muy claro ya que las matrices que utilizamos no fueron lo suficientemente grandes como para observar completamente esta diferencia.

Referencias

http://es.wikipedia.org/wiki/Algoritmo_de_Strassen

http://www.ing.ula.ve/~aguilar/actividad-docente/AYDA/Clase7MiniSem.pdf