|
Commands14
Commands(Modeling Guide)
Table of ContentsGeneral syntaxA command is a keyword, followed by specific attributes, some of them mandatory (in bold), some of them optional. One of the attribute names can be ommitted (the one that is omissible in the sequel). It has to be the first one. command_keyword expression1 attribute2: expression2 ... ; or command_keyword attribute1: expression1 attribute2: expression2 ...; If the command encloses other commands, they are declared between curly brakets, as in: command_keyword1 expression1 attribute2: expression2... {
command_keyword2 expression1 attribute2: expression2...;
command_keyword3 expression1 attribute2: expression2...;
}addAttributes
DefinitionAllows the agent to add, i.e. to insert, a new element in a container (a list, matrix, map, ...). The new element can be added either at the end of the container or at a particular position. Incorrect use: The addition of a new element at a position out of the bounds of the container will produce a warning and let the container unmodified. add expr to: expr_container; // Add at the end add expr at: expr to: expr_container; // Add at position expr Note that the behavior and the type of the attributes depends on the specific kind of container.
In the case of list, the expression in the attribute at: should be an integer. let emptyList type: list value: []; add 0 at: 0 to: emptyList ; // emptyList now equals [0] add 10 at: 0 to: emptyList ; // emptyList now equals [10,0] add 25 at: 2 to: emptyList ; // emptyList now equals [10,0,20] add 50 to: emptyList; // emptyList now equals [10,0,20,50]
This command can not be used on matrix. Please refer to the command `put`.
As a map is basically a list of pairs key::value, we can also use the add command on it. It is important to note that the behavior of the command is slightly different, in particular in the use of the at attribute. let emptyMap type: map value: []; add "val1" at: "x" to: emptyMap; // emptyList now equals [x::val1] If the at: attribute is ommitted, a pair null::expr_item will be added to the map. An important exception is the case where the is a pair expression: in this case the pair is added. add "val2" to: emptyMap; // emptyList now equals [null::val2, x::val1] add 5::"val4" to: emptyMap; // emptyList now equals [null::val2, 5::val4, x::val1] Notice that, as the key should be unique, the addition of an item at an existing position (i.e. existing key) will only modify the value associated with the given key. add "val3" at: "x" to: emptyMap; // emptyList now equals [null::value2, 5::val4, x::val3] askAttributes
DefinitionAllows an agent, the sender agent, to ask another (or other) agent(s) to perform a set of commands. It obeys the following syntax, where the target attribute denotes the receiver agent(s): ask receiver_agent(s) {
[commands]
}
Or
ask target: receiver_agent(s) {
[commands]
}If the value of the target attribute is nil or empty, the command is ignored. The species of the receiver agents must be known in advance for this command to compile. If not, it is possible to cast them using the as attribute, like : ask receiver_agent(s) as: a_species_expression {
[command_set]
}Alternative forms for this casting are :
ask species_name (receiver_agent) {
[command_set]
}
ask receiver_agents of_species species_name {
[commands]
}Any command can be declared in the block commands. All the commands will be evaluated in the context of the receiver agent(s), as if they were defined in their species, which means that an expression like *self* will represent the receiver agent and not the sender. If the sender needs to refer to itself, some of its own attributes (or temporary variables) within the block commands, it has to use the keyword *myself*. species animal {
var energy type: float init: rnd (1000) min: 0.0 {
reflex when: energy > 500 { // executed when the energy is above the given threshold
let others type: list of: animal value: (self neighbours_at 5) of_species animal; // find all the neighbouring animals in a radius of 5 meters
let shared_energy type: float value: (energy - 500) / length (others); // compute the amount of energy to share with each of them
ask others { // no need to cast, since others has already been filtered to only include animals
if (energy < 500) { // refers to the energy of each animal in others
set energy value: energy + myself.shared_energy; // increases the energy of each animal
set myself.energy value: myself.energy - myself.shared_energy; // decreases the energy of the sender
}
}
}
}NoticeIf the target is an addition of list like "target = (list speciesA) + (list speciesB)", the temporary built list will use the default cast from the first list and won't add the second list as the elements are from a different type. captureAttributes
DefinitionAllows an agent to capture other agent(s) as its micro-agent(s). The preliminary for an agent A to capture an agent B as its micro-agent is that the A's species must defined a micro-species which is a sub-species of B's species (cf. Nesting species). species B {
...
}
species A {
...
species C parent: B {
...
}
...
}
capture list(A) as: C; or capture target: list (A) as: C; createAttributes
DefinitionAllows an agent to create *number* agents of species *species*, to create agents of species *species* from a shapefile or to create agents of species *species* from one or several localized entities (discretization of the localized entity geometries). Its simple syntax is:
create a_species number: an_int; or create species: a_species number: an_int; If *number* equals 0 or species is not a species, the command is ignored.
create a_species from: the_shapefile with: [type:: 'TYPE_OCC', nature::'NATURE']; One agent will be created by object contained in the shapefile. In this example, we assume that for the species *a_species*, two variables *type* and *nature* are declared and that their type corresponds to the types of the shapefile attributes.
create a_species from: [agentA, agentB, agentC]; Two types of discretization exist:
create a_species from: [agentA, agentB, agentC] type: 'Triangles' size: 10.0;
create a_species from: [agentA, agentB, agentC] type: 'Squares' size: 10.0; The agents created are initialized following the rules of their species. If one wants to refer to them after the command is executed, the returns keyword has to be defined: the agents created will then be referred to by the temporary variable it declares. For instance, the following command creates 0 to 4 agents of the same species as the sender, and puts them in the temporary variable children for later use. create species (self) number: rnd (4) returns: children;
ask children {
...
}If one wants to specify a special initialization sequence for the agents created, create provides the same possibilities as ask. This extended syntax is: create a_species number: an_int {
[commands]
}The same rules as in ask apply. The only difference is that, for the agents created, the assignments of variables will bypass the initialization defined in species. For instance: create species(self) number: rnd (4) returns: children {
set location value: myself.location + {rnd (2), rnd (2)}; // tells the children to be initially located close to me
set parent value: myself; // tells the children that their parent is me (provided the variable parent is declared in this species)
}doAttributes
Enclosed tags
DefinitionAllows the agent to execute an action or a primitive. For a list of primitives available in every species, see this page; for the list of primitives defined by the different skills, see this page. Finally, see this page to know how to declare custom actions. The simple syntax (when the action does not expect any argument and the result is not to be kept) is: do name_of_action_or_primitive; or do action: name_of_action_or_primitive; In case the result of the action needs to be made available to the agent, the returns keyword has to be defined; the result will then be referred to by the temporary variable declared in this attribute: let result value: self name_of_action_or_primitive []; or let result value: name_of_action_or_primitive(self, []); In case the action expects one or more arguments to be passed, they are defined by using facets, enclosed tags or a map. We can have the three following notations: do name_of_action_or_primitive arg1: expression1 arg2: expression2; which is equivalent to: do name_of_action_or_primitive {
arg arg1 value: expression1;
arg arg2 value: expression2;
...
}or to: do name_of_action_or_primitive with: [arg1::expression1, arg2::expression2]; In the case of an action returning a value, we can only use facets or a map as follows: do name_of_action_or_primitive arg1: expression1 arg2: expression2 returns: result; or let result value: self name_of_action_or_primitive [arg1::expression1, arg2::expression2]; or let result value: name_of_action_or_primitive(self, [arg1::expression1, arg2::expression2]); ifAttributes
Following tags
DefinitionAllows the agent to execute a sequence of commands if and only if the condition evaluates to true. The generic syntax is: if bool_expr {
[commands]
}
or
if condition: bool_expr {
[commands]
}Optionally, the commands to execute when the condition evaluates to false can be defined in a following command else. The syntax then becomes: if bool_expr {
[commands]
}
else {
[commands]
}ifs and elses can be imbricated as needed. For instance: if bool_expr {
[commands]
}
else if bool_expr2 {
[commands]
}
else {
[commands]
}letAttributes
DefinitionAllows the agent to declare a temporary variable, local to the scope in which it is defined. The naming rules follow those of the variable declarations. In addition, a temporary variable cannot be declared twice in the same scope. The generic syntax is: let temp_var1 type: a_datatype value: an_expression; If the datatype of the variable is not specified, it is inferred from that of the expression (which can be enforced using casting operators if necessary). After it has been declared this way, a temporary variable can be used like regular variables (for instance, the set command should be used to assign it a new value within the same scope). loopAttributes
DefinitionAllows the agent to perform the same set of commands either a fixed number of times, or while a condition is true, or by progressing in a collection of elements or along an interval of integers. The basic syntax for each of these usages are: loop times: an_int_expression {
[commands]
}Or: loop while: a_bool_expression {
[commands]
}Or: loop a_temp_var over: a_list_expression {
[commands]
}Or: loop a_temp_var from: int_expression_1 to: int_expression_2 {
[commands]
}
loop a_temp_var from: int_expression_1 to: int_expression_2 step: int_expression3{
[commands]
}In these latter two cases, the var attribute designates the name of a temporary variable, whose scope is the loop, and that takes, in turn, the value of each of the element of the list (or each value in the interval). For example, in the first instance of the "loop over" syntax : let a type: int value: 0;
loop i over: [10, 20, 30] {
set a value: a + i;
} // a now equals 60The second (quite common) case of the loop syntax allows one to use an interval of integers. The from and to attributes take a a integer expression as arguments, with the first (resp. the last) specifying the beginning (resp. end) of the interval. The step is assumed equal to 1. let the_list value:list (species_of (self)) {
loop i from: 0 to: length (the_list){
ask target: the_list at i {
...
}
} // every agent of the list is asked to do somethingBe aware that there are no prevention of infinite loops. As a consequence, open loops should be used with caution, as one agent may block the execution of the whole model. putAttributes
DefinitionAllows the agent to replace a value in a container at a given position (in a list or a map) or for a given key (in a map). The allowed parameters configurations are the following: put expr at: expr in: expr_container; put all: expr in: expr_container; Note that the behavior and the type of the attributes depends on the specific kind of container:
let testList type: list value: [1,2,3,4,5]; // testList now contains [1,2,3,4,5] put -10 at: 1 in: testList; // testList now contains [1,-10,3,4,5] put all: 10 in: testList; // testList now contains [10,10,10,10,10]
let testMat type: matrix value: [[0,1],[2,3]]; //testMat now contains [[0,1],[2,3]]
put -10 at: {1,1} in: testMat; //testMat now contains [[-10,1],[2,3]]
put all: 10 in: testMat; //testMat now contains [[10,10],[10,10]]
let testMap type: map value: ["x"::4,"y"::7]; //testMap now contains ["x"::4,"y"::7] put -10 key: "y" in: testMap; //testMap now contains ["x"::4,"y"::10] put -20 key: "z" in: testMap; //testMap now contains ["x"::4,"y"::7, "z"::-20] put all: -30 in: testMap; //testMap now contains ["x"::-30,"y"::-30, "z"::-30] releaseAttributes
DefinitionAllows an agent to release its micro-agent(s). The preliminary for an agent to release its micro-agents is that species of these micro-agents are sub-species of other species (cf. Nesting species). The released won't be micro-agents of the calling agent anymore. Being released from a macro-agent, the micro-agents will change their species and host (macro-agent) . species A {
}
species B {
species C parent: A {
}
species D {
}
}Agents of "C" species can be released from a "B" agent to become agents of A species. Agents of "D" species cannot be released from the "A" agent because species "D" has no parent species.
release target: list (C); The "C" agent will change to "A" agent. The won't consider "B" agent as their macro-agent (host) anymore. Their host (macro-agent) will the be the host (macro-agent) of the "B" agent. removeAttributes
DefinitionAllows the agent to remove an element from a container (a list, matrix, map...). This command should be used in the following ways, depending on the kind of container used and the expected action on it: remove expr from: expr_container remove index: expr from: expr_container remove key: expr from: expr_container remove all: expr from: expr_container
In the case of list, the attribut item: is used to remove the first occurence of a given expression, whereas all is used to remove all the occurences of the given expression. let testList type: list value: [3,2,1,2,3]; //testList now contains [3,2,1,2,3] remove 2 from: listTest; // testList now contains [3,1,2,3] remove all: 3 from: listTest; // testList now contains [1,2] remove index: 1 from: listTest;
This command can not be used on matrix.
In the case of map, the attribute key: is used to remove the pair identified by the given key. let mapTest type: map value: ["x"::5, "y"::7]; // mapTest now contains ["x"::5, "y"::7] remove key: "x" from: mapTest; // mapTest now contains ["y"::7] returnAttributes
DefinitionAllows to specify which value to return from the evaluation of the surrounding command. Usually used within the declaration of an action. Contrary to other languages, using return does not stop the evaluation of the surrounding command (for instance, a loop). It simply indicates what value to return: if it is inside a loop, then, only the last evaluation of return will be returned. Example: action foo {
return 'foo';
}
...
reflex {
let foo_result type: string value: self.foo [];
do write {
arg message value: foo_result;
}
}
// the agent will print foo on the console at each stepIn the specific case one wants an agent to ask another agent to execute a command with a return, it can be done similarly to: Species A:
action foo_different {
return 'foo_not_same';
}
---
Species B
reflex
let temp type: string value: some_agent_A.foo_different [];
do write {
arg message value: temp;
}
}
// the agent will print foo_not_same on the console at each stepsaveAttributes
DefinitionAllows to save the localized entities of species *species* into a particular kind of file (shapefile, text or csv...). The type can be "shp", "text" or "csv". Its simple syntax is: save species: a_species to: the_shapefile type: a_type_file; setAttributes
DefinitionAllows the agent to assign a value to a variable. See this section to know how to access variables. Examples: set my_var value: expression; set temp_var value:expression; set global_var value:expression; The variable assigned can be accessed in the value atribute. In that case, it represents the value of the variable before it has been modified. Examples (with temporary variables): let my_int type: int value: 1000; set my_int value: my_int + 1; // my_int now equals 1001 switchAttributes
Embedded tags
DefinitionThe "switch... match" statement is a powerful replacement for imbricated "if ... else ..." constructs. All the blocks that match are executed in the order they are defined. The block prefixed by default is executed only if none have matched (otherwise it is not). Examples: switch an_expression {
match value1 {...}
match_one [value1, value2, value3] {...}
match_between [value1, value2] {...}
default {...}
}Example: switch 3 {
match 1 {do write with: [message::"Match 1"]; }
match 2 {do write with: [message::"Match 2"];}
match 3 {do write with: [message::"Match 3"]; }
match_one [4,4,6,3,7] {do write with: [message::"Match one_of"];}
match_between [2, 4] {do write with: [message::"Match between"];}
default {do write with: [message::"Match Default"];}
}
| |