// 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 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 KleeneStar(A Nfa) Nfa { var q0 State for i := 0; ; i += 1 { q0 = State(fmt.Sprint(i)) if A.States().Probe(q0) == false { break } } A.States().Add(q0) // add transitions from before final states to the new initial state for i := 0; i < A.States().Size(); i += 1 { for j := 0; j < A.Alphabet().Size(); j += 1 { q_, _ := A.States().At(i) q := q_.(State) a_, _ := A.Alphabet().At(j) a := a_.(Letter) Q := A.Transition(q, a) if set.Intersect(Q, A.FinalStates()).Size() != 0 { Q.Add(q0) A.SetTransition(q, a, Q) } } } // add transitions from the new initial state // to the destinations of the old initial states for i := 0; i < A.InitialStates().Size(); i += 1 { for j := 0; j < A.Alphabet().Size(); j += 1 { q_, _ := A.InitialStates().At(i) q := q_.(State) a_, _ := A.Alphabet().At(j) a := a_.(Letter) Q := A.Transition(q, a) Q0 := A.Transition(q0, a) A.SetTransition(q0, a, set.Join(Q, Q0)) } } A.InitialStates().Clear() A.InitialStates().Add(q0) A.FinalStates().Clear() A.FinalStates().Add(q0) return A }
// 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 }