Ps-i 2.2 - routines

General description

A routine are used to explain ps-i how to compute quantities specific to a particular model. Writing a routine is very much like using a calculator. In fact the name "routine" was chosen specifically to remind a person used to C or C++ that these are not functions in the sense of these programming languages.

Using routines

Routines take no arguments. Rather, there is a global notion of "current agent". Before any routine is execute the "current agent" is set to point to a particular agent on a field. Thus if you routine is told to look for the value of attribute influence the particular value it obtains depends on particular current agent. There are several types of routines: You can see the list of all functions currently known to Ps-i (this can depend upon the model loaded) by opening "Main menu->Help->Routine Browser" window.

Section format

Example:
routine 'test1' composite
	comment 'An example'
	code "[inactive]*([influence]+6)"
end
Each routine has a distinct name, a type and a comment. Other directives vary depending on the type of the routine.

Builtin routines and prototype routines

These require no declaration in the model

Customized routines

Example:
routine 'identity_poll' from 'sum_over'
	comment 'Computes identity count around the current agent'
	parameters "agent_range" "activated([cache])==$1"  "agent_influence"
end
This type of routine specifies from which routine it was derived. You should also specify a parameters directive. The number of parameters vary depending on which prototype routine was used. In the above example a customized routine "cache_activated" is derived from prototype routine "activated" by specifying which attribute to use. The routine "cache_activated" will thus return the activated identity in attribute "cache" (assumed to be of type repertoire). Note: due to time constraints no type checking was implemented (however the necessary hooks are in place). Though you can use attribute of any type in the above example only attributes of repertoire type will produce meaningful numbers.

Composite routines

Example:
routine 'test1' composite
	comment 'An example'
	code "[inactive]*([influence]+6)"
end

You can use three directives, beside comment, during routine declaration.
code "expression" is used to specify an expression, which is computed to obtain routine value.
default "expression" is synonymous to code and is provided for extra code readability.
when "condition" "expression" must always be followed by code or default, or another when directive. It evaluates condition and when true computes expression, othewise it computes the value of directives following it.
Example:

routine 'agent_range' composite
	comment 'Returns range of an agent'
	when "agentclass==[[#basic]]"  "b_range"
	when "agentclass==[[#entrepreneur]]"  "e_range"
	when "agentclass==[[#innovator]]"  "e_range"
	when "agentclass==[[#apathetic]]"  "b_range"
	when "agentclass==[[#fanatic]]"	"-1"
	code "0"
end

Known operations (here A,B and C are some valid expressions):
(A)value of A
$2value of parameter 2. Produces recoverable error when number specified is greater than number of existing parameters. Parameters start with 1 and cannot be 0 or negative.
A + Badd values of A and B
A - Bsubtract B from A
A * Bmultiply values of A and B
A / Bdivide A by B (division by 0 produces recoverable error)
A mod Bremainder of division A by B (division by 0 produces recoverable error)
A ? B : Cif value of A is non zero return value of B, otherwise return value of C
A and Breturn 1 if both A and B are non zero, return 0 otherwise
A or Breturn 1 if at least one of A and B is non zero, return 0 otherwise
A intersect Bintersect two sets (bitwise and)
A union Bunion of two sets (bitwise or)
A <= Breturn 1 if A is less or equal to B, return 0 otherwise
A < Breturn 1 if A is strictly less than B, return 0 otherwise
A >= Breturn 1 if A is greater or equal to B, return 0 otherwise
A > Breturn 1 if A is strictly greater than B, return 0 otherwise
A = Breturn 1 if A and B have equal values
[[aname]] return index of attribute aname
[[#aname]] return index of agentclass aname
[aname] return value of attribute aname of the current agent
{aname}, also aname return value of function with name aname
aname(a,b,c) return value of function with name aname and parameters a, b, c
falsesame as 1
true same as 0

Example:

routine 'test4' composite
	comment 'Returns square of its argument'
	code "$1*$1"
end
Making a call "test4(rand)" will only call rand one time as it is evaluated before calling test4

Inline routines

These routines have no user assigned name and are not visible in routine browser. They are created whenever the user specified an expression.
Example:
statistics
	sum		'active_agents' "1" "[inactive]==false"  
end
In this case two inline functions would be created one for "1" and another for "[inactive]==false".

Recoverable errors

During evaluation of expression it may happen that Ps-i will encounter an error, like, for example, division by 0. When this happens an expression is assigned a special "error" value. This value always resolves as false in boolean tests. When saving in statistics file it will be printed as "NaN". When displayed it will produce gray color. All further manipulations with an error value will produce another error value. You can force an expression to return a recoverable error by calling builtin function error.

Related

See also About Ps-i 2.2.