Métodos Numéricos Apuntes sobre las utilidades de MATLAB más utilizadas durante el curso 14 de mayo del 2018 1 Índice 1. Fundamentos de MATLAB 1.1. Aspectos básicos . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 2. Operaciones básicas en MATLAB 2.1. Creación de matrices y vectores . . . . . . . . . . . . . . . . . . . 2.2. Operaciones básicas . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 5 3. Indexación de matrices. 8 4. Funciones especiales de MATLAB 4.1. Funciones especiales para matrices y vectores . 4.2. Funciones para creación de matrices especiales 4.3. Funciones de entrada y salida de datos . . . . . 4.4. Funciones de ayuda . . . . . . . . . . . . . . . . 4.5. Otras funciones especiales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 12 14 14 15 16 5. Polinomios en MATLAB 16 5.1. Representación de polinomios en MATLAB . . . . . . . . . . . . 16 5.2. Funciones especiales para polinomios . . . . . . . . . . . . . . . 16 6. Programación en MATLAB 6.1. Scripts . . . . . . . . . . . 6.2. Funciones . . . . . . . . . 6.3. Estructuras de control . . 6.3.1. La sentencia if . . 6.3.2. La sentencia for . . 6.3.3. La sentencia while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 18 20 24 24 26 28 7. Discretización y gráficos 28 7.1. Lo básico sobre Gráficos . . . . . . . . . . . . . . . . . . . . . . . 28 7.2. Un poco más de gráficos . . . . . . . . . . . . . . . . . . . . . . . 29 8. Consideraciones generales sobre errores 2 32 1. Fundamentos de MATLAB MATLAB (del inglés ”matrix laboratory”, laboratorio de matrices) es un entorno de programación principalmente orientado a la realización de cálculos numéricos a través de vectores y matrices utilizando un lenguaje de programación de alto nivel. Además de permitir una eficiente manipulación de matrices, MATLAB es capaz de realizar diversos tipos de gráficos de funciones y datos, implementación de algoritmos, creación de interfaces de usuario y puede proveer interfaz con programas escritos en otros lenguajes como Java, Python, C, C++ y Fortran. MATLAB es un lenguaje interpretado, es decir, que está diseñado para ser ejecutado por medio de un intérprete. Su ventaja principal es la simplicidad con la cual es posible escribir en su entorno diversos algoritmos en comparación con lenguajes de compilación tales como C++ o Fortran. La desventaja fundamental del MATLAB en el ámbito de la computación numérica es, al ser un lenguaje de interpretación, su baja velocidad de procesamiento de datos, en comparación a lenguajes de compilación. MATLAB es un producto de la empresa MathWorks, empresa que tiene un sitio web en el que ofrece una extensa y organizada documentación acerca de las funciones de MATLAB y que se recomienda consultar. 1.1. Aspectos básicos Al iniciar MATLAB, el usuario podrá observar una ventana similar a la que se muestra en la figura 1, con posibles variaciones del entorno dependiendo de la versión de MATLAB utilizada. Se puede observar que la ventana principal de MATLAB está compuesta, a su vez, de otras ventanas entre las cuales podemos destacar por su importancia: La ventana de comandos (command window). La ventana de espacio de trabajo (workspace). La ventana de directorio actual (current folder). La ventana de comandos es la ventana en la cual se ingresan todos los comandos a ser ejecutados por MATLAB. Para ello, basta con escribir los comandos a continuación del prompt (>>), la señal que indica que MATLAB está listo para recibir los comandos. La ventana de comandos es la ventana en la cual se ingresan todos los comandos a ser ejecutados por MATLAB. Para ello, basta con escribir los comandos a continuación del prompt (>>), la señal que indica que MATLAB está listo para recibir los comandos. A la izquierda de la ventana de comandos tenemos la ventana de directorio actual. El directorio actual o directorio activo es el primer sitio en el que MATLAB busca un fichero cuando se ordena su ejecución. Luego de esto, MATLAB procede a buscar el fichero o la función en el path, una lista ordenada de directorios que el usuario puede modificar. En esta ventana no sólo podemos visualizar los ficheros que se hallan en ella, también podemos ejecutarlos 3 Figura 1: Ventana principal de MATLAB haciendo doble clic en ellos. Para cambiar el path (la lista de directorios que consulta MATLAB cuando busca un archivo) se puede utilizar el comando pathtool. Abajo de la ventana de current folder tenemos la ventana de espacio de trabajo. La ventana de espacio de trabajo contiene información sobre las variables y las funciones que ha definido el usuario. Cada vez que se crea una nueva variable o se define una función, estas deben aparecer en la ventana de espacio de trabajo. El espacio de trabajo es especialmente útil para visualizar matrices de gran tamaño en detalle, algo que puede resultar incómodo en la ventana de comandos. Haciendo doble clic sobre las variables en el workspace, se puede visualizar su contenido en detalle e incluso editarlo. Haciendo doble clic sobre los comandos en la ventana de historial de comandos estos se vuelven a ejecutar. 4 2. 2.1. Operaciones básicas en MATLAB Creación de matrices y vectores Todo elemento definido en MATLAB es, en esencia, una matriz. Por ejemplo, un escalar es considerado como una matriz de dimensión 1 × 1, un vector fila es una matriz de dimensión n × 1 y un vector es una matriz de dimensión n × 1. Para asignar un valor a una variable, la asignación se realiza de derecha a izquierda. Por ejemplo, si deseamos asignar el valor 3 a la variable a, el comando a utilizar es: a = 3 o si deseamos asignar el valor de la variable b a la variable a, hacemos: a = b Para definir un vector fila en MATLAB y asignarlo a una variable, digamos A, basta con ejecutar el siguiente comando: A = [1 2 3] Nótese que las componentes están separadas entre sı́ mediante espacios. También es posible crear el mismo vector separando las componentes mediante comas, es decir, con el comando siguiente: A = [1,2,3] Para crear un vector columna, en lugar de los espacios o las comas se utiliza el punto y coma (;) como separador. Por ejemplo, para crear un vector columna con las mismas componentes de A se escribe lo siguiente: A = [1;2;3] Para crear una matriz en MATLAB se separan, al igual que en los casos anteriores, las columnas mediante espacios (o comas) y las filas mediante el separador punto y coma (;). El comando siguiente crea una matriz de dimensión 2 × 3. A = [1 2 3;4 5 6] 2.2. Operaciones básicas Operaciones de escalar con matriz MATLAB permite modificar todos los valores de una matriz utilizando un operador aritmético o una función. >> A=[1 2 3; 4 5 6] A = 5 1 4 2 5 3 6 12 15 13 16 >> A+10 ans = 11 14 >> sin(A+10) ans = -1.0000 0.9906 -0.5366 0.6503 0.4202 -0.2879 Una excepción a la regla se aplica con el operador de potenciación (ˆ). Mediante el comando A^2 no se eleva cada elemento de una matriz al cuadrado, sino se obtiene el cuadrado de la matriz A, es decir, A2 . En la sección “operaciones de elemento por elemento en matrices”, se verá cómo elevar cada elemenfto de una matriz a una potencia determinada. Operaciones entre matrices Seguidamente, procedemos a listar los operadores aritméticos principales para realizar operaciones entre matrices: Operador suma (+) : Para calcular la suma de dos matrices. Operador resta (-) : Para calcular la resta de dos matrices. Operador de multiplicación (*) : Para calcular el producto de dos matrices. Operador de división por la derecha (/) : Se utiliza entre dos matrices para multiplicar a una por la inversa de la otra por la derecha, o para dividir dos escalares. Operador división por la izquierda (\) : Se utiliza entre dos matrices para multiplicar a una por la inversa de otra por la izquierda. También funciona con escalares. Operador de potenciación (ˆ) : Se utiliza para elevar una matriz o un escalar a cierta potencia. 6 Operaciones de elemento por elemento en matrices Operador de multiplicación elemento a elemento (.*) : Calcula el producto de dos matrices elemento a elemento. Esto es, dadas dos matrices A = {aij } y B = {bij } de dimensión m × n, el comando C=A.*B tendrá por resultado una matriz C = {cij } de m × n, donde cij = aij × bij . Operador de división elemento a elemento (./) : Calcula la división elemento a elemento entre dos matrices. Esto es, dadas dos matrices A = {aij } y B = {bij } de dimensión m × n, el comando C=A./B tendrá por resultado una matriz C = {cij } de m × n, donde cij = aij /bij . Operador de potenciación elemento por elemento (.ˆ) : Se utiliza para elevar a una cierta potencia cada elemento de una matriz. Operaciones sobre matrices Operador de transposición (’) : Aplicado a una matriz, calcula su transpuesta conjugada. Operador de potenciación (ˆ) : Aplicado a una matriz, calcula una potencia determinada de una matriz. Operador de concatenación ([ ]) : Concatenar matrices es el proceso de juntarlas para obtener matrices más grandes. Los comandos siguientes permiten concatenar matrices de forma horizontal y de forma vertical. >> A=[1 2 3; 4 5 6; 7 8 9] A = 1 4 7 2 5 8 3 6 9 >> B=[10 10 10; 10 10 10; 10 10 10] B = 10 10 10 10 10 10 10 10 10 >> C=[A B] C = 1 2 3 10 10 7 10 4 7 5 8 6 9 2 5 8 10 10 10 3 6 9 10 10 10 10 10 10 10 10 10 >> D=[A;B] D = 1 4 7 10 10 10 3. Indexación de matrices. Existen ocasiones en las que es necesario acceder a elementos particulares de una matriz, ya sea para recuperar sus valores o para modificarlos. Por ejemplo, supongamos que definimos la matriz A = {aij }: >> A = [1 2 3;4 5 6;7 8 9] A = 1 4 7 2 5 8 3 6 9 Para recuperar el elemento de la fila i y la columna j se escribe el nombre de la matriz (en este caso A) y los ı́ndices entre paréntesis. Por ejemplo, observe el comando en MATLAB para recuperar el elemento a22 y el resultado correspondiente: >> A(2, 2) ans = 5 Algo similar ocurre con los vectores. Supongamos que definimos un vector v y deseamos obtener su cuarta y quinta componentes. En MATLAB hacemos. >> v = [2 3 4 5 6] v = 8 2 3 4 5 6 >> v(4) ans = 5 >> v(5) ans = 6 Además, recordemos que el vector v tal como y ha sido definido es en realidad una matriz de una fila y cinco columnas. Por lo tanto, también podemos referirnos a la cuarta y a la quinta componente de la forma siguiente: >> v(1, 4) ans = 5 >> v(1, 5) ans = 6 Algo que resulta muy interesante es que los ı́ndices utilizados también pueden ser vectores lo cual permite hacer referencia a varias componentes a la vez. Por ejemplo, supongamos que queremos conocer la primera, la tercera y la quinta componente a la vez. Para ello, podemos ejecutar el siguiente comando: v = 2 3 4 5 6 >> v(1, [1 3 5]) ans = 2 4 6 Observemos un ejemplo similar con matrices: >> M = [1 2 3;4 5 6;7 8 9] 9 M = 1 4 7 2 5 8 3 6 9 >> M(2, [2, 3]) ans = 5 6 El comando (2, [2,3]) extrae los elementos m22 y m23 . En este caso, como en el caso anterior, el segundo ı́ndice de M que utilizamos es un vector. ¿Qué pasarı́a si ambos ı́ndices de M son en realidad vectores? Lo averiguaremos a continuación: >> M M = 1 4 7 2 5 8 3 6 9 >> M([1, 2], [2, 3]) ans = 2 5 3 6 Probablemente el lector ya haya deducido que el efecto del comando M([1, 2], [2, 3]) es extraer parcialmente dos filas (la primera y la segunda). Más concretamente, el comando mencionado extrae las componentes dos y tres de la primera y segunda filas. Ahora supongamos que deseemos extraer completamente la segunda fila de la matriz M . Para ello, en lugar de colocar como segundo ı́ndice un vector enumerando todas las columnas que se quieren extraer, MATLAB permite simplemente colocar dos puntos (:). Observemos esto en el ejemplo siguiente: >> M M = 1 2 3 10 4 7 5 8 6 9 5 6 >> M(2, :) ans = 4 >> M(2, [1 2 3]) ans = 4 5 6 Los dos puntos también pueden utilizarse para extraer columnas completas. Modificar el valor de los elementos de una matriz es muy fácil una vez que hemos aprendido a recuperar sus valores. Por ejemplo, supongamos que deseamos modificar los valores de una matriz M . Observemos en el siguiente ejemplo cómo hacerlo: >> M = [1 2 3;4 5 6;7 8 9] M = 1 4 7 2 5 8 3 6 9 >> M(1, 1) = 0 M = 0 4 7 2 5 8 3 6 9 >> M(1, [2, 3]) = [17, 22] M = 0 4 7 17 5 8 22 6 9 >> M(2, :) = [1 1 1] 11 M = 0 1 7 17 1 8 22 1 9 Es importante destacar que cuando se accedió a más de una componente a la vez, se utilizaron vectores para hacer las asignaciones. 4. 4.1. Funciones especiales de MATLAB Funciones especiales para matrices y vectores En este apartado veremos algunas funciones aplicadas a matrices y/o vectores que resultarán útiles a lo largo del curso. Función min(v) : Aplicada a un vector retorna dos valores: el valor de la componente mı́nima y la posición de dicha componente. >> v = [11 12 13 10 15 8] v = 11 12 13 10 15 8 >> [componente pos] = min(v) componente = 8 pos = 6 Función max(v) : De manera similar a la función min, retorna el valor de la componente máxima de un vector y la posición de dicha componente dentro del vector. Función sum(v) : Suma todos los elementos de un vector. >> v = [1 2 3 4 5 6] v = 12 1 2 3 4 5 6 >> sum(v) ans = 21 Función prod(v): De forma similar a sum(v), aplicada a un vector, retorna el producto de todas sus componentes. Función length(v) : Aplicada a un vector, retorna las dimensiones de la matriz. Función size(M): Aplicada a una matriz, retorna las dimensiones de la matriz. >> M = [1 2 3;4 5 6] M = 1 4 2 5 3 6 >> [filas, columnas] = size(M) filas = 2 columnas = 3 Función det(M) : Calcula el determinante de una matriz. M = 1 3 2 4 >> det(M) ans = 13 -2 Función inv(M) : Calcula la inversa de una matriz. >> M M = 1 3 2 4 >> inv(M) ans = -2.0000 1.5000 4.2. 1.0000 -0.5000 Funciones para creación de matrices especiales A lo largo del curso, frecuentemente necesitaremos utilizar matrices especiales tales como lo matriz identidad o una matriz de ceros. Si bien crear tales matrices no presenta ninguna dificultad, debido a la frecuencia con la que se necesitan, MATLAB tiene funciones incorporadas para crearlas. En este breve apartado veremos algunas de ellas: Función eyes(m,n) : Crea una matriz de m filas y n columnas con unos en la diagonal y todos los demás elementos nulos. Esta función es muy usada para crear la matriz identidad. Función zeros(m,n) : Crea una matriz de m filas y n columnas en la que todos los elementos son nulos. Función ones(m,n) : Crea una matriz de m filas y n columnas en la que todos los elementos son uno. Función diag(v) : Crea una matriz diagonal donde las componentes de la diagonal principal son las componentes del vector v. 4.3. Funciones de entrada y salida de datos A lo largo del curso escribiremos muchos programas que en algún punto necesitarán comunicarse con el usuario, ya sea para recibir los datos de un problema en tiempo de ejecución, o bien, para desplegar los resultados obtenidos. Para cumplir este propósito MATLAB dispone, entre otras, de las siguientes funciones básicas: 14 Función display() : Recibe una cadena de caracteres entre comillas simples o bien, una variable. Cuando el programa llega al punto de ejecución en el que se encuentra la función display, despliega en pantalla el argumento ingresado. Función input() : Se utiliza para desplegar un mensaje y pedir al usuario el ingreso de una variable. >> n = input(’Ingrese el valor de n: ’) Ingrese el valor de n: 22 n = 22 4.4. Funciones de ayuda Debido al gran número de funciones especiales que posee MATLAB, es frecuente que a veces tengamos dificultades para recordar algunas, o bien, a veces deseamos saber más sobre el funcionamiento de alguna función en particular. Para resolver dichas cuestiones MATLAB posee, entre otras, las siguientes alternativas: Función help : Se utiliza para obtener más información sobre alguna función especı́fica. Por ejemplo, supongamos que queremos saber más acerca de la función det. Observe cómo se usa la función help y cuál es el resultado obtenido: >> help det det - Matrix determinant This MATLAB function returns the determinant of square matrix A. d = det(A) Reference page for det See also cond, condest, inv, lu, mldivide, rcond, rref Other uses of det symbolic/det Vemos que al teclear det a continuación de help y presionar enter en la ventana de comandos, MATLAB nos proporciona información acerca de qué hace la función y cómo se utiliza. Además, MATLAB nos indica con un hipervı́nculo dónde conseguir más información acerca de ella y nos sugiere que busquemos información sobre funciones relacionadas. 15 Función lookfor: Esta función se utiliza cuando en lugar de buscar una función conocida, buscamos saber qué funciones podrı́an estar relacionadas con cierta tarea. Por ejemplo, supongamos que no sabemos cuál es la función que halla el determinante de una matriz. Entonces usamos lookfor para solicitar información sobre todas las funciones que contengan la palabra “determinant” en su contenido de la siguiente forma: >> lookfor determinant det - Determinant. Vemos que MATLAB nos indica que la función det contiene dentro de su definición la palabra “determinant”, por lo cual podrı́amos correctamente deducir que det es la función que debe usarse en MATLAB para calcular el determinante de una matriz. 4.5. Otras funciones especiales En este apartado, se presentarán algunas funciones adicionales que facilitan el trabajo con MATLAB: Función clear : Permite borrar todos los comandos ejecutados en la pantalla en la ventana de comandos (los comandos igualmente quedan registrados en el historial de comandos). Función clc : Permite borrar todas las variables del espacio de trabajo y de la memoria del computador. Si se desea borrar una variable particular, se ejecuta el comando y seguidamente se escribe el nombre de la variable que se desea borrar. 5. 5.1. Polinomios en MATLAB Representación de polinomios en MATLAB En MATLAB los polinomios se representan mediante vectores. Dado un vector cualquiera definido en MATLAB, este puede ser considerado como un polinomio donde cada componente está asociada a un coeficiente polinomial, empezando por el coeficiente de mayor grado. El polinomio P (x) = 2x2 + 3x + 1 es representado mediante el vector P = [2, 3, 1]. La primera componente del vector es el coeficiente polinomial de mayor grado y la última componente es el término independiente. El número de componentes del vector determina el grado del polinomio. Para un vector de n componentes, su polinomio asociado será de grado n − 1 5.2. Funciones especiales para polinomios MATLAB posee funciones muy útiles para manipular polinomios. A continuación, veremos algunas de las funciones útiles para analizarlos. 16 Función roots(polinomio) : Aplicada a un polinomio, retorna un vector con sus raı́ces. >> P=[2 3 1] P = 2 3 1 >> roots(P) ans = -1.0000 -0.5000 Función polyval(polinomio, x) : Aplicada a un polinomio y a un vector de valores retorna el resultado de evaluar todos los valores de ese vector en el polinomio. >> vp vp = 2 3 1 >> polyval(vp, [1 2 3 4 5]) ans = 6 15 28 45 66 Función poly(v) : Dado un conjunto de valores en forma de vector, genera un polinomio que tenga como raı́ces ese conjunto de valores. Función conv(p1, p2) : Calcula el producto de dos polinomios. >> polinomio = [1 1] polinomio = 1 1 >> polinomio_cuadrado = conv(polinomio, polinomio) 17 polinomio_cuadrado = 1 6. 6.1. 2 1 Programación en MATLAB Scripts Un script o fichero de comandos no es más que un archivo que contiene un conjunto de comandos escritos en él que se ejecutan sucesivamente una vez que el script es llamado. Para editar un script se puede utilizar cualquier editor de textos para escribir los comandos, no obstante, MATLAB posee su propio editor de scripts. Para crear un script en MATLAB, basta con hacer click en New Script (el menú contextual puede variar un poco según la versión de MATLAB utilizada, por ejemplo, en la versión 2010 probablemente el usuario deba clickar en File y luego en New Script). Se desplegará entonces una ventana parecida a la que se observa en la figura 2. Figura 2: Editor de MATLAB En un script, los comandos se escriben de forma sucesiva tal y como se escribirı́an en la ventana de comandos y se ejecutan en el orden en el que aparecen. Consideremos un ejemplo simple. Supongamos que deseamos escribir un programa que calcule el área de un cuadrado. Para ello, le pedimos al usuario que 18 ingrese el valor del lado del cuadrado y posteriormente desplegamos el resultado. Una forma de hacer esto es con el siguiente script: % Ejemplo. Calcular el area de un cuadrado conociendo el valor del lado. clear lado = input(’Ingrese el valor del lado del cuadrado : ’); display(’El area del cuadrado es’) area = lado * lado Observe que la primera lı́nea del ejemplo comienza con un sı́mbolo de porcentaje ( %), con lo cual todo lo seguido es considerado como comentario por el intérprete de MATLAB y, por lo tanto, no es ejecutado. El punto y coma (;) al final de una lı́nea indica a MATLAB que deseamos que ejecute un comando pero sin mostrarnos el resultado inmediato, es decir, no se imprimirá el resultado de dicha asignación en pantalla. Para ejecutar un script, este debe guardarse en el directorio activo de MATLAB. Al guardarse un script se crea un archivo de extensión .m. Si el script no se encuentra guardado en el directorio activo de MATLAB, se entregará por resultado un error en el momento de su ejecución. Una vez que el script haya sido guardado en una ubicación adecuada, para ejecutarlo basta con introducir el nombre del script en la lı́nea de comandos. Ahora, veremos como se ve la ventana de comandos una vez que se ejecuta el script. Recordemos que lo primero que debemos hacer es escribir el nombre con el que se guardó el archivo (en este caso, areacuad ). Ası́ es como se ve el proceso en la ventana de comandos: >> area_cuad Ingrese el valor del lado del cuadrado: 12 El area del cuadrado es: area = 144 Consideremos a continuación otro ejemplo simple. Supongamos que queremos hacer una rutina para calcular la suma, la resta y el producto de dos matrices A y B. Para ello, utilizamos el siguiente script: % Ejemplo: Calcular la suma, la resta y el producto de dos matrices A y B. A = input(’Ingrese la matriz A: ’); B = input(’Ingrese la matriz B: ’); display(’La suma de las matrices es: ’) suma = A+B display(’La diferencia de las matrices es:’) 19 diferencia = A-B display(’El producto de las matrices es:’) producto = A*B Si guardamos el archivo como sumresprod, entonces podemos utilizar el script desde la ventana de comandos de la siguiente forma: >> sumresprod Ingrese la matriz A: [1 2;3 4] Ingrese la matriz B: [1 1;1 1] La suma de las matrices es: suma = 2 4 3 5 La diferencia de las matrices es: diferencia = 0 2 1 3 El producto de las matrices es: producto = 3 7 6.2. 3 7 Funciones Las funciones son también ficheros de comandos, en el sentido de que son un conjunto de comandos que se almacena en un fichero. Sin embargo, difieren de los scripts en un aspecto fundamental: las funciones tienen su propio espacio de trabajo, lo cual quiere decir que las variables que se definen dentro de una función solamente tienen uso dentro de la función. Es por esto que, a diferencia de los scripts, el hecho de que exista una variable con el mismo nombre previamente definida por otra rutina no afectará a la función. Las funciones también se almacenan en ficheros de extensión .m al igual que los scripts y sus comandos se escriben de la misma forma que se escribirı́an en un script, no obstante, las funciones se diferencian de los scripts en que siempre empiezan por la lı́nea: function [arg_retorno] = nombre_funcion(arg_entrada) A continuación, explicaremos los componentes de esta lı́nea: 20 function : Es una palabra reservada de MATLAB y con ella indicamos que vamos a definir una función. [argumentos retorno] : Entre corchetes se colocan los nombres de todas las variables que debe retornar la función. Si sólo se retornará una variable no es necesario incluir los corchetes. nombre funcion : Es el nombre con que se llamará a la función. En este punto tenemos que hacer una observación importante, a saber: nombre funcion debe coincidir exactamente con el nombre con el cual se guarda el archivo para poder llamar a la función en la ventana de comandos usando nombre funcion. argumentos entrada : Son los nombres de las variables que la función tendrá como parámetros de entrada. En MATLAB los parámetros se pasan por valor, al igual en que C. Esto quiere decir que cuando se llama a una función para actuar sobre una variable, la función trabaja con una copia del valor de la variable y no con la variable en sı́. Veamos dos ejemplos sencillos. En particular, veamos los ejemplos analizados en la sección de scripts pero realizados con funciones. Supongamos entonces que queremos crear una función que calcule el área de un cuadrado dado el lado del cuadrado. Para ello, creamos la siguiente función: function [ area ] = farea_cuad( lado ) % farea_cuad Calcula el area de un cuadrado dado el lado area = lado * lado; end Luego de crear la función, podemos ejecutarla desde la ventana de comandos para calcular el área de un cuadrado de lado 5: >> Area = farea_cuad(5) Area = 25 Ahora, creemos una función para realizar la suma, la resta y el producto de dos matrices A y B. Esta función tendrá entonces dos parámetros de entrada (las matrices A y B) y tres parámetros de salida (la suma, la resta y el producto) de las matrices ingresadas. Observemos el código de la función que realiza esto: function [ suma, resta, producto ] = fsumresprod( A, B ) % fsumresprod: Retorna la suma, la resta y el producto de dos matrices A y B. suma = A + B; resta = A - B; producto = A * B; end 21 Cuando una función tiene más de un argumento de retorno hay que indicarle a MATLAB de manera explı́cita que deseamos obtener todos esos argumentos al ejecutar la función, y no sólo el primero. >> A = [1 2; 3 4] A = 1 3 2 4 >> B = [2 2;2 2] B = 2 2 2 2 >> [suma, resta, producto] = fsumresprod(A, B) suma = 3 5 4 6 resta = -1 1 0 2 producto = 6 14 6 14 Cuando escribimos [suma, resta, producto] = fsumresprod(A, B) estamos indicando a MATLAB que queremos recuperar los tres argumentos de retorno y almacenarlos en las variables suma, resta y producto. Supongamos que deseamos crear una función simple que podrı́a definirse en una sola lı́nea. En vez de crear un archivo para dicha función, MATLAB nos ofrece la opción de definirla en el momento en que la necesitamos sin crear un archivo distinto para ella. A lo largo del curso haremos esto con mucha frecuencia y para ello, usaremos las siguientes dos opciones: Funciones inline: El comando inline permite definir una función a partir de una cadena de caracteres. Por ejemplo, 22 >> Sa = inline(’sin(x)/x’,’x’) Sa = Inline function: Sa(x) = sin(x)/x >> Sa(pi) ans = 3.898171832519376e-17 Observe que la función inline tiene dos argumentos. El primer argumento es la función en sı́, el segundo argumento es la variable de la función. La función inline también permite definir funciones con más de un argumento de entrada. Por ejemplo, >> areatriangulo = inline(’0.5*b*h’, ’b’,’h’) areatriangulo = Inline function: areatriangulo(b,h) = 0.5*b*h >> areatriangulo(3,5) ans = 7.5000 Es importante destacar que el orden en que damos los argumentos a la función inline deberá ser siempre el orden en el que le pasemos los argumentos a la función que creamos. Funciones handle: Las funciones handle pueden crearse de forma similar a las funciones inline. Para ello, se utiliza el sı́mbolo @. Por ejemplo, >> Sa = @(x)(sin(x)/x) Sa = @(x)(sin(x)/x) >> Sa(pi) 23 ans = 3.898171832519376e-17 En la declaración de las funciones handle, lo que está en el primer par de paréntesis son los argumentos de la función que deseamos crear (en este caso solo x) mientras que en el segundo par de paréntesis está la función que se desea crear. También podemos crear una función de más de una variable, análogamente al ejemplo de función inline, de la siguiente forma: areatriangulo = @(b,h)(0.5*b*h) areatriangulo = @(b,h)(0.5*b*h) >> areatriangulo(3,5) ans = 7.5000 6.3. Estructuras de control Las funciones que hemos aprendido a crear hasta ahora son muy simples. Supongamos ahora que deseamos realizar programas que realicen operaciones más complejas, en las que necesitamos modificar el flujo de ejecución de las instruciones. Para ello, recurrimos a las estructuras de control. 6.3.1. La sentencia if La sentencia if, como sugiere su nombre, nos permite indicar a MATLAB que realice un conjunto de instrucciones sólo si se cumplen ciertas condiciones. En general, la sintaxis para la sentencia if es la siguiente: if (condiciones que deben cumplirse) sentencias a ejecutar end Los paréntesis que encierran a la evaluación de las condiciones que deben cumplirse no son realmente necesarios, pero se pueden poner si se desean. Para crear estructuras de selección más complejas, es posible usar las sentencias elseif y else en conjunto con la sentencia if. Para ello, la sintaxis general es la siguiente: if (condiciones 1) 24 instrucciones 1 elseif (condiciones 2) instrucciones 2 elseif (condiciones 3) instrucciones 3 else instrucciones 4 end Como probablemente el lector intuya a esta altura, la diferencia entre las sentencias elseif y else es que el bloque de instrucciones correspondiente a la sentencia elseif se ejecuta si las condiciones anteriores no se cumplieron y si además se cumple cierta condición adicional. Por otro lado, el bloque de instrucciones correspondiente a la sentencia else se ejecuta directamente si las condiciones anteriores no se cumplieron sin necesidad de que se cumpla alguna condición adicional. Para ilustrar con más claridad el uso de las sentencias if, elseif y else obsérvese la siguiente función de ejemplo: 1 2 function [ ] = analizar a (a) % a n a l i z a r a : a n a l i z a l a v a r i a b l e a para i l u s t r a r e l uso de l a s s e n t e n c i a s de d e c i s i o n . 3 4 5 6 7 8 9 10 11 12 i f ( a ˜= 3 ) d i s p ( ’ La v a r i a b l e a e s d i s t i n t a de 3 ’ ) e l s e i f ( a == 3 ) d i s p ( ’ La v a r i a b l e a e s i g u a l a 3 ’ ) e l s e i f ( a < 4) d i s p ( ’ La v a r i a b l e a e s menor a 4 ’ ) else d i s p ( ’ La v a r i a b l e a e s l a v a r i a b l e a . D e j a l a s e r . ’ ) end Recuerde que la función anterior debe guardarse en un archivo de extensión .m con el mismo nombre de la función. // Seguidamente, llamamos a la función creada desde la ventana de comandos de la siguiente forma y obtenemos los resultados que se muestran: >> a n a a ( 3 ) La v a r i a b l e a e s i g u a l a 3 Observe que a pesar de que la variable ingresada cumple con las condiciones de la lı́nea 4 y de la lı́nea 8 sólo se ejecutan las instrucciones autorizadas por la lı́nea 8, esto es, no se imprime ’La variable a es menor a cuatro’. ¿Puede el lector deducir por qué ocurre esto? 25 6.3.2. La sentencia for Como mencionamos previamente, es posible que exista la necesidad de ejecutar un conjunto de instrucciones varias veces. Para ello existen las estructuras de iteración o de repetición. En particular, la sentencia for se utiliza cuando se desea que se repita la ejecución de un conjunto de instrucciones (denominado bucle) un número exacto de veces. La sintaxis general para el uso de la sentencia for es la siguiente: for i = vector de valores bucle de sentencias; end Donde vector de valores es un vector con n componentes. El conjunto de instrucciones bucle de sentencias se ejecutará entonces n veces (una vez por cada componente de vector de valores) y en cada iteración la variable de control i tomará el valor de una de las componentes de vector de valores. No obstante, la forma más utilizada de la sentencia for es la siguiente: for i = 1:n bucle de sentencias; end En la que queda claro que simplemente se busca repetir n veces la ejecución del bucle de sentencias. Ahora, veamos algunos ejemplos. Supongamos que queremos hacer una función que reciba un vector v y nos diga cuál es el valor de la componente más pequeña y la posición de ella dentro del vector (como la función min() de MATLAB). Para ello, usamos el siguiente código: 1 2 3 4 5 6 7 8 9 10 11 12 f u n c t i o n [ v a l o r m i n , p o s i c i o n ] = mi min ( v ) % mi min ( ) Busca e l v a l o r minimo de un v e c t o r n = length (v) ; valor min = v (1) ; posicion = 1; for i = 2:n i f (v( i ) < valor min ) valor min = v( i ) ; posicion = i ; end end end En el código, la primera lı́nea es como siempre la necesaria para indicar a MATLAB que estamos escribiendo una función, cuáles serán sus parámetros de entrada y cuáles son los valores que esperamos recibir de la función. En las lı́neas 4 y 5 simplemente indicamos que antes de comenzar la búsqueda, el valor mı́nimo es el primer valor del vector. Luego, el for se programa para buscar desde la segunda componente si existe un valor menor al de la primera componente del vector. Note que el vector creado para la variable de control del valor va desde dos hasta n, ¿qué pasará entonces si el valor de n resulta ser menor a 26 2 (igual a 1)? Pues en ese caso el for simplemente no se ejecuta. Recuerde que para llamar a la función desde la ventana de comandos es necesario que el archivo.m se guarde en un directorio contenido en el path y con el mismo nombre de la función. Veamos ahora el resultado de llamar la función desde la ventana de comandos: >> [ v a l o r m i n , p o s i c i o n ] = mi min ( [ 4 3 2 3 4 ] ) valor min = 2 posicion = 3 A veces es necesario (o más claro) utilizar sentencias for en forma anidada. Un caso tı́pico es cuando se necesitan usar matrices y modificar de alguna manera las todas las componentes de manera individual. Por ejemplo, supongamos que deseamos crear una matriz V DM de orden n, a partir de un vector de n componentes v = [a1 , a2 , a3 , ..., an ] tal que la columna j-ésima de la matriz sea igual al vector v elevado a la potencia j − 1. Esto es, deseamos crear la matriz: 1 a1 a21 . . . an−1 1 n−1 1 a2 a22 . . . a2 n−1 2 VDM = 1 a3 a3 . . . a3 . .. .. .. .. . . . 1 an a2n . . . an−1 n Para hacer eso vamos a crear una función que reciba un vector v y a partir de él cree la matriz V DM . Observe el código de dicha función: 1 2 3 4 5 6 7 8 9 10 f u n c t i o n [ VDM] = matriz vandermonde ( v ) % matriz vandermonde Crea una m a t r i z de Vandermonde a p a r t i r d e l vector v . n = length (v) ; VDM = z e r o s ( n ) ; for i = 1:n f o r j =1:n VDM( i , j ) = v ( i ) ˆ ( j − 1 ) ; end end end Discutamos ahora el código del programa arriba escrito. En primer lugar se determina el tamaño del vector v para saber de qué orden va a ser la matriz construida, esto tiene lugar en la lı́nea 3. La lı́nea 4 define a la matriz V DM como una matriz de ceros de orden n. Ésta es la matriz sobre la cual vamos a trabajar y se define antes del for anidado para que no cambie constantemente de tamaño (lo cual perjudica la eficiencia del programa). Entre las lı́neas 5 y 9 se encuentran los dos bucles anidados. El primer for (el más externo) controla 27 la variación de filas mientras que el for más interno controla la variación de columnas. Ası́, para cada fila se calculan todas las componentes de esa fila y luego se procede a calcular las componentes de la siguiente fila. Observe el resultado de llamar a esta función en la lı́nea de comandos: >> matriz vandermonde ( [ 1 2 3 4 5 ] ) ans = 1 1 1 1 1 6.3.3. 1 2 3 4 5 1 4 9 16 25 1 8 27 64 125 1 16 81 256 625 La sentencia while Cuando se desea repetir un bucle hasta que se cumpla cierta condición pero no se conoce de antemano el número exacto de repeticiones se emplea la sentencia while. La sintaxis general de uso para esta sentencia es la siguiente: while( condiciones ) bucle de sentencias; end La sentencia while es de uso tı́pico en los cálculos de aproximaciones mediante métodos iterativos (algo que haremos muchı́simo durante el curso) ya que dichos procesos iterativos generalmente repiten un proceso hasta que se alcanza cierta condición de tolerancia. 7. 7.1. Discretización y gráficos Lo básico sobre gráficos Aunque a lo largo del curso trabajaremos siempre con funciones continuas y las funciones continuas están definidas en un conjunto infinito de valores las computadoras en realidad no pueden manejar un conjunto infinito de valores, debido a que su memoria es limitada. Por ello, lo que hacen los computadores para trabajar con funciones continuas en ciertas situaciones (por ejemplo, para graficarlas) es obtener un conjunto finito de muestras de la función. Generalmente, estas muestras se toman equiespaciadas a lo largo de cierto intervalo de la variable independiente. Es a este proceso de tomar un intervalo continuo y analizarlo mediante conjunto de muestras finito a lo que nos referiremos cuando usemos el término discretizar. Por ejemplo, supongamos que queremos graficar la función sin(x) en el intervalo [−4π, 4π]. Para ello, primero debemos discretizar la variable independiente para tomar muestras de un conjunto de valores de la función y graficarlos. Para ello, utilizamos los siguientes comandos: 28 1 0.8 0.6 0.4 0.2 0 -0.2 -0.4 -0.6 -0.8 -1 -15 -10 -5 0 5 10 15 Figura 3: Gráfico de sin(x), en el intervalo [−4π, 4π] >> x = -4*pi:0.001:4*pi; >> y = sin(x); Lo que hicimos fue evaluar la función sin(x) para los valores del vector x y una vez hecho esto, podemos utilizar el comando plot para graficar la función de la siguiente forma. >> plot(x, y) >> grid Observe que el comando plot recibe como argumentos dos vectores (aunque en realidad puede tener más argumentos opcionales). El primer vector se interpreta como el conjunto de abcisas de los puntos de la función a graficar, mientras que el segundo vector se interpreta como las ordenadas de dichos puntos. El comando plot, entonces, ubica esos puntos en un gráfico y por defecto, los une con lı́neas rectas. Si los puntos son tomados lo suficientemente cercanos entre sı́, entonces la función graficada parece a simple vista el gráfico de una curva suave. Por último, el comando grid sirve para desplegar una cuadrı́cula para poder seguir mejor los valores que toma la función. El resultado puede verse en la figura (3). 7.2. Un poco más de gráficos A veces, necesitamos un poco más que tan solo visualizar una función. Por ejemplo, supongamos necesitamos visualizar varias funciones a la vez (una situación bastante recurrente). En particular, supongamos que dichas funciones son sin(x), cos(x) y sin(1,5x) en el intervalo [−2π, 2π]. Si simplemente hacemos: 29 clear clc x = -2*pi:0.0001:2*pi; y1 = sin(x); y2 = cos(x); y3 = sin(1.5*x); plot(x, y1) plot(x, y2) plot(x, y3) El lector puede comprobar que solamente se visualizará el gráfico de tan(x). MATLAB elimina los gráficos anteriores, a no ser que haya una indicación explı́cita del programador para no hacerlo. Resolver este problema depende de lo que busquemos. Por ejemplo, si buscamos que las tres funciones se grafiquen en una misma ventana, podemos usar el código siguiente: clear clc x = -2*pi:0.0001:2*pi; y1 = sin(x); y2 = cos(x); y3 = sin(1.5*x); plot(x, y1) hold on plot(x, y2) plot(x, y3) legend(’sin(x)’, ’cos(x)’, ’sin(1.5*x)’) xlabel(’Valores de la abcisa’) ylabel(’Valores de la ordenada’) title(’Gráfico de ejemplo’) El comando clave de este código con respecto al anterior es hold on. Este comando indica a MATLAB que los gráficos que se realicen sobre la figura en la que se está trabajando deben ser persistentes, es decir, deben perdurar incluso aunque se grafiquen nuevas funciones. Esta opción puede desactivarse con el comando hold off. Los demás comandos nuevos sirven sencillamente para hacer más clara la gráfica. El comando legend() asigna los nombres que se le pasan (las tres cadenas de caracteres en este ejemplo) a los conjuntos de datos que se han graficado en la figura y crea una caja en donde se indica qué color y qué forma se utilizó para graficar cierto conjunto de datos (para entender mejor esto, observe la figura (4), resultante de los comandos anteriormente descriptos). El comanda xlabel() sirve para colocar un mensaje descriptivo en el el eje x, ylabel() sirve para lo propio pero con el eje y. El comando title() sirve para poner un tı́tulo general a la gráfica. Por último, también resulta frecuente la necesidad de realizar gráficas múltiples pero no todas en una misma ventana, sino que en ventanas distintas. El siguiente código muestra cómo puede realizarse esto: 30 Gráfico de ejemplo 1 sin(x) cos(x) sin(1.5*x) 0.8 Valores de la ordenada 0.6 0.4 0.2 0 -0.2 -0.4 -0.6 -0.8 -1 -8 -6 -4 -2 0 2 4 6 8 Valores de la abcisa Figura 4: Gráfico en el que se visualiza más de una función. clear clc x = -2*pi:0.0001:2*pi; y1 = sin(x); y2 = cos(x); y3 = sin(1.5*x); figure(1) plot(x, y1) grid figure(2) plot(x,y2) grid figure(3) plot(x,y3) grid Se deja como ejercicio al lector comprobar que efectivamente, cada comando figure(i) le indica a MATLAB que todos los gráficos que se realizan a continuación deben ubicarse en la figura i, hasta que haya una orden explı́cita de cambiar de figura. Como probablemente el lector ya sospeche, si no se indica la figura, MATLAB pone los gráficos por defecto en la figura 1. 31 8. Consideraciones generales sobre errores En muchos problemas de aplicación de ingenierı́a no es posible obtener la solución analı́tica o exacta; por lo tanto inevitablemente se cometen errores. Es por esta razón que el estudio de los errores que un método en particular comete es una parte fundamental de su comprensión y es por eso que al análisis de tales errores se le dedica al menos un capı́tulo en la mayorı́a de los libros sobre métodos numéricos. Al no conocerse las solución exacta del problema no es posible determinar con exactitud cuál es el error que se comete. En consecuencia, cuando se analiza el error que comete un método es necesario buscar una aproximación o estimación del mismo. A lo largo del curso veremos diferentes métodos numéricos y en cada caso analizaremos cuáles son los errores que se cometen al aplicarlos. En particular, a la hora de estudiar los métodos, nos referiremos fundamentalmente a dos tipos de errores: Errores de redondeo: Debidos a que el computador utiliza sólo una cantidad finita de dı́gitos para representar los números. Errores de truncamiento: Debidos a la diferencia existente entre la formulación matemática exacta del problema y las simplificaciones propias de una aproximación. Esta terminologı́a se originó en la sustitución de una función por uno de sus polinomios de Taylor truncado (algo que haremos con mucha frecuencia a lo largo del curso). 32