Producto de matrices con Python
Hola, y bienvenido a esta 4ta entrada en la serie de operaciones en matrices con Python. En esta ocasión, como podrán leer en el título, se trata sobre como podemos calcular el producto de matrices con python.
Una vez más aprovecho para invitarte a que me sigas en mis redes Twitter o en la Fanpage de Facebook, donde podrás estar informado de nuevas entradas del blog, o si tienes alguna duda o comentario puedes decirmelo sin problema.
Operaciones en matrices con python
Hasta el momento las entradas de esta serie han sido las siguientes:
Como en las entradas anteriores, para realizar el ejemplo utilizaremos la clase base que creamos en la primera entrada de esta serie, así que si aún no la tienes, lee la primera entrada y vuelves 😀
Un poco de teoría
El producto de matrices encuentra su origen en el papel que desempeñan las matrices como funciones lineales. Según la forma en que se define este producto, se puede decir que proviene de la composición de funciones lineales.
Si f y g son aplicaciones lineales tal que f: A -> B y g: B -> C (A, B son los dominios respectivos de f, g y B, C son los imágenes que corresponden a estos dominios) entonces la composición de f y g denotada por el operador o, cumple que f o g: A -> C. Los dominios pueden verse como los posibles valores de entrada de la función y pudiera hallarse representado por un conjunto de con las posibles salidas ofrecidas por esta función y también pudiera ser el conjunto de números reales. Por esta razón el producto de la matriz A(m,n) con la matriz B(n,p) sería una matriz C(m,p) lo cual representa una restricción. Dicho de otra forma, solo es posible multiplicar matrices cuando la cantidad de columnas de la primera es igual a la cantidad de filas de la segunda. En la siguiente imagen podemos observar un ejemplo:
Código: producto de matrices con python
La implementación de la función con la que llevaremos a cabo esta operación, será una función generadora como las que hemos realizado en anteriores entradas de esta serie:
def product(self, m): """ Recibe una matriz como argumento """ if self.rows is not m.cols: raise Exception('Number of rows' 'and number of columns' "don't match") for i in range(self.rows): row = [] for j in range(m.cols): add = 0 for c in range(self.cols): add += self.get_value_of_position(i, c) * \ m.get_value_of_position(c, j) row.append(add) yield row
El código es sencillo, primero se hace una comparación para verificar si el número de filas de la matriz A es diferente al número de columnas de la matriz pasada como argumento B, en caso de que esto se cumpla lanzamos una excepción, caso contrario utilizando bucles recorremos las matrices, multiplicando y sumando los valores tal y como se explico anteriormente y añadiendolos a la nueva matriz C.
Si deseamos verificar el comportamiento de nuestra nueva función podemos realizarlo con el siguiente código:
ma = Matrix(2,3) # First row ma.define_elem(0,0,1) ma.define_elem(0,1,2) ma.define_elem(0,2,3) # Second row ma.define_elem(1,0,7) ma.define_elem(1,1,8) ma.define_elem(1,2,9) mb = Matrix(3,2) # First col mb.define_elem(0,0,1) mb.define_elem(1,0,7) mb.define_elem(2,0,13) # Second col mb.define_elem(0,1,2) mb.define_elem(1,1,8) mb.define_elem(2,1,14) for e in ma.product(mb): print(e)
Teniendo la siguiente salida:
[54, 60] [180, 204]
Que como verás corresponden a los valores de las matrices representadas en la imagen anterior. Hasta este punto nuestra clase debe encontrarse de la siguiente forma (Recuerda que también se encuentra todo el código en el repositorio de Github):
#!/usr/bin/python # -*- coding: utf-8 -*- # author: Gabriel Cueto <TheMushr00m - @Mushr00m_Dev> class Matrix: _n = 0 _m = 0 _elems = None def __init__(self, n, m): """Inicializa la matriz con valor 0 en cada posición""" self._n = n self._m = m self._elems = [] for i in range(self._n): self._elems.append([]) for j in range(self._m): self._elems[i].append(0) def define_elem(self, i, j, v): """ Sobreescribe el valor de una celda """ self._elems[i][j] = v def show_matrix(self): """ Imprime los valores almacenados en la matriz """ for i in range(self._n): for j in range(self._m): # Imprime de una forma elegante la matriz print("| {0} ".format(self.get_value_of_position(i, j)), sep=',', end='') print('|\n') def get_cols(self): """ Devuelve el número de columnas en la matriz """ return self._m def get_rows(self): """ Devuelve el número de filas en la matriz """ return self._n def get_value_of_position(self, i, j): """ Devuelve el valor en la fila(i), columna(j) de la matriz """ return self._elems[i][j] def add(self, *matrix): """ Puede recibir varias matrices como argumentos """ for i in range(self.rows): row = [] for j in range(self.cols): tmp = self.get_value_of_position(i, j) for m in matrix: tmp += m.get_value_of_position(i, j) row.append(tmp) yield row def scalar_product(self, x): """ x: Número real """ for i in range(self.rows): row = [] for j in range(self.cols): row.append(self.get_value_of_position(i, j)*x) yield row def product(self, m): """ Recibe una matriz como argumento """ if self.rows is not m.cols: raise Exception('Number of rows' 'and number of columns' "don't match") for i in range(self.rows): row = [] for j in range(m.cols): add = 0 for c in range(self.cols): add += self.get_value_of_position(i, c) * \ m.get_value_of_position(c, j) row.append(add) yield row cols = property(fget=get_cols) rows = property(fget=get_rows)
Y bien, es todo por esta ocasión, espero la explicación haya sido clara y cualquier comentario no dudes en dejarlo aquí abajo, o con confianza mencionalo por Twitter o en la Fanpage de Facebook, y aprovecho a invitarte para que me sigas en las redes y compartas el contenido del blog, con lo cual me harías un gran favor.
Saludos.
Hey hola, tengo un problema, me gustaria que el producto entre matrices quedara expresado como una nueva matriz. Alguna idea de como conseguirlo?
Debido a que se está utilizando una función generadora, podrías modificar la clase Matrix añadiendo un método define_row, que tomaría el parámetro de la fila a definir y el valor que se definirá, recuerda que al recorrer el método product, nos devuelve una fila en cada iteración.
Aquí podrás encontrar la prueba rápida que realicé con este método que te comento, otra opción sería modificar el método producto para que no utilice generators, y así construir ahí la nueva matriz.
https://gist.github.com/TheMushrr00m/8c9f8f314afc8aeb67f423f82ffb8df4