// +-+ // --> 1 -- a --> 2 -- b --> |3| // ^ +-+ // | | // +--------- a ----------+ // func TestSimpleNfa(t *testing.T) { a := Letter("a") b := Letter("b") q0 := State("0") q1 := State("1") q2 := State("2") A := NewNfa() A.Alphabet().Add(a, b) A.States().Add(q0, q1, q2) A.InitialStates().Add(q0) A.FinalStates().Add(q2) trans := func(s State, l Letter) StateSet { if s.IsEqual(q0) && l.IsEqual(a) { return set.NewSet(q1) } else if s.IsEqual(q1) && l.IsEqual(b) { return set.NewSet(q2) } else if s.IsEqual(q2) && l.IsEqual(a) { return set.NewSet(q0) } return set.NewSet() } A.SetTransitionFunction(trans) s := []byte(`{"States":["0","1","2"],"Alphabet":["a","b"],"InitialStates":["0"],"Transitions":{"0":{"a":["1"]},"1":{"b":["2"]},"2":{"a":["0"]}},"FinalStates":["2"]}`) compareNfaToMarshaledNfa(A, s, true, t, "") }
func Concat(A, B Nfa) Nfa { C := NewNfa() C.SetAlphabet(set.Join(A.Alphabet(), B.Alphabet())) //add B as it is with a 1 prepended to all states //add A as it is with a 0 prepended to all states for k, T := range []Nfa{A, B} { for i := 0; i < T.States().Size(); i += 1 { s, _ := T.States().At(i) s_ := State(fmt.Sprint(k, s)) C.States().Add(s_) if k == 1 && T.FinalStates().Probe(s) == true { //B C.FinalStates().Add(s_) } else if k == 0 && T.InitialStates().Probe(s) == true { //A C.InitialStates().Add(s_) } for j := 0; j < T.Alphabet().Size(); j += 1 { a, _ := T.Alphabet().At(j) S := T.Transition(s.(State), a.(Letter)) S_ := set.NewSet() for l := 0; l < S.Size(); l += 1 { t, _ := S.At(l) S_.Add(State(fmt.Sprint(k, t))) } C.SetTransition(s_, a.(Letter), S_) } } } // add transititons from before final states in A to all initial states in B S_ := set.NewSet() for i := 0; i < B.InitialStates().Size(); i += 1 { s, _ := B.InitialStates().At(i) S_.Add(State(fmt.Sprint(1, s))) } for i := 0; i < A.States().Size(); i += 1 { s, _ := A.States().At(i) s_ := State(fmt.Sprint(0, s)) for j := 0; j < A.Alphabet().Size(); j += 1 { a, _ := A.Alphabet().At(j) S := A.Transition(s.(State), a.(Letter)) if set.Intersect(A.FinalStates(), S).Size() > 0 { C.SetTransition(s_, a.(Letter), set.Join(A.Transition(s_, a.(Letter)), S_)) } } } return C }
func (A *simpleNfa) UnmarshalJSON(b []byte) error { type simpleNfaForUnmarshaling struct { States []State Alphabet []Letter InitialStates []State Transitions map[string]map[string][]string //using Letter or State won't work here FinalStates []State } var B simpleNfaForUnmarshaling if err := json.Unmarshal(b, &B); err != nil { return err } states := set.NewSet() alphabet := set.NewSet() initialStates := set.NewSet() transitions := make(map[State]map[Letter]StateSet) finalStates := set.NewSet() for _, s := range B.States { states.Add(s) } for _, l := range B.Alphabet { alphabet.Add(l) } for _, s := range B.InitialStates { initialStates.Add(s) } for _, s := range B.FinalStates { finalStates.Add(s) } for k, v := range B.Transitions { for l, w := range v { if _, ok := transitions[State(k)]; ok != true { transitions[State(k)] = make(map[Letter]StateSet) } S := set.NewSet() for _, s := range w { S.Add(State(s)) } transitions[State(k)][Letter(l)] = S } } *A = simpleNfa{states, alphabet, initialStates, transitions, finalStates} return nil }
func (A simpleNfa) reachableStates() StateSet { reached := set.NewSet() var recurse func(State) recurse = func(q State) { if reached.Probe(q) == true { return } reached.Add(q) for i := 0; i < A.Alphabet().Size(); i += 1 { a, _ := A.Alphabet().At(i) Q := A.Transition(q, a.(Letter)) for j := 0; j < Q.Size(); j += 1 { q_, _ := Q.At(j) recurse(q_.(State)) } } } for i := 0; i < A.InitialStates().Size(); i += 1 { q, _ := A.InitialStates().At(i) recurse(q.(State)) } return reached }
// Q will be the new initial states func (A simpleNfa) inducedNfa(q State) Nfa { B := NewNfa().(*simpleNfa) B.initialStates = set.NewSet(q) B.alphabet = A.Alphabet() var recurse func(State) recurse = func(q State) { if B.States().Probe(q) == true { return } B.States().Add(q) if B.transitions[q] == nil && len(A.transitions[q]) > 0 { B.transitions[q] = make(map[Letter]StateSet) } for l, w := range A.transitions[q] { B.transitions[q][l] = w.Copy().(StateSet) for i := 0; i < w.Size(); i += 1 { r, _ := w.At(i) recurse(r.(State)) } } } recurse(q) B.finalStates = set.Intersect(A.FinalStates(), B.States()) return B }
func Union(A, B Nfa) Nfa { C := NewNfa() C.SetAlphabet(set.Join(A.Alphabet(), B.Alphabet())) for k, T := range []Nfa{A, B} { for i := 0; i < T.States().Size(); i += 1 { s, _ := T.States().At(i) ss := State(fmt.Sprint(k, s)) C.States().Add(ss) if T.InitialStates().Probe(s) == true { C.InitialStates().Add(ss) } if T.FinalStates().Probe(s) == true { C.FinalStates().Add(ss) } for j := 0; j < T.Alphabet().Size(); j += 1 { a, _ := T.Alphabet().At(j) S := T.Transition(s.(State), a.(Letter)) SS := set.NewSet() for l := 0; l < S.Size(); l += 1 { t, _ := S.At(l) SS.Add(State(fmt.Sprint(k, t))) } C.SetTransition(ss, a.(Letter), SS) } } } return C }
// states and transitions from which no final state is reachable // states and transitions that are unreachable func (A simpleNfa) removeUselessParts() Nfa { reachableStates := A.reachableStates() nonEmptyLanguageStates := set.NewSet() var recurse func(State) recurse = func(u State) { if nonEmptyLanguageStates.Probe(u) == true { return } nonEmptyLanguageStates.Add(u) for k, v := range A.transitions { //map[State]map[Letter]StateSet for _, w := range v { if set.Intersect(set.NewSet(u), w).Size() > 0 { recurse(k) } } } } //backward search for all states that can reach a reachable final state reachableFinalStates := set.Intersect(reachableStates, A.FinalStates()) for i := 0; i < reachableFinalStates.Size(); i += 1 { q, _ := reachableFinalStates.At(i) recurse(q.(State)) } usefulStates := set.Intersect(reachableStates, nonEmptyLanguageStates) B := NewNfa().(*simpleNfa) B.states = usefulStates B.initialStates = set.Intersect(A.InitialStates(), usefulStates) B.finalStates = set.Intersect(A.FinalStates(), usefulStates) for k, v := range A.transitions { for l, w := range v { usefulGoalStates := set.Intersect(usefulStates, w) if usefulStates.Probe(k) == true && usefulGoalStates.Size() > 0 { B.alphabet.Add(l) B.SetTransition(k, l, usefulGoalStates) } } } return B }
func (A simpleNfa) Transition(s State, l Letter) StateSet { var m map[Letter]StateSet if _, ok := A.transitions[s]; ok == false { return set.NewSet() } else { m = A.transitions[s] } var S StateSet if _, ok := m[l]; ok == false { S = set.NewSet() } else { S = m[l] } return S }
func OneLetter(a Letter) Nfa { A := NewNfa() q0 := State("0") qf := State("f") A.Alphabet().Add(a) A.States().Add(q0, qf) A.InitialStates().Add(q0) A.FinalStates().Add(qf) A.SetTransition(q0, a, set.NewSet(qf)) return A }
func TestJson(t *testing.T) { a := Letter("a") q0 := State("0") q1 := State("1") q2 := State("2") q3 := State("3") // -> □ -> o // // o -> □ A := NewNfa() A.Alphabet().Add(a) A.States().Add(q0, q1, q2, q3) A.InitialStates().Add(q0) A.FinalStates().Add(q0, q3) A.SetTransition(q0, a, set.NewSet(q1)) A.SetTransition(q2, a, set.NewSet(q3)) s1, err1 := json.Marshal(A) if err1 != nil { t.Error(err1) } B := NewNfa() err2 := json.Unmarshal(s1, &B) if err2 != nil { t.Error(err2) } s3, err3 := json.Marshal(B) if err1 != nil { t.Error(err3) } if bytes.Compare(s1, s3) != 0 { t.Error() } }
func NewNfa() Nfa { return &simpleNfa{set.NewSet(), set.NewSet(), set.NewSet(), make(map[State]map[Letter]StateSet), set.NewSet()} }
func (A simpleNfa) IsEqual(B Nfa) bool { var transitionCount func(simpleNfa) int transitionCount = func(A simpleNfa) int { ret := 0 for _, v := range A.transitions { for _, w := range v { ret += w.Size() } } return ret } C := B.(*simpleNfa) if A.States().Size() != C.States().Size() || A.InitialStates().Size() != C.InitialStates().Size() || A.FinalStates().Size() != C.FinalStates().Size() || A.Alphabet().IsEqual(C.Alphabet()) != true || transitionCount(A) != transitionCount(*C) { return false } var incomingEdgesCount func(simpleNfa, State, Letter) int incomingEdgesCount = func(C simpleNfa, q State, l Letter) int { ret := 0 for _, v := range C.transitions { for l_, w := range v { if l_ == l && w.Probe(q) == true { ret += 1 } } } return ret } var outgoingEdgesCount func(simpleNfa, State, Letter) int outgoingEdgesCount = func(C simpleNfa, q State, l Letter) int { ret := 0 for l_, w := range C.transitions[q] { if l_ == l { ret += w.Size() } } return ret } permutations := make([]map[State]State, 0) var generatePermutations func(int, StateSet, map[State]State) generatePermutations = func(i int, U StateSet, m map[State]State) { if U.Size() == 0 { permutations = append(permutations, m) return } q_, _ := A.States().At(i) q := q_.(State) for j := 0; j < U.Size(); j += 1 { u_, _ := U.At(j) u := u_.(State) for k := 0; k < A.Alphabet().Size(); k += 1 { l_, _ := A.Alphabet().At(k) l := l_.(Letter) if incomingEdgesCount(A, q, l) != incomingEdgesCount(*C, u, l) || outgoingEdgesCount(A, q, l) != outgoingEdgesCount(*C, u, l) { continue } } U_ := U.Copy().(StateSet) U_.Remove(u) m_ := make(map[State]State) for k, v := range m { m_[k] = v } m_[q] = u generatePermutations(i+1, U_, m_) } } generatePermutations(0, C.States(), make(map[State]State)) var translateSet func(StateSet, map[State]State) StateSet translateSet = func(Q StateSet, m map[State]State) StateSet { U := set.NewSet() for i := 0; i < Q.Size(); i += 1 { q, _ := Q.At(i) U.Add(m[q.(State)]) } return U } for _, identify := range permutations { //check initial and final states if B.InitialStates().IsEqual(translateSet(A.InitialStates(), identify)) != true || B.FinalStates().IsEqual(translateSet(A.FinalStates(), identify)) != true { continue } //check transitions correct := true for k, v := range A.transitions { for l, w := range v { if B.Transition(identify[k], l).IsEqual(translateSet(w, identify)) != true { correct = false break } } if correct == false { break } } if correct == true { return true } } return false }