static void Main(string[] args)
        {
            Console.WriteLine("Given Regular Expression: a+bc");
            EpsilonNFA thomsonNFA1 = EpsilonNFA.ThomsonsConstruction("a+bc");

            Console.WriteLine(thomsonNFA1.ToString());
            Console.WriteLine("-----------------------------------------------------------\n");

            Console.WriteLine("Given  Expression: a");
            EpsilonNFA thomsonNFA2 = EpsilonNFA.ThomsonsConstruction("a");

            Console.WriteLine(thomsonNFA2.ToString());
            Console.WriteLine("-----------------------------------------------------------\n");

            Console.WriteLine("Given  Expression: A+B");
            EpsilonNFA thomsonNFA3 = EpsilonNFA.ThomsonsConstruction("A+B");

            Console.WriteLine(thomsonNFA3.ToString());
            Console.WriteLine("-----------------------------------------------------------\n");

            // Subset Construction은 오류 때문에 실행이 안됩니다 ㅠㅠ.
            Console.WriteLine("Subset Construction");
            //DFA subsetDFA = EpsilonNFA.SubsetConstruction(thomsonNFA2);
            //Console.WriteLine(subsetDFA.ToString());
            Console.WriteLine("-----------------------------------------------------------\n");
        }
예제 #2
0
        // 왼쪽NFA에 오른쪽NFA의 State추가 Transition추가해서 통합시켜 준다
        private static EpsilonNFA IntegrateEpsilonNFA(EpsilonNFA l, EpsilonNFA r)
        {
            // copy l to new instance
            var leftCopy = new EpsilonNFA();

            leftCopy.Inputs = l.Inputs;
            foreach (var start in l.StartState)
            {
                leftCopy.StartState.Add(start);
            }
            foreach (var final in l.FinalStates)
            {
                leftCopy.FinalStates.Add(final);
            }
            foreach (var state in l.States)
            {
                leftCopy.States.Add(state);
            }
            foreach (var trans in l.TransitionFunctions)
            {
                foreach (var val in trans.Value)
                {
                    leftCopy.AddTransition(new Tuple <string, string>(trans.Key.Item1, trans.Key.Item2), val);
                }
            }

            // do integration
            foreach (var item in r.States)
            {
                leftCopy.States.Add("r" + item);
            }
            foreach (var item in r.TransitionFunctions)
            {
                var rCurrentState = item.Key.Item1;
                rCurrentState = "r" + rCurrentState;
                var rInput = item.Key.Item2;

                var rValues = item.Value;
                foreach (var rVal in rValues)
                {
                    leftCopy.TransitionFunctions.Add(new Tuple <string, string>(rCurrentState, rInput), "r" + rVal);
                }
            }

            return(leftCopy);
        }
예제 #3
0
        // 두 입실론 NFA를 Concat한다
        static EpsilonNFA Concat(EpsilonNFA l, EpsilonNFA r)
        {
            if (null == l || l.FinalStates.Count == 0 || l.StartState.Count == 0)
            {
                return(r);
            }
            else if (null == r || r.FinalStates.Count == 0 || r.StartState.Count == 0)
            {
                return(l);
            }
            else
            {   // concat Thomson's Construction 적용
                // l에 State 추가 ㅁ -> ㅁ (->) ㅇ -> ㅇ
                // l의 final state 랑 r의 start state 연결
                // final 재설정
                var target = IntegrateEpsilonNFA(l, r);

                target.FinalStates.RemoveAll(s => true); // remove all
                foreach (var rFinal in r.FinalStates)
                {
                    target.FinalStates.Add("r" + rFinal);
                }
                if (l.FinalStates.Count == 0)
                {
                    return(target);
                }

                foreach (var start in r.StartState)
                {
                    target.AddTransition(new Tuple <string, string>(l.FinalStates[0].ToString(), string.Empty), "r" + start);
                    break;
                }

                return(target);
            }
        }
예제 #4
0
        //e-NFA to DFA
        public static DFA SubsetConstruction(EpsilonNFA epsilonNFA)
        {
            HashSet <string>         startState = new HashSet <string>();
            List <HashSet <string> > states     = new List <HashSet <string> >();

            Microsoft.Collections.Extensions.MultiValueDictionary <Tuple <string, string>, string> transitionFunctions = new Microsoft.Collections.Extensions.MultiValueDictionary <Tuple <string, string>, string>();
            HashSet <string> reconstructedStates = new HashSet <string>();
            List <string>    finalStates         = new List <string>();

            foreach (var item in epsilonNFA.StartState)
            {
                startState.UnionWith(epsilonNFA.closure(item));
                break;
            }

            foreach (var input in epsilonNFA.Inputs)
            {
                foreach (var state in startState)
                {
                    foreach (var output in epsilonNFA.TransitionFunctions[new Tuple <string, string>(state, input)])
                    {
                        var newState = epsilonNFA.closure(output);
                        if (states.Contains(newState)) // 여기서 같은것이 반복되면 무시!
                        {
                            continue;
                        }

                        states.Add(newState);

                        string reconstructedStartState = "";
                        string reconstructedFinalState = "";
                        foreach (var item in startState)
                        {
                            reconstructedStartState += item;
                        }
                        foreach (var item in newState)
                        {
                            reconstructedFinalState += item;
                        }
                        if (reconstructedFinalState.Equals(string.Empty))
                        {
                            continue;
                        }

                        transitionFunctions.Add(new Tuple <string, string>(reconstructedStartState, input), reconstructedFinalState);
                    }
                }
            }

            // 해쉬셋을 재구성해서 스테이트로 쓰기위해 하나의 문자열로 만든다
            foreach (var set in states)
            {
                var newState = "";
                foreach (var str in set)
                {
                    newState += str;
                }
                reconstructedStates.Add(newState);
            }

            // 원래 NFA의 finalstate를 가진 것이 곧 DFA의 finalStte
            foreach (var state in reconstructedStates)
            {
                foreach (var nfaFinal in epsilonNFA.FinalStates)
                {
                    if (state.Contains(nfaFinal.ToString()))
                    {
                        finalStates.Add(state);
                    }
                }
            }

            return(new DFA(reconstructedStates, epsilonNFA.Inputs, transitionFunctions, startState, finalStates));
        }
예제 #5
0
        public static EpsilonNFA ThomsonsConstruction(string RegularExpression)
        {
            // 톰슨이 가능한 경우
            if (canKleene(RegularExpression))
            {
                var newNFA = new EpsilonNFA();

                //do kleene
                if (RegularExpression.StartsWith("("))
                {// (RE)*인 경우
                    newNFA.StartState.Add("q0");
                    newNFA.FinalStates.Add("q3");
                    newNFA.States.Add("q0");
                    newNFA.States.Add("q3");
                    // can skip
                    newNFA.AddTransition(new Tuple <string, string>("q0", string.Empty), "q3");
                    // can loop
                    string innerRE  = RegularExpression.Substring(1, RegularExpression.Length - 3);
                    var    innerNFA = ThomsonsConstruction(innerRE);
                    foreach (var startState in innerNFA.StartState)
                    {
                        innerNFA.AddTransition(new Tuple <string, string>(innerNFA.FinalStates[0].ToString(), string.Empty), startState);
                        break;// startstate는 하나일 것이므로 바로 break
                    }

                    //두개의 NFA 통합
                    var output = IntegrateEpsilonNFA(newNFA, innerNFA);
                    foreach (var innerStartState in innerNFA.StartState)
                    {
                        output.AddTransition(new Tuple <string, string>("q0", string.Empty), "r" + innerStartState);
                        break;// startstate는 하나일 것이므로 바로 break
                    }
                    output.AddTransition(new Tuple <string, string>("r" + innerNFA.FinalStates[0].ToString(), string.Empty), "q3");

                    return(output);
                }
                else
                {// a*인 경우
                    newNFA.StartState.Add("q0");
                    newNFA.FinalStates.Add("q3");
                    newNFA.States.Add("q0");
                    newNFA.States.Add("q1");
                    newNFA.States.Add("q2");
                    newNFA.States.Add("q3");
                    newNFA.AddTransition(new Tuple <string, string>("q0", string.Empty), "q1");
                    newNFA.AddTransition(new Tuple <string, string>("q0", string.Empty), "q3");
                    newNFA.AddTransition(new Tuple <string, string>("q1", RegularExpression), "q2");
                    newNFA.AddTransition(new Tuple <string, string>("q2", string.Empty), "q3");
                    newNFA.AddTransition(new Tuple <string, string>("q2", string.Empty), "q1");

                    return(newNFA);
                }
            }
            else if (canConcat(RegularExpression))
            {
                //do concat // ab
                var left  = ThomsonsConstruction(RegularExpression.Substring(0, 1));
                var right = ThomsonsConstruction(RegularExpression.Substring(1));
                return(Concat(left, right));
            }
            else if (canUnion(RegularExpression))
            {
                if (RegularExpression.Length == 3)
                { // a + b인 경우
                    var newNFA = new EpsilonNFA();
                    //do branch
                    newNFA.StartState.Add("q0");
                    newNFA.FinalStates.Add("q5");
                    newNFA.States.Add("q0");
                    newNFA.States.Add("q1");
                    newNFA.States.Add("q2");
                    newNFA.States.Add("q3");
                    newNFA.States.Add("q4");
                    newNFA.States.Add("q5");
                    newNFA.AddTransition(new Tuple <string, string>("q0", string.Empty), "q1");
                    newNFA.AddTransition(new Tuple <string, string>("q0", string.Empty), "q2");
                    newNFA.AddTransition(new Tuple <string, string>("q3", string.Empty), "q5");
                    newNFA.AddTransition(new Tuple <string, string>("q4", string.Empty), "q5");
                    newNFA.AddTransition(new Tuple <string, string>("q1", RegularExpression.Substring(0, 1)), "q3");
                    newNFA.AddTransition(new Tuple <string, string>("q2", RegularExpression.Substring(2)), "q4");

                    return(newNFA);
                }
                else
                {
                    // 괄호가 있는 경우 구현 못했음
                }
            }
            else if (canParen(RegularExpression))
            {
                // (RE)인 경우 => RE
                // do paren
                string noParen = RegularExpression.Substring(1, RegularExpression.Length - 2);
                return(ThomsonsConstruction(noParen));
            }
            else if (RegularExpression.Length == 1 && DefaultInputs.Contains(RegularExpression))
            {
                // 하나의 인풋인 경우 // a
                var newNFA = new EpsilonNFA();
                newNFA.StartState.Add("q0");
                newNFA.FinalStates.Add("q1");
                newNFA.States.Add("q0");
                newNFA.States.Add("q1");
                newNFA.AddTransition(new Tuple <string, string>("q0", RegularExpression), "q1");
                return(newNFA);
            }

            // 더 쪼개야 톰슨이 가능한 경우
            // 제일 먼저 적용돼야되는 부분을 m으로 두고 쪼갠다
            EpsilonNFA l = new EpsilonNFA();
            EpsilonNFA m = new EpsilonNFA();
            EpsilonNFA r = new EpsilonNFA();

            if (RegularExpression.Contains("*"))
            {
                int starIndex = RegularExpression.IndexOf("*");
                if (DefaultInputs.Contains(RegularExpression[starIndex - 1].ToString()))
                {// a*
                    l = ThomsonsConstruction(RegularExpression.Substring(0, starIndex - 1));
                    m = ThomsonsConstruction(RegularExpression.Substring(starIndex - 1, 2));
                    r = ThomsonsConstruction(RegularExpression.Substring(starIndex + 1));
                }
                else
                {// (RE)*
                 //괄호가 있는 경우 구현하지 못했습니다  ㅠㅠ
                }
            }
            else if (RegularExpression.Length > 1 && hasConcatableInput(RegularExpression) != -1)
            {// abRE
                int concatIndex = hasConcatableInput(RegularExpression);
                l = ThomsonsConstruction((RegularExpression.Substring(0, concatIndex)));
                m = ThomsonsConstruction((RegularExpression.Substring(concatIndex, 2)));
                if (concatIndex + 2 < RegularExpression.Length - 1)
                {
                    // abRE인 경우
                    r = ThomsonsConstruction((RegularExpression.Substring(concatIndex + 2)));
                }
                else
                {
                    //ab인 경우
                    r = null;
                }

                // 괄호가 있는 경우는 고려하지 못했습니다 ㅠㅠ
            }
            else if (RegularExpression.Contains("+"))
            {
                int unionIndex = RegularExpression.IndexOf("+");

                if (DefaultInputs.Contains(RegularExpression[unionIndex - 1].ToString()) && DefaultInputs.Contains(RegularExpression[unionIndex + 1].ToString()))
                {//a+b
                    l = ThomsonsConstruction(RegularExpression.Substring(0, unionIndex - 1));
                    m = ThomsonsConstruction(RegularExpression.Substring(unionIndex - 1, 3));
                    r = ThomsonsConstruction(RegularExpression.Substring(unionIndex + 2));
                }
                else
                {
                    //괄호가 있는 경우 구현하지 못했습니다  ㅠㅠ
                }
            }
            // 우선 순위대로 쪼갠다
            else if (RegularExpression.Contains("(") && RegularExpression.Contains(")"))
            {
                int firstIndex = RegularExpression.IndexOf("(");
                int lastIndex  = RegularExpression.LastIndexOf(")");
                if (firstIndex > 0)
                {
                    l = ThomsonsConstruction(RegularExpression.Substring(0, firstIndex));
                }
                else
                {
                    l = null;
                }

                m = ThomsonsConstruction(RegularExpression.Substring(firstIndex, lastIndex - firstIndex + 1));

                if (lastIndex == (RegularExpression.Length - 1))
                {// RE(RE)
                    r = null;
                }
                else
                {
                    r = ThomsonsConstruction(RegularExpression.Substring(lastIndex));
                }
            }

            return(Concat(Concat(l, m), r));
        }