Apuntando a una función en Matlab (Punteros)

Matlab Tips and Tricks.

Esta es una sección donde se explicaran algunos conceptos sobre programación que me han sido útiles para aplicar algoritmos en Matlab. Muchos de estos pequeños tutoriales pueden ser aplicados a diversos lenguajes de programación, donde cada uno maneja un concepto es similar, sin embargo otros serán exclusivos de la forma en la que trabaja Matlab, sobre todo aquellos orientados a la indexación y manejo de matrices.

La intensión de esta información no es proporcionar un estudio o definición formal de estos conceptos, y puede que los nombres aquí asignados varíen con los oficiales en la documentación. En todo tiempo trataré de proporcionar un link directo a documentación oficial que los respalde.

Apuntando a una función (Punteros).

Para quienes tienen conocimiento de lenguaje C, o similares, la palabra puntero no es nueva en su vocabulario. Los punteros son referencias a espacios en memoria, que pueden ser variables o funciones, o cualquier espacio de memoria donde la interpretación de contenido tiene que hacerse explícitamente. Para este tipo de lenguajes el uso de punteros es algo común, usualmente se utiliza para pasar variables a las funciones en forma de referencia, veremos un poco más a detalle sobre qué significa esto en un momento.

In computer science, a pointer is a programming language object, whose value refers to (or “points to”) another value stored elsewhere in the computer memory using its memory address.
Wikipedia: Pointer (computer programming)

En Matlab no existe tal concepto de punteros para pasar variables por referencia, al menos no de la forma clásica. Existe una forma de realizar esto mediante una transformación de tipo de variable C-like que puede encontrarse en este link, o también en la definición de objetos que heredan el comportamiento de Handle, un tema que trataremos en otra ocasión.

Sin embargo existe una forma útil de hacer referencia a un espacio de memoria, que permite pasar funciones como referencia a otras funciones. Para tener en claro el concepto haremos uso de un ejemplo práctico. Suponemos que tenemos que realizar una función grafique cualquier función trigonométrica en un rango de 0 a 2Pi. Llamaremos a esta función graficaTrig y tomara un solo argumento func el cual indica la función trigonométrica que quiere ser graficada.

Podríamos resolver este requerimiento de múltiples formas, en este caso vamos a analizar dos de ellas. Si definimos que el argumento será una cadena (String) con el nombre de la función (Coseno, Seno, etc), entonces la función tendrá que comparar entre un conjunto de fórmulas conocidas.

function graficaTrig(func)
 x = [0:0.01:2*pi]
 if func == 'Coseno'
  plot(x,cos(x))
 end
 if func == 'Seno'
  plot(x,sin(x))
 end
 … %others
end 

Para este caso tenemos que tener conocimiento de todas las posibles Funciones Trigonométricas de antemano, y comparar la cadena con el nombre de cada una, y aplicar la función de Matlab que corresponde a tal función.

La segunda opción que analizaremos, y el propósito de este escrito, es hacer uso de un manejador (handle) de la función trigonométrica, para pasarlo como argumento de la función y evaluarlo directamente. Para esto haremos uso del operador @, que además de otorgarnos un puntero una función puede ser utilizado para definir funciones anónimas (tema que quizá veremos en el futuro). El siguiente código ejemplifica el su forma de uso:

cos(0)
newCos = @cos
newCos(0)

Como se puede observar la función cos devuelve el valor del coseno del número que pasamos como argumento, podemos apuntar a esta función utilizando @ y almacenando dicho puntero a una nueva variable, la cual funcionara como si fuera la misma función. Haciendo uso de este método podemos resolver nuestro problema ejemplo de forma sencilla.

function graficaTrig(func)
 x = [0:0.01:2*pi]
 plot(x,func(x))
end

Donde para obtener la gráfica de la función coseno utilizamos: graficaTrig(@cos). En este caso la función cos es pasada como argumento, tomando un nuevo nombre de variable (func). Por lo que para hacer uso de dicha función solo se manda a llamar de la forma func(x).

En Matlab para ejecutar una función no es necesario hacer uso de los paréntesis (a diferencia de la mayoría de lenguajes) por lo que rand y rand() producen el mismo resultado. Sin embargo en lenguajes como Javascript o Python, hacer uso del nombre de la función sin paréntesis devuelve el handle (dirección de memoria) de dicha función.

En el área de algoritmos metaheurísticos es común que estos algoritmos sean probados en un conjunto de funciones llamadas funciones de prueba (benchmark). Estas funciones contienen ecuaciones matemáticas multidimensionales sobre las cuales se pretende buscar los valores máximos o mínimos. A diferencia de nuestro ejemplo práctico sencillo, no se conocen de antemano todas las posibles funciones que podríamos requerir o utilizar, ya que nuevas funciones pueden irse agregando a nuestro conjunto.

Para el autodenominado toolbox expuesto en Una Clase Para Gobernarlos A Todos, se explica que hacer uso de una clase general sobre la cual desarrollar los múltiples algoritmos metaheurísticos tiene sus ventajas. Y para ello en la clase tenemos una propiedad que contiene la función de costo (función de prueba (fitnessFunction)) que pretende optimizarse. Para ello hacemos uso de un puntero a alguna de estas funciones, y en la parte de la evaluación de la población simplemente utilizamos dicha propiedad de la siguiente forma:

fit(i) = obj.fitnessFunction(population(i,:));

De esta manera podemos hacer pruebas de distintas funciones de manera sencilla. Del repositorio en GitHub se puede observar el script de prueba que hace uso del toolbox.

clear, clc
AISearch = DE(@Rastrigin,30);
AISearch.sizePopulation = 500;
AISearch.maxNoIterations = 1000;
AISearch.start()

La explicación formal de este concepto puede encontrarse en: https://www.mathworks.com/help/matlab/matlab_prog/creating-a-function-handle.html
Si tienes algún problema haciendo uso de punteros a funciones o requieres alguna explicación adicional no dudes en comentar en la sección de abajo. Te responderemos a la brevedad.

Apuntando a una función en Matlab (Punteros)

Leave a Reply

Your email address will not be published. Required fields are marked *