package ab1.impl.GRUPPE; import ab1.FinalizedStateException; import ab1.NFA; import ab1.NFAFactory; import ab1.Transition; import lombok.Getter; import java.util.*; import java.util.stream.Collectors; public class NFAImpl implements NFA { private Set states; private Set transitions; private String initialState; private Set acceptingStates; @Getter private Set alphabet; private boolean isFinalized; public NFAImpl(String startState) { this.initialState = startState; this.states = new HashSet<>(); this.states.add(startState); this.transitions = new HashSet<>(); this.acceptingStates = new HashSet<>(); this.alphabet = new HashSet<>(); this.isFinalized = false; } @Override public Set getStates() { return this.states; } @Override public Collection getTransitions() { return this.transitions; } @Override public Set getAcceptingStates() { return this.acceptingStates; } @Override public String getInitialState() { return this.initialState; } @Override public void addTransition(Transition transition) throws FinalizedStateException { if (this.isFinalized) { throw new FinalizedStateException(); } if (!states.contains(transition.fromState())) { this.states.add(transition.fromState()); } if (!states.contains(transition.toState())) { this.states.add(transition.toState()); } // add symbol to alphabet. If it is already in the alphabet, nothing happens this.alphabet.add(transition.readSymbol()); this.transitions.add(transition); } public void addAllTransition(Set transitions) throws FinalizedStateException { if(this.isFinalized){ throw new FinalizedStateException(); } for (Transition transition : transitions) { this.addTransition(transition); } } @Override public void addAcceptingState(String state) throws FinalizedStateException { if (this.isFinalized) { throw new FinalizedStateException(); } this.states.add(state); this.acceptingStates.add(state); } public void addAllAcceptingStates(Set states) throws FinalizedStateException { if(this.isFinalized){ throw new FinalizedStateException(); } for (String state : states) { this.addAcceptingState(state); } } // #TODO @Override public NFA union(NFA other) throws FinalizedStateException { if (!this.isFinalized || !other.isFinalized()) { throw new FinalizedStateException(); } NFAImpl unionNFA = new NFAImpl(this.initialState); unionNFA.states.addAll(this.states); unionNFA.states.addAll(other.getStates()); unionNFA.transitions.addAll(this.transitions); unionNFA.transitions.addAll(other.getTransitions()); return unionNFA; } // #TODO @Override public NFA intersection(NFA other) throws FinalizedStateException { if (!this.isFinalized || !other.isFinalized()) { throw new FinalizedStateException(); } NFAImpl intersectionNFA = new NFAImpl(this.initialState); intersectionNFA.states.addAll(this.states); intersectionNFA.states.retainAll(other.getStates()); intersectionNFA.transitions.addAll(this.transitions); intersectionNFA.transitions.retainAll(other.getTransitions()); return intersectionNFA; } // #TODO @Override public NFA concatenation(NFA other) throws FinalizedStateException { if (!this.isFinalized || !other.isFinalized()) { throw new FinalizedStateException(); } NFAImpl concatenationNFA = new NFAImpl(this.initialState); concatenationNFA.states.addAll(this.states); concatenationNFA.states.addAll(other.getStates()); concatenationNFA.transitions.addAll(this.transitions); concatenationNFA.transitions.addAll(other.getTransitions()); for (String accceptingState : this.acceptingStates) { Transition epsilon = new Transition(accceptingState, null, other.getInitialState()); concatenationNFA.transitions.add(epsilon); } return concatenationNFA; } @Override public NFA kleeneStar() throws FinalizedStateException { if (!this.isFinalized) { throw new FinalizedStateException(); } NFAImpl nfa = new NFAImpl(this.initialState); // copy, but without accepting states nfa.states.addAll(this.states); nfa.transitions.addAll(this.transitions); // adding the initial state as accepting state because we have to accept the empty string nfa.acceptingStates.add(this.initialState); // for each accepting state for (String acceptingState : this.acceptingStates) { Transition loopBackTransition = // creating an epsilon transition (null) for each accepting state new Transition(acceptingState, null, this.initialState); if (!nfa.transitions.contains(loopBackTransition)) { nfa.transitions.add(loopBackTransition); } } return nfa; } @Override public NFA plusOperator() throws FinalizedStateException { if (!this.isFinalized) { throw new FinalizedStateException(); } NFAImpl nfa = new NFAImpl(this.initialState); // simple copy nfa.states.addAll(this.states); nfa.transitions.addAll(this.transitions); nfa.acceptingStates.addAll(this.acceptingStates); // for each accepting state for (String acceptingState : this.acceptingStates) { Transition loopBackTransition = // creating an epsilon transition (null) for each accepting state new Transition(acceptingState, null, this.initialState); if (!nfa.transitions.contains(loopBackTransition)) { nfa.transitions.add(loopBackTransition); } } return nfa; } // #TODO @Override public NFA complement() throws FinalizedStateException { if (!this.isFinalized) { throw new FinalizedStateException(); } NFAImpl complementNFA = new NFAImpl(this.initialState); complementNFA.states.addAll(this.states); complementNFA.transitions.addAll(this.transitions); /* for(String state : this.states){ } */ return null; } @Override public boolean isFinalized() { return isFinalized; } @Override public void finalizeAutomaton() { this.isFinalized = true; } // #TODO @Override public boolean isFinite() { //transitions={fromState==toState} //states={A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z} //obergrenze = anzahl der states (26) return false; } // #TODO @Override public boolean acceptsWord(String word) throws FinalizedStateException { //check if word is accepted return false; } public NFA convertNFAtoDFA(NFAImpl input) { /* What do we need to do? Helper Methods: - epsilonClosure - getStateAfterTransition - determineAcceptingStates */ Set dfaAcceptingStates = new HashSet<>(); // all states of the DFA List> dfaStates = new ArrayList<>(); // all transitions of the DFA Set dfaTransitions = new HashSet<>(); // all states of the NFA Set startState = new HashSet<>(); startState.add(input.getInitialState()); // getting the epsilon closure of the start state startState = epsilonClosure(startState, input); dfaStates.add(startState); if (isAcceptingState(startState, input)){ dfaAcceptingStates.add(getIndexOfSet(startState, dfaStates)); } // do the above with each DFA state Queue> queue = new LinkedList<>(); queue.add(startState); // iterate each Letter while (!queue.isEmpty()) { Set currentState = queue.poll(); // for each possible Letter for (char letter : input.getAlphabet()) { // get the new state after the transition Set newState = epsilonClosure(getStateAfterTransition(currentState, letter, input), input); if (!dfaStates.contains(newState)) { queue.add(newState); dfaStates.add(newState); if (isAcceptingState(newState, input)) { dfaAcceptingStates.add(getIndexOfSet(newState, dfaStates)); } } // build new Transition dfaTransitions.add(new Transition(getIndexOfSet(currentState, dfaStates), letter, getIndexOfSet(newState, dfaStates))); // we got to change this to only a string is given //dfaTransitions.add(new Transition(currentState, letter, newState)); } } NFAImpl newDFA = new NFAImpl("0"); for(int i=1;i epsilonClosure(Set states, NFA nfa) { /* Original: boolean isAccepting = false; int index = 0; List> DFA_states = new ArrayList<>(); Set DFA_transitions = new HashSet<>(); // start state alle verbindungen mit epsilon als set for(String state : states) { for (Transition transition : input.transitions) { if (state.equals(transition.fromState()) && transition.readSymbol() == null) { if(!isAccepting) { for (String acceptingState : acceptingStates) if (transition.toState().equals(acceptingState)) { isAccepting = true; break; } } states.add(transition.toState()); // funktioniert immer noch, wenn w epsilon Übergänge hintereinander? } } } DFA_states.add(new HashSet<>(states)); */ Set closure = new HashSet<>(states); Stack stack = new Stack<>(); stack.addAll(states); while (!stack.isEmpty()) { String state = stack.pop(); for (Transition transition : nfa.getTransitions()) { if (transition.fromState().equals(state) && transition.readSymbol() == null) { if (closure.add(transition.toState())) { stack.push(transition.toState()); } } } } return closure; } private Set getStateAfterTransition(Set states, char symbol, NFA nfa) { Set result = new HashSet<>(); for (String state : states) { for (Transition transition : nfa.getTransitions()) { if (transition.fromState().equals(state) && transition.readSymbol() != null && transition.readSymbol() == symbol) { result.add(transition.toState()); } } } return result; } private boolean isAcceptingState(Set states, NFA input) { for (String accState : input.getAcceptingStates()) { if (states.contains(accState)) { return true; } } return false; } private String getIndexOfSet(Set set, List> dfaStates){ return Integer.toString(dfaStates.indexOf(set)); } }