Custom applications - ParaPhraseAGH/erlang-mas GitHub Wiki

MAS enables one to implement a custom usecase, which can take advantage of the program engine. By fulfilling some necessary requirements and writing a few modules, the application can be used to run various multi-agent problems without the need to design the whole environment.

The usecase can consist of any number of modules, but one of them has to implement the agent_env behaviour. It is the one necessary module, which needs to be provided to run the program.

agent_env behaviour

The behaviour is defined in the file src/utils/mas_agent_env.erl. It forces the programmer to provide implementations of several functions that define the specific behaviour of the program. These functions will be enumerated and thoroughly described below.

Important

An atom representing a name of the module implementing mas_agent_env behaviour should be set as the value of a parameter agent_env in mas.config.

start(model(), time()) -> ok.

This is the starting function. It is the function you call to start the simulation and it usually consists of only a call to the function:

mas:start(?MODULE, Model, Time, SimParams, ConfigOptions).

These four arguments describe consequently: the model (mas_concurrent, mas_hybrid, mas_sequential or mas_skel), the time of the simulation in miliseconds (e.g. 10000), simulation parameters (can be any term and are passed later to callback functions) and MAS framework configuration (a list of key-value tuples).

One can also provide other function clauses that take also parameters of the simulation as well as parameters of the MAS framework.

The description of MAS framework configuration can be found in the default config file etc/mas.config. Parameters that are passed in start/4 function overload default parameters fetched from the config file.

behaviours() -> [agent_behaviour()].

This short function returns a list of atoms defining possible interactions in the program. The content of the list is arbitrary.

initial_agent(sim_params()) -> agent().

Provides an agent for the initial population of the algorithm. It takes custom simulation parameters as an argument. It should return an agent, who will be later fed to the behaviour_function().

behaviour_function(agent(), sim_params()) -> agent_behaviour().

Function takes an agent and returns a behaviour, which should be performed by this agent. This behaviour has to be one of the list specified in the function behaviours().

meeting_function({agent_behaviour(), [agent()]}, sim_params()) -> [agent()].

This function should implement the logic behind interactions. It takes a behaviour and a group of agents and should return a list of agents after performing this interaction. The output list does not need to be the same length as the input list and the content obviously may vary as well. It is necessary to provide the logic for every behaviour defined in the behaviours().

stats() -> [funstat()].

The last callback defines the stats that should be monitored in the program. It should return a list of tuples structured as follows: {Name::atom(), Map::fun(), Reduce::fun(), Value::term()}.

The first argument is an atom defining the name of the statistic - it is arbitrary. Following two arguments define functions map and reduce which will be used to extract and calculate the final value of the statistic.

  • map(agent()) -> term().

The function basically extracts a certain value from an agent which will then be used to calculate the final result. It is applied to every agent in the program during each generation.

  • reduce(term(), term()) -> term().

The reduce function is applied to all values extracted from agents by the previous fun(). It performs some commutative and associative calculations e.g. min, max, sum, product etc. and returns their result. This function is also run during every generation.

The final argument is the initial value that should be reduced with the first agent. For instance it might be 0 when calculating the sum or -1 when finding the maximum element in a positive set.