« Usando Patches de Net… « || Inicio || » NetLogo: Procedimient… »

NetLogo: Estructuras del lenguaje

Última modificación: 7 de Octubre de 2020, y ha tenido 4774 vistas

Etiquetas utilizadas: || || ||

Agentes

Como se comentó en el capítulo introductorio, NetLogo trabaja con tres tipo de agentes bien diferenciados: el observador (que es único), las tortugas (que representan los individuos móviles) y los patches (que representan una unidad de mundo en la que se mueven las tortugas).

Es importante comprender que todo el código que deba ejecutar un agente (o un grupo de agentes) debe estar dentro de un contexto adecuado al tipo de agente. Es decir, no podemos enviarle a un agente de tipo patch un comando que corresponde únicamente a uno de tipo tortuga, o a una tortuga un comando propio del observador. Para establecer este contexto el sistema ofrece tres alternativas:

  • En un botón, por medio de la selección del tipo de agente al que está enlazado en el momento de su creación (es una propiedad editable posteriormente, aunque no en tiempo de ejecución).
  • En el centro de comandos, análogo al caso del botón.
  • Por medio del comando ask para pedir que los agentes (solo tortugas y patches) ejecuten una lista de comandos.

La estructura general de este último comando es:

ask grupo-de-agentes [lista de comandos]

Por ejemplo:

ask turtles [
    set color red
    fd 5
]

Lo que hemos denotado por grupo-de-agentes puede ser, o bien todo la colección de agentes de un tipo (turtles o patches) o bien una subgrupo de ellos. Este último caso es lo que se denomina un conjunto de agentes, y lo veremos con más profundidad un poco más adelante en ese mismo cápítulo.

Cada tortuga creada tiene un número de identificación (ID) que es asignado de forma sucesiva y creciente comenzando opr 0. La primitiva turtle nos permite acceder a una tortuga en particular por medio de su identificador, por ejemplo:

ask turtle 0 [
    set color blue
]

En el caso de los patches, sus individuos se identifican por las coordenadas que ocupan en el mundo. La primitiva patch toma como entrada las coordenadas y devuelve el patch correspondiente. Por ejemplo:

ask patch 1 3 [
    set pcolor red
]

En el caso de los patches también disponemos de una primitiva, patch-at, que nos permite referirnos a ellos desde una posición relativa a otro agente indicando los incrementos en ambas coordenadas. Por ejemplo:

ask turtle 0 [
    ask patch-at 1 0 [ 
set pcolor red
]
]

Conjuntos de Agentes

Un conjunto de agentes puede contener individuos de la familia de tortugas o de la familia de patches, pero no elementos de ambos tipos simultáneamente.

Un conjunto de agentes no tiene un orden particular, y cada vez que se accede a él se hace en un orden distinto, de esta forma, ninguno de los individuos que lo componen tiene características diferenciadoras frente a los demás. Ya hemos visto una primitiva que devuelve un conjunto de agentes compuesto por todas las tortugas disponibles, turtles, y otra que devuelve un conjunto de agentes compuesto por todos los patches, patches.

Pero la potencia real de los conjuntos de agentes se pone de manifiesto al permitir construir conjuntos que no contienen a todos los individuos, sino únicamente algunos de ellos. Por ejemplo, el conjunto de tortugas rojas, el conjunto de patches con coordenada pxcor divisible por 5 o el conjunto de tortugas que están sobre un patch de color verde. Tras la generación de un conjunto de agentes, podemos hacer que realicen un conjunto de operaciones (solo ellos) por medio de la primitiva ask.

Algunos ejemplos iniciales son (más adelante veremos los diferentes métodos que proporciona NetLogo para producir conjuntos de agentes):

  • Tortugas Rojas:
    turtles with [color = red]
  • Tortugas en el patch actual con color verde:
    turtles-here with [color = red]
  • Patches en coordenada pxcor positiva:
    patches with [pxcor > 0]
  • Tortugas no más alejadas de 3 patches del patch actual:
    turtles in-radius 3
  • Los cuatro patches en las direcciones cardinales respecto al actual:
    patches at-points 1
  • Tortugas en el primer cuadrante sobre un patch verde:
    turtles with [(xcor > 0) and (ycor > 0) and (pcolor = green)]
  • Tomar un agente al azar entre un conjunto de agentes: one-of
    ask one-of patches [ sprout 1 [ ] ]
  • Usar los reporters max-one-of o min-one-of para encontrar qué agente es el que alcanbza el máximo o mínimo de algún valor. Por ejemplo, para eliminar el agente que sea más rico:
    ask max-one-of turtles [sum dinero] [ die ]

Hay tres operaciones básicas sobre un conjunto de agentes:

  • Pedirles que realicen una secuencia de comandos:
    ask conj-agentes [lista-comandos]
  • Ver si el conjunto es vacío:
    any? conj-agentes
  • Contar cuántos individuos tiene el conjunto:
    count conj-agentes

Y hay tres conjuntos de agentes especiales: no-turtles, no-patches y no-links, para indicar un conjunto vacío de cada uno de los tipos principales.

Variables/Propiedades

Las variables en NetLogo, como en cualquier lenguaje de programación, son objetos que nos permiten almacenar valores (como números, texto, etc.). Normalmente, cuando estamos trabajando en un lenguaje de programación que admite la definición de programas por medio de un conjunto de procedimientos y funciones, las variables se distinguen entre:

  • Globales: se definen al principio del programa y todos los procedimientos que pueden acceder a su contenido para leerlo o para modificarlo; y
  • Locales: se definen para un procedimiento en particular y solo se puede acceder a ella por medio del código de ese procedimiento.
Además, en NetLogo existen variables que dependen de los agentes. La diferencia principal entre estas variables y las globales es que si una variable es global, existe un único valor de la misma, pero si una variable es de agente, entonces para cada uno de los agentes la variable puede tener un valor distinto (por ejemplo, la variable sexo que definimos en el ejemplo de introducción). El sistema viene ya con algunas variables definidas para los agentes, por ejemplo, la variable color que almacena en las tortugas el color que muestra, o su equivalente pcolor para los patches (suele ser habitual que las variables con significado común entre tortugas y patches se diferencian porque para estos últimos empiezan con la letra "p"). Ejemplos de otras variables asociadas a agentes que trae el sistema son: xcor, ycor, heading (en tortugas) y pxcor, pycor (en patches).

Definir variables

Una forma directa de definir variables globales se realiza por medio de la inclusión de elementos específicos (como selectores deslizantes y switches) en el interfaz. Para definir variables globales basta usar el comando globals, y proporcionar la lista de variables que se quieren definir como globales entre corchetes:

globals lista-variables

Por ejemplo:

globals [Pasos Temperatura]

Para definir variables asociadas a agentes tenemos dos comandos (dependiendo de si son variables asociadas a tortugas, patches y links) que se usan de igual forma:

turtles-own lista-variables
patches-own lista-variables
links-own lista-variables

Por ejemplo:

turtles-own [energia velocidad]
patches-own [rozamiento]
links-own [peso]

Lectura y modificación

En general, para acceder al valor de una variable basta usar su nombre (el uso de las variables asociadas a agentes debe realizarse desde dentro de un entorno que especifique a qué agente nos referimos, y en ese caso, el nombre de la variable devolverá el valor de la variable asociada a dicho agente).

Para modificar el valor de una variable, se debe hacer uso del comando:

set nombre-variable valor

Por ejemplo:

set Temperatura 35
set Temperatura (Temperatura + 1)

Las variables globales, como hemos dicho, son accseibles en cualquier momento por cualquier agente.

Además, las tortugas pueden leer y modificar los valores del patch sobre el que están directamente. Así, por ejemplo:

ask turtles [set pcolor blue]

provoca que los patches sobre los que hay tortugas se pongan de color azul. (Debido a que las tortugas pueden modificar las variables de los patches, el NetLogo no permite llamar de igual forma a variables de estos dos tipos de agentes).

Variables Locales

Una variable local se define y usa en el contexto de un procedimiento particular o una parte suya (un conjunto de comandos enmarcado entre corchetes). Para crear una variable local se usa el comando let, que permite asignarle directamente el valor (es obligatorio asignar un valor inicial en el momento de crear una variable local):

let variable valor

Las variables locales solo tienen validez dentro del bloque en el que se han creado (puede ser un procedimiento o un bloque de una estructura tipo ask, foreach, repeat, etc.) y se destruyuen una vez ejecutado dicho bloque.

Listas

Debido a que NetLogo está basado en el lenguaje de programación Logo, no nos debe sorprender que una de las piedras fundamentales sobre las que descansa sea el concepto de lista.

Una lista es una estructura de datos que permite almacenar múltiples piezas de información encapsuladas en un solo objeto. En NetLogo las listas son suficientemente flexibles como para poder almacenar información de diversos tipos, como números, cadenas de texto, agentes, conjuntos de agentes o incluso otras listas.

A medida que vayamos construyendo con NetLogo modelos más complejos, nos iremos dando cuenta que esta estructura de datos es especialmente útil y proporciona una potencia difícil de alcanzar con variables normales (atómicas).

Listas Constantes

Para crear una lista basta poner los elementos que la forman entre corchetes y separados por espacios; por ejemplo [2 4 6 8] o 2. Existe una lista de especial importancia que es la lista vacía, que simplemente se denota con los corchetes pero sin poner ningún valor en si interior: [].

Construcción de listas

Si se desea crear una lista cuyos valores no conocemos a priori (por ejemplo, que sean el resultado de una función), no podemos hacer uso de los corchetes, que solo funcionan para las listas constantes, pero disponemos del comando list, que recibe una cantidad variable de argumentos y devuelve la lista formada por esos argumentos en el orden dado.

(list a_0 a_1 ... a_n) --> [a_0 a_1 ... a_n]

Nota: es importante poner el comando completo entre paréntesis, ya que es la forma en que NetLogo puede saber qué argumentos se le están pasando para formar la lista (recuerda que puede recibir una cantidad arbitraria de argumentos). Si solo se le pasan dos argumentos, no es necesario poner los paréntesis, porque es la entrada que por defecto espera el comando.

Un comando similar pero que es capaz de trabajar a nivel de listas también es sentence, que genera una lista con los elementos que se le pasen (como hace list) pero con la peculiaridad de que si alguno de ellos es una lista, añade sus elementos en ese orden. Por ejemplo:

sentence 1 2               --> [1 2]
sentence 1 [2 3] --> [1 2 3]
(sentence 1 [2 3] 4 [5 6]) --> [1 2 3 4 5 6]
(sentence 1 [[2 3] 4] 5) --> [1 [2 3] 4 5]

A continuación veremos algunas de las funciones que NetLogo trae implementadas para trabajar sobre listas.

Acceso a listas

En los lenguajes de programación que trabajan con listas hay dos funciones esenciales sobre ellas (y que junto con el concepto de recursión, permiten definir todos los demás), y que respectivamente permiten acceder a la cabeza de la lista (el primer elemento por la izquierda) y la cola de la lista (el resto de objetos eliminando la cabeza). En NetLogo estas fuciones son:

first [a_0 a_1 ... a_n]     --> a_0
but-first [a_0 a_1 ... a_n] --> [a_1 ... a_n]

Adicionalmente, disponemos de funciones similares como son:

last [a_0 .. a_n b]     --> b
but-last [a_0 .. a_n b] --> [a_0 .. a_n]
one-of [a_0 .. a_n] --> a_j (un elemento aleatorio de la lista)
n-of n ls --> [a_j1 ... a_jn] (toma aleatoriamente n elementos de la lista ls)
item i [a_0 .. a_n] --> a_i (el elemento i-ésimo, el primer índice es 0)

También disponemos de funciones que permiten añadir o modificar elementos de una lista (debe notarse que en algunos casos no modifican la lista original, sino que generan otra lista con la modificación realizada):

fput b [a_0 ... a_n]            --> [b a_0 ... a_n]
lput b [a_0 ... a_n] --> [a_0 ... a_n b]
remove b [a_0 ... a_n] --> devuelve la lista eliminado todas las apariciones de b
remove-duplicates [a_0 ... a_n] --> devuelve la lista eliminando todos los elementos duplicados
(dejando solo las primeras apariciones de los mismos)
remove-item i [a_0 ...a_i-1 a_i a_i+1 ... a_n] --> [a_0 ... a_i-1 a_i+1 ... a_n]
replace-item i [a_0 ...a_i-1 a_i a_i+1 ... a_n] b --> [a_0 ...a_i-1 b a_i+1 ... a_n]

Además, disponemos de funciones que proporcionan información diversa relacionada con las listas:

  • empty? ls : devuelve true si ls es vacía ([]) y false en caso contrario.
  • is-list? var : devuelve true si var es de tipo lista, y false en caso contrario.
  • length [a_1 ... a_n] : devuelve n.
  • member? b ls : devuelve true si b es un elemento de la lista ls, y false en caso contrario.
  • modes ls : devuelve la moda de la lista ls (el valor que más se repite).
  • position b ls : devuelve la primera posición en que aparece b en la lista ls, o false si no aparece.
  • reverse [a_0 ... a_n] : devuelve [a_n ... a_0]
  • shuffle ls : devuelve una lista con los mismos elementos que ls, pero en orden aleatorio.
  • sort ls : devuelve una lista con los mismo elementos que ls, pero ordenados crecientemente. Si la lista contiene números y elementos no numéricos, elimina estos últimos. Pero si ninguno es numérico y hay al menos una cadena de texto, ordena la lista alfabéticamente.
  • sort-by [predicado] ls : devuelve la lista ls ordenada de acuerdo al perdicado que se le pase (que debe ser binario porque se aplicará sobre pares de elementos de ls para compararlos).
  • sublist [a_0 ... a_n] i j : devuelve [a_i .. a_j-1]

Listas de Propiedades

Para quedarnos con la lista de todos los valores de una cierta propiedad de un grupo de agentes basta usar la partícula of:

[propiedad] of conjunto-agentes

Y podemos usar una propiedad directamente, o incluso un reporte que trabaja sobre los agentes y devuelve un valor (posiblemente, usando sus propiedades). Por ejemplo:

[who] of turtles

devolverá una lista de identificadores de las tortugas que haya en el mundo.

[ max contenido ] of patches

devolverá, suponiendo que cada patch tiene una propiedad contenido (que es una lista), una lista con los máximos de los contenidos de cada patch.

« Usando Patches de Net… « || Inicio || » NetLogo: Procedimient… »