Hooks are how you get your own code into a Helipad model. A complete list of them can be found in the function reference.
Background
There are two different strategies that govern the relationship between your code and the code of an agent-based modeling framework. The two are not entirely mutually exclusive, but in practice, frameworks will hew toward one or the other.
- An imperative strategy. Many frameworks are simply a collection of functions and classes that you can call from your own loop. If you want to take advantage of a certain piece of functionality, you have to call it. The advantage of this strategy is that it gives you explicit and precise control over every aspect of your model’s runtime. The disadvantage is that you have to explicitly specify a lot of boilerplate in your model, even if you don’t need to change anything.
- A hook strategy. Helipad, by contrast, incorporates the boilerplate and takes care of the looping, allowing you to insert your own code in key specified places. The advantage of this is that it allows you to organize your code logically and avoid boilerplate code. The disadvantage is that it can be somewhat harder to figure out how to do something unusual.
Helipad uses a hook strategy, and tries to minimize the disadvantages by allowing direct access to the model class in most instances. This allows just as much fine-grained control over the model’s runtime as would be possible with an imperative framework, with the proviso that some of this will involve direct manipulation of the model class.
How To Use Hooks in Helipad
Helipad provides the structure of a model loop. Most elements of this structure will allow you to insert your own code. Some of these will be critical to the model’s functioning (e.g. the agents’ step function); others you will likely never have to worry about (e.g. the Cpanel
hooks). A complete list of hooks is available in the following section, and on the function reference page.
To use a hook, you’ll simply write a function, and tell Helipad where to run it. Each hook will provide a certain set of arguments to your function, so it will be important to write your function with the right signature.
For example, suppose you want an agent that works in the first stage, and consumes his product in the second stage.
from helipad import *
heli = Helipad()
@heli.hook
def agentStep(agent, model, stage):
if stage==1: agent.wealth += produce(agent.id, agent.laborSupply)
elif stage==2:
agent.utility += sqrt(agent.wealth)
agent.wealth = 0
agent.laborSupply = random.normal(100, 10)
To tell Helipad to run this code for every agent every stage of every period, we simply add the @heli.hook decorator to the top of our function, and name it so that Helipad runs it during the agentStep
hook.
There are a few things to notice in this example.
- Helipad passes three arguments to any function used in the
agentStep
hook:agent
,model
, andstage
. Be sure to consult the documentation to see what arguments your hook function takes. - The
agent
andmodel
objects are passed as arguments. You can access properties of the agent and model objects usingagent.property
andmodel.property
, respectively. Do not access properties usingself
. - You can add multiple functions to a single hook, in which case they will be executed in the order they were registered. See
Hooks.add()
for more details.