1 Introduction

The research on multi-agent systems based on the biologically inspired computation can be carried out in three basic approaches. The first approach is a theoretical study of the features of the system. One can focus on the computational power of variants or the ability to solve complex theoretical problems, like NP-complete problems. The second approach is to design and develop the software simulating such a model and study its behavior.

The third way combines both above-mentioned approaches. Based on the theoretical study, a model is configured; and to prove the results a simulation needs to be carried out. For the second and third approaches, it is necessary to develop a software which is able properly simulate the given theoretical model.

Membrane systems, P systems, (see [14, 15]) are bio-inspired computational systems. The inspiration is based on living cell membranes, where the computation is provided by letting an object from the environment pass through the membranes of the cell. During over two decades of research in the field of membrane computing, there have been introduced many variants of P systems. For some of those variants the simulators were developed.

In [8] a general-purpose P system simulator named UPSimulator for cell-like, tissue-like and neural-like P systems was introduced. This simulator can serve as both a simulator and a development library for P system models. It provides a feasible solution for the simulation of hybrid P systems by supporting the complex evolutionary rules and structures in different types of P systems.

Great piece of work in the field of simulation of P systems was done by the research group lead by Prof. Catalin Buiu. Open-source simulators of standard and enzymatic numerical P systems, and P colonies and P swarms are accessible on the webpage dedicated to the Membrane computing and robotics (see [1] and [7]).

A lead role in the P systems software development has the Spanish Research Group on Natural Computing from the University of Seville. The most recent projects include P Lingua (e.g. see [16]), a programming language for Membrane Computing, which created a background for a simulator run on the GPU, a PMCGPU (see [13]), Parallel simulators for Membrane Computing on the GPU.

Spiking neural P (SN P) systems are models of computation inspired by spiking neurons. These systems are equivalent to Turing machines solving computationally hard problems using a space-time trade-off. A simulator of these systems was introduced in [6].

2 2D P Colony with Evolving Environment

The P colony (see [10]) is a very simple membrane system derived from P systems (see [14]). It is composed of a community of agents living in a shared environment represented by a multiset of objects. The agent, i.e. a membrane contains a certain number of objects, from which it can evolve into other objects, or it can swap them for other objects with the environment.

Let us briefly sum up the results obtained in the research of the P colonies.

In [5] Ciencialová et al. explored variants of P colonies with a passive environment and demonstrated that these systems are computationally complete.

In [4] Cienciala et al. introduced a novel type of rules for P colonies inspired by the cell division. These extended P colonies were proved to be effective in solving the 3-SAT problem in linear time with respect to the number of clauses. They also provided the solutions in polynomial time for classes NP and co-NP, thus posing intriguing questions regarding the characterization of the borderline between P and NP using certain parameters of P colonies.

The dynamic environment influenced by the 0 L scheme in the terms of P colonies was introduced in [3]. Cienciala et al. demonstrated their computational capabilities.

In [2] Cienciala et al. introduced the concept of transferable programs as a common knowledge shared among various types of P colonies, including their 2D variants. They demonstrated the potential applications of transferable programs and explored their utility in enhancing the computational power of the P colonies.

In our paper [17], we presented a model for 2D P colonies which communicates using a blackboard. In that manner, we can simulate other multi-agent systems, such as the Grey Wolf algorithm. We introduced also the operations with real numbers, expanding the utility of the 2D P colonies for practical applications.

The 2D P colony is a theoretical model of the multi-agent system designed for observing the behavior of a community of very simple agents living in a shared two-dimensional environment. Each agent of the 2D P colony is equipped with a set of programs consisting of a small number of simple rules. These programs allow the agent to act and move in the environment.

In our previous research (see [12]), we equipped the 2D P colony with a set of rules allowing the environment to evolve. This extension of the 2D P colony was designed to simulate a simple zoocoenosis, like the ant colony, in a more detailed manner. It enabled us to simulate features like vanishing pheromone trails.

Let us recall the definition of the 2D P colony with evolving environment.

Definition 1

A 2D P colony with evolving environment, 2Dev P COL is a construct

$$\begin{aligned} \Pi = (V, e, Env, A_1,\dots , A_d, f), d \ge 1, \end{aligned}$$

where:

  • V is the alphabet of the colony. The elements of the alphabet are called objects.

  • \(e\in V\) is the basic environmental object of the 2D P colony,

  • Env is a triplet \((m \times n, w_E, R)\), where:

    • \(m \times n, m, n \in {\mathbb {N}}\) is the size of the environment.

    • \(w_E\) is the initial contents of the environment, it is a matrix of size \(m \times n\) of multisets of objects over \(V \setminus \{e\}\).

    • R is a set of evolution rules. Each rule is of the form \(S \rightarrow T\), where S is a multisets over the objects over \(V \setminus \{e\}\), and where T is a multisets over the objects over V. We say, that the multiset S evolves into the multiset T.

  • \(A_i,\ 1 \le i \le d\), is an agent. The number d is called a degree of the colony. Each agent is a construct \(A_i=\left( O_i, P_i, [o,p]\right) ,\) \(\ 0\le o\le m,\ 0\le p \le n\), where

    • \(O_i\) is a multiset over V, it determines the initial state (contents) of the agent, \(|O_i|=c, c \in {\mathbb {N}}\). The number c is called a capacity of the colony.

    • \(P_i=\left\{ p_{i,1},\dots , p_{i,l_i}\right\} , l\ge 1, 1\le i\le k\) is a finite set of programs for each agent, where each program contains exactly \(h \in {\mathbb {N}}\) rules, h is called a height. Each rule is in the following form:

      • \(*\) \(a \rightarrow b, a,b\in V\) is an evolution rule,

      • \(*\) \(a \leftrightarrow b, a, b \in V\) is a communication rule,

      • \(*\) \(\left[ a_{q,r}\right] \rightarrow s, a_{q,r}\in V, 0\le q,r \le 2, s\in \{\Leftarrow , \Rightarrow , \Uparrow , \Downarrow \}\) is a motion rule. \(\left[ a_{q,r}\right]\) is a matrix representing the vicinity of an agent.

    • \([o,p],\ 1\le o\le m,\ 1\le p \le n,\) is an initial position of agent \(A_i\) in the 2D environment,

  • \(f \in V\) is the final object of the colony.

A configuration of the 2Dev P COL is given by the state of the environment—the matrix of type \(m \times n\) of multisets of objects over \(V-\{e\}\), the states of all agents—the multisets of objects over V, and the coordinates of the agents. An initial configuration is given by the definition of the 2Dev P colony.

A computational step of the 2Dev P COL is a transition between two consecutive configurations. The computational step consists of four sub-steps. In the first sub-step, a set of the applicable programs of the agents is determined, according to the current configuration of the colony. In the second sub-step, for each agent, one program from this set is chosen. The condition of the chosen programs is that there is no collision between the communication rules of each two different programs. In the third sub-step, chosen programs are executed, the values of the environment are updated.

The fourth sub-step is the evolution of the environment. Let \(E_{i, j}, 0 \le i \le m, 0 \le j \le n\) be a multiset representing the contents of the environment at the coordinates [ij]. Let \(A_{i, j}, 0 \le i \le m, 0 \le j \le n\) be a multiset of all the objects forming right sides of the communication rules of the programs chosen in the second sub-step for all the agents at the position [ij]. Consider multisets \(S^1_{i, j}, \ldots S^{o_{i, j}}_{i, j}, o_{i, j} \in {\mathbb {N}}\) such that \(\cup _{k=0}^{ o_{i, j}} S^k_{i, j} = E_{i, j} {\setminus } A_{i, j}\). Then the evolution of the environment in this particular derivation step is provided by the application of the evolution rules \(S^k_{i, j} \rightarrow T \in R\).

Generally speaking, the objects of the environment, which were not changed by the actions of the agents, are modified by the evolution rules of the environment. The application of the rules of the agents has higher priority over evolution rules of the environment.

A computation is non-deterministic and maximally parallel. The non-determinism means that there is a uniform distribution on all the applicable rules. Hence, if an agent can apply more rules, or there can be applied more rules of the environment in one particular derivation step, only one rule is non-deterministically chosen, but each and every rule can be applied with the same probability. The computation ends by halting, when there is no agent that has an applicable program.

The result of the computation is the number of copies of the final object placed in the environment at the end of the computation.

Remark: Since the only difference between 2Dev P COL and 2D P COL is the evolving environment, if the set of evolution rules R is empty, or all the rules are identity, then in this case we obtain the definition of the 2D P COL from the 2Dev P COL.

3 The 2D P colony simulator

The main goal is to develop an application simulating not only 2D P colony, but also allow further extensions, such as support for dynamic environments, blackboard (see [17]) and other modules at a future point.

3.1 Requirements

The very basic requirement is the modularity. We require the application to be easily extendable and scalable, which can be reached by the modularity of the application. The user must be able to specify and define all the key aspects of the application.

Except the parameters, which are required by the definition of the 2D P COL, we also introduce parameters simplifying the definition of the rules and defining the behavior of the application. Let us briefly summarize all the parameters of the colony, which need to be defined.

  • The parameters of the colony—dimension of an environment, a number of the evolving rules of the environment, a number of the computational steps with a possibility of entering an infinite loop, animation delay, the pause between displaying new iteration step, joker symbols and color settings for the specific symbols.

  • The environment—content of the environment.

  • The evolution rules—a set of the evolution rules of the environment.

  • The agent—each agent contains an identifier, starting position with a possibility of specifying a random position, a number of its copies and a set of its programs.

The definition of the colony is in the defined structure in a definition file. This file is parsed by a separate module. During the run of the simulation, it must be possible to start and pause the simulation. It must be also possible modify the parameters such as speed, zooming in and out, and display of visualized elements. The non-functional requirements include the simulation speed, which should be smooth enough. We do not really focus on the speed of the simulation itself; we measure the performance of the colony in the number of the iterations, rather than in a measure of time. Hence, we require the response time for redrawing a configuration of 100 agents in a \(1000 \times 1000\) environment takes no more than 1 s on an average computer with an Intel i5 series processor or higher, unless the user adjusts the simulation speed to a slower speed deliberately using the animation delay parameter in the configuration.

For the development of the application, we choose the Python 3.10 programming language. Python is a great choice for its simplicity, extensive libraries, scientific computing capabilities, community support, and cross-platform compatibility. In addition, the object-oriented nature of Python allows the implementation of modular and reusable code, which facilitates the organization and maintenance of the components of the simulator. The chosen version was at the time of the start of this project approximately in the middle of its lifetime. It was a stable version in a security maintenance status.

4 Implementation

In this section, we describe the implementation of the application. We focus on the specifics and implementation of the individual components of the application. The core of the application is a computational tool accurately simulating the computational steps, the behavior of 2Dev P COL and provides a platform for studying its complex processes. We discuss the technical details and strategies used during the process of the implementation to ensure the accuracy of the simulator in reproducing the key characteristics of 2D P colonies. With a focus on accuracy during implementation, we aim to create a reliable tool that researchers and practitioners can use to analyze and explore 2D P colony simulations in depth.

4.1 Input parameters

The input parameters for the simulation, including the definitions of the environment, evolution rules, agents, their programs, and visualizations, should be customizable by the user. To fulfill this requirement, we utilize a standard xslx file with four sheets and a consistent structure, which can be edited in any spreadsheet software.

The module parsing the colony definition file, extractExcel, uses the openpyxl library for Python. This library enables fast and efficient retrieval of the values from individual cells, and allows further manipulation with those values as the variables.

First sheet of this xlsx file, called Parameters, is reserved for the definition of the basic parameters of the simulation:

  • envRows and envColumns—integer values defining the size of the environment,

  • envRules—the number of environmental rules which will be defined in a separate sheet (see below),

  • steps—the integer value defining a termination criterion as the maximum number of the computational steps, where the value \(-1\) stands for an infinite loop.

  • animationDelay—integer value defining the redraw speed (pause between two consequent iterations of the computation) during visualization in seconds,

  • JokerSymbols—block starting with the keyword JokerSymbolsBegin and ending with the keyword JokerSymbolEnd allows the definition of the substitute characters for the sets of the objects of the alphabet. The Joker symbols can be used in motion rules of the agent, in the case we want to allow the agent to act on a specific set of symbols. This allows rapidly reduce a number of programs of the agent. The substitute character (e.g., *, +, etc.) is written in the second column, while the comma-separated objects represented by this character are written in the third column on the same row within this block.

  • ColorSettings—block starting with the keyword ColorSettingsBegin and ending with the keyword ColorSettingsEnd enables the definition of colors for significant objects that should be displayed on the visualization. The object that should be displayed is written in the second column, and its color is written in the third column on the same row within this block.

To enhance clarity, we use the first column of the sheet mainly to define keywords that are descriptive and facilitate user orientation. The particular values are defined in the second column or in the second and third columns if it is a block of definitions. In the case where the multiple values need to be entered, we use a comma as a separator. This structure is clear and makes it easy to add additional parameters in the future.

The second sheet of the xlsx file, called Environment, is used to define the contents of the environment. Here we define the multisets of objects in the x and y coordinates of the environment. Each cell can contain several objects separated by a comma or can be empty. The environmental symbol e does not have to be defined in any cell, since by the definition, this symbol is present at any place of the environment in an unlimited amount. The application operates only with an environment of a size determined by the variables envRows and envColumns, defined in the Parameters sheet. An example of a simple definition of the environment of a size \(3\times 3\) and several objects can be seen in Table 1.

Table 1 \(3\times 3\) environment definition

The next sheet of xlsx file, called Environmental rules, is reserved for the definition of the evolution rules of the environment. The syntax of the rule is as follows (see the definition of the 2Dev P COL 1 for the definition of an evolution rule); in the first column, there is the multiset S of the objects. In the second column on the same row, there is a symbol >, representing the evolution of the multiset S into the multiset T, which is defined in the third column on the same row. The parser reads only a specific number of rules defined in the Parameters sheet. An example of a definition of two simple evolution rules can be seen in Table 2.

Table 2 The definition of two environmental rules

The last sheet of the xlsx file, called Agents, contains the definition of the agents. Here, the user can define individual agents in blocks starting with the keyword AgentBegin and ending with the keyword AgentEnd, which are written in the first column of the sheet.

Within this block, one can specify the parameters of an agent in a sequential manner, beginning with the definition of the identification of the agent using the keyword ID, followed by the initial contents (a multiset of objects) using the keyword content. Additionally, user can specify the position of the agent in the environment on the i-axis using the keyword start i and on the j-axis using the keyword start j. For each of the axis, there can be entered value \(-1\) for a random position on the particular axis. The last attribute, number of copies, is the number of the copies of this particular agent. This attribute allows creating an arbitrary number of the same agent without defining them separately. If the number of the copies of the agent is greater than 1, there a suffix \(\_x\) is added to the id of each gent, where the x is and index of the particular copy of the agent. These parameters are entered sequentially on the same line following the keyword AgentBegin, with each keyword-value pair written in the subsequent columns.

Next within this block, the definition of the programs of the agents follows. The definition starts with the keyword programBegin and ends with the keyword programEnd. These keywords are defined in the second column of the sheet. Inside the program block, there are individual rules. Each rule starts with the keyword “rule” on the same row within this block and the definition of the rule follows. The third column contains the left side of the rule, the fourth column contains the operator and the fifth column contains the right side of the rule. Operators are defined as follows:

  • > for an evolution rule,

  • \(<>\) for a communication rule,

  • l for a motion to the left,

  • r for a motion to the right,

  • u for a motion to the up,

  • d for a motion to the down.

The motion rule has no right side and its left side is the matrix where the lines are written one by one in a line separated by the commas. (see Example 3).

Table 3 Example of the motion rule “up”

A number of rules in the program must correspond to the height of the colony.

A simple example of the definition of an agent can be seen in Table 4. The identifier of the agent is Agent1. The agent contains internal objects e and a, and the initial position in the environment is 2, 2.

Table 4 The definition of two environmental rules

The output of the module parsing the excel file is a Python dictionary containing a dictionary of parameters, a dictionary of the environment, and a list of agents:

figure a

where the dictionary of the parameters is defined as follows:

figure b

and the dictionary of the environment is defined as follows:

figure c

Further structures can be obtained from the source code (see [11]).

The Excel input file served well as a tool for the analysis of the necessary parameters, but its weakness is, that the input cannot be easily programmatically created or modified. However, recent module parsing the Excel file can be replaced with another module, which parses an arbitrary input format like JSON, YAML, CVS or other; or the configuration can be generated as the python dictionary and imported as a flat file.

4.2 2D P colony controller

Before describing particular technical solutions, let us explain first the logic of the simulation. As we know from the definition, in one computation step, the agents act in parallel and if there is a conflict between two or more agents, one of the agents is non-deterministically chosen to deliver the action. Then, those symbols of the environment untouched by any agent are evolved according to the evolving rules of the environment.

From this point of view, the evolution rules of the agents cannot cause any conflict and can be executed without any check or other necessary actions. Hence, we need to focus on the motion and communication rules of the agents. In one derivation step, a symbol, which is used by a communication rule of one agent cannot be evolved by the environment and cannot be used by another agent. A symbol, which is entered into the environment by an agent cannot be evolved by the environment or used by another agent in the same step of computation. In the case of the motion rules, there can arise a situation, in which some symbol needed for the motion rule is removed from the environment.

At the beginning of each computational step, each agent creates a set of applicable programs, according to its position in the environment. Then one of the programs is non-deterministically chosen, but is not executed yet. All agents are lined up into a random order, which is different for each computational step. Then, each agent in this order tries to execute its chosen program. If there are only the evolution rules in the chosen program, the program can be executed without any other checks or conditions. For the other rules, the check if the rule is applicable must be performed first, since the contents of the environment might have been changed. If the communication rule has to be applied, e.g. \(a \leftrightarrow b\), then the symbol b entering the agent is removed from the environment, but yet, the symbol a, that should be inserted into the environment is stored in a special list toConcat2env. The pair consisting of recent position of the agent, hence the place, where the symbols enter the environment, and the particular symbol, a, is stored in this list. In this way, neither other agent nor the environment can use the symbol b, because it was already removed from the environment, and they cannot use the symbol a as well, since it was not inserted into the environment yet. Note, that the program is executed iff all the rules it contains can be applied.

Once all the agents have already tried to execute their programs, the evolving rules of the environment are applied. Then, the symbols from the list toConcat2env are inserted into the environment in the corresponding coordinates, and the computation step is done.

The application contains one main class Colony with a nested class Agent. The definition of the colony is passed via three attributes, environment, agents and jokerSymbols.

The class Colony implements six methods, which control the run of the simulation.

  • The method initComputationalStep(self) empties the toConcat2env list, mentioned above.

  • The method getApplicableRules(self, i, j) creates a set of applicable evolving rules of the environment.

  • The method evolveEnvironmet(self) applies the set of evolving rules of the environment.

  • The method add2environment(self) inserts the symbols from the list toConcat2env into the environment.

  • The method agentsAct(self) performs the actions of the agents:

    • generates a set of applicable programs for each agent,

    • creates a random order of the agents,

    • applies a random program of the agent.

  • The method colonyStep(self) performs one computational step of the colony. It subsequently calls the methods initComputationalStep(), agentsAct(), evolveEnvironmet(), add2environment().

The implementation of the nested class Agent involves the definition of the necessary attributes and methods for representing and manipulating the agents. The class Agent serves as a template for creating individual instances of the object agent with specific properties. The class Colony passes to the class Agent following attributes:

  • col—since the nested class in Python cannot reach the properties of the upper class, and we need to access the recent state of the environment, the contents of the object colony are passed as an attribute to each agent.

  • agentId—the identifier of the agent,

  • contents—the initial contents of the agent,

  • programs—the set of programs of the agent,

  • coordinates—the initial position of the agent in the environment,

  • jokerSymbols—the set of joker symbols, which allows the agent to work with substitute symbols if they are defined.

Each of these attributes is assigned to the agent during initialization based on the defined values in the configuration file as described in the previous subsection.

The class Agent implements five methods that control the behavior of the agent.

  • getVicinity(self)—this method reads the contents of the environment at all neighboring points around the agent, the method is used in the motion rules,

  • getEnvironmentContent(self)—this method reads the contents of the environment at the current position of the agent,

  • isProgramApplicable(self, program)—this method checks, if the passed program is applicable within the recent state of the environment and the contents of the agent,

  • getApplicablePrograms(self)—this method creates a list of all applicable programs within the recent state of the environment and the contents of the agent,

  • applyRandomProgram(self)—this method randomly selects one of the applicable programs and applies it.

4.3 GUI and visualization tools

The Graphical User Interface (GUI) is an important part of the 2D P colony simulator. It is a visualization of an interaction between the (evolving) environment and the community of the agents. It provides the user a clear and intuitive way to interact with the simulation. The GUI enables user to monitor the behavior of 2D P colony, observe real-time changes, and analyze the outputs of the different scenarios.

To render the simulation, we used the Matplotlib library, which is one of the most commonly used libraries for data visualization in Python. This library provides all the necessary tools to control the graphical interface such as zoom, environment navigation, etc. The Matplotlib library has several advantages, particularly the ability to create various types of visualizations, ability to capture images and flexibility in tailoring the results to the specific needs of this project. The library provides fast enough rendering in (so far) all tested cases on the usual hardware. The Matplotlib library assures a real-time animation of the simulation process. Moreover, the simulator is modular, hence recent rendering module can be easily replaced by a new module using another library like pygame or pyopengl, or utilizing different real-time data visualization methods, for example based on GPU image rendering.

The method called first is initPopulation. This method handles the initialization of a graphics window and its components. Its input parameters are the size of the environment, the positions of the agent, and the colors for significant elements, which have to be displayed on the visualization. This information is obtained from the class Colony.

In the first step, a Pyplot graphical window is created using the matplotlib library. The window displays the environment and its objects, such as agents. The matplotlib.imshow method is used for rendering. The arguments of this method are the size of the environment and the positions of the agents. By default, the canvas (environment) is gray, and the agents are represented as blue dots. The additional significant objects, for which the colors are defined in the parameters file, are rendered using a separate function called markInterest. This function iterates through each position in the environment and, if it finds a significant object, it colors its position.

Control tools, as movement, panning, zooming, taking a screenshot, etc., are part of the pyplot canvas and do not require additional definitions. However, the application can be extended with additional elements from the standard Tkinter library, such as labels that provide information about the state of the simulation (running, current iteration, etc.) or buttons controlling the simulation. The additional elements in the application window are arranged using the grid geometry manager, which allows organizing them in a tabular structure. In our case, we add only one necessary element, a label displaying the current state of the program.

The user can interact with the application during the simulation using the keyboard shortcuts. This feature is implemented by the keypress. We define two shortcuts. The c key is used to terminate the application (sys.exit), and the p key pauses the simulation for 5 s (pyplot.pause(5)). It is important to mention, that certain keys may be reserved by the matplotlib library (see the documentation for more information [9]).

At this point, the graphics window is initialized and all the components are displayed. For the next updates, i.e. redrawing the window to animate the computation, it is not necessary to recreate all these elements, but rather update them. To achieve this feature, we defined a method called updatePlot, which works as follows:

  1. 1.

    it retrieves the current information about the colony; contents of the environment and the positions of the agent,

  2. 2.

    then it modifies the labels if needed, such as updating the label counting the iteration steps,

  3. 3.

    then it highlights the significant symbols in the environment using the predefined colors,

  4. 4.

    and finally, it pauses the computation for a defined time period, as specified in the input xlsx file, to allow the user to observe the changes.

By implementing the updatePlot method, we can efficiently update and display the changes in real-time without recreating the entire plot. This method is called in the main application loop while the calculation is in progress.

When the simulation is completed, we call the termination method endOfVisualization. This method updates the labels to display the text End of simulation and keeps the final configuration displayed on the canvas until the user presses any key to exit. This allows the user to review the last configuration before closing the visualization. The final GUI example can be seen in Fig. 1.

Fig. 1
figure 1

The final GUI shows a \(10\times 7\) environment with two agents and several significant points highlighted in color

4.4 The function main, flow and execution

The function main of the program orchestrates the execution flow and serves as the entry point for the application. The application is launched in the standard way using the Python interpreter.

As we already mentioned, our application utilizes an input file containing parameters for the 2D P colony and its simulation. This xlsx file needs to be loaded and parsed. The loading process is handled by the openpyxl library in our extractExcel method, which requires a specific file structure as described in the previous sections. This method takes a file as input, which can be specified as an absolute path or defined as an input attribute using sys.argv.

Since the application is modular, if necessary, another module, parsing a different input file format, can replace the recent parsing module.

Once the file is parsed and all the values are loaded into the related variables of the newly created object Colony, the GUI with the visualizer can be initialized by the method initPopulation.

Afterwards, the main while loop of the application is initiated. Within this loop, the following steps are executed until the termination criterion, i.e. the maximum number of steps, is reached:

  1. 1.

    firstly, the controller performs a computation step of the 2D P colony, during which the state of agents and the environment is updated.

  2. 2.

    then, the output is passed to the GUI for visualization through the updatePlot method.

  3. 3.

    additional information about agent configuration and possible error messages can be entered into the operating system’s text console (command line or terminal).

Finally, when the computation is complete, the state at the last computation step remains in the GUI and the positions of the agents are written to the text console.

The final application (and further versions) is accessible at [11].

5 Example

Let us now demonstrate the creation of a 2D P colony configuration. An environment is a matrix 50 times 50 (Fig. 2). There are some objects O randomly placed in the environment. The objects are displayed in green. The border of the environment is created by the symbol #. Note, that the environmental symbol e is not present in the definition, since each field contains this symbol by default.

Fig. 2
figure 2

The definition of the environment

In our example, we use also one joker symbol *, representing any of the symbols occurring in the environment, hence e, O, and #. We use one environment rule and run the simulation in an infinite loop. The definition of the parameters can be seen in the Fig. 3.

Fig. 3
figure 3

The parameters of the colony

Our 2D P colony has one type of the agent which randomly wanders the environment and is able to carry the object. If the agent finds an object in front of it and does not carry anything, it steps on the field with the object and picks the object up. Then it turns back and continue the random movement. If it finds an object in front of it and carries an object, it steps on the field with the object and stockpiles carried object. Then, again, it turns back and continue the random movement. The definition of the mentioned rules for manipulating the object can be seen in Fig. 4. There are three programs defined in this example. The first program consists of the motion rule, the agent heads up and there is an object in front of it, respectively, above it, with respect to the grid. The second rule rewrites the symbol U, representing the motion up, into a symbol t. The symbol t allows us to control picking up or dropping down the object and it carries also the information that the agent heads up. The second program rewrites the symbol t into the D, hence turns the agent down and drops the object (exchanges it for an environmental symbol), if the agent carries one. The third program is applied, if the agent does not carry an object, so it turns the agent and picks the object.

The first rule of the first program demonstrates also the use of the joker symbol. The string “*,O,*,*,*,*,*,*,* ” represents the matrix in Table 5.

Table 5 The vicinity of an agent

The matrix represents the vicinity of the agent, where the agent is located in the middle of the matrix. The joker symbols represent any of the environmental symbol; hence, the only condition for applying this rule is that above the agent there must be a symbol O. All the other places can be taken by any symbol, which may occur in the environment. The topic of the random movement was discussed in our previous work (see [12]).

Fig. 4
figure 4

The rules for handling the object

A special set of rules is defined for a situation, when the agent reaches the borderline (the symbol #). The agent is not allowed to step on the symbol #; hence, when this symbol occurs in front of it, the agent turns back and continues the random movement (see Fig. 5).

Fig. 5
figure 5

The rule for reaching the borderline

Finally, a set of rules for movement is set. If there is neither border nor an object in front of the agent, it can freely move to that position (see Fig. 6).

Fig. 6
figure 6

Free movement rule

6 Conclusion and further extensions

In this paper, we discussed the process of design and implementation of the 2D P colony simulator, a very valuable tool for studying and analyzing the dynamics of this model. Through the use of agent-based modeling, customizable input parameters, and an intuitive graphical user interface, the simulator allows researchers and enthusiasts to explore the behavior, properties and emergent effects of 2D P colonies. Unlike our previous simulator, where the entire colony was hard-coded in the source code, this parametric approach allows us to change the definition of a colony using the parameters in a file.

Recently, the application is stable and provides all the basic functions. For further research, it is desirable to extend the functions of the run of the simulation, like navigating through the simulation back and forth, running alternative route of the simulation from a selected point of the simulation, and of course, save the run of the simulation, step by step into a file. This feature can be easily implemented by logging each computational step. A configuration of the 2D P colony in a particular step can be serialized and saved in a chosen format, e.g. YAML, JSON, CSV, into a flat file. Each logged configuration can then serve as an input configuration of the colony for an alternative scenario. As the rendering module consumes as the input the configuration of the colony, it is easy to navigate through the logged configuration and view the simulation as needed.