fucking hell
This commit is contained in:
parent
10c49f3b70
commit
347e78fc98
4 changed files with 258 additions and 87 deletions
|
|
@ -14,7 +14,6 @@ public class NFAImpl implements NFA {
|
|||
private String initialState;
|
||||
private Set<String> acceptingStates;
|
||||
|
||||
@Getter
|
||||
private Set<Character> alphabet;
|
||||
|
||||
private boolean isFinalized;
|
||||
|
|
@ -35,6 +34,12 @@ public class NFAImpl implements NFA {
|
|||
return this.states;
|
||||
}
|
||||
|
||||
public void safeAddStates(Set<String> states, Set<String> toCheck, NFAImpl nfa) {
|
||||
for (String state : states) {
|
||||
nfa.states.add(changeIfNecessary(state, toCheck));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Transition> getTransitions() {
|
||||
return this.transitions;
|
||||
|
|
@ -50,6 +55,10 @@ public class NFAImpl implements NFA {
|
|||
return this.initialState;
|
||||
}
|
||||
|
||||
public Set<Character> getAlphabet() {
|
||||
return this.alphabet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTransition(Transition transition) throws FinalizedStateException {
|
||||
if (this.isFinalized) {
|
||||
|
|
@ -62,12 +71,14 @@ public class NFAImpl implements NFA {
|
|||
this.states.add(transition.toState());
|
||||
}
|
||||
// add symbol to alphabet. If it is already in the alphabet, nothing happens
|
||||
this.alphabet.add(transition.readSymbol());
|
||||
if (transition.readSymbol() != null) {
|
||||
this.alphabet.add(transition.readSymbol());
|
||||
}
|
||||
this.transitions.add(transition);
|
||||
}
|
||||
|
||||
public void addAllTransitions(Set<Transition> transitions) throws FinalizedStateException {
|
||||
if(this.isFinalized){
|
||||
if (this.isFinalized) {
|
||||
throw new FinalizedStateException();
|
||||
}
|
||||
for (Transition transition : transitions) {
|
||||
|
|
@ -85,7 +96,7 @@ public class NFAImpl implements NFA {
|
|||
}
|
||||
|
||||
public void addAllAcceptingStates(Set<String> states) throws FinalizedStateException {
|
||||
if(this.isFinalized){
|
||||
if (this.isFinalized) {
|
||||
throw new FinalizedStateException();
|
||||
}
|
||||
for (String state : states) {
|
||||
|
|
@ -93,8 +104,14 @@ public class NFAImpl implements NFA {
|
|||
}
|
||||
}
|
||||
|
||||
public void safeAddAcceptingStates(Set<String> states, Set<String> toCheck, NFAImpl nfa) {
|
||||
for (String state : states) {
|
||||
nfa.addAcceptingState(changeIfNecessary(state, toCheck));
|
||||
}
|
||||
}
|
||||
|
||||
// #TODO
|
||||
// handle case where the state is duplicated
|
||||
// write more testcases
|
||||
@Override
|
||||
public NFA union(NFA other) throws FinalizedStateException {
|
||||
if (!this.isFinalized || !other.isFinalized()) {
|
||||
|
|
@ -102,44 +119,74 @@ public class NFAImpl implements NFA {
|
|||
}
|
||||
// new initialState with epsilon to initialState of this and other.
|
||||
// Problem: what if states are called the same in this and other + what do we use as initialState?
|
||||
Set<String> unionStates = new HashSet<>();
|
||||
unionStates.addAll(this.states);
|
||||
|
||||
//do the union:
|
||||
String start = changeIfNecessary(changeIfNecessary("START", unionStates), other.getStates());
|
||||
|
||||
|
||||
|
||||
|
||||
for(String state : other.getStates()){
|
||||
if(!unionStates.contains(state)){
|
||||
unionStates.add(state);
|
||||
}else{
|
||||
// a state of other has the same name as one in this.
|
||||
//change name of state and every Transitions it is a part of in other
|
||||
String newstate = state;
|
||||
while (unionStates.contains(newstate)){
|
||||
//change the state slightly and save the different version
|
||||
newstate = newstate+"|";
|
||||
}
|
||||
for(Transition transition : other.getTransitions()){
|
||||
if(transition.fromState().equals(state)){
|
||||
Transition changedTransition = new Transition(newstate, transition.readSymbol(), transition.toState());
|
||||
}
|
||||
if(transition.toState().equals(state)){
|
||||
Transition changedTransition = new Transition(transition.fromState(), transition.readSymbol(), newstate);
|
||||
}
|
||||
}
|
||||
unionStates.add(newstate);
|
||||
}
|
||||
}
|
||||
NFAImpl unionNFA = new NFAImpl(this.initialState);
|
||||
NFAImpl unionNFA = new NFAImpl(this.getInitialState());
|
||||
|
||||
unionNFA.states.addAll(this.states);
|
||||
unionNFA.states.addAll(other.getStates());
|
||||
|
||||
unionNFA.transitions.addAll(this.transitions);
|
||||
unionNFA.transitions.addAll(other.getTransitions());
|
||||
unionNFA.addAllAcceptingStates(this.acceptingStates);
|
||||
|
||||
Set<String> otherAcceptingStates = new HashSet<>(other.getAcceptingStates());
|
||||
unionNFA.safeAddAcceptingStates(this.acceptingStates, otherAcceptingStates, unionNFA);
|
||||
|
||||
|
||||
Set<Transition> newTransitions = new HashSet<>();
|
||||
for (Transition transition : other.getTransitions()) {
|
||||
Transition newTransition =
|
||||
new Transition(transition.fromState(), transition.readSymbol(), transition.toState());
|
||||
newTransitions.add(newTransition);
|
||||
}
|
||||
String flag = "";
|
||||
newTransitions.add(new Transition(flag, null, other.getInitialState()));
|
||||
|
||||
for (String state : other.getStates()) {
|
||||
if (!unionNFA.states.contains(state)) {
|
||||
unionNFA.states.add(state);
|
||||
if (other.getAcceptingStates().contains(state)) {
|
||||
unionNFA.acceptingStates.add(state);
|
||||
}
|
||||
} else {
|
||||
// a state of other has the same name as one in this.
|
||||
// change name of state and every Transition it is a part of in other
|
||||
String newState = changeIfNecessary(state, unionNFA.states);
|
||||
|
||||
// wieder a neues set
|
||||
Set<Transition> tempTransitions = new HashSet<>();
|
||||
|
||||
// check each transition of other if start or to state was state
|
||||
for (Transition transition : newTransitions) {
|
||||
if (transition.fromState().equals(state)) {
|
||||
transition = new Transition(newState, transition.readSymbol(), transition.toState());
|
||||
}
|
||||
if (transition.toState().equals(state)) {
|
||||
transition = new Transition(transition.fromState(), transition.readSymbol(), newState);
|
||||
}
|
||||
}
|
||||
for (String accState : other.getAcceptingStates()) {
|
||||
if (accState.equals(state)) {
|
||||
unionNFA.acceptingStates.add(newState);
|
||||
}
|
||||
}
|
||||
newTransitions = tempTransitions; // Replace the original set with the updated set
|
||||
}
|
||||
}
|
||||
// add, alphabet
|
||||
|
||||
Iterator<Transition> iterator = newTransitions.iterator();
|
||||
while (iterator.hasNext()){
|
||||
Transition transition = iterator.next();
|
||||
if(transition.fromState().isEmpty()){
|
||||
iterator.remove();
|
||||
|
||||
newTransitions.add(new Transition(unionNFA.initialState, transition.readSymbol(), transition.toState()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unionNFA.addAllTransitions(newTransitions);
|
||||
|
||||
unionNFA.addAllTransitions(this.transitions);
|
||||
|
||||
unionNFA.finalizeAutomaton();
|
||||
|
||||
|
||||
return unionNFA;
|
||||
|
|
@ -258,19 +305,47 @@ public class NFAImpl implements NFA {
|
|||
// create a copy of this NFA
|
||||
NFAImpl nfa = new NFAImpl(this.initialState);
|
||||
nfa.states.addAll(this.states);
|
||||
nfa.transitions.addAll(this.transitions);
|
||||
nfa.acceptingStates.addAll(this.acceptingStates);
|
||||
nfa.addAllTransitions(this.transitions);
|
||||
nfa.addAllAcceptingStates(this.acceptingStates);
|
||||
|
||||
//nfa = nfa.convertNFAtoDFA(nfa);
|
||||
NFAImpl fakeNFA = convertNFAtoDFA(nfa);
|
||||
|
||||
// state -> accepting
|
||||
// accepting -> state
|
||||
|
||||
/*
|
||||
for(String state : this.states){
|
||||
Set<String> newAcceptingstate = new HashSet<>();
|
||||
|
||||
for (String state : fakeNFA.getStates()) {
|
||||
if (!fakeNFA.getAcceptingStates().contains(state)) {
|
||||
newAcceptingstate.add(state);
|
||||
}
|
||||
}
|
||||
*/
|
||||
fakeNFA.acceptingStates.clear();
|
||||
fakeNFA.addAllAcceptingStates(newAcceptingstate);
|
||||
|
||||
return null;
|
||||
Set<Character> originalAlphabet = new HashSet<>(fakeNFA.alphabet);
|
||||
|
||||
fakeNFA.alphabet.clear();
|
||||
|
||||
Set<Character> newAlphabet = new HashSet<>();
|
||||
|
||||
for (char ch = 'a'; ch <= 'z'; ch++) {
|
||||
if (!originalAlphabet.contains(ch)) {
|
||||
newAlphabet.add(ch);
|
||||
}
|
||||
}
|
||||
|
||||
for (Transition transition : fakeNFA.transitions) {
|
||||
for (Character letter : newAlphabet) {
|
||||
fakeNFA.addTransition(new Transition(transition.fromState(), letter, transition.toState()));
|
||||
}
|
||||
}
|
||||
|
||||
fakeNFA.alphabet = newAlphabet;
|
||||
|
||||
fakeNFA.finalizeAutomaton();
|
||||
|
||||
return fakeNFA;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -299,34 +374,23 @@ public class NFAImpl implements NFA {
|
|||
throw new FinalizedStateException();
|
||||
}
|
||||
|
||||
char[] wordArray = word.toCharArray();
|
||||
|
||||
Set<String> currentStates = new HashSet<>();
|
||||
currentStates.add(this.initialState);
|
||||
currentStates = epsilonClosure(currentStates, this);
|
||||
currentStates = (epsilonClosure(currentStates, this));
|
||||
|
||||
|
||||
for (char letter : word.toCharArray()) {
|
||||
Set<String> nextStates = new HashSet<>();
|
||||
|
||||
|
||||
for (String state : currentStates) {
|
||||
nextStates.addAll(getStateAfterTransition(currentStates, letter, this));
|
||||
}
|
||||
|
||||
nextStates = epsilonClosure(nextStates, this);
|
||||
|
||||
currentStates = nextStates;
|
||||
for (char letter : wordArray) {
|
||||
// schritt a
|
||||
currentStates = getStateAfterTransition(currentStates, letter, this);
|
||||
// schritt b
|
||||
currentStates = epsilonClosure(currentStates, this);
|
||||
}
|
||||
|
||||
for (String state : currentStates) {
|
||||
if (this.acceptingStates.contains(state)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return isAcceptingState(currentStates, this);
|
||||
}
|
||||
|
||||
public NFA convertNFAtoDFA(NFAImpl input) {
|
||||
public NFAImpl convertNFAtoDFA(NFAImpl input) {
|
||||
|
||||
// all accepting states of the DFA
|
||||
Set<String> dfaAcceptingStates = new HashSet<>();
|
||||
|
|
@ -342,7 +406,7 @@ public class NFAImpl implements NFA {
|
|||
// getting the epsilon closure of the start state
|
||||
startState = epsilonClosure(startState, input);
|
||||
dfaStates.add(startState);
|
||||
if (isAcceptingState(startState, input)){
|
||||
if (isAcceptingState(startState, input)) {
|
||||
dfaAcceptingStates.add(getIndexOfSet(startState, dfaStates));
|
||||
}
|
||||
|
||||
|
|
@ -372,15 +436,13 @@ public class NFAImpl implements NFA {
|
|||
|
||||
NFAImpl newDFA = new NFAImpl("0");
|
||||
|
||||
for(int i=1;i<dfaStates.size();i++){
|
||||
newDFA.states.add(""+i);
|
||||
for (int i = 0; i < dfaStates.size(); i++) {
|
||||
newDFA.states.add("" + i);
|
||||
}
|
||||
|
||||
newDFA.addAllTransitions(dfaTransitions);
|
||||
newDFA.addAllAcceptingStates(dfaAcceptingStates);
|
||||
|
||||
newDFA.finalizeAutomaton();
|
||||
|
||||
return newDFA;
|
||||
}
|
||||
|
||||
|
|
@ -422,13 +484,13 @@ public class NFAImpl implements NFA {
|
|||
return false;
|
||||
}
|
||||
|
||||
private String getIndexOfSet(Set<String> set, List<Set<String>> dfaStates){
|
||||
private String getIndexOfSet(Set<String> set, List<Set<String>> dfaStates) {
|
||||
return Integer.toString(dfaStates.indexOf(set));
|
||||
}
|
||||
|
||||
private String changeIfNecessary(String str, Set<String> toCheck){
|
||||
while(toCheck.contains(str)){
|
||||
str = str+"|";
|
||||
private String changeIfNecessary(String str, Set<String> toCheck) {
|
||||
while (toCheck.contains(str)) {
|
||||
str = str + "1";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue