Está en la página 1de 18

INSTITUTO POLITCNICO NACIONAL

ESCUELA SUPERIOR
DE
CMPUTO

UNIDAD DE APRENDIZAJE:
ANALISIS DE ALGORITMOS
PROFESORA:
GARCIA MENDOZA CONSUELO VARINIA

ALUMNOS:
BENITEZ CRUZ DANIELA
OLIVARES REYES CARLOS ALBERTO
SAAVEDRA PALESTINA ROBERTO
PRACTICA 3:
Multiplicacin de Matrices
GRUPO:
3CM4

Introduccin
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
nmero de columnas de A debe coincidir con el nmero de filas de B. Si A tiene
dimensin m x n y B dimensin n x p, la matriz P ser de orden m x p:

La divisin en submatrices sugiere una estrategia recursiva de divide y vencers,


que puede ser especialmente ventajoso en sistemas de memoria compartida.
La ventaja de esta estrategia es que en cada paso de recursin, los datos
transmitidos son ms pequeos y estn ms localizados.
Algoritmo de Strassen
En la disciplina matemtica del lgebra lineal, el algoritmo de Strassen, llamado as
por Volker Strassen, es un algoritmo usado para la multiplicacin de matrices. Es
asintticamente ms rpido que el algoritmo de multiplicacin de matrices
estndar, pero ms lento que el algoritmo ms rpido conocido, y es til en la
prctica 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 ms sumas que el mtodo tradicional).
Algoritmo de multiplicacin de Strassen
Si reemplazamos cada elemento de A y B por una matriz de n x n, las frmulas
anteriores nos dan una forma de multiplicar dos 2n X 2n matrices.
A partir de esto tenemos un mtodo recursivo para calcular el producto de matrices
con n Algoritmo de multiplicacin de Strassen potencia de 2.
Este mtodo se puede generalizar tambin a matrices cuyas dimensiones no sean
de la forma 2n

Objetivos
Realizar un programa para dar solucin al problema de la multiplicacin de
matrices, mediante el mtodo divide y vencers, 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 prctica observamos que el problema de multiplicacin de matrices se
puede resolver de diferentes formas, por medio de divide y vencers y el mtodo de
Strassen, con esto aprendimos que para este problema en particular la tcnica
divide y vencers es ms 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

También podría gustarte