Documentos de Académico
Documentos de Profesional
Documentos de Cultura
2 de abril de 2019
Índice general
1. Introducción 2
1.1. ¿Qué es Octave? . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2. Lo que debes aprender de Octave para este curso es: . . . . . . . 2
1.3. Acerca de estas notas: . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Usando Octave 4
2.1. Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2. Acceso a elementos . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3. Matrices especiales . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4. Funciones predefinidas para trabajar con matrices y vectores . . 14
3. Archivos Script 23
3.1. Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.2. Guardar y cargar datos . . . . . . . . . . . . . . . . . . . . . . . 25
4. Programación en Octave 28
4.1. Operadores relacionales y lógicos . . . . . . . . . . . . . . . . . . 28
4.2. Operadores Lógicos . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.3. Sentencias condicionales . . . . . . . . . . . . . . . . . . . . . . . 32
4.4. Bucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5. Funciones 39
5.1. Cómo definir una función . . . . . . . . . . . . . . . . . . . . . . 39
5.2. Subfunciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.3. Manejadores de Funciones. . . . . . . . . . . . . . . . . . . . . . . 43
5.4. Comando feval. . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.5. Formas de llamar a una función. . . . . . . . . . . . . . . . . . . 44
5.6. Directorios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
6. Gráficas 46
6.1. El comando plot . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
6.2. El comando contour. . . . . . . . . . . . . . . . . . . . . . . . . 55
7. Temas Avanzados 57
7.1. Aumentar la calidad del código escrito en Octave . . . . . . . . . 57
7.2. Vectorizar, la clave para aumentar la velocidad . . . . . . . . . . 57
7.3. El truco más importante de la programación en Octave . . . . . 58
1
Capı́tulo 1
Introducción
2
ayuda , manuales) para lograr dominar el lenguaje y optimizar tu código poco a
poco. Octave cuenta con recursos de programación sofisticados que vale la pena
aprender.
3
Capı́tulo 2
Usando Octave
$ octave
GNU Octave, version 3.2.4
Copyright (C) 2009 John W. Eaton and others.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. For details, type ‘warranty’.
Octave was configured for "x86_64-pc-linux-gnu".
Additional information about Octave is available at
http://www.octave.org.
For more information, visit http://www.octave.org/help-wanted. html
Report bugs to <bug@octave.org> (but first, please read...
For information about changes from previous versions, type ‘news’.
octave:1>
2.1. Matrices
La estructura de datos básica en Octave es la matriz, de esta forma, los
escalares son vistos como matrices de tamaño 1x1.
octave:1> 2
ans = 2
octave:2> 235
ans = 235
4
Los vectores son matrices de tamaño nx1 o 1xn y se introducen de la siguiente
forma:
octave:3> a=[1 2 3 4 5 6 7 8 9]
a =
1 2 3 4 5 6 7 8 9
octave:4> b=[1;2;3;4;5;6;7;8;9]
b =
1
2
3
4
5
6
7
8
9
octave:5> d=[1 2 3;4 5 6]
d =
1 2 3
4 5 6
octave:38> a=[1 2 3]
a =
1 2 3
octave:6> d’
ans =
1 4
2 5
3 6
octave:7> c=d’
c =
1 4
2 5
3 6
Concatenación de matrices
5
1 2 3
4 5 6
octave:38> a=[1 2 3]
a =
1 2 3
octave:39> s=[d;a]
s =
1 2 3
4 5 6
1 2 3
Suma de matrices y multiplicación por un escalar.
octave:13> c=a+b’
c =
2 4 6 8 10 12 14 16 18
octave:14> c=2*c
c =
4 8 12 16 20 24 28 32 36
Existen casos en el que, sin embargo, las operaciones no son las usuales
entre matrices y es cuando una de las matrices es de orden 1x1, es decir, un
escalar. En el caso de la suma, cuando se suma una matriz a un escalar, a
cada elemento de la matriz se le suma dicho escalar, en la suma normal, las
dimensiones de la matriz deben de coincidir para poder realizar esta suma. En
el caso de multiplicación, cuando una variable es un escalar, entonces se realiza
la multiplicación usual entre un escalar y una matriz, es decir, el escalar por cada
entrada, ignorándose la convención de que el número de columnas de la primer
matriz debe de coincidir con el número de renglones de la segunda matriz. Es
posible hacer otras operaciones útiles como multiplicación entrada por entrada,
asegurándose desde luego que las matrices a operar sean de la misma dimensión
agregando ’.’ antes del operador de multiplicación ’*’.
octave:1> a = [1 2 3]
a =
1 2 3
octave:2> b = [4 5 6]
b =
4 5 6
octave:3> a.*b
ans =
4 10 18
6
El operador . es también compatible con los operadores de división / y ex-
ponenciación ^, la sintaxis es igual que en el caso de la multiplicación. En el
caso de la exponenciación el exponente es un escalar y cada entrada de la matriz
es elevada a dicho exponente.
octave:15> c
c =
4 8 12 16 20 24 28 32 36
Tx = a
T \ x
4 5 6
1 8 9
3 5 -1
octave:9> a = [1;2;3]
a =
1
2
3
octave:10> T\a
ans =
-0.043011
0.569892
-0.279570
octave:11> inv(T)*a
ans =
7
-0.043011
0.569892
-0.279570
xt T = at
octave:12> T = T’
T =
4 1 3
5 8 5
6 9 -1
octave:13> a=a’
a =
1 2 3
octave:14> a/T
ans =
Obteniéndose el mismo resultado que en el caso anterior, salvo que ahora las
soluciones están en un vector renglón.
Para tener acceso a una o varias de las entradas de una matriz, se utilizan
ı́ndices y paréntesis. por ejemplo
8
octave:20> a
a =
5 8 6
1 7 3
8 2 4
octave:21> a(3,2)
ans = 2
octave:22> a(3,end)
ans = 4
octave:23> a([1,2],3)
ans =
6
3
octave:24> a([1,2],[2,3])
ans =
8 6
7 3
En un vector (matriz de 1xn o nx1) basta con indicar un solo ı́ndice, aunque
tampoco es incorrecto escribir ambos ı́ndices.
octave:1> v = [1 2 3]
v =
1 2 3
octave:2> v(1) = 5
v =
5 2 3
5 2 200
9
octave:1> v = 3:6
v =
3 4 5 6
octave:6> v1 = [1 2 3 4 5 6]
v1 =
1 2 3 4 5 6
Usando una sintaxis similar podemos crear vectores donde cada elemento
corresponde a una sucesión aritmética, por ejemplo:
octave:11> x = 0:0.2:1
x =
octave:12> x = 1:0.3:2
x =
octave:13> 0:-0.2:-1
ans =
octave:14> linspace(1,2,5)
ans =
10
Ejercicio 2.1 Hacer que se muestren los elementos de la matriz x en orden
inverso por renglón y por columna, es decir, en una sola orden queremos que
tome la matriz:
1 2 3
4 5 6
7 8 9
ans =
9 8 7
6 5 4
3 2 1
Otro operador útil es el operador : este operador es usado para indicar que
se desea acceder a todos los elementos de un renglón o columna de una matriz.
1 2 3
4 5 6
7 8 9
octave:18> a(1,:)
ans =
1 2 3
octave:19> a(:,2)
ans =
2
5
8
11
1 2 3
4 5 6
7 8 9
octave:21> a(2,:) = []
a =
1 2 3
7 8 9
octave:22> a(:,1) = []
a =
2 3
8 9
Cabe notar que a diferencia de los lenguajes de bajo nivel como C, en Octave
no es necesario reservar memoria declarando las variables o su tipo, Octave reali-
za todo el proceso de asignación y liberación de memoria, como en cada ejemplo
donde hemos creado o redefinido los tamaños de las matrices.
Hasta ahora se han creado variables de forma intuitiva, las reglas para nom-
brar las variables son como en casi cualquier lenguaje de programación:
12
2.3. Matrices especiales
Algunas matrices son muy frecuentemente usadas, las más usadas son las
siguientes 3: zeros(m,n) que nos crea una matriz de m renglones y n columnas
con elementos iguales a cero, ones(m,n) que nos crea una matriz de m renglones
y n columnas con elementos iguales a uno, y la función eye(n) que crea una
matriz identidad de nxn.
octave:135> A = zeros(3,2)
A =
0 0
0 0
0 0
octave:136> B = ones(4,5)
B =
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
octave:137> C = eye(3)
C =
Diagonal Matrix
1 0 0
0 1 0
0 0 1
Aunque existen otras matrices especiales, por ejemplo magic(n) que genera
una matriz cuyos elementos forman un cubo mágico de tamaño nxn, pascal(n)
que forma una matriz que vista desde la esquina superior izquierda y en direc-
ción a la esquina inferior derecha contiene los elementos del triángulo de Pascal,
entre otras. Aunque pareciera que son en cierta forma funciones inútiles, y lo
cierto es que rara vez se van a llegar a usar, un uso por ejemplo de la matriz de
pascal es en la generación de números aleatorios de Faure.
octave:35> v = [5 30 20]
v =
13
5 30 20
octave:41> M = diag(v)
M =
Diagonal Matrix
5 0 0
0 30 0
0 0 20
octave:42> M(3,1) = 40
M =
5 0 0
0 30 0
40 0 20
1 2 0
3 4 0
40 0 20
octave:44> v = diag(M)
v =
1
4
20
whos Muestra una lista de todas las variables en memoria y su tamaño junto
con su clase y longitud.
octave:114> x = [1 2 3 4];
octave:115> y=[1:5];
14
octave:116> z = [eye(3) ones(3,1) zeros(3,2)];
octave:117> whos
Variables in the current scope:
x 1x4 32 double
y 1x5 40 double
octave:118> who
Variables in the current scope:
x y z
octave:127> x = [1 2 3 4];
octave:128> z = [eye(3) ones(3,1) zeros(3,2)];
octave:129> length(x)
ans = 4
octave:130> size(z)
ans =
3 6
octave:131> x = magic(4)
x =
15
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
16 2 3 13
5 11 100 8
9 7 6 12
4 14 15 1
octave:133> A = [5 1 6;8 0 2]
A =
5 1 6
8 0 2
octave:134> reshape(A,3,2)
ans =
5 0
8 6
1 2
sum(A)
16
Si A es un vector, calcula la suma de todos sus elementos.
octave:2> A = 1:6
A =
1 2 3 4 5 6
octave:3> sum(A)
ans = 21
octave:4> A = magic(5)
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
octave:5> sum(A)
ans =
65 65 65 65 65
octave:6> sum(A,2)
ans =
65
65
65
65
65
sort(A)
octave:10> x = randperm(8)
x =
17
4 3 6 5 7 2 1 8
octave:11> sort(x)
ans =
1 2 3 4 5 6 7 8
octave:12> sort(x,’descend’)
ans =
8 7 6 5 4 3 2 1
La función sort(A) puede devolver dos valores de salida, cuando se hace una
asignación a una variable(o a ninguna como en el caso de los ejemplos) sólo se
devuelve un valor que es el vector ordenado, el segundo valor de salida de esta
función es una lista del orden en que se encontraba cada entrada en el vector
original. La sintaxis es:
octave:14> A = magic(5)
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
octave:15> sort(A)
ans =
4 5 1 2 3
10 6 7 8 9
11 12 13 14 15
18
17 18 19 20 16
23 24 25 21 22
octave:16> sort(A,2)
ans =
1 8 15 17 24
5 7 14 16 23
4 6 13 20 22
3 10 12 19 21
2 9 11 18 25
4 5 1 2 3
10 6 7 8 9
11 12 13 14 15
17 18 19 20 16
23 24 25 21 22
indice =
3 2 1 5 4
4 3 2 1 5
5 4 3 2 1
1 5 4 3 2
2 1 5 4 3
X =
0.92398 0.90550
0.85098 0.44459
0.40337 0.51532
0.16965 0.63489
0.63003 0.63630
Y =
1.2199
1.5620
1.7899
1.7908
1.6123
Y devolver:
X2 =
19
0.16965 0.63489
0.40337 0.51532
0.63003 0.63630
0.85098 0.44459
0.92398 0.90550
Y2 =
1.7908
1.7899
1.6123
1.5620
1.2199
mean(A)
Calcula el promedio de los valores del vector A, si A es una matriz entonces
calculará el promedio por columna, obteniéndose un vector renglń con cada pro-
medio. Al igual que las funciones sort(A) acepta un 2 como segundo parámetro
con lo que calcula el promedio por renglón en vez de por columna.
octave:6> X = magic(5)
X =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
octave:7> mean(X)
ans =
13 13 13 13 13
octave:8> mean(X,2)
ans =
13
13
13
13
13
octave:9> mean(X(1,:))
ans = 13
20
Ası́ como las anteriores existen muchas funciones, explicar cada una de ellas
serı́a algo tardado, Octave nos puede dar información detallada de las funciones
siempre que conozcamos el nombre de la misma, basta con teclear en la terminal
la palabra help seguida de un espacio y el nombre de la función de la cual
queremos información.
returns the
largest element of the matrix X, and
21
Thus,
Ejercicio 2.3 Una variable X U (a, b) (Uniforme en el intervalo (a, b)) puede
ser generada usando la siguiente fórmula: X = (b − a) ∗ U + a, donde U es
una variable aleatoria uniforme en el intervalo (0, 1). Búsquese usando help
el funcionamiento de la función rand y genérese un vector con 100000 valores
de esta variable aleatoria, use la función hist para graficar un histograma y
comprobar que se sigue una distribución uniforme.
22
Capı́tulo 3
Archivos Script
Para evitar este problema se usan los Archivos script, que tratan de emular
lo que se hace en lenguajes de programación como C o Pascal en donde se
tiene que escribir el código, luego compilarlo y finalmente ejecutar el programa.
Algunas caracterı́sticas de los scripts son:
Como se puede ver, editar un script es muy sencillo, solo hace falta tener
un editor de texto y guardar el archivo con la extensión .m para ser ejecutado.
No se necesita de algún tipo de sintaxis adicional, en el script los comandos se
escriben tal y como se escrbirı́an en la terminal.
23
Para poder ejecutar un script se debe de asegurar primero que el script
tiene extensión .m y segundo que nos encontramos en la carpeta que contiene el
script. para movernos a la carpeta que contiene al script solo hace falta conocer
la direcciń de esta y movernos al directorio usando el comando cd.
octave:15> cd /home/sltkbcu/Documents
octave:16>
3.1. Variables
Las variables globales son variables que pueden ser reconocidas en cualquier
parte, incluidos los Archivos script. Su utilidad es apreciada principalmente en
el manejo de funciones (se hablará más adelante de ellas). Las variables globa-
les, a diferencia de las variables comunes que hemos manejado, deben de ser
declaradas en el ambiente en el que van a ser utilizadas, y se debe de asegurarse
que estas ya tienen un valor cuando son utilizadas, para declarar variables glo-
bales se escribe global seguido de espacio y el nombre de cada variable global
separada por espacio.
octave:18> global x y z w
octave:19> ejemplo
a =
1 2 3 4 5 6 7 8 9 10
24
alguna variable en particular mientras que se sigue trabajando con el resto, se
usa el mismo comando, se deja un espacio y luego la/las variables a eliminar
seguidas de espacio.
octave:20> clear
octave:21> x = 1;
octave:22> y=4
y = 4
octave:23> z=[1,2,5]
z =
1 2 5
octave:24> clear x y
octave:25> x
error: ’x’ undefined near line 25 column 1
octave:25> z
z =
1 2 5
octave:26>
octave:31> x = 2;
octave:32> y = [1,2,3];
octave:33> z = [1 2 ; 4 5];
octave:34> save-ascii’archivo.txt’ x y z
25
contiene información detallada sobre cada variable guardada, el nombre del ar-
chivo debe de proveerse, si el archivo no existe lo crea y si existe lo reemplaza.
Las variables a guardarse pueden o no especificarse, si no se especifica alguna
variable entonces se guardan todas las variables con las que se esté trabajando.
octave:14> y = load(’X.txt’)
y =
octave:15> load(’X.txt’)
octave:16> X
X =
26
Como se ve, existen dos formas de cargar el archivo, la primera es asignárselo
directamente a una variable (y en el caso del ejemplo). La segunda es solo usar
el comando load con lo que Octave creará una variable con el mismo nombre
del archivo (sin extensión) y guardará el archivo ahı́. Cuando se usa el comando
save para guardar varias variables, es conveniente guardar las variables en ar-
chivos por separado, si las matrices son de tamaños distintos provocará un error
al usar load además de que sólo se puede usar load para asignar valor a una sola
variable, en el caso de un archivo .txt. Por el contrario si se carga un archivo
guardado como .mat no hace falta asignarse a una variable en particular, por
default se asigna cada variable en el archivo a una variable con el mismo nombre
que tenı́a al ser guardada, en este caso es posible recuperar más de una variable
desde un solo archivo. Ambos formatos son útiles, si se guardan en un archivo
.txt se puede usar otro programa para usar estos datos, por ejemplo gnuplot
para graficarlos, si por el contrario sólo se desea guardar los datos para usarse en
una sesión posterior entonces quizá sea más conveniente guardarlos como .mat.
27
Capı́tulo 4
Programación en Octave
< Menor a
> Mayor a
== Igual a
<= Menor o igual a
>= Mayor o igual a
∼= Distinto a
octave:27> 1<3
ans = 1
octave:28> 5>0
ans = 1
octave:29> x = rand(5,1)
x =
28
0.265078
0.730114
0.969672
0.212333
0.050660
octave:30> y = rand(5,1)
y =
0.36415
0.42134
0.24123
0.47921
0.85776
octave:31> x<=y
ans =
1
0
0
1
1
También es posible comparar una matriz con un escalar, en este caso se com-
para cada elemento de la matriz con dicho escalar.
octave:32> M = rand(4)
M =
octave:33> M>0.5
ans =
0 1 1 0
1 1 0 1
0 1 1 0
0 0 1 0
29
==== ==== ==== ===== =====
ans 4x4 16 logical
octave:35> sum(sum(ans))
ans = 8
Los operadores lógicos al igual que los relacionales se pueden ocupar con
vectores y matrices siempre que se haga la comparación entre matrices del
mismo tamaño o una matriz y un escalar.
30
octave:39> x1 = 1;
octave:40> x2 = 0;
octave:41> x1&x2
ans = 0
octave:42> x1|x2
ans = 1
octave:43> ~x2
ans = 1
0 1 0
1 2 3
-1 0 4
octave:45> y&x1
ans =
0 1 0
1 1 1
1 0 1
octave:46> y|x2
ans =
0 1 0
1 1 1
1 0 1
octave:47> ~y
ans =
1 0 1
0 0 0
0 1 0
0 0 1
2 3 7
1 1 1
octave:49> y&y2
ans =
0 0 0
31
1 1 1
1 0 1
octave:56> x=0;
octave:57> y=1;
octave:58> z=4;
octave:59> if x==0
> y=2;
> z=0;
> x=1;
> endif
octave:60> x
x = 1
octave:61> y
y = 2
octave:62> z
z = 0
32
octave:63> if x==0
> x=100;
> y=0;
> endif
octave:64> x
x = 1
octave:65> y
y = 2
octave:66> z
z = 0
octave:6> x=1;
octave:7> y=2;
octave:8> opcion=2;
octave:9> if opcion==1
> x=0;
> y=0;
> else
> x=10;
> y=10;
> endif
octave:10> x
x = 10
octave:11> y
y = 10
octave:14> x=0;
octave:15> y=1;
octave:16> opcion=3;
octave:17> if opcion==0
> x=10;
> elseif opcion==1
> y=10;
> elseif opcion==2
> x=x*y;
33
> elseif opcion==3
> y=x/y;
> else
> x=2;
> y=2;
> end
octave:18> x
x = 0
octave:19> y
y = 0
octave:19> x = 2;
octave:20> opcion = mod(x,2)
opcion = 0
octave:21> switch(opcion)
> case 0
> fprintf(’x es un número par\n’)
> case 1
> fprintf(’x es un número impar\n’)
> otherwise
> fprintf(’Ocurrio un error\n’)
> end
x es un número par
34
Una sentencia case puede tener más de un valor con el cual establecer
coincidencias. Para declararlos solo es necesario ponerlos a continuación
entre llaves y separados por comas { valor1, valor2,...}.
4.4. Bucles
Los bucles o sentencias repetitivas nos sirven para realizar un mismo grupo
de comandos en forma consecutiva. Cada una de estas repeticiones se denomina
paso o iteración. Existen dos tipos de bucles que se pueden usar en Octave,
estos son los bucles tipo for-endfor y los bucles tipo while-endwhile.
Estructura for-endfor La sintaxis para este tipo de bucle es la siguiente:
1 2 3 4 5
octave:9> y = ones(1,10);
octave:10> for x = 1:2:10
> y(x) = 0;
> end
octave:11> y
y =
0 1 0 1 0 1 0 1 0 1
octave:1> a = ones(1,5)
a =
1 1 1 1 1
35
octave:2> for i = a
> x(a) = a;
> end
octave:3> x
x = 1
octave:15> a = zeros(1,5);
octave:16> cont = 1
cont = 1
a =
Estructura while-endwhile
Estos bucles constan de las siguientes partes: la palabra while seguida de
espacio y una expresión condicional, una serie de instrucciones, y finalmente la
palabra endwhile para indicar el fin del bucle.
octave:24> x = 0;
octave:25> i = 1;
octave:26> while x<20
> x = x + i;
> i = i + 1;
> endwhile
octave:27> x
x = 21
36
Cuando se trabaja con bucles del tipo while hay que tener en cuenta que
este continuará ejecutándose hasta que la expresión lógica sea falsa, es algo
común cometer errores y que la expresión lógica siempre sea verdadera, en ese
caso se puede cancelar la ejecución del bucle mediante la combinación de teclas
control+C. Esto, sin embargo, detiene la ejecución de todo el código restante
por lo que se debe de ocupar en caso de que sepamos que se ha cometido un
error o no se desee continuar con el resto de cálculos por algún motivo.
Existen dos herramientas que nos ayuda al control de los bucles, la primera
es el comando break, este comando forza la terminación del bucle, en el caso
del bucle for-endfor ignora el resto de iteraciones y en el caso del bucle tipo
while-endwhile no se vuelve a evaluar la expresión lógica. La otra herramienta
es el comando continue al aparecer este comando se provoca que el grupo de
instrucciones en la iteración actual sea ignorada y se comienza con las instruc-
ciones de la siguiente iteración.
Estructura do-until Este bucle consta de iniciar el código con la palabra do, se-
guido de un espacio donde se colocarán todas las instrucciones que se ejecutarán
hasta que se cumpla la condición que coloquemos en la palabra until
octave:28> x = 0;
octave:29> i = 1;
octave:30> do
> x = x + i;
> i = i + 1;
> until x>20
octave:31> x
x = 21
Ejercicio 4.1 Recordemos que una expresión lógica, en Octave, puede ser tam-
bién un vector. ¿Qué sucede si en una expresión condicional se usa un vector?.
Por ejemplo, ¿Qué devuelve el siguiente código?.
octave:47> x = [1 2 3 4];
octave:48> y = [4 3 2 1];
octave:49> a = 1;
octave:50> if x<y
> a = 0;
> endif
¿Y si el código es el siguiente?
octave:56> x = [0 0 0 0];
octave:57> y = [1 2 3 4];
37
octave:58> a = 1;
octave:59> if x<y
> a = 0;
> endif
38
Capı́tulo 5
Funciones
39
x = z.^2;
y = z + x - 1;
endfunction
function funcion2()
fprintf(’Esta funcion no devuelve nada\n’)
endfunction
octave:79> z = 1:5;
octave:80> funcion1(z)
ans =
1 4 9 16 25
octave:81> funcion2
Esta funcion no devuelve nada
1 4 9 16 25
y =
1 5 11 19 29
1 5 11 19 29
Usando el operador ∼ no hace falta reservar memoria para una variable que
no vamos a ocupar. También es posible que una función haga un llamado a otra
función, como es el caso de la primer función que planteamos (paraboloide) que
usa la función sum, podemos usar una función siempre que esta esté definida
en el mismo directorio de trabajo, y se llamará de la forma usual. Algo que
es muy útil es que una función usada dentro de otra función sea una variable,
40
por ejemplo, si deseamos calcular la derivada en un punto, nos gustarı́a que
esta función sirva para cualquier función, o lo que es lo mismo, que la función
”derivada.acepte como argumento de entrada otra función. En C esto se hace
mediante un puntero a una función, en Octave esto se realiza mediante la ex-
presión:
octave:84> A = @funcion2
A = @funcion2
octave:85> A
A = @funcion2
octave:86> A()
Esta funcion no devuelve nada
El operador @ nos permite asignar la función a una variable para poder
enviarla como argumento a una función. Volviendo al ejemplo de la derivada de
una función, la función tendrı́a una estructura como la siguiente:
function [y] = derivada(f,x)
....
....
....
endfunction
Donde f es la función de la cual queremos obtener la derivada, x el punto
en el que hay que evaluarse y y la variable de salida con el valor de f 0 (x).
Una cosa importante y que no ha sido mencionada es que para poder ejecu-
tar una función desde un archivo .m (podrı́a definirse la función en la terminal
sin necesidad de un archivo que la contenga) es necesario que el archivo .m tenga
el mismo nombre de la función, es decir, en nuestros ejemplos los archivos de-
berı́an de llamarse paraboliode.m, funcion1.m, funcion2.m, derivada.m.
En general las funciones tienen muchas similitudes con los scripts, por ejemplo,
que son una serie de comandos y que estas pueden guardarse en un archivo .m
para poder ejecutarse después, sin embargo, las funciones tienen diferencias con
respecto a los scripts.
Una función puede requerir o no de argumentos de entrada. Un script no
requiere de argumentos de entrada para poder ejecutarse.
En una función todos los valores usados son eliminados (salvo por los
valores de salida y variables globales) una vez acabadas las instrucciones
de esta. En un script las variables usadas pueden seguirse usando y si no se
desea seguir usándolas requiere de eliminarse (usando clear por ejemplo).
Cuando se ejecuta una función o script, al igual que con los bucles, se puede
detener la ejecución de estos usando la combinación de teclas control+C.
Para terminar esta sección se muestra a manera de ejemplo un programa
que permite calcular el gradiente de una función usando diferencias finitas:
41
function [G] = grad(F,X,h), %F es el nombre de la
%función, X es el punto en el que se
%evaluará el gradiente, h es el tama~no del
%incremento en cada
% variable
dim = length(X); %Aquı́ se calcula el número de
%variables de la función
% En I se guardan vectores que representan los
%incrementosen cada variable
I = h*eye(dim);
%G es la inicialización del vector que se
%devolverá(el gradiente de
%F en X)
G = zeros(1,dim);
%En el siguiente bucle se calcula el gradiente para
%cada variable i, i=1,..,dim
for i = 1:dim
G(i) = (F(X+I(i,:))-f(X-I(i,:)))/(2*h);
endfor
endfunction
Como nota del programa anterior, X debe ser un vector renglón para que
las dimensiones de las sumas de matrices sean compatibles.
octave:36> f1 = @(x) x . ^ 2 - 2;
octave:37> f2 = @(t, x) - t . / x;
Ahora definimos una función con más de un parámetro, usando las funciones
anónimas.
function [x]=producto(f1,f2,a,b)
x=f1(a,b)*f2(a,b); %Regreso el producto de la función f1 con f2
% evaluada en (a,b)
endfunction
42
Ahora en la ventana de comandos, definimos f1 y f2 como en el siguiente
ejemplo y llamamos a la función producto con parámetros f1,f2,a,b donde (a,b)
es el punto donde se evaluarán las funciones:
5.2. Subfunciones.
Un archivo .m donde hemos programado una función puede contener fun-
ciones secundarias llamadas subfunciones. Estas funciones secundarias sólo son
visibles para las otras funciones en el mismo archivo de la función. Por ejemplo,
un archivo f.m que contenga
function f ()
printf ("in f, calling g\n");
g ()
endfunction
function g ()
printf ("in g, calling h\n");
h ()
endfunction
function h ()
printf ("in h\n")
endfunction
@nombre de la función
Por ejemplo;
f = @sin
43
f = @sin
quad (f, 0, pi)
ans =
2
Como otro ejemplo, podemos usar la función feval (que se tratará en la si-
guiente subsección) para llamar a una función usando manejadores de funciones
0 simplemente escribir el nombre de la función del manejador de función seguido
de un argumento entre paréntesis.
f = @sin
feval (f, pi/4)
ans =
0.70711
f(pi/4)
ans =
0.70711
f = @exp
feval (f, 1)
ans =
2.71183
@nombre de la función
44
function [y] = prueba(x),
y = cos(x) + exp(x+1);
end
cos(@prueba(10))
ans = 59,873.347
5.6. Directorios.
Cuando trabajamos con funciones programadas por nosotros mismos y la
llamamos, Octave busca una lista de en directorios el archivo en el que se haya
declarado dicha función. Esta lista de directorios es conocido como Loadpath.
Por default, el load path contiene una lista de diretorios distribuidos con Octave
más el directorio en que se esté trabajando.
Es posible agregar o remover directorios del load path usando los comandos
addpath y rmpath. Como ejemplo, el siguiente código agrega ‘ /Octave’ al load
path.
addpath ("~/Octave")
45
Capı́tulo 6
Gráficas
octave:6> x = rand(1,100);
octave:7> plot(x)
octave:8> print(’-djpg’,’1.jpg’)
Produce:
46
Figura 6.1: Gráfica de una serie
El comando usado luego del comando plot, print, se usa para guardar la
imagen graficada en un archivo, en el caso anterior se usÓ el argumento ’-djpg’
para guardar la imagen en el archivo ’ej1.jpg’, puede guardarse la imagen en
distintos tipos de archivo, por ejemplo .eps, PS, PNG, PDF, TIFF,.
octave:14> x = rand(20,5);
octave:15> plot(x)
octave:16> print(’-djpg’,’2.jpg’)
Muestra:
47
Figura 6.2: Gráfica de varias series
En general plot la forma más común de usar plot es usando dos argumen-
tos, estos argumentos son vectores que contendrán las abscisas y las ordenadas
respectivamente, hay que tener en cuenta que deben de tener el mismo tamaño.
En el código siguiente se grafica la función f (x) = cos(x) en el intervalo [1, 4].
octave:21> x = 1:0.01:4;
octave:22> y = cos(x);
octave:23> plot(x,y)
octave:24> print(’-djpg’,’3.jpg’)
48
Figura 6.3: Gráfica de f (x) = cos(x)
En realidad lo que hace Octave es hacer una correspondencia entre los va-
lores de x y los de y y graficar punto por punto, al no especificarse más acerca
de lo que se quiere, por default, Octave unirá esos puntos por una lı́nea, si sólo
necesitáramos ver los puntos se necesita agregar más argumentos, por ejemplo:
octave:52> x = 1:0.5:4;
octave:53> y = x.^2;
octave:54> plot(x,y,’marker’,’*’,’color’,
’b’,’marker size’,20,’linestyle’,’none’)
octave:55> print(’-djpg’,’4.jpg’)
49
Figura 6.4: Gráfica discreta
1. color. Esta opción cambia el color del gráfico, puede usarse con valores
predeterminados como b para azul, r para rojo, etc. O puede usarse un
vector con porcentajes de los colores primarios azul, rojo y verde, por
ejemplo [0, 4, 0,5, 0].
2. marker. Esta opción determina el tipo de marcador que usarán los pun-
tos en el gráfico, puede usar como valores . para usar un punto, ∗ para
asterisco, o para circulo, s para cuadrado, d para diamante y muchos más.
3. linestyle. Determina el tipo de lı́nea con el que se unirán los puntos, como
valores puede tomar: − para una lı́nea recta, −− lı́nea punteada, none
para no poner lı́nea etc.
4. linewidth Se usa para cambiar el grosor de la lı́nea dibujada entre puntos.
50
7. markerfacecolor. Se usa para indicar el color del relleno de la figura usada
como marcador, usa las mismas opciones que color.
La sintaxis para un formato muy especı́fico puede ser muy larga, pero si
no hace falta especificar mucho se puede usar un formato más corto como el
siguiente:
octave:83> x = linspace(-1,3,10);
octave:84> y = x.^2;
octave:85> plot(x,y,’k.’)
octave:86> print(’-djpg’,’5.jpg’)
octave:87> plot(x,y,’m’)
octave:88> print(’-djpg’,’6.jpg’)
51
Figura 6.6: Gráfica simple (puntos unidos)
Antes pudimos graficar en una sola gráfica varias series de tiempo, también
es posible graficar varias gráficas en un mismo gráfico, para eso usamos los
comandos hold on y hold off. Para usarse sólo se debe de colocar entre estos
las instrucciones plot.
octave:1> x = linspace(0,pi,100);
octave:2> hold on
octave:3> plot(x,cos(x),’ro’)
octave:4> plot(x,sin(x),’bp’)
octave:5> plot(x,x.^2,’mx’)
octave:6> plot(x,exp(x),’k^’)
octave:7> hold off
octave:8> print(’-djpg’,’7.jpg’)
52
Figura 6.7: Gráficas usando hold on y hold off
Además de las figuras es posible agregar texto a las mismas, por ejemplo
incluir un tı́tulo a las gráficas o nombrar los ejes, etc.
Para darle un tı́tulo a la imagen se usa el comando title, para darle nom-
bre a los ejes se usa xlabel y ylabel, para poner una texto que asocie los
marcadores con alguna caracterı́stica se usa legend, todas estas funciones(salvo
legend) usan como parámetro una cadena de texto (hay que tener cuidado con
los acentos) que indica lo que debe de escribirse como etiqueta, el tamaño del
texto se puede ajustar con la opción fontsize y un tamaño de fuente, el valor
por defecto es 10.
octave:27> x = linspace(0,pi,100);
octave:28> hold on
octave:29> xlabel(’Abscisas’,’fontsize’,20)
octave:30> ylabel(’Ordenadas’,’fontsize’,20)
octave:31> title(’Ejemplo de texto en
graficas’,’fontsize’,20)
octave:32> plot(x,cos(x),’ro’)
octave:33> plot(x,sin(x),’b.’)
octave:34> legend(’Grafica de cos(x)’,’Grafica de
sen(x)’)
octave:35> hold off
octave:36> print(’-djpg’,’8.jpg’)
53
Figura 6.8: Gráficas con etiquetas
octave:38> x = linspace(0,pi,100);
octave:39> subplot(2,2,1)
octave:40> plot(x,cos(x),’yo’)
octave:41> subplot(2,2,2)
octave:42> plot(x,sin(x),’cd’)
octave:43> subplot(2,2,3)
octave:44> plot(x,x.^2,’color’,rand(1,3),’marker’,’h
’,’linestyle’,’none’)
octave:45> subplot(2,2,4)
octave:46> plot(x,exp(x),’bx’)
octave:47> print(’-djpg’,’9.jpg’)
54
Figura 6.9: Gráficas con etiquetas
x = 0:2;
y = x;
z = x’*y;
contourc(x, y, z, 2:3)
Genera:
55
colormap ("default");
[x, y, z] = peaks ();
contour (x, y, z);
title ({"contour() plot (isolines of constant Z)"; "Z = peaks()"});
Genera la figura:
56
Capı́tulo 7
Temas Avanzados
57
pero para un bloque grande de memoria, de tal forma que todas las sumas se
realizan a la vez.
a = rand(66); %matriz de 66 x 66
b = rand(66);
tic
for i = 1:66
for j = 1:66
c(i,j) = a(i,j)+b(i,j);
endfor
endfor
toc
Elapsed time is 0.05702 seconds.
tic
c = a+b;
toc
Elapsed time is 3.501e-05 seconds.
58
Podrı́amos decir que fue un ejemplo amañado ya que el segundo método (el
más rápido) es más intuitivo de hacer y en realidad no es algo que harı́amos de
forma premeditada. Supongamos ahora el siguiente ejemplo, tenemos un vector
y una matriz, supongamos que deseamos multiplicar cada renglón de la matriz
por un elemento del vector. Nuevamente se pensará en realizar por dos métodos
diferentes, en el primero se formará un bucle y se tomará cada elemento del
vector y se multiplicará por cada renglón de la matriz y se guardará en otra
matriz, en el segundo método la secuencia de números del vector se convertirán
en una matriz para poder luego multiplicar la matriz.
a = 1:66;
b = rand(66);
tic
for i = 1:66
c(i,:) = a(i)*b(i,:);
endfor
toc
tic
c = a’*ones(1,66).*b;
toc
Lo que hace que estos bucles sean lentos no es exactamente el bucle en sı́,
tampoco la ausencia de vectorización, en los ejemplos anteriores el principal
problema fue en la asignación de memoria. Cuando se sumaron las matrices en
el primer ejemplo al final tenı́amos una matriz en donde se estaba guardando
la suma, recordemos que las variables no se declaran y se crean en el instante
en el que se les asigna un valor, cuando se inicia el bloque, esta matriz se está
igualando a un escalar (1x1), en los siguientes pasos del ciclo la matriz está
cambiando de tamaño hasta que al final terminamos con una matriz de 66x66,
precisamente porque no lo vemos es que pasa desapercibido, Octave realiza la
reserva de memoria para la variable, y cuando esta cambia de tamaño realiza
la reserva de memoria para una variable más grande, copia los valores de la
59
variable anterior en la nueva variable, asigna el nuevo valor calculado y libera
la memoria de la variable vieja. Es por lo que los ciclos se vuelven tan lentos.
En el segundo caso la reserva de memoria se realiza sólo una vez. Además de
evitar los ciclos, una práctica común es reservar memoria para las variables,
por ejemplo creando una matriz de ceros del tamaño que necesitamos. Este
comportamiento está ligado al funcionamiento de los arrays en C; un buen texto
para comprenderlo mejor es [?] donde encontraremos un capı́tulo inicial sobre
qué es verdaderamente un array y qué relación tiene con un puntero.
60