1 Introduction

IMDS (Integrated Model of Distributed Systems [1]) is a formalism used to identify and verify distributed systems, in particular to detect deadlocks and check distributed termination. The formalism reflects the behavior of components of distributed systems: servers in a distributed environment act asynchronously and make decisions autonomously. However, many modeling and verification formalisms provide mechanisms based on simultaneous actions of processes, like synchronous transitions on common symbols in Büchi automata [2] or Timed Automata [3], synchronization on send and receive operations in CSP [4] or Uppaal Timed Automata [5], synchronous operations on complementary input and output ports in CCS [4] or Occam [6]. Several automata-based formalisms (including Büchi automata and Timed Automata) use synchronous coordination. By contrast, IDMS models may be checked asynchronously.

The main feature of our IMDS is providing two views of a distributed system: cooperating servers or migrating agents. The system definition is uniform, but two projections allow for observation and verification of different properties: communication deadlock in the server view, and resource deadlock and distributed termination in the agent view. Mostly they are the same deadlocks but observed from different perspectives [1]. The vital feature of IMDS is finding partial deadlock/termination, in which a subset of processes is involved.

Students and engineers avoid formal methods, especially model checking, because determining the properties of a system in temporal formulas is not an easy task [7]. Avoiding formal methods is also a summary of our several years of observation. In order to persuade users to use formal methods, on the one hand, it is necessary to facilitate the specification of the system to be verified, and on the other hand, to simplify the verification process as much as possible. We achieved the latter by “push the button” verification, as we developed general temporal formulas, independent of the structure of the system under test. These formulas are built into the verifier and invisible to the user, who sees only the result of the verification in the form of meeting certain properties or not. A counterexample or a witness allows seeing the sequence of system behavior leading to the given result.

However, the verification itself must be preceded by a formal system specification, which is not an easy task. Ideally, we can describe the system components, and the verifier will automatically build a global model. These are the reasons for creating, for example, temporal verification systems for source languages, such as Bandera [8]. Likewise, in our Dedan environment, the imperative higher-level programming language Rybu [9] has been developed, however, it is beyond the scope of this article.

Also, the observation of the results and verification in the form of sequence diagrams is not an easy matter in the case of large systems. The development of an automatic model of system components, the semantics of which corresponds to a formal mathematical model, can facilitate both the specification of the system as a graphical input of the verifier and the observation of the verification result as a simulation of a counterexample over a graphical representation in the form of automata.

In this article, we describe just such an automata-based model, which is a graphical counterpart of the formal IMDS model. Together with automatic verification, our distributed automata make it easy for students and other users to enter easily and apply formal verification of distributed systems. Just as IMDS allows the system to be projected onto cooperating nodes or migrating agents, likewise distributed automata in graphical representation take the form of server automata or agent automata. The designer can choose between these two forms of specification and observation, and the verifier allows for easy switching between server and agent views, even with a partially completed model.

The contribution of this article is the introduction of DAAA—Distributed, Asynchronous and Autonomous Automata for modeling distributed systems (shortened to DA3—D-triple-A or DA-cubed). Their goal is to define distributed systems graphically and to simulate modeled systems graphically. An essential function of the simulation is to show changes in system components according to the verification counterexample. There are two versions of DA3 that reflect the communication duality: Server DA3 (S-DA3) and Agent DA3 (A-DA3). Both have the semantics equivalent to the IMDS specification, and therefore to each other. These two forms reflect two ways of describing distributed systems: as cooperating servers in the Client–Server-like specification or as traveling agents in the Remote Procedure Call (RPC) view [10]. They also reflect the fundamental characteristics of distribution: unicast communication, locality of execution, autonomy of decisions, and asynchrony of operation and communication.

First, we introduce the idea of DA3. Figure 1 presents an informal view of a distributed system buffer. This figure enumerates the elements of the example system, which are introduced formally later in the article. The system consists of 1-element buffer buf, and two users—producer Sprod and consumer Scons, so there are three servers presented in red. Each server can be in one of the states shown as red ovals; the initial states have a double border. Servers offer services presented by green arrows. These services are invoked by messages sent in the context of distributed computations called agents. The agents Aprod and Acons are initiated on the Sprod and Scons servers, respectively, and they migrate in the system to the server buf and back using messages identified with servers’ services. Here we do not distinguish between the concepts of service and messages, this distinction will be described in Sect. 5. Besides, the agents call from their home servers doSth services on the same servers, which models performing of activities other than operations on buf. Those messages are shown as Looping arrows. Initial messages (just doSth) have a double border.

Fig. 1
figure 1

The example 1-element buffer system

The system evolves by performing an action: each action takes a message in a given server state and creates a new server state and a new agent message that invokes the next action on some server.

The automata are graphical Mealy-style [11] projections of the system onto distributed components, i.e., servers or agents. Server automata S-DA3 are presented in Fig. 2. The automata headings are the server names in rounded red boxes. The nodes of individual automata (we do not call them “states” to avoid ambiguity) are placed vertically under the automata headings. Automata nodes are server states. In the full notation provided in Sect. 4, they have the form (server, value), here shortened to the value only, because the server name is the automaton heading. Actions are modeled as the transitions from a node to another node, having agent messages being input and output symbols. Messages are triples (agent, server, service) made up of the service name, and the server and agent names that match the action context. Service names, being part of message triples, are underlined. They are introduced in the informal Fig. 1. The automata are equipped with input sets of pending messages that are in no way organized into data structures such as vectors, stacks, or queues. The sets are shown as bags under the automata, with their initial contents. The view of these S-DA3 automata in the Dedan program is presented later in Fig. 6.

Fig. 2
figure 2

Server automata for the buffer system

The same system projected onto agents is presented in Fig. 3. In this view, everything is dual: the automata nodes are the agents’ messages, while the servers’ states occur as the transition input/output symbols. The automata headings are the agent names in rounded green boxes. The nodes of individual automata are placed vertically under the automata headings. States (server, value) consist of the server name and the state value. Message triples in the full notation provided in Sect. 4 are (agent, server, service), here shortened to the pairs (server, service), because agent name is the automaton heading. States are pairs (server, value) made up of the server name and state value. State value names, being part of state pairs, are underlined. They are introduced in the informal Fig. 1. The states are input and output symbols on the automata transitions. There is also a global vector of current server states, shown below the automata. The view of the A-DA3 automata in the Dedan program is presented later in Fig. 7.

The basic formalism for specifying and verifying distributed systems is IMDS, rather than the DA3. Automata facilitate the specification of the graphics system as a set of cooperating state machines. At the same time, in the Dedan environment, it is possible to simulate system operation in terms of automata and to track the steps of the counterexample obtained from model checking. The source IMDS code of a distributed system has semantics in the form of labeled transition system (LTS). A fragment of the LTS of the example system is presented in Fig. 4. We will show that the LTS-es produced by both forms of DA3 define the same semantics.

Our approach is not completely different from the other proposed automata models. The main difference is in the combination of the automata-based and the process-based model, the two formalisms with equivalent semantics but different in the way they express the behavior of servers and migrant agents. The textual process model is ideal for studying the characteristics of specific systems using temporal logic and other algebraic methods. On the other hand, the automata are closer to the designer's intuition and are perfectly suited to the specification of the system, its simulation or the observation of the course of counterexamples obtained from temporal verification. The duality of the automata model is important in this context, as it emphasizes the cooperation of distributed servers, or the migration of agents traveling between nodes. It is an extension of Lauer Needham's concurrency dualism postulate [12] to distributed environments.

IMDS as a broad theoretical base has been discussed in several articles, including [1]. The present article is the continuation of the work presented in [13], in which the informal background of DA3 was given. The novelty of the approach presented in the present article is:

  • More formal specification, as the construction of the LTS for a set of automata was not defined yet;

  • On the base of the DA3 LTS, and the IMDS LTS the specification, the equivalence between IMDS and DA3 is described;

  • The application of DA3 in modeling and verification of distributed systems was previously presented in brief three paragraphs, now we present some procedures of verification and simulation in the Dedan environment in detail; these procedures evolved during several years of developing and using Dedan, mainly in education;

  • Only a tiny model was provided as the subject to IMDS and DA3 specification, now we discuss a reasonable size system;

  • A new feature is added to the Dedan verification environment and described in this article: the simulation of DA3 run following a counterexample; this is very useful in the verification procedure.

The article is organized as follows. The numerous formalisms known as distributed automata are discussed in Sect. 2. The definition of the basic IMDS formalism is given in Sect. 3. Section 4 provides an IMDS specification of the same buffer system as seen above. An informal view of the distributed automata DA3 is given in Sect. 5, and the definition in two forms S-DA3 and A-DA3, in Sect. 6. A practical example of DA3 application is described in Sect. 7. Section 8 presents an example of how Dedan works when simulating an example from Sect. 4. Also shown are examples of S-DA3 and A-DA3 views in the Dedan environment. Conclusions and further work are covered in Sect. 9. The equivalence of basic IMDS and both versions of DA3 is presented in the Appendix.

2 Related work

Discrete event systems are those whose evolution is triggered by symbols produced and consumed or exchanged with the external world. They are especially useful for modeling digital distributed systems. Among them, the most common are Petri nets, process algebras, and finite automata [15]. Generally, automata-based specification consists in connecting some states by means of transitions [16]. Formally, states are valuations of internal variables of a system. The transitions show changes between these states in response to occurring symbols (letters of the input alphabet). In practice, these symbols denote external events sent to the automaton, such as signals or messages. Distribution is often modeled as decomposing the global automaton into a set of concurrently behaving component automata, and splitting the set of symbols into subsets, which can overlap. Private symbols mean local actions, while common symbols are treated as communication [17].

An important element of the automaton is the current state, which illustrates the phase in the automaton evolvement. The automaton starts from the initial state. Additionally, some approaches require final states and some do not. In formal linguistics, final states accept input sequences, while in behavioral automata they are treated as termination.

Automata are used to express the behavior of state-based systems that are most commonly used in computer science and technology. The second area of application is formal linguistics, used to check whether a given sequence belongs to a language or to transform an input sequence to an output sequence. Sometimes these two functions are combined, for example in compilers. This article covers the first area that describes the behavior of a system as a state-transition diagram. Whereas actions typically happen on the transitions, in some approaches the states also encapsulate activity, consisting of sequences or parallel combinations of actions. Examples of activity states include the tasks of BPMN (Business Process Model and Notation) [18] and the states of UML (Unified Modeling Language) State Machine Diagrams [19]. An important feature of automata is their descriptive graphic form, friendly to human perception. Therefore, automata are widely used in education, digital circuit design, information systems specification, and other purposes.

Concurrency is a crucial issue in hardware and software design. For this purpose, sets of cooperating automata have been developed. In a system of concurrent automata, their states form a state vector describing the global state. Concurrent automata are used, for example, in hardware design, communication protocol specification, and parallel programs description. Two important considerations are: how the transitions in component automata are combined to global transitions and how the symbols are exchanged. Externals events may come from outside the system and events generated by automata, that are offered to other automata and to the external world. The system is open if events can come from the external world, and closed if they come only from automata.

The semantics of an automaton is defined such that if it remains in a given state and an input letter is proposed that matches a letter on the transition, the automaton changes its state to the target of the transition. If the same letter triggers multiple transitions, or if more than one letter is offered at the same time, the automaton is assumed to be nondeterministic. The semantics of concurrent automata concerns the way of combining the transitions of individual automata: in parallel, interleaved or mixed. Parallel semantics is the simultaneous execution of enabled transitions, interleaving means execution of one transition at a time. In the case of mixed semantics, for example in parallel Büchi automata [2], parallel transitions mean synchronization, while interleaved transitions refer to individual behavior. The communication structure can be designed in various ways, e.g., when signals are received by every automaton, it is assumed to be a kind of global ether through which all distributed components observe symbols. If the automata cooperate in pairs, synchronous or asynchronous communication channels are assumed. Some intermediate communication structures may exist, such as the previously mentioned stacks or queues, which further complicate the semantics and which may introduce additional asynchrony (aspects of asynchronous behavior are discussed below). Even more complicated structure of the multi-access Reo channels is proposed in [20]. Many types of concurrent or parallel automata were elaborated [21,22,23]. The timed versions are described in [24], and probabilistic versions in [25].

Many works describe formalisms called "distributed automata." There are fundamental differences between parallel but centralized, and distributed automata that model distributed computing. A significant difference between our automata and other presented models is the reflection of the actual features in distributed systems of communicating nodes. The features of these systems are unicasting, autonomy, locality, and asynchrony. It is imperative to fully explain our understanding of these concepts to avoid terminological confusion. Of course, other authors may use a different interpretation of the given terms, and they have every right to do so. However, we will focus on the interpretation that, in our opinion, reflects the specifics of the operation of actual components of existing distributed systems, because we focus on modeling and verification of such systems.

  • addressed communication—there are different communication methods in distributed systems, and here we have no ambition to cover all possible ways. Systems that disseminate information about events or provision of services may naturally use a broadcasting model of communication (messages are sent to every component node). Systems that consist of replicated server clusters may naturally use a multicasting communication model (messages are targeted at relevant subsets of the component nodes, of which one or another node may choose to respond). Systems that model distributed computing explicitly are best described using a unicasting model (messages target specific component nodes in the system, where migrating agents may execute sequences of operations on the target server). Examples of the kind of distributed processing environment suitable for unicasting include: object-oriented middleware, in which processes migrate between distributed objects that execute these; or systems of communicating physical agents, such as autonomous vehicles, or collections of communicating nodes in IoT networks, or similarly in web services computing. Each event should be routed precisely to the server automaton rather than available for all components. We deliberately exclude broadcast or multicast-based systems that are modeled for example in CSM (Concurrent State Machines [26]);

  • locality—in a distributed environment, the components do not have access to the global state. The automaton’s knowledge of other automata is limited to the last communication with them. The decision of each automaton is made on the basis of its local state and received events. In a centralized solution, an automaton can observe the global state, i.e., the values of all global items: states of other automata, globally pending symbols and/or global variables, if they are present in the formalism. The automata shown in Fig. 5 , which are components of automata systems (PDA—Pushdown Distributed Automaton, MPA—Message Passing Automaton and DA3—our distributed automaton), can be assumed distributed when composed with other automata of the same communication scheme, because the automaton and its input structure (stack, queue or set, respectively) provide a local framework for making decisions which transition to execute. We could think of a set of locally pending messages as an extension of the server state, but we think that it is more convenient to extract them as carriers of distributed agents. Whether the server remains in a state or leaves—it depends entirely on its current state and pending messages, it is not affected by any non-local system elements: the states of other servers, the actions they take, or refraining from taking any action;

  • autonomy—the automaton autonomously decides which event is accepted and causes the transition to be executed. No action or property of the environment can order or prevent a server from taking a certain action. It is modeled as collecting events on the automaton’s input, that can trigger transitions outgoing from a given state, each triggered by an input symbol (or in some solutions by a combination of symbols). In nondeterministic models, the same symbol can trigger more than one transition. In some formalisms, the freedom of the automaton is limited, as depicted in Fig. 5 . It shows two concepts of automata that only have access to one of the pending symbols. They are: PDA that gets the symbol on the top of the stack, and MPA that gets the symbol waiting the longest in the input queue. The third type DA3, the subject of this article, chooses freely from its input set. The random selection of the input message is realized comparably to the guarded select statement. Of course, what actions can be taken under what circumstances depends on the "program" contained on the server, which we model as a set of actions that have the server states and messages directed to this server on their input. It is up to the designer to accept the message and take action (or not accept a certain message in a particular state). Messages are treated the same way: there is no data structure that stores messages and makes them available in a particular way—like a queue or a stack. If the designer wants to accept messages in a specific regime, he or she can program this feature in the server action set. Significantly, delivering new messages to a server can never reduce the set of actions allowed in a given state, it can at most increase that set. Obviously, accepting the message leads the server to a new state in which specific actions may be forbidden. Autonomy is closely related to locality, but in our opinion, it is not conceptually identical with it;

  • asynchrony—can be considered in three aspects: asynchrony of actions in processes, asynchronous delivery of messages, and whether the communication primitives are blocking or non-blocking.

  1. i.

    The asynchrony of actions consists in the fact that two processes provide in a certain way the input elements necessary for its execution, in our case: the state of the server and the message. There may times when the process itself provides all the elements (in the DA3 case, it happens when a message is sent to the same server—then the same process provides the state and the message). In this case, both are delivered synchronously, but the synchrony is hidden inside the process. If two processes need to deliver the items at the same time, or if the delivery of the item depends on what is happening in the other process, we will call the action synchronous. This is the idea behind Büchi automata and Timed Automata [27], where two (or more) automata perform a synchronous joint action (although the authors call them asynchronous because the remaining local actions are performed completely independently). The necessary condition for the performance of this joint action is that both automata reach the states preceding these synchronous transitions, which we can interpret precisely as providing the elements necessary for its implementation. If the processes (in our case two, but in other formalisms there may be more of them) provide the elements necessary to perform the action without looking at the other—then the action is asynchronous.

    In our case, apart from the situation of sending the message to the same server, in the action λ of the server s, the output message m to is delivered to another server s’—the message m target server. The servers’ can already be waiting in the state p’ for the message m. In such a case, an action λ’ will be initiated on the target server s’ (see Sect. 3 for formal details of action as the relation between messages and states). If the message m is not an input pair with the current state p’ of the server s’, then the message m will wait on the server s’ for such a state. The new state p’’ of the server s, generated in the action λ, can match one or more messages waiting on the server s, which together with the state p’’ will initiate another action λ’ on the server s. If the state p’’ does not match any of the messages pending at the server s—it will wait for the matching one to appear. On both servers s and s’, the actions are initiated asynchronously: the state is waiting for a message, or the message is waiting for the matching state. Of course, this always happens in the interleaved model, which is ours. In some models with coincident semantics, the state and message may appear simultaneously but accidentally. However, this accidental synchrony is not required for the asynchronous execution of actions.

  2. ii.

    Communication asynchrony—the moment of sending the message does not depend in any way on the recipient's readiness to accept it, the recipient's state or actions performed in it. Models such as the coincident, precisely synchronous message delivery in two Büchi automata or Timed Automata are not adequate for distributed processing in our opinion. In the Büchi and TA formalisms, automata communicate by performing a joint transit with the same symbols. This is usually interpreted as sending and receiving a message. In TA implementation of the Uppaal verifier, this common symbol even comes with attributes ! and ?, denoting sending and receiving of the message. This corresponds to actions (which in Büchi and TA are equivalent to communication, but not in our case, because the actions are local) when automata reach certain states at the same time or need to find out what the current node of the other automaton is (i.e., synchrony or non-locality). In fact, in our opinion, there is no other way to know if the other server is willing to accept the message other than sending the message and waiting for a reply. Moreover, receiving a reply informs only the state of the second server at the time of sending the reply, but at the moment of receiving the reply, it is not known what could have happened after sending it. In some models, asynchrony is modeled by a kind of "buffer" separating servers [28]. The process can send to the buffer at any time, and the reception will take place at the right moment. In our opinion, this significantly limits modeling, as such buffers clearly organize messages (typically FIFO), and there is also a problem with determining the buffers capacity (see below). A direct consequence of the asynchrony of communication is the indefinite time of message delivery, which is also a way of defining this asynchrony [29]. On the other hand, in [30][31], the communication asynchrony is defined as the separation of the operations of sending and receiving messages. In summary, it can be said that in the synchronous model, the automata synchronize to communicate, while in the asynchronous model, they communicate in order to synchronize.

  3. iii.

    The third aspect is blocking: synchronous communication consists in passively waiting for sending/receiving a message when the partner is not ready, i.e., non-blocking communication as opposed to blocking [32, 33]. While sending, the sender waits until the recipient is ready to receive the message, unless it is already ready. When receiving, the recipient waits for the message after initiating the operation, unless it is already ready to receive it. So we refer again to knowing the state of the other server, or the communication takes place at the same time. While from the recipient’s point of view, it is possible to imagine blocking communication, from sender’s point of view it is unrealistic, for the reasons already discussed. In our model, communication is non-blocking both on the part of the sender’s side, i.e., sending the message is sent without knowing the recipient's state, as well as on the receiver’s side, because the recipient is always sensitive to receiving new messages from any sender, even if it is waiting for a specific message.The third aspect is blocking: synchronous communication consists in passively waiting for sending/receiving a message when the partner is not ready, i.e., non-blocking communication as opposed to blocking [32, 33]. While sending, the sender waits until the recipient is ready to receive the message, unless it is already ready. When receiving, the recipient waits for the message after initiating the operation, unless it is already ready to receive it. So we refer again to knowing the state of the other server, or the communication takes place at the same time. While from the recipient’s point of view, it is possible to imagine blocking communication, from sender’s point of view it is unrealistic, for the reasons already discussed. In our model, communication is non-blocking both on the part of the sender’s side, i.e., sending the message is sent without knowing the recipient's state, as well as on the receiver’s side, because the recipient is always sensitive to receiving new messages from any sender, even if it is waiting for a specific message.

All the above features of asynchrony are met by the construction both in the IMDS formalism and in the DA3 model that is unambiguous with it. Note that a synchronous system can be defined as one in which all distributed components execute in lock-step, using the same central clock, for example CSM [26]. Therefore, an asynchronous system is one in which all distributed components execute following their own local clocks, out of lock-step. In our approach, we do not introduce any notion of clocks, neither central nor local.

Another aspect of distributed computations is communication duality—this non-obvious feature applies to two aspects of distributed computations. The famous Lauer-Needham postulate [12] concerns the equivalence of communication through messages and resources (variables). This duality expresses itself in distributed systems as the alternative of Remote Procedure Call versus Client–Server architectures. Thus, the system described in the two paradigms should have two forms of automata: distributed servers communicating via messages and traveling agents communicating by servers’ states. This leads to unobvious assumptions about the states of distributed automata and exchanged events: in the view of the servers following the Client–Server architecture, there are natural automata nodes reflecting the server servers, and the transitions are triggered by events—messages exchanged between servers. However, in the view of RPC architecture, in which the computations take the form of agents traveling between servers, the automata nodes should be assigned to the messages by which the agents run, and the events relate to the states of the servers. This turns the description of the distributed system upside down, but after reflection it is as natural as the wave-particle duality in Physic. However, everything is fine if both descriptions—distributed server automata versus traveling agent automata—have the same semantics, described as all possible system executions.

Note that in Fig. 1 , and in all subsequent figures, all elements related to the servers and their states are colored red, while all elements related to agents and their messages are colored green.

In the literature, several types of automata are called distributed (DA).

  1. 1.

    Automata on distributed alphabets, communicating by means of common symbols, based on Zielonka’s automata [34]. The automata are called DA in many works concerning the behavior of concurrent systems (sometimes additionally equipped with real-time clocks for time analysis with real-time constraints): [35,36,37]. Those automata are called asynchronous in [38, 39], although they perform actions (execute the transitions) asynchronously only if the input symbols are different. They make synchronous moves on common input symbols (and it is the only common aspect of separate automata). From our point of view, those automata should be called synchronous. Alur’s Timed Automata [3] (sometimes called DA [35]) are very close to Zielonka’s automata; they are additionally equipped with time constraints and time invariants. CSP processes are similar, synchronizing on ! and ? operations instead of common alphabet symbols. The advantage of CSP is to specify the direction of communication (! sends, ? receives), which in the case Zielonka’s automata should be provided informally. A similar concept is used in modeling distributed hardware systems in [40]. The hierarchical description of distributed symbols is undertaken using the nested version of such automata [41].

  2. 2.

    Close to Zielonka’s automata are Büchi automata. They differ in distinguishing some states as accepting, used for LTL model checking (for instance, in Spin [2]). They are called DA in [42].

  3. 3.

    Message Passing Automata (MPA, called DA in [43, 44]) are really distributed and asynchronous. They contain ordered sets on symbols waiting for acceptance, called buffers or queues. Such automata using FIFO buffers are called asynchronous DA in [45].

  4. 4.

    Pushdown Distributed Automata (PDA) are equipped with local memories of input symbols (stacks) [46].

  5. 5.

    The two former cases (MPA and PDA) are combined in [47, 48] and called DA.

  6. 6.

    Cellular automata are sometimes called DA [49]. They are synchronous in nature, but their evolution does not depend on the global state. Only the previous state of the cell and its neighbors’ states are taken into account. Cellular automata with reduced communication for the purpose of distributed implementation are presented in [50].

Above listed formalisms are referred to as “automata,” but there are other models of distributed systems, some of them even closer to some of the requirements presented, for example, synchronous statecharts with sets of input events [51] and asynchronous statecharts with input dispatchers [14]. Communicating stream X-machines [52] with input buffers communicate asynchronously. We can treat any buffered communication as asynchronous because no knowledge about the target component state is required. However, they are formally intractable because of unbounded delays. Moreover, such buffers are unrealistic to implement, and if they are bounded, incoming messages must be blocked or lost in a case of a full buffer. Therefore, some knowledge about the receiver state comes back. In addition, the size of the input buffers is difficult to define, and too small buffers can cause deadlocks [53]. Note that in our formalism, the messages are the carriers of agents, therefore the total number of messages pending on input of servers is limited to the number of agents. Also, the agent is the context of the message, and the message is part of the action definition, so the maximum number of messages in a given server is limited to the number of agents that can invoke the server’s services. Message designates something like "agent state," and therefore there is exactly one system-wide message for each non-terminated agent, so the same agent cannot route multiple messages to a node, for example, messages coming from different servers.

In our opinion, none of the aforementioned formalisms fully meet the requirements set by DA described above: addressed communication, locality, autonomy, asynchrony, and communication duality. We developed Distributed Autonomous, Asynchronous Automata—DA3 (D-triple-A or DA-cubed, to distinguish them from all the outlined formalisms, all called DA). Our automata reflect the behavior of distributed components. Servers independently make decisions (perform actions) without knowing the state and pending messages in other servers (autonomy), and messages are sent regardless of the states and messages in the target servers (asynchrony). Since there are two distributed system views in IMDS, two forms of DA3 have been developed—Server-DA3 and Agent-DA3 (S-DA3 and A-DA3). We present them in Sect. 5 after describing the basic IMDS formalism. Both forms of DA3 are equivalent to IMDS.

3 Integrated Model of Distributed Systems (IMDS)

We model closed distributed systems, i.e., those in which all activities depend on internal components and are not possible to interact with the outside world. All the signals that cause changes to the system come from its distributed components. If there are user processes that interact with the system, they must be modeled as components inside. No external signal can be observed, but the signals generated in the system can be observed from the outside, informing about system activity.

In IMDS [1], a distributed system is simply a set of actions, having pairs of state and message on input and on output. It is based on the observation that the server is activated by an incoming message in a distributed environment. If the message is accepted—which depends on the server’s current state—it performs some action. The action executes the specified service and generates the next server state. The messages are the carriers of agents. The agent has a mission to fulfill in a distributed environment. This mission is accomplished through distributed computing performed on servers. Therefore, the action on its output generates a new agent message in addition to the new server state. Typically, a new message is sent to continue the agent computation on a different server or sometimes on the same server. Thus, the system actions are the relation Λ on the set P of servers’ states and the set M of agents’ messages. Precisely, the action λ ∈ Λ connects two pairs: an input pair (message, state) and a similar output pair:

$$ {\varLambda} \subset (M \times P) \times (M \times P) $$
(3.1)

There are sets of servers S = {s1s2, …, sn} and agents A = {a1a2, …, ak}. The set P is split into disjoint subsets attributed to the servers: Ps1, …, Psn, while the set M is split into disjoint subsets attributed to the agents: Ma1, …,Mak. The mapping Ms is the same as assigning agent visits to servers; it means that the corresponding agent messages will be seen by the appropriate servers. The action λ ∈ Λ, λ = ((m, p), (m’, p’)) involves server si and agent aj. The input and output state belong to the same server: p, p’ ∈ Pi, and the input and output message belong to the same agent: m, m’ ∈ Mj. Each state is attributed to a server, and each message is directed to the specific server to invoke its service, which is modeled by functions Ps: P → S, Ms: M → S, Ma: M → A. In each pair (m, p) which is the input of action λ, the server components must match: Ms(m) = Ps(p).

Agents can be infinite or may terminate in special actions of the form λ = ((m, p), (p’)), where the output message is absent. Note that we exclude broadcast and multicast communication because the messages are agents carriers.

The behavior of the distributed system is determined by its labeled transition system—LTS [54]. The vertex in LTS (we do not use the name “state” to avoid ambiguity) is a configuration T of IMDS model: a set of current states of all servers and current messages of all agents (except terminated). The initial configuration T0 contains initial states P0 and initial messages M0. The input configuration Tinp(λ) of the action λ = ((m, p), (m’, p’)) contains m and p belonging to its input pair (m, p) and the output configuration Tout(λ) contains m’ and p’ of its output pair (m’, p’). Obviously, Tinp(λ) and Tout(λ) are not functions because they include the elements of the pairs (m, p) and (m’, p’), respectively, all states and messages about servers and agents other than those participating in λ are arbitrary.

$$ \begin{aligned} {\text{LTS }} & = \left\langle {Q,~q_{0} ,~W} \right\rangle {\text{where}}: \\ Q & = {\text{ }}\left\{ {T_{0} ,~T_{1} ,~ \ldots } \right\}{\text{ }}\left( {{\text{vertices}}} \right) \\ q_{0} & = T_{0} \left( {{\text{initial}}\,{\text{vertex}}} \right) \\ W & = {\text{ }}\{ {\text{ }}\left( {T,\lambda ,{\text{ }}T^{\prime } } \right), \ldots {\text{ }}|\lambda \in \varLambda ,T = T_{{{\text{inp}}}} \left( \lambda \right),T^{\prime } = T_{{{\text{out}}}} \left( \lambda \right){\text{ }}\} {\text{ }}\left( {{\text{transitions}}} \right) \\ \end{aligned} $$
(3.2)

Actions are interleaved (one action executed at a time [55]). Note that each server performs its action locally and autonomously (only the state of the server and the messages pending on that server are taken into account). In addition, the communication is asynchronous: the server process sends a message to another server process (or the agent sets the server state for another agent) regardless of the current situation of the target process (and any other process). The pair (message, state) that triggers the action does not occur synchronously: the state is waiting for a matching message, or the message is waiting for a matching state. The only exception is the message sent to the server itself: the new state and the new message appear in the server synchronously. This is natural because synchrony is allowed on a single server. As a result, we may call the processes autonomous and asynchronous, and the action is executed locally.

Note that in real distributed systems, there is no interleaving; unrelated activities may run in parallel but are not synchronized. Interleaving is one of the possible semantics of parallelism, another is the semantics of simultaneity, more akin to the operation of a distributed system. We use interleaved semantics because of its simplicity, and Manna and Pnueli have shown that it is equivalent to concurrent [56]. Also, please note that the servers are autonomous, thus no action can invalidate another action in other server. On the other hand, the actions enabled in the same server are always in conflict due to interleaving: one of them is executed at a time and typically it disables other actions prepared in the same server (if the output state is different from the input one).

Processes in the system are defined as sequences of actions. Suppose two consecutive actions in the process are connected by the server state. In that case, it is a server process that communicates with other server processes by means of messages (states are carriers of server processes). If two consecutive actions in the process are connected by an agent message—it is an agent process that communicates with other agent processes through the states of the servers (agents’ messages are carriers of agent processes). As some actions may be inaccessible in a given system, they are not included in any process, as they are not part of any sequence. To avoid such “orphan” actions, we allocate them to sets instead of sequences. The process Bi of the server si is the set of actions with the sever si states on input. The process Cj of the agent aj is the set of actions with the agent aj message on input.

$$ \begin{aligned} B_{i} & = \{\lambda_{1} , \, \lambda_{2} , \ldots \in \varLambda |\lambda = \left( {\left( {m, p} \right), \left( {m^{\prime } , p^{\prime } } \right)} \right) \vee \lambda = \left( {\left( {m, p} \right), \left( {p^{\prime } } \right)} \right),p, p^{\prime } \in P_{i} \} ,i = 1, \ldots , n \\ C_{j} & = \{ \lambda_{1} , \, \lambda_{2} , \ldots \in \varLambda |\lambda = \left( {\left( {m, p} \right), \left( {m^{\prime } , p^{\prime } } \right)} \right) \vee \lambda = \left( {\left( {m, p} \right), \left( {p^{\prime } } \right)} \right),m, m^{\prime } \in M_{j} \} ,j = 1, \ldots , k \\ \end{aligned} $$
(3.3)

The decomposition of the system into server processes is called the server view, and the other is the agent view.

$$ \begin{aligned} B & = \{ B_{1} , B_{2} , \ldots , B_{n} \} \\ C & = \{ C_{1} , C_{2} , \ldots , C_{k} \} \\ \end{aligned} $$
(3.4)

Examples of distributed systems modeled in IMDS can be found in [57]. In [58], the verification of the Karlsruhe Production Cell is covered, in which servers implement devices in the cell and agents implement metal plates that are processed. In automatic vehicle guidance system [59]—servers implement road segment controllers, and agents implement vehicles.

4 Simple IMDS example: buffer

The Dedan program was developed for the specification and verification of distributed systems. A distributed system in IMDS is simply a set of actions and initial items (states and messages), but for programming purposes, the input form of Dedan contains a definition of types and variables, formal and actual parameters, and an initialization part. In addition, actions are grouped for individual servers or agents, and repeaters can be applied to facilitate the definition of sets of similar actions. For the action λ = ((m, p), (m’, p’)), treated as the execution of the service on the server, a more convenient notation is used, in which the server state p is denoted as pair (s, v), where s is the server and v is the value of the state, s ∈ S, v ∈ V. This allows the introduction of server types with similar sets of states, but differing in s. We have two server vectors mE[2] and lotE[2] in AVGS source code in Sect. 7. The message m is denoted as triple (a, s, r), in which agent a invokes the service r is on the server s, a ∈ A, s ∈ S, r ∈ R. Therefore, instances of the agent type can differ only in a or in a and s. We have the agent vector AMP[N], N = 2 in AVGS code. The server type can offer a number of services, for example, wait and signal on a semaphore, put and get on a buffer, etc. The action λ = (((a, s, r), (s, v)), ((a, s’, r’), (s, v’))) has the form {a.s.r, s.v}- > {a.s’.r’, s.v’} in Dedan source code. Note that the symbol → does not represent a function; it is introduced to show the progress of the action from its input to its output items and is similar to the graphical representation of an automaton transition as an arrow. Also note that a single action is deterministic as it is a tuple in the Λ relation. The nondeterminism lies in the fact that the same pair (m, p) can be an input pair of many actions, corresponding to nondeterministic divergences, for example λ1 = ((m, p), (m’, p’)), λ2 = ((m, p), (m’’, p’’)). Nondeterminism can refer to the server: m’ = m’’, p’ ≠ p’’, to the agent: m’ ≠ m’’, p’ = p’’, or both: m’ ≠ m’’, p’ ≠ p’’. Yet another type of nondeterminism arises from interleaving, since when multiple actions are enabled, only one of them is executed. If the actions are in different servers, then the execution of the action cannot invalidate the action in the other server.

The more abstract imperative language Rybu has been developed [9], but the basic IMDS notation is more appropriate for the purposes of this article, so we do not refer to Rybu here.

A simple example of a buffer with producer and consumer agents (each one originating from its own server) is provided in the listings below, to illustrate the two views of a distributed system. First, the server view follows. The notation is intuitive: server types are defined (lines 2, 9, 16). The formal parameters specify the agents and other servers used. Each server type contains states (3, 10), services (4, 11), and actions (6–7, 13–14). Then the server and agent variables are declared (17,18). Variables can have the same names as the types; they are distinguished by context. If a variable has the same identifier as its type, then the variable:type declaration may be suppressed to a single identifier, as in the example. Finally, servers (20–22) and agents (23,24) are initialized, and variable names are associated with formal parameters of servers.

figure b

Sample action (6) reads: when the agent Aprod invokes the service put on the server buf, and the server is in no_elem state, then the server changes its state to elem and the message ok_put is issued to the server Sprod in the context of the same agent. The system converted to the agent view (this is done automatically by the Dedan program) is as follows.

figure c

Note that the set of system actions is uniform; the views differ only in a manner actions are grouped. In the server view, the actions are grouped into individual server types, while in the agent view, they are grouped into individual agent types.

A fragment of the LTS of the example system is presented in Fig. 4 . The vertices in the first line display messages of the agents Aprod and Acons are (without agent identifiers), and the states of all servers (buf, Sprod, Scons) are displayed in the second line (without server identifiers). Of course, the LTS’es generated from both the server view and the agent view are identical because they are projections on servers and on agents of a uniform system, and the views are its decompositions.

In the example, the servers and agents are deterministic, just to reduce the system and its LTS to a small size. Nondeterminism in the LTS comes from concurrency. Nondeterministic automata can be found in our other papers, where automata notation is used informally for the illustration of distributed systems designed in IMDS: A special kind of bounded buffer with agents switching between producer and consumer roles [60] or buffer with a capacity > 1, that can accept both putting and getting if it is neither full nor empty [1]. In student exercise examples shown later in Fig. 24, S-DA3 views on the left are almost all nondeterministic: more than one transition is enabled (highlighted). The system components in the present example could be easily converted to nondeterministic, allowing the producer and consumer to do something different in many steps between their activities connected with the buffer. Actions introducing nondeterminism in producer would, according to the server view, be additional action 13a:

13a. {Aprod.Sprod.doSth, Sprod.neutral}—> {Aprod.Sprod.doSth, Sprod.neutral}.

and according to the agent view, additional action 8a (in fact, it is the same action buf in different grouping):

8a. {Aprod.Sprod.doSth, Sprod.neutral}—> {Aprod.Sprod.doSth, Sprod.neutral}.

Nondeterminism can result from multiple agents that run is a single server. For example, if we have several producers, any of them can call put on the buffer. The changes of the source code in the server view are (original line numbers are preserved, and line 0 is added for a constant definition, the differences are underlined):

figure d

Using Dedan, communication deadlocks in the server view and resource deadlocks in the agent view can be identified, and distributed termination can be checked. There is no deadlock in our example; deadlocked systems are presented with counterexamples in [57][58][59]. For a simple, practical example, see Sect. 7. A counterexample or other behavior can be tracked in Dedan using the simulator. The simulation is performed over the LTS of the verified system. Often, however, the simulation would be better performed over the components (servers and agents) of the verified system, shown separately and cooperating with each other. For this reason, we have introduced distributed automata—an alternative formulation of IMDS systems. Our distributed automata are equivalent to IMDS, but allow for graphical definition and graphical simulation of distributed systems in terms of its components. Of course, the graphic form should maintain the locality of actions, the autonomy of components and the asynchrony of their behavior. The duality of communication must also be preserved, so two forms of graphical specification have been developed: one for the server view and the other for the agent view.

5 Informal view of Distributed Automata DA3

We are introducing DA3 informally but systematically. Since everything is dual in IMDS, we build the automata so that in server automata, the transitions lead from state to state (of the same server), having messages as input and output symbols on the transitions. In the opposite view, agent automata lead from message to message (of the same agent), having servers’ states as input and output symbols on the transitions. So for the action ((m, p), (m’, p’)), we have the transition \(p^{\underrightarrow {m~/~m^{{\text{'}}}}}p{\text{'}} \) in server automaton s = Ps(p) and the transition  \(m^{\underrightarrow {p~/~p^{{\text{'}}}}}m{\text{'}} \) in agent automaton a = Ma(m).

Let us look at the server view first. To avoid ambiguity, we call the automaton states nodes, as the term “state” is attributed to IMDS servers. Each server process is modeled using a server automaton equipped with its input message set. This models distributed servers communicating through message passing, similar to the Client–Server model of distributed systems [10]. There are three severs automata in the buffer example depicted in Fig. 2. In the automaton Sprod, its nodes are simply the states of the server Sprod: (Sprod, neutral) and (Sprod, prod). Since the name of the server is the same in both pairs, the figure shows only the state values in the ovals of the nodes. Each transition relates to an action in the server Sprod, triggered by a message addressed to the server, which matches its current state. The figure shows the initial content of the input sets. The initial nodes of the automata have double borders. The view of these server automata in the Dedan program is presented in Fig. 6 .

For example, the node (Sprod, neutral) accepts the message (Aprod, Sprod, doSth), which is the input symbol of the automaton transition \((Sprod, neutral)^{\underrightarrow {\left( {Aprod,~Sprod~,doSth} \right)~/~\left( {Aprod~,buf~,put} \right)}}(Sprod, prod)\). The message must be stored in the input set of the automaton to fire the transition. The action generates the new state of the server (Sprod, prod) and the new message (Aprod, buf, put), which are modeled as the destination node (Sprod, prod) of the transition and the output symbol of the transition (Aprod, buf, put): the message generated on the transition. Since the action took the only message from the input set, and the new message is addressed to the buf automaton, the Sprod input set becomes empty. Therefore, no action can be executed in the automaton Sprod at this time. However, if in the future the automaton can receive a message to its input set, and if this message matches the state (Sprod, prod), then the transition in the automaton will be possible.

The input set of the automaton buf can contain two messages simultaneously: (Aprod, buf, put) and (Aprod, buf, get). However, only one of them can be accepted in a given node, which triggers the appropriate transition: the first one in the node (buf, no_elem), the second in the node (buf, elem). Initially, the input set is empty.

Figure 4 shows a set of agent automata, which is equivalent to the previously described set of server automata. However, this form of automata highlights the resource sharing aspect of a distributed system, where traveling agents communicate by setting the server state values. This model conforms to the Remote Procedure Call paradigm [10]. In the figure, each agent travels between its home server and the shared buf server. Let us focus on producer Aprod. The agent name is omitted from message triples because it is common to all Aprod messages. The automaton starts from the initial node (message) of the Aprod automaton (Aprod, Sprod, doSth). The Sprod server initial state: (Sprod, neutral) is the input symbol of the transition from the node (Aprod, Sprod, doSth) so that the transition can be executed, leading to the next node (message) of the agent: (Aprod, buf, put) which transfers the agent to the buf server. In addition, the action generates a new state of the Prod server (Sprod, prod), which is the output symbol of the transition. If the current state of the buf server is (buf, no_elem), which means this symbol is present, the next Aprod transition can be fired. If not, the agent is waiting for such state of the buf server to occur. The next transition leads from (Aprod, buf, put) to (Aprod, Sprod, ok_put) and it changes the current state of buf from (buf, no_elem) to (buf, elem), which are the input and output symbol of the transition \((Aprod,buf,put)^{\underrightarrow {\left( {buf,no\_elem} \right)~/~\left( {buf,elem} \right)}}(Aprod,Sprod,ok_{put})\). Thus, in the agent automaton, we see the messages as the nodes, and the automata states as input and output symbols of the transitions. This is counterintuitive to a user who is used to other kinds of automata and takes some getting used to.

We see that server states are common to some agents; in the example, the state of the buf server is important to both agents: Aprod and Acons. Thus, we have a vector of the current server states, common to all agents, which contains input symbols for transitions and receives their output symbols. This is safe because the transitions are interleaved, so there can be no conflict between the transitions in distinct agent automata that set new states of the same server.

Automata in their nondeterministic form, in which the producer can perform several steps of doing something else between producing subsequent elements, are presented in Fig. 8, as sever automaton and agent automaton (nondeterministic transitions are shown as bold blue arrows).

6 Distributed Autonomous and Asynchronous Automata (DA3)

6.1 Server automata S-DA 3

The IMDS system in the server view can be represented as a set of communicating automata S-DA3 (distributed server automata), similar to MPA (point 3 in the enumeration in Sect. 2). The server states are the nodes (we do not use “state” to avoid ambiguity) of the corresponding automaton.

The initial state of the server is the initial node of the automaton. The server process actions are automaton. The automaton is Mealy-style [11], the transition labels in the automaton have the form extracted from actions; IMDS action λ = ((m, p), (m’, p’)) is converted to a transition from p to p’ with the label m/m’ (m is the input symbol firing the transition while m’ is the output symbol generated on the transition). Transitions in the server si automaton are the relation in Pi × M × M × Pi. Of course, m fulfils Ps(m) = si. Note that "traditional" distinction between transition relation Pi × M × Pi and output function (Pi × M × Pi) → M is not held because the set of actions may contain nondeterministic actions λ1 = ((m, p), (m’, p’)), λ2 = ((m, p), (m’’, p’)), m’ ≠ m’’. The automaton is equipped with an input set—a set of input symbols, corresponding to a set of messages pending at the server. Firing the transition (p, m/m’, p’) in the server s automaton retrieves the symbol m from the input set of this automaton and inserts the symbol m’ to the input set of the server s’ automaton, appointed by m’, Ms(m’) = s’. The initial input set consists of the initial agents’ messages that are directed to this server. The special agent-terminating action λ = ((m, p), (p’)) is converted to a transition that generates no output symbol. To distinguish between the two types of actions, we call the former form a progress action.

Formally, having the definition of S, A, V, R, P, M in IMDS (respectively: servers, agents, values, services, states, messages), we have the set Ψ (originally we used reflected S, but there was a problem with typesetting of this symbol in the article) of n distributed sever automata, Ψ = {ψi | i = 1, …, n}, where n is the number of servers in set S. Intuitively, Ψ is the set of automata in which each automaton ψi corresponds to the server si in the IMDS system. Therefore, S is the set of servers while Ψ is the set of server automata. In the definition below, exp(arg) is used for powerset 2arg. The ith distributed server automaton is ψi = (si, Pi, p0i, Fi, Xi, X0i) ∈ Ψ, where:

  • si ∈ S—the ith server,

  • Pithe set of nodes, which are the states of si,

  • p0i ∈ Pithe initial node,

  • Fi = { (p1, m/m’, p2) for λ = ((m, p1), (m’, p2)) or (p1, m/, p2) for λ = ((m, p1), (p2)) | p1, p2 ∈ Pi, ∃aj ∈ Am, m’ ∈ Mj}—the set of transitions (for ordinary actions and agent-terminating actions, respectively),

  • Xi ∈ exp({m|Ms(m) = si})the input set; Xi is the variable having a set value: each transition λ = ((m1, p1),(m2, p2)) removes its input message m1 from the input set of the server s1 appointed by the message m1, Ms(m1) = s1, and inserts the message m2 to the input set of the server s2 appointed by m2, Ms(m2) = s2 (except for the agent-terminating transition), accordingly to the rules for semantics described below,

  • X0i ∈ exp({m|Ms(m) = si, m ∈ M0})—the initial input set of the server si.

The following conditions must hold, but they are achieved by construction using the rules for semantics described below:

  • m1 ∈ Xim2 ∈ Xjm1 ∈ Mkm2 ∈ Ml: m1 ≠ m2k ≠ l: for each agent at most one message can exist in the global configuration,

  • ∀(p1, m/m’, p2) ∈ FiFj: m’ ∈ Fj: each output symbol (m’) is an input symbol of an automaton belonging to Ψ.

The server automata of the example buffer system in the server view are illustrated in Fig. 3. The initial nodes of the server automata have double borders. Server names are omitted in the node labels, because they are identical for all nodes of a given server automaton. The input sets of the automata Xbuf, XSprod and XScons are shown with their initial contents at the bottom of the picture; they change as the automata run.

The semantics of Ψ is defined as global vertex space ({TΨ}, \(T_{\Psi_{0}}\), nextΨ), where {TΨ} is a set of global vertices, \(T_{\Psi_{0}}\) is the initial global vertex, and next Ψ is the transition relation, defined as follows:

  • The global vertex of Ψ is TΨ = ((p1, X1), (p2, X2), …, (pn, Xn)) (current states and input sets of pending messages of all servers).

  • If in TΨ there exists an ψi in which (pi1, Xi), (pi1, m/m’, pi2) ∈ Fi, m ∈ Xi, Ms(m’) = sj then a possible next global vertex T’Ψ is:

    $$ T_{\psi }^{\prime } = \left( {\left( {p_{k}^{\prime } ,X_{k}^{\prime } } \right){\text{|}}\left\{ {\begin{array}{*{20}l} {p_{k}^{\prime } = p_{k} } \hfill & {{\text{for}}\;k \ne i} \hfill \\ {~p_{k}^{\prime } = p_{{i_{2} }} } \hfill & {{\text{for}}\;k = i} \hfill \\ \end{array} } \right\},\left\{ {\begin{array}{*{20}l} {X_{k}^{\prime } = X_{k} \backslash \left\{ m \right\} \cup \left\{ {m^{\prime } } \right\}~} \hfill & {{\text{for}}\;~i = k = j} \hfill \\ {X_{k}^{\prime } = X_{k} \backslash \left\{ m \right\}} \hfill & {{\text{for}}\;~k = i{\text{~}} \ne {\text{~}}j} \hfill \\ {X_{k}^{\prime } = X_{k} \cup \left\{ {m^{\prime } } \right\}} \hfill & {{\text{for}}\;~k = j \ne i} \hfill \\ {X_{k}^{\prime } = X_{k} } \hfill & {{\text{for}}\;~i \ne k \ne j} \hfill \\ \end{array} } \right\},k = 1, \ldots ,n} \right) $$
    (6.1)

(the automaton ψi changes its node from pi1 to pi2, all other automata preserve their nodes; the message m is extracted from the input set Xi of the automaton ψi, the continuation message m’ is inserted into the input set Xj of the automaton ψj appointed by m’, Ms(m’)= sj, all other input sets remain unchanged; the special case is for (i = k = j, first case), where the server si sends the message m’ to itself).

  • If in TΨ there exists an ψi in which (p1, Xi), (pi1, m/, pi2) ∈ Fi, m ∈ Xi (message m terminates the agent), then a possible next global vertex is:

    $$ T_{\psi }^{^{\prime}} = {(}\left( {p^{\prime}_{k} ,X_{k}^{^{\prime}} } \right){|}\left\{ {\begin{array}{*{20}c} {\begin{array}{*{20}c} {p^{\prime}_{k} = p_{k} } & {\begin{array}{*{20}l} {for} & k \\ \end{array} \ne i} \\ \end{array} } \\ {\begin{array}{*{20}l} { p^{\prime}_{k} = p_{{i_{2} }} } & {\begin{array}{*{20}l} {\begin{array}{*{20}l} {for} & k \\ \end{array} } & { = i} \\ \end{array} } \\ \end{array} } \\ \end{array} } \right\},\left\{ {\begin{array}{*{20}l} {X_{k}^{^{\prime}} = X_{k} \backslash \left\{ m \right\} \quad for \,\, k = i} \\ {X_{k}^{^{\prime}} = X_{k} \quad for \,\, k \ne i} \\ \end{array} } \right\},k = 1, \ldots ,n) $$
    (6.2)

(the automaton ψi changes its node from pi1 to pi2, all other automata preserve their nodes; the message m is extracted from the input set Xi of the automaton ψi, all other input sets remain unchanged).

  • The initial global vertex is TΨ0 = ((p01, X01), (p02, X02), …, (p0n, X0n)).

  • For a given global vertex TΨ, the transition relation nextTΨ(TΨ) is the set of pairs (TΨT’Ψ). The transition relation nextΨ = \({\bigcup }_{T_{\psi}}{nextT}({T})\).

    Comment: in the execution, if for TΨ there exist multiple possible next global vertices, one of them is chosen in nondeterministic way; however, it is not important in the definition of the global vertex space.

The global vertex space of Ψ cooperation is a counterpart to the LTS of IMDS system: global vertices contain states of all servers, input symbol (message) of a transition should be attributed to a source global vertex, while output symbol (message) to a target global vertex. The fragment of a global vertex space for the buffer system is presented in Fig. 9.

The nodes of server automata Ψ = {ψbuf, ψSprod, ψScons} (server states) shown in Fig. 3 are (note that the server state has the form (server, value)):

Pbuf = {(buf, no_elem), (buf, elem)},

PSprod = {(Sprodneutral), (Sprodprod)},

PScons = {(Sconsneutral), (Sconscons)}.

The sets of transitions are (the message has the form (agent, server, service), and the transition has the form (input node = (sv), input symbol = (asr)/output symbol = (a,s’, r’), output node = (sv’)), or \((s, v) ^{\underrightarrow {\left( {a,s,r} \right)/\left( {a,s{\text{'}},r{\text{'}}} \right)}} (s,v{\text{'}})\), where nodes are states and symbols are messages):

Fbuf = {((buf, no_elem), (Aprod, buf, put)/(Aprod, Sprod, ok_put), (buf, elem)),

((buf, elem), (Acons, buf, get)/(Acons, Scons, ok_get), (buf, no_elem))},

FSprod = {((Sprod, neutral), (Aprod, Sprod, doSth)/(Aprod, buf, put), (Sprod, prod)),

((Sprod, prod), (Aprod, Sprod, ok_put)/(Aprod, Sprod, doSth), (Sprod, neutral))}

FScons = {((Scons, neutral), (Acons, Scons, doSth)/(Acons, buf, get), (Scons, cons)),

((Scons, cons), (Acons, Scons, ok_get)/(Acons, Scons, doSth), (Scons, neutral))}

Every automaton is equipped with the input set of pending messages:

Xbuf ∈ exp({(Aprod, buf, put), (Acons, buf, get)}),

XSprod ∈ exp({(Aprod, Sprod, doSth), (Aprod, Sprod, ok_put)}),

XScons ∈ exp({(Acons, Scons, doSth), (Acons, Scons, ok_get)}).

Note that both messages in the base set of XSprod cannot be included in XSprod at the same time, as they belong to the same agent, likewise in the case of XScons.

The initial input sets of ψbuf, ψSprod and ψScons are:

X0buf = ∅,

X0Sprod = {(Aprod, Sprod, doSth)},

X0Scons = {(Acons, Scons, doSth)}.

S-DA3 are similar to Message Passing Automata. The difference is in the ordering of messages at the input of the automaton: in MPA, pending messages are ordered in the input queue (or input buffer) [43][44], while in S-DA3 any message form the input set may fire a transition (no ordering). If the input buffers in the MPA implementation are limited, a deadlock can occur due to all processes sending messages/data to the full buffers. This situation can occur when the size of the buffers is set to a too small value [53]. IMDS helps overcome this problem by posing an accurate size limit to the input set: it is simply the number of agents, or precisely: the number of agents visiting the server (occurring in its actions). For example, the repertoire of agents putting their messages into the input set of the buf automaton is {AprodSprod}, while in the case of the Sprod automaton, it is {Aprod}. Therefore, the sizes of the input sets in the implementation of the servers should be: 2 and 1, respectively.

6.2 Agent automata A-DA3

The IMDS system in the agent view can be shown as a set of communicating automata A-DA3 (agent distributed autonomous and asynchronous automata). We use the term node in these automata instead of state, because the states are attributed to servers in IMDS, and this could be misleading. The A-DA3 automata are similar to timed automata with variables used in Uppaal [5] (but here we only consider timeless systems):

  • The agent messages are the nodes of the automaton.

  • The agent’s initial message is the automaton initial node.

  • The actions of the agent process are the automaton transitions.

  • The automaton is Mealy-style [11]; the labels of the transitions in the automaton have the form extracted from actions; IMDS action λ = ((m, p), (m’, p’)) is converted to a transition (m, p/p’, m’) from the node m to the node m’ with the label p/p’ (p is the input symbol conditioning transition, while p’ is the output symbol generated on the transition; as before a transition relation in Mi × P × Mi and output function (Mi × P × Mi) → P are replaced by a single relation in Mi × P × P × Mi because of the possible nondeterminism in the set of actions: λ1 = ((m, p), (m’, p’)), λ2 = ((m, p), (m’, p’’)), p’ ≠ p’’.

  • In the case of the agent-terminating action λ = ((m,p), (p’)), the special terminating node ta in the automaton is added to be the target node of the transition, Ma(m) = a, and the transition is of the form (m, p/p’, ta). For node ta, there are no outgoing transitions. The action ((m, p), (p’)) in the agent a automaton, a = Ma(m), has the form \(m^{{\underrightarrow {p/p^{\text{'} }}}}t_{a}\) (see below), while in the server automaton Ψs, s = Ps(p), the transition is \(p^{{\underrightarrow {m/}}}p^{\text{'} }\).

  • The automata system is equipped with a global input vector—a vector of current input symbols for the transitions of the agent automata: servers’ states. The vector is indexed with the servers. Firing the transition (m, p/p’, m’) in the automaton replaces the symbol p in the vector with the new symbol p’ in the position of the server s = Ps(p). The initial global input vector consists of initial states of all automata.

Note that in server automata, the transitions are stretched between states, and the input/output symbols are agent messages. Everything is dual in the agent view of the system, i.e., the transitions lead from one message to another, while server states are input and output symbols. This is counterintuitive to a user who is used to other kinds of automata and takes some getting used to.

Formally, having the definition of PMSAVR from IMDS (respectively: states, messages, servers, agents, values, services), we have the set Ʉ (A upside down, rounded to distinguish it from the general quantifier ∀) of k distributed agent automata, Ʉ = {ɐi | i = 1, …, i}, where k is the number of agents in the set A, and n is the number of servers in the set S (used in the agent automaton definition below). Intuitively, Ʉ is the set of automata in which each automaton ɐi corresponds to the agent ai in the IMDS system. Therefore, A is the set of agents while Ʉ is the set of agent automata. The ith distributed agent automaton is ɐi  =  (aiMim0itɐiGiYY0) ∈ Ʉ, where:

  • aithe ith agent,

  • Mi ∪ {tɐi}—the set of nodes, which are the messages of the agent ai; tɐi is the destination node of the agent-terminating transitions if the agent ai terminates (tɐi appears as the target node of the agent-terminating transition),

  • m0i ∈ Mi—the initial node,

  • Gi = { (m1, p/p’, m2) for λ = ((m1, p), (m2, p’)) or (m1, p/p’, tɐi) for λ = ((m1, p), (p’)) | m1, m2 ∈ Mi, ∃sj ∈ Sp,p’ ∈ Pj}—the set of transitions,

  • Y = [p1, …, pn] | pj ∈ Pj—the global input vector (common for all automata ɐi in the system); Y is the vector of variables, Y/j is the jth position of Y, every variable Y/j has the range over the set of states of the server sj: the action λ1 = ((m, p), (m’, p’)) changes the value of the variable Y/j at the position of its input and output state server, Ps(p) = Ps(p’) = sj; accordingly to rules for semantics below,

  • Y0 = [p01,…, p0n] | pj ∈ Pj, pj ∈ P0—the initial global input vector, consisting of initial states of all servers.

The semantics of Ʉ is defined as global vertex space ({TɄ}, nextɄ), where {TɄ} is a set of global vertices, is initial global vertex, and nextɄ is a transition relation, defined as follows:

  • The global vertex of Ʉ is TɄ = {m1, …, mk, Y}, mi ∈ Mi ∪ {tɐi}. If in TɄ there exists mi, for which there exists (mi, p/p’, mj) ∈ Gi, p, p’ ∈ Px (message mi causes a change of a state from p to p’ in a server sx, Ms(mi) = sx, and a message mj to a server sy, Ms(mj) = sy is issued) then a possible next global vertex is:

    (6.3)

(the automaton ɐi i changes its node to mj, all other automata preserve their nodes; the state p in input vector Y, in the position appointed by p and p’, sx=Ps(p)=Ps(p’), all other elements of the vector Y remain unchanged).

  • If in { TɄ} there exists mi, for which there exists (mi, p/p’, tɐi) ∈ Gi, p, p’ ∈ Px (message mi is the last message in the run of agent ai, then the agent terminates, the sever sx appointed by the message mi, Ms(mi) = sx, changes its state from p to p’) then a possible next global vertex is:

    (6.4)

(the automaton ɐi changes its node to tɐi all other automata preserve their nodes; the state p in Y is replaced by p’ as above).

  • The initial global node TɄ0 = {m01, …, m0n, Y0}. For a given global vertex TɄ, transition relation nextTɄ(TɄ) is a set of pairs (TɄT’Ʉ).

  • The transition relation nextɄ =UTɄnextTɄ(TɄ).

    Comment: in the execution, if there are multiple next vertices possible, one of them is chosen in nondeterministic way; however, it is not important in the definition of the global vertex space.

The distributed agent automata for the buffer system Ʉ = {ɐAprod, ɐAcons} are illustrated in Fig. 4. The initial nodes of the automata, being the initial messages of the agents, have double borders. Agent identifiers are omitted in message labels (nodes of the automata), because they are identical for all messages in the given agent.

The nodes of sever automata (agent messages) shown in Fig. 4 are (note that the message has the form (agent, server, service)):

MAprod = {(Aprod, buf, put), (Aprod, Sprod, doSth), (Aprod, Sprod, ok_put)},

MAcons = {(Acons, buf, get), (Acons, Scons, doSth), (Acons, Scons, ok_get)}.

As the agents do not terminate in the buffer system, there are not terminating nodes. Note that the server state has the form (server, value), and the transition has the form (input node = (a,sr), input symbol = (s, v)/output symbol = (sv’), output node = (as’, r’)), or \((a,s,r) ^{\underrightarrow {\left( {s,v} \right)/\left( {s,v{\text{'}}} \right)}} (a,s{\text{'}}, r{\text{'}})\), where nodes are messages and symbols are states. The same action (((asr), (sv)), ((as’, r’), (sv’))) as the transition in the server automaton ψs has the form \((s, v) ^{\underrightarrow {\left( {a,s,r} \right)/\left( {a,s{\text{'}},r{\text{'}}} \right)}} (s,v{\text{'}})\). The sets of transitions ɐAprod and ɐAcons are:

MAprod = {((Aprod, Sprod, doSth), (Sprod, neutral)/(Sprod, prod), (Aprod, buf, put)),

((Aprod, buf, put), (buf, no_elem)/(buf, elem), (Aprod, Sprod, ok_put)),

((Aprod, Sprod, ok_put), (Sprod, prod)/(Sprod, neutral), (Aprod, Sprod,doSth))}

MAcons = {((Acons, Scons, doSth), (Scons, neutral)/(Scons, cons), (Acons, buf, get)),

((Acons, buf, get), (buf, elem)/(buf, no_elem), (Acons, Scons, ok_get)),

((Acons, Scons, ok_get), (Scons, cons)/(Scons, neutral), (Acons, Scons, doSth))}

Below is the global input vector of current states of servers:

Y = [(Sprodvalue ∈ {neutral, prod}), (bufvalue ∈ {no_elem, elem}),

(Sconsvalue ∈ {neutral, cons})].

The initial content of the global input vector is:

Y0 = [(Sprod, neutral), (buf, no_elem), (Scons, neutral)].

The global vertex space of Ʉ collaboration is the IMDS LTS equivalent: global vertices contain the messages of all non-terminated agents, and the states of all servers in the global input vector. The fragment of the global vertex space for the buffer system is presented in Fig. 10.

7 Practical example of DA3: Automatic Vehicle Guidance System

The buffer example is tiny, just to present the main ideas. Now we introduce the automatic vehicle guidance system (AVGS) from [59]. The system consists of road markers and warehouse lots, presented in Fig. 11, communicating with each other to guide autonomous moving platforms (AMPs) from LotE1 to LotE2 or vice versa. The two AMPs might collide in section MarkerM, but there is the chance that one could wait temporarily in LotM, until the other has passed. There are six servers representing the Lots and Markers controllers, with a protocol for requesting and granting road segments managed by the controllers.

The server view describes the system from the point of view of communicating controllers. The code of AVGS in IMDS source notation is given below. Only the MarkerM controller actions are shown, as other controllers are quite simple: request and grant if not occupied.

figure g

The designer defines server (or agent) types rather than individual instances, choosing a graphic or text form. Having the types defined, individual server/agent variables can be declared as type instances. In this example, some servers and agents are grouped into vectors (lines 59, 60). Moreover, some formal parameters are in the form of vectors (2, 19, …). Services and state values can also be vectors (4, 23). For a compact definition, repeaters precede the actions (10–17, …). The indices of agents, states and services indicate individual instances (26–29). The markers E and M names are shortened to mE and mM. The server type lotE is shown as S-DA3 automaton in Fig. 12. Note the transition from res to occ (the label is surrounded by a blue ellipse)—it is the agent-terminating transition when AMP has reached its destination. There is no output message in this case.

The server view of the system is automatically converted to the agent view by Dedan. In the agent view, actions are grouped by agent. During conversion, the type AMP is split into two separate types and renamed to separate AMP and AMP__1, due to different action sequences on controllers. The agent view shows the system from the point of view of the AMP vehicles (listing below). Figure 14 presents a fragment of the AMP agent type automaton. The view of the agent automaton in Dedan, which is the visualization of the AMP[1] agent specification in IMDS, is presented in Fig. 15.

This image has been obtained automatically: from the graphical specification of server types in the graphical design tool, through the binding of specific server and agent instances in the IMDS source code, automatic conversion from server view to agent view, to display the automata in the A-DA3 graphical simulator. The arrangement of the nodes in the plane results from an iterative algorithm that moves nodes in an invisible mesh if any transition intersects the node. We are still working on this algorithm. The user can rearrange the nodes to get a clearer view.

A fragment of the AMP automaton is visible; the other is named AMP__1. The program tries to find agents that have common action sets and combine them into vectors, in this case it would be AMP[2], but in this case, it fails because the agents pass through the servers in a different index order: the instance AMP[1] ascending and the instance AMP[2] descending.

figure h

8 Using DA3 in the Dedan environment

Editing server automata or agent automata, and simulation over two versions of automata are four different tools in the Dedan integrated verification framework.

We describe a typical procedure during verification: the user defines the system graphically, usually in S-DA3, then verifies in IMDS: detects deadlocks or missing termination, or confirms the inevitable termination of the system, then Dedan generates a counterexample (in case of confirmed termination called a witness). When the analysis of the counterexample is not easy, because it is either long or difficult to analyze due to a large number of servers/agents, the designer proceeds to simulate the counterexample. Simulation is possible in a configuration graph (LTS, see Fig. 16); however, the graph is usually huge, and the user sees a configuration consisting of the states of all servers and all agents’ messages, which often obscures the matter. Then it is possible to proceed to the distributed automata simulation, where the designer can place panels of important automata next to each other and observe their progress step by step. The S-DA3 view is frequently selected, for example, when verifying IoT sensor systems and data processing nodes, but the A-DA3 view is also very useful, for example, when tracking the positions of moving parts in Karlsruhe Production Cell [58], vehicles running in the AVGS system [59] or special agents monitoring satellite equipment [61]. The latter move between ground services and individual satellite modules, checking the correctness of the sequences of actions.

The above design, verification and simulation scenarios are typical for students verifying their solutions to synchronization tasks, and implementing projects of autonomous vehicles cooperation or collaborating IoT controllers. The Dedan system was used by over 300 students, most often defining distributed systems textually, but in many cases also graphically in DA3. Usually, at the design stage, the simulation function is used, in which the designer selects one automaton from among those containing the enabled actions, and makes a nondeterministic choice if more than one action is enabled. Typical student solutions consist of 8–16 servers, 4–6 agents, and the total number of states is typically less than 100 to about 400 actions. The number of states in the server type varies from 2 (semaphores) to 15, as does the number of server services. The number of agent messages (derived from the number of agents, the number of servers visited, and the number of their services) varies considerably from case to case, reaching up to hundreds. Thus, tracking agents is not easy, but much easier than analyzing an LTS or simulating a counterexample in the LTS over configurations. Compare the LTS fragment of AVGS in Fig. 16 with the server automata in Fig. 13 and agent automata in Fig. 15.

After designing the system, verification takes place, the important feature of which is automatism, because Dedan has built-in general formulas that check total or partial deadlock and termination regardless of the structure of the specific system. This is important because the use of model checking and temporal logics is not easy [62] (especially for 2nd year students, but also many engineers avoid formal methods [7]). In about 10% of cases, the systems have errors, and the counterexample has from a few to several dozen steps. In the first case, these are most often errors in the structure of the solution, while the longer ones concern faulty synchronization. Then, the graphical simulation of the counterexample is most often used, in which the subsequent steps are determined by its course until the error or the desired situation occurs.

The basic form of specification used in Dedan is IMDS, because it enables automatic conversion between the server view and the agent view of a system, and conversion to other formalisms: Petri net for static analysis and finding deadlocks using siphons [63], Uppaal input for timed verification [64], etc. However, the specification in the form of a relation between pairs λ = ((message, state), (message’, state’)) is exotic for the users. Therefore, two alternative input forms are provided: imperative-style language Rybu (not covered in this article) and DA3 automata.

In the graphic design, the user creates nodes and transitions by clicking on a window in desired coordinates. It should be emphasized that the automata type is being defined, and instances of this type can be declared in the system. New nodes are added by right-clicking on the surface (Fig. 17), a new node window appears as in Fig. 18 on the left (in this case, the state node, because it is S-DA3). A transition is placed in the graph by clicking first on its source node, then on its target node, and then the label of this transition is defined in the right-hand window in Fig. 18. In this case, AMP[1].markerE.tryM is the transition input symbol and AMP[1].lotE.try[2] is the output symbol. The transition leads from markerE.free to markerE.resM state. The names of other servers/agents that appear in these windows are formal parameters of automata types. Typical editing operations are available, like moving nodes on the surface shown in Fig. 19.

The specified system is verified by searching for deadlocks or checking distributed termination (Fig. 20 on the left). The verification confirms desired features or presents a counterexample leading to an incorrect or desired configuration. In such a case, the designer analyzes the system under test, observing the counterexample as a sequence diagram in the server view (Fig. 20 center) or in agent view (Fig. 20 on the right) and inspecting the source code, graphical specification, and LTS fragments.

A distributed system can be simulated over the global space of configurations (LTS), but it can also be simulated in terms of DA3, in the window illustrated in Fig. 6. All automata in the system are displayed, with input sets shown under the automata identifiers. The current states of the automata are blue, and all others are red.

The user can select the automaton (Sprod in the example, the selected automaton has a white background and blue name), then on the left side, a list of transitions outgoing from the current state of the selected automaton is displayed (enabled are highlighted; it is only one transition leading from neutral to prod in this case and it is enabled, with accepting of doSth message and issuing of the put message to buf). If the user clicks an enabled transition, it is “executed,” and the destination automaton of the message becomes current (in this case: buf), as shown in Fig. 21.

Figure 22 shows such a situation after selecting Scons and executing a transition in it. This sends a message to the buf automaton: now two messages are pending at this automaton. Of course, only one of them can be accepted, namely, the one invoking the action {Aprod.buf.put, buf.no_elem}—> {Aprod.Sprod.ok_put, buf.elem}.

The deadlock situation is easy to identify. This is clearly shown on the sequence diagram (see Fig. 20 on the right). During the simulation, the deadlock is presented in Fig. 23: this is a version of the buffer system, in which users switch randomly between producer and consumer roles. For example, a deadlock occurs when all users choose to read from an empty buffer. This situation is shown in the figure: all messages are pending at the input of buf, but no action is enabled. Of course, it is a total deadlock. In the case of a partial deadlock, some automata work, so the deadlock should be observed in the comparison of the automata and sequence diagram. In agent automata, the total deadlock is observed when every automaton has its own message, but neither automaton is enabled. Partial deadlock affects a subset of automata.

Figure 24 shows several examples of student exercises observed as S-DA3 and A-DA3.

9 Conclusions and further work

The Dedan program supports the engineer in the specification of distributed systems and their verification for deadlocks freeness and distributed termination. If a deadlock occurs, or a termination is checked, a sequence diagram of messages and states is generated, leading from the initial configuration to the deadlock/termination. If the deadlock/termination is not total, the involved servers/agents are shown. Distributed automata (in S-DA3 or in A-DA3 version) allow for the design of the system in graphical form, and to simulate system components and their interaction instead of simulating on the full configuration graph (LTS). Figures 6, 21, 22 show the simulation of the buffer system in Dedan. Also, a counterexample can be observed as a sequence of transitions in the cooperating DA3 automata. Engineers are familiar with the concept of automata (S-DA3 are similar to Message Passing Automata [43][44] and asynchronous statecharts [14], and A-DA3 are like Timed Automata with global variables of Uppaal [5]), which can be naturally used in distributed systems design. For example, some models of transport cases were modeled. The server view is equivalent to the exchange of messages between road segment controllers that automatically lead the vehicles through the road segments [59]. In the agent view, it is the observation of vehicles moving on the road, with interactions to other vehicles occupying some segments of the road, via their controllers. Possible deadlocks in communication can be easily identified, and the verifier shows the behavior of vehicles leading to a deadlock as transitions of DA3 automata. Table 1 compares the features of a distributed system, observed in equivalent formalisms: IMDS and DA3.

Fig. 3
figure 3

Agent automata for the buffer system

Fig. 4
figure 4

A fragment of the LTS for the buffer system

Fig. 5
figure 5

Three types of automata, showing different scheduling semantics for events: a PDA—most recently received event presented to the automaton: transition state 2 → state 1 can be enabled if the current state is state 2, b MDA—least recently received event presented to the automaton: transition state 1 → state 2 can be enabled if the current state is state 1, and c DA3 (also asynchronous statecharts with input dispatchers [14])—all events are presented simultaneously: some transition is enabled if any of the states is current

Fig. 6
figure 6

Dedan S-DA3 view of server automata shown in Fig. 2

Fig. 7
figure 7

Dedan A-DA3 view of agent automata shown in Fig. 3

Fig. 8
figure 8

Nondeterministic S-DA3 and A-DA3. Nondeterministic transitions are bold blue arrows. Note that these automata never coexist in the same view; they are parts of two alternative views of the system

Fig. 9
figure 9

The fragment of the global vertex space of server automata; the first row of a vertex contains the states of the servers, the second row the input sets

Fig. 10
figure 10

The fragment of the global graph of agent automata; the first row of a vertex contains the agent messages, the second row the global input vector

Fig. 11
figure 11

The structure of road segment controllers. The AMPs are in their start positions

Fig. 12
figure 12

source code, line 59). A blue ellipse surrounds the agent-terminating transition label. The window of the Dedan program showing the automaton of the lotE[1] instance is shown on the right

The server automaton of lotE server type. There are two instances of this type, forming a 2-element vector lotE[2] (see the

Fig. 13
figure 13

The AVGS shown as S-DA3. The chosen automaton is LotE[1] (light background and blue name), list of all transitions outgoing from the current state occ is on the left, with enabled transition highlighted (color figure online)

Fig. 14
figure 14

The agent automaton of AMP agent type

Fig. 15
figure 15

The AVGS shown as A-DA3. Server states—floating panel showing global input vector (of server states)

Fig. 16
figure 16

Simulation in LTS. The current configuration is green, with states and messages shown without server and agent ids to save the space. The actions leading to its successors are red arrows, and input items of the actions are on the pink background. On the left, the output items of every action are displayed (color figure online)

Fig. 17
figure 17

The window for defining the position of nodes on the plane (S-DA3 automaton type)

Fig. 18
figure 18

Defining the state—the node in S-DA3 and action, i.e., the transition in both S-DA3 and A-DA3

Fig. 19
figure 19

Moving nodes on a plane: click a node and then click at its new location. It is the same S-DA3 automaton type (lotE) as before, only with different node positions

Fig. 20
figure 20

The verification window (left), the sequence diagram of found communication deadlock in server buf (center) and the same situation seen in resource deadlock in the agent view of user agents (right)

Fig. 21
figure 21

Simulation over S-DA3 after executing the transition in the automaton Sprod, highlighted in Fig. 3: {Aprod.Sprod.doSth, Sprod.neutral}—> {Aprod.buf.put, Sprod.prod}. The target automaton of the action is buf, and it becomes the current one

Fig. 22
figure 22

Simulation over S-DA3 after manually changing the current automaton to Scons and executing the transition in the automaton Scons. Now the automaton buf is current, and two messages pending at this automaton are displayed: Aprod.put and Acons.get (automaton name in the messages is omitted, because in both cases it is buf)

Fig. 23
figure 23

There is no move: there are two messages in the buf server, both do not match the state of this node, and there is no other enabled agent in the system. If such an agent existed, it could potentially send a message to the buf server that would match the elem0 state and cause an action to change that state. It is a graphical interpretation of the deadlock in the system

Fig. 24
figure 24

Several examples of student exercises shown in S-DA3 (left) and A-DA3 (right) views

Table 1 Verification facilities in the three equivalent formalisms

Several years of Dedan development showed possible improvements in using DA3 in both forms:

  • Translation of graphic BPMN diagrams to IMDS allows for verification of them against partial deadlocks and checking partial termination (which is rare between verifiers). Especially, simulation of counterexamples in DA3 with simultaneous observation of the current state in source BPMN is winning. ICS students carry out this project, but its scope exceeds this article. This successful project showed that specification in graphic domain specific languages (DSL) could be useful, when the designer can compare the counterexample in the form of sequence diagram with simulation in DA3 and with the current state shown in source specification. Currently, DA3 specifications for autonomous vehicles and web-service composition, which are being developed by our students, are to be considered as kinds of DSL for these domains. In our laboratory, we are working on DSL for the digital twin specification for railway signaling. The important feature of these projects is a simultaneous observation of sequence diagram counterexample, DA3 simulation, and the state of source specification.

  • In the simulation of DA3, some new features are planned, like starting the simulation from a configuration pointed in the sequence diagram, backtracking the simulation, and diverging from counterexample simulation to free choice of enabled transitions.

  • During the simulation, we plan to show in separate windows a few kinds of counterexample tracking simultaneously: DA3 concurrently in the two forms, sequence diagram and configuration graph (LTS)—Figs. 16, 20, 21, 23, respectively. A move (or backward move) in one of the windows would cause similar moves in the other windows. In the case of a DSL specification mentioned above, simultaneously, the current state in the source graphical specification can be shown.

In addition, some new features in the development of IMDS and the Dedan program are planned; some of them are subject of student projects:

  • Non-exhaustive timeless and timed verification, using 2-vagabonds algorithm and various types of heuristics [65]. This could allow for verification of huge systems, whose LTS cannot be represented in the computer memory.

  • Probabilistic DA3 automata to identify deadlock probability if the alternative actions in system processes are equipped with probabilities.

  • Language-based input—elaboration of two languages for distributed systems specification: one for the server view (exploiting locality in servers and message passing) and the other for the agent view (exploiting traveling of agents and resource sharing in a distributed environment); the initial version of the declarative language-based preprocessor Rybu for the server view of verified systems is developed by the students of ICS, WUT (Institute of Computer Science, Warsaw University of Technology) [9]. Rybu is not covered in this paper, as it is based on textual representation.

  • Agents’ own actions—equipping the agents with their own sets of actions, carried in their “backpacks,” parameterizing their behavior; this will allow modeling of mobile agents (agents carrying their own actions model code mobility) and to avoid many server types in specification, differing slightly.

The Dedan environment is successfully used in the student laboratory in ICS, WUT. Students verify their solutions to synchronization problems. The graphic definition of the component automata and simulation over distributed automata supports the verification procedure.