ISIS1225 - Laboratorio4
ISIS1225 - Laboratorio4
ISIS1225 - Laboratorio4
Contenido
1 Objetivos ............................................................................................................................................. 2
2 Fecha de Entrega ................................................................................................................................ 2
3 Preparación......................................................................................................................................... 2
3.1 Estudiar DISCLib y los algoritmos ............................................................................................... 2
4 Trabajo Propuesto............................................................................................................................... 3
4.1 Bifurcar el proyecto en su organización .................................................................................... 3
4.2 Clonar el proyecto en el computador ........................................................................................ 3
4.3 Estudiar y Analizar el Ejemplo .................................................................................................... 4
4.4 Modificar Código del View ......................................................................................................... 6
4.5 Implementar Funciones en el Modelo ....................................................................................... 9
4.6 Probar Modificaciones .............................................................................................................. 13
5 Avance en el Reto No. 1 .................................................................................................................. 16
5.1 Integrar la pila de compilación ................................................................................................ 16
6 Entrega.............................................................................................................................................. 16
6.1 Confirmar avance del Reto ....................................................................................................... 16
6.2 Confirmar cambios finales en el laboratorio ........................................................................... 16
6.3 Revisar entregables de la practica ........................................................................................... 16
6.4 Compartir resultados con los evaluadores ............................................................................... 17
1 Objetivos
Comprender el funcionamiento y la implementación de los algoritmos recursivos. Al finalizar este
laboratorio el estudiante estará en capacidad de:
1) Comprender y solucionar las particularidades técnicas de implementar funciones y
procedimientos recursivos.
2) Comprender la complejidad temporal de los algoritmos recursivos.
3) Analizar los tiempos de ejecución de los algoritmos ejecutando pruebas funcionales.
4) Comprender las diferencias entre los algoritmos de ordenamiento recursivos e iterativos en
DISCLib.
5) Integrar código de monitoreo (toma de datos) dentro de lo previamente implementado.
2 Fecha de Entrega
Recuerde que para el final de la sesión del laboratorio los miembros del grupo deben completar todas
las modificaciones propuestas en el paso 4.4 Modificar Código .
La entrega completa del laboratorio hasta el paso 6.4 Compartir resultados con los evaluadores
será el martes 20 de febrero antes de la media noche (11:59 p.m.)
3 Preparación
3.1 Estudiar DISCLib y los algoritmos
Esta práctica aplicará los ordenamientos recursivos sobre el TAD Lista. Para ello se recomienda que los
estudiantes revisen los siguientes recursos del curso:
a. La librería DISCLib del curso, en específico los módulos que implementan el del ADT Lista
ubicado en DISClib\ADT\list.py
b. Los algoritmos de ordenamiento recursivos (Merge y Quick) disponibles en la carpeta
DISClib\Algorithms\Sorting\* en los repositorios de los laboratorios.
c. Utilice el documento Observaciones-Lab4.docx del Laboratorio 4 para completar las preguntas
de observación y análisis de la práctica.
NOTA: Cuando se trabaja con Python es posible obtener un mensaje de error que indica que se ha
alcanzado el límite de recursión. Este mensaje ("RecursionError: maximum recursion depth exceeded
in comparison"), señala que el espacio reservado en memoria para almacenar las instrucciones del
programa, conocido como la pila (stack), está lleno. Como resultado, el proceso de ejecución de la
operación no podrá finalizarse adecuadamente.
Una forma de permitir más operaciones dentro del stack, es actualizar el límite de recursión del
programa desde view.py como se muestra en el código escrito en el Segmento 1.
import sys
…
default_limit = 1000
sys.setrecursionlimit(default_limit*10)
Segmento 1. modificaciones para el límite de recursión de Python en el view.py.
4 Trabajo Propuesto
4.1 Bifurcar el proyecto en su organización
Bifurque/haga un Fork del repositorio en su organización utilizando el procedimiento aprendido en las
prácticas anteriores. Recuerde que los siguientes pasos los debe completar solo un miembro de la
organización:
p.1. Abra el enlace SampleRecursion.
p.2. Bifurque el repositorio privadamente como lo aprendió en la práctica pasada.
p.3. Cambie el nombre del repositorio siguiendo el esquema LabRecursive-L<<XX>>-G<<YY>>
donde XX es el numero de la práctica que se está haciendo y YY el número del grupo de trabajo
(ej.: LabRecursive-L04-G01 para el quinto laboratorio del primer grupo).
p.4. Confirme los cambios en el nombre del repositorio seleccionando la opción de Renombrar
(Rename) la pestaña de Ajustes (Settings).
NOTA: Recuerde que NO necesita agregar la sección o el semestre en este nombre porque ya está
identificado en su organización.
p.6
1
Este proceso puede completarse por diferentes medios, utilizando la terminal/consola de Windows o MacOS, y
también utilizando aplicaciones independientes como GitHub Desktop y Sourcetree
4.3 Estudiar y Analizar el Ejemplo
El proyecto SampleRecursion busca familiarizarlos con especificar, desarrollar y probar funciones
recursivas, así como también probar su desempeño comparándolas con implementaciones iterativas
equivalentes en el MVC. Antes de iniciar a explorar y modificar el ejemplo:
p.9. Descargue los datos de trabajo Goodreads disponibles en el portal oficial del curso en Bloque
Neón. Descargue el Zip, descomprímalo y guarde los archivos CSV en la carpeta
*/Data/GoodReads/ de su copia local de código.
p.10. Cambie los archivos que está cargando el programa desde el controller.py, para ello borre
el sufijo “-small” (marcadas con el comentario “# TODO cambiar nombre del archivo
(parte 1)”) en las funciones loadBooks() y loadBooksTags().
p.11. Ejecute el menú de opciones desde el archivo view.py, al hacerlo podrá ver el siguiente menú
por consola como lo muestra la Ilustración 2.
Ilustración 2. Menú de opciones por consola del SampleRecursion ejecutado desde el view.py.
p.13
Para comprender como funciona el ordenamiento anterior, complete los siguientes pasos:
p.15. Diríjase al archivo model.py
p.16. Revise en el código las implementaciones de sortBooks() y compareISBN() marcadas con
el comentario # TODO examinar el ordenamiento (parte 1)”.
p.17. Responda la siguiente pregunta de observación basado en la implementación del model.py y
expuesta en el Segmento 2.
a. ¿Qué modificaciones debería hacer en la librería DISCLib para crear un nuevo algoritmo
de ordenamiento?, especifique archivos, rutas de y encabezados de las posibles
funciones a implementar.
p.18. Registre las respuestas en el documento Observaciones-lab4.docx
def sortBooks(catalog):
"""
Ordena los libros por ISBN
"""
# TODO examinar el ordenamiento (parte 1)
books = catalog["books"]
sorted_list = qs.sort(books, compareISBN)
catalog["books"] = sorted_list
return sorted_list
Segmento 2. Modificaciones para la función sortBooks() en el model.py.
4.4 Modificar Código del View
Ahora, la práctica se concentrará en modificar el código para darle la habilidad al usuario de ejecutar
recursiva o iterativamente las siguientes operaciones:
1. Encontrar por búsqueda binaria un libro dentro del catálogo.
2. Calcular el promedio de la calificación de todos los libros en el catálogo.
3. Filtrar los libros del catálogo según un rango de calificaciones.
Además, tendrá una opción más que le permitirá al usuario elegir el tipo de algoritmo (recursivo o
iterativo) que utilizará en las opciones anteriores. Para ello complete las siguientes indicaciones:
p.19. Diríjase al archivo view.py.
p.20. Busque la función que imprime las opciones del menú llamada printMenu() utilizando el
comentario “# TODO agregar opciones al menu (parte 2)”.
p.21. Modifique la función según las indicaciones que muestra el Segmento 3.
def printMenu():
print("Bienvenido")
print("1- Cargar información en el catálogo")
print("2- Consultar los Top x libros por promedio")
print("3- Consultar los libros de un autor")
print("4- Libros por género")
print("5- Ordenar los libros por ISBN")
print("6- Desordenar los libros por ISBN")
# TODO agregar opciones al menu (parte 2)
print("7- Buscar un libro por ISBN")
print("8- Calcular el rating promedio de libros")
print("9- Filtrar el catálogo de libros por un rango de califaciones")
print("10- Cambiar tipo de algoritmos (recursivos o iterativos)")
print("0- Salir")
Segmento 3. Modificaciones para la función printMenu() en el view.py.
Note que todavía no hemos modificado los archivos model.py y controller.py y que las
funcionalidades expuestas en el menú deben completarse en el resto del MVC.
Recuerde que la función del Segmento 3 es simplemente informativa y que las opciones deben
habilitarse en la función principal llamada menu_cycle() para habilitar el IO (Input/Output) apropiado
en el view.py.
p.22. Busque el comentario “# TODO modificar opcion 7 del menu (parte 2)”.
p.23. Modifique el segmento de código correspondiente para la opción 7 tal como lo muestra el
Segmento 4.
elif int(inputs) == 7:
# TODO modificar opcion 7 del menu (parte 2)
isbn = input("Ingrese el ISBN del libro a buscar: ")
isbn = int(isbn)
result = controller.findBookByISBN(control,
isbn,
recursive=rec)
delta_time = f"{result[0]:.3f}"
book = result[1]
print("===== El libro encontrado es: =====")
print("Para encontrar el libro con ISBN", isbn,
", tiempo:", str(delta_time), "[ms]")
print("Algoritmo recursivo:", rec)
printSearchResults(book)
Segmento 4. Modificaciones para la opción 7 de la función menu_cycle() en el view.py.
p.24. Ahora, busque el comentario “# TODO modificar opcion 8 del menu (parte 2)”.
p.25. Modifique el segmento de código correspondiente para la opción 8 tal como lo muestra el
Segmento 5.
elif int(inputs) == 8:
# TODO modificar opcion 8 del menu (parte 2)
result = controller.getBooksAverageRating(control,
recursive=rec)
delta_time = f"{result[0]:.3f}"
average = result[1]
print("===== El rating promedio de los libros es: =====")
print("Para", controller.bookSize(control), "elementos, tiempo:",
str(delta_time), "[ms]")
average = f"{average:.3f}"
print("Algoritmo recursivo:", rec)
print("El rating promedio es:", average)
Segmento 5. Modificaciones para la opción 8 de la función menu_cycle() en el view.py.
p.26. Ahora, busque el comentario “# TODO modificar opcion 9 del menu (parte 2)”.
p.27. Modifique el segmento de código correspondiente para la opción 9 tal como lo muestra el
Segmento 6.
elif int(inputs) == 9:
# TODO modificar opcion 9 del menu (parte 2)
print("Filtra los libros con un rating entre dos valores")
lower = float(input("Ingrese el rating mínimo: "))
upper = float(input("Ingrese el rating máximo: "))
result = controller.filterBooksByRating(control,
lower,
upper,
recursive=rec)
print("===== Los libros entre", lower, "y", upper, "son: =====")
delta_time = f"{result[0]:.3f}"
filtered_list = result[1]
size = lt.size(filtered_list)
print("Para", size, "elementos, tiempo:", str(delta_time), "[ms]")
print("Algoritmo recursivo:", rec)
printSortResults(filtered_list)
Segmento 6. Modificaciones para la opción 9 de la función menu_cycle() en el view.py.
p.28. Ahora, busque el comentario # TODO modificar opcion 10 del menu (parte 2)”.
p.29. Modifique el segmento de código correspondiente para la opción 10 tal como lo muestra el
Segmento 7.
elif int(inputs) == 10:
# TODO modificar opcion 10 del menu (parte 2)
# configurar si usa algoritmos recursivos
rec = input("Usar algoritmos recursivos? (S/N): ")
if rec in bool_lt_opt:
rec = True
else:
rec = False
Segmento 7. Modificaciones para la opción 10 de la función menu_cycle() en el view.py.
NOTA: Si después de ejecutar los cambios y volver a compilar el programa no observa ningún cambio
en el comportamiento borre la carpeta __pycache__ dentro de /App/*, esto forzará a VS Code a
compilar el código nuevamente y junto con los cambios sobre la nueva ejecución del programa.
4.5 Implementar Funciones en el Modelo
Después de modificar el view.py iniciaremos las modificaciones del resto del MVC. Para comprender
la lógica detrás de las modificaciones esperadas observe la Ilustración 6 y la Ilustración 7.
Primero, la Ilustración 6 contiene el diagrama de responsabilidades y actividades para las funciones
recursivas e iterativas que deseamos crear. La Ilustración 6 especifica como los cambios en el view.py
permiten al controller.py redireccionar las peticiones y parámetros asociados al model.py
mientras que este se responsabiliza de tomar los tiempos de ejecución.
Por su parte, el model.py contiene la función principal invocada por controlador. A su vez, esta función
se divide en las implementaciones recursiva e iterativa del mismo requerimiento. En particular, la
versión recursiva del requerimiento se divide en una máscara y en la implementación recursiva
principal, esto se hace para mantener el estado de la función a lo largo de sus invocaciones y poder
recomponer la respuesta final.
Adicionalmente, la Ilustración 7 contiene un ejemplo de las referencias a los bloques de código
asociados a las responsabilidades descritas en Ilustración 6. Por ejemplo, en el modelo la línea de
código “elif int(inputs) == 7:” está asociada con seleccionar la funcionalidad en el menú.
En el controlador, el bloque de código “deltaTime(start_time, end_time)” está asociado a la
toma de tiempos de ejecución. Consecuentemente, el bloque de código “def
SearchBookByISBN(catalog, bookisbn):” muestra la función asociada con invocar la máscara
recursiva en el model.py.
Seleccionar la opción
Vista (view.py) del menú
Modelo
(model.py)
Invocar la función
recursiva
Controller.py
def findBookByISBN(control,isbn,recursive=True):
…
if recursive:
…
else:
…
Model.py
def searchBookByISBN(books, bookisbn):
…
def recursiveSearchBookByISBN(catalog, bookisbn, low,
high):
…
def iterativeSearchBookByISBN(catalog, bookid):
…
Ilustración 7. definiciones y bloques de código Python relacionados con las responsabilidades MVC.
Ahora, utilizando las marcas “# TODO…” deberán modificar el código del model.py para completar
las funcionalidades asociadas al menú principal. Recuerde que estas son:
1. Encontrar por Búsqueda Binaria un libro dentro del catálogo.
2. Calcular el promedio de la calificación de todos los libros en el catálogo.
3. Filtrar los libros del catálogo según un rango de calificaciones.
Para implementar correctamente las modificaciones complete las siguientes instrucciones:
p.33. Dividir los tres requerimientos entre cada uno de los miembros del grupo de trabajo.
p.34. Examinar las marcas de pendientes “# TODO…” con TODO Tree para conocer que funciones
debe modificar como lo muestra la Ilustración 8.
p.35. Examinar la documentación y los encabezados de las funciones asociadas a cada requerimiento
como se muestra en el ejemplo de la función searchBookByISBN() en el Segmento 8.
p.36. Implementar las modificaciones necesarias en el model.py para completar:
a. La versión iterativa del algoritmo (ej.: iterativeSearchBookByISBN()).
b. La máscara recursiva del algoritmo (ej.: searchBookByISBN()).
c. La versión recursiva del algoritmo (ej.: recursiveSearchBookByISBN()).
p.37. Confirme (push) los cambios hechos a su repositorio con el mensaje “modificaciones
algoritmos recursivos, <<función principal del modelo>> – Laboratorio 4”. (ej.: “git commit
-m “modificaciones algoritmos recursivos, searchBookByISBN()– Laboratorio
4”).
def searchBookByISBN(catalog, bookisbn):
"""searchBookByISBN es la MASCARA para la busqueda recursiva,
recibe el catalogo y el ISBN del libro buscarlo en la lista de libros del
catalogo y prepara las condiciones para la recursion
Args:
catalog (dict): el catalogo de libros
bookisbn (int): el ISBN del libro que se busca
Returns:
book: el diccionario que cumple con el ISBN dentro de la
lista de libros
"""
# TODO implementar la mascara de la busqueda recursiva (parte 2)
pass
Ilustración 8. Listado de modificaciones e instrucciones en TODO Tree para modificar el código de SampleRecursion.
Al finalizar ordene los libros con la opción 5, pruebe buscando el ISBN 9789993911560 y observe que
su programa deberá comportarse como lo muestra la Ilustración 9.
Además, note que si desordena los libros (opción 6) y vuelve a buscar el ISBN, el resultado será
drásticamente diferente como lo muestra la Ilustración 10 ya que el algoritmo falla al no encontrar el
libro deseado.
p.38. Al finalizar, considere las siguientes preguntas de observación sobre los cambios realizados.
b. ¿Cómo se relaciona la opción 10 del menú en el view.py con las funciones principales
(opciones 7, 8 y 9) dentro del model.py?
c. ¿Por qué se usa la máscara en las funciones propuestas?, ¿siempre es necesaria?,
argumente su respuesta.
p.39. Registre las respuestas en el documento Observaciones-lab4.doc.
.
Ilustración 9. Ejemplo funcional de una búsqueda binaria exitosa en el SampleRecursion.
Ilustración 10. Ejemplo funcional de una búsqueda binaria fallida en el SampleRecursion.
Ilustración 11. Ejemplo del fallo al ejecutar el código por exceder el límite de recursión.
Ilustración 13. Ejemplo del comportamiento normal del programa al configurar correctamente el límite de recursión y el
tamaño de la pila de ejecución.
6 Entrega
6.1 Confirmar avance del Reto
Confirme los cambios en el repositorio Reto1-G<<XX>> con el comentario “Avance pila de memoria
recursiva – Reto 1 ” (git commit -m “Avance pila de memoria recursiva – Reto 1”) 2
2
Para prevenir errores en los repositorios GitHub, GIT (por medio del .gitignore) bloquea la carga de
archivos .csv dentro de la carpeta /Data/* y así evitar que los datos de trabajo excedan el límite permitido
por los repositorios. Los estudiantes deberán descargar localmente los archivos desde Bloque Neón sin que esto
afecte el funcionamiento de la aplicación.
2) Enlace al repositorio GitHub Reto1-G<<XX>> con rama main actualizada con el comentario
“Avance pila de memoria recursiva – Reto 1” antes de la fecha límite de entrega.
3) Enlace al repositorio GitHub LabRecursive-L<<XX>>-G<<YY>> con rama Main actualizada con el
comentario “Laboratorio 4 – Entrega final” antes del límite de entrega, recuerde que este es el
mismo que el laboratorio anterior de ordenamientos recursivos.
4) README del repositorio con los datos completos de los integrantes del grupo (nombre completo,
correo Uniandes y código de estudiante).
5) Enlace al repositorio GitHub Reto1-G<<XX>> con rama main actualizada con el comentario
“Avance pila de memoria recursiva – Reto 1” antes de la fecha límite de entrega.
6) Incluir en repositorio la carpeta Docs el documento Observaciones-lab4.pdf con la siguiente
información:
a. Nombres, apellidos, código de estudiante de los integrantes del grupo.
b. Respuesta a las preguntas de análisis:
i) ¿Qué modificaciones debería hacer en la librería DISCLib para crear un nuevo
algoritmo de ordenamiento?, especifique archivos, rutas de y encabezados de las
posibles funciones a implementar.
ii) ¿Cómo se relaciona la opción 10 del menú en el view.py con las funciones
principales (opciones 7, 8 y 9) dentro del model.py?
iii) ¿Por qué se usa la máscara en las funciones propuestas?, ¿siempre es necesaria?,
argumente su respuesta.
iv) ¿Cuál es la causa del error “RecursionError: maximum recursion Depth
exceded” al ejecutar el código?
v) ¿Cuál es la causa por la que termina anormalmente el programa?
vi) ¿Qué es lo que hacen las modificaciones del main al incluir el uso de threading
en la ejecución del código?, utilice el código Segmento 10 y la documentación
oficial de Python para argumentar su respuesta.
vii) ¿Qué diferencias existen entre exceder el límite de recursión y la terminación
anormal del programa?