Escolar Documentos
Profissional Documentos
Cultura Documentos
2 Usando Octave
Octave se encuentra disponible para sistemas UNIX (Linux) y MS Windows.
También se conoce como Octave al lenguaje de alto nivel en el que se codifica.
Se trata de un lenguaje interpretado que posee muchas similitudes con Matlab,
con el fin de hacerlo compatible (*).
Cuando se inicia Octave, se tiene una leyenda descriptiva seguida de la lı́nea
de comandos (prompt).
$ 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...
1
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
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:38> a=[1 2 3]
a =
1 2 3
2
Se pueden efectuar las operaciones tı́picas sobre matrices, por ejemplo:
1 4
2 5
3 6
1 4
2 5
3 6
Concatenación de matrices
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
octave:13> c=a+b’
c =
2 4 6 8 10 12 14 16 18
3
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
octave:15> c
c =
4
4 8 12 16 20 24 28 32 36
Tx = a
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 =
-0.043011
0.569892
-0.279570
5
Sin embargo usar el operador diagonal es computacionalmente más eficiente
que calcular la inversa de T y multiplicar con a debido a que al usar el operador
diagonal se realiza eliminación gaussiana para resolver el sistema de ecuaciones,
con la consecuente mejora numérica, mientras que en la otra forma se calcula
la inversa y luego se realiza un producto de matrices.
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. p.ej.
5 8 6
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
7
La expresión x1 : x2 devuelve un vector renglón (fila) de enteros entre x1 y
x2 .
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 =
8
0.00000 -0.20000 -0.40000 -0.60000 -0.80000 -1.00000
octave:14> linspace(1,2,5)
ans =
1 2 3
4 5 6
7 8 9
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,:)
9
ans =
1 2 3
octave:19> a(:,2)
ans =
2
5
8
Algunas veces es deseable eliminar por alguna razón el contenido de un
renglón o columna de una matriz, o simplemente un elemento de un vector, esto
se puede hacer usando la siguiente sintaxis:
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 real-
iza 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:
10
2. Pueden contener números.
3. Hay sensibilidad a letras mayúsculas y minúsculas.
4. No es posible asignarle como nombre de variable una palabra reservada
por el sistema, por ejemplo Sin, Cos, sqrt, entre otras.
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
11
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 direcció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.
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
12
1 2 0
3 4 0
40 0 20
octave:44> v = diag(M)
v =
1
4
20
octave:114> x = [1 2 3 4];
octave:115> y=[1:5];
octave:116> z = [eye(3) ones(3,1) zeros(3,2)];
octave:117> whos
Variables in the current scope:
octave:118> who
Variables in the current scope:
x y z
13
Sin embargo, si solo se desea conocer información de una variable en especı́fico
se pueden utilizar los comandos:
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 =
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
14
x(2, 1), y en particular el elemento x(10) para el ejemplo corresponde con el el-
emento x(2, 3). Usando esta correspondencia es que trabaja la siguiente función:
5 1 6
8 0 2
octave:134> reshape(A,3,2)
ans =
5 0
8 6
1 2
En general Octave posee un gran número de funciones que trabajan con
arreglos y matrices y, de momento, solo se mostrarán algunas de ellas.
sum(A)
octave:2> A = 1:6
A =
1 2 3 4 5 6
octave:3> sum(A)
ans = 21
Si A es una matriz entonces devuelve la suma de los elementos por columna
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
15
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)
4 3 6 5 7 2 1 8
octave:11> sort(x)
ans =
1 2 3 4 5 6 7 8
Pero si lo que se desea es obtener los elementos ordenados en forma decre-
ciente se puede usar la palabra ’descend’ como segundo argumento.
octave:12> sort(x,’descend’)
ans =
8 7 6 5 4 3 2 1
16
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) solo 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:
1 2 3 4 5 6 7 8
indices =
7 6 2 1 4 3 5 8
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
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
17
octave:17> [y,indice] = sort(A)
y =
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
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 =
0.16965 0.63489
0.40337 0.51532
18
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 matrı́z en-
tonces calculará el promedio por columna, obteniéndose un vector renglón con
cada promedio. 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
19
octave:9> mean(X(1,:))
ans = 13
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.
octave:2> help max
’max’ is a function from the file /usr/lib/i386-linux-gnu/octave/
3.6.4/oct/i686-pc-linux-gnu/max.oct
compares each element of the range ’2:5’ with ’pi’, and returns
a row vector of the maximum values.
If called with one input and two output arguments, ’max’ also
returns the first index of the maximum value(s). Thus,
20
Additional help for built-in functions and operators is
available in the online version of the manual. Use the command
’doc <topic>’ to search the manual index.
3 Archivos Script
El uso de Octave es muy similar al de una calculadora en donde damos orden
por orden lo que se debe realizar, esto puede ser muy tedioso si la cantidad de
instrucciones que hemos de ingresar es relativamente grande, además de que
si cometimos algún error al escribir alguna variable, entrada de matriz, orden,
etc. generalmente tendrı́amos que comenzar desde el principio, lo cual es poco
práctico.
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:
21
• Los scripts pueden ser creados usando cualquier editor de texto plano
(gedit, block de notas, Emacs, Kate, etc.). Asimismo el texto puede ser
copiado y pegado en la terminal para ser ejecutado.
• Los Archivos script también se denominan Archivos M ya que la extensión
.m es la que se debe utilizar para ser reconocidos por Octave.
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.
Para poder ejecutar un script se debe de asegurar primero que el script tiene ex-
tensió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ón de esta y movernos al directorio usando el comando cd.
octave:15> cd /home/sltkbcu/Documents
octave:16>
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 glob-
ales, 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 glob-
ales se escribe global seguido de espacio y el nombre de cada variable global
separada por espacio.
octave:18> global x y z w
22
octave:19> ejemplo
a =
1 2 3 4 5 6 7 8 9 10
Cuando se trabaja con un script grande o se resuelven varios problemas es
posible que se tenga guardada una cantidad relativamente grande de variables
en la memoria, es una práctica común en cualquier lenguaje de programación ir
desechando estas variables de tal forma que la memoria quede libre para poder
usarse en cualquier momento. No nos gustarı́a que una aplicación falle a medio
proceso por falta de memoria. Para realizar eso se usa el comando clear. Esto
borra todas las variables con las que se esté trabajando, si se desea eliminar
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>
Los comandos save y load permiten guardar y cargar datos en diversos for-
matos.
save El comando save sirve para guardar los valores de las variables con las que
se esté trabajando actualmente, usa la sintaxis save opciones archivo x1 x2
23
· · · . Se escribe primero la palabra save seguida de espacio, en seguida la o las
opciones que se van a utilizar, si se usa más de una opción entonces cada opción
se separará por un espacio, luego de un espacio se escribe entre comillas simples
el nombre del archivo en el que se guardarán las variables y finalmente la/las
variables que se guardarán, cada una de ellas separadas por un espacio.
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
Es necesario escribir save, las opciones pueden o no ser escritas, en caso de
no indicarse alguna opción la salida por default es un archivo de texto que con-
tiene información detallada sobre cada variable guardada, el nombre del archivo
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 vari-
able entonces se guardan todas las variables con las que se esté trabajando.
octave:14> y = load(’X.txt’)
y =
24
2.47802 0.57247 3.42081 12.68678 3.27684
12.01603 9.17642 12.15015 10.33811 4.43015
octave:15> load(’X.txt’)
octave:16> X
X =
4 Programación en Octave
Hasta ahora se ha hablado sobre el ambiente de Octave, la naturaleza de las
variables y la utilidad de los scripts para organizar las instrucciones de una forma
clara y susceptible a cambios. Por si solo lo que se ha visto no es suficiente para
resolver un problema.
25
4.1 Operadores relacionales y lógicos
Un operador relacional es aquel que compara dos números y devuelve como re-
spuesta falso o verdadero. Si el resultado es falso se devuelve o y si es verdadero
se devuelve 1. Los operadores relacionales disponibles en Octave son:
< 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 =
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 =
26
1
0
0
1
1
También es posible comparar una matriz con un escalar, en este caso se compara
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
octave:34> whos ans
Variables in the current scope:
octave:35> sum(sum(ans))
ans = 8
27
4.2 Operadores Lógicos
Los operadores lógicos son usados en la lógica proposicional para aceptar o
rechazar una sucesión de proposiciones relacionadas entre sı́. Los operadores
lógicos que son posible de usar en Octave son:
• 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.
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
octave:44> y = [0 1 0;1 2 3;-1,0,4]
y =
0 1 0
1 2 3
-1 0 4
28
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
1 1 1
1 0 1
29
Orden de Precedencia Operación
1(la mayor) Paréntesis, si hay paréntesis anidados el
más interno tiene mayor precedencia.
2 Exponenciación
3 Operación lógica de negación (⇠)
4 Multiplicación y división
5 Suma y resta
6 Operadores relacionales
7 Operación Lógica Y (&)
8(la menor) Operación lógica O ( | )
Si dos o más operadores tienen la misma precedencia entonces la operación
se efectuará de izquierda a derecha.
30
y = 2
octave:66> z
z = 0
Un valor distinto de cero funciona como verdadero.
Estructura if-else-endif
Esta estructura es usada para ejecutar uno entre dos grupos de comandos
en función de su evaluación lógica. la sintaxis es como sigue:
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
si se cumple la sentencia lógica entonces se ejecuta el primero grupo de
comandos y en caso contrario se ejecuta el segundo grupo. También es posi-
ble “anidar” de tal forma que se ejecute un grupo de comandos entre varios
disponibles, para eso se usa la sentencia elseif seguida de una expresión condi-
cional.
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;
> elseif opcion==3
> y=x/y;
> else
31
> x=2;
> y=2;
> end
octave:18> x
x = 0
octave:19> y
y = 0
En este tipo de estructura, cuando se cumple una expresión condicional se ejecu-
tará el grupo de datos correspondiente y luego de eso no se seguirán evaluando
las demás expresiones condicionales, es decir son ignoradas.
Estructura switch-case
La función de la estructura switch-case es muy similar al de la estructura
if-elseif-else-end, también es utilizada para ejecutar un grupo de comandos
pero no se verifica una expresión condicional sino el valor de una variable(que
en algún sentido es evaluar una expresión condicional de manera indirecta), la
sintaxis es la siguiente:
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
La estructura switch-case tiene las siguientes reglas:
32
Para los que estén familiarizados con C, la estructura switch-case funciona
de la misma forma salvo que en C es necesario terminar cada grupo de comandos
con la sentencia break; ya que de no hacer esto se siguen buscando coincidencias
de tal forma que se puede ejecutar más de un grupo de comandos.
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:
x =
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 =
33
1 1 1 1 1
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
octave:17> for i = linspace(1,2,5)
> a(cont) = i;
> cont = cont + 1;
> end
octave:18> a
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
Cuando se entra al bucle tipo while-endwhile se empieza por verificar la
expresión lógica, si esta es verdadera entonces se ejecutan las instrucciones den-
tro del bucle, si esta no se cumple entonces se ignora el bucle y se continua con
las siguientes instrucciones. En C existe el tipo de bucle do-while que asegura
que siempre se ejecuta al menos una vez el grupo de instrucciones, en Octave
este tipo de bucle no existe, hay que tener en cuenta este detalle.
Cuando se trabaja con bucles del tipo while hay que tener en cuenta que
34
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.
Ejercicio 4 Recordemos que una expresión lógica, en Octave, puede ser también
un vector.¿ Que 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];
octave:58> a = 1;
octave:59> if x<y
> a = 0;
> endif
5 Funciones
En la sección 1 se usaron algunas funciones que trabajan sobre matrices, que
devuelven la suma de sus elementos, que devuelven su tamaño, etc. Aunque
en Octave existen un sinnúmero de funciones predefinidas para hacer gran can-
tidad de tareas, siempre será necesario poder crear nuestras propias funciones
para realizar tareas personalizadas o rutinas que no se encuentran programadas
en Octave, las funciones sirven para esto.
35
Una función es un conjunto de instrucciones que, al igual que los scripts, son
guardadas en un archivo .m. Una función puede requerir de algunas variables
de entrada (argumentos) o no, y devuelven una o más variables de salida. Para
manejar una función, al igual que con los scripts, es necesario que la función
se encuentre guardada en el directorio donde se está trabajando actualmente.
Debe de tener la siguiente forma:
function y = paraboloide(x)
y = sum(x.^2);
endfunction
Se inicia con la palabra function seguida de espacio y el nombre de la vari-
able de salida, el operador de asignación y entre paréntesis los argumentos que
usará la función, la función podrı́a no necesitar de parámetro alguno, en ese
caso se deja vacı́o el interior de los paréntesis. Una función en Octave puede
no devolver valor alguno, una o más variables. Los siguientes son ejemplos de
funciones que no devuelven valores y que devuelven más de uno.
function funcion2()
fprintf(’Esta funcion no devuelve nada\n’)
endfunction
Ejecutar una función en Octave se realiza como en cualquier otro lenguaje,
tan solo se escribe el nombre de la función y entre paréntesis los valores de
entrada que requiere.
octave:79> z = 1:5;
octave:80> funcion1(z)
ans =
1 4 9 16 25
octave:81> funcion2
Esta funcion no devuelve nada
Como se puede observar en el ejemplo, la función funcion1 que queremos
que devuelva dos valores de salida solo devuelve uno, solo es posible visualizar
la segunda variable de salida si esta es asignada a una variable, por ejemplo,
para poder obtener los dos valores de salida de la función podrı́amos hacer algo
como:
36
octave:82> [x,y] = funcion1(z)
x =
1 4 9 16 25
y =
1 5 11 19 29
Mientras que si lo que deseamos es solo el segundo valor que devuelve la
función podemos hacer:
octave:83> [~,y] = funcion1(z)
y =
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 ésta este 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, por ejem-
plo, 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 funcion ”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 expresió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)
37
Una cosa importante y que no ha sido mencionada es que para poder ejecutar
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 deberı́an
de llamarse paraboliode.m, funcion1.m, funcion2.m, derivada.m
En general las funciones tienen muchas similitudes con los scripts, por ejem-
plo, 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:
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 incrementos en 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.
38
Ejercicio 5 Usando como base el programa anterior, elabórese un programa que
permita calcular la hessiana de una función F en el punto X con un incremento
h.
6 Gráficas
Además de los resultados numéricos, mostrar gráficas que muestren dichos re-
sultados siempre es más ilustrativo. En Octave se pueden realizar graficas en
2D y 3D usando los comandos plot y plot3 respectivamente, en esta sección
se mostrará algunas de las caracterı́sticas de estas funciones.
octave:6> x = rand(1,100);
octave:7> plot(x)
octave:8> print(’-djpg’,’ej1.jpg’)
produce:
39
figuras/ej1.jpg
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’,’ej2.jpg’)
muestra
40
figuras/ej2.jpg
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 gráfica 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’,’ej3.jpg’)
41
figuras/ej3.jpg
En realidad lo que hace Octave es hacer una correspondencia entre los val-
ores 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 solo
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’,’markersize’,20,
’linestyle’,’none’)
octave:55> print(’-djpg’,’ej4.jpg’)
que muestra la siguiente figura:
42
figuras/ej4.jpg
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.
5. markersize. Determina el tamaño del marcador, su argumento es un
número real.
6. markeredgecolor. Indica el color del contorno de la figura usada como
marcador, puede usar los colores predeterminados por letras o un vector
de 3 componentes como la opción color.
7. markerfacecolor. Se usa para indicar el color del relleno de la figura usada
como marcador, usa las mismas opciones que color.
43
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’,’ej5.jpg’)
octave:87> plot(x,y,’m’)
octave:88> print(’-djpg’,’ej6.jpg’)
figuras/ej5.jpg
44
figuras/ej6.jpg
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 solo 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’,’ej7.jpg’)
45
figuras/ej7.jpg
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 te 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’,’ej8.jpg’)
46
figuras/ej8.jpg
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’,’ej9.jpg’)
47
figuras/ej9.jpg
7 Temas Avanzados
Cuando se programa se está interesado en que nuestro código nos devuelva el
resultado que deseamos, la mayorı́a de las veces esto es suficiente, sin embargo,
cuando los problemas aumentan en dificultad, resolver el problema ya no es sufi-
ciente, además de resolverlo necesitamos que lo haga lo más rápido posible. Esta
sección se centra en mencionar algunos detalles que están más bien relacionados
a la programación en general y cálculo numérico.
48
Aumentar la calidad del código escrito en Octave
El uso de scripts y funciones ayuda a tener ordenado lo que se desea progra-
mar, siempre es conveniente crear módulos sobre los cuales si ocurre un error
sea fácil identificar la sección de donde proviene dicho error. Es por esto que
un buen hábito es el de usar estas herramientas. En general, Octave es un
lenguaje interpretado, de alto nivel y por tanto difı́cilmente podrá compararse
en tiempo de ejecución a programas compilados en C, y sin embargo, existen
algunas técnicas de programación que pueden ayudarnos a que esta diferencia
no sea tan significativa.
Octave es un software que está basado esta ideologı́a y está optimizado para
hacer las cosas en dicha forma, pero si se le pide hacer las cosas elemento a
elemento(por ejemplo en un bucle) también lo hará aunque no está optimizado
para trabajar de esta forma. Entonces, hay que pensar siempre en la forma en
que se hagan los cálculos por bloques de memoria en vez de elemento a elemento
usando por ejemplo submatrices.
a = rand(66); %matriz de 66 x 66
b = rand(66);
tic
for i = 1:66
49
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.
a = 1:66;
b = rand(66);
tic
for i = 1:66
c(i,:) = a(i)*b(i,:);
endfor
toc
a = 1:66;
b = rand(66);
tic
c = a’*ones(1,66).*b;
toc
50
al problema(aun cuando pareciera que estamos realizando más operaciones) el
tiempo resulta menor.
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
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 solo 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 com-
portamiento 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.
51