{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introducción a la Programación en MATLAB (C7)\n", "\n", "Mauricio Tejada\n", "\n", "ILADES - Universidad Alberto Hurtado\n", "\n", "Agosto 2017" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Contenidos\n", "\n", "- [Programar en Matlab](#7.-Programar-en-MATLAB)\n", " - [m-files](#7.1-m-files)\n", " - [funciones](#7.2-Funciones)\n", " - [Loops](#7.3-Loops)\n", " - [Condicionales y Operadores Lógicos](#7.4-Condicionales-y-Operadores-Lógicos)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. Programar en MATLAB" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.1 m-files\n", "\n", "Los *m-files* son archivos de texto donde guardamos una secuencia de comandos. Dichos archivos son guardados con extensión `.m` y pueden ser de dos tipos: \n", "\n", "- Los *Scripts* son útiles para automatizar un bloque de comandos. Los *Scripts* operan sobre datos existentes y crean nuevos datos a partir de las operaciones contenidas (y guardados en el espacio de trabajo). \n", "- Las *Funciones* son también m-files, pero que tienen el nombre de la función y ejecutan tareas específicas. Si están en el directorio de trabajo, se pueden utilizar como comandos de Matlab (built-in-functions).\n", "\n", "Los *m−files* (scripts y funciones) puede llevar comentarios, esto es bloques de texto que son ignorados por el compilador. Toda línea que empieza con signo de porcentaje (`%`) es considerada comentarios.\n", "\n", "Nota: En Funciones, las primeras líneas que llevan `%` son consideradas la documentación (help) de la función.\n", "\n", "Matlab tiene su propio editor de textos el mismo que cuenta con *highlighting* y opciones de *debbuging*.\n", "\n", "- `File/New/Script` Crea un nuevo m-file en el editor de Matlab.\n", "- `File/Save as ...` (elegir directorio de trabajo) Guarda el m-file en el directorio de trabajo.\n", "- `alt-cmd-R` (`F5`) Guarda y ejecuta el m-file que esté activo. MAC (WIN).\n", "- `fn-SHIFT-F7` (`F9`) Ejecuta un bloque de comandos del m-file que esté activo. MAC (WIN).\n", "- `Ctrl-C` Detiene la ejecución del m-file. MAC (WIN).\n", "\n", "Comentarios:\n", "1. Una vez que se crea un m-file se abre el editor de Matlab.\n", "2. El directorio de trabajo es donde se guardan las funciones que se se utilizaran en el programa que estén trabajando.\n", "3. Al ejecutar el m-file por primera vez, Matlab preguntará si se desea cambiar la carpeta actual donde está trabajando Matlab a la carpeta donde se encuentra el m-file. Acepte. (Esto ocurre sólo si no se cambió el directorio de trabajo previamente). " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.2 Funciones" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Las funciones son m-files que se guardan con el nombre de la función. \n", "\n", "- Las funciones ubicadas en el directorio de trabajo se pueden utilizar como funciones de Matlab. \n", "\n", "- Es una buena práctica dividir la tarea que queremos realizar con Matlab en tareas simples y asignar una función para cada tarea simple. \n", "\n", "- Son muy útiles para procedimiento repetidos. \n", "\n", "- Las distintas funciones se pueden llamar desde el script (m-file) principal." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La sintaxis de una función es:\n", "\n", "```\n", "function [output1, output2, ...] = nombre_funcion(input1, input2,...) \n", "% Comentario\n", "\n", "comandos\n", "\n", "end\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Ejemplo 1:** Crear un m-file con la función de nombre `fx` que evalúa un polinomio de grado 2 y guardarla en el directorio de trabajo.\n", "\n", "```\n", "function out = fx(x)\n", "% FX Evalúa un polinomio de segundo grado. Función aplica sólo a escalares.\n", "% Uso: \n", "% val = fx(x)\n", "\n", "out = 2*x^2 + 3*x - 5;\n", "\n", "end\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ans =\n", "\n", " '/Users/mauriciotejada/Dropbox/MT/Teaching/MAE - Matlab/Nootebooks'\n" ] } ], "source": [ "pwd" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f1 =\n", "\n", " 39\n", "\n", "\n", "f2 =\n", "\n", " 0\n" ] } ], "source": [ "f1 = fx(4)\n", "f2 = fx(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Ejemplo 2:** Crear un m-file con la función de nombre `stat`, que calcula la media y la desviación estándar de un vector, y guardarla en el directorio de trabajo.\n", "\n", "```\n", "function [mean, stdev] = stat(x)\n", "% STAT Calcula la media y la desviación estándar de un vector x.\n", "% uso:\n", "% [mean, stdev] = stat(x) \n", "\n", "n = length(x);\n", "mean = sum(x)/n;\n", "stdev = sqrt(sum(x.^2)/n - mean^2);\n", "\n", "end\n", "```" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "media =\n", "\n", " 50.4923\n", "\n", "\n", "desv =\n", "\n", " 4.6263\n" ] } ], "source": [ "xvec = 50+4*randn(100,1);\n", "\n", "[media, desv] = stat(xvec)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Funciones simples pueden crearse de manera anónima (sin un m-file). Hay dos opciones:\n", "\n", "- Usando el comando `inline`" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ans =\n", "\n", " cell\n", "\n", " 'x'\n", "\n", "\n", "ans =\n", "\n", " '2*x^2 + 3*x - 5'\n", "\n", "\n", "ans =\n", "\n", " 60\n" ] } ], "source": [ "fx2 = inline('2*x^2 + 3*x - 5');\n", "argnames(fx2)\n", "formula(fx2)\n", "\n", "\n", "fx2(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Usando el formato `@(input)`:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fx3 =\n", "\n", " function_handle with value:\n", "\n", " @(x)2*x^2+3*x-5\n", "\n", "\n", "out3 =\n", "\n", " 60\n" ] } ], "source": [ "fx3 = @(x) 2*x^2 + 3*x - 5\n", "\n", "out3 = fx3(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Nota Importante!!**\n", "\n", "- Las funciones creadas en un m-file cuentan únicamente con la información provista como `input` y todas las variables creadas al interior de la función son *variables locales* (esto es, sólo existen dentro de la función).\n", "- Los argumentos (inputs) de una función pueden contener strings, matrices, vectores, escalares, y funciones. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Ejemplo 3:** Crear un m-file con la función de nombre `fxalt` que evalúa un polinomio de grado 2 y guardarla en el directorio de trabajo.\n", "\n", "```\n", "function out = fxalt(params,x)\n", "% FX Evalúa un polinomio de segundo grado.\n", "% Uso: \n", "% val = fxalt(params,x)\n", "% params: vector 3 x 1 de parámetros.\n", "\n", "a = param(1);\n", "b = param(2);\n", "c = param(3);\n", "\n", "out = a*x^2 + b*x + c;\n", "\n", "end\n", "```" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "p =\n", "\n", " 3\n", " 3\n", " -5\n", "\n", "\n", "x =\n", "\n", " 4\n", "\n", " 55\n" ] } ], "source": [ "\n", "pa = 3;\n", "pb = 3;\n", "pc = -5;\n", "\n", "p = [pa; pb; pc]\n", "x = 4\n", "\n", "val = fxalt(p,x);\n", "disp(val)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Una forma de transformar la función `fxalt` para que sólo dependa del argumento `x` es usar una función anónima." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ans =\n", "\n", " 39\n" ] } ], "source": [ "pa = 2;\n", "pb = 3;\n", "pc = -5;\n", "\n", "p = [pa; pb; pc];\n", "\n", "fx4 = @(x) fxalt(p,x);\n", "\n", "fx4(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.3 Loops\n", "\n", "Los *Loops* son bucles que sirven para realizar operaciones de manera repetida. Existen dos tipos de Loops:\n", "\n", "- **For Loop:** Realiza la misma acción un número determinado de veces. Su sintaxis es como sigue:\n", "\n", "```\n", "for variable = expresión\n", "\n", " Comando 1 \n", " Comando 2\n", " Comando 3\n", " ...\n", "\n", "end\n", "```\n", "\n", " Ejemplo:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x =\n", "\n", " 0.7943\n", " 0.3112\n", " 0.5285\n", " 0.1656\n", " 0.6020\n", " 0.2630\n", "\n", "\n", "sumx =\n", "\n", " 0.7943\n", " 1.1055\n", " 1.6340\n", " 1.7997\n", " 2.4017\n", " 2.6646\n" ] } ], "source": [ "n = 6;\n", "x = rand(n,1)\n", "sumx = zeros(n, 1);\n", "sumx(1)= x(1); \n", "\n", "for i = 2:n\n", " sumx(i) = sumx(i-1)+x(i);\n", "end\n", "\n", "sumx" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "- **While Loop:** Realiza la misma acción hasta que una condición se cumpla.\n", "\n", "```\n", "while Condición\n", "\n", " Comando 1\n", " Comando 2\n", " Comando3\n", " ...\n", "end\n", "```\n", "\n", " Ejemplo:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.5000\n", "\n", " 0.2500\n", "\n", " 0.1250\n", "\n", " 0.0625\n", "\n", " 0.0312\n" ] } ], "source": [ "delta = 1;\n", "\n", "while (delta) > 0.05\n", " delta = delta/2;\n", " disp(delta);\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comentarios:\n", "\n", "- MATLAB es MUY ineficiente al utilizar loops. Es mucho más eficiente realizar la misma tarea con matrices (operaciones vectorizadas).\n", "- Un for loop puede comportarse de forma descendente: `for i=10:-1:1`.\n", "- Podemos anidar varios loops. Por ejemplo:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "H =\n", "\n", " 1.0000 0.5000\n", " 0.5000 0.3333\n", " 0.3333 0.2500\n" ] } ], "source": [ "m = 3;\n", "n = 2;\n", "H = zeros(m,n);\n", "\n", "for i = 1:m\n", " for j = 1:n \n", " H(i, j) = 1/(i+j-1);\n", " end\n", "end\n", "\n", "H" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Podemos utilizar un while loop como un for loop, sólo se necesita definir un contador. Por ejemplo:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "\n", " 2\n", "\n", " 3\n", "\n", " 4\n" ] } ], "source": [ "iter = 1;\n", "\n", "while iter < 5 \n", " disp(iter)\n", " iter = iter +1;\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Es posible usar el comando `pause` para introducir una pausa en cada iteración del Loop, el procedimiento continuará cuando cualquier tecla del teclado sea presionada. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 7.4 Condicionales y Operadores Lógicos\n", "\n", "Los condicionales sirven para ejecutar un comando si se cumple cierta condición. La sintaxis para condicionales es:\n", "\n", "```\n", "if condicion 1\n", " comando\n", "elseif condicion 2 \n", " comando\n", "elseif condicion 3 \n", " comando\n", "else\n", " comando\n", "end\n", "\n", "```\n", "\n", "Las condiciones son verificadas de manera secuencial. En cuando se cumple una condición, el comando `if` ya no continúa con las demás condiciones.\n", "\n", "Operadores lógicos:\n", "\n", "- `<` menor a\n", "- `>` mayor a\n", "- `<=` menor o igual a\n", "- `>=` mayor o igual a\n", "- `==` igual a\n", "- `~=` no es igual a\n", "- `|` o: verdadero si al menos una es verdadera (genera escalar o matriz)\n", "- `||` o: verdadero si al menos una es verdadera (genera escalar) \n", "- `&` y: verdadero si todas son verdaderas (genera escalar o matriz)\n", "- `&&` y: verdadero si todas son verdaderas (genera escalar) \n", "- `~` negativo\n", "- `any` verdadero si algún elemento es no nulo\n", "- `all` verdadero si todos los elementos no nulos\n", "- `find` encuentra índices de valor no nulos en una matriz\n", "- `isnan` detecta valores NaN en una matriz\n", "- `isempty` detecta si es una matriz vacía.\n", "\n", "Ejemplo:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n" ] } ], "source": [ "n = 0; \n", "\n", "if -1 > 0 \n", " n = 1;\n", "elseif 2 > 0 \n", " n = 2;\n", "elseif 3 > 0\n", " n = 3; \n", "else\n", " n = 4;\n", "end\n", "\n", "disp(n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Otro ejemplo:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A =\n", "\n", " 0.4900\n", "\n", "A es positivo\n" ] } ], "source": [ "A = randn(1)\n", "\n", "if A>0\n", " disp('A es positivo');\n", "elseif A==0\n", " disp('A es cero');\n", "else\n", " disp('A es negativo');\n", "end;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comentarios:\n", "\n", "- En un condicional es mejor utilizar `&&` y `||` para asegurarnos que la respuesta es un escalar. Si utilizamos `&` y `|` y la respuesta es una matriz, solamente si la condición se cumple para todos los elementos se ejecuta el comando indicado.\n", "- Matrices lógicas: `dummy = (condicion)` genera una matriz de dummies si se cumple la condición.\n", "- Referenciación: `A(condicion)` genera una matriz con los elementos de `A` que cumplen la condición.\n", "- Los condicionales `if` pueden estar anidados entre si y anidados dentro Loops.\n", "\n", "Ejemplo del uso de matrices lógicas:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ " A = [1 4 7 2 8 5 2 7 9]'; \n", " B = [2 5 1 4 8 0 3 4 3]';\n", " \n", " dummy = A>B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ejemplo de referenciación:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "F =\n", "\n", " 1 2\n", " 4 5\n", " 7 1\n", " 2 4\n", " 8 8\n", " 5 0\n", " 2 3\n", " 7 4\n", " 9 3\n", "\n", "\n", "subF1 =\n", "\n", " 7 1\n", " 5 0\n", " 7 4\n", " 9 3\n" ] } ], "source": [ "F = [A B]\n", "\n", "subF1 = F(A>B,:) % Alternativa 1" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "subF2 =\n", "\n", " 7 1\n", " 5 0\n", " 7 4\n", " 9 3\n" ] } ], "source": [ "subF2 = F(F(:,1)>F(:,2),:) % Alternativa 2" ] } ], "metadata": { "kernelspec": { "display_name": "Matlab", "language": "matlab", "name": "matlab" }, "language_info": { "file_extension": ".m", "help_links": [ { "text": "MetaKernel Magics", "url": "https://github.com/calysto/metakernel/blob/master/metakernel/magics/README.md" } ], "mimetype": "text/x-octave", "name": "matlab", "version": "0.9.4" } }, "nbformat": 4, "nbformat_minor": 1 }