LAB 04 - Representación en memoria
Contents
!wget --no-cache -O init.py -q https://raw.githubusercontent.com/rramosp/20192.L3/master/init.py
import init; init.init(force_download=False); init.get_weblink()
import init
from local.lib.rlxmoocapi import submit, session
import inspect
student = session.Session(init.endpoint).login( course_id=init.course_id,
session_id="UDEA",
lab_id="lab_04" )
LAB 04 - Representación en memoria¶
Ejercicio 1¶
Una matriz diagonal 2D es aquella en la que cualquier elemento \(m_{ij}=0 \iff i \ne j\). Trataremos solamente con matrices cuadradas, es decir \(\in \mathbb{R}^{n \times n}\).
Si asumimos que solo tenemos matrices cuadradas, podemos almacenar solo la diagonal.
Completa la siguiente función para que, dado un array numpy
de entrada:
Lance un
AssertionError
si no es cuadrado o no es diagonalDevuelva un vector con las posiciones de almacenamiento de su diagonal, asumiendo una posición inicial y un tamaño de dato.
Por ejemplo, para esta entrada:
[[ 1 0 0]
[ 0 3 0]
[ 0 0 -3]]
con init_pos=19
y size=5
, la salida debería de ser:
[19, 24, 29]
def diag_store(m, init_pos=0, size=4):
import numpy as np
assert <... TU CODIGO AQUI ...>
return <... TU CODIGO AQUI ...>
comprueba manualmente tu código
import numpy as np
a = np.array([[1,0,0], [0,3,0], [0,0,-3]])
print(a)
diag_store(a, init_pos=19, size=5)
registra tu solución en línea¶
student.submit_task(globals(), task_id="task_01");
Ejercicio 2¶
Una matriz triangular 2D es aquella en la que cualquier elemento \(m_{ij}=0 \iff i > j\), en donde \(i\) son las filas y \(j\) las columnas. Si asumimos que solamente trataremos con matrices cuadradas, es decir \(\in \mathbb{R}^{n \times n}\).
Completa la siguiente función para que, dado un array numpy
de entrada:
Lance un
AssertError
si no es cuadrado o no es triangular superiorLance un
AssertError
si el parámetroorientation
es distinto decolumns
orows
Devuelva un vector con las posiciones de almacenamiento de sus elementos, asumiendo una posición inicial y un tamaño de dato.
Tenga en cuenta el parámetro
orientation
q
Por ejemplo, para esta entrada:
[[ 1 0 0]
[ 0 3 0]
[ 0 0 -3]]
con init_pos=19
y size=5
, la salida debería de ser:
[19 24 29 34 39 44]
observa que dada una matriz triangular superior \(\in \mathbb{R}^{n\times n }\), el número de elementos que hay que almacenar viene dado por:
ya que
\(n^2\) es el número total de elementos de la matriz
\(n^2-n\) es el número de elementos excluyendo la diagonal
\(\frac{n^2-n}{2}\) es el número de elementos de un triángulo (superior o inferion) excluyendo la diagonal
\(\frac{n^2 - n}{2} + n\) es el número de elementos de un triángulo incluyendo la diagonal
def triang_store(m, init_pos=0, size=4, orientation="columns"):
import numpy as np
assert <... TU CODIGO AQUI ...>
return <... TU CODIGO AQUI ...>
comprueba manualmente tu código
import numpy as np
a = np.array([[1,0,3], [0,3,1], [0,0,-3]])
print(a)
print(triang_store(a, init_pos=19, size=5))
registra tu solución en línea¶
student.submit_task(globals(), task_id="task_02");
Ejercicio 3¶
Dado:
una especificación de dimensiones de un array \((d_0, d_1, ... d_{n-1})\) de \(n\) dimensiones
una especificación de orden de almacenamiento \(\mathbb{P}[0,1,..,n-1]\) (una permutación de los elementos del \(0\) a \(n-1\))
una dirección de memoria de base (de inicio)
un tamaño de dato
obtén la matriz de posiciones de memoria de cualquier array de tales dimensiones. Tu salida ha de ser un array de numpy
Por ejemplo, para
dims = [2,2,2]
order = [0,1,2]
la salida ha de ser
[[[ 0 16]
[ 8 24]]
[[ 4 20]
[12 28]]]
y para
dims = [2,3,4]
order = [2,1,0]
la salida ha de ser
[[[ 0 4 8 12]
[16 20 24 28]
[32 36 40 44]]
[[48 52 56 60]
[64 68 72 76]
[80 84 88 92]]]
Sugerencia: usa la siguiente estrategia de implementación
Genera todas las posibles coordenadas de la matriz correspondiente a
dims
. Con esto deberías de generar un array de dimensiones \((\prod d_i)\times n\)Usa
pandas.sort_values
para ordenar todas las posibles coordenadas segúnorder
(usa el parámetroby
)El dataframe generado anteriormente contiene en orden en el que se almacenarían en memoria los elementos de la matriz original según la especificación en
dims
y enorder
Genera una matriz de ceroz de tamaños
dims
y recorre secuencialmente el dataframe anterior actualizando cada coordenada.
def get_storage_positions(dims, order, size, init_pos=0):
import pandas as pd
import numpy as np
import itertools
<... TU CODIGO AQUI ...>
return <... TU CODIGO AQUI ...>
print(get_storage_positions(dims = [3,2], order = [0,1], size=4))
print(get_storage_positions(dims = [2,3,4], order = [0,1,2], size=4))
print("--")
print(get_storage_positions(dims = [2,3,4], order = [2,1,0], size=4))
print("--")
print(get_storage_positions(dims = [2,2,2], order = [0,1,2], size=4))
print("--")
print(get_storage_positions(dims = [2,2,2], order = [2,1,0], size=4))
registra tu solución en línea¶
student.submit_task(globals(), task_id="task_03");
Ejercicio 4¶
Dado un array de posiciones en memoria de \(n\) dimensiones queremos descubrir qué ordenación tiene en memoria. Este ejercicio es el inverso del anterior.
Por ejemplo, dada la siguiente matriz de entrada
[[[ 0 4 8 12]
[16 20 24 28]
[32 36 40 44]]
[[48 52 56 60]
[64 68 72 76]
[80 84 88 92]]]
tu función ha de devolver la tupla
[2,1,0]
o con la siguiente matriz:
[[[ 0 4 8 12]
[32 36 40 44]
[64 68 72 76]]
[[16 20 24 28]
[48 52 56 60]
[80 84 88 92]]]
ha de devolver la tupla
[2,0,1]
Sugerencia de implementación: para resolver este problema tienes que fijarte en el incremento en cada eje. Por ejemplo, fíjate en los dos primeros elementos de cada eje en la última matriz. Observa como el primer eje es el 2, el segundo el 0 y el último el 1.
import numpy as np
a = [2,4]
np.argsort(a)
a = [10,4,7,-1,20]
print(np.array(a))
print(np.r_[a])
print(np.argsort(a))
a = np.random.randint(10, size=(2,5,4))
a
dims = len(a.shape)
my_slices = tuple([slice(0,1,1)]*dims)
print(my_slices)
a[my_slices].flatten()
import numpy as np
r = np.array([[[ 0, 4, 8, 12],
[32, 36, 40, 44],
[64, 68, 72, 76]],
[[16, 20, 24, 28],
[48, 52, 56, 60],
[80, 84, 88, 92]]])
print(r[:2,0,0])
print(r[0,:2,0])
print(r[0,0,:2])
ndims = 3
r = np.random.randint(100, size=[2]*ndims)
print(r)
mis_slices = tuple([slice(0,2,None)]+[0]*(ndims-1))
print("--")
print(r[mis_slices])
r[:2,0,0]
import numpy as np
a = np.r_[10,4,2,20,1]
np.sort(a)
np.argsort(a)
por tanto te sugiero una implementación en la que:
Hagas un bucle por el número de dimensiones
Para cada dimensión generes una lista de
slices
equivalentes a la notación de indexado anteriorObtengas los dos primeros elementos de cada eje
Ordenes los ejes por la diferencia entre esos dos elementos
quizá la función np.argsort
pueda serte de ayuda
def get_storage_order(r):
import numpy as np
return <... TU CODIGO AQUI ...>
comprueba manualmente tu código
r = np.array([[[ 0, 4, 8, 12],
[32, 36, 40, 44],
[64, 68, 72, 76]],
[[16, 20, 24, 28],
[48, 52, 56, 60],
[80, 84, 88, 92]]])
get_storage_order(r)
registra tu solución en línea¶
student.submit_task(globals(), task_id="task_04");