/** * inLanguage determines if the given string is accepted by this NFA * * @param s the string being tested * @param current the current state that we are at in the machine (will initially be at the start * state) * @return true if s is accepted, else false */ public boolean inLanguage(String s, NState current) { // check all of the episilon stransitions from this state for (int i = 0; i < current.getEpsilon().length; i++) { if (inLanguage(s, current.getEpsilon()[i])) { return true; } } // if we have eaten through all of the string for this branch, // then we can see if we are in an accepting state if (s.length() == 0) { if (current.isAccepting()) { return true; } return false; } // still have some string to go through else { // go through all of the 'a' transitions if (s.charAt(0) == aTransition) { for (int i = 0; i < current.getA().length; i++) { if (inLanguage(s.substring(1, s.length()), current.getA()[i])) { return true; } } return false; } // go through all of the 'b' transistions else { for (int i = 0; i < current.getB().length; i++) { if (inLanguage(s.substring(1, s.length()), current.getB()[i])) { return true; } } return false; } } }
/** * getDFA takes this NFA and converts is to its corresponding DFA * * @return the DFA that corresponds to this NFA */ public DFA getDFA() { // create powerset of all states (regular State) ArrayList<State> DFAmachine = new ArrayList<State>((int) (Math.pow(2, machine.length))); ArrayList<ArrayList<NState>> power = powerSet(machine); // will be used to determine the state transitions // NOTE: could optimize with a wrapper class to hold both HashMap<State, ArrayList<NState>> stateMap = new HashMap<State, ArrayList<NState>>(); HashMap<ArrayList<NState>, State> nstateMap = new HashMap<ArrayList<NState>, State>(); NState newStartState = start; NState[] nssEpsilon = newStartState.getEpsilon(); HashSet<NState> newStartStateSet = new HashSet<NState>(); // the set that represents our new start state newStartStateSet.add(newStartState); for (int i = 0; i < nssEpsilon.length; i++) { newStartStateSet.add(nssEpsilon[i]); } State nullState = new State("NULL", null, null, false); nullState.setA(nullState); nullState.setB(nullState); DFAmachine.add(nullState); ArrayList<NState> oldStartState = new ArrayList<NState>(); oldStartState.add(start); ArrayList<NState> SSS = new ArrayList<NState>(); SSS.addAll(newStartStateSet); // System.out.println("SSS: " + SSS); // if(SSS.get(0) instanceof NState) // { // System.out.println("Is a NState object"); // } // add all states in power to DFAmachine and populate state map for (ArrayList<NState> item : power) { Collections.sort(item, NState.NStateComparator); // The null state if (item.size() != 0) { String name = ""; boolean anyStateAccept = false; for (NState state : item) { name += state.getName(); // make sure that accepting states are correct if (state.isAccepting()) { anyStateAccept = true; } } State newState = new State(name, null, null, anyStateAccept); if (item.equals(oldStartState)) { stateMap.put(newState, oldStartState); nstateMap.put(oldStartState, newState); } else if (item.equals(SSS)) { stateMap.put(newState, SSS); nstateMap.put(SSS, newState); } else { stateMap.put(newState, item); nstateMap.put(item, newState); } DFAmachine.add(newState); } else { stateMap.put(nullState, item); nstateMap.put(item, nullState); } } boolean flag = false; State finalStartState = nstateMap.get(oldStartState); // no epsilon transitions if (oldStartState.size() == SSS.size()) { Collections.sort(oldStartState, NState.NStateComparator); finalStartState = nstateMap.get(oldStartState); // System.out.println("finalStartSte is : " + finalStartState); } // there are epsilon transitions; update start state and // remove the old start state else { Collections.sort(SSS, NState.NStateComparator); Collections.sort(oldStartState, NState.NStateComparator); System.out.println(oldStartState); System.out.println(SSS); if (SSS.equals(oldStartState)) { // System.out.println("SSS does equal oldStartState"); finalStartState = nstateMap.get(oldStartState); } else { flag = true; System.out.println("SSS doe snot equal oldStartState " + nstateMap.get(SSS)); if (nstateMap.get(SSS) != null) { finalStartState = nstateMap.get(SSS); } else { finalStartState = nstateMap.get(oldStartState); } } // System.out.println("finalStartState is: " + finalStartState); DFAmachine.remove(oldStartState.get(0)); nstateMap.remove(oldStartState); stateMap.remove(oldStartState.get(0)); } // System.out.println(flag); // System.out.println("Start state: " + finalStartState.getName()); // set all the transistions in the machine for (State s : DFAmachine) { ArrayList<NState> currentNStates = stateMap.get(s); HashSet<NState> allStatesATransitions = new HashSet<NState>(); HashSet<NState> allStatesBTransitions = new HashSet<NState>(); // for the current state, grab all of the a, b, and epsilon transistions that // the NStates can go to and put them in sets for (NState currentNS : currentNStates) { NState[] cnsATrans = currentNS.getA(); NState[] cnsBTrans = currentNS.getB(); for (int i = 0; i < cnsATrans.length; i++) { allStatesATransitions.add(cnsATrans[i]); } for (int j = 0; j < cnsBTrans.length; j++) { allStatesBTransitions.add(cnsBTrans[j]); } } // after we grab all the a and b transitions, we check those // transitions for epsilon transitions, and add that to our set HashSet<NState> allStatesEpsilonTrans = new HashSet<NState>(); for (NState currentAA : allStatesATransitions) { NState[] asETrans = currentAA.getEpsilon(); for (int k = 0; k < asETrans.length; k++) { allStatesEpsilonTrans.add(asETrans[k]); } } allStatesATransitions.addAll(allStatesEpsilonTrans); allStatesEpsilonTrans = new HashSet<NState>(); for (NState currentAB : allStatesBTransitions) { NState[] asETrans = currentAB.getEpsilon(); for (int k = 0; k < asETrans.length; k++) { allStatesEpsilonTrans.add(asETrans[k]); } } allStatesBTransitions.addAll(allStatesEpsilonTrans); ArrayList<NState> a = new ArrayList<NState>(); ArrayList<NState> b = new ArrayList<NState>(); a.addAll(allStatesATransitions); b.addAll(allStatesBTransitions); Collections.sort(a, NState.NStateComparator); Collections.sort(b, NState.NStateComparator); /* System.out.print(s.getName() + ": a tran: "); for(NState i : a) { System.out.print(i.getName()); } System.out.print(" b tran: "); for(NState i : b) { System.out.print(i.getName()); } System.out.println(); */ // make all the connections; if the state we are trying to get to is not in // the map(i.e. a removed start state) we have this state point to the // null state State stateATran = nstateMap.containsKey(a) ? nstateMap.get(a) : nullState; State stateBTran = nstateMap.containsKey(b) ? nstateMap.get(b) : nullState; s.setA(stateATran); s.setB(stateBTran); } // remove all unreachable states ArrayList<State> toRemove = new ArrayList<State>(); for (State r : DFAmachine) { ArrayList<State> visited = new ArrayList<State>(); if (r == null) { System.out.println("State we are checking is null"); } if (finalStartState == null) { System.out.println("finalStartState we have is null"); } if (!DFA.isReachable(r, finalStartState, visited, DFAmachine.size())) { toRemove.add(r); } } for (State t : toRemove) { DFAmachine.remove(t); } State[] stateArray = new State[DFAmachine.size()]; DFA finalMachine = new DFA(finalStartState, DFAmachine.toArray(stateArray), aTransition, bTransition); return finalMachine; }