This document explains how to write a GarlicSim simpack. In order to get started quickly with your simpack, it is recommended that you use the start_simpack.py script. (Launch start_simpack.py --help for details.) This script will create a simpack skeleton with all the required definitions, so you could easily fill the contents in instead of creating files manually.
Every simpack must define a State class, which contains the most important part of the simpack: The step function. The State class may also define a few other helpful bits for added functionality, like a create_messy_root method, but these are not mandatory.
The simpack may also contain a settings.py module which specifies a few settings, all of them optional.
The simpack must define a State class, which must inherit from garlicsim.data_structures.State. The State class must be available from the root namespace of your simpack; this is usually done by putting a from .state import State line in your simpack’s __init__.py.
Example State class:
class State(garlicsim.data_structures.State):
# Your step function(s) here...
The step function is the most important part of your simpack, and, (not counting the State class itself,) it’s the only definition that your simpack must make.
There are several different kinds of step functions, as will be detailed below. You only have to define one step function, but you may define multiple step functions, from multiple types. (Just don’t mix history-dependent ones with non-history-dependent ones.)
More detailed explanations about step functions can be found here.
You may define methods for creating new states objects. These should be made inside the State class as staticmethods.
You may define a bunch of definitions, listed below, as globals in a settings.py module. (You may also have a settings package instead, or any other kind of settings object that holds settings as attributes.)
Again, all of these settings are optional. You don’t even have to have a settings.py module if you don’t need it.
Cruncher types that this simpack says it can use.
Cruncher types can be specified in different ways. You may specify either (a) a cruncher type, or (b) the string name of a cruncher type, or (c) a list of either of those (sorted by priority,) or (d) a filter function for cruncher types.
This is useful because some simpacks can’t be used with certain kinds of crunchers.
A few examples:
CRUNCHERS = garlicsim.asynchronous_crunching.crunchers.ThreadCruncher
Or:
CRUNCHERS = 'ProcessCruncher'
Or:
CRUNCHERS = ['ThreadCruncher', 'ProcessCruncher']
Or:
def CRUNCHERS(cruncher_type):
return True
Function that takes a step profile and says whether its deterministic.
What this function says is, “If you do a simulation using this step profile, then you will have a deterministic simulation.” (Or undeterministic, depends on the step profile.)
This is useful because it allows GarlicSim to detect if a simulation has reached a repititive state, so it can stop the crunching right there and avoid wasting resources. (Still not implemented, sorry.)
Note that this function does not return True or False: It returns a DeterminismSetting class, from the garlicsim.misc.settings_constants.settings module.
The function will return None if it’s unknown whether the step profile is deterministic.
Example:
def DETERMINISM_FUNCTION(step_profile):
if step_profile.step_function == State.step:
if step_profile.randomness == 0:
return garlicsim.misc.settings_constants.DETERMINISTIC
else:
return garlicsim.misc.settings_constants.UNDETERMINISTIC
else:
return None