In [1]:
import numpy as np
import pprint

Ejercicio 1


In [2]:
B = np.array([[1,2,3], [4,5,6]]) # habiendo corrido import numpy as np

In [3]:
B + 2*B # Python sabe sumar y multiplicar arrays como algebra lineal


Out[3]:
array([[ 3,  6,  9],
       [12, 15, 18]])

In [12]:
np.matmul(B.transpose(), B) # B^t*B


Out[12]:
array([[17, 22, 27],
       [22, 29, 36],
       [27, 36, 45]])

In [8]:
B[1,1]


Out[8]:
5

In [17]:
B[1,:]


Out[17]:
array([4, 5, 6])

In [18]:
B[:,1]


Out[18]:
array([2, 5])

In [21]:
x = [1,2,3]
x[0] = 'hola'
x


Out[21]:
['hola', 2, 3]

Ejercicio 1: Escribe los metodos repr y str para la clase Array de forma que se imprima legiblemente como en numpy arrays.

A. Primero hacemos un metodo para repr y str


In [9]:
class Array:
    "Una clase minima para algebra lineal"    
    def __init__(self, list_of_rows): 
        "Constructor"
        self.data = list_of_rows
        self.shape = (len(list_of_rows), len(list_of_rows[0]))      
    def __repr__(self):
        return "\n".join([str(x) for x in self.data])
    def __str__(self):
        for l in self.data:
            x= "\n".join([str(s) for s in self.data])
            for s in x:
                return x.replace(',','')

In [5]:
A=Array([[1,2,3], [4,5,6], [4,5,9]])

In [64]:
A


Out[64]:
[1, 2, 3]
[4, 5, 6]
[4, 5, 9]

In [16]:
print(A)


[1 2 3]
[4 5 6]
[4 5 9]

In [17]:
A.data


Out[17]:
[[1, 2, 3], [4, 5, 6], [4, 5, 9]]

Ejercicio 2


In [7]:
class Array:
    "Una clase minima para algebra lineal"    
    def __init__(self, list_of_rows): 
        "Constructor y validador"
        # obtener dimensiones
        self.data = list_of_rows
        nrow = len(list_of_rows)
        #  ___caso vector: redimensionar correctamente
        if not isinstance(list_of_rows[0], list):
            nrow = 1
            self.data = [[x] for x in list_of_rows]
        # ahora las columnas deben estar bien aunque sea un vector
        ncol = len(self.data[0])
        self.shape = (nrow, ncol)
        # validar tamano correcto de filas
        if any([len(r) != ncol for r in self.data]):
            raise Exception("Las filas deben ser del mismo tamano")

In [11]:



Out[11]:
__main__.Array

Ejercicio 3

Escribe el metodo setitem para que el codigo A[i,j] = new_value cambie el valor de la entrada (i,j) del array. El esqueleto de la funcion es

class Array:

def setitem(self, idx, new_value): "Ejercicio" #


In [52]:
class Array:
    "Una clase minima para algebra lineal"    
    def __init__(self, list_of_rows): 
        "Constructor y validador"
        # obtener dimensiones
        self.data = list_of_rows
        nrow = len(list_of_rows)
        #  ___caso vector: redimensionar correctamente
        if not isinstance(list_of_rows[0], list):
            nrow = 1
            self.data = [[x] for x in list_of_rows]
        # ahora las columnas deben estar bien aunque sea un vector
        ncol = len(self.data[0])
        self.shape = (nrow, ncol)
        # validar tamano correcto de filas
        if any([len(r) != ncol for r in self.data]):
            raise Exception("Las filas deben ser del mismo tamano")
    
    def __getitem__(self, idx):
        return self.data[idx[0]][idx[1]]
    def __setitem__(self, idx, new_value):
        self.data[idx[0]][idx[1]]=new_value
        print(self.data)

In [45]:
A = Array([[1,2],[3,4]])
A[0,0]=1


[[1, 2], [3, 4]]

Ejercicio 4

Definir matriz de ceros


In [12]:
def zeros(m, n):
    return [[0]*n for _ in range(m)]
    def __str__(self):
        for l in self.data:
            x= "\n".join([str(s) for s in self.data])
            for s in x:
                return x.replace(',','')

In [13]:
zeros(4,6)


Out[13]:
[[0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0]]

Ahora la función eye


In [40]:
def eye(n):
    rv_i = []
    for i in range(n):
        rv_j = []
        for j in range(n):
            if i == j:
                rv_j.append(1)
            else:
                rv_j.append(0)
        rv_i.append(rv_j)
    return rv_i

In [98]:
C = eye(10)

In [100]:
C


Out[100]:
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]]

5. Transposición

Intenté definir una función para transponer


In [90]:
B = [[1,2,3], [4,5,6]]

In [88]:
BT = [[1,4], [2,5], [3,6]]

In [92]:
len(B[0])


Out[92]:
3

Y la matriz diagonal


In [81]:
for i, value in enumerate(B):
    print(i, value)


0 [1, 2, 3]
1 [4, 5, 6]
2 [7, 8, 9]

In [87]:
rv = []
for x in range(10):
    rv.append([])
print(rv)


[[], [], [], [], [], [], [], [], [], []]

In [17]:
def transpose(self):
    # Singulete
    if len(self) == 1 and type(self[0]) != list:
        return self
    # Matrices nxm s.t. n, m >= 2
    else:        
        rv = []
        try:
            filas = len(self[0])
        except:
            filas = len(self)
        for x in range(filas):
            rv.append([])
        for i, fila in enumerate(self):
            try:
                for j, value_fila in enumerate(fila):
                    rv[j].append(value_fila)
            except:
                rv[i].append(fila)
        return rv

In [34]:
R=transpose([[1,2],[3,4]])
print(R)


[[1, 3], [2, 4]]

In [30]:
transpose([1])


Out[30]:
[1]

Ejercicio 6. SUMA Y RESTA DE MATRICES

Intenté definir primero funciones para suma y resta de matrices. No contiene el caso escalar


In [74]:
def suma_matrices(A, B):
    rv = []
    for x in range(len(A)):
        rv.append([])
    for i in range(len(A)):
        for j in range(len(A[i])):
            c = A[i][j] + B[i][j]
            rv[i].append(c)
    return rv

In [ ]:
#supuesto 1 = se tiene que asegurar que matriz A sea nxm y b mxk

In [44]:
def subs_matrices(A, B):
    rv = []
    for x in range(len(A)):
        rv.append([])
    for i in range(len(A)):
        for j in range(len(A[i])):
            c = A[i][j] - B[i][j]
            rv[i].append(c)
    return rv

In [42]:
A=[[1, 3], [2, 4] , [2, 4]]
B=[[5, 5], [4, 8], [2, 4]]

In [43]:
suma_matrices(A,B)


Out[43]:
[[6, 8], [6, 12], [4, 8]]

In [45]:
subs_matrices(A,B)


Out[45]:
[[-4, -2], [-2, -4], [0, 0]]

In [47]:
suma_matrices(A,1)  #No sirve para sumar escalares!


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-47-6c24fc722bde> in <module>()
----> 1 suma_matrices(A,1)

<ipython-input-41-749d23f66cb9> in suma_matrices(A, B)
      5     for i in range(len(A)):
      6         for j in range(len(A[i])):
----> 7             c = A[i][j] + B[i][j]
      8             rv[i].append(c)
      9     return rv

TypeError: 'int' object is not subscriptable

In [ ]:
##Multiplicación de Matrices

In [135]:
def dot_product(list_1, list_2):
    if len(list_1) == len(list_2):
        rv = 0
        for i, x in enumerate(list_1):
            product = list_1[i] * list_2[i]
            rv += product
        return rv
    else:
        print('Error: lists with different lengths!')

In [ ]:


In [137]:
def multiplicacion_matrices(A, B):
    # suponiendo supuesto 1
    rv = []
    for x in range(len(A)):
        rv.append([])
    for i, fila in enumerate(A):
        columna_b = []
        for fila_b in B:
            b = fila_b[i]
            columna_b.append(b)
        producto = dot_product(fila, columna_b)
        print(producto)

In [140]:
multiplicacion_matrices(B, transpose(B))


14
77

Aquí acaba lo que pude hacer


In [67]:
class Array:
    "Una clase minima para algebra lineal"    
    def __init__(self, list_of_rows): 
        "Constructor y validador"
        # obtener dimensiones
        self.data = list_of_rows
        nrow = len(list_of_rows)
        #  ___caso vector: redimensionar correctamente
        if not isinstance(list_of_rows[0], list):
            nrow = 1
            self.data = [[x] for x in list_of_rows]
        # ahora las columnas deben estar bien aunque sea un vector
        ncol = len(self.data[0])
        self.shape = (nrow, ncol)
        # validar tamano correcto de filas
        if any([len(r) != ncol for r in self.data]):
            raise Exception("Las filas deben ser del mismo tamano")
        
    def __add__(self, other):
        "Hora de sumar"
        if isinstance(other, Array):
            if self.shape != other.shape:
                raise Exception("Las dimensiones son distintas!")
            rows, cols = self.shape
            newArray = Array([[0. for c in range(cols)] for r in range(rows)])
            for r in range(rows):
                for c in range(cols):
                    newArray.data[r][c] = self.data[r][c] + other.data[r][c]
            return newArray
        elif isinstance(2, (int, float, complex)): # en caso de que el lado derecho sea solo un numero
            rows, cols = self.shape
            newArray = Array([[0. for c in range(cols)] for r in range(rows)])
            for r in range(rows):
                for c in range(cols):
                    newArray.data[r][c] = self.data[r][c] + other
            return newArray
        else:
            return NotImplemented # es un tipo de error particular usado en estos metodos
    def __radd__(self,other):
        if  isinstance(other, (int, float, complex)): 
            rows, cols = self.shape
            newArray = Array([[0. for c in range(cols)] for r in range(rows)])
            for r in range(rows):
                for c in range(cols):
                    newArray.data[r][c] = self.data[r][c] + other
            return newArray
        else:
            return NotImplemented

In [72]:
A = Array([[1,2], [3,4]])
B = Array([[5,6], [7,8]])
C = A + B
C.data


Out[72]:
[[6, 8], [10, 12]]

In [70]:
D=A+10
D.data


Out[70]:
[[11, 12], [13, 14]]

In [73]:
1+A = Array([[1,2], [3,4]])


  File "<ipython-input-73-d6e899e82ae0>", line 1
    1+A = Array([[1,2], [3,4]])
                               ^
SyntaxError: can't assign to operator