I’m currently teaching a Masters level Automata Theory course, and I want to make it a bit more hands on (since we are virtual...). While looking for people using Mathematica, I was surprised that I could not find much code out there. I did find this post on this community
Simulating Finite Automata (and making it look nice)
https://community.wolfram.com/groups/-/m/t/1611589
which I enjoyed, but I wanted to make something a bit more closer to theory, and with a “cleaner” code.
Simulating Finite Automata (and making it look nice)
https://community.wolfram.com/groups/-/m/t/1611589
which I enjoyed, but I wanted to make something a bit more closer to theory, and with a “cleaner” code.
Definitions
Definitions
A finite state machine is an abstract mathematical structure. It is a 5-tuple , where,
(Q,Σ,δ,,F)
q
0
◼
Q
◼
Σ
◼
δ:QΣQ
◼
A start state ∈Q
q
0
◼
A set of final states
F⊆Q
For practical purposes, in Mathematica , and we will define a transition function as Associations[{q,x}q’,...], where q, q’ are states and x is a character (so Head[x] = String)
Q{0,1,2,…}
"Running" a finite state machine
"Running" a finite state machine
Consider the following state transition definition:
In[]:=
δ=Association[{0,"1"}1,{0,"0"}0,{1,"0"}0,{1,"1"}2];
It is a 2 state machine, that takes characters “0” and “1”. To “apply” this automata, we define the following function in Mathematica:
In[]:=
ApplyAutomata[δ_,q0_,string_]:=FoldList[(δ[{#1,#2}])/._Missing0&,q0,Characters[string]]
Notice how we apply the function FoldList, to recursively “move” form state to state, depending on the current string input. we capture undefined transitions, identifying Missing functions that are returned if an association does not contain a particular Key. Applying to the previous definitions, with 0 as the starting state,
δ
ApplyAutomata[δ,0,"01110101"]
Out[]=
{0,0,1,2,0,0,1,0,1}
We are interested to know if a string is valid. If in our previous example 2 is a final state “01110101” does not finish in that state so that string is NOT accepted by this automata. We can build a function for this,
In[]:=
IsValidQ[δ_,q0_,string_,qf_]:=Fold[(δ[{#1,#2}])/._Missing0&,q0,Characters[string]]qf;IsValidQ[δ_,q0_,string_,qf_List]:=MemberQ[qf,Fold[(δ[{#1,#2}])/._Missing0&,q0,Characters[string]]];
It is very similar to ApplyAutomata[], but we want to check if the final state reached belongs to the set of final states. So,
IsValidQ[δ,0,"01110101",2]
Out[]=
False
A valid one,
IsValidQ[δ,0,"011",2]
Out[]=
True
Building a graph representation
Building a graph representation
Creating a graph function based on the state transitions , requires converting rules to Directededges[] and to create the corresponding labels for arcs.
δ
In[]:=
ToEdges[δ_]:=MapThread[DirectedEdge,{First/@Keys[δ],Values[δ]}];ToVertexLabels[s_]:=Table[Rule[i-1,Placed[i-1,Center]],{i,1,s}];ToEdgeLabels[δ_]:=MapThread[Rule,{ToEdges[δ],Last/@Keys[δ]}];
So we don’t draw double arcs, we have also to unify,
In[]:=
UnifyLabels[labels_]:=If[Length[#]>1,First[Keys[#]](Values[#]&/@#),First[#]]&/@GatherBy[labels,First];
In[]:=
UnifyEdges[edges_]:=First/@Gather[edges];
Now we define a graph function,
ShowGraph[δ_,s_,q0_,q_List]:=Graph[UnifyEdges[ToEdges[δ]],VertexSizeLarge,VertexLabelsToVertexLabels[s],EdgeLabelsUnifyLabels[ToEdgeLabels[δ]],VertexStyleJoin[{0White},Map[(#Red)&,q]]]
As you can see the function ShowGraph[δ_,s_,q0_,q_List], takes the transition function , since we are labeling states from 0 onward, we need to define how many states the machine has, the initial state, and the set of final states. Initial states nodes are filled white, and final states red. With the previous example,
δ
s
ShowGraph[δ,3,0,{2}]
Out[]=
A nice example taken from Sipser Book (See references)
In[]:=
δ=Association[{0,"a"}1,{0,"b"}3,{1,"a"}1,{1,"b"}2,{2,"b"}2,{2,"a"}1,{3,"b"}3,{3,"a"}4,{4,"b"}3,{4,"a"}4];
This state machine accepts strings that start and finish with “a”, or start and finish with “b”. So for example
IsValidQ[δ,0,"bb",{1,3}]
Out[]=
True
Is a valid string, but,
IsValidQ[δ,0,"bba",{1,3}]
Out[]=
False
Not
The corresponding graph,
ShowGraph[δ,5,0,{1,3}]
Out[]=
References
References
◼
Michael Sipser, Introduction to theTheory of Computation. PWS Publishing Company, 2006.