Ejemplos 1

Matriz traspuesta

ALGORÍTMICA Y COMPLEJIDAD
Grados en Ing. Informática y Matemáticas
Universidad de Cantabria
Camilo Palazuelos Calderón

Definimos la función Trasponer, que devuelve la traspuesta de la matriz cuadrada $\mathbf{A}$ que recibe como parámetro en forma de array bidimensional $A[0..\ell - 1, 0..\ell - 1]$.

In [ ]:
def Trasponer(A):
    return [[A[j][i] for j in range(len(A))] for i in range(len(A))]

Probamos la función con la matriz $\mathbf{A} = \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{pmatrix}$. Trasponer($A[0..2, 0..2]$) debería devolver $\begin{pmatrix} 1 & 4 & 7 \\ 2 & 5 & 8 \\ 3 & 6 & 9 \end{pmatrix}$.

In [ ]:
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(f'Trasponer({A}) = {Trasponer(A)}')
Trasponer([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Para evaluar el coste temporal empírico de Trasponer, creamos un array bidimensional $B[0..m - 1, 0..m - 1]$ de ceros y unos con $m$ suficientemente grande (por ejemplo, $m = 10^4$). Iterativamente, traspondremos las primeras $n$ filas y $n$ columnas de $B[0..m - 1, 0..m - 1]$ y añadiremos el coste temporal empírico de Trasponer($B[0..n - 1, 0..n - 1]$) a una lista $T$.

In [ ]:
m = 10000
B = [[i % 2 for _ in range(m)] for i in range(m)]
T = [0]

Modificamos Trasponer para acceder a fragmentos de posiciones consecutivas de $B[0..m - 1, 0..m - 1]$ y evitar así crear arrays de entrada en cada iteración. Para ello, añadimos un parámetro $n$ a la cabecera de la función tal que $n \le m$.

In [ ]:
def Trasponer2(A, n):
    return [[A[j][i] for j in range(n)] for i in range(n)]

Trasponer2(B, 5)
Out[ ]:
[[0, 1, 0, 1, 0],
 [0, 1, 0, 1, 0],
 [0, 1, 0, 1, 0],
 [0, 1, 0, 1, 0],
 [0, 1, 0, 1, 0]]

Evaluamos el coste temporal empírico de Trasponer2 con matrices cuadradas de orden $n$ desde $1 \cdot 10^3$ hasta $10 \cdot 10^3$ (de $10^3$ en $10^3$).

In [ ]:
import time

for n in range(m // 10, m + 1, m // 10):
    t = time.time()
    Trasponer2(B, n)
    T.append(time.time() - t)
    #print(f'Iteración {n // (m // 10)} de 10')

Dibujamos una gráfica con el tiempo de ejecución $T(n)$ de Trasponer2 en función del orden $n$ de las matrices cuadradas de entrada.

In [ ]:
import matplotlib.pyplot as plt
import numpy as np

with plt.style.context('ggplot'):
    plt.plot(np.array(T), label = '$T(n) \in O(n^2)$')
    plt.xticks(
        [    x               for x in range(0, 11, 2)],
        [f'${x} \cdot 10^3$' for x in range(0, 11, 2)])
    plt.xlabel(        '$n$', fontsize = 12)
    plt.ylabel('$T(n)$ en s', fontsize = 12)
    plt.title('Complejidad temporal')
    plt.legend()

plt.show()
No description has been provided for this image
In [ ]: