Click here to Skip to main content
15,891,423 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello. I am doing a simple project which consists of 3 questions. It is related to finite automata. In the second question, we have to convert an NFA to DFA, but we must not simplify the result DFA.
My implementation can only pass half of the test cases. I have 3 class in my code.
The first one is for every state in the automata, here is its code:
C#
public class State
{
    public bool isFinal;
    public bool isInitial;
    public string name;
    public List<Transition> transitions = new List<Transition>();
    public State(){}
    public State(bool _isFinal, bool _isInitial, string _name)
    {
        isFinal = _isFinal;
        isInitial = _isInitial;
        name = _name;
    }
}

And another class for storing information about every transition:
C#
public class Transition
{
    public State start {get; set;}
    public State end {get; set;}
    public char symbol {get; set;}
}

The final class consists of 2 methods.
C#
public class NFAtoDFA
{
    public List<State> states {get; set;}
    public List<Transition> transitions {get; set;}
    public List<char> symbols {get; set;}
    public NFAtoDFA(List<State> _states, List<Transition> _transitions, 
                    List<char> _symbols)
    {
        states = _states;
        transitions = _transitions;
        symbols = _symbols;
    }
    public int convertNFAtoDFA()
    {
        List<State> newStates = new List<State>();
        /* Initialize every state */
        for (int i = 0; i < states.Count; i++)
        {
            State tmpState = new State();
            tmpState.isFinal = states[i].isFinal;
            tmpState.isInitial = states[i].isInitial;
            for (int j = 0; j < states[i].transitions.Count; j++)
            {
                Transition tmpTr = new Transition();
                tmpTr.start = states[i].transitions[j].start;
                tmpTr.end = states[i].transitions[j].end;
                tmpTr.symbol = states[i].transitions[j].symbol;
                tmpState.transitions.Add(tmpTr);
            }
            tmpState.name = states[i].name;
            newStates.Add(tmpState);
        }
        /* Now we should look for landa transitions */
        for (int i = 0; i < states.Count; i++)
        {
            for (int j = 0; j < states[i].transitions.Count; j++)
            {
                if (states[i].transitions[j].symbol == '$')
                {
                        states[i].name = states[i].name + " " + 
                         states[i].transitions[j].end.name;
                }
            }

            states[i].name = states[i].name.Trim();
        }

        for (int i = states.Count - 1; i >= 0; i--)
        {
            for (int j = states[i].transitions.Count - 1; j >= 0; j--)
            {
                if (states[i].transitions[j].symbol == '$')
                {
                    states[i].transitions.Remove(states[i].transitions[j]);
                }
            }
        }

        List<State> DFA = new List<State>();
        State Initial = new State(states[0].isFinal, true, states[0].name);
        DFA.Add(Initial);

        for (int i = 0; i < DFA.Count; i++)
        {
            for (int j = 0; j < symbols.Count; j++)
            {
                State tmp = new State();
                tmp.isFinal = false;
                List<State> newAdjStates = new List<State>();

                var statesName = DFA[i].name.Trim().Split(' ');
                
                for (int k = 0; k < statesName.Length; k++)
                {
                    for (int m = 0; m < newStates.Count; m++)
                    {
                        for (int n = 0; n < newStates[m].transitions.Count; n++)
                        {
                            if (newStates[m].name ==  statesName[k] 
                                                 && 
                             (char)newStates[m].transitions[n].symbol == symbols[j])
                            {
                                newAdjStates.Add(newStates[m].transitions[n].end);
                            }
                        }
                    }
                }
                string newName = "";
                for (int k = 0; k < newAdjStates.Count; k++)
                {
                    newName = newName + " " + newAdjStates[k].name;
                }
                for (int k = 0; k < newAdjStates.Count; k++)
                {
                    if (newAdjStates[k].isFinal)
                    {
                        tmp.isFinal = true;
                    }
                }

                tmp.name = newName;
                bool exist = false;
                int index = -1;
                for (int k = 0; k <= i; k++)
                {
                    if (DFA[k].name.Trim() == newName.Trim())
                    {
                        exist = true;
                        index = k;
                    }
                }

                Transition trDFA = new Transition();
                if (exist)
                {
                    trDFA.start = DFA[i];
                    trDFA.symbol = symbols[j];
                    trDFA.end = DFA[index];
                    DFA[i].transitions.Add(trDFA);
                }
                else
                {
                    trDFA.start = DFA[i];
                    trDFA.symbol = symbols[j];
                    trDFA.end = tmp;
                    DFA.Add(tmp);
                    DFA[i].transitions.Add(trDFA);
                }
            }
        }
        return removeDuplicates(DFA);
    } 
    public int removeDuplicates(List<State> DFA)
    {
        /* Key --> initial state, Value --> list of all transition */
        Dictionary<string, List<string>> resDFA = 
        new Dictionary<string, List<string>>();
        StringBuilder sb;
        for (int i = 0; i < DFA.Count; i++)
        {
            for (int j = 0; j < DFA[i].transitions.Count; j++)
            {
                sb = new StringBuilder();
                string source = DFA[i].transitions[j].start.name.Trim();
                string dest = DFA[i].transitions[j].end.name.Trim();
                char symbol = DFA[i].transitions[j].symbol;
                if (source == "" || source == null)
                {
                    source = "Trap";
                }
                if (dest == "" || dest == null)
                {
                    dest = "Trap";
                }
                sb.Append($"{source} + {symbol} + {dest}");
                if (resDFA.ContainsKey(source.Trim()))
                {
                    List<string> list = resDFA[source];
                    if (!list.Contains(sb.ToString()) && sb.ToString() != "")
                    {
                        list.Add(sb.ToString());
                    }
                }
                else
                {
                    List<string> list = new List<string>();
                    list.Add(sb.ToString());
                    resDFA.Add(source.Trim(), list);
                }
            }
        }
        return resDFA.Keys.Count;
    }
}

And here is the driver code:
C#
class Program
{
    static void Main(string[] args)
    {
        List<State> NFA = new List<State>();
        List<Transition> transitions = new List<Transition>();
        /*
            The second part is to convert the NFA to DFA
        */
        var states = Console.ReadLine().Split(',', '{', '}').
                     Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
        var sigma = Console.ReadLine().Split(',', '{', '}').
                           Where(x => !string.IsNullOrWhiteSpace(x)).
                           Select(item =>  char.Parse(item)).ToList();
        var finals = Console.ReadLine().Split(',', '{', '}').
                     Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
        long numberOfTransitions = Convert.ToInt64(Console.ReadLine());
        for (int i = 0; i < states.Count; i++)
        {
            State newState = new State();
            if (i == 0)
            {
                newState.isInitial = true;
            }
            newState.name = states[i];
            NFA.Add(newState);
        }
        for (int i = 0; i < finals.Count; i++)
        {
            for (int j = 0; j < NFA.Count; j++)
            {
                if (NFA[j].name == finals[i])
                {
                    NFA[j].isFinal = true;
                }
            }
        }
        for (int i = 0; i < numberOfTransitions; i++)
        {
            var t = Console.ReadLine().Split(',');
            Transition tr = new Transition();
            tr.symbol = Convert.ToChar(t[1]);
            for (int j = 0; j < NFA.Count; j++)
            {
                if (NFA[j].name == t[0])
                {
                    tr.start = NFA[j];
                }
                if (NFA[j].name == t[2])
                {
                    tr.end = NFA[j];
                }
            }
            transitions.Add(tr);
        }

        for (int i = 0; i < NFA.Count; i++)
        {
            for (int j = 0; j < transitions.Count; j++)
            {
                if (NFA[i] == transitions[j].start)
                {
                    NFA[i].transitions.Add(transitions[j]);
                }
            }
        }
        NFAtoDFA obj = new NFAtoDFA(NFA, transitions, sigma);
        
        System.Console.WriteLine(obj.convertNFAtoDFA());
    }
}


For example for the below test case, my test does not work correctly(The output should be 11, but for me is 3).
{q0,q1,q2,q3,q4,q5,q6}
{0,1}
{q6}
11
q0,0,q1
q0,1,q1
q1,1,q1
q2,0,q3
q3,$,q1
q3,1,q4
q4,0,q5
q5,1,q3
q5,1,q6
q6,0,q6
q6,1,q6


What I have tried:

I know that it is hard to answer this kind of question, and I have to rectify the algorithm on my own, but I will be grateful for any help or advice.
Posted
Comments
Maciej Los 22-Mar-22 17:18pm    
What is NFA/DFA?
Aylin Naebzadeh 22-Mar-22 17:30pm    
NFA stands for non-deterministic finite automata, and DFA stands for deterministic finite automata. There are more information about these two topics in these links:
1 - https://www.geeksforgeeks.org/introduction-of-finite-automata/

2 - https://www.javatpoint.com/deterministic-finite-automata

3 - https://www.javatpoint.com/non-deterministic-finite-automata

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900