Beispiel #1
0
//                           +-+
// --> 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, "")
}
Beispiel #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
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}
Beispiel #5
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
}
Beispiel #6
0
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
}
Beispiel #7
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
}
Beispiel #8
0
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
}
Beispiel #9
0
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
}
Beispiel #10
0
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()
	}
}
Beispiel #11
0
func NewNfa() Nfa {
	return &simpleNfa{set.NewSet(), set.NewSet(), set.NewSet(), make(map[State]map[Letter]StateSet), set.NewSet()}
}
Beispiel #12
0
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
}