Evolución y mejora en la traducción de código Vensim a código Python: ingeniería inversa y mantenimiento de PySD
Abstract
Grado en Ingeniería Informática
Full text
Universidad de Valladolid ESCUELA DE INGENIER´ IA INFORM´ ATICA GRADO EN INGENIER´ IA INFORM ´ ATICA Menci´on en Ingenier´ıa del Software Evoluci´on y mejora en la traducci´on de c´odigo Vensim a c´odigo Python: Ingenier´ıa inversa y mantenimiento de PySD Alumna: Mar´ıa Robles del Blanco Tutores: Yania Crespo Gonz´alez-Carvajal David Escudero Mancebo
A mis padres, por todo su apoyo I
II
AGRADECIMIENTOS Agradecimientos A mi familia, por su gran amor y continuo apoyo. A mis amigos, por ayudarme a crecer d´ıa a d´ıa y acompa˜narme en todo momento. A mi tutora Yania, por su gran supervisi´on y gu´ıa durante el proyecto y, sobretodo, por su gran labor como profesora. A mi tutor David, por sus sugerencias y ayuda. Al grupo GEEDS de la UVa, por su aportaci´on con la realizaci´on de modelos y compartir sus conocimientos. Al proyecto LOCOMOTION, por la financiaci´on de la beca para este trabajo. III
AGRADECIMIENTOS IV
RESUMEN Resumen El objetivo de este Trabajo de Fin de Grado es mejorar el proyecto de PySD para poder traducir IAMs (Integrated Assessment Models) creados con Vensim al lenguaje Python. Este Trabajo de Fin de Grado se engloba dentro del proyecto europeo LOCOMOTION [27], el cual est´a basado en desarrollar modelos sofisticados que permiten evaluar el impacto ambiental y sociecon´omico que tendr´a la toma de ciertas decisiones, para poder llegar a obtener un futuro sostenible con bajas emisiones de carbono. M´as concretamente, este proyecto tiene como objetivo la traducci´on del modelo WILIAM, basado en modelos MEDEAS [47] existentes, que simulan las relaciones altamente complejas entre el ser humano y el entorno. El citado modelo se desea traducir del lenguaje Vensim al lenguaje Python, para lo que se utilizar´a el proyecto PySD, desarrollando funcionalidades adicionales necesarias. Este trabajo se ha desarrollado bajo el marco de trabajo Scrum. Finalmente, se ha conseguido agregar funcionalidad nueva a PySD, corregir ligeros fallos y colaborar con otros contributors mediante tres pull requests realizadas al repositorio central de PySD. Adem´as, se ha creado documentaci´on en ingl´es sobre el funcionamiento interno de PySD, para reducir la complejidad de la curva de aprendizaje de futuros desarrolladores. V
RESUMEN VI
ABSTRACT Abstract The purpose of this project is to improve the PySD project by translating IAMs (Integrated Assessment Models) created with Vensim into the Python language. This final degree project is part of the European LOCOMOTION project [27], which is based on the development of sophisticated models that will assess the socioeconomic and enviromental impact of certain decisions in order to achieve a sustainable future with low-carbon emisions. Specifically, this project aims to translate the WILIAM model, based on MEDEAS models [47], which simulate the complex relationship between the humans and the enviroment. This model is to be translated from the Vensim language into the Python language, for which the PySD project will be used, developing the necessary additional functionalities. This project has been developed under the Scrum framework. Finally, it has been possible to add new functionalities to PySD, fix minor bugs and collaborate with other contributors through three pull requests made to the PySD central repository. In addition, documentation on the inner workings of PySD has been created in English to reduce the complexity of the learning curve for future developers. VII
´ INDICE GENERAL B. Resumen de enlaces adicionales 119 Bibliograf´ıa 121 XIV
LISTA DE FIGURAS Lista de Figuras 2.1. Artefactos y Eventos de Scrum. [30] . . . . . . . . . . . . . . . . . . . . . . . 9 3.1. Ramas principales de PySD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.2. Estructura del patr´on Visitor. [5] . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.3. Diagrama de secuencia del patr´on Visitor. [5] . . . . . . . . . . . . . . . . . . 28 3.4. Diagrama de clases y de secuencia: Patr´on Decorator [73] ........... 30 4.1. El Modelo de Vistas 4+1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.2. Vista de desarrollo PySD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.3. Relaciones entre m´odulos de PySD . . . . . . . . . . . . . . . . . . . . . . . . 41 4.4. M´odulos principales PySD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.5. Gram´aticas de vensim2py simplificadas..................... 44 4.6. Clases asociadas a las gram´aticas del m´odulo vensim2py ........... 45 4.7. Clases asociadas a las gram´aticas del m´odulo vensim2py ........... 45 4.8. M´odulo functions ysusclases .......................... 46 4.9. M´odulo functions y clase Time ......................... 47 4.10. Clases Stateful,Integ,Macro yModel del m´odulo functions ........ 48 4.11. M´odulo builder .................................. 49 4.12. M´odulo utils .................................... 50 4.13. M´odulo external ysusclases........................... 50 XV
LISTA DE FIGURAS 4.14. Clase Excels yExternal del m´odulo external ................. 51 4.15. Clases del m´odulo external ............................ 52 4.16. M´odulo decorators ................................ 53 4.17. Diagrama de actividad principal . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.18. Diagrama de actividad. Separar en secciones . . . . . . . . . . . . . . . . . . . 54 4.19. Diagrama de actividad. Crear la lista de macros . . . . . . . . . . . . . . . . . 54 4.20. Diagrama de actividad. Organizar cada secci´on . . . . . . . . . . . . . . . . . 55 4.21. Diagrama de actividad. Crear namespace en Python . . . . . . . . . . . . . . 56 4.22. Diagrama de actividad. Parsear cada componente . . . . . . . . . . . . . . . . 57 4.23. Diagrama de Casos de Uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.24. Diagrama de secuencia principal: Traducci´on . . . . . . . . . . . . . . . . . . 59 4.25. Diagrama de secuencia: Traducir secci´on . . . . . . . . . . . . . . . . . . . . . 61 4.26. Diagrama de secuencia: A˜nadir traducci´on y llamar al builder . . . . . . . . . 62 4.27. Diagrama de secuencia: Ejecuci´on del modelo ya traducido . . . . . . . . . . . 63 5.1. GitlabIssues .................................... 66 5.2. GitlabIssues .................................... 67 7.1. Diagrama modificaciones m´odulo builder . . . . . . . . . . . . . . . . . . . . . 103 7.2. Diagrama m´odulo functions con clase SampleIfTrue a˜nadida . . . . . . . . . 104 7.3. Diagrama clase SampleIfTrue a˜nadida . . . . . . . . . . . . . . . . . . . . . . 104 7.4. Diagrama modificaciones m´odulo functions . . . . . . . . . . . . . . . . . . . 105 7.5. Diagrama modificaciones m´odulo vensim2py . . . . . . . . . . . . . . . . . . . 105 7.6. Diagrama gram´aticas modificadas . . . . . . . . . . . . . . . . . . . . . . . . . 106 8.1. Respuesta Eneko Martin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 8.2. Respuesta James Houghton . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 XVI
LISTA DE TABLAS Lista de Tablas 2.1. ProductBacklogInicial .............................. 11 2.2. Calendarizaci´on inicial del proyecto . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3. Riesgodeenfermedad ............................... 12 2.4. Riesgo de cambios en los requisitos . . . . . . . . . . . . . . . . . . . . . . . . 13 2.5. Riesgo de falta de formaci´on . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.6. Riesgo de falta de conocimiento Vensim para pruebas . . . . . . . . . . . . . . 13 2.7. Riesgo de fallar en la planificaci´on . . . . . . . . . . . . . . . . . . . . . . . . 14 2.8. Riesgo de falta de tiempo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.9. Riesgo asociado al hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.10. Riesgo de confinamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.11. Riesgo de funcionalidad limitada Vensim . . . . . . . . . . . . . . . . . . . . . 15 2.12.Costessimulados .................................. 17 2.13.Costesreales .................................... 18 3.1. Reglasdesintaxis.................................. 32 6.1. TareasdelSprint0................................. 72 6.2. TareasdelSprint1................................. 74 6.3. TareasdelSprint2................................. 75 6.4. TareasdelSprint3................................. 77 XVII
LISTA DE TABLAS 6.5. TareasdelSprint4................................. 78 6.6. TareasdelSprint5................................. 80 6.7. TareasdelSprint6................................. 82 6.8. TareasdelSprint7................................. 84 6.9. TareasdelSprint8................................. 87 6.10.TareasdelSprint9................................. 89 6.11.TareasdelSprint10 ................................ 91 6.12.TareasdelSprint11 ................................ 92 6.13.TareasdelSprint12 ................................ 94 6.14.Tablaresumenfinal ................................ 94 6.15. Calendarizaci´on final del proyecto . . . . . . . . . . . . . . . . . . . . . . . . . 95 6.16. Costes simulados finales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 6.17.Costesrealesfinales ................................ 96 XVIII
CAP´ ITULO 1. INTRODUCCI ´ ON Cap´ıtulo 1 Introducci´on 1.1. Motivaci´on Este Trabajo de Fin de Grado se ha realizado como parte de una beca de colaboraci´on con el proyecto europeo LOCOMOTION [27]. Con la financiaci´on del programa Horizonte 2020 [19] de la UE, LOCOMOTION pretende dise˜nar un conjunto de IAM (Integrated Assessment Models) que permitir´a obtener un sistema de modelado confiable con el que se podr´a evaluar las diferentes opciones relacionadas con pol´ıticas de sostenibilidad. LOCOMOTION ayudar´a a la toma de decisiones en base a los resultados del modelado din´amico con variables ambientales, econ´omicas, sociales, tecnol´ogicas y biof´ısicas para poder llegar a una sociedad con menores emisiones de carbono. En el ´ambito de LOCOMOTION se desarrolla el modelo integrado de evaluaci´on WILIAM (“within limits”), basado en modelos MEDEAS existentes. Se trata de un modelo a trav´es del cual se simulan complejos escenarios medioambientales permitiendo ver las consecuencias que tendr´ıa la toma de ciertas decisiones. M´as all´a de eso, se aspira a poder permitir a todo el mundo que quiera la posibilidad de simular y tomar sus propias decisiones, intentando as´ı concienciar de la importancia que tienen ´estas. Actualmente, el modelo est´a desarrollado en el lenguaje Vensim, utilizando unas funcionalidades espec´ıficas de la licencia de pago del programa. Se determin´o poder convertir el modelo a un lenguaje gratuito, como es el caso del lenguaje Python. La traducci´on del modelo a Python permitir´a que sea utilizado en otros proyectos y su c´odigo pueda ser publicado. Asimismo, cualquier persona que lo desee podr´a ejecutar el citado modelo y obtener los resultados en base a las decisiones tomadas. Por tanto, la motivaci´on que dirige este Trabajo de Fin de Grado es realizar una traducci´on autom´atica del modelo WILIAM a un lenguaje abierto. 1
1.2. OBJETIVOS 1.2. Objetivos El objetivo fundamental de este TFG es lograr la traducci´on del modelo WILIAM en el lenguaje Vensim al lenguaje Python. Para poder alcanzarlo, se divide en los siguientes subobjetivos: Comprensi´on del lenguaje Vensim. La alumna no hab´ıa trabajado anteriormente con este software ni con ning´un simulador de sistemas, por lo que es necesario estudiar el funcionamiento de Vensim y de algunas de sus funcionalidades para poder reproducir su comportamiento en Python. Comprensi´on del proyecto PySD. Estudiar el funcionamiento interno con el que cuenta el proyecto ya comenzado de PySD para poder realizar mejoras en ´el. Adem´as, el proceso de estudio sobre este proyecto ser´a plasmado como documentaci´on del mismo para disminuir la curva de aprendizaje a futuros desarrolladores. Contribuci´on al repositorio de PySD. Los cambios realizados sobre el proyecto de PySD, deber´an a˜nadirse al repositorio central para que los colaboradores y todo el que lo desee pueda acceder a ´el. 1.3. Proyectos open source Un proyecto open source, tambi´en conocido como c´odigo abierto, es aquel que presenta licencias abiertas que permiten a desarrolladores y usuarios acceder al c´odigo fuente del proyecto y a los documentos de dise˜no [58]. As´ı, la gente que lo desee, puede involucrarse en un proyecto open source. Normalmente, los principales motivos por los que alguien quiere formar parte de un desarrollo open source son diferentes pero, al final, contribuye una gran cantidad de gente que da como resultado un amplio rango de talento volcado en el proyecto. Esta modalidad de desarrollo software se enfoca m´as en los beneficios pr´acticos que puede llegar a tener el c´odigo fuente que en cuestiones ´eticas y de libertad que se tratan en el movimiento de software libre [51]. Existen tres t´erminos b´asicos relacionados con open source: contribuidores o contributors, fork ypull request. Normalmente, en un proyecto de este estilo, se parte de un proyecto ra´ız al que se le suman diferentes contribuidores que a˜naden funcionalidad nueva y/o mejoras al c´odigo o a la documentaci´on del proyecto ra´ız. Para ser un contribuidor m´as, es necesario realizar un fork de la rama del proyecto en la que se quiera a˜nadir o mejorar funcionalidad. Este fork es una copia del repositorio y en ´el se podr´an efectuar los cambios que se crean convenientes sin modificar el proyecto original. Adem´as, a trav´es de las issues de GitHub, se suelen debatir las deficiencias del proyecto y se especifica qu´e falta por mejorar. Cada contribuidor puede a˜nadir las issues que crea conveniente o los problemas que encuentre y, a su vez, puede intentar solventar alguna issue ya presentada. 2
CAP´ ITULO 1. INTRODUCCI ´ ON Posteriormente, cuando un contribuidor haya terminado de realizar los cambios que crea necesarios, deber´a hacer una pull request al due˜no del repositorio desde el cual se ha hecho previamente el fork. La aceptaci´on o denegaci´on de dicha solicitud est´a guiada por una serie de requisitos impuestos, as´ı como puede exigirse un cierto porcentaje de cobertura de tests sobre la funcionalidad a˜nadida para corroborar la mejora que supone al proyecto. Cuando se realiza una pull request se abre un debate en el que los dem´as contribuidores pueden pedir que se modifiquen ciertas partes del c´odigo que se ha a˜nadido o pueden realizar preguntas sobre fragmentos de c´odigo que no entiendan o que falte documentaci´on al respecto. Una vez resueltas las posibles dudas, el due˜no de la rama donde se ha hecho el fork, si acepta la pull request, se a˜nadir´an los cambios realizados a la rama principal. 1.4. Ingenier´ıa Inversa El origen de la ingenier´ıa inversa se encuentra en la ingenier´ıa mec´anica. La ingenier´ıa se ocupa de dise˜nar elementos de un producto para poder obtener un aparato funcional, la ingenier´ıa inversa invierte este proceso [26]. Este tipo de desarrollo permite obtener informaci´on acerca de cu´ales son los componentes de un determinado sistema y de qu´e manera interact´uan entre s´ı. La ingenier´ıa inversa [50] es un m´etodo de resoluci´on, que supone una gran profundizaci´on en el estudio de un proyecto, hasta el punto de que se pueda llegar a entender, modificar y mejorar el modo de funcionamiento de dicho proyecto. Para realizar el mantenimiento del proyecto PySD, teniendo en cuenta que la alumna no ten´ıa ning´un conocimiento previo sobre ´el, ha sido necesario realizar una comprensi´on exhaustiva del software, conocer c´omo funciona, cu´ales son los objetivos y c´omo se estructura internamente. Para esto se ha utilizado el m´etodo de ingenier´ıa inversa. 1.4.1. Ingenier´ıa Inversa de software El Instituto de Ingenieros El´ectricos y Electr´onicos (IEEE), en 1990, defini´o la ingenier´ıa inversa como el proceso de analizar un sistema para identificar sus componentes y sus interrelaciones y crear representaciones del sistema en otra forma o en un nivel superior [1]. Es un proceso de examen ´unicamente, ya que el sistema de software en consideraci´on no se modifica, o bien se redise˜na o se reestructura. La ingenier´ıa inversa se puede realizar desde cualquier etapa del ciclo de vida del producto, no necesariamente cuando ´este haya finalizado. La aplicaci´on a un proyecto de ingenier´ıa inversa nunca debe cambiar la funcionalidad del mismo. Al poner en pr´actica esta metodolog´ıa se pueden encontrar algunas ventajas: se puede reducir la complejidad del sistema, generar diferentes alternativas como representaciones gr´aficas, recuperar y/o actualizar la informaci´on perdida, detectar efectos laterales y facilitar la reutilizaci´on de sistemas existentes. 3
1.5. PROYECTOS DE MANTENIMIENTO 1.5. Proyectos de mantenimiento En muchas ocasiones el software necesita ser modificado, ya sea por detecci´on de errores, nuevas exigencias o necesidades del usuario del sistema. A esta fase se le conoce fase de mantenimiento [67]. Entre las caracter´ısticas sobresalientes de mantenimiento de software destacan: El software no envejece realmente pero se puede degradar o quedar obsoleto. El mantenimiento de software supone adaptar el paquete o sistema objeto del mismo a nuevas situaciones como cambio del hardware o del sistema operativo. Todo sistema software conlleva mejoras o a˜nadidos indefinidamente. Existen 4 tipos de mantenimiento: correctivo, adaptativo, perfectivo y preventivo, explicados a continuaci´on. Este Trabajo de Fin de Grado se enmarca como un proyecto de mantenimiento perfectivo y preventivo de PySD. 1.5.1. Mantenimiento correctivo Localiza y elimina los posibles defectos del software que pueden provocar fallos en el mismo. Estos fallos pueden originar un comportamiento diferente al esperado. Estos fallos pueden ser de procesamiento (salidas incorrectas de un programa), rendimiento (tiempo de respuesta demasiado alto), programaci´on (inconsistencias en el dise˜no) o documentaci´on (inconsistencias entre la funcionalidad de un programa y el manual de usuario). 1.5.2. Mantenimiento adaptativo Tiene lugar cuando se realizan cambios en el entorno en el que se ejecuta, tanto hardware como software, para mantener la plena funcionalidad del sistema. Estos cambios var´ıan desde cambios en el sistema operativo, en la arquitectura f´ısica del sistema inform´atico hasta cambios en el entorno de desarrollo software. Se trata de un tipo de mantenimiento cada vez m´as frecuente debido a la tendencia actual de actualizaci´on de hardware y sistemas operativos cada poco tiempo. 1.5.3. Mantenimiento perfectivo Conjunto de actividades para mejorar o a˜nadir nuevas funcionalidades requeridas por el usuario. Puede ser de ampliaci´on, en el cual se incorporan nuevas funcionalidades al sistema, o de mejora de eficiencia de la ejecuci´on. 4
CAP´ ITULO 1. INTRODUCCI ´ ON 1.5.4. Mantenimiento preventivo Tiene como objetivo principal mejorar las propiedades del software (calidad y mantenibilidad) sin alterar sus especificaciones funcionales. Algunos ejemplos de mantenimiento preventivo pueden ser: incluir sentencias que comprueben la validez de los datos de entrada, reestructuraci´on de los programas para aumentar su legibilidad o incluir nuevos comentarios. Este tipo de mantenimiento utiliza las t´ecnicas de ingenier´ıa inversa y reingenier´ıa. 1.6. Estructura de la memoria En adelante, este documento se estructura de la siguiente forma: Cap´ıtulo 2. Requisitos y planificaci´on: Describe el marco de trabajo utilizado en este proyecto y su adaptaci´on al mismo. Cap´ıtulo 3. Marco te´orico: Describe todos los conocimientos te´oricos que forman la base y han sido necesarios para desarrollar y entender el proyecto. Cap´ıtulo 4. Ingenier´ıa Inversa: Describe el proceso de ingenier´ıa inversa que se ha llevado a cabo para comprender el funcionamiento de la versi´on de PySD desde la que se part´ıa. Cap´ıtulo 5. Tecnolog´ıas utilizadas: Describe todas las tecnolog´ıas necesarias para la gesti´on y desarrollo del proyecto. Cap´ıtulo 6. Seguimiento del proyecto: Describe la evoluci´on del proyecto dividida en sprints. Cap´ıtulo 7. Dise˜no de las modificaciones: Describe las modificaciones y mejoras realizadas sobre PySD. Cap´ıtulo 8. Implementaci´on y pruebas de las modificaciones: Describe los tests realizados, la organizaci´on de cada modificaci´on junto con enlaces a los cambios comentados y la cobertura final obtenida. Cap´ıtulo 9. Conclusiones: Describe los resultados, el aprendizaje que ha supuesto el proyecto y las l´ıneas de trabajo futuras. Anexo A Manuales: Incluye manuales de instalaci´on, despliegue y de uso. Anexo B Resumen de enlaces adicionales: Incluye enlaces de inter´es sobre el proyecto, como el repositorio de c´odigo de pysd en GitLab y GitHub, el repositorio de c´odigo de los tests en GitHub y las issues que se han abierto durante el desarrollo del Trabajo de Fin de Grado. 5
2.5. RIESGOS Sprint Fecha de comienzo Fecha de finalizaci´on Observaciones Sprint 0 14/09/2020 21/10/2020 Sprint 1 21/10/2020 4/11/2020 Sprint 2 4/11/2020 18/11/2020 Ex´amenes parciales Sprint 3 2/12/2020 16/12/2020 Navidad y convocatoria ordinaria Sprint 4 20/1/2021 3/2/2021 Sprint 5 3/2/2021 17/2/2021 Sprint 6 17/2/2021 3/3/2021 Sprint 7 3/3/2021 17/3/2021 Sprint 8 17/3/2021 31/3/2021 Sprint 9 31/3/2021 14/4/2021 Sprint 10 14/4/2021 28/4/2021 Sprint 11 28/4/2021 12/5/2021 Sprint de refuerzo Sprint 12 12/5/2021 26/5/2021 Sprint de refuerzo Tabla 2.2: Calendarizaci´on inicial del proyecto Para llevar a cabo una buena gesti´on de riesgos es necesario seguir una serie de pasos: 1. Identificar los posibles riesgos del proyecto 2. Analizar y priorizar los riesgos, teniendo en cuenta el impacto y la probabilidad de cada uno 3. Planificar c´omo se lidia con cada riesgo. 4. Monitorizar y controlar los riesgos, si han ocurrido o a aumentado su probabilidad. Desde la Tabla 2.3 a la Tabla 2.11, se han presentado los diferentes riesgos analizados, acompa˜nados de una breve descripci´on del mismo, su probabilidad e impacto, un plan de mitigaci´on y un plan de contingencia. Riesgo 1 Enfermedad de desarrollador Descripci´on Un miembro del equipo de desarrollo enferma y es incapaz de realizar sus tareas asignadas Probabilidad Baja Impacto Alto Plan de mitigaci´on A˜nadir un sprint a mayores a la planificaci´on para poder realizar las tareas que no haya dado tiempo Plan de contingencia Aumentar las horas de trabajo diarias Tabla 2.3: Riesgo de enfermedad 12
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Riesgo 2 Cambios en los requisitos Descripci´on A lo largo del desarrollo del proyecto, se necesitan cambiar los requisitos establecidos en un primer momento ya que se han encontrado diferentes necesidades Probabilidad Alta Impacto Medio Plan de mitigaci´on Usar un marco de desarrollo ´agil para el desarrollo del proyecto, como Scrum, har´a m´as f´acil lidiar con los posibles cambios en los requisitos que pueda haber, reduciendo as´ı el alcance que este riesgo pueda tener Plan de contingencia Replanificar y llevar a cabo los cambios necesarios Tabla 2.4: Riesgo de cambios en los requisitos Riesgo 3 Falta de formaci´on Descripci´on Debido a la naturaleza del proyecto, el desarrollador puede no tener el conocimiento necesario sobre el mismo Probabilidad Media Impacto Medio Plan de mitigaci´on Sprint 0, sprint dedicado a realizar el trabajo de ingenier´ıa inversa sobre el proyecto para aumentar los conocimientos de los desarrolladores sobre el proyecto Plan de contingencia Consultar a profesionales o contribuidores Tabla 2.5: Riesgo de falta de formaci´on Riesgo 4 Falta de conocimiento del software Vensim para pruebas Descripci´on El desconocimiento del software Vensim puede derivar en problemas al intentar implementar pruebas para poder probar el c´odigo desarrollado Probabilidad Alta Impacto Bajo Plan de mitigaci´on En el Sprint 0 se dedica un cierto n´umero de horas a comprender mejor el lenguaje Vensim Plan de contingencia Preguntar a los expertos de Vensim, pidiendo las pruebas que sean necesarias Tabla 2.6: Riesgo de falta de conocimiento Vensim para pruebas 13
2.5. RIESGOS Riesgo 5 Fallo en la planificaci´on Descripci´on Puede haber retrasos si alguna tarea se estima de manera incorrecta, lo que puede afectar a la duraci´on del proyecto Probabilidad Media Impacto Alto Plan de mitigaci´on Al utilizar Scrum como marco de trabajo, se reduce el impacto si existiese la necesidad de replanificar. Adem´as, se ha incluido dos sprints de refuerzo al final de la planificaci´on para posibles retrasos que puedan existir Plan de contingencia Aumentar las horas de trabajo diarias o aumentar el plazo de entrega Tabla 2.7: Riesgo de fallar en la planificaci´on Riesgo 6 Falta de tiempo Descripci´on Debido a que una parte del proyecto se realiza durante el primer cuatrimestre y la alumna cuenta con 5 asignaturas a mayores, puede darse el caso de falta de tiempo por ex´amenes o entregas de pr´acticas Probabilidad Alta Impacto Medio Plan de mitigaci´on A˜nadir un sprint a mayores para poder recuperar el tiempo que no se ha podido invertir Plan de contingencia Replanificar y/o aumentar el plazo de entrega Tabla 2.8: Riesgo de falta de tiempo Riesgo 7 Problemas con el hardware Descripci´on Si hubiera cualquier problema con el hardware, se podr´ıa perder el progreso y los cambios realizados en el proyecto Probabilidad Baja Impacto Medio Plan de mitigaci´on Utilizar plataformas de control de versiones como Git y tener actualizado el repositorio frecuentemente Plan de contingencia Reemplazar el hardware estropeado Tabla 2.9: Riesgo asociado al hardware 14
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON Riesgo 8 Confinamiento por COVID Descripci´on Dada la situaci´on sanitaria actual, puede haber retrasos por confinamiento a causa de la COVID-19 Probabilidad Media Impacto Medio Plan de mitigaci´on Sprints a˜nadidos a mayores para lidiar con posibles retrasos Plan de contingencia Trabajar un mayor n´umero de horas cuando sea posible, replanificar Tabla 2.10: Riesgo de confinamiento Riesgo 9 Funcionalidad limitada a la versi´on profesional de Vensim Descripci´on Alguna funcionalidad que presenta Vensim est´a solo disponible en versiones de pago. La versi´on que utiliza la alumna es la gratuita para estudiantes. Alguna funcionalidad no se puede probar debido a la falta de la licencia profesional, como los subscripts. Probabilidad Alta Impacto Medio Plan de mitigaci´on Plan de contingencia La UVa cuenta con licencia para el software de Vensim, por lo que se podr´ıa acceder a esa funcionalidad exclusiva desde ciertos equipos de la Escuela Tabla 2.11: Riesgo de funcionalidad limitada Vensim 2.6. Presupuesto simulado Para calcular el presupuesto asociado a un proyecto debemos fijarnos en los costes de plantilla, gastos generales y los cargos por uso de un suministro [31]. Los costes de plantilla incluyen los sueldos de los desarrolladores y otros costes directos, como la contribuci´on por trabajador a la Seguridad Social. Para calcular este coste, se ha consultado el Bolet´ın Oficial del Estado [11] y en las tablas salariales se ha observado que el sueldo de un Programador Junior (categor´ıa E I) a partir del 31/12/2019 es de 15.680,56 e brutos al a˜no y su jornada laboral es de 1.800 horas/a˜no. Contando con un 30 % [42] del salario a mayores para cubrir los gastos sociales, el coste total para la empresa ser´ıa 20.384,73 epor trabajador. Sabiendo esto, se puede calcular el coste por horas, que ser´ıan aproximadamente 11,32 e. Teniendo en cuenta los valores obtenidos anteriormente y que el proyecto est´a estimado 15
2.6. PRESUPUESTO SIMULADO que se desarrolle en un total de 300 horas, el coste de plantilla relativo al proyecto ser´ıa 3.397,45 e. Los gastos generales incluyen aquellos costes como el alquiler de las oficinas, la luz y el agua. Normalmente, estos gastos se calculan aplicando un cargo fijo a los departamentos de desarrollo o mediante un cargo porcentual adicional sobre los costos directos de plantilla. Para este proyecto, los costes generales pueden corresponder al consumo que tiene un port´atil y la tarifa de la luz actual. Un ordenador port´atil consume como promedio un total de 220Wh [23]. Si la duraci´on del proyecto es de 300 horas, el port´atil consumir´a en ese periodo 66 kWh. Si el precio medio al d´ıa de la luz es 0.11059 e/kWh [63], el precio de consumo de la luz en base a lo que consume un ordenador alcanzar´a 7,30 e, siendo estos los gastos generales del proyecto. Durante el desarrollo del proyecto se usar´a un MacBook Pro de 2019, valorado en 2.699 e. Para calcular el coste que aporta este dispositivo es necesario calcular su depreciaci´on a lo largo del tiempo y tener en cuenta la duraci´on del proyecto. Debemos contar con el valor inicial o el precio de su adquisici´on, su vida ´util y su valor residual o el valor estimado cuando su vida ´util haya terminado [45]. Contando con estos tres valores se obtiene la cuota de depreciaci´on anual con la F´ormula 2.1. Cuota de depreciaci´on anual =valor inicial −valor residual vida ´util en a˜nos (2.1) Teniendo en cuenta que la vida ´util estimada para el ordenador en cuesti´on ser´ıa de 5 a˜nos aproximadamente y su valor residual 100 e, podemos sustituir estos datos en la F´ormula anterior (2.1) y obtendr´ıamos el valor representado en la F´ormula 2.2. Cuota de depreciaci´on anual =2.699 −100 5= 519,8 (2.2) Se obtiene una depreciaci´on de 519,8 eal a˜no. Teniendo en cuenta que la duraci´on del proyecto son 6 meses, la depreciaci´on del ordenador en este periodo es de 259,9 e. Tambi´en se debe contar con los costes asociados a los servicios utilizados, como licencias de software. Para desarrollar el proyecto se necesitan las licencias de Vensim,Astah yVisual Paradigm. Otras tecnolog´ıas utilizadas, como GitLab,GitHub,Visual Studio Code yOverleaf, no necesitan ninguna licencia para su uso, por lo que su coste asociado es 0 e. Comenzando con la licencia de Vensim, se ha utilizado la versi´on PLE o gratuita, pero con funcionalidad limitada. En un equipo de la Escuela de Ingenier´ıa Inform´atica se cuenta con una licencia para Vensim DSS, ya que esta versi´on aporta funcionalidad con la que se ha trabajado, como subscripts, y ha sido necesaria para ejecutar determinados modelos a lo largo del proyecto. El costo de esta licencia es 1995$/persona al a˜no [37], equivalente a 1636,73 e[76]. Como la duraci´on de este trabajo es de 6 meses, la licencia de Vensim DSS tiene un coste de 818,37 epara este proyecto. Se utiliza tambi´en la versi´on Professional de Astah. Se necesita una licencia para esta versi´on que conlleva un costo de 40$ al a˜no [2]. Convirtiendo esta cantidad a euros, obtenemos 16
CAP´ ITULO 2. REQUISITOS Y PLANIFICACI ´ ON una licencia de 33,35 eal a˜no [75]. Si la duraci´on del proyecto son 6 meses, la licencia de Astah Professional para este proyecto son 16,67 e. Para el uso de Visual Paradigm se utiliza la versi´on standard que tiene un coste de 19$ al mes [53], es decir, 15,85 eal mes [74]. Teniendo en cuenta la duraci´on del proyecto (6 meses) la licencia standard de Visual Paradigm finalmente tendr´ıa un costo de 95 e. Entre las licencias de Visual Paradigm,Astah yVensim, se obtendr´ıa un coste total de 930,04 erelativo a las licencias software requeridas para el desarrollo del proyecto. Finalmente, en la Tabla 2.12 se recogen todos los costes anteriormente calculados, adem´as del coste total del proyecto. Obteniendo un coste simulado de 4.594,69 epara este proyecto. Costes de Plantilla 3.397,45 e Gastos Generales 7,30 e Material 259,9 e Licencias software 930,04 e Total 4.594,69 e Tabla 2.12: Costes simulados 2.7. Presupuesto real Este proyecto est´a remunerado con una beca, la cual tiene una duraci´on de 6 meses con un sueldo de 300 eal mes. Realmente, los costes de plantilla del proyecto est´an compuestos por dicha remuneraci´on, siendo un total de 1.800 e. Los gatos generales calculados son an´alogos a los calculados en la Secci´on 2.6, es decir, 7,30 e, correspondiendo a la electricidad que consume un port´atil durante el periodo de desarrollo de este proyecto. Los gatos relativos al material con el que se realiza el desarrollo del proyecto siguen teniendo el mismo valor que el calculado en la Secci´on 2.6, es decir, 259,9 epor la cuota de depreciaci´on del ordenador durante la duraci´on del proyecto. Las licencias de Astah,Visual Paradigm yVensim las proporciona la Universidad de Valladolid, por lo que su coste no se tiene en cuenta en el presupuesto real. Finalmente, el presupuesto real del proyecto es el que se presenta en la Tabla 2.13, alcanzando el valor de 2.067,2 e. 17
2.7. PRESUPUESTO REAL Costes de Plantilla 1.800 e Gastos Generales 7,30 e Material 259,9 e Licencias software 0 e Total 2.067,2 e Tabla 2.13: Costes reales 18
CAP´ ITULO 3. MARCO TE ´ ORICO Cap´ıtulo 3 Marco te´orico 3.1. Din´amica de Sistemas La din´amica de sistemas [68] es una t´ecnica para analizar ymodelar el comportamiento temporal de los sistemas. Est´a basada en herramientas extra´ıdas de la ingenier´ıa de control como la simulaci´on por ordenador. Se puede aplicar a sistemas de diferentes ´areas como pueden ser sistemas econ´omicos, sociales, tecnol´ogicos, industriales, etc. De esta manera se puede estructurar, a trav´es de modelos matem´aticos, la din´amica del comportamiento de estos sistemas [44]. Este tipo de modelos de simulaciones, ayuda a la comprensi´on de los sistemas complejos y a la toma de decisiones sobre los mismos. Permite analizar y comparar los supuestos y modelos mentales acerca de c´omo funcionan las cosas, obtener una visi´on cualitativa sobre el funcionamiento de un sistema, conocer las consecuencias de una decisi´on o reconocer arquetipos de sistemas disfuncionales en la pr´actica diaria. Los modelos permiten simular el impacto de diferentes pol´ıticas relativas a la situaci´on a estudiar ejecutando simulaciones que permitir´an ver las consecuencias a corto y medio plazo, adem´as de ayudar a comprender c´omo los cambios en un sistema se ven afectados por el tiempo. Se utiliza en especial para investigar la dependencia de los recursos naturales y los problemas resultantes del creciente consumo a nivel global. Existe una gran variedad de marcas de software en el mercado que ayudan a aplicar esta herramienta como son: Vensim, Stella, ithink, Powersim, y Dynamo, entre otras. 3.2. Vensim Vensim [69] es una herramienta visual de modelizaci´on que permite conceptualizar, documentar, simular, analizar y optimizar modelos de din´amica de sistemas [15]. 19
3.2. VENSIM Vensim es el software elegido por miles de analistas, consultores e investigadores de todo el mundo debido a que integra en un solo entorno un poderoso conjunto de herramientas que permiten desarrollar, probar, interpretar y distribuir modelos [39]. Provee una forma simple y flexible de construir modelos de simulaci´on mediante diagramas de influencias y diagramas de Forrester. Cuando se realiza un modelo en Vensim, se genera un archivo con extensi´on .mdl. Este tipo de archivo se puede abrir con el entorno gr´afico de Vensim o con un editor de texto. Le´ıdo como texto plano se encuentran tres partes bien diferenciadas. Comienza con la definici´on de todas las funciones y constantes creadas por el usuario, seguido de la inicializaci´on de los par´ametros de control de la simulaci´on y finalmente, cuenta con una serie de caracteres alfanum´ericos ´utiles para la representaci´on del modelo en el entorno gr´afico. Una sentencia en Vensim habitualmente tiene la estructura representada en el Fragmento de C´odigo 3.1 1Nombre = 2Ecuacion 3~ Unidades y limites 4~ Comentario 5| Fragmento de c´odigo 3.1: Ejemplo de sentencia Vensim Se distinguen 5 elementos: nombre de la variable, ecuaci´on que describe el comportamiento de la variable, unidades y l´ımites y un comentario describiendo la variable. Las unidades, l´ımites y comentario son opcionales. Dichos elementos se encuentran separados por un igual y dos virgulillas, finalizando la sentencia con una barra lateral. Un ejemplo de una variable real ser´ıa el representado en el Fragmento de C´odigo 3.2, donde se presenta una constante con nombre Characteristic Time cuyo valor es 10. Se mide en minutos con l´ımites [0, inf) y est´a acompa˜nada de un comentario. 1Characteristic Time = 210 3~ Minutes [0.0 , inf ] 4~ How long will it take the teacup to cool 1/e of the way to equilibrium? 5| Fragmento de c´odigo 3.2: Ejemplo real de sentencia Vensim 3.2.1. Estructuras espec´ıficas de Vensim En Vensim se pueden presentar en un modelo gran variedad de s´ımbolos [35]. Los m´as ´utiles para este proyecto y que aparecer´an a lo largo de la memoria son los explicados a continuaci´on. 20
CAP´ ITULO 3. MARCO TE ´ ORICO Subscripts Los subscripts [34] son unas estructuras de datos espec´ıficas de Vensim que permiten representar en una sola variable m´as de un valor, equivalente a una matriz. Un posible ejemplo de subscript se presenta en el siguiente Fragmento de C´odigo 3.3, donde se define un subscript de pa´ıses. 1paises : MEXICO , USA , CANADA ~~| Fragmento de c´odigo 3.3: Ejemplo de Subscript Los subscripts se dividen en dos partes, el nombre y los valores de un subscript. La primera parte se llama subscript name y es el nombre con el que se identifica al subscript. En el ejemplo anterior el subscript name es “paises”. Adem´as, contienen otra segunda parte la cual se encarga de dotar de valor al subscript name y se denomina subscript values o los valores del subscript, que en este ejemplo ser´ıan “MEXICO, USA y CANADA”, 3 subscript values. Para poder utilizar los subscripts, es necesario que se incluyan entre corchetes ([ ]), tanto el subscript name como los subscript values, despu´es del nombre de una variable. Una variable puede contener un m´aximo de 8 subscripts separados por comas ( , ). En el Fragmento de C´odigo 3.4 se puede apreciar el uso del anterior subscript definido. 1nacimientos [ paises ] = 2poblacion [ paises ] * factor de natalidad [ paises ] 3~ personas / a~no 4~ Total de nacimientos en un pa ´ıs espec ´ıfico. 5| Fragmento de c´odigo 3.4: Ejemplo de uso de Subscript 3.2.2. Compatibilidad de Subscripts Los subscripts, definidos anteriormente, cuentan con una serie de operaciones asociadas para su manejo. Las m´as relevantes para este proyecto se explican a continuaci´on. Subscripts numeric range (Rango num´erico de Subscripts) Normalmente, los subscripts se definen como se muestra en el Fragmente de c´odigo 3.3. Sin embargo, en algunos modelos es necesario trabajar con un gran n´umero de subscript values y el lenguaje Vensim presenta un atajo para poder definir un subscript a partir de rangos num´ericos, sin tener que escribir todos los elementos que conforman el subscript. Un numeric range o rango num´erico [70] es una representaci´on simplificada para definir varios subscript values similares entre s´ı asociados a un subscript. En un rango num´erico solo se especifican los l´ımites (inferior y superior) de los subscript values, 21
3.4. PARSIMONIOUS Cliente: interact´ua con la estructura (element) y con el Visitor. Es el encargado de crear los visitors y los env´ıa al elemento para su procesamiento. Element: es la ra´ız de la estructura, sobre la que se utiliza el Visitor. Este objeto, por lo general, es una interfaz que define el m´etodo accept y que deben implementar todos los objetos de la estructura. ConcreteElement: representa un hijo de la estructura. La estructura completa puede estar compuesta por varios ConcreteElement y cada uno debe implementar el m´etodo accept. IVisitor: interfaz que define la estructura del visitor. ´ Esta deber´a tener un m´etodo por cada element que se quiera analizar. ConcreteVisitor: representa la implementaci´on del Visitor. Realiza una operaci´on sobre un element concreto. Para poder entender mejor las relaciones y la interacci´on entre las clases se ha proporcionado en la Figura 3.3 un diagrama de secuencia sobre c´omo se relacionan las clases en el patr´on Visitor. Figura 3.3: Diagrama de secuencia del patr´on Visitor. [5] Primero, el cliente crea la estructura (element) y la instancia del visitor asociado. Cuando el cliente ejecuta el m´etodo accept de un elemento le pasa como argumento el visitor.Element env´ıa un m´etodo al visitor pas´andose a s´ı mismo como par´ametro para poder distinguir la operaci´on asociada a ese element concreto. Cada visitor deber´a tener un m´etodo para cada tipo de element. 28
CAP´ ITULO 3. MARCO TE ´ ORICO 3.4.3. Patr´on visitor en Parsimonious El patr´on Visitor, como se ha visto anteriormente, permite aportar nueva funcionalidad sin modificar el c´odigo. En Parsimonious esto se utiliza para aportar funcionalidad a las diferentes reglas de la gram´atica. Para ello, se crea una clase que herede de NodeVisitor y se crea en ella todos los m´etodos correspondientes a la gram´atica que Parsimonious visitar´a. En Parsimonious, se agrega un visitor por cada regla de la gram´atica, es decir, se distingue entre diferentes instancias de un mismo objeto no entre diferentes objetos. Se presenta la siguiente gram´atica en Parsimonious, Fragmento de c´odigo 3.13, que define un dato como nombre o DNI y, a su vez, define nombre y DNI [60]. 1dato = nombre / dni 2nombre = ~"[a-zA -Z ]" 3dni = ~"[0 -9]+" ~"[ A-Z ]" IU Fragmento de c´odigo 3.13: Gram´atica Simple Parsimonious Se le asocia una l´ogica a cada regla heredando de la clase NodeVisitor y definiendo una funci´on con nombre: visit nombre-de-la-regla, como se muestra en el Fragmento de c´odigo 3.14. 1class logicaEjemplo ( NodeVisitor ): 2def visit_nombre (self , nodo , hijos ): 3# Aqu ´ı l´ogica asociada a nombre 4 5def visit_dni (self , nodo , hijos ): 6# Aqu ´ı l´ogica asociada a DNI 7 8def generic_visit (self , nodo , hijos ): 9# L´ogica de cualquier otro elemento Fragmento de c´odigo 3.14: L´ogica Parsimonious Finalmente, cuando se parsee un texto con Parsimonious y se satisfaga la regla “nombre”, visitar´a la funci´on visit nombre y si confronta con dni, se ejecutar´a la funci´on visit dni. La funci´on generic visit es ´util cuando se quiera tratar reglas de manera especial. Cabe destacar, como se ha presentado en el Fragmento de C´odigo 3.14, cada m´etodo visitor tiene tres par´ametros. Estos son: Self: primer argumento de los m´etodos de instancia en Python. Corresponde a una regla de nomenclatura del lenguaje Python [20]. Este par´ametro hace referencia a la instancia actual de la clase y se utiliza para acceder a las variables que pertenecen a la clase. 29
3.5. PATR ´ ON DECORATOR Nodo: estructura de tipo Node (clase que se encuentra en el m´odulo parsimonious.nodes). Representa el nodo que se est´a visitando en el ´arbol de an´alisis. Hijos: lista que contiene los resultados de visitar a los nodos hijos del nodo actual. 3.5. Patr´on Decorator El patr´on Decorator [22], es un patr´on de dise˜no estructural que permite a˜nadir funcionalidad a un objeto din´amicamente. Tambi´en conocido como Wrapper, proporciona una alternativa flexible a las subclases permitiendo extender la funcionalidad. Cuando se tiene que a˜nadir o modificar el comportamiento de un objeto tendr´ıa cabida utilizar la herencia entre clases. Sin embargo, hay que tener en cuenta que la herencia es est´atica y esto no permite alterar la funcionalidad de un objeto durante el tiempo de ejecuci´on. Se puede ´unicamente sustituir el objeto completo por otro creado [56]. Adem´as, una gran limitaci´on se ocasiona cuando las subclases solo pueden tener una ´unica clase padre, que ocurre en la mayor´ıa de lenguajes. Al contrario que la herencia, el patr´on decorator permite a˜nadir un comportamiento a un objeto individual, sin afectar a los dem´as objetos de la misma clase, es decir, din´amicamente. Un wrapper es un objeto que se vincula a otro objeto. El wrapper cuenta con los mismos m´etodos que el objeto al que se vincula y le delega todas las solicitudes. Sin embargo, no tienen exactamente el mismo comportamiento ya que el wrapper altera el resultado antes o despu´es de pasar la solicitud al objeto. En la Figura 3.4 se presenta un ejemplo de un diagrama de clases y de secuencia utilizando el patr´on Decorator. Utilizando este patr´on se pueden agregar responsabilidades a un objeto de forma din´amica y ampliar la funcionalidad en tiempo de ejecuci´on [73]. Se crean objetos decorators separados que permiten agregar responsabilidades a un objeto ya existente. Figura 3.4: Diagrama de clases y de secuencia: Patr´on Decorator [73] A trav´es de estos objetos decorator se puede ampliar la funcionalidad de un objeto en tiempo de ejecuci´on. En la Figura 3.4 se define una clase Decorator que implementa la interfaz 30
CAP´ ITULO 3. MARCO TE ´ ORICO Component de forma trasparente y as´ı, el cliente solo conoce e interacciona con dicha interfaz. La clase Decorator mantiene una referencia a un objeto Component y le reenv´ıa las solicitudes a este componente. Posteriormente, las subclases de Decorator (Decorator1 yDecorator2) a˜nadir´an funcionalidad adicional que se realizar´an antes y/o despu´es de reenviar la solicitud al componente. As´ı es como este patr´on crea una clase decoradora, que envuelve la clase original y proporciona la funcionalidad adicional esperada manteniendo intactos los m´etodos de la clase. Adem´as, se pueden anidar varios decorators de forma recursiva y no hay restricciones sobre las posibles combinaciones a la hora de agregar responsabilidades con decorators. En la Figura 3.4, en el diagrama de secuencia cabe destacar el anidamiento del Decorator2 yDecorator1 para alterar la funcionalidad del objeto Component. El uso de este patr´on puede ser m´as eficiente que la creaci´on de subclases, ya que de esta manera el comportamiento de un objeto puede aumentarse sin tener que definir un objeto completamente nuevo. En Python, el uso del patr´on decorator es bastante com´un. La funcionalidad que se quiere agregar o el comportamiento que se quiere modificar se escribe en una funci´on. Posteriormente, donde se quiera a˜nadir el comportamiento adicional se escribe el nombre de la funci´on decoradora con el car´acter @ delante y encima de la funci´on a la que se le quiere a˜nadir funcionalidad. En PySD se utiliza este patr´on para implementar una cach´e de dos niveles, m´as adelante se explica en detalle. 31
3.5. PATR ´ ON DECORATOR Regla Descripci´on “literal” Se utiliza para que el texto que aparezca entrecomillado se considere literalmente. [espacio] Para definir espacios o tabuladores en las reglas. a/b/c Alternativas. El primero en tener ´exito de a, b o c gana thing? Expresi´on opcional, es decir, “thing” se consume si es que existe. &thing Afirmaci´on anticipada. Asegura que “thing” coincida con la posici´on actual pero no se consume. !thing Negativa. Coincide si “thing” no se encuentra en la posici´on actual, no consume ning´un token. thing* Cero o m´as tokens. Asegura que “thing” aparezca cero o m´as veces en la posici´on actual y consume tantos tokens como haya. thing+ Uno o m´as tokens. Asegura que “thing” aparezca una o m´as veces en la posici´on actual y consume tantos tokens como haya. (thing) Los par´entesis se utilizan simplemente para agrupar. ∼r“regex” ilmsux Las expresiones regulares se definen con el s´ımbolo ∼delante y se citan como literales. Se puede utilizar “r” para tratar el texto de la expresi´on regular como crudo sin tener que escapar caracteres, aplicable tambi´en a la primera regla. Despu´es de la expresi´on regular se pueden utilizar los caracteres i, l, m, s, u y x que facilitan el trabajo. “i”:ignore case, no distingue entre may´usculas y min´usculas. “l”:locale, hace que los caracteres {\w, \W, \b, \B}dependan de la configuraci´on local. “m”:multiline, los caracteres ˆ y $ corresponden al principio y al final de cada l´ınea en vez de al string. “s”: el car´acter “.” sustituye al car´acter de nueva l´ınea. “u”:unicode, hace que los caracteres {\w, \W, \b, \B}dependan de la codificaci´on de caracteres. “x”:verbose, permite insertar comentarios dentro de la expresi´on regular seguidos del car´acter #. Tabla 3.1: Reglas de sintaxis 32
CAP´ ITULO 4. INGENIER´ IA INVERSA Cap´ıtulo 4 Ingenier´ıa Inversa En este cap´ıtulo se expondr´an los conocimientos sobre PySD tras realizar el proceso de ingenier´ıa inversa sobre ´el. Para conocer m´as detalles sobre el mismo es necesario que se comprendan las 5 gram´aticas que posee PySD y la funci´on de cada una en el proyecto, adem´as de la estructura del proyecto, mediante un modelo 4+1 vistas que ha sido el m´as conveniente para poder comprender toda la funcionalidad que encierra PySD. 4.1. Gram´aticas de PySD PySD tiene dos fases principales, la traducci´on del fichero Vensim a un fichero Python equivalente, y posteriormente, la ejecuci´on del fichero Python creado. La traducci´on de PySD es compleja, debido a que no cuenta con un parser “tradicional”. En PySD, no se ha creado una ´unica gram´atica donde se encuentren todas las reglas correspondientes a Vensim con sus clases visitors, si no que PySD cuenta con un total de 5 gram´aticas para poder traducir un archivo Vensim. Estas son: file structure grammar,model structure grammar, component structure grammar,expression grammar ylookup grammar, cuyo funcionamiento y raz´on se explican a continuaci´on. 4.1.1. file structure grammar Es la primera gram´atica que analiza el c´odigo Vensim. Se encarga de separar las Macros de Vensim y el c´odigo principal. Una Macro [38] permite representar una estructura de modelo sin tener que volver a escribir ecuaciones. Primero, la macro se define escribiendo ecuaciones y se invoca de la misma forma que cuando se llama a una funci´on. Se debe encontrar definida antes de usarla. Esta gram´atica como entrada tiene el archivo .mdl convertido a una cadena de texto. Devuelve una lista de diccionarios, en la que cada diccionario representa una secci´on, una 33
4.1. GRAM ´ ATICAS DE PYSD macro o el main (c´odigo principal) del archivo pasado como par´ametro. A su vez, cada diccionario se compone de varios elementos. Estos son: returns: lista de strings. Representa lo que contiene una macro o est´a vac´ıa cuando se trata del main. params: lista de string. Representa los par´ametros que recibe una macro o est´a vac´ıa si se trata del main. name: es un string. Contiene el nombre de la macro o “main” cuando se trata del main del modelo. string: string. Contiene el c´odigo Vensim. Si se trata del c´odigo principal del modelo, el diccionario generado se compondr´a por: en el elemento name, el nombre main y las listas de returns yparams se encontrar´an vac´ıas. El c´odigo Vensim se encontrar´a en strings. Se toma como ejemplo el c´odigo Vensim del Fragmento de c´odigo 4.1 que consta de 3 sentencias Vensim [60]. En la l´ınea 1, se define un subscript, “pa´ıses”, con 3 subscripts values cuya unidad es pa´ıs y el comentario asociado, listado de pa´ıses. Posteriormente, se define la variable “prueba” utilizado el subscript “pa´ıses” cuyo valor es el valor de la funci´on, en este caso el m´aximo de 3 valores. La ´ultima sentencia, comienza en la l´ınea n´umero 7, solo aporta un comentario ´util para el desarrollador. 1pa´ıses : italia , francia , alemania 2~ pa´ıs 3~ listado de pa´ıses | 4prueba [ pa´ı ses ] = MAX (1 , MAX (2 , 3)) 5~ unidades 6~ comentario | 7.Control ~ 8Simulation Control Parameters | Fragmento de c´odigo 4.1: Ejemplo c´odigo Vensim Si se parsea el c´odigo Vensim previo (4.1) con la gram´atica file structure grammar, ´esta generar´ıa un diccionario como el representado en el Fragmento de c´odigo 4.2. El ejemplo de c´odigo Vensim no contiene ninguna Macro, por lo que, como se ha comentado anteriormente, las listas returns yparams est´an vac´ıas, adem´as de asignar a name el valor “main”. El c´odigo de la sentencia Vensim se almacena en el elemento string. 1[{ 2’returns ’ : [], 3’params ’ : [], 4’name ’ : ’main ’, 5’string ’ : ’pa´ıses: italia , francia , alemania 6~ pa´ıs 34
CAP´ ITULO 4. INGENIER´ IA INVERSA 7~ listado de pa´ıses | 8prueba [ pa´ı ses ] = MAX (1 , MAX (2 , 3)) 9~ unidades 10 ~ comentario | 11 .Control ~ 12 Simulation Control Parameters |’ 13 }] Fragmento de c´odigo 4.2: Salida de file-structure-grammar 4.1.2. model structure grammar Model structure grammar es la segunda gram´atica que parsea el c´odigo Vensim en PySD. Se encarga de parsear un string que representa el c´odigo principal del modelo y organiza su contenido. Separa ecuaciones de secciones y de comentarios, etiquet´andolos de manera diferente. La principal distinci´on entre ecuaciones y comentarios radica en que los comentarios no afectar´an posteriormente a la ejecuci´on, ya que su ´unica funci´on es aportar informaci´on para los programadores del modelo. Como salida, esta gram´atica proporciona una lista de diccionarios, en el que cada diccionario contiene los componentes de un elemento del modelo separados en ecuaci´on, unidades, documentaci´on, l´ımites y tipo. M´as en detalle, en cada diccionario se encuentran las siguientes keys: doc: documentaci´on, comentarios asociados a la sentencia. eqn: parte de la sentencia que contiene la ecuaci´on. units: las unidades con las que se opera. lims: valores entre los que se acotan las unidades de la ecuaci´on. kind: tipo de la secci´on: comentario o ecuaci´on. En la Secci´on 3.2 se explican las diferentes secciones con las que cuenta una sentencia de Vensim. Resumidamente, estas son: ecuaci´on, unidades y comentario. La gram´atica model structure grammar se encarga de separar la secci´on de unidades en unidades y l´ımites de ´estas, ya que se pueden agregar intervalos entre los cuales la variable tome valores. Si partimos del ejemplo del Fragmento de c´odigo de ejemplo (4.1) y parseamos la 2a sentencia presentada (l´ınea 4 a 6) obtendr´ıamos como salida el diccionario representado en el Fragmento de c´odigo 4.3. Este diccionario almacena en la key ‘doc’ el comentario de la sentencia, en la key ‘eqn’ la ecuaci´on, en ‘units’ las unidades con las que se opera en la ecuaci´on y en la key ‘limits’ el rango de valores entre los que puede tomar valor la variable. Finalmente, el diccionario cuenta con la key ‘kind’ a la que se le asigna el valor ‘entry’ debido a que se trata de una ecuaci´on. 35
4.1. GRAM ´ ATICAS DE PYSD 1[{ 2’doc ’ : ’comentario ’, 3’eqn ’ : ’ prueba [ pa ´ı ses ] = MAX (1, MAX (2 ,3) )’, 4’units ’ : ’unidades ’, 5’limits ’ : ’[1 ,3] ’, 6’kind ’ : ’entry ’ 7}] Fragmento de c´odigo 4.3: Salida de model-structure-grammar Ecuaci´on En el ejemplo previo se ha presentado una sentencia correspondiente a una ecuaci´on. Sin embargo, si se tratase de una sentencia que pertenezca a un comentario, la gram´atica model structure grammar generar´ıa un diccionario similar al presentado en el Fragmento de c´odigo 4.4, cuyos elementos ‘eqn’,‘units’ y‘limits’ se encuentran vac´ıos. En el campo ‘doc’ se almacena el texto del comentario en cuesti´on y se indica que es un comentario asignando el valor ‘section’ al elemento ‘kind’. 1[{ 2‘doc ’ : ‘aqu ´ı el texto del comentario ’, 3‘eqn ’ : ‘’, 4‘units ’ : ‘’, 5‘limits ’ : ‘’, 6‘kind ’ : ‘section ’ 7}] Fragmento de c´odigo 4.4: Salida de model-structure-grammar Comentario 4.1.3. component structure grammar La tercera gram´atica con la que cuenta PySD, component structure grammar, parsea ´unicamente las ecuaciones, es decir, aquellas sentencias que poseen en su diccionario el valor ‘entry’ en el campo ‘kind’ que se ha asignado previamente en la gram´atica model structure grammar. Adem´as, no parsea todas las entradas del diccionario creado en la gram´atica anterior, si no que solo parsea el elemento ‘eqn’. En resumen, la gram´atica component structure grammar divide la cadena que representa la parte de la ecuaci´on de un elemento del modelo. La funci´on en la que se define esta gram´atica toma como entrada dos par´ametros: equation str: la ecuaci´on. root path: ruta ra´ız del archivo Vensim, necesaria para resolver rutas de archivos de datos externos. El objetivo de esta gram´atica es dividir la parte izquierda de la ecuaci´on en real name y subs y la parte derecha en ‘expr’. Generando un diccionario con los siguientes elementos: 36
CAP´ ITULO 4. INGENIER´ IA INVERSA ‘real name: nombre. ‘subs’: subscripts si incluye. ‘expr’: parte derecha completa. ‘kind’: puede ser component,lookup,subdef odata, dependiendo del tipo de la ecuaci´on. Cabe destacar que se asocia un nuevo tipo al elemento ‘kind’, mientras que anteriormente se hab´ıa definido ‘kind’ con el valor ‘entry’ para ecuaciones. Esto se debe a que la funci´on para la que est´a el elemento ‘kind’ es conducir cada sentencia por diferentes caminos durante la ejecuci´on. El elemento ‘kind’ (en la gram´atica component structure grammar) depende del tipo de la ecuaci´on pudiendo obtener 4 valores: component: una expresi´on de modelo normal o una constante. lookup: una definici´on de lookup. subdef: una definici´on de subscript. data: una variable de datos. Para poder comprender mejor esta gram´atica, se toma el ejemplo de antes, presentado en el Fragmento de c´odigo 4.1. Si solo se analizan las ecuaciones, de este ejemplo solo se analizar´ıa las dos l´ıneas presentadas en el Fragmento de c´odigo 4.5. N´otese que los comentarios y unidades de la sentencia Vensim ya no se consideran. 1pa´ıses : italia , francia , alemania 2 3prueba [ pa´ı ses ] = MAX (1 ,MAX (2, 3) ) Fragmento de c´odigo 4.5: Entradas de component-structure-grammar Los diccionarios creados para cada una de estas ecuaciones ser´ıan los presentados en el Fragmento de c´odigo 4.7 para el subscript definido en la l´ınea 1 (4.5) y en el Fragmento de c´odigo 4.6 para la variable “prueba”, l´ınea 3 (4.5). La primera ecuaci´on se etiqueta como subdef (4.6) debido a que es la definici´on de un subscript y la segunda como component (4.7) debido a que se trata de la definici´on de una variable. 1{ 2’real_name ’: ’pa´ıses ’, 3’subs ’: [] , 4’expr ’: ’italia , francia , alemania ’, 5’kind ’: ’subdef ’ 6} Fragmento de c´odigo 4.6: Salida de component-structure-grammar Subscript 37
4.2. MODELO DE VISTAS 4+1 As´ı mismo, las funciones get model elements,get equation components, parse general expression yparse lookup expression, contienen las 4 gram´aticas restantes con las que cuenta PySD: model structure grammar,component structure grammar, expression grammar ylookup grammar, respectivamente. Adem´as, justo despu´es de cada funci´on se definen las clases descendientes de NodeVisitor de cada gram´atica para que se pueda realizar y recorrer el ´arbol de an´alisis. Se puede destacar la funci´on include common grammar, que contiene la gram´atica explicada en la Secci´on 4.1.6. Contiene las reglas gramaticales b´asicas comunes utilizadas por todas las dem´as gram´aticas. Debido a la complejidad del m´odulo vensim2py, ya que cuenta con las cinco funciones en las que se definen las gram´aticas de PySD y sus clases NodeVisitors asociadas, en la Figura 4.5 se han representado, sin entrar en detalle, las clases que contiene vensim2py. Estas clases son: FileParser, ModelParser, ComponentParser, ExpressionParser y LookupParser. Asociadas a las 5 gram´aticas de PySD: file structure grammar,model structure grammar, component structure grammar,expression grammar ylookup grammar, respectivamente. A su vez, estas clases heredan de la clase NodeVisitor, lo que les proporciona un marco de inversi´on de control para recorrer un ´arbol y devolver una nueva construcci´on basada en ´el. Figura 4.5: Gram´aticas de vensim2py simplificadas En las Figuras 4.6 y 4.7 se representan los diagramas con detalle de las clases asociadas a las gram´aticas. 44
CAP´ ITULO 4. INGENIER´ IA INVERSA Figura 4.6: Clases asociadas a las gram´aticas del m´odulo vensim2py Figura 4.7: Clases asociadas a las gram´aticas del m´odulo vensim2py Los m´etodos presentados en cada clase se corresponden con todos los m´etodos visitors asociados a las diferentes reglas gramaticales. No hay un m´etodo visitor por cada regla, si no que tienen m´etodos visitors asociados solamente aquellas reglas en las que es ´util almacenar cierta informaci´on del modelo que est´a siendo parseado. Dentro de los visitors se guarda esta informaci´on en los atributos de la clase, para posteriormente, cuando la gram´atica haya terminado de parsear los elementos del modelo, se pueda devolver el resultado a partir de esos atributos. Y a partir de esta informaci´on que se ha obtenido con ayuda de los visitors se crear´a el modelo en Python. Los m´etodos visitors asociados a las gram´aticas siempre tienen tres par´ametros, explicados en la Secci´on 3.4.3. Self, que representa a la instancia actual de la clase; n, de tipo Node, es el nodo que se est´a siendo visitado del ´arbol de an´alisis y vc (visit children), que se 45
4.2. MODELO DE VISTAS 4+1 trata de una lista con todos los resultados de recorrer los nodos hijos que forman la sentencia que ha concordado con la regla gramatical. A partir de los valores que componen el tercer par´ametro, vc, de los m´etodos visitors, se completa la informaci´on que se almacena en los atributos de la clase, como anteriormente se ha comentado. Posteriormente, con los atributos se rellenar´a el diccionario que se devuelve como resultado obtenido en cada gram´atica. Una vez terminado el m´odulo vensim2py, se explican a continuaci´on los dem´as m´odulos que conforman PySD. Functions El m´odulo functions est´a representado en la Figura 4.8. Es uno de los m´as importantes de PySD, ya que cuenta con las clases que se instanciar´an en el modelo Pyhton traducido y con la l´ogica necesaria para poder ejecutar la simulaci´on. En dicha figura se presentan las clases que se definen en ´el y las relaciones entre ´estas. Posteriormente, se detallan aquellas clases que son m´as relevantes para este proyecto. Figura 4.8: M´odulo functions y sus clases En la Figura 4.9, se presenta el detalle del m´odulo functions y la clase Time que se define en ´el. En este m´odulo encontramos muchas de las funciones que se utilizan en Vensim pero con la l´ogica correspondiente en Python, por ejemplo: PULSE,IF THEN ELSE, RANDOM UNIFORM, etc. La clase Time es la encargada de representar el tiempo durante la simulaci´on. Con el atributo trepresenta el tiempo actual que se va modificando a medida que avanza la simulaci´on y mediante el atributo step se representa el aumento de tiempo que se incrementa en cada iteraci´on. 46
CAP´ ITULO 4. INGENIER´ IA INVERSA Figura 4.9: M´odulo functions y clase Time En la Figura 4.10 se presenta el diagrama con detalle de las clases Stateful,Integ, Macro yModel definidas en el m´odulo functions. Como se ha representado en la Figura 4.8, la clase Stateful es una de las clases m´as importantes de este m´odulo, ya que, excepto Time, todas las dem´as clases heredan de ella. Esta clase permite representar la evoluci´on de estado de ciertos elementos del modelo, recreando el proceso de simulaci´on en Vensim. Para ello, cuenta con un atributo state, que simula el estado de los elementos. La clase Integ permite simular los stocks de Vensim. Recibe y almacena un valor inicial y la funci´on de la que se obtiene la derivada necesaria para poder realizar la integraci´on. La clase Model almacena toda la informaci´on que respecta al c´odigo principal del modelo (ya traducido). A una instancia de esta clase se le llama modelo de pysd, ya que es la representaci´on que se hace en el lenguaje Python del archivo Vensim. Es decir, la clase Model implementa una representaci´on de objetos con estado del sistema y contiene la mayor´ıa de m´etodos para poder acceder y modificar los componentes del modelo. Adem´as, esta clase es la encargada de instanciar el tiempo dependiendo de las variables del modelo para el mismo y tambi´en se encarga de llevar a cabo la simulaci´on utilizando la integraci´on por Euler. De esta clase se puede destacar la funci´on initialize la cual inicializa la simulaci´on del modelo, o la funci´on run que permite simular el comportamiento del modelo a medida que avanzan los instantes de tiempo o steps. La funci´on euler step permite realizar la integraci´on por Euler en un solo paso, utilizando para ello el estado que tienen los elementos Stateful y actualiz´andolo. 47
4.2. MODELO DE VISTAS 4+1 Figura 4.10: Clases Stateful,Integ,Macro yModel del m´odulo functions Model hereda de la clase Macro (Figura 4.8). ´ Esta implementa la l´ogica para representar las macros de Vensim, encarg´andose de obtener aquellos objetos Stateful que hayan sido creados en la fase de traducci´on e inicializarlos para, posteriormente, obtener sus derivadas y los resultados de la ejecuci´on. Model realiza las mismas funciones que Macro, pero Model es el objeto ra´ız del modelo por lo que tiene m´as m´etodos agregados que facilitan la ejecuci´on. Builder Continuando con el m´odulo builder, ´este se representa en detalle en la Figura 4.11. En este m´odulo no se define ninguna clase, pero es el encargado de realizar el texto del modelo en Python completando con los resultados obtenidos de la traducci´on. Tiene el c´odigo necesario para ensamblar en un modelo pysd todos los elementos que hayan sido traducidos tanto de Vensim o XMILE y formar, a partir de estos, una versi´on compatible con Python. La principal funci´on de este m´odulo es build, la encargada de construir y escribir la 48
CAP´ ITULO 4. INGENIER´ IA INVERSA representaci´on en Python del modelo. Se llama desde el m´odulo vensim2py, despu´es de haber terminado todo el proceso de traducci´on del modelo Vensim. Como par´ametros se le pasan los diferentes elementos del modelo que han sido parseados, subscripts, namespace y el nombre del archivo donde se debe escribir el resultado de la representaci´on en Python. Esta funci´on contiene ciertas l´ıneas de texto fijo que siempre se escriben en los modelos creados, como la versi´on de PySD, o imports pero luego hay ciertas l´ıneas que se completan con la traducci´on generada anteriormente en el m´odulo vensim2py las cuales se le pasan a la funci´on por par´ametro. En este m´odulo tambi´en se encuentra la funci´on build function call que se menciona en el Seguimiento del proyecto (Secci´on 6.6). A esta funci´on se le llama desde los visitors de la gram´atica expression grammar y permite crear la expresi´on completa en Python de una funci´on de Vensim, pas´andole el nombre de la funci´on y los argumentos. Figura 4.11: M´odulo builder Utils El diagrama que presenta en detalle del m´odulo utils se encuentra en la Figura 4.12. La principal funci´on de utils es fusionar en un solo m´odulo todas aquellas funciones de gran utilidad para el proyecto. Muchas de estas funciones se usan varias veces a lo largo del flujo de traducci´on. De hecho, este m´odulo, como se ha presentado en la Figura 4.3, es utilizado por los m´odulos builder,functions,external yvensim2py. A su vez, en utils se importan aquellos nombres accesibles de los m´odulos decorators,external yfunctions para poder definir una lista con aquellos nombres que ya han sido usados y que tienen un significado particular en el modelo que se est´e traduciendo. De este m´odulo se puede destacar la funci´on add entries undescore, mencionada en la Secci´on 6.5 dedicada al seguimiento del proyecto. Dicha funci´on se encarga de intercambiar en los nombres de las funciones los espacios por guiones bajos, ya que en Vensim se pueden escribir indistintamente. 49
4.2. MODELO DE VISTAS 4+1 Figura 4.12: M´odulo utils External En la Figura 4.13 se presenta el diagrama del m´odulo external y las clases definidas en ´el. Es en este m´odulo donde se definen varias clases cuya raz´on principal es leer datos externos. El principal prop´osito del m´odulo external se trata de unificar, en un solo archivo, todas las herramientas necesarias para leer datos de archivos externos. Figura 4.13: M´odulo external y sus clases En la Figura 4.14 se muestran los diagramas con detalle de las clases External yExcels. La clase principal de este m´odulo es la clase External, de la que heredan las dem´as exceptuando la clase Excels. La clase External permite almacenar cierta informaci´on como el nombre del fichero que se lee y los datos que contiene ese fichero. La clase Excels se encarga de leer archivos Excel y almacenar informaci´on de los mismos, para evitar que dichos archivos sean le´ıdos m´as de una vez, poniendo en pr´actica el patr´on Singleton. En la Figura 4.15 se presentan todas las clases pertenecientes al m´odulo external y que a su vez, heredan de la clase anteriormente comentada, External. 50
CAP´ ITULO 4. INGENIER´ IA INVERSA Figura 4.14: Clase Excels yExternal del m´odulo external Existen diferentes sentencias en Vensim que permiten obtener datos de ficheros externos que se utilizan como variables en un modelo Vensim. El conjunto de estas funciones que tienen soporte en PySD son las que se presentan a continuaci´on. Para obtener los datos de las sentencias Vensim GET XLS DATA yGET DIRECT DATA, se encuentra la clase ExtData. A su vez, para las sentencias GET XLS LOOKUPS yGET DIRECT LOOKUPS, la clase ExtLookup. Para las funciones GET XLS CONSTANT yGET DIRECT CONSTANT, la clase ExtConstant y, finalmente, para las sentencias GET XLS SUBSCRIPT yGET DIRECT SUBSCRIPT, se cuenta con la clase ExtSubscript. Estas expresiones crean una nueva instancia de la clase External, donde se almacena la informaci´on necesaria para presentar las estructuras de datos necesarias. Dichas instancias de la clase External se inicializan antes de los objetos Stateful. En la Figura 4.16 se presenta el m´odulo decorators. Para poder entender mejor el funcionamiento y la raz´on de este m´odulo se debe conocer el patr´on Decorator y su uso en Python, explicado en la Secci´on 3.5. En PySD se implementa una especie de cach´e de dos niveles para poder hacer que la ejecuci´on sea lo m´as r´apida posible. La cach´e se implementa mediante el uso de decoradores. En la fase de traducci´on se etiqueta a cada funci´on con uno de los dos tipos de cach´e. Se a˜nade el decorador cache.run para aquellas funciones cuyo valor es constante durante toda la ejecuci´on independientemente del tiempo de la simulaci´on. De esta manera, solo se calcula su valor una ´unica vez en toda la ejecuci´on. Se etiquetan con el decorador cache.step aquellas funciones que necesitan tener diferentes valores a lo largo de la ejecuci´on y cambiar su valor dependiendo del tiempo de la simulaci´on. 51
4.2. MODELO DE VISTAS 4+1 Figura 4.15: Clases del m´odulo external Decorators En el m´odulo decorators, detallado en la Figura 4.16, es donde se encuentran las funciones encargadas de desarrollar y decorar las funciones en la fase de traducci´on. La clase Cache representada es la que permite definir la funcionalidad deseada para esos decoradores. Las funciones run ystep define la funcionalidad para la cach´e de doble nivel utilizada en PySD. La funci´on reset, restablece el tiempo con el introducido por par´ametro y limpia la cach´e de aquellos valores que se hayan etiquetado con step. La funci´on clean limpia la cach´e cuyo nombre se le introduce como par´ametro. 4.2.3. Vista de proceso La arquitectura de proceso tiene en cuenta los requisitos no funcionales, como la disponibilidad y el rendimiento. Trata los aspectos din´amicos del sistema, explica los procesos del sistema y c´omo interact´uan entre ellos, entendiendo como proceso una agrupaci´on de tareas que forman una unidad ejecutable. Esta vista se enfoca en el comportamiento del sistema en 52
CAP´ ITULO 4. INGENIER´ IA INVERSA Figura 4.16: M´odulo decorators tiempo de ejecuci´on. Se suele representar a trav´es de diagramas de actividad UML. El diagrama asociado a la secuencia principal de traducci´on de modelos Vensim que realiza PySD, se presenta desde la Figura 4.17 hasta la Figura 4.22. Recalcar, que la Figura 4.17 corresponde a la secuencia principal del diagrama de actividad y los dem´as diagramas presentados son un desglose de las principales actividades de ´este. El proceso de traducci´on comienza a partir del usuario, cuando indica el modelo Vensim (con extensi´on mdl) que desea traducir, utilizando para ello la funci´on read vensim del m´odulo pysd (Figura 4.4). En esta funci´on, internamente se llama a la funci´on translate vensim, a la cual se le pasa como par´ametro el modelo Vensim y se encuentra en el m´odulo vensim2py (Figura 4.4). Es entonces cuando se modifica la extensi´on del path que contiene el modelo para poder guardar la traducci´on con el mismo nombre y en la misma ruta que el archivo Vensim, pero con diferente extensi´on utilizando .py. Despu´es, se separan las secciones que forman el modelo y, posteriormente, a partir de estas secciones obtenidas, se crea una lista con todas las macros existentes. Adem´as, cada secci´on se organiza y se traduce dando lugar a la traducci´on que completar´a el archivo Python. A continuaci´on, se explican los subsistemas que componen la Figura 4.17 con mayor detalle. Figura 4.17: Diagrama de actividad principal En la Figura 4.18 se presenta el subsistema “Separar por secciones”. Dentro de la funci´on citada anteriormente, translate vensim, se lee el modelo Vensim en modo texto y 53
4.2. MODELO DE VISTAS 4+1 pysd, que contiene todas traducciones de los elementos que se han recopilado en la secuencia anteriormente representada equivalentes al modelo Vensim introducido por el usuario. Por lo que, cuando este proceso de traducci´on finalice se obtendr´a como resultado en la misma ruta en la que se localiza el modelo Vensim, el modelo pysd equivalente. Es en la Figura 4.27 donde se muestra el diagrama de secuencia que representa la interrelaci´on entre los diferentes m´odulos en el proceso de ejecuci´on de un modelo pysd. El usuario comienza utilizando la funci´on run de la clase Model, cuyos par´ametros corresponden a determinadas funcionalidades que se pueden a˜nadir a la ejecuci´on o al resultado de la misma, como por ejemplo se permite indicar qu´e columnas de resultados se devuelven, en lugar de devolver todos los resultados del modelo. La instancia model de la clase Model (m´odulo functions) es la obtenida como resultado en el proceso anterior de traducci´on. En esta secuencia de ejecuci´on, se inicializan todos los objetos con los que cuente model y, mediante la funci´on integrate, se lleva a cabo la integraci´on por euler de todos los elementos con los que cuente el modelo y a partir de los cuales se obtendr´a el resultado. Tras estas dos secuencias, las funciones de la librer´ıa PySD que m´as utilizan los usuarios son read vensim, para traducir el modelo Vensim, y run, para ejecutarlo, como se ha explicado anteriormente y tambi´en se indica en la documentaci´on oficial del proyecto para el uso b´asico enfocado a usuarios [28]. 60
CAP´ ITULO 4. INGENIER´ IA INVERSA Figura 4.25: Diagrama de secuencia: Traducir secci´on 61
4.2. MODELO DE VISTAS 4+1 Figura 4.26: Diagrama de secuencia: A˜nadir traducci´on y llamar al builder 62
CAP´ ITULO 4. INGENIER´ IA INVERSA Figura 4.27: Diagrama de secuencia: Ejecuci´on del modelo ya traducido 63
4.2. MODELO DE VISTAS 4+1 64
CAP´ ITULO 5. TECNOLOG´ IAS UTILIZADAS Cap´ıtulo 5 Tecnolog´ıas utilizadas En este cap´ıtulo se explican las tecnolog´ıas utilizadas para la gesti´on y el desarrollo del proyecto. 5.1. Tecnolog´ıas para la gesti´on del proyecto 5.1.1. Jitsi Se ha utilizado Jitsi [12], herramienta de videoconferencia proporcionada por la Escuela de Ingenier´ıa Inform´atica de la UVa. Mediante esta plataforma se han llevado a cabo las weeklies necesarias entre la tutora y la alumna para el correcto seguimiento del proyecto. 5.1.2. Rocket.Chat Rocket.Chat [59] ha sido la plataforma de intercambio de mensajes para estar en contacto con la tutora, en el caso de que hubiera alg´un inconveniente o duda y no tener la necesidad de esperar a la siguiente reuni´on semanal. Esta plataforma la proporciona la Escuela de Ingenier´ıa Inform´atica. 5.1.3. GitLab Issues GitLab Issues [13] es una herramienta que permite monitorizar y controlar el progreso del proyecto. Permite compartir y debatir mejoras o propuestas para el proyecto entre todos los integrantes del mismo. Las issues permiten a su vez llevar un seguimiento de las tareas y estado laboral, pudiendo incluir el tiempo estimado y el tiempo invertido en la realizaci´on 65
5.1. TECNOLOG´ IAS PARA LA GESTI ´ ON DEL PROYECTO de cada tarea. Adem´as, permiten aceptar propuestas de funciones, preguntas, solicitudes de soporte o informes de errores, funci´on muy ´util cuando se trata de un proyecto open source para hacer m´as f´acil la contribuci´on entre todos los integrantes del proyecto. GitLab Issue Board [14] es una herramienta, dentro de GitLab Issues, que permite gestionar los proyectos software, planificando, organizando y visualizando un flujo de trabajo de issues o para la realizaci´on de una release. En este proyecto se ha realizado un tablero para poder visualizar y administrar las issues en base al marco de trabajo Scrum. Esto permite conocer el avance y estado de cada issue. El tablero se divide en listas, las cuales simulan las etapas por las que evoluciona una issue. En orden, estas son: Icebox: lista de todas las tareas consideradas en el proyecto. Backlog: lista de tareas ordenadas con alg´un tipo de prioridad. Sprint Backlog: tareas pertenecientes al sprint actual, ordenadas por prioridad. Doing: tareas que est´an siendo realizadas. Under review: lista de las tareas ya realizadas que se est´an revisando para poder darlas por finalizadas. En el caso de que se encuentre alguna deficiencia o alg´un aspecto a mejorar, se retrocede la issue a la anterior lista (Doing) y se corrige. Done: aquellas tareas realizadas y revisadas. En las Figuras: 5.1 y 5.2 se presenta el tablero realizado con GitLab Issues y en ´el se encuentran las listas antes comentadas. Cada lista tiene asociadas diferentes issues dependiendo del nivel de completitud que lleven ´estas. Figura 5.1: Gitlab Issues 66
CAP´ ITULO 5. TECNOLOG´ IAS UTILIZADAS Figura 5.2: Gitlab Issues Adem´as, se ha a˜nadido otro tipo de etiquetas para diferenciar la tipolog´ıa de las issues entre s´ı. Estas son: “Memoria”: utiliz´andose en aquellas issues relativas a la actualizaci´on de la memoria del proyecto. “C´odigo”: para las issues que implican desarrollo de funcionalidad. “Test”: utilizadas en aquellas issues correspondientes a testear funcionalidad a˜nadida previamente. “Pul request”: para las issues que conlleven la preparaci´on de un pull request. 5.1.4. Overleaf Overleaf [8] es un editor de texto de LaTeX en la nube utilizado para escribir, editar y publicar documentos. Se ha utilizado esta tecnolog´ıa para desarrollar la memoria del proyecto y poder plasmar el seguimiento del proyecto de manera escrita. 5.2. Tecnolog´ıas para el desarrollo del proyecto 5.2.1. Visual Studio Code Visual Studio Code [49] es un editor de c´odigo fuente desarrollado para Windows,macOS yLinux, desarrollado por Microsoft. Incluye control integrado de Git, resaltado de sintaxis, 67
5.2. TECNOLOG´ IAS PARA EL DESARROLLO DEL PROYECTO soporte para la depuraci´on, finalizaci´on de c´odigo inteligente, etc. Se ha utilizado para realizar los cambios y mejoras del c´odigo de PySD. 5.2.2. Git El control de versiones es un sistema que registra los cambios de un proyecto a lo largo del tiempo y permite revertir los cambios de archivos concretos a una versi´on anterior, revertir todo el proyecto, comparar diferentes cambios, ver qui´en modific´o cada archivo, etc. Es muy recomendable usar herramientas de control de versiones para cualquier desarrollo, aunque sea individual [4]. Git [7], desarrollado por Linus Torvals, es un sistema de control de versiones distribuido, gratuito y de c´odigo abierto dise˜nado para manejar cualquier tipo de proyecto. 5.2.3. GitHub GitHub [25] es una plataforma de desarrollo colaborativo para alojar proyectos utilizando Git. El c´odigo de los proyectos en GitHub se almacena normalmente de forma p´ublica. GitHub es la plataforma m´as importante de colaboraci´on de proyectos open source. El proyecto PySD se aloja en esta plataforma y cuenta con muchas contribuciones de diferentes desarrolladores. 5.2.4. GitLab GitLab es otro servicio de control de versiones y desarrollo colaborativo basado en Git. GitLab ofrece algunas caracter´ısticas similares para el seguimiento de problemas y la gesti´on de proyectos como GitHub. Pero una de las grandes diferencias entre estas dos plataformas radica en la Integraci´on Continua que solo GitLab incorpora [54]. La CI(continuous integration) consiste en hacer integraciones autom´aticas de un proyecto lo m´as a menudo posible para as´ı localizar los fallos cuanto antes, entendiendo como integrar el proceso de compilar y ejecutar las pruebas de un proyecto completo. 5.2.5. Astah Astah [3] es una herramienta para realizar modelos de UML, creada por la empresa japonesa Change Vision. Permite crear f´acilmente los diagramas UML que sean necesarios proporcionando todas las caracter´ısticas precisas para ello. En este proyecto se ha utilizado esta herramienta para poder representar la estructura de paquetes y archivos de PySD mediante un diagrama de clases. 68
CAP´ ITULO 5. TECNOLOG´ IAS UTILIZADAS 5.2.6. Visual Paradigm Visual Paradigm [52] es una herramienta de modelado UML. Permite varios tipos de diagramas, como diagramas de clases, de secuencia, de m´aquinas de estado, de actividad, de componentes, de paquetes, etc. En este proyecto se ha utilizado Visual Paradigm para realizar el diagrama de actividad relativo al flujo de informaci´on y proceso de traducci´on de PySD. A diferencia del programa Astah,Visual Paradigm proporciona la recreaci´on de bucles en los diagramas de actividad, material que ha sido clave para poder modelar con mayor exactitud el proyecto PySD. 5.2.7. Unittest Unittest [21] es un m´odulo de Python para definir y ejecutar pruebas unitarias. Se inspir´o originalmente en JUnit y es similar a los principales frameworks de prueba de otros lenguajes. Proporciona un gran conjunto de herramientas para programar y ejecutar tests. En PySD, este framework es utilizado en los tests unitarios de cada m´odulo. 5.2.8. Nose Nose [55] permite escribir tests simples y proporciona una serie de funciones ´utiles para poder escribir test cronometrados, tests de excepciones y otros casos de uso comunes. Adem´as, contiene plugins para permitir que se capturen los datos de salida, la cobertura del c´odigo, los tests de documentos y otras funcionalidades realmente ´utiles. En el proyecto de PySD, se utiliza el framework nose en los tests de integraci´on. 5.2.9. Travis CI Travis CI [66] es un servicio de integraci´on continua que permite ejecutar los tests, depurar e implementar c´odigo. Los proyectos se pueden sincronizar con esta herramienta y, como resultado, los tests se ejecutar´an autom´aticamente. En el proyecto de PySD, cada vez que se realiza una pull request, los tests se ejecutan autom´aticamente con Travis CI. La herramienta informa si ha habido alg´un error, si alg´un test ha fallado o si todos los tests han sido ejecutados correctamente. 5.2.10. Markdown Markdown [43] es una herramienta de conversi´on de texto a HTML para escritores web. Markdown le permite escribir usando un formato de texto plano f´acil de leer y escribit, y luego convertilo a XHTML (o HTML). Por lo tanto, Markdown proporciona una sintaxis 69
6.5. SPRINT 4 actual de PySD. No obstante, la funci´on RANDOM 0 1 est´a implementada y no causa ning´un error de parsing. Se termin´o a˜nadiendo a la gram´atica las operaciones de compatibilidad de subscripts, solventando los errores encontrados en los sprints anteriores. Esta implementaci´on se demor´o debido a que no se hab´ıa entendido con detalle el funcionamiento del parser utilizado, dando lugar al Riesgo 3, falta de formaci´on en parsimonious (Tabla 2.5). No se encontraba la manera de acceder a los hijos del ´arbol de an´alisis para, as´ı, poder obtener la informaci´on que se necesitaba. Finalmente, se pregunt´o a Diego Rodrigo sobre la posible soluci´on y se pudo completar la gram´atica de subscript mapping ysubscripts copy. Para poder probar la gram´atica implementada, se parti´o de los ejemplos de la gu´ıa de usuario que proporciona Vensim [32]. Se crearon test unitarios para sequence subscripts, subscripts copy ysubscripts mapping. Sin embargo, eran ejemplos incompletos y no se pod´ıan ejecutar en el entorno Vensim sin que se produjera ning´un error. Debido al desconocimiento de la alumna sobre Vensim, se pidi´o ayuda a los desarrolladores expertos de modelos en Vensim, explic´andoles los ejemplos que se necesitaban para as´ı poder testear la nueva gram´atica implementada con ejemplos funcionales. Ocurri´o el riesgo de la falta de conocimiento sobre Vensim para poder realizar tests, que corresponde al Riesgo 4 indicado en la Tabla 2.6. No obstante, cuando se termin´o el Sprint 3 no se hab´ıa recibido ning´un ejemplo, por lo que la tarea de testear la gram´atica implementada est´a en progreso. La ´unica consecuencia que tuvo el riesgo comentado, fue la demora de la tarea y tener que aplazarla para los sprints siguientes. Esta tarea se retomar´a cuando los expertos de Vensim nos proporcionen los ejemplos pedidos. Como en los sprints anteriores, se actualiz´o la memoria en lo que respecta al sprint actual y se a˜nadi´o la informaci´on precisa. En este sprint cabe destacar que se ha dedicado una mayor parte del tiempo a realizar la memoria, ya que se han a˜nadido parte de los conocimientos adquiridos y asentados hasta el momento y esto ha permitido estructurar la memoria con una idea m´as clara y mejorada. 6.5. Sprint 4 Duraci´on: del 27/1/2021 al 10/2/2021 El Sprint 4 se ha comenzado el d´ıa 27 de enero. Su fecha inicial estimada era el d´ıa 20, como se establece en la Planificaci´on inicial, Tabla 2.2 de la Secci´on 2.4. Esto se debe a que la alumna estuvo confinada desde el d´ıa 7 de enero hasta el 18 de enero. Los ex´amenes de la convocatoria ordinaria estaban previstos para esas fechas y tuvieron que ser aplazados. Finalmente, los ex´amenes se realizaron el d´ıa 21 y 22 de enero, por lo que la weekly que se hab´ıa establecido para el d´ıa 20 tuvo que verse aplazada una semana para que la alumna pudiera estudiar y centrarse ´unicamente en los ex´amenes. As´ı se ve materializado el riesgo por confinamiento debido a la situaci´on sanitaria actual, expuesto en la Tabla 2.10, el cual como consecuencia deja con una semana de retraso al proyecto y ha sido necesaria una replanificaci´on de los sprints. Las tareas acordadas para este sprint se han enumerado en la Tabla 6.5. 76
CAP´ ITULO 6. SEGUIMIENTO DEL PROYECTO Nombre de la Tarea Tiempo estimado Tiempo invertido Estado 3.1 - Completar Tarea 1.1. A˜nadir tests para la funci´on RANDOM 0 1 30m 30m Completada 3.2 - Completar Tarea 1.2. A˜nadir a la gram´atica subscripts sequence 3h 15m Completada 3.3 - Completar Tarea Tarea 2.2. A˜nadir a la gram´atica subscripts copy y a˜nadir diccionario para subscripts copy 4h 15m Completada 3.4 - Completar Tarea 2.3. A˜nadir a la gram´atica subscripts mapping y a˜nadir diccionario para subscripts mapping 4h 4h 40m Completada 3.5 - A˜nadir y ejecutar tests para las modificaciones de la gram´atica de compatibilidad de subscripts 3h 15m En progreso 3.6 - Actualizar memoria seguimiento Sprint 3 4h 13h 25m Completada Total 19h 20m 5/6 Tabla 6.4: Tareas del Sprint 3 A finales del mes de diciembre, se acept´o la pull request que Diego Rodrigo hab´ıa hecho, integrando sus cambios en PySD. Junto con las contribuciones de Eneko, se incorporaron todos los cambios a master. Se descargaron ambas versiones y se ejecut´o MEDEAS con la nueva rama de master y fallaba en la traducci´on. Se han comparado las dos versiones de PySD para poder encontrar el fallo o los cambios que lo producen. Se ha invertido gran cantidad de tiempo en buscar las posibles diferencias entre ambas versiones, adem´as de que se han ejecutado m´as archivos Vensim, no solo MEDEAS. Se invierte tanto tiempo en la b´usqueda de las causas de fallo, debido a la inexperiencia con el proyecto PySD y la poca informaci´on que arroja parsimonious sobre los errores gramaticales. Con la versi´on que ten´ıa Diego Rodrigo se encontr´o un error con respecto a los guiones bajos. Las funciones de Vensim pueden escribirse con espacios, cuando sea necesario o, en su lugar, con guiones bajos. Por ejemplo, tendr´ıa el mismo efecto escribir la funci´on RANDOM 0 1 que RANDOM 0 1. La versi´on de Diego Rodrigo fallaba cuando se escrib´ıan las funciones con guiones bajos, como ocurr´ıa en el proyecto WILIAM. Sin embargo, en la nueva rama master, se ha implementado la funci´on add entries underscore en el fichero utils.py que resuelve este problema. Se ha intentado implementar la funci´on de Vensim SAMPLE IF TRUE ya que PySD no tiene soporte para ella. En las issues de PySD aparece la necesidad de implementar esta funci´on por lo que ser´ıa interesante a˜nadir esta funci´on para acompa˜nar a una pull request y resolver dicha issue [41]. Se ha tenido que profundizar en su funcionamiento ya que esta funci´on no era conocida por la alumna y era muy similar a la funci´on IF THEN ELSE. Se ha estudiado las diferencias entre ambas funciones, ya que los par´ametros que tienen son similares. Se ha implementado finalmente la funci´on SAMPLE IF TRUE. La traducci´on se 77
6.6. SPRINT 5 realiza sin problema, sin embargo, la ejecuci´on de dicha funci´on ocasiona un error tras superar la m´axima recursividad posible de una funci´on. Este problema est´a relacionado con la cach´e y a´un, en el Sprint 4, no se ha encontrado una posible soluci´on. Tambi´en se ha continuado escribiendo la memoria, avanzando en el cap´ıtulo de An´alisis, explicando m´as en profundidad las gram´aticas con las que cuenta PySD y se ha comenzado a explicar PySD como un Modelo 4+1 vistas, para que fuera m´as f´acil entender su funcionamiento. Se ha explicado en detalle el funcionamiento de Parsimonious y los Visitors asociados a cada regla. Adem´as, se ha a˜nadido el seguimiento del Sprint 4 correspondiente. Nombre de la Tarea Tiempo estimado Tiempo invertido Estado 4.1 - Ejecutar pruebas y mirar diferencias entre master ynew functions 7h 12h 15m Completada 4.2 - Analizar la funci´on SAMPLE IF TRUE 3h 1h 35m Completada 4.3 - Actualizar memoria seguimiento Sprint 4 5h 17h 30m Completada Total 31h 20m 3/3 Tabla 6.5: Tareas del Sprint 4 6.6. Sprint 5 Duraci´on: del 10/2/2021 al 24/2/2021 Las tareas acordadas para este sprint se presentan en la Tabla 6.6. En este sprint, se han ejecutado nuevos ejemplos Vensim y se han intentado solventar los errores que se ocasionaban en la traducci´on. El archivo WOLIM 1 5-to-share.mdl generaba un error en la gram´atica parse general expression. Este error ten´ıa lugar cuando se buscaba en el namespace el nombre de una variable y no se encontraba. Esto se deb´ıa a que se parseaba mal la sentencia y no se almacenaba en el namespace. Se ha comprobado que el error estaba causado porque el comentario en la definici´on de la variable conten´ıa un n´umero impar de comillas. Al final, aunque el fallo se generase en la gram´atica parse general expression, el error se encontraba en la gram´atica model structure grammar, la cual parseaba mal la sentencia y no la almacenaba. En esta gram´atica los comentarios se definen con la regla “element”, la cual determina que si se poseen comillas tiene que ser un n´umero par. Puede darse el caso de que en algunas sentencias, como es este ejemplo, los comentarios no contienen un n´umero par de comillas lo que hace que no se almacenen correctamente las variables del modelo. Para solucionar este fallo, se ha definido una nueva regla en la gram´atica model structure grammar 78
CAP´ ITULO 6. SEGUIMIENTO DEL PROYECTO que define los comentarios de las sentencias Vensim como cualquier car´acter excepto una virgulilla (“˜”) o una tuber´ıa (“|”), los cuales son caracteres de control de las sentencias. Se continu´o ejecutando otro modelo modelo vld 20201130.mdl, el cual daba un error en el builder al intentar escribir el texto traducido en el archivo nuevo. El error ocurr´ıa cuando se intenta parsear e introducir saltos de l´ınea y corregir la indentaci´on en Python. Esto se deb´ıa a que faltan par´entesis para cerrar las funciones, es decir, estaban mal traducidas. M´as concretamente, esto estaba causado por la funci´on build function call que se encuentra en el m´odulo builder.py, la cual se encarga de traducir las funciones Vensim. Esta funci´on se utiliza en la gram´atica parse general expression. Dicho error se debe a alg´un cambio realizado en la nueva versi´on de PySD (master) ya que en la versi´on de Diego Rodrigo se traduc´ıan sin errores las funciones. Por esta raz´on, este ejemplo tambi´en se ha utilizado para poder comparar los cambios que presentan ambas versiones de PySD. Se ha intentado implementar la funci´on SAMPLE IF TRUE. Sin embargo, se continuaba con el problema de recursividad al ejecutar una sentencia como la que se muestra en el Fragmento de C´odigo 6.1. En este ejemplo se define una variable a partir de la funci´on SAMPLE IF TRUE la cual, a su vez, cuenta con la misma variable en uno de sus argumentos, exactamente en la condici´on de la funci´on. Las variables y constantes en la traducci´on de Python se representan como funciones que devuelven un valor. Al ejecutar la traducci´on creada por PySD, se alcanza el m´aximo nivel de recursi´on debido a que se ha definido una funci´on recursiva, es decir, que se define la funci´on a partir de s´ı misma. Se genera un error debido a que no se cuenta con un caso base que haga terminar, en alg´un momento, la recursi´on. Localizado este posible fallo con la funci´on SAMPLE IF TRUE, la implementaci´on de dicha funci´on se ha dejado en progreso para poder completarla en el siguiente sprint y as´ı poder probar si en la funci´on IF THEN ELSE, que son parecidas, ocurre lo mismo cuando se trate de una sentencia recursiva. 1max workforce = SAMPLE IF TRUE ( 2Workforce > max workforce , Workforce , Workforce ) Fragmento de c´odigo 6.1: Sentencia SAMPLE IF TRUE Se han realizado los diagramas de clases que representan la vista l´ogica de PySD, para poder definir de una manera m´as sencilla el funcionamiento del proyecto. Se han realizado los diagramas de clases relativos a los m´odulos de PySD y las clases que representan las gram´aticas. Sin embargo, falta pulir dichos modelos. Tambi´en se ha completado y a˜nadido el seguimiento de la memoria relativo al Sprint 5. 79
6.7. SPRINT 6 Nombre de la Tarea Tiempo estimado Tiempo invertido Estado 5.1 - Implementar la funci´on SAMPLE IF TRUE 4h 2h 15m En progreso 5.2 - Diagrama de clases para la vista l´ogica 3h 3h 30m En progreso 5.3 - Analizar cambios entre distintas versiones de PySD 6h 4h 50m En progreso 5.4 - Ejecutar diferentes ejemplos Vensim y corregir posibles errores 3h 12h 20m Completada 5.5 - Actualizar memoria seguimiento Sprint 5 6h 8h 45m Completada Total 31h 40m 2/5 Tabla 6.6: Tareas del Sprint 5 6.7. Sprint 6 Duraci´on: del 24/2/2021 al 10/3/2021 La Tabla 6.7 muestra el desglose de las tareas propuestas para este sprint. En el sprint anterior no se pudo completar la implementaci´on de la funci´on SAMPLE IF TRUE, ya que se descubri´o el fallo de recursividad que presentaba el modelo traducido en Python (explicado en el seguimiento del Sprint 5). En este sprint se ha comenzando estudiando si Vensim permite que exista una variable, por ejemplo: X, cuya definici´on est´e compuesta por la funci´on IF THEN ELSE y la condici´on de esta funci´on est´e formada por la misma variable X, para poder probar la recursividad. Se ha buscado un ejemplo Vensim con una funci´on IF THEN ELSE sencilla y se ha modificado para que se de esa situaci´on de recursividad. Se ha abierto el modelo en el entorno Vensim y se ha realizado un check model que permite determinar si el modelo cuenta con alg´un error o warning. Tras modificar el modelo y abrirlo en el entorno Vensim, ´este daba un error al comprobarlo, m´as concretamente: ERROR: Simultaneous equations involving. Lo que indica que Vensim no admite en la funci´on IF THEN ELSE ning´un tipo de recursividad. Sin embargo, con la funci´on SAMPLE IF TRUE s´ı admite recursividad entre la variable que se define y los par´ametros de la funci´on. En definitiva, teniendo en cuenta que variables y constantes de un modelo Vensim se traducen en PySD como funciones de Python, no es posible generar una traducci´on equivalente a la funci´on SAMPLE IF TRUE por el problema de recursividad presentado anteriormente. Sin embargo, s´ı se puede realizar una traducci´on de la funci´on SAMPLE IF TRUE para utilizarla en aquellos modelos que no tengan recursividad entre la variable y los par´ametros. Se ha realizado la implementaci´on de esta funci´on para PySD, utilizando una variable global para poder guardar el valor de la simulaci´on. Esta implementaci´on genera un resultado 80
CAP´ ITULO 6. SEGUIMIENTO DEL PROYECTO satisfactorio para ejemplos sin recursividad. Con respecto al anterior sprint, se ha probado el correcto funcionamiento del cambio realizado en la gram´atica model estructure grammar. Se ha probado con el ejemplo teacup.mdl, ejemplo b´asico de Vensim, al cual se le han a˜nadido 3 comillas a un comentario de una variable. PySD generaba una mala traducci´on en este caso, ya que parseaba mal la sentencia que conten´ıa esas 3 comillas y, debido a esto, no almacenaba correctamente las variables del modelo. El mismo ejemplo con la modificaci´on realizada en la gram´atica, generaba la traducci´on esperada, recalcando la necesidad de ese cambio. El ejemplo de teacup.mdl con el a˜nadido de las 3 comillas puede servir entonces para ser usado como un test a la hora de a˜nadir este cambio en el repositorio central del proyecto. Tras probar varios ejemplos para poder solventar los problemas con SAMPLE IF TRUE, surgi´o la necesidad de que algunos modelos pod´ıan tener la extensi´on en may´usculas, es decir, llamarse archivo.MDL, modelo que era v´alido para Vensim, lo abr´ıa y simulaba correctamente. En cambio, en PySD, generaba la traducci´on pero la escrib´ıa en el mismo fichero de partida, no generaba otro nuevo con extensi´on .py. Esto se deb´ıa a que no contaban con la opci´on de que el modelo pudiera tener la extensi´on en may´usculas. Se ha implementado esta funcionalidad, adem´as de a˜nadir que se lance una excepci´on cuando se de el caso de que el modelo introducido que se quiera traducir no tenga terminaci´on ni .mdl ni .MDL, es decir, no sea un modelo Vensim, aumentando la robustez del sistema. En este sprint, los desarrolladores de modelos Vensim nos han mandado los tests que pedimos en el Sprint 3, relativos a los subscripts para poder comprobar la gram´atica implementada sobre mapping y copy de subscripts y la secuencia de subscripts. Las reglas a˜nadidas para poder parsear la compatibilidad de subscripts son v´alidas ya que dichos ejemplos no causan ning´un error en el parsing. Sin embargo, faltar´ıa a˜nadir la funcionalidad para aquellos casos en los que haya que acceder a valores de subscripts que est´en vinculados a otros, ya que a d´ıa de hoy PySD no tiene soporte para eso. Entonces, se ha podido comprobar que la gram´atica a˜nadida anteriormente para las operaciones de subscripts, es correcta. Como en este sprint ya hemos contado con los tests de subscripts, se ha dedicado m´as tiempo a ello, ya que dicha tarea estaba pendiente, y no se ha podido iniciar la tarea relativa a encontrar las diferencias entre ambas versiones. M´as concretamente, comprobar que la funci´on build function call en el archivo builder.py tenga el funcionamiento esperado en la nueva versi´on de PySD. Por lo que esta tarea se pospone para el siguiente sprint. Se ha actualizado y mejorado los diagramas de clases para poder representar las relaciones e interacciones entre clases de PySD. Falta por hacer los diagramas que representen las estructuras de datos utilizadas en PySD para realizar la traducci´on. Adem´as, se ha a˜nadido el seguimiento necesario del Sprint 6 a la memoria. 81
6.8. SPRINT 7 Nombre de la Tarea Tiempo estimado Tiempo invertido Estado 6.1 - Completar Tarea 5.1. Implementar la funci´on SAMPLE IF TRUE 4h 3h 55m Completada 6.2 - Completar Tarea 5.2. Diagrama de clases para la vista l´ogica 5h 12h 30m En progreso 6.3 - Completar Tarea 5.3. Analizar cambios entre distintas versiones de PySD 4h 0 m No iniciada 6.4 - Testear la modificaci´on realizada en model structure grammar 6h 4h Completada 6.5 - Extensi´on del modelo Vensim a traducir 2h 2h 10m Completada 6.6 - Completar Tarea 3.5 - A˜nadir y ejecutar tests para las modificaciones de la gram´atica de compatibilidad de subscripts 5h 2h En progreso 6.7 - Actualizar memoria seguimiento Sprint 6 6h 4h 25m Completada Total 29h 4/7 Tabla 6.7: Tareas del Sprint 6 6.8. Sprint 7 Duraci´on: del 10/3/2021 al 24/3/2021 La Tabla 6.8 muestra el desglose de tareas acordadas para realizar en el s´eptimo sprint. En el sprint anterior, al ejecutar los ejemplos de los subscripts, se descubri´o que el resultado no era el mismo que el esperado. Se obten´ıa como resultado el nombre de la funci´on a la que se llamaba o una sentencia de c´odigo en vez de un n´umero (Tarea 7.4). Esto tambi´en ocurr´ıa cuando se intent´o ejecutar la funci´on SAMPLE IF TRUE, por lo que se dedujo que era un fallo que ten´ıa PySD cuando guardaba los resultados de las ejecuciones. Por ejemplo, cuando se intentaba ejecutar el ejemplo de la funci´on SAMPLE IF TRUE se obten´ıa como resultado: <function max workforce.<locals>.<lambda>at 0...>. En el caso de la funci´on SAMPLE IF TRUE esto se deb´ıa a que se hab´ıan definido sus par´ametros como expresiones lamba y por eso se obten´ıa ese resultado. Si se omit´ıa esa definici´on de los par´ametros, se generaba el resultado esperado. Con respecto a los subscripts, como se trata de matrices bidimensionales, para poder obtener el resultado num´erico correcto hay que filtrar el resultado con las dimensiones del subscript que se quiera comprobar. Es decir, en la funci´on run que ejecuta el modelo ya traducido, se debe a˜nadir el par´ametro return columns e igualarlo al nombre de la variable de la cual se quiera conocer el resultado junto a las dimensiones del subscript. Un ejemplo ser´ıa: return columns=[’Level 2[A,B]’], siendo Level 2 la variable y AyBlos subscripts asociados. 82
CAP´ ITULO 6. SEGUIMIENTO DEL PROYECTO En los tests que recibimos relativos a subscripts, se encontraba un modelo simple de subscripts, uno que realizaba un copy de susbscripts y otro sobre el mapping de subscripts. En este proyecto se ha implementado la secuencia de subscripts (Secci´on 3.2.2), por lo que faltaba un test que definiera un subscript con una secuencia. Para generar este nuevo test, se ha partido de un modelo, de los tests recibidos, que define un subscript de la forma representada en el Fragmento de c´odigo 6.2. Se ha intercambiado dicha sentencia por su equivalente, representada en el Fragmento de c´odigo 6.3, en la cual se define el mismo subscript pero con un rango num´erico. 1DimA : da1 ,da2 ,da3 ,da4 , da5 ~~| Fragmento de c´odigo 6.2: Sentencia Subscript 1DimA : (da1 -da5 ) ~~| Fragmento de c´odigo 6.3: Sentencia Sequence Subscript Como estas dos definiciones de subscripts son equivalentes, el resultado del primer modelo contemplado debe ser igual al resultado del test creado con la secuencia. Tras ejecutarlo, el resultado ha sido el esperado, por lo que se puede concluir que la definici´on de un subscript a partir de un rango num´erico implementada en la gram´atica funciona correctamente para PySD. Sin embargo, el mapping y copy de subscripts no reflejan ning´un error gramatical, pero la funcionalidad necesaria no est´a implementada. Por lo que al ejecutar la traducci´on del modelo, falla. Para cada subscript vac´ıo, sin subscript values asociados, que se define como copy de otro (Secci´on 3.2.2) se le han a˜nadido los subscripts values del subscript copia. Con respecto a los subscripts que se mapean, se ha determinado unificar los subscripts que utilizan. Sin embargo, esta funcionalidad no se ha podido completar en este sprint. Tambi´en, en este sprint se ha intentado abordar el fallo de la funci´on build function call, la cual es la encargada de traducir las funciones a Python y, como se ha comentado en sprints pasados, daba alg´un fallo en las ´ultimas modificaciones de PySD en casos concretos. Sin embargo, no se ha podido completar por la dificultad encontrada y el tiempo empleado en la implementaci´on de subscripts copy y mapping. Con los cambios realizados anteriormente, como la implementaci´on de la funci´on RANDOM 0 1, la nueva definici´on de los comentarios en la gram´atica model structure grammar y los cambios realizados sobre la extensi´on de un modelo Vensim, se ha realizado una pull request al repositorio principal. La pull request en cuesti´on se encuentra en: https: //github.com/JamesPHoughton/pysd/pull/247. El creador de PySD pidi´o algunos cambios con respecto a esta pull request, pero no dio tiempo a realizarlos en este sprint por lo que se finalizar´a esta tarea en el siguiente sprint. 83
6.9. SPRINT 8 Como en todos los dem´as sprints, se ha a˜nadido la informaci´on necesaria relativa al Sprint 7 a la memoria. Adem´as, se han terminado de pulir los diagramas de clases que se utilizan en la vista l´ogica de PySD. Nombre de la Tarea Tiempo estimado Tiempo invertido Estado 7.1 - Completar Tarea 5.2. Diagrama de clases para la vista l´ogica 3h 30 m Completada 7.2 - Completar Tarea 5.3. Analizar cambios entre distintas versiones de PySD 2h 45m En Progreso 7.3 - Completar Tarea 3.5 - A˜nadir y ejecutar tests para las modificaciones de la gram´atica de compatibilidad de subscripts 1h 30m 10m Completada 7.4 - Analizar el valor que devuelve para algunas variables la nueva versi´on de PySD 2h 3h Completada 7.5 - Realizar la primera contribuci´on en PySD 3h 5h 35m En Progreso 7.6 - Implementar funcionalidad adecuada para subscript mapping y copy 8h 15h En Progreso 7.7 - Actualizar memoria seguimiento Sprint 7 5h 5h 25m Completada Total 30h 25m 4/7 Tabla 6.8: Tareas del Sprint 7 6.9. Sprint 8 Duraci´on: del 24/3/2021 al 7/4/2021 En la Tabla 6.9 se muestra el desglose de tareas propuestas para este sprint. Continuando con la pull request realizada, se han realizado los cambios que pidieron a mayores para poder mergear a la rama principal del proyecto. Los cambios que se pidieron eran que los modelos Vensim de tests a˜nadidos, utilizados para comprobar los cambios realizados, se a˜nadiesen al subm´odulo de tests (SDXorg/test-models). Se hizo un fork de este repositorio y se a˜nadieron estos modelos de tests nuevos. Despu´es se realiz´o una pull request al repositorio original de los tests. Adem´as, se cambiaron los tests al archivo integration test vensim pathway.py donde se encuentran todos los tests que comprueban el correcto funcionamiento de PySD. En el subm´odulo de tests, se encontr´o un modelo Vensim que utilizaba la funci´on SAMPLE IF TRUE, el cual no conten´ıa ninguna recursividad entre la variable y los par´ametros de 84
CAP´ ITULO 6. SEGUIMIENTO DEL PROYECTO la funci´on, problema anteriormente explicado. Por lo que se prob´o con ese modelo la funci´on SAMPLE IF TRUE anteriormente implementada. Fall´o, debido a que conten´ıa DataArrays y no se hab´ıa a˜nadido soporte para los mismos. A´un as´ı, se ha dedicado bastante tiempo a modificar la funci´on ya que la presencia de DataArrays y su manejo ha supuesto un aprendizaje para poder utilizarlos y modificarlos adecuadamente. Resumidamente, los par´ametros que recibe la funci´on son: una condici´on, un valor inicial que se utiliza en el primer step de la simulaci´on y un valor actual. Adem´as, se guarda un diccionario con el valor que se almacena entre los diferentes steps cuando se ejecuta el modelo. En primer lugar, se vio que el primer error cometido a la hora de implementar dicha funci´on era que se guardaba un ´unico valor para todas las funciones SAMPLE IF TRUE que pudiera haber en un modelo. Tras encontrar el ejemplo del subm´odulo, en el que se defin´ıan varias variables con la funci´on SAMPLE IF TRUE, se vio que siempre que se tuviera que devolver el valor almacenado, se devolv´ıa el mismo valor independientemente de la variable que se tratase. Esto se solucion´o a˜nadiendo un par´ametro m´as a la funci´on, el nombre de la variable a la que esa funci´on estaba asociada, para as´ı poder identificar los valores almacenados de cada variable. Es decir, se guarda el valor almacenado junto al nombre de la variable en la que se encuentra, para poder identificar los diferentes valores almacenados. Adem´as, se cambi´o la forma de guardar los valores, y se convirti´o el ´unico valor almacenado en un diccionario con valores almacenados, en el cual se a˜nad´ıa una entrada cada vez que se correspond´ıa al primer step de la simulaci´on. Dicho diccionario de valores almacenados est´a compuesto por el nombre de la variable como key y el ´ultimo valor almacenado como value. Adem´as, en la funci´on implementada solamente se hab´ıa tenido en cuenta el caso m´as simple, que se daba cuando la condici´on y los valores inicial, actual y almacenado, eran de tipos simples como bool oint. Sin embargo, la condici´on podr´ıa ser un subscript, es decir, se traduce como un DataArray. En otras palabras, lo que se obtiene cuando la condici´on es un subscript es que para una sola variable almacena varios valores diferentes, como por ejemplo una condici´on que almacene [False, True, False] que hacen referencia a las dimensiones ’A’, ’B’ y ’C’. Por consiguiente, no se puede almacenar un ´unico valor para esa variable ya que hay que tener en cuenta cada valor de la condici´on y almacenar un valor u otro dependiendo de ´esta. Entonces, se cambi´o el valor almacenado por un DataArray cuando la condici´on lo fuera, adem´as de que el valor actual pod´ıa ser o no DataArray, por lo que hubo tambi´en que redimensionar el DataArray del valor guardado en este ´ultimo caso. Tambi´en, se deb´ıa comprobar la condici´on con las dimensiones adecuadas y actualizar el valor almacenado solo en las coordenadas necesarias. El tercer par´ametro de SAMPLE IF TRUE es el valor inicial, con el que se inicializa el valor almacenado. ´ Este siempre se ha tratado como si fuera de tipo simple y con ´el, en un principio, se rellenaban todas las dimensiones del DataArray que almacenaba los valores. Posteriormente, se encontr´o la posibilidad de que el valor inicial pudiese ser un DataArray, ya que al final las diferentes coordenadas del DataArray pod´ıan estar inicializadas con valores diferentes. Para esto hubo que hacer una ligera modificaci´on donde se inicializaba el valor almacenado, teniendo en cuenta las diferentes coordenadas y dimensiones de los DataArrays. Tras estos cambios y combinaciones posibles entre los par´ametros de SAMPLE IF TRUE, el modelo de test que se encontraba en el subm´odulo se traduc´ıa correctamente y generaba la salida esperada. 85
6.12. SPRINT 11 de subscripts y el copy, se recibi´o respuesta por parte de los programadores de Vensim. Como se hab´ıa pensado en un principio, los subscripts mapeados no variaban el resultado de la simulaci´on. Finalmente, en el modelo de prueba que hab´ıan enviado los programadores de Vensim faltaba un mapeo entre dos subscripts, es decir, estaba una sentencia de la forma: DimB ->DimC, pero faltaba la sentencia: DimC ->DimB. Al a˜nadir esta sentencia el resultado proporcionado por Vensim era el mismo que devolv´ıa PySD. Al realizar este mapeo en ambas direcciones causa el mismo efecto que si fuera un copy entre ambos subscripts. Se ha decidido tener cuanto antes implementada en PySD la funcionalidad de copy de subscripts y la funcionalidad ‘simple’ de mapping de subscripts para, junto a la documentaci´on del an´alisis en markdown, poder realizar otra pull request al repositorio. La funcionalidad de mapear varios subscripts es mucho m´as amplia de lo que se ha presentado en este proyecto, ya que se pueden mapear ´unicamente subranges (subrangos) de un subscript con otro. Esto requiere mucho m´as estudio sobre c´omo afecta al resultado de la simulaci´on y c´omo ser´ıa la mejor manera de implementarlo. Debido al tiempo, se ha decido implementar ´unicamente aquella funcionalidad de mapeo de subscripts que tiene, a fin de cuentas, el mismo resultado que el copy de subscripts. Se ha continuado intentando desarrollar dicha funcionalidad, pero se continuar´a en el siguiente sprint. Adem´as, se ha a˜nadido el seguimiento relativo al Sprint 11 a la memoria del proyecto. Nombre de la Tarea Tiempo estimado Tiempo invertido Estado 11.1 - Completar Tarea 7.6. Implementar funcionalidad adecuada para subscript mapping y copy 6h 9h 10m En Progreso 11.2 - Completar Tarea 9.3. Realizar la segunda contribuci´on en PySD 5h 2h 40m Completada 11.3 - Completar Tarea 10.4. Traducir y convertir a markdown el Modelo 4+1 vistas 8h 11h Completada 11.4 - Redefinir la funci´on SAMPLE IF TRUE 6h 5h Completada 11.5 - Completar Vista de Escenarios con Diagrama de Secuencia 4h 2h 10m En Progreso 11.6 - Actualizar memoria seguimiento Sprint 11 3h 1h Completada Total 31 h 4/6 Tabla 6.12: Tareas del Sprint 11 92
CAP´ ITULO 6. SEGUIMIENTO DEL PROYECTO 6.13. Sprint 12 Duraci´on: del 19/5/2021 al 2/6/2021 En la Tabla 6.13 se presentan las tareas propuestas para realizar en el Sprint 12. Se ha comenzado este sprint continuando las tareas pendientes del anterior sprint, completando el diagrama de secuencia para a˜nadirlo a la vista de escenarios e implementar la funcionalidad de subscript copy as´ı como de subscript mapping simple. Se ha priorizado la realizaci´on de ´estas ya que urge crear una nueva pull request en PySD para poder a˜nadir cuanto antes los nuevos cambios. Se ha realizado la pull request, que se encuentra en el siguiente enlace: https://github.c om/JamesPHoughton/pysd/pull/260. Se sugiri´o convertir el documento sobre el an´alisis para desarrolladores de PySD a rst (reStructuredText) [57], un lenguaje de marcas ligero, similar amarkdown, ya que es el que se utiliza para generar la documentaci´on asociada a PySD. Adem´as, cabe destacar que tuvo buena acogida la documentaci´on a˜nadida, comprobando realmente su necesidad en el proyecto para los futuros contribuidores. Finalmente, se integraron los cambios de esa pull request en el repositorio central y se actualiz´o la documentaci´on de PySD con el trabajo de an´alisis que se hab´ıa adjuntado, pudiendo acceder a ella a trav´es del siguiente enlace: https://pysd.readthedocs.io/en/m aster/development/pysd architecture views/4+1view model.html. Tras tener los nuevos cambios se prob´o a traducir el modelo WILIAM. Surgi´o un error debido a que faltaba la implementaci´on de name box a la hora de escoger las casillas en la funci´on GET SUBSCRIPT DIRECT. Un name box en Excel determina un rango de celdas y en la Wiliam se utiliza name box para determinar en la funci´on GET SUBSCRIPT DIRECT cu´ales son las celdas del Excel con las que se tiene que trabajar en dicha funci´on. Tras ver este error, se abri´o una nueva issue en la que se indicaba el problema y se adjuntaba el fichero Excel y el modelo Vensim que se hab´ıa probado. En este sprint, se ha dedicado una gran parte del tiempo a redactar algunos cap´ıtulos de la memoria pendientes. 6.14. Resumen y calendarizaci´on final En la Tabla 6.14, se presenta un resumen en el cual se contabiliza algunos de los hechos m´as relevantes en este proyecto sobre PySD, como son las pull requests realizadas, issues a˜nadidas, etc. En la Tabla 6.15, se encuentra la planificaci´on final que realmente se ha llevado a cabo, indicando brevemente aquellas causas por las que la planificaci´on inicial del proyecto ha tenido que verse pospuesta. 93
6.15. COSTES SIMULADOS FINALES Nombre de la Tarea Tiempo estimado Tiempo invertido Estado 12.1 - Completar Tarea 7.6. Implementar funcionalidad adecuada para subscript mapping y copy 6h 10h Completada 12.2 - Completar Tarea 11.5. Completar Vista de Escenarios con Diagrama de Secuencia 6h 5h 30m Completada 12.3 - Realizar tercera contribuci´on en PySD 5h 10h 45m Completada 12.4 - A˜nadir issue a PySD con el error visto 30m 45m Completada 12.5 - Actualizar memoria seguimiento Sprint 12 8h 24h 10m Completada Total 51h 10m 5/5 Tabla 6.13: Tareas del Sprint 12 Nombre N´umero de veces Issues a˜nadidas a PySD 10 Issues cerradas de PySD 5 Pull Requests abiertas en PySD 3 ... de las cuales cerradas 3 Pull Requests abiertas en test-models 3 ... de las cuales cerradas 3 Modelos Vensim a˜nadidos a test-models 5 Tabla 6.14: Tabla resumen final 6.15. Costes simulados finales La duraci´on del proyecto finalmente fue de 8 meses y medio, por lo que los costes tanto de personal, como de depreciaci´on del ordenador y de licencias software calculados en la Secci´on 2.6 deben ser actualizados. La duraci´on final en horas del proyecto ha sido de 389 horas y 20 minutos, incrementando el tiempo inicial estimado. Siguiendo con la misma m´etrica calculada en la Secci´on anteriormente citada, el coste de plantilla por horas son 11,32 e. Total: 4.403,48 e. Los gastos generales finales teniendo en cuenta el valor previo, calculado en la Secci´on 2.6, del precio medio al d´ıa de la luz es de 0,11059 e/kWh y contemplando que la duraci´on del proyecto finalmente ha sido de 389 horas, los gastos generales ascender´ıan a la cantidad de 43,02 e. La depreciaci´on del ordenador calculada era de 519,8 e/a˜no. Debido a que finalmente 94
CAP´ ITULO 6. SEGUIMIENTO DEL PROYECTO Sprint Fecha de comienzo Fecha de finalizaci´on Observaciones Sprint 0 14/09/2020 21/10/2020 Sprint 1 21/10/2020 4/11/2020 Sprint 2 4/11/2020 18/11/2020 Ex´amenes parciales Sprint 3 2/12/2020 16/12/2020 Entregas finales, Navidad y convocatoria ordinaria Cuarentena por COVID-19, convocatoria ordinaria aplazada Sprint 4 27/1/2021 10/2/2021 Sprint 5 10/2/2021 24/2/2021 Sprint 6 24/2/2021 10/3/2021 Sprint 7 10/3/2021 24/3/2021 Sprint 8 24/3/2021 7/4/2021 Sprint 9 7/4/2021 21/4/2021 Sprint 10 21/4/2021 5/5/2021 Sprint 11 5/5/2021 19/5/2021 Sprint de refuerzo Sprint 12 19/5/2021 2/6/2021 Sprint de refuerzo Tabla 6.15: Calendarizaci´on final del proyecto el proyecto se alarg´o y dur´o 8 meses y medio, la depreciaci´on del ordenador para este periodo de tiempo es de 368,19 e. El coste relativo a las licencias se ver´a aumentado por la duraci´on del proyecto. La licencia de Vensim DSS tiene un coste de 1636,73 epor usuario al a˜no. Teniendo en cuenta la prolongaci´on en el tiempo del trabajo, para 8 meses y medio la licencia de Vensim DSS tiene una coste final de 1159,35 e. Continuando con la licencia de Astah Professional, seg´un lo calculado en la Secci´on 2.6 antes citada, se calcul´o un costo de 33,35 eal a˜no. El coste final de la licencia asociada a Astah Professional ascender´ıa a 23,62 een base al incremento en la duraci´on del proyecto. Para Visual Paradigm se utiliza una licencia que conlleva un costo de 15,85 e/mes, de acuerdo con el aumento del tiempo equivale a 134,73 epara el proyecto. Las tecnolog´ıas GitLab,GitHub,Visual Studio Code yOverleaf, utilizadas en el desarrollo de este trabajo, tienen licencias de uso abiertas por lo que no aumentan el presupuesto del proyecto. Por lo tanto, las licencias de Astah Professional,Vensim DSS yVisual Paradigm acumulan un presupuesto total de 1317,7 esiendo ´este el coste asociado a las licencias software. En la Tabla 6.16 se recogen todos estos costos anteriormente razonados y la suma de los mismos, obtieniendo un total de 6.132,39 ecomo coste simulado final de este Trabajo Fin de Grado. 95
6.16. COSTES REALES FINALES Costes de Plantilla 4.403,48 e Gastos Generales 43,02 e Material 368,19 e Licencias software 1.317,7 e Total 6.132,39 e Tabla 6.16: Costes simulados finales 6.16. Costes reales finales Finalmente, a´un habiendo un aumento en la duraci´on del proyecto, los costes de plantilla reales asociados a ´este son los mismos que los calculados en la Secci´on 2.7, 1.800 ecomo resultado de la beca por 6 meses. Los gastos generales son id´enticos a los calculados en la Secci´on 6.15, es decir, 43,02 e. Los gastos relativos al material con el que se ha trabajado en el desarrollo del proyecto son an´alogos a los calculados en la Secci´on 6.15, siendo 368,19 e. Los costes asociados a las licencias de software las ha proporcionado la Universidad de Valladolid, por lo que su coste no aumenta el presupuesto de este proyecto. En la Tabla 6.17 se presenta un resumen con todas los costes anteriormente justificados, acompa˜nados del total que suman, ascendiendo esta cantidad a 2.211,92 ecomo coste real final de este Trabajo Fin de Grado. Costes de Plantilla 1.800 e Gastos Generales 43,02 e Material 368,9 e Licencias software 0 e Total 2.211,92 e Tabla 6.17: Costes reales finales 96
CAP´ ITULO 7. DISE ˜ NO DE LAS MODIFICACIONES Cap´ıtulo 7 Dise˜no de las modificaciones En esta secci´on se exponen y se explican todas las mejoras y contribuciones realizadas al c´odigo de PySD. Se han corregido bugs, se han implementado funciones de Vensim para las cuales PySD a´un no ten´ıa soporte y se han a˜nadido algunas operaciones sobre subscripts, adem´as de mejorar la documentaci´on para desarrolladores. Todas las modificaciones y mejoras realizadas sobre PySD se han hecho en base a la regla del boy scout: “leave the campground cleaner than you found it” [46]. En ella, se hace hincapi´e en limpiar el c´odigo o dejarlo mejor de lo que te has encontrado. En esta regla se destaca que no es necesaria una limpieza muy extensa sobre el c´odigo y que, por peque˜nas que sean las mejoras, siempre se ayudar´a a que el c´odigo no empeore con el paso del tiempo y los futuros contribuidores se ver´an beneficiados con esta “limpieza”. 7.1. Bugs 7.1.1. Extensi´on de los modelos Vensim En el entorno gr´afico Vensim est´an permitidos aquellos modelos en los que el nombre del fichero se encuentre con la extensi´on en may´usculas, como ejemplo el nombre del archivo: teacup.MDL. Sin embargo, en PySD solo se hab´ıa contemplado el caso en el cual los nombres de los modelos Vensim terminan con la extensi´on en min´uscula. Cuando se hizo una prueba con un ejemplo Vensim cuyo nombre estaba en may´usculas, incluida la extensi´on, se encontr´o el fallo de que la traducci´on se guardaba en el mismo archivo del que se part´ıa, es decir, se sobrescrib´ıa el modelo Vensim con el resultado Python. Esto se deb´ıa a que PySD no era capaz de encontrar la extensi´on .mdl, ya que estaba en may´usculas, de tal forma que no 97
7.2. FUNCIONES llegaba a intercambiar dicha extensi´on por .py y almacenaba el resultado en la misma ruta en la que se encontraba el modelo Vensim, sobrescribi´endolo. Se a˜nadieron las l´ıneas de c´odigo pertinentes para que PySD permitiese indistintamente modelos con la extensi´on en may´usculas o min´usculas. A mayores, se crey´o conveniente a˜nadir un ligero control para comprobar la extensi´on de los archivos que se quer´ıan traducir. Se incorpor´o entonces el lanzamiento de un error cuando el par´ametro de la funci´on translate vensim no correspondiese a un archivo Vensim, o lo que es lo mismo, solo se admit´ıan archcivos cuya extensi´on fuera: mdl oMDL. 7.1.2. Comentarios de sentecias en Vensim Las sentencias Vensim suelen constar de 3 partes separadas por virgulillas (s´ımbolo ˜), como se muestra en el Fragmento de C´odigo 7.1. La gram´atica model structure grammar es la segunda gram´atica de PySD y la encargada de separar ecuaci´on, unidades y comentario que contenga cada sentencia Vensim. 1nombre : valor 2~ unidades 3~ comentario | Fragmento de c´odigo 7.1: Sentencia Vensim Intentando traducir y ejecutar un determinado ejemplo Vensim, PySD fallaba y no almacenaba correctamente en el diccionario namespace todos los nombres de las variables definidas en el modelo. Esto se deb´ıa a que en la gram´atica model structure grammar se hab´ıa definido mal los comentarios de las sentencias Vensim. El problema era cuando se ten´ıa una sentencia Vensim con un n´umero de comillas impares en el comentario, ya que solamente estaba definida la posibilidad de comentarios con un n´umero par de comillas. Se modific´o y a˜nadi´o una regla en esta gram´atica, indicando que los comentarios pod´ıan estar formados por cualquier car´acter que no fuera ni una tuber´ıa (|) ni una virgulilla(˜), ya que estos caracteres eran caracteres especiales de Vensim porque se utilizan como delimitadores en las sentencias para indicar la separaci´on de elementos o el fin de una sentencia. El uso de estos delimitadores se puede comprobar en el fragmento de c´odigo anteriormente presentado, 7.1. 7.2. Funciones 7.2.1. Random 0 1 Se a˜nadi´o la implementaci´on para la funci´on RANDOM 0 1 de Vensim, cuyo funcionamiento est´a explicado en la Secci´on 3.2.3. Para ello, se defini´o en el m´odulo functions la 98
CAP´ ITULO 7. DISE ˜ NO DE LAS MODIFICACIONES funci´on random 0 1, la cual utilizaba la funci´on random.uniform de la librer´ıa numpy de Python que permit´ıa devolver un valor aleatorio entre 0 y 1. En la funci´on creada se a˜nadi´o la documentaci´on de la misma. Adem´as, para que en PySD se pudiera mapear la funci´on Random 0 1 de Vensim con la creada en Python, random 0 1, se a˜nadi´o una entrada que mapeaba ambos nombres al diccionario de funciones, denominado functions en el m´odulo principal de la traducci´on, vensim2py. Cabe destacar que la documentaci´on de Vensim califica a esta funci´on como obsoleta. A´un as´ı, se decidi´o a˜nadirla debido a que se encontr´o en un modelo Vensim con el que se trabaj´o al principio. Adem´as, de esta manera se a˜nad´ıa soporte para aquellos modelos Vensim de versiones anteriores y permit´ıa que PySD guardase la compatibilidad hacia atr´as. Fue un cambio relativamente sencillo y, por ello, un buen punto de comienzo para contribuir y realizar cambios en el proyecto de PySD. 7.2.2. Sample If True La funci´on Sample If True de Vensim se ha explicado en la Secci´on 3.2.3. Se trata de una funci´on cuyo resultado var´ıa en tiempo de ejecuci´on, ya que eval´ua la condici´on pasada por par´ametro en cada step. El valor que esta funci´on devuelve, depende del resultado de la condici´on en cada paso de tiempo del modelo. En el caso de que dicha condici´on sea cierta, se devolver´a y almacenar´a el valor del segundo par´ametro. En caso contrario, se retorna el valor que estaba previamente almacenado. Debido a que consta de un valor almacenado, el cual depende de cada iteraci´on del modelo, y tambi´en cuenta con un valor inicial que permite inicializarlo, dicha funci´on se ha implementado como una clase derivada de la clase Stateful. De esta manera se permite que cada funci´on Sample If True que aparezca en un modelo Vensim tenga un estado que se corresponda al valor guardado y se actualice siempre que sea necesario. Para implementar esta funcionalidad, se a˜nadi´o la clase SampleIfTrue al m´odulo functions. Cuenta con tres atributos que corresponden a los par´ametros de la funci´on: condici´on, valor actual y valor inicial. Adem´as, al heredar de la clase Stateful cuenta con un atributo state que permite simular el comportamiento del valor guardado. Se cre´o una funci´on initialize que inicializa el atributo state con el valor inicial, teniendo en cuenta si ´este es de tipo DataArray o no. Si el valor inicial es de tipo DataArray, se almacena en una ´unica variable, en este caso initial value, una matriz con varios valores, por lo que ser´a necesario que el valor almacenado o state tambi´en sea un DataArray y pueda almacenar varios valores en una variable. La funci´on call contiene el comportamiento principal, actualiza el estado utilizando para ello la funci´on if then else. En la Secci´on 3.2.3 se coment´o el parecido entre el comportamiento de la funci´on If Then Else ySample If True, llegando a la conclusi´on de que la diferencia entre ambas se encontraba en que esta ´ultima almacenaba el estado y lo devolv´ıa como resultado cuando fuera oportuno. Por ese motivo, se puede utilizar la funcionalidad de If Then Else, a˜nadi´endole la caracter´ıstica de almacenar el valor devuelto por If Then Else en el caso de que la condici´on sea cierta. A la clase SampleIfTrue creada tambi´en se le a˜nadi´o un m´etodo ddt el cual devolv´ıa un 99
7.3. SUBSCRIPTS valor constante, 0. Este m´etodo se utiliza en la integraci´on por Euler de aquellas variables cuyo valor var´ıe en cada iteraci´on, correspondiendo a la derivada. En el caso de esta funci´on, al ser 0 se consigue que este valor no influya en el resultado que se almacena en la variable state. Para crear instancias de esta clase en base a las apariciones de la funci´on Sample If True en los modelos de Vensim, se cre´o la funci´on add sample if true en el m´odulo builder. Esta funci´on es la encargada de instanciar objetos con estado de la clase SampleIfTrue. 7.3. Subscripts 7.3.1. Subscript numeric range La explicaci´on sobre la funcionalidad de la operaci´on subscript numeric range se encuentra en la Secci´on 3.2.2. Esta operaci´on de atajo para definir subscripts que proporciona Vensim, no ten´ıa su traducci´on en PySD. Para ello, se ha modificado la gram´atica component structure grammar y se ha a˜nadido una regla correspondiente con la definici´on de un subscript a partir de un rango num´erico o un valor ´unico o la combinaci´on de ambos separados por comas. Los nombres de los subscript que forman parte de un rango num´erico deben tener la misma secuencia de caracteres y terminar con un n´umero. Es decir, en el ejemplo presentado en el Fragmento de C´odigo 7.2, es necesario que la “cadena” del primer nombre del subscript sea igual a la “cadena” del segundo nombre del subscript. Los n´umeros 1 y 4 se corresponden a los l´ımites del rango que est´an definiendo. 1numericRange : 2(cadena1 - cadena4) Fragmento de c´odigo 7.2: Subscript Numeric Range Para comprobar que ambas cadenas de caracteres son iguales, fue necesario hacerlo desde el visitor de la regla, a partir de una expresi´on regular utilizando regex de Python. Se a˜nadi´o funcionalidad asociada al visitor de “numeric range”, que separa la cadena de ambos elementos del n´umero y se realiza un bucle desde el l´ımite inferior (determinado por el primer n´umero) hasta el l´ımite superior (determinado por el segundo n´umero) en el cual se a˜nade en cada iteraci´on una entrada formada por la cadena com´un y el n´umero de la iteraci´on al diccionario de subscripts. La definici´on de un subscript utilizando un rango num´erico simplemente es un atajo que Vensim proporciona a los programadores de modelos y no interfiere en la ejecuci´on del modelo, por lo que no se tuvo que hacer ning´un cambio relativo a la ejecuci´on. 100
CAP´ ITULO 7. DISE ˜ NO DE LAS MODIFICACIONES 7.3.2. Subscript copy La operaci´on de subscript copy tambi´en se explica en la Secci´on 3.2.2. Se trata de que dos subscripts tengan los mismos valores pero diferentes nombres. Se ha modificado la gram´atica component structure grammar, a˜nadiendo una regla que utilizase el s´ımbolo “<->” para definir un subscript copia de otro. En la clase correspondiente a esa gram´atica, ComponentParser, se ha creado un atributo nuevo al que se ha llamado subscript compatibility, un diccionario en el que se almacenan aquellos subscript que est´an copiados o mapeados. En el m´etodo visitor de la regla de subscript copy, se a˜nade una entrada al diccionario subscript compatibility con los nombres de los subscripts, indicando que son una copia. Cada elemento del modelo tiene asociado un diccionario de compatibilidad. En la funci´on translate section de vensim2py, despu´es de haber llamado a la funci´on que contiene la gram´atica component structure grammar, se unifica en un solo diccionario, llamado subs compatibility dict, todas las entradas que cada elemento contiene en su diccionario subscript compatibility. En el Fragmento de c´odigo 7.3, se presenta una operaci´on de copia de subscripts. El subscript ‘DimB’ no tiene ning´un subscript value asociado. Por esa raz´on y porque se encuentra enlazado con el subscript ‘DimA’, se toman los subscript values de ‘DimA’ (da1, da2, da3) y se duplican para formar parte, a su vez, de ‘DimB’. 1DimA : da1 , da2 , da3 2DimB <-> DimA Fragmento de c´odigo 7.3: Subscript Copy 7.3.3. Subscript mapping La implementaci´on de subscript copy y de subscript mapping son bastante similares, debido a que la funcionalidad de subscript mapping que se ha implementado es equivalente a utilizar un subscript copy. En el Fragmento de c´odigo 7.3 se ha presentado una sentencia de una copia de los subscripts DimA y DimB. En el Fragmento de c´odigo 7.4 se encuentra una sentencia equivalente a la copia de subscripts presentada, pero utilizando s´olo el mapeo (s´ımbolo ->) entre los dos subscripts. 1DimA : da1 , da2 , da3 -> DimB 2DimB : da1 , da2 , da3 -> DimA Fragmento de c´odigo 7.4: Subscript Mapping Se modific´o la gram´atica component structure grammar, a˜nadiendo las reglas necesarias para que se pudiera parsear el mapping de subscripts. En el m´etodo visitor asociado a esta 101
8.1. CONTRIBUIR EN PYSD sim se podr´ıa haber malentendido. Cabe destacar que en este punto, cuando una pull request est´a abierta, los commits que contiene ´esta no se a˜nadir´an al repositorio central hasta que el due˜no del repositorio o alguna otra persona autorizada para ello, cierre la pull request. Mientras la pull request est´e abierta, se pueden seguir a˜nadiendo commits a ella, los cuales pueden contener recomendaciones hechas por otros contribuidores del proyecto que mejoren los cambios realizados. Cuando se hayan resuelto las dudas o sugerencias, se cerrar´a la pull request en el caso de que el due˜no del proyecto lo crea conveniente. En PySD se tienen en cuenta algunos factores por cada pull request que se realiza. Al abrir la pull request se comienza autom´aticamente a compilar la documentaci´on del proyecto y posteriormente, la ejecuci´on de los tests utilizando para ello Travis-CI (Secci´on 5.2.9). Estos dos requisitos tienen que contar con un resultado satisfactorio para que se puedan a˜nadir los cambios. Al mismo tiempo que se est´an ejecutando los tests, se analiza la cobertura del c´odigo, calculando un porcentaje de cobertura de todo el c´odigo del proyecto teniendo en cuenta los cambios realizados. En el caso de que el porcentaje de cobertura disminuya un 1 % o m´as en comparaci´on con el porcentaje previo a la pull request, seguramente, sea necesario a˜nadir tests que prueben las l´ıneas de c´odigo agregadas para aumentar dicho porcentaje y que la pull request pueda ser mergeada al repositorio. En PySD, para poder a˜nadir nuevos tests se deben a˜nadir a los archivos que se encuentran en la carpeta “pysd/tests/”. Dichos tests pueden ser de integraci´on o unitarios y, en ocasiones, quiz´as sea necesario que hagan referencia a modelos Vensim para probar el correcto funcionamiento de traducci´on y ejecuci´on de PySD. Estos modelos referenciados se deber´an adjuntar al s´ubmodulo que contiene los modelos Vensim utilizados para los test, llamado test-models [62]. Para poder a˜nadir nuevos modelos Vensim al repositorio test-models es necesario realizar de nuevo el proceso para contribuir en un proyecto open source, comenzando por realizar un fork del proyecto para tener una copia del repositorio y desde ah´ı comenzar a a˜nadir los nuevos modelos Vensim. Se deber´a adjuntar el modelo Vensim (extensi´on mdl) y los resultados que se obtengan con Vensim en un archivo que se denomine “output”, para poder automatizar la comprobaci´on de ´estos contra los resultados que genera PySD. A mayores, se deber´a adjuntar una captura de pantalla del modelo en el entorno gr´afico Vensim y un README que explique brevemente lo que se intenta comprobar con ese modelo, en el que se haga referencia a la captura de pantalla y una tabla con datos sobre el contribuidor que ha a˜nadido ese modelo. Cuando se hayan realizado todos los pasos anteriormente descritos, se puede abrir una pull request en el repositorio test-models. Si ´esta es aceptada se podr´a a˜nadir entonces al repositorio PySD aquellos tests en los que se referencien los nuevos modelos Vensim a˜nadidos. Una vez que se haya cerrado la pull request, se puede continuar realizando m´as cambios en el proyecto de nuestro repositorio y creando pull requests cada vez que lo creamos conveniente en base a los cambios que vayamos realizando. De la misma forma, ser´a necesario actualizar nuestro repositorio en base a los cambios que se vayan haciendo en el repositorio central para que no haya conflictos futuros a la hora de realizar futuras modificaciones y/o mejoras. 108
CAP´ ITULO 8. IMPLEMENTACI ´ ON Y PRUEBAS DE LAS MODIFICACIONES 8.2. Tests en PySD Test Driven Development (TDD) [18] es una pr´actica iterativa de dise˜no de software orientado a objetos, presentada por Kent Beck yWard Cunningham como parte de la metodolog´ıa Extreme Programming. Principalmente esta t´ecnica se centra en la realizaci´on de las pruebas antes de escribir el c´odigo a probar. Al realizar los tests primero, se fuerza a pensar acerca de c´omo se desea que el c´odigo se comporte e interaccione con sus colaboradores. Una vez que el test se ha realizado, se escribe el c´odigo asociado. En PySD se destaca el uso de TDD, debido a que se conoce de antemano el comportamiento que se espera del sistema, ya que se cuenta previamente con los ejemplos de Vensim y los resultados que ´estos generan al ser ejecutados. Por esa raz´on, se parte sabiendo qu´e resultados se quiere que genere el sistema PySD, que son los mismos que se han obtenido al ejecutar los ejemplos con Vensim, dando cabida al desarrollo de software bajo TDD. En el repositorio de PySD se encuentra un directorio dedicado a los tests, en ´el se encuentran los tests unitarios y los tests de integraci´on. 8.2.1. Test unitarios Los test unitarios de PySD son aquellos que se encargan de probar una funcionalidad concreta del c´odigo. TDD implica desarrollar las pruebas unitarias a las que se va a someter el software antes de escribirlo, es decir, crear primero aquellos tests que prueben aisladamente la funcionalidad de cada m´odulo que compone el sistema. En el repositorio de PySD, los tests unitarios se encuentran en el directorio de “tests”. Este directorio cuenta con tantos archivos de tests unitarios como m´odulos hay en PySD. En Python, los tests unitarios se pueden realizar utilizando la librer´ıa unittest (Secci´on 5.2.7). En PySD los ficheros cuyo nombre comienza por “unit test” seguido de el nombre de un m´odulo, son aquellos que contienen los tests unitarios que prueban ese m´odulo. Para poder ejecutar estos tests se debe utilizar el comando representado en el Fragmento de C´odigo 8.1. Tras ejecutar el comando, se prueba uno de los m´odulos que componen PySD. Posteriormente, cuando el test haya finalizado, se informar´a por pantalla si el resultado esperado es igual al obtenido o si ha ocurrido alg´un error y d´onde se ha producido este. 1python -m unittest <nombre - test - unitario .py > Fragmento de c´odigo 8.1: Ejecutar test unitario 8.2.2. Test de integraci´on Una vez que se han realizado los tests unitarios necesarios, se deben realizar las pruebas de integraci´on. Estas pruebas se encargan de probar en conjunto el correcto funcionamiento 109
8.2. TESTS EN PYSD de los elementos unitarios que componen el sistema y de que la interacci´on entre ellos funcione adecuadamente. Los test de integraci´on de PySD se encuentran, al igual que los tests unitarios, en el directorio “test” de la carpeta “pysd”. Estos tests se identifican f´acilmente ya que su nombre comienza por “integration test”, seguido del nombre del subsistema que prueba, ya bien sea Vensim o XMILE. M´as concretamente, los test de integraci´on de Vensim se encuentran en el archivo llamado integration test vensim pathway.py, el cual contiene aquellos tests que se encargan de probar la traducci´on y ejecuci´on de modelos Vensim. Los modelos Vensim que se referencian en los tests de integraci´on de PySD, se encuentran en un subm´odulo Git, llamado test-models, explicado en detalle en la subsecci´on 8.2.3. En el archivo integration test vensim pathwat.py se hacen referencias a los modelos Vensim de test-models, los cuales se traducen, se ejecutan y se compara el resultado obtenido con el esperado. De esta forma, se permite comprobar si la interacci´on entre todos los m´odulos que componen el proyecto y el funcionamiento en conjunto generan el resultado esperado. Con el comando del Fragmento de C´odigo 8.2 se ejecutan los tests de integraci´on de PySD, utilizando para ello la librer´ıa nosetests (Secci´on 5.2.8). 1python -m nose <nombre - test - integracion .py > Fragmento de c´odigo 8.2: Ejecutar test de integraci´on Adem´as, en PySD se ha a˜nadido un Makefile que permite ejecutar todos los tests del proyecto autom´aticamente y generar un informe html sobre la cobertura del c´odigo. 8.2.3. Subm´odulo SDXorg/test-models Los subm´odulos [24] permiten mantener un repositorio de Git como subdirectorio de otro repositorio. De esta manera se consigue clonar otro repositorio en un proyecto manteniendo los commits separados pero siempre actualizados. En PySD, este subm´odulo se encuentra en el directorio de tests, se llama test-models y est´a redirigido al proyecto test-models [62]. Test-models contiene modelos Vensim con la salida que se espera de estos archivos. Est´a compuesto por dos directorios, test ysamples. El directorio de test contiene modelos funcionales en Vensim que cuentan con m´ınima funcionalidad, para poder probar funciones concretas. En el directorio samples encontramos modelos Vensim completos. Adem´as, cada ejemplo de modelo que forma este proyecto cuenta con una imagen que representa el modelo en el entorno gr´afico de Vensim, un archivo con extensi´on .csv o.tab que recoge los resultados que genera el modelo y, en algunos casos, cuenta con un modelo en Xmile id´entico al modelo presentado en Vensim. Aunque PySD utilice el proyecto test-models para probar la funcionalidad implementada, este proyecto se puede utilizar para cualquier otro que requiera modelos Vensim. 110
CAP´ ITULO 8. IMPLEMENTACI ´ ON Y PRUEBAS DE LAS MODIFICACIONES 8.3. Organizaci´on de la implementaci´on de las aportaciones Es posible acceder a todo el c´odigo relativo a los cambios comentados en la Secci´on 7. En los siguientes enlaces se pueden encontrar las diferentes pull request realizadas al repositorio central de PySD. Asimismo, se muestran las issues creadas y solventadas en cada pull request, la pull request realizada al repositorio de tests Vensim y se especifican los test creados o descomentados de los archivos de tests de pysd que permit´ıan comprobar los cambios realizados. Primera pull request Enlace: https://github.com/JamesPHoughton/pysd/pull/247 Cambios realizados: •Extensi´on de los modelos Vensim •Funci´on Random 0 1 •Documentaci´on Random uniform •Comentarios de sentencias en Vensim Issues abiertas para realizar esta pull request: •Issue 244, extensi´on de los modelos Vensim. Enlace: https://github.com/JamesPHoughton/pysd/issues/244 •Issue 245, soporte para la funci´on Random 0 1. Enlace: https://github.com/JamesPHoughton/pysd/issues/245 •Issue 246, fallo en comentarios de sentencias Vensim. Enlace: https://github.com/JamesPHoughton/pysd/issues/246 Issues solventadas: •Issue 244, extensi´on de los modelos Vensim. •Issue 245, soporte para la funci´on Random 0 1. •Issue 246, fallo en comentarios de sentencias Vensim. Pull request asociada en el repositorio test-models:https://github.com/SDXorg/ test-models/pull/69 En esta pull request se a˜naden a los tests de integraci´on dos tests: test run uppercase y test odd number quotes, que testean el correcto funcionamiento de pysd cuando se introduce un modelo Vensim cuya extensi´on est´a en may´usculas y un modelo Vensim que en un comentario de una sentencia Vensim tiene un n´umero impar de comillas, respectivamente. Para estos tests se utilizan los modelos Vensim teacup-upper.MDL yteacup 3quotes.mdl, que se 111
8.3. ORGANIZACI ´ ON DE LA IMPLEMENTACI ´ ON DE LAS APORTACIONES pueden encontrar en la pull request hecha en el repositorio de los tests. Tambi´en, se a˜nade un test que no es un archivo Vensim al repositorio pysd, llamado Not-Vensim.txt. Este archivo se utiliza en un test a˜nadido a los test unitarios del m´odulo pysd, para comprobar que el programa lanza una excepci´on cuando se introduce un fichero que no es un modelo Vensim. Segunda pull request Enlace: https://github.com/JamesPHoughton/pysd/pull/252 Cambios realizados: •Funci´on Sample If True •Soporte Subscript numeric range Issues abiertas para realizar esta pull request: •Issue 251, soporte para rango num´erico de subscripts. Enlace: https://github.com/JamesPHoughton/pysd/issues/251 Issues solventadas: •Issue 217, soporte para la funci´on Sample If True. Enlace: https://github.com/JamesPHoughton/pysd/issues/217 •Issue 251, soporte para rango num´erico de subscripts. Pull request asociada en el repositorio test-models:https://github.com/SDXorg/ test-models/pull/70 En esta segunda pull request se descomenta el test que comprueba el funcionamiento de Sample If True del archivo que contiene los tests de integraci´on de Vensim. Se a˜nade a los tests de integraci´on el test: test subscript numeric range, que testea el correcto funcionamiento de pysd cuando un modelo Vensim contiene una definici´on de un subscript a partir de un rango num´erico. Para este test se utiliza el modelo Vensim llamado test subscript numeric range.mdl que se ha a˜nadido a la pull request del repositorio de test models. Tercera pull request Enlace: https://github.com/JamesPHoughton/pysd/pull/260 Cambios realizados: •Soporte subscript copy •Soporte subscript mapping •Documentaci´on para desarrolladores Pull request asociada en el repositorio test-models:https://github.com/SDXorg/ test-models/pull/73 112
CAP´ ITULO 8. IMPLEMENTACI ´ ON Y PRUEBAS DE LAS MODIFICACIONES La documentaci´on para desarrolladores a˜nadida a la documentaci´on principal de PySD se encuentra en el siguiente enlace: https://pysd.readthedocs.io/en/master/development/pysd architecture vie ws/4+1view model.html Esta documentaci´on parte del modelo de vistas 4+1 sobre PySD desarrollado en la Secci´on 4.2. Este modelo tuvo que traducirse al ingl´es y convertirlo al formato rst (explicado en la Secci´on 5.2.11), ya que este formato es el que se utiliza para generar la documentaci´on asociada al proyecto PySD. Al realizar esta pull request, el colaborador Eneko Martin y el due˜no del proyecto, James Houghton, me dieron su enhorabuena por el trabajo realizado sobre la documentaci´on a˜nadida. Se muestra en las Figuras 8.1 y 8.2 las felicitaciones que ambos dejaron en los comentarios de esta pull request. A ellos se puede acceder a trav´es del enlace de la pull request. Figura 8.1: Respuesta Eneko Martin Figura 8.2: Respuesta James Houghton Para comprobar el correcto funcionamiento de las modificaciones a˜nadidas en esta tercera pull request se a˜nade a los tests de integraci´on el test test subscript copy que testea el correcto funcionamiento de pysd cuando en un modelo Vensim se utiliza la operaci´on de copia de subscripts, y el test test subscript mapping simple que comprueba el correcto funcionamiento de la l´ogica desarrollada para la operaci´on de subscript mapping. Para estos tests se utilizan los modelos Vensim llamados test subscript copy.mdl, que contiene una copia de subscripts, y test subscript mapping simple.mdl, que contiene un mapping de subscripts. Se pueden encontrar en la pull request asociada del repositorio de test models. 113
8.4. COMPROBACI ´ ON DEL OBJETIVO FUNDAMENTAL Adem´as, se han actualizado los tests unitarios del m´odulo vensim2py debido a la creaci´on del nuevo diccionario subs compatibility. Al finalizar la 3apull request, la cobertura del proyecto PySD obtenida con los modelos y tests a˜nadidos fue de 94.902 %. 8.4. Comprobaci´on del objetivo fundamental Tras todos los cambios realizados y a˜nadidos al repositorio central de PySD a trav´es de las 3 pull requests anteriormente comentadas, se ha comprobado la traducci´on del modelo WILIAM. La traducci´on de este modelo, como se ha comentado en la Secci´on 1.2, es el objetivo fundamental de este Trabajo Fin de Grado. As´ı que, una vez finalizadas todos las contribuciones que se han realizado al repositorio, se ha probado a traducir el modelo WILIAM con la versi´on actual de PySD. Al intentar traducir WILIAM se han encontrado varios errores de parseo debido a que a´un falta la implementaci´on de algunas funciones de Vensim en el proyecto PySD. Para poder probar el correcto funcionamiento de los cambios implementados, se han extra´ıdo las funciones que daban error del modelo, intercambi´andolas por constantes para que no generasen ning´un fallo. Adem´as, se han ido anotando todas las funciones que no tienen soporte en PySD y se ha abierto una issue en el repositorio por cada funci´on que falta. ´ Estas se han listado a continuaci´on, en la Secci´on 9.1, donde se describen las posibles l´ıneas de trabajo futuro. Despu´es de extraer las funciones que generaban error de parsing del modelo WILIAM, ´este se ha podido parsear perfectamente y se ha generado la traducci´on del mismo sin ning´un problema. 114
CAP´ ITULO 9. CONCLUSIONES Cap´ıtulo 9 Conclusiones Tras completar este Trabajo de Fin de Grado se ha obtenido un resultado muy satisfactorio y realmente enriquecedor. Se han cumplido los objetivos presentados inicialmente. Se ha logrado aportar funcionalidad nueva al repositorio de pysd, dotando al proyecto de caracter´ısticas que Vensim posee y que PySD no ten´ıa. Adem´as, se ha llegado a traducir el modelo WILIAM, utilizando para ello las nuevas funcionalidades desarrolladas y con la salvedad de las funciones enumeradas en la Secci´on 9.1. Se ha conseguido realizar un estudio exhaustivo de PySD y, a partir de ´el, se ha logrado evolucionar y mejorar la funcionalidad y documentaci´on con la que contaba previamente el proyecto de PySD. Este trabajo ha supuesto un gran aprendizaje para la alumna, pues ha significado: Conocer los sistemas din´amicos que existen, c´omo funcionan y c´omo pueden ser utilizados con fines realmente provechosos. En concreto, el lenguaje Vensim y algunas de sus funciones en las que se ha incidido en este proyecto. Mejorar los conocimientos sobre Python, obteniendo m´as soltura y destreza con el lenguaje, as´ı como con algunas de sus librer´ıas. Conocer la librer´ıa parsimonious en profundidad y su funcionamiento, junto al uso del patr´on Visitor. Comprobar la gran utilidad de la documentaci´on en proyectos software y la gran ayuda que ´esta puede aportar para futuros desarrolladores. Comprender en profundidad la librer´ıa PySD y su funcionamiento. Trabajar y aportar a un proyecto open source, lo que conlleva aprender c´omo hacerlo y bajo qu´e requisitos. Cabe destacar que ha sido de gran utilidad cuando colaboradores del proyecto daban su opini´on o suger´ıan ciertas mejoras en las pull request, aprendiendo de algunos conocimientos de los colaboradores. De la misma manera, era 115
9.1. L´ INEAS DE TRABAJO FUTURAS muy gratificante cuando resaltaban los cambios realizados y los a˜nad´ıan al repositorio principal. Finalmente, se ha logrado colaborar en un proyecto open source, junto a otros contributors. Se ha conseguido aportar nueva funcionalidad al proyecto y mejorar la gram´atica del mismo. Un trabajo fundamental ha sido la ingenier´ıa inversa realizada sobre PySD, que ha permitido obtener un buen nivel de conocimientos sobre el proyecto para poder realizar modificaciones y mejoras en ´el. Este proceso de ingenier´ıa inversa ha sido traducido y a˜nadido al repositorio principal, recibiendo felicitaciones por su aportaci´on y el trabajo realizado. 9.1. L´ıneas de trabajo futuras Si bien los objetivos de este trabajo est´an completos, pero se pueden hacer mejoras para continuar el proyecto de PySD y el de traducci´on y ejecuci´on de WILIAM. Ser´ıa un buen punto de partida mejorar o implementar algunas de las funcionalidades de Vensim en PySD con las que cuenta WILIAM, para poder llevar a cabo una perfecta traducci´on y ejecuci´on automatizada del citado modelo. Las funciones Vensim o palabras reservadas que se han encontrado en WILIAM y para las que, a d´ıa de hoy, PySD no tiene soporte, son: La funci´on GET TIME VALUE de Vensim. La funci´on INVERT MATRIX de Vensim. La funci´on ALLOCATE BY PRIORITY de Vensim. La funci´on VECTOR SELECT de Vensim. La funci´on FORECAST de Vensim. La funci´on SHIFT IF TRUE de Vensim. El uso de la palabra reservada :NA: en Vensim. Se ha abierto una lista de issues para indicar la necesidad sobre la implementaci´on de estas funciones en el Issue Tracker del proyecto PySD. Algunas de esas funciones no se encuentran en la lista de issues del proyecto, debido a que est´an indicadas como no implementadas en el c´odigo del mismo junto a un TODO. Adem´as, puede ser realemente interesante estudiar una posible mejora sobre la eficiencia del proyecto PySD. 116
AP´ ENDICE A. MANUALES Ap´endice A Manuales A.1. Manual de despliegue e instalaci´on En esta secci´on se detallan los pasos necesarios para instalar PySD. Se puede descargar el c´odigo fuente clonando el repositorio de GitHub, Fragmento de c´odigo A.1. 1git clone https :// github . com / marrobl / pysd . git Fragmento de c´odigo A.1: Descargar PySD Utilizando el instalador de paquetes pip se podr´a descargar la versi´on m´as reciente del paquete PySD, como se muestra en el Fragmento de c´odigo A.2. 1pip pysd Fragmento de c´odigo A.2: Descargar PySD Una vez descargado el paquete PySD, ser´a necesario actualizar e instalar las dependencias. Para ello, dentro del directorio pysd se ejecutar´a el comando de la Fragmento de c´odigo A.3. 1cd pysd 2python setup . py install Fragmento de c´odigo A.3: Instalar dependencias y PySD Si se ha realizado la descarga del paquete PySD con pip, las dependencias se deber´ıan haber instalado autom´aticamente, por lo que no ser´ıa necesario utilizar el ´ultimo comando presentado. 117
BIBLIOGRAF´ IA [44] Jos´e I. Santos Luis R. Izquierdo, Jos´e M. Gal´an and Ricardo del Olmo. Modelado de sistemas complejos mediante simulaci´on basada en agentes y mediante din´amica de sistemas. http://www.luis.izqui.org/papers/Izquierdo Galan Santos Olmo 200 8.pdf. Accessed: 2020-10-20. [45] Estefan´ıa Mac. F´ormulas de contabilidad b´asica: ¿c´omo calcular la depreciaci´on de una computadora? https://www.cuidatudinero.com/13074026/como-calcular-la-am ortizacion-de-una-computadora-portatil, Sep 2019. Accessed: 2021-02-03. [46] Robert C. Matin. Clean code, 2009. ed. Pearson Education, Inc. [47] MEDEAS. Modeling the renewable energy transition in europe. https://www.medeas .eu/. Accessed: 2020-09-20. [48] MEDEAS. Mooc course. https://www.medeas.eu/model/mooc-course. Accessed: 2020-09-20. [49] Microsoft. Visual studio code - code editing. redefined. https://code.visualstudio. com/, Apr 2016. Accessed: 2020-09-28. [50] Javier Olmo. ¿qu´e es la ingenier´ıa inversa y c´omo funciona? - blog de tecnicoo. https: //acentocoop.es/blog/ingenieria-inversa/, Sep 2020. Accessed: 2020-10-14. [51] Opensource.org. Open source news. https://opensource.org/. Accessed: 2020-10-10. [52] Visual Paradigm. The #1 development tool suite. https://www.visual-paradigm.co m/. Accessed: 2021-02-03. [53] Visual Paradigm. Visual paradigm pricing. https://www.visual-paradigm.com/shop /vp.jsp. Accessed: 2021-02-04. [54] Thomas Peham. Gitlab vs github: What are the key differences? the ultimate guide. https://usersnap.com/blog/gitlab-github/, Sep 2020. Accessed: 2020-10-11. [55] Jason Pellerin. Testing with nose¶.https://nose.readthedocs.io/en/latest/test ing.html. Accessed: 2021-05-26. [56] Refactoring.Guru. Decorator. https://refactoring.guru/es/design-patterns/de corator. Accessed: 2021-04-17. [57] reStructuredText Docutils. https://docutils.sourceforge.io/rst.html, May 2016. Accessed: 2021-05-27. [58] EOS Costa Rica. ¿por qu´e involucrarse en proyectos open source? https://medium.c om/@eoscostarica/https-medium-com-eoscostarica-por-que-involucrarse-enproyectos-open-source-80533e34408c, Jan 2020. Accessed: 2020-10-10. [59] rocket.chat. The ultimate communication platform. https://rocket.chat/es/. Accessed: 2020-09-14. [60] Diego Rodrigo Verdugo. Desarrollo de nuevas funcionalidades del software pysd para la traducci´on del modelo medeas de lenguaje vensim a python. http://uvadoc.uva.es/ handle/10324/44423, Jan 1970. Accessed: 2020-09-20. 124
BIBLIOGRAF´ IA [61] Ken Schwaber and Jeff Sutherland. La gu´ıa de scrum. https://scrumguides.org/do cs/scrumguide/v2016/2016-Scrum-Guide-Spanish.pdf. Accessed: 2021-06-12. [62] SDXorg. Sdxorg/test-models. https://github.com/SDXorg/test-models/tree/8fe 779fb9b84eb8426ddf3e4e7e1e796d180d636. Accessed: 2021-02-09. [63] Selectra. Precio del kwh de luz por horas. https://tarifaluzhora.es/. Accessed: 2021-02-11. [64] Fabio Mascarenhas Sergio Medeiros and Roberto Ierusalimschy. The packrat parsing and parsing expression grammars page. https://bford.info/packrat/. Accessed: 2021-02-02. [65] Ventana Systems. Random number functions. https://www.vensim.com/documenta tion/fn random.htm. Accessed: 2020-10-24. [66] GMBH TRAVIS CI. Travis ci. https://travis-ci.org/. Accessed: 2021-06-03. [67] Inform´atica UV. Mantenimiento. http://informatica.uv.es/iiguia/2000/IPI/ma terial/tema7.pdf. Accessed: 2020-10-17. [68] UVAgeeds. ¿qu´e es la din´amica de sistemas? https://geeds.es/que-es-la-dinamic a-de-sistemas/, Mar 2020. Accessed: 2020-10-20. [69] Ventana Systems Inc. Vensim. Vensim. https://vensim.com/. Accessed: 2020-10-24. [70] Inc. Ventana Systems. Vensim help. https://www.vensim.com/documentation/220 90.html. Accessed: 2021-04-19. [71] Inc. Ventana Systems. Vensim help. https://www.vensim.com/documentation/fn s ample if true.html. Accessed: 2021-04-05. [72] Inc. Ventana Systems. Vensim help. https://www.vensim.com/documentation/str eam id.html. Accessed: 2021-05-30. [73] w3sDesign. The gof design patterns memory - learning object-oriented design & programming. http://w3sdesign.com/?gr=s04&ugr=proble#gf, Oct 2017. Accessed: 2021-04-17. [74] XE.com. 19 usd to eur: Convert d´olares estadounidenses to euros. https://www.xe .com/es/currencyconverter/convert/?Amount=19&From=USD&To=EUR. Accessed: 2021-02-04. [75] XE.com. 40 usd to eur: Convert d´olares estadounidenses to euros. https://www.xe .com/es/currencyconverter/convert/?Amount=40&From=USD&To=EUR. Accessed: 2021-02-04. [76] XE.com. The worlds trusted currency authority: Money transfers & free exchange rate tools. https://www.xe.com/es/currencyconverter/convert/?Amount=1995&From= USD&To=EUR. Accessed: 2021-05-30. 125