Example #1
0
// 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
}
Example #2
0
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
}
Example #3
0
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
}
Example #4
0
// 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
}