|
1 |
| -import random |
| 1 | +import transitions |
2 | 2 |
|
3 |
| -class ExceptionFSM(Exception): |
4 |
| - pass |
| 3 | +""" |
| 4 | +Algorithm 5.7.2 |
| 5 | +Determination of Equivalent States of DFA |
5 | 6 |
|
6 |
| -class State(object): |
| 7 | +input: DFA M = (Q, Alphabet, TransitionFunctoin, q<sub>0</sub>, F) |
7 | 8 |
|
8 |
| - def __init__(self): |
9 |
| - pass |
| 9 | +1. (Initialization) |
| 10 | + for every pair of states q<sub>i</sub> and q<sub>j</sub>, i < j, do |
| 11 | + 1.1 D[i,j] := 0 |
| 12 | + 1.2 S[i,j] := null set |
| 13 | + end for |
| 14 | +2. for every pair i, j, i < j, if one of q<sub>i</sub> or q<sub>j</sub> is |
| 15 | + and accepting state and the other is not an accepting state, then set D[i,j] := 1 |
| 16 | +3. for every pair i, j, i < j, with D[i,j] = 0, do |
| 17 | + 3.1 if there exists an a which is element of Alphabet such that delta(q<sub>i</sub>, a) = q<sub>m</sub>, |
| 18 | + delta(q<sub>j</sub>, a) = q<sub>n</sub> and D[m,n] = 1 or D[n,m] = 1, then DIST(i,j) |
10 | 19 |
|
11 |
| - def isFinalState(self): |
12 |
| - return fState |
| 20 | + 3.2 else for each a that is element of Alphabet, do: Let delta(q<sub>i</sub>, a) = q<sub>m</sub>, |
| 21 | + delta(q<sub>j</sub>m a) = q<sub>n</sub> |
| 22 | + if m < n and [i,j] /= [m,n], then add [i,j] to S[m,n] |
| 23 | + else if m > n and [i,j] /= [n,m], then add [i,j] to S[n,m] |
| 24 | + end for |
13 | 25 |
|
14 |
| - def isAcceptState(self): |
15 |
| - return aState |
| 26 | +DIST(i,j); |
| 27 | +begin |
| 28 | + D[i,j] := 1 |
| 29 | + for all [m,n] that are elements of S[i,j], DIST(m,n) |
| 30 | +end |
| 31 | +""" |
| 32 | +def determineEquivelantStatesOfDFA( dfa ): |
| 33 | + equivStates = set() |
| 34 | + states = list(dfa.states.items()) |
| 35 | + D, S = [], [] |
| 36 | + # initialization |
| 37 | + for i in range(len(states)): |
| 38 | + D.append([]) |
| 39 | + S.append([]) |
| 40 | + for j in range(len(states)): |
| 41 | + D[-1].append(False) if i < j else D[-1].append(None) |
| 42 | + S[-1].append(set()) if i < j else S[-1].append(None) |
| 43 | + # Step 2 |
| 44 | + for i in range(len(states)): |
| 45 | + for j in range(len(states)): |
| 46 | + if i < j and any(s.is_final() for s in states[i:j+1]) |
| 47 | + and not all(s.is_final() for s in states[i:j+1]): |
| 48 | + D[i][j] = 1 |
| 49 | + # Step 3 |
| 50 | + for i in range(len(states)): |
| 51 | + for j in range(len(states)): |
| 52 | + if i < j and D[i][j] == 0: # Do |
| 53 | + # if there is an "a" for which both qi and qj have a transition and the |
| 54 | + # resulting state m,n are not equal (m!=n) and D[m][n] or D[n][m] == 1 then |
| 55 | + # DIST(i,j) |
| 56 | + # 3.1 |
| 57 | + for symbol in dfa.alphabet.keys(): |
| 58 | + qi_transition = getTransitionWithSymbol( symbol, states[i].name ) |
| 59 | + qj_transition = getTransitionWithSymbol( symbol, states[j].name ) |
| 60 | + m_state, n_state = qi_transition.dest, qj_transition.dest |
| 61 | + # get indexes |
| 62 | + m_index, n_index = 0,0 |
| 63 | + if D[m_index][n_index] == 1 or D[n_index][m_index] == 1: |
| 64 | + DIST(i. j) |
| 65 | + # 3.2 |
| 66 | + for symbol in dfa.alphabet.key(): |
| 67 | + pass |
| 68 | + # Now determine the set of equiv states. If D[i][j] = 0 then i and j are equiv |
| 69 | + for i in range(len(states)): |
| 70 | + for j in range(len(states)): |
| 71 | + if D[i][j] == 0: |
| 72 | + equivStates.add(states[i]) |
| 73 | + equivStates.add(states[j]) |
16 | 74 |
|
17 |
| -class Transition(object): |
18 | 75 |
|
19 |
| - def __init__(self, input_state, symbol, result_state): |
20 |
| - self.state = input_state |
21 |
| - self.symbol = symbol |
22 |
| - self.result_state |
| 76 | +def DIST(i, j, D, S): |
| 77 | + """ Helper function for our main algorithm """ |
| 78 | + D[i][j] = 1 |
| 79 | + for m,n in S[i][j]: |
| 80 | + DIST(m, n) |
23 | 81 |
|
24 |
| -class FiniteAutomaton(object): |
| 82 | +def getTransitionWithSymbol( dfa, symbol, source ): |
| 83 | + """ |
| 84 | + Find a transition, if one exists, that involves the named |
| 85 | + symbol and source |
| 86 | + """ |
| 87 | + for event in dfa.events.keys(): |
| 88 | + for transition in event.transitions.values(): |
| 89 | + if event == symbol and transition.source == source: |
| 90 | + return transition |
25 | 91 |
|
26 |
| - def __init__(self, initial_state): |
27 |
| - self.init_state = initial_state |
28 |
| - self.Q = set() |
29 |
| - self.F = set() |
30 |
| - self.alphabet = set() |
| 92 | +""" |
| 93 | +input: an NFA-null M = (Q, Alphabet, TransitionFunction, q<sub>0</sub>,F) |
| 94 | + input transition function t of M |
31 | 95 |
|
32 |
| - def add_transition(self, symbol, state, action, next_state): |
33 |
| - pass |
34 |
| - |
35 |
| - def getOtherStates(self,state): |
36 |
| - return [s for s in Q if s != state] |
37 |
| - |
38 |
| - def getNonFinalStates(self): |
39 |
| - return self.Q.difference(self.F) |
40 |
| - |
41 |
| - def getANonFinalState(self): |
42 |
| - return random.choice(self.getNonFinalStates()) |
| 96 | +1. initialize Q' to null-closure(q<sub>0</sub>) |
| 97 | +2. repeat |
| 98 | + 2.1 if there is a node X, X is element of Q' and a symbol a that's element of Alphabet |
| 99 | + with no arc leaving X labeled "a", then |
| 100 | + 2.1.1 let Y = UNION over q<sub>i</sub>, where q<sub>i</sub> is element of X of |
| 101 | + t(q<sub>i</sub>,a) |
| 102 | + 2.1.2 if Y /= Q', then set Q' := Q UNION {Y} |
| 103 | + 2.1.3 add an arc from X to Y labeled a |
| 104 | + else done:= true |
| 105 | + until done |
| 106 | +3. the set of accepting states of DM if F' = {X, where X is element of Q' | X contains |
| 107 | + an element q<sub>i</sub> that is element of F} |
| 108 | +""" |
| 109 | +def constructEquivelantDFAFromNFA( nfa ): |
| 110 | + raise NotImplementedError |
0 commit comments