MASTER EN INGENIERÍA DEL HORMIGÓN MODELOS PREDICTIVOS Y DE OPTIMIZACIÓN DE ESTRUCTURAS DE HORMIGÓN Profesores: Víctor Yepes Piqueras, Julián Alcalá González PROGRAMACIÓN DE UN GENERADOR DE LISTAS DE NÚMEROS ALEATORIOS 1 Introducción Como ejercicio previo para familiarizarse con el manejo del FORTRAN 95, del entorno Plato IDE, y del compilador FTN95, se va a describir el proceso para hacer un pequeño programa capaz de generar aleatoriamente una lista de números al azar, y de escribirlos en un archivo. Para hacer este ejercicio se requiere haber instalado el compilador FTN95 de Silverfrost, y el entorno de desarrollo Plato IDE. Esta instalación se describe en otro documento. 2 Crear el proyecto Se abre el programa Plato IDE, apareciendo la ventana siguiente: Los programas de FORTRAN se escriben en archivos que son ASCII, es decir, son archivos que se pueden editar con cualquier editor de textos (el “bloc de notas” de Windows, por ejemplo). Para ser identificados como códigos fuente de FORTRAN, y facilitar su manipulación por los compiladores, estos archivos suelen manejar extensiones como .ftn, .f90 o .f95. Un programa de FORTRAN debe estar escrito en un archivo de este tipo. Puede suceder que el programa utilice subrutinas o funciones, que son pequeños programas subordinados a un programa principal. Estas subrutinas y funciones pueden estar escritas en archivos diferentes al que contiene el programa principal. El compilador se encarga de unir los archivos cuando genera el programa ejecutable (el .exe). Por eso, los programas se desarrollan en los denominados proyectos (project), que aglutinan todos los archivos y librerías que se han utilizado en el programa. El primer paso para escribir un programa es entonces crear un nuevo proyecto. Para ello se pincha en el menú superior: File > New Project. Aparece el siguiente cuadro: - En el apartado Project Type debe seleccionarse una aplicación FORTRAN (marcar FORTRAN application). - En el campo Name, indicar un nombre. En este caso, puede ser: harvest, el nombre del programa que vamos a crear, pero no tiene porqué coincidir. - En Location, hay que determinar una ubicación para el programa. Por ello, es conveniente haber creado previamente (puede hacerse ahora) una carpeta donde deseemos guardar el programa: Al aceptar, aparece un cuadro a la derecha de la pantalla. Es el Project Explorer, que si no aparece automáticamente puede activarse manualmente desde el menú seleccionando: View > Proyect Explorer El Project Explorer muestra el contenido del proyecto. Éste está formado por tres elementos: las carpetas Source files e Include files, y la de References. Las siguientes veces que vayamos a trabajar con este proyecto no habrá que crearlo, obviamente. Se abre bien desde el menú: Files > Open Project, o mejor Files > Recent Projects lo que abre una lista de los proyectos recientes con los que hemos trabajado, evitando tener que buscar la ruta en el disco duro. Los proyectos no se guardan manualmente nunca. Cada vez que el programa se compila, o cuando se cierra el Plato IDE, el contenido del proyecto es actualizado en el disco duro. Los archivos que formen parte del proyecto sí hay que guardarlos manualmente, como veremos más adelante. 3 Crear el archivo .f95 Ahora podemos empezar a hacer el programa dentro del proyecto. Para ello vamos a crear un archivo dentro del proyecto. En el Project Explorer se pincha sobre el proyecto, y con el botón secundario del ratón se nos muestra un menú desplegable: Debemos pulsar la opción: Add New Item, porque el archivo en el que vamos a empezar a programar no existe. Si existiese, habría que seleccionar la opción: Add Existing Items. Al pulsar aquella aparece el cuadro: Se selecciona la opción Free format FORTRAN file, se teclea un nombre, que puede ser el nombre del programa que se va a crear (aunque puede ser cualquier otro), y si se desea se especifica una ubicación diferente a la del proyecto, pero esto no es recomendable en principio. Al pulsar el cuadro Open aparecerá el archivo en blanco: Ahora puede comenzar a escribir el programa. 4 Escribir el programa A continuación se va a escribir el código fuente del programa. Todo lo que se indica a continuación debe ir quedando anotado en el archivo harvest.f95, que es el que está activo en la pantalla del Plato ID. Cualquier programa de FORTRAN debe comenzar con la palabra program, seguida del nombre del programa la palabra program es un comando de FORTRAN (indica que comienza un programa), y como tal, se escribe literalmente. Escriba, pues la primera línea del siguiente modo: program harvest Al hacerlo, observe que el editor utiliza diferentes fuentes a medida que va escribiendo. Por defecto, los comandos aparecen en letra normal y color negro. Si al terminar de escribir no toma ese formato es porque estará mal tecleado. El lenguaje FORTRAN no distingue mayúsculas o minúsculas, esto es, da igual escribir: program harvest, que Program Harvest, que PROGRAM HARVEST, o incluso que pRoGrAm HaRvEsT. Es decir, las mayúsculas o minúsculas son potestativas. Los programas de FORTRAN deben terminar con el comando end program, seguido del nombre. Vaya unas líneas hacia abajo y teclee el comando final: end program harvest Todo el programa (excepto las subrutinas y funciones) debe quedar contenido entre esas dos líneas de código. Tras el inicio del programa debe efectuarse la declaración de variables. Una variable es una posición de memoria en la que se almacenará un dato. Va identificada por un nombre, y aunque hay ciertas excepciones, cualquier palabra que contenga letras, números y la mayoría de signos tipográficos es correcta. Algunas excepciones son que no pueden tener espacios (sería más de una variable), y no pueden tomar el nombre de comandos, evidentemente. Existe la posibilidad de utilizar variables de diferentes tipos, y cuando la variable se declara, se define su tipo. Una vez declarada, la variable no puede modificar su tipo. Las que vamos a emplear habitualmente son: lógicas, números enteros, números reales y caracteres alfanuméricos (letras). Las variables lógicas son un tipo especial de variable que puede tomar dos valores únicamente: true o false. Además todas ellas pueden ser bien variables sencillas, o bien vectores o matrices de dos o más dimensiones. El programa que vamos a escribir operará del modo siguiente: se establecerá de antemano el número de valores aleatorios que se quiere generar. Se generarán tantos números aleatorios como se haya determinado en el paso anterior, pero a medida que aparecen esos valores se “escribirán” en un archivo al que podremos acceder posteriormente. Para operar de ese modo, el programa necesita definir al menos dos variables: una que contenga el valor aleatorio generado en cada paso, y otra para contar el número de valores que se van generando. Supongamos que denominamos ran a la primera, e i al contador. El comando que genera los números aleatorios proporciona un número real comprendido entre el 0,0 y el 1,0. Por eso, la variable ran debe ser definida como real. Para ello se escribe la instrucción siguiente en la segunda línea del editor: real ran El contador debe ser un número entero. Para definirlo escribimos a continuación la instrucción siguiente: integer i En la práctica el manejo de variables es diferente, porque es difícil prever de antemano cuantas y qué tipo de variables van a ser necesarias. A medida que se va desarrollando el programa se van estableciendo las variables, y se procede a su definición. El paso siguiente es “abrir” el archivo en el que vamos a escribir la lista de números. Cuando pretendemos que un programa de FORTRAN escriba datos en un archivo, o que los lea de un archivo existente, es necesario indicar cuál es ese archivo, como se llama, donde se ubica y lo que se va a hacer con él. Eso es así en cualquier programa de ordenador, y no solo en FORTRAN. La línea que debe teclearse ahora es la siguiente: open (UNIT=1,FILE="datos.txt", ACTION="write") De este modo se ha abierto el archivo denominado datos.txt asignándole el número de unidad 1, para escribir en él (ACTION=”write”). No podrán abrirse otros archivos ahora en la unidad 1 hasta que éste no se cierre, pero podrían abrirse archivos en las unidades 2, 3, etc. La unidad * es la pantalla del ordenador. Lo que se escribe en la unidad * aparecerá en la pantalla del ordenador. El nombre y extensión del archivo (datos.txt) es potestativo, aunque es muy práctico darle la extensión .txt, porque el sistema operativo identificará al archivo como de texto, y lo vinculará con el editor de textos de nuestro ordenador (típicamente el Bloc de Notas), lo que facilitará su apertura posteriormente. El archivo debe cerrarse antes de finalizar el programa. Para ello basta con escribir, inmediatamente antes del final, la instrucción: close (1) Entre la orden de apertura y la ce cierre el archivo permanece abierto, y será posible escribir en él. El siguiente paso es generar los números aleatorios y escribirlos en el archivo. En primer lugar, se define un valor obtenido aleatoriamente, y se almacena en la variable ran. Esto se consigue con la instrucción siguiente: call random_number(ran) El comando call ejecuta una subrutina, en este caso denominada random_number que en este caso esta programada en las librerías del compilador. Normalmente las subrutinas las haremos nosotros, pero en este caso no es así. Esta subrutina genera un número aleatorio y lo asigna a la variable del argumento (variable cuyo nombre se pone en el paréntesis). Este número está siempre dentro del intervalo 0,0 – 1,0, como se dijo anteriormente. La línea de código anterior hará que el ordenador genere un número aleatorio cuyo valor será asignado a la variable ran. EL paso siguiente es escribir el valor de la variable var en el archivo mediante la instrucción write, que escribimos a continuación de la anterior: write (1,*) ran Con ello se está diciendo al ordenador que el valor que tenga la variable ran debe ser escrito en la unidad 1, que es el número de unidad del archivo datos.txt. Pero claro, escrito así el programa lo va a hacer una sola vez, y nuestro propósito es que lo haga varias veces de forma consecutiva. Este tipo de procesos repetitivos que se ejecutan en sucesivas iteraciones se programan con los denominados bucles. Hay otras formas de definir bucles en FORTRAN, pero la más inmediata sería del modo siguiente: do i=1,1500 call random_number(ran) write (1,*) ran end do Así escrita se van a generar 1500 números aleatorios de forma consecutiva que se irán escribiendo en el archivo. Con todo ello, el programa completo, una vez ordenado para darle más claridad, queda como sigue: La cantidad de números a generar y escribir se controla por el límite del bucle. Si quiere más números solo tiene que cambiar la cifra de 1500 por la cantidad que desee. 5 Ejecución del programa Para ejecutar el programa éste debe ser compilado (build). Hay tres formas de hacerlo: 5.1 - Desde el propio entorno Plato IDE. - En modo interrupcción. - Ejecutando manualmente el programa. Ejecución desde el propio entorno. Este modo de ejecución es el típico cuando se está programando para verificar el funcionamiento del programa que estamos escribiendo. Se selecciona la opción Start Run en el Menú: Build > Start Run. También con la opción Start ( ) en la barra de herramientas. Esta barra suele estar activa por defecto, pero si no lo está puede activarse desde el menú en caso necesario (View > View Toolbar): Primero aparece un mensaje como el siguiente, que dura unos segundos (en las versiones con licencia normal este mensaje no aparece): Y a continuación se ejecuta el compilador y el nuestro programa. En la parte inferior de la pantalla hay un espacio denominado Output en el que se nos muestra información relativa al proceso de compilación, advertencias o errores en su caso. La ejecución del programa, al ser una aplicación de consola, y no una aplicación “visual”, se hace a través de la ventana del sistema. Cuando el programa termina se muestra el mensaje: Pulsando RETURN el programa ha terminado. Si se accede a la carpeta donde se almacena el proyecto se verá el archivo datos.txt, que se puede abrir. 5.2 Ejecución en modo interrupción. Cuando el programa se ha ejecutado puede verse el resultado de la ejecución, pero cuando se está programando se necesita verificar que los comandos, el resultado de operaciones, el valor de las variables, etc., se ejecutan de un modo correcto. El entorno Plato IDE permite una ejecución a través del depurador (debugger), en la que es posible, entre oras cosas, detener el programa en puntos de parada, ejecutar el programa línea a línea o visualizar el valor de las variables. Esta información es de gran utilidad para detectar anomalías en el funcionamiento de un programa. Se selecciona la opción Start Run en el menú: Build > Step Intro. También con la opción Continue debugging ( ) de la barra de herramientas. Este modo de ejecución se muestra en el depurador. Cuando se ejecuta éste se muestra en una ventana como la siguiente: Tras unos segundos aparece un mensaje avisando de que se está preparando el depurador, tras el cual se muestra el código preparado para su ejecución. Una vez preparado, puede ejecutarse el algoritmo línea a línea (tecla F8), introducir un punto de parada en una línea del código (tecla F2) y ejecutar hasta ella o hasta el final (tecla F6). Veamos un ejemplo. Una vez cargado el programa harvest en el depurador, en la ventana donde se muestra el código sitúe el cursor en la línea donde se abre el archivo de resultados, y pulse F2. La línea tomará este aspecto: Ahora se selecciona en el menú Run > Restart Program. Al hacerlo se reinicial el programa. Pulse Restart en la ventana que aparece: y sucederá que el programa se ejecuta hasta la línea donde hemos puesto el punto de parada. Ahora ésta quedará señalada en rojo, lo que indica que se ha interrumpido la ejecución en ese punto. A partir de ahora, cada vez que pulse F8 se ejecuta una línea de código. Hágalo, y observará como se inicial el bucle, se genera al número aleatorio, se escribe en el archivo, se vuelve al principio del bucle, etc. Si ahora pulsa F6 la ejecución vuelve a ser automática hasta que se encuentre otro punto de parada, o hasta que termine el programa. Simultáneamente a la ejecución se puede chequear el valor de las variables, comprobar las unidades abiertas o cerradas, etc. Cuando termine, puede salir del depurador simplemente cerrando la ventana. 5.3 Ejecutando manualmente el programa. Al compilar el programa se habrá creado un archivo ejecutable, en este caso llamado harvest.exe, en la carpeta *\CheckMate\Win32 que estará grbado donde se haya almacenado el proyecto. Para compilar el programa sin ejecutarlo se selecciona la opción Build en el menú: Build > Build. También esta disponible la opción en la barra de herramientas Build ( ). Para demostrar su funcionamiento podemos copiarlo a la ubicación que deseemos, y si se pulsa dos veces sobre él se ejecutará. Aparece entonces la ventana de ejecución (la negra), y el aviso de Silverfrost. A continuación el programa se ejecuta. Al finalizar la ventana desaparece (a menos que se haya producido algún error): En la ubicación en la que hayamos ejecutado el programa harvest.exe aparecerá ahora el archivo datos.txt. Pruebe a copiar el archivo a su escritorio y ejecutarlo para verificar su funcionamiento. NOTA FINAL: Observe que todas las veces que se ejecuta el programa, el archivo genera data.txt los mismos números. El porqué esto es así y como evitarlo se tratará en clase.