# We disable autosave for technical reasons.
# Replace 0 by 120 in next line to restore default.
%autosave 0
Autosave disabled
import awalipy # If import fails, check that
# Python version used as Jupyter
# kernel matches the one
# Awalipy was compiled with.
[Warning] The python module awalipy relies on compilation executed "on-the-fly" depending on the context (type of weights, of labels, etc.). As a result, the very first call to a given function in a given context may take up to one minute.
(The above warning is displayed every time awalipy is imported.)
Alphabets we use are Python str
char
of the str
is a letter the alphabet"abc"
and "bac"
represent the same alphabet)alph1 = "abc" # represents {a,b,c}
alph2 = "01" # represents {0,1}
An automaton is built from an alphabet
A = awalipy.Automaton(alph1)
# or directly `awalipy.Automaton("abc")`
A
is an automaton with no states and no transitions over the alphabet {a,b,c}
Adding states
By default the displayed name of the state is given by its index: the first state is named "s0"
, the second "s1"
, etc.
stt_0 = A.add_state()
stt_1 = A.add_state()
Adding transitions
tr_0 = A.set_transition(stt_0,stt_1,'a')
tr_1 = A.set_transition(stt_1,stt_0,'b')
tr_2 = A.set_transition(stt_0,stt_0,'b')
print (stt_0)
print (tr_2)
0 2
Making states initial or final
A.set_initial(stt_0)
A.set_final(stt_1)
Displaying an automaton graphically, using dot for state placement.
(Works well for small automata only.)
A.display()
Displayin an automaton in text format.
A
Automaton (static context: lal_char_b) Weightset: B Alphabet: abc Epsilon-transitions: Disallowed - States:{ 0(i) 1(f) } - Transitions:{ 0-a->1 1-b->0 0-b->0 }
NB: the mention (i)
following a state means that the state is initial. Similarly, (f)
means final and (i,f)
means initial and final.
By default, automata do not allow epsilon transitions.
Moreover, automata with/without epsilon transitions are not represented by the same data structure. Allowing epsilon transition hence provokes a complete copy of the automaton.
Ae = A.allow_eps_transition()
Ae.display()
Adding an epsilon transition using the specific function.
tr_3 = Ae.set_eps_transition(stt_1,stt_0)
Ae.display()
Epsilon transition is represented by the string "\e"
.
(NB: the '\'
must be escaped by a preceding '\'
)
Adding an epsilon-transition using the general function.
Ae.set_transition(stt_1,stt_1,"\\e")
6
For convenience we also allow ""
as input to mean epsilon.
Ae.set_transition(stt_0,stt_0,"")
7
Resulting automaton:
Ae.display()
Let us consider the automaton A
.
A.display()
First we add a bunch of states and transitions
stt_2 = A.add_state()
tr_3 = A.set_transition(stt_1,stt_1,'a')
# Not recording ids of transitions any further
A.set_transition(stt_2,stt_2,'b')
A.set_transition(stt_0,stt_2,'a')
A.set_transition(stt_2,stt_0,'b')
A.set_transition(stt_1,stt_2,'b')
A.set_transition(stt_1,stt_2,'a')
A.set_transition(stt_2,stt_1,'a')
A.display()
Deleting a transition by id
A.del_transition(tr_3) # tr_3 is the transition: s2 --a--> s2
A.display()
Deleting a transition by triplet (origin, destination, label)
A.del_transition(stt_2,stt_2,'b')
A.display()
Deleting all transitions from a state to another (order matters).
A.del_transition(stt_1,stt_2)
A.display()
Deleting a state (and all its outgoing and incoming transitions)
A.del_state(stt_2)
A.display()
Saving an automaton to file. The format used is JavaScript Object Notation (JSON) hence the extension ".json" .
A.save("fibo.json")
# This created a new file on the disk called fibo.json in the current directory
Loading an automaton.
B = awalipy.load("fibo.json")
B.display()
A few example are given as part of the library. The examples are listed by the following function.
examples_dict = awalipy.list_examples()
for kind in ["automata","ratexps"]:
print("======== {} ==========".format(kind))
for name in examples_dict[kind]:
print("- {}\t{}".format(name, examples_dict[kind][name]))
print ("")
======== automata ========== - a1 NFA that accepts words with at least one factor 'ab' - astar-bstar NFA with epsilon transition which recognizes words in 'a*b*' - b1 Z-FA that counts the number of 'b' in words of {a,b}* - binary Z-FA that converts words of {0,1}^* into their binary values - binary-int Z-FA whose labels are integers and that converts words of {0,1}^* into their binary values - c1 Z-FA that converts words of {a,b}^* into their binary values - d1 Z-FA computes the difference between the numbers of 'a' and 'b' - e1 Q-FA that converts words of {a,b}^* into their binary values after the radix point - english-dict DFA accepting a small english dictionary (54316 words) - evena DFA which recognizes words with an even number of 'a' - fibotdc-lr Sequential transducer which tries to replace 'abb' by 'baa' - flipper Transducer that mimics a flipper game - gray Gray code increment - heapmodel Z-max-plus automaton, heap model with 2 pieces - lamplighter Group automaton which realizes the Lamplighter group - minab Z-min-plus-automaton which computes the minimum among the numbers of 'a' and 'b' in every word - minblocka Z-min-plus-automaton which computes the length of the shortest block of 'a' in every word - oddb DFA which recognizes words with an odd number of 'b' - prob-rabin R-automaton (probabilistic automaton) that accepts w with prob. expansion(w) - rotation C-automaton realizing a rotation - slowcerny Synchronisable NFA which meets Cerny bound - slowgrow Z-min-plus-automaton with a slow growing length function - url-validator Automaton with epsilon transition that validates url ======== ratexps ========== - conway-exp Running example of an expression in Conway's book Regular Algebra and Finite Machines - div3b2-exp Writing in base 2 of the integers divisible by 3
Example automata can be loaded with the function load
with their name
C = awalipy.load("a1")
C.display()
make_cerny(n)
returns an n
-states DFA whose smallest synchronising word is of length (n-1)**2
. This automaton attains the upper bound for the Cerny conjecture.
awalipy.make_cerny(5).display()
make_divkbaseb(k,b)
returns an automaton accepting integers divisible by k
, written in base b
.
awalipy.make_divkbaseb(3,2).display()
make_ladybird(n)
returns an automaton with n
-states, whose equivalent minimal DFA has 2**n
states.
awalipy.make_ladybird(5).display()
See also make_de_bruijn
, make_double_ring
, make_witness
awalipy.make_random_DFA(5,"ab").display()
A.display()
Getting the list of states, of transitions.
(It cannot be assumed that the ids of states are [0,1,...,n]
for some n)
A.states(), A.transitions()
([0, 1], [0, 1, 2])
Getting the list of initial states, of final states.
A.initial_states(), A.final_states()
([0], [1])
Listing the transitions adjacent to a state.
A.outgoing(stt_1), A.incoming(stt_1)
([1], [0])
Listing the transitions from a state to another.
A.outin(stt_0,stt_1)
[0]
Getting information from a transition identifier.
# NB: tr_1 is a transition s1 --b--> s0
print (A.src_of(tr_1)) ## Source of transition tr_2
print (A.label_of(tr_1)) ## Label of tr_2
print (A.dst_of(tr_1)) ## Destination of tr_2
print (A.unpack_transition(tr_1)) ## All the above. (Third component
## is the weight and may be ignored.)
1 b 0 (1, 'b', 'true', 0)
List of states reachable from a state in one transition.
A.successors(stt_0), A.successors(stt_0, 'a')
([1, 0], [1])
List of states that may reach a state in one transition.
A.predecessors(stt_0), A.predecessors(stt_0, 'a')
([1, 0], [])
def bf_traversal(A):
visited = {}
for i in A.states():
visited[i] = False
to_treat = A.initial_states()
while len(to_treat) > 0 :
stt = to_treat.pop()
if not (visited[stt]):
visited[stt] = True
out_trs = A.outgoing(stt)
for tr in out_trs:
print (A.unpack_transition(tr))
to_treat.append(A.dst_of(tr))
bf_traversal(A)
(0, 'a', 'true', 1) (0, 'b', 'true', 0) (1, 'b', 'true', 0)
bf_traversal(awalipy.make_ladybird(3))
(0, 'a', 'true', 1) (1, 'b', 'true', 1) (1, 'c', 'true', 1) (1, 'c', 'true', 0) (1, 'a', 'true', 2) (2, 'b', 'true', 2) (2, 'c', 'true', 2) (2, 'c', 'true', 0) (2, 'a', 'true', 0)