| Deterministic Automata |
| ====================== |
| |
| Formally, a deterministic automaton, denoted by G, is defined as a quintuple: |
| |
| *G* = { *X*, *E*, *f*, x\ :subscript:`0`, X\ :subscript:`m` } |
| |
| where: |
| |
| - *X* is the set of states; |
| - *E* is the finite set of events; |
| - x\ :subscript:`0` is the initial state; |
| - X\ :subscript:`m` (subset of *X*) is the set of marked (or final) states. |
| - *f* : *X* x *E* -> *X* $ is the transition function. It defines the state |
| transition in the occurrence of an event from *E* in the state *X*. In the |
| special case of deterministic automata, the occurrence of the event in *E* |
| in a state in *X* has a deterministic next state from *X*. |
| |
| For example, a given automaton named 'wip' (wakeup in preemptive) can |
| be defined as: |
| |
| - *X* = { ``preemptive``, ``non_preemptive``} |
| - *E* = { ``preempt_enable``, ``preempt_disable``, ``sched_waking``} |
| - x\ :subscript:`0` = ``preemptive`` |
| - X\ :subscript:`m` = {``preemptive``} |
| - *f* = |
| - *f*\ (``preemptive``, ``preempt_disable``) = ``non_preemptive`` |
| - *f*\ (``non_preemptive``, ``sched_waking``) = ``non_preemptive`` |
| - *f*\ (``non_preemptive``, ``preempt_enable``) = ``preemptive`` |
| |
| One of the benefits of this formal definition is that it can be presented |
| in multiple formats. For example, using a *graphical representation*, using |
| vertices (nodes) and edges, which is very intuitive for *operating system* |
| practitioners, without any loss. |
| |
| The previous 'wip' automaton can also be represented as:: |
| |
| preempt_enable |
| +---------------------------------+ |
| v | |
| #============# preempt_disable +------------------+ |
| --> H preemptive H -----------------> | non_preemptive | |
| #============# +------------------+ |
| ^ | |
| | sched_waking | |
| +--------------+ |
| |
| Deterministic Automaton in C |
| ---------------------------- |
| |
| In the paper "Efficient formal verification for the Linux kernel", |
| the authors present a simple way to represent an automaton in C that can |
| be used as regular code in the Linux kernel. |
| |
| For example, the 'wip' automata can be presented as (augmented with comments):: |
| |
| /* enum representation of X (set of states) to be used as index */ |
| enum states { |
| preemptive = 0, |
| non_preemptive, |
| state_max |
| }; |
| |
| #define INVALID_STATE state_max |
| |
| /* enum representation of E (set of events) to be used as index */ |
| enum events { |
| preempt_disable = 0, |
| preempt_enable, |
| sched_waking, |
| event_max |
| }; |
| |
| struct automaton { |
| char *state_names[state_max]; // X: the set of states |
| char *event_names[event_max]; // E: the finite set of events |
| unsigned char function[state_max][event_max]; // f: transition function |
| unsigned char initial_state; // x_0: the initial state |
| bool final_states[state_max]; // X_m: the set of marked states |
| }; |
| |
| struct automaton aut = { |
| .state_names = { |
| "preemptive", |
| "non_preemptive" |
| }, |
| .event_names = { |
| "preempt_disable", |
| "preempt_enable", |
| "sched_waking" |
| }, |
| .function = { |
| { non_preemptive, INVALID_STATE, INVALID_STATE }, |
| { INVALID_STATE, preemptive, non_preemptive }, |
| }, |
| .initial_state = preemptive, |
| .final_states = { 1, 0 }, |
| }; |
| |
| The *transition function* is represented as a matrix of states (lines) and |
| events (columns), and so the function *f* : *X* x *E* -> *X* can be solved |
| in O(1). For example:: |
| |
| next_state = automaton_wip.function[curr_state][event]; |
| |
| Graphviz .dot format |
| -------------------- |
| |
| The Graphviz open-source tool can produce the graphical representation |
| of an automaton using the (textual) DOT language as the source code. |
| The DOT format is widely used and can be converted to many other formats. |
| |
| For example, this is the 'wip' model in DOT:: |
| |
| digraph state_automaton { |
| {node [shape = circle] "non_preemptive"}; |
| {node [shape = plaintext, style=invis, label=""] "__init_preemptive"}; |
| {node [shape = doublecircle] "preemptive"}; |
| {node [shape = circle] "preemptive"}; |
| "__init_preemptive" -> "preemptive"; |
| "non_preemptive" [label = "non_preemptive"]; |
| "non_preemptive" -> "non_preemptive" [ label = "sched_waking" ]; |
| "non_preemptive" -> "preemptive" [ label = "preempt_enable" ]; |
| "preemptive" [label = "preemptive"]; |
| "preemptive" -> "non_preemptive" [ label = "preempt_disable" ]; |
| { rank = min ; |
| "__init_preemptive"; |
| "preemptive"; |
| } |
| } |
| |
| This DOT format can be transformed into a bitmap or vectorial image |
| using the dot utility, or into an ASCII art using graph-easy. For |
| instance:: |
| |
| $ dot -Tsvg -o wip.svg wip.dot |
| $ graph-easy wip.dot > wip.txt |
| |
| dot2c |
| ----- |
| |
| dot2c is a utility that can parse a .dot file containing an automaton as |
| in the example above and automatically convert it to the C representation |
| presented in [3]. |
| |
| For example, having the previous 'wip' model into a file named 'wip.dot', |
| the following command will transform the .dot file into the C |
| representation (previously shown) in the 'wip.h' file:: |
| |
| $ dot2c wip.dot > wip.h |
| |
| The 'wip.h' content is the code sample in section 'Deterministic Automaton |
| in C'. |
| |
| Remarks |
| ------- |
| |
| The automata formalism allows modeling discrete event systems (DES) in |
| multiple formats, suitable for different applications/users. |
| |
| For example, the formal description using set theory is better suitable |
| for automata operations, while the graphical format for human interpretation; |
| and computer languages for machine execution. |
| |
| References |
| ---------- |
| |
| Many textbooks cover automata formalism. For a brief introduction see:: |
| |
| O'Regan, Gerard. Concise guide to software engineering. Springer, |
| Cham, 2017. |
| |
| For a detailed description, including operations, and application on Discrete |
| Event Systems (DES), see:: |
| |
| Cassandras, Christos G., and Stephane Lafortune, eds. Introduction to discrete |
| event systems. Boston, MA: Springer US, 2008. |
| |
| For the C representation in kernel, see:: |
| |
| De Oliveira, Daniel Bristot; Cucinotta, Tommaso; De Oliveira, Romulo |
| Silva. Efficient formal verification for the Linux kernel. In: |
| International Conference on Software Engineering and Formal Methods. |
| Springer, Cham, 2019. p. 315-332. |