**IAIC**
NetLogo: Introducción
!!!warn
El documento que aquí se expone es una guía rápida orientada a explicar las particularidades de NetLogo a lectores que ya tengan conocimientos de programación (en cualquier lenguaje habitual que no sea muy esotérico). En ningún momento debe usarse como único recurso de aprendizaje del lenguaje, sino como complemento de otros recursos y como apoyo de conocimientos previos.
# Recursos de NetLogo
!!!

* [Transparencias](./slides/NetLogo.pptx) (pensadas para explicación interactiva, no como soporte de estudio).
* [Curso básico de NetLogo](https://www.cs.us.es/~fsancho/?p=netlogo).
* [NetLogo 6.0 QuickGuide](http://luis.izqui.org/resources/NetLogo-6-0-QuickGuide.pdf) (de [Luis R. Izquierdo](http://luis.izqui.org/)).
* [Documentación Oficial](http://ccl.northwestern.edu/netlogo/docs/).
# Ideas fundamentales
* La principal orientación de NetLogo es la de **modelar sistemas compuestos por individuos que tienen capacidad de actuación y percepción**, basándose en el paradigma de **modelado por agentes**:
* Un **agente** es un *individuo sintético, autónomo y dotado de reglas o características que gobiernan su comportamiento y su capacidad de tomar decisiones*.
* Los agentes pueden **interactuar entre sí y con el medio ambiente** obedeciendo un conjunto de reglas.
* Los agentes son **flexibles** y tienen capacidad de aprender y adaptar su comportamiento basándose en la experiencia (depende de nuestra habilidad para programarlos). Algunas de estas capacidades pueden requerir alguna forma de memoria y diversas técnicas de programación.
* Si ignoramos el uso específico de los agentes, NetLogo es simplemente un lenguaje muy sencillo de programación que proporciona un soporte gráfico muy accesible.
* El conjunto de definiciones, comportamientos y procedimientos que componen un modelado entero se denomina **modelo**, y suele venir dado en forma de fichero de texto con algunas particularidades:
* A pesar de ser un fichero de texto, mantiene una estructura en la que almacena tanto la información **gráfica** del modelo (interfaz, formas de los agentes, etc.) como el **código** asociado y la **documentación**. Por ello, es conveniente siempre abrirlo por medio de la interfaz que proporciona NetLogo.
* La sección dedicada a código diferencia entre una **cabecera** (donde se pueden dar definiciones generales del modelo) y un **cuerpo** donde se definen los procedimientos asociados.
* Ciertas partes del código pueden estructurarse en ficheros de texto independientes a modo de **librerías**, y ser **importados** desde el fichero principal del modelo. Ver **Modularización** más abajo.
* Las **variables** no tienen tipos asignados a priori, solo son contenedores de valores (del tipo que sean).
* Las **variables locales** se crean con `let` (no siempre es necesario crear todas las variables, por ejemplo, los parámetros de los procedimientos se declaran en la cabecera de la función) y se asignan con `set`. No se usa `=` para la asignación:
~~~~~~~~~~~~~~~~~~~~
let a 3
set a "tres"
~~~~~~~~~~~~~~~~~~~~
* Las **variables globales** se declaran (sin especificación de tipos, claro) al principio del fichero del modelo.
~~~~~~~~~~~~~~~~~~~~
globals [Temperatura Presion]
~~~~~~~~~~~~~~~~~~~~
* Distinguimos entre **procedimientos** (acciones, sin devolución) y **reports** (funciones, con devolución). Los parámetros de entrada se indican en la cabecera de la declaración:
~~~~~~~~~~~~~~~~~~~~linenumbers
to avanza [dist]
fd dist
end
to-report suma [a b]
report a + b
end
~~~~~~~~~~~~~~~~~~~~
* **Formato prefijo** para su llamada: los paréntesis solo son necesarios por motivos de agrupación o de delimitación de sus entradas (obligatorios en funciones vari-ádicas):
~~~~~~~~~~
(f a1 ... an)
~~~~~~~~~~
Ejemplo:
~~~~~~~~~~
(suma 3 4)
(producto (suma 3 4) 5)
suma 3 4
~~~~~~~~~~
* **Procedimientos vari-ádicos**: admiten un número variable de parámetros. No son necesarios los paréntesis cuando se usan la aridad por defecto. No son definibles por el usuario (built-in del lenguaje).
~~~~~~~~~~
(list 1 2)
(list 1 2 3 4)
list 1 2
~~~~~~~~~~
* **Procedimientos anónimos**: esencialmente, de una sola línea. Útiles en combinación con funciones de orden superior o para usarlos como objetos coleccionables. Para ejecutarlos sobre datos concretos se debe usar `run-result` (si es de tipo report) o `run` (si es de tipo acción).
~~~~~~~~~~
let fun1 [x -> 2 * x]
let fun2 [[x y] -> x + y]
(run-result fun1 2) = 4
(run-result fun2 1 2) = 3
~~~~~~~~~~
* Los **operadores binarios** deben separarse por espacios:
~~~~~~~~~~~~~~~~~~~~
let correcto 3 + 4
set incorrecto 3+4
~~~~~~~~~~~~~~~~~~~~
* **Extensiones**: Se indican en la cabecera del modelo. Proporcionan colecciones de funciones adicionales para tareas específicas (tratamiento de GIS, estructuras de datos adicionales, conexión con otros lenguajes, etc.).
~~~~~~~~~~
extensions [ext1 ... extN]
~~~~~~~~~~
Ejemplos:
~~~~~~~~~~
extensions [array]
extensions [array matrix table]
~~~~~~~~~~
* **Modularización**: Sistema muy simple de inclusión de ficheros fuente de NetLogo (`*.nls`). Puede ofrecer características similares a las librerías en otros lenguajes, pero no ofrece ningún tipo de encapsulamiento ni espacios de nombres alternativos.
~~~~~~~~~~
__includes [fichero1 ... ficheroN]
~~~~~~~~~~
Ejemplos:
~~~~~~~~~~
__includes ["BFS.nls" "Astar.nls"]
~~~~~~~~~~
* **Editor**: Incrustado en el sistema (editor + entorno de ejecución).
* **Comentarios**: La aparición de `;` determina el inicio de un comentario (marcado en gris en el editor) y se ignora el resto de la línea a partir de ese carácter.
* **Saltos de línea y tabulaciones**: Puramente estéticos y para facilitar la lectura. Podría estar escrito todo en una sola línea. Atención a los [ ].
* **Números de líneas**: Opcionales.
* **Pestaña de Código**: Detachable (a partir de NetLogo 6.x).
# Estructuras de Datos
* **Números** (no distingue tipos de números), **Booleanos** (True/False).
~~~~~~~~~~
1
3.1415
True
-5
~~~~~~~~~~
* **Listas**: sucesión ordenada y heterogénea de valores. Operaciones principales: `first`, `last`, `bf`, `bl`, `empty?`, `length`, `item`, `max`, `min`, `n-of`, `one-of`, `range`, `lput`, `fput`, `list`, `reverse`, `sentence`, `sort`, `sublist`, ...
~~~~~~~~~~
[a1 ... an]
~~~~~~~~~~
Ejemplos:
~~~~~~~~~~
[1 2 3 4]
[]
[1 "a" True]
first [1 2 3]
length [1 2]
item 2 [1 2 3]
one-of [1 2 3 4]
empty? []
(list var 1 2)
~~~~~~~~~~
Con el constructor `[]` solo se pueden crear listas de objetos constantes (no puede contener variables):
~~~~~~~~~~
[ 1 2 3 x (x + 1) ] ; error!!!
~~~~~~~~~~
Para este tipo de construcciones podemos usar la función `list` vista en los procedimientos vari-ádicos:
~~~~~~~~~~
(list 1 2 3 x (x + 1) ) ; correcto!!!
~~~~~~~~~~
* **Cadenas**. Similares a otros muchos lenguajes. Operaciones principales: (similares a listas), `word`, `substring`, ...
~~~~~~~~~~
"cadena"
(word "a" "b")
"abc" > "bc"
~~~~~~~~~~
* **arrays**, **matrices**, **diccionarios/tablas**: Por medio de extensiones.
* **Agentes**: Ver sección siguiente.
* **Agentsets**: Ver sección siguiente.
# Agentes
Se pueden tratar como estructuras de datos especiales, que pueden ser agrupadas en colecciones. Propiedades personalizables. Disponen de métodos específicos (pueden verse como una versión muy específica de la programación orientada a objetos).
* Tres tipos:
* **Turtles**: Agentes de tipo móvil, con propiedades: `xcor`, `ycor`, `color`, `heading`, `shape`, `breed`, ...
* **Patches**: Agentes de tipo inmóvil, forman una teselación rectangular del plano, con propiedades: `pxcor`, `pycor`, `pcolor`, ...
* **Links**: Agentes de conexión entre turtles, con propiedades: `end1`, `end2`, `color`, ...
* Accesos a las colecciones completas de cada uno de los tipos (de tipo Agentset):
~~~~~~~~~~~~
turtles ; Devuelve un objeto con todos los agentes de tipo turtles
patches ; Idem para patches
links ; Idem para links
~~~~~~~~~~~~
* Se pueden agrupar en colecciones personalizables: **Agentsets**.
~~~~~~~~~~~~
let RedTurtles turtles with [color = red]
let PosPatches patches with [pxcor > 0 and pycor > 0]
~~~~~~~~~~~~
* **Creación de especies de turtles**: Crea un subtipo de turtles.
~~~~~~~~~~~~
breed [grupo individuo]
breed [nodos nodo]
~~~~~~~~~~~~
* **Creación de especies de links**: Crea un subtipo de link que puede ser dirigido o no dirigido.
~~~~~~~~~~~~
directed-link-breed [grupo individuo]
undirected-link-breed [grupo individuo]
~~~~~~~~~~~~
* **Propiedades personalizables**. Se declaran al principio del modelo (solo el nombre):
~~~~~~~~~~~~
turtles-own [...]
patches-own [...]
links-own [...]
breed-own [...]
~~~~~~~~~~~~
# Estructuras de Programación
* `repeat`:
~~~~~~~~~~
repeat N [
comandos
]
~~~~~~~~~~
Ejemplo:
~~~~~~~~~~
let suma 0
let i 1
repeat 4 [
set suma suma + i
set i i + 1
]
~~~~~~~~~~
* `while`:
~~~~~~~~~~
while [condicion] [
comandos
]
~~~~~~~~~~
Ejemplo:
~~~~~~~~~~
let n 10
let fact 1
while [n > 0] [
set fact fact * n
set n n - 1
]
~~~~~~~~~~
* `if`, `ifelse`, `ifelse-value`(report):
~~~~~~~~~~
if condicion [comandos]
ifelse condicion [comandos-SI] [comandos-NO]
ifelse-value condicion [valor-SI] [valor-NO]
~~~~~~~~~~
Ejemplos:
~~~~~~~~~~
if n > 10 [set n n - 10]
ifelse n > 10 [set n n - 10] [set n n + 10]
ifelse-value n > 10 [True] [False]
~~~~~~~~~~
* `ask`, `ask...with`:
~~~~~~~~~~
ask coleccion-agentes [comandos]
~~~~~~~~~~
Ejemplos
~~~~~~~~~~
ask turtles [set color blue]
ask turtles with [color = blue] [set color red]
~~~~~~~~~~
# Funciones de colecciones
* `map`: Aplica una función a todos los términos de una lista.

~~~~~~~~~~
f:X -> X
map f [a1 ... an] = [(f a1) ... (f an)]
g: X^k -> X
(map g [a11...a1n] ... [ak1...akn]) = [(g a11...ak1) ... (g a1n ... akn)]
~~~~~~~~~~
Ejemplos:
~~~~~~~~~~
to-report doble [x]
report 2 * x
end
map doble [1 2 3 4] = [2 4 6 8]
map [x -> 2 * x] [1 2 3 4] = [2 4 6 8]
to-report suma [x y]
report x + y
end
(map suma [1 2 3] [4 5 6]) = [5 7 9]
(map [[x y] -> x + y] [1 2 3] [4 5 6]) = [5 7 9]
~~~~~~~~~~
* `reduce`: Aplica iteradamente una función binaria sobre los elementos de una lista hasta reducirla a un solo valor.

~~~~~~~~~~
f:X^2 -> X
reduce f [a1] = a1
reduce f [a1 a2 a3 ... an] = [(f a1 a2) a3 ... an]
~~~~~~~~~~
Ejemplo:
~~~~~~~~~~
reduce + [1 2 3 4 5] = 15
~~~~~~~~~~
* `filter`: Filtra los términos de una lista en función de un predicado (función booleana).

~~~~~~~~~~
filter predicado [a1 ... an]
~~~~~~~~~~
Ejemplo:
~~~~~~~~~~
to-report positivo [x]
report x > 0
end
filter positivo [-1 1 -2 2 -3] = [1 2]
filter [x -> x > 0] [-1 1 -2 2 -3] = [1 2]
~~~~~~~~~~
* `foreach`: Aplica un conjunto de comandos a cada elemento de una lista (también es vari-ádico).
~~~~~~~~~~
foreach [a1...an] [comandos]
(foreach [a1...an]...[z1...zn] [comandos])
~~~~~~~~~~
Ejemplos:
~~~~~~~~~~
foreach [1 2 3 4] [x -> show x]
foreach [1 2 3 4] show
(foreach [1 2 3] ["a" "b" "c"] [[x y] -> show (word x "," y)])
~~~~~~~~~~
* `n-values`: Genera una lista a partir de un procedimiento (actúa como un `map` sobre un rango).
~~~~~~~~~~
n-values n f = map f [0 ... n-1]
~~~~~~~~~~
Ejemplo:
~~~~~~~~~~
n-values 5 [x -> 2 * x] = [0 2 4 6 8]
~~~~~~~~~~
* `sort-by`: Ordena la lista haciendo uso del predicado que se proporciona.
~~~~~~~~~~
sort-by predicado [a1 ... an]
~~~~~~~~~~
Ejemplo:
~~~~~~~~~~
sort-by [ [x y] -> first x < first y] [ [2 4] [1 5] [3 3] ] = [ [1 5] [2 4] [3 3] ]
sort-by [ [x y] -> last x < last y] [ [2 4] [1 5] [3 3] ] = [ [3 3] [2 4] [1 5] ]
~~~~~~~~~~
# Listas y agentes
## Listas de Agentes
* Los conjuntos de agentes se procesan siempre en orden aleatorio (distinto cada vez que se accede a ellos). Recuérdese que un conjunto no tiene definido ningún orden implícito.
* Si se quiere fijar un orden en el conjunto de agentes se deben transformar en **lista de agentes** (y entonces usar `shuffle` o `sort-by`).
* Una lista de agentes se comporta como cualquier lista y se pueden usar funciones de orden superior sobre ella (pero ya no se pueden usar estructuras que trabajan sobre conjuntos de agentes, como `ask`):
~~~~~~~~~~
foreach lista-agentes
[ x -> ask x lista-comandos]
~~~~~~~~~~
* Casos especiales: `(sort conjuntoAgentes)` devuelve una lista con los agentes ordenados según su identificador (numéricamente por `who` en el caso de turtles, de izquierda a derecha y de arriba a abajo en el caso de patches).
## Listas de Propiedades
* Extraer la lista de todos los valores de una cierta propiedad de un grupo de agentes:
~~~~~~~~~~
[propiedad] of conjuntoAgentes
~~~~~~~~~~
Ejemplo:
~~~~~~~~~~
[who] of turtles
~~~~~~~~~~
* Extraer la lista de todos los valores de un cierto report sobre un grupo de agentes:
~~~~~~~~~~
[report] of conjuntoAgentes
~~~~~~~~~~
Ejemplo
~~~~~~~~~~
[(list xcor ycor)] of turtles
~~~~~~~~~~
* **Importante**: el orden en que se extraen es aleatorio, así que la lista que se obtenga no es exactamente la misma si se repite la ejecución sobre un mismo conjunto.
!!!warn:Trabajo en Proceso
¿Echas algo en falta? Coméntamelo y lo iré ampliando con las sugerencias recibidas.