Simpack API

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.

Mandatory definitions

The State class

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...

Step function(s)

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.

  • def step(self, <optional defaultful arguments>):Simple step function – A simple step function, which takes a state and returns a new state that follows it in time.
  • def inplace_step(self, <optional defaultful arguments>):Inplace step function – An inplace step function, which takes a state and modifies it in place to be “the next state”.
  • def step_generator(self, <optional defaultful arguments>):Step generator – A step generator, taking an initial state and yields new states indefinitely.
  • def inplace_step_generator(self, <optional defaultful arguments>):Inplace step generator – An inplace step generator, taking an initial state and, on every iteration, modifies it in place to be “the next state”.
  • def history_step(history_browser, <optional defaultful arguments>):History step function – A history step function takes an history browser instead of a state. The history browser allows it to inspect the entire history of the simulation. Returns the next state. Is usually a staticmethod.
  • (Not yet implemented, sorry:) def history_step_generator(history_browser, <optional defaultful arguments>):History step generator – A history step generator takes an history browser instead of a state. The history browser allows it to inspect the entire history of the simulation. Keeps yielding new states indefinitely. Is usually a staticmethod.

Non-mandatory definitions

State creation methods

You may define methods for creating new states objects. These should be made inside the State class as staticmethods.

  • def create_root(<optional defaultful arguments>): - Create a plain state, i.e. a state which is empty and featureless, like an empty canvas.
  • def create_messy_root(<optional defaultful arguments>): - Create a messy state, i.e. a state which is random and has interesting features. This is mainly intended for playing around with the simulation, which is very important.

settings.py module

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.

CRUNCHERS

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

DETERMINISM_FUNCTION

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