-
Notifications
You must be signed in to change notification settings - Fork 6
Language Special Variables
Fred Rothganger edited this page Oct 6, 2024
·
39 revisions
The following table defines all $ variables. Entries that begin with “A.” are attributes of a reference within the context of a connection part. The name "A" is merely a stand-in for the actual reference variable.
Several of these are semantically integers. However, to allow for dynamics at runtime, they may be set to non-integers, and will return non-integers. When the value is actually applied by the backend, it gets converted to one of the two closest integers in an unspecified manner. That is, it could be converted by ceil(), floor(), or round(), at the backend's discretion.
Name | Description |
---|---|
$all.variable | Causes "variable" to be treated as global, that is, pertaining to the whole population rather than each instance. This is roughly the equivalent of the "static" keyword in C++ and related languages. This prefix should only be used in a local declaration (left-hand side). References to the variable (right-hand side or from an external part) should omit $all. The compiler automatically detects variables that should be global. For example, $n is global so any temporaries it depends on are processed in the global context. A variable that only references global variables is also global. Otherwise, user-defined variables are always local. This prefix is the way to override that default. |
$each.variable | The inverse of $all. In cases where the compiler detects that a user-defined variable can be global, this prefix forces it to remain local. |
$connect | Read only. Evaluates to 1 only when a latent connection is being probed for potential creation. Decision is indicated via $p. |
$index | Read only. An unique non-negative integer identifying this instance within its population. Values start at zero and are allocated contiguously. However, if an instance dies, it leaves a gap in the sequence. If a new instance is later born, it may either fill that gap or get a new index. |
$inherit | Specifies a comma-separated list of parts to inherit from. Each named part takes precedence over any parts listed to its right on the line. An inherited part's equations are inserted if there is not already an equation with the same name. This extends to any sub-parts underneath the part in the model. Once all the inherited parts are processed, each sub-part is examined in turn, and if it has a $inherit line, additional equations are inserted at that lower level. Comma is the only delimiter permitted. In particular, do not put quote marks around the name of each part. |
$init | Read only. Evaluates to 1 only during the initial cycle when the instance is being constructed. You can use this as a condition to explicitly set initial values. |
$kill | A pseudo-variable that excludes its containing part from simulation. These parts are also hidden in the GUI editor unless a special view mode is set. |
$live | Read only. Evaluates to 1 during the normal lifespan of an instance, after the init cycle is over. Evaluates to 0 during connect or init cycles. Also evaluates to 0 after the instance dies. Usually a dead instance is removed before the next simulation cycle, so it is rare to see this third case. |
$meta | A pseudo-variable that holds a metadata block. The contents have no mathematical effect on the rest of the model, though they may control how the model is simulated. For example, the host system, simulator and numeric precision can all be set through metadata. |
$n | Write: determines the final number of instances at the end of the current cycle, even if $type splits or death by $p occur. Creates or kills instances as needed, in an arbitrary manner. Only has an effect if explicitly assigned (or integrated from $n') in the current cycle. Read: the last value written. May differ from actual population size for short periods of time. Specifically, if $n is referenced by a newly created part in the population while it is growing to fulfill a $n setting, then $n will report the set (target) value rather than the current size. Furthermore, if $type splits or death by $p occur, the value of $n will not be updated until after the current simulation cycle of the container. If $n is set to a fractional value, for example by integrating $n', then the fractional portion will be retained even when the integer portion is updated to match the current population size. This allows structural dynamics via $n' to work in conjunction with $type and $p. Default is 1. |
$p | Probability that a part will survive 1 second of simulation time. A value of 0 or less forces a part to die, and a value of 1 or more forces it to live. A value between 0 and 1 results in a random draw. Default value is 1, meaning the part always exists. Compartments: used to implement population dynamics by randomly killing off instances. Connections: Have a connect phase ($connect==1) distinct from the init or run phases ($connect==0). In the connect phase, $p is the probability of being born during 1 second of simulation time. Each new combination of connection endpoints is checked once, whenever new instances are born in the target populations. In this case, the probability is treated as instantaneous (or equivalently, as if 1 second has already transpired). If the connection is created, $p is initialized to 1. This can be changed during the init and regular cycles, and has the same effect as for compartments. Polling: If the connect-phase value of $p is not a deterministic value of 0 or 1, then the simulator will periodically poll each latent connection to check if it should exist. The default is to check all latent connections once per second of simulated time. The polling rate can be controlled by setting the metadata tag "poll" under $p. It's value is the amount of time the simulator can take to make one complete pass through the latent connections. Zero indicates every cycle. Less than zero disables polling. Only latent connections are considered for creation. Thus, duplicate connections are never created. If the connection dies, for example via the live-phase value of $p, it becomes latent again and could be reborn during polling. In connections, $p will usually be qualified with a phase indicator. Suppose you wish to create 20% of the possible connections, create them only once, and have them survive for the entire simulation. Write: $p=0.2 @ $connect && $t==0 As an alternative to $t==0, you could set poll=-1 so the latent connections are never examined again. If the expression for $p refers to external data, the compiler cannot determine whether it is boolean ahead of time. For example: $p=M(A.$index,B.$index) M=matrix("fileName") The compiler will choose to do polling, and the model may be surprisingly expensive to simulate. One solution is to make it an explicit boolean expression: $p=M(A.$index,B.$index)==1 The other is to set poll=-1. |
$ref | A pseudo-variable that holds references to supporting literature. |
$t | Seconds of simulated time since start. |
$t' | The preferred evaluation period for this instance. On simulators that support it, setting this may move the instance to a different position in the event queue, so its next update may come at a completely different time than its peers. Setting this does not necessarily change the actual evaluation period. For example, a variable-step integrator may decide this from cycle to cycle, regardless of what the part requests. Thus it should be viewed as a hint to the simulator. Default value is determined by the simulator. |
$type=A,B,... | Enables an instance to change into a different kind of part, or to split into instances of several different parts, analogous to cell-division and specialization. The right-hand-side of the assignment is a comma-separated list of part names. Any number of the child parts are allowed to be the same as the parent. It is good practice to make every $type equation conditional. Assignments to $type are ignored during the init cycle. Write: Create a new instance for each part listed on the right-hand-side. For each variable in a new child part with exactly the same name as a variable in the parent part, the current value will be copied over. Other child variables get their standard default value (0 in most cases). Then newly created children go through the init cycle. If one or more child parts are the same as the parent part, exactly one will be chosen to retain the identity of the parent. It will not go through an init cycle. A compartment that lives on retains its current connections and substructure, while all new compartments must form new connections and substructure. On the other hand, a connection that splits retains the same set of endpoints regardless. Read: If this instance was created by any process other than an assignment to $type, then the value reads 0. If this instance was born from a $type assignment, then the value is the one-based position in the list of parts on the right-hand-side. After one cycle (init in the case of new children, or regular update in the case of a parent that lives on) this value resets to 0. This allows the post-split instances to specialize into new roles, for example a stem cell spawning another stem cell plus a new neuron. |
$up.variable | Forces "variable" to be resolved in our container rather than the current equation set. $up may be repeated several times. That is, $up.$up.variable resolves in the container of our container. Notice that when $up appears on the left-hand side of an equation, it assigns to the variable in the container. The value in the sub-part will be treated like any other external write to the container's variable. Also note that if the sub-part is a singleton (only one instance), the compiler will merge it into the container's equations. This merge will respect the reduction type if present. For example, $up.variable=+2 will add 2 to the end of equations on variable in the container. On the other hand, if it is direct assignment (replace value), then the merge will replace equations with matching condition in the container. This enables the design of drop-in parts that modify the container's equation set. |
$xyz | Spatial location of instance. Default is [0;0;0]. |
A.$count | Read only. Current number of connections of this type to A. |
A.$k | An integer number of nearest neighbors to search for potential connections. If undefined or non-positive, then treated as unlimited. See $radius for more explanation of spatial constraints. |
A.$max | No more than this many connections may target a given instance of A. If undefined or non-positive, then treated as unlimited. |
A.$min | At least this many connections must target a given instance of A. Default is 0. Note that $min is extremely expensive to implement and has vague semantics. The simplest interpretation is that A should die if it fails to form enough connections. |
A.$project | For spatial filtering, declares a transformation from the 3D space of A into the 3D space of this connection. Default value is A.$xyz (that is, no transformation). Since A.$project is used in testing whether to create a connection C, the expression must only reference values known by A. References to variables in C or to other endpoints are forbidden. However, $project may reference constants in C and use temporaries provided they follow the same rule. Connection C has its own $xyz, which acts as the query point for collecting candidate instances from population A. If C.$xyz is not explicitly defined, then it acquires the value from an arbitrary endpoint (via $project if specified). To save space, C avoids storing $xyz unless necessary. |
A.$radius | A distance to search in the space of the target population for potential connections. If undefined or non-positive, then treated as unlimited. Spatial constraints ($k, $radius) are only a hint to the simulator, to avoid evaluating connections that will never exist. Express all formal connectivity in $p, whether you use spatial constraints or not. |