Best Practices#
Here are some general principles that have proven helpful for developing models.
Model Layout#
A model should be contained in a folder named with lower-case letters and
underscores, such as wolf_sheep. Within that directory:
Readme.mddescribes the model, how to use it, and any other details.model.pyshould contain the model class.agents.pyshould contain the agent class(es).app.pyshould contain the Solara-based visualization code (optional).
You can add more files as needed, for example:
run.pycould contain the code to run the model.analysis.pycould contain any analysis code.
Input data can be stored in a data directory, output data in an output, processed results in a results directory, images in an images directory, etc.
All our examples follow this layout.
Randomization#
If your model involves some random choice, you can use the built-in random
property that many Modelly objects have, including Model, Agent, and AgentSet. This works exactly
like the built-in random library.
class AwesomeModel(Model):
# ...
def cool_method(self):
interesting_number = self.random.random()
print(interesting_number)
class AwesomeAgent(Agent):
# ...
def __init__(self, model, ...):
super().__init__(model)
# ...
def my_method(self):
random_number = self.random.randint(0, 100)
Agent.random is just a convenient shorthand in the Agent class to self.model.random. If you create your own AgentSet
instances, you have to pass random explicitly. Typically, you can simply do, in a Model instance,
my_agentset = AgentSet([], random=self.random). This ensures that my_agentset uses the same random
number generator as the rest of the model.
Models also expose self.rng, a NumPy Generator, which is useful for vectorized random draws.
When a model object is created without a seed, its random number generators are
seeded from fresh operating system entropy, so every run differs. The seed determines
the sequence of random numbers; if you instantiate a model with the same seed, you will
get the same results. To allow you to set the seed, make sure your model has an rng
argument in its __init__ and passes it on to super().__init__().
class AwesomeModel(Model):
def __init__(self, rng=None):
super().__init__(rng=rng)
...
def cool_method(self):
interesting_number = self.random.random()
print(interesting_number)
>>> model0 = AwesomeModel(rng=0)
>>> model1 = AwesomeModel(rng=0)
>>> model0.random.random() == model1.random.random()
True