<< Click to Display Table of Contents >>
|Show/Hide Hidden Text|
Actions and triggers are used to make instantaneous changes to stocks and attributes, to create or delete entities, or both. Actions describe what will happen; triggers determine when the action occurs. We will discuss actions first, then triggers. There is also a separate exercise provided as a step-by-step example of using actions.
You define an action as part of an entity type definition. If you are defining chameleon entities, one property you will add is a "change color" action that, when triggered, changes the color of the chameleon. The "change color" action will be listed on the actions tab of the chameleon entity type, and the chameleon entity type is said to be the parent of the action.
Most action types have some settings on the Properties tab of their inspector.
All actions have an Invoker and a Parent on the References tab of their inspector.
•The Parent is the entitytype or collection within which the action is defined. You can't change this type (unless you redefine the action somewhere else).
•The Invoker is the context of the Trigger that caused the action to occur. By default, the invoker type is the same as the parent type, but you can change this if your action will be called from a different entitytype. More than one type can invoke an action, though this will produce a warning, or an error if a necessary variable is needed but not available from the actual invoker.
•Create actions have a special reference for the new entity to be created, e.g., newPerson.
•Process List actions have a special reference for the current entity target in the iteration over a collection, e.g., refPerson.
•You can add other references you may need, for example to the top-level Model singleton, to a collection, or to some other entity known to the Invoker or Parent.
Actions can contain local variables for performing intermediate computations, like determining the attractiveness of options to be selected in a Process List.
You can use stock-flow notation to calculate accumulations within a Process List action. In this case, the accumulation is not over time, but over iterations of the action on its target collection.
Because action computations are volatile, these have no independent existence outside the action, and are not stored.
Variables used from the Parent, Invoker, or other references can be references or surrogates. A reference is a pointer to a variable somewhere else, whereas a surrogate is a local proxy for the variable.
Reference (or Referenced Variable)
Appearance (in default color schemes)
Notation (in diagram labels and expressions)
Drag from the inspector. In some cases you may need to use the <control> key as a modifier while dragging.
Enter the desired name in the expression (autocomplete will help you fill in the name if you start with Parent. etc.). The result will be underlined, indicating that the cause is not shown on the diagram. Right-click the underline and use the "Draw Arrows" method from the context menu.
Generally automatic in a Create action.
•To initialize it (Create action only): surrogate
•To change it: surrogate
•To use it: reference
•Unless you already have the surrogate, in which case you could use that
•To initialize it (Create action only): surrogate
•To change it: reference, with a local flow
•To use it: reference
Other variable types always use a reference.
Initializing Surrogates from Parent references.
Initializing a Surrogate from a Parent reference, then propagating the value to initialize another Surrogate (rare).
Making a conserved flow from one referenced stock to another in a Process List action.
Invoker (a Bank) lends startup cash to the surrogate of a newCompany in a Create action.
There are several types of actions, but all of them have in common the ability to make immediate changes to the values of stocks and attributes. Actions that do nothing other than make such changes are called command actions, and are the most basic type. The other types of actions have the same capabilities as command actions, plus additional capabilities depending on the type.
Note: On any of the action tabs, you can create surrogate links by dragging and dropping a variable on to the page. You can suppress the creation of surrogates and instead create ghosts by holding the Cntrl key while dragging and dropping a variable.
There are three things you can do in a command action:
To do any of the above, we must identify the target attribute or stock to be changed, or the target action to be triggered. Every action must have a reference to the entity it will affect. Every action is automatically created with two pre-existing references: parent, a reference to the entity that owns the action, and invoker, a reference to the entity that owns the trigger that fires the action. These references are used to access the target attribute or stock to be changed. Some actions involve other references as well, discussed below. For now, we'll use the parent reference in examples of things one can do with command actions.
1. Change the Value of an Attribute:
Continuing with our chameleon example, we will first create an action that changes the chameleon's color to red.
We start with a chameleon entity type, having an attribute color with default initial value "green".
Add an action either by right-clicking on the chameleon entity type in the model overview, or by clicking the "New Action" button on the actions tab of the chameleon inspector:
When the editor for the new action appears, set the name to "turn red", the action type to "command", and add a description.
The action now exists, and even has its own inspector and (empty) diagram, but doesn't actually do anything yet. To complete the action definition, go to the references tab of the action, and drag "color" from under the parent reference to the "turn red" diagram:
The resulting "Parent•color" node is a surrogate for the color attribute of each chameleon entity. You use a surrogate of a stock or an attribute to specify the change to that stock or attribute that you want the action to effect. The surrogate is not a reference to any chameleon or its color; instead, it is a construct that lives entirely within the action. You can see it listed on the attributes tab of the action inspector:
Right-click and choose "Edit attribute", and set the "new value" field to "red":
The action is now completely defined. When triggered (see below), this action will change its parent entity's "color" value to "red".
2. Move a value into, out of, or between stocks:
You can use flows in your action diagram to cause a transfer into our out of a stock. On the action diagram, the stock is represented by its reference. So in an action that removes mass from the chameleon (say, when it loses its tail), you first drag a reference to the chamelon's mass from the reference tab, then add an outflow to represent the loss:
There is an important difference between regular flows, and flows in actions: Regular flows represent a rate of change over time, e.g. chameleon mass is growing at 0.5 grams per day. A flow in an action is a single, instantaneous transfer: when the "lose tail" action is triggered, the chameleon suffers an immediate, one-time loss of 3 grams of mass. Thus, while units for a regular flow are generally time dependent (for example, with units of gram/day), action flows not time-dependent (with units of gram).
The same applies to transfers between stocks. You can even make transfers between stocks of different entities. For example, the action pictured below executes a transfer of money from invoking entity (the entity where the trigger is defined--see below) to the parent entity (the entity where the action is defined):
3. Trigger other actions:
A command action can trigger a second action. Triggers are discussed below, but the basic idea is that a trigger checks to see if the criteria for performing an action are met, and if they are, the action occurs. To cause a command action to trigger a second action, add a trigger to the first action's diagram (see below for how to add a trigger). Each time the first action occurs, the trigger will be evaluated and if conditions warrant, the second action will also occur.
Command actions can act on any attribute or stock of either the parent entity or the invoking entity. They can also act on any entity to which those entities have a reference. If the parent entity of an action has a reference called "employer" that points to another entity, then the action can affect not only parent.bank_balance, but also parent.employer.bank_balance. (References can be chained, so it is possible for an action to affect the subsidiary of the competitor of the holding company of the parent, so long as all the references in parent.holding company.competitor.subsidiary exist.) When one action triggers a second action, the parent of the first action is the invoker of the second.
A Self-delete Action causes the parent entity to exit the model. Before deleting the parent entity, self-delete actions can also do any changes of stocks or attributes in the same way that command actions do. When an entity self-deletes, results and records up to that moment are not deleted, but the entity ceases to appear in any interactions, results or records from that moment forward.
To create a self-delete action, create a new action (by right-clicking the entity type on the model overview, or choosing "New Action" from the actions tab of the entity inspector), then select "Self-delete" as the type, as shown:
That's all that's required for a self-delete action, but if you wish, you can add commands (as described in Command Actions above) to change attribute values or stock values elsewhere, or to trigger other actions. For example, you might transfer a business' assets or a chameleon's mass to some other entity's stock as part of the self-delete action. Any commands you add will be carried out prior to the deletion of the entity.
Self-delete actions, by definition, delete their parent entities. Commands in self-delete actions can affect parent, invoker, or parent's and invoker's references, just as in command actions.
Create Actions cause a new entity to be created and become active in the model. You might use a create action to cause a new animal to be born, create a new business, or establish a new loan. Choose "Kind: Create" on the properties tab of an action (Item 1 in the figure below). Next, specify what kind of entity will be created, and how many of those entities the action will create each time it is invoked. The description field is available for any notes or documentation you wish to include.
The important function of a create action is to specify the properties of each newly created entity. To facilitate this, the action has a reference to the entity to be created, named for the entity type with the prefix "new": "newchameleon", "newbusiness", or "newloan". Each create action automatically has a diagram, populated with surrogates of the attributes and stocks of the new entity. You can edit the "default initial value" field of these attributes and stocks to specify what values they will take on when a new entity is created (item 2 in the figure above).
Like all actions, create actions can also do anything command actions can do, so you can add attribute changes or stock transfers to the action and they will be carried out after the new entity is created and initialized.
Create actions initialize the created entity. Commands in create actions can affect parent, invoker, or parent's and invoker's references, just as in command actions.
Process list actions are just like command actions, but they act on one entity at a time from a collection. Process list actions can be used either to select one or more entities from a collection and act only on those, or to act on every member of a collection in some way.
Like all actions, process list actions come with predefined references to the parent (owning entity) and the invoker (entity that owns the trigger). Process list actions also come with a third reference, to the current entity being processed. The name of the reference is always the name of the entity type being processed with the prefix "ref". So if your action is acting on a collection of gazelles, the reference called "refGazelle" points to whichever particular gazelle is being acted on at the moment.
To create a process list action, create a new action,
and choose "Process List" as the Kind.
Next, name the collection whose members your action will act upon. This can be a named full collection, as shown here, or it can be a reference to a subcollection.
The "filter" field determines which members of the collection are included for processing. As shown, the action will only apply to gazelles weighing more than 200 pounds*. To process all members of the collection, enter true in the filter field.
Next, choose the order in which the entities will be processed. As shown here, the list of gazelles is sorted by weight, descending from heaviest to lightest. Thus the heaviest gazelle will be sorted first, the next heaviest second, and so on, down to the lightest gazelle that still meets the filter condition. Process list actions currently sort collections only by variables' value (so, numerical values), not attributes or other properties. So you can sort by weight, but not alphabetically by (say) color. You may, however, put any numerical expression you wish in the sort field, as long as it produces a value for each entity in the collection. You can sort, for example, on the function Random() to process the entities in random order.
Process list actions do not have to process all the entities that meet the filter condition. The Process While field is used to determine when the action should stop processing entities. Here, the action will continue while the parent (a Lion entity) weighs less than 400 pounds. If the lion entity who owns this action should gain enough weight to cross 400 pounds (perhaps by eating gazelles, one at a time), then the action will stop. If you wish for an action to process every entity in a collection that meets the filter condition, enter true in the Process While field.
Finally, the description is a place to enter any explanatory notes or comments about the action.
* or whatever weight units are used in the definition of the Weight variable of the Gazelle entity.
Process list actions can do commands on members of the target collection, the parent or the invoker, or entities connected by references to any of those.
Allocate and market actions are in development and subject to major changes. Ideas and feedback are welcome, either to firstname.lastname@example.org or on the forum.
Allocate and market actions distribute a constrained resource among entities.
•Allocate actions are used to to distribute a known quantity to a number of competing destinations. This can represent the distribution of a single, fixed supply among many demanding entities, or the distribution of a single, fixed demand among many competing suppliers.
•Market actions are used to represent a number of demanders and suppliers in a common market to buy and sell a particular good. In the current formulation, market actions assume that any buyer can buy from any seller, that all buyers agree about which suppliers are preferred, and all sellers agree on which buyers are preferred.
Both allocate actions and market actions are based on the same heuristic developed by William T. Wood in the 1980's. We describe the idea behind these actions in the following section ("Background"). We then describe the details of each action in turn.
To summarize the above, we first discussed command actions, the most basic actions that can change attributes and stock values and trigger other actions. We then looked at three variations on the command action: self-delete actions that perform commands then remove an entity from the model, create actions that create new entities and then perform commands, and process list actions, that perform commands on one or more entities from a collection. Finally we looked at allocate and market actions that resolve mismatches in supply and demand. All these actions specify what will happen. We next discuss how to use triggers to specify whether and when an action happens.
Every action must have a trigger that specifies whether and when the action occurs. A trigger may be created in the same entity where the action is defined, or in a different entity. The entity where the action is defined is called the parent of the action, the entity where the trigger is defined is called the invoker of the action. Thus it is possible and even common for a single entity to be both the invoker and the parent of an action.
To create a trigger, either drag a trigger node onto the diagram of the invoking entity and then right click to edit,
or use the New Trigger button on the actions tab of the inspector for the invoking entity,
or drag an action onto a diagram, which will automatically create a new trigger for that action.
Right-click the new trigger to edit. You will be asked to provide the following:
A name for the trigger. You can name the trigger after the action, as shown here, or give it any other descriptive name.
The sequence number sets the order of priority in case more than one trigger is set to occur at the same time.
Period Start triggers occur at the beginning of the time slice; Period End triggers occur at the end of the time slice after other calculations have been done. Set this to "Never" to disable a trigger. Note: Triggers for Allocate and Market actions must be set to "Period Start".
In the "Trigger If:" field, set the conditions that must be met for the triggered action to occur.
Specify the action that will be performed. When the action and trigger are not defined in the same entity, you will need to use a reference to identify the action. See "Who triggers whom?" below.
The description field is a place for any notes or related information.
As shown in the description field in the image above, this trigger is checked every time slice, at the start of the period. If the chameleon's temperature is over 100 and the color is anything other than red, the "Turn Red" action will be invoked, which will set the chameleon's "color" attribute to "red".
The most crucial aspect of defining a trigger is making sure the correct entity's action is being invoked. The invoker entity (the entity that owns the trigger) must have a defined relationship to the entity that owns the triggered action.
There are three situations to consider:
1.The parent and invoker are the same entity. In other words, the action is defined in the same entity as the trigger, and both show up on the actions tab of the same inspector. In this simplest case, you can specify the Action to Invoke simply by writing the name of the action, as with the "turn red" example above where the trigger and action are owned by the same chameleon entity.
2.The parent and invoker are different entities. In this case, the Action to Invoke field must include a reference to the owner of the action. If your "boy" entity is going to make his girlfriend blush, then the boy entity must have a reference called "girlfriend" to a specific girl. Girl entities must have a "turn red" action defined. The trigger defined in the boy entity will then list "girlfriend.turn red" in the Action to Invoke field.
Note that this applies even if both entities are of the same type. If each platypus entity has a reference to a second platypus called "mate", then a platypus that wants to make its mate blush must list "mate.turn red" in the Action to Invoke field of the trigger. If it just says, "turn red", then each platypus will be making itself blush.
3.The invoker is an action. In other words, you are chaining actions so one trigger invokes an action, which includes a trigger that invokes a second action. For example, if each phoenix entity has both a self-delete action called "death" and a create action called "rebirth", the trigger for "rebirth" should be defined inside the "death" action so a new phoenix can be created just as the old one dies. In this case, the owner of the trigger is the action called "death". The owner of the action to be invoked is the phoenix--that is, the parent of the death action. So, the trigger for rebirth should list "parent.rebirth" as the Action to Invoke.
Fine print: If you are using chains of references to trigger an action, such as writing mother.brother.son.BakeCookies for an entity to invoke its cousin's tendency to produce cookies, you may not send that chain through an action other than the one you mean to invoke. The first action that is encountered in the sequence of references will be invoked. If your trigger is owned by an action, the first action found outside of that invoking action will be the one that is triggered.
You may create more than one trigger for a single action. The triggers can even be defined in entities of different types -- for example, lions, cheetahs and wild dogs all might have triggers for the action that results in a particular gazelle being eaten. However, any variables that are used in the trigger must be defined in all the different invoking types. If this is not so, an error will result and the model will not run.