Added toDFSM method.
This commit is contained in:
		
							parent
							
								
									0741d9d62d
								
							
						
					
					
						commit
						d58c4d8d3b
					
				| 
						 | 
				
			
			@ -20,9 +20,13 @@ public class GrammarTool {
 | 
			
		|||
				-> q0 : "" -> q1, "b" -> q2
 | 
			
		||||
				   q1 : "c" -> q1, "a" -> q2,
 | 
			
		||||
				   q2 : "d" -> q2, "d" -> q3,
 | 
			
		||||
				 * q3 : "c" -> q1
 | 
			
		||||
				 * q3 : "c" -> q0
 | 
			
		||||
				""");
 | 
			
		||||
		System.out.println(f1);
 | 
			
		||||
		System.out.println("Deterministic? " + f1.isDeterministic());
 | 
			
		||||
 | 
			
		||||
		FiniteStateMachine d1 = f1.toDeterministic();
 | 
			
		||||
		System.out.println(d1);
 | 
			
		||||
		System.out.println("Deterministic? " + d1.isDeterministic());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,6 +7,8 @@ import java.util.Objects;
 | 
			
		|||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
public class Symbol implements Comparable<Symbol> {
 | 
			
		||||
	public static final Symbol EMPTY = Symbol.of("");
 | 
			
		||||
 | 
			
		||||
	@Getter
 | 
			
		||||
	private final String identifier;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,10 +2,7 @@ package nl.andrewlalis.grammar_tool.machine;
 | 
			
		|||
 | 
			
		||||
import nl.andrewlalis.grammar_tool.grammar.Symbol;
 | 
			
		||||
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.regex.Matcher;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +46,90 @@ public class FiniteStateMachine {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Set<Transition> getTransitionsStartingAt(State state) {
 | 
			
		||||
		Set<Transition> stateTransitions = new HashSet<>();
 | 
			
		||||
		for (Transition t : this.transitions) {
 | 
			
		||||
			if (t.getStartState().equals(state)) {
 | 
			
		||||
				stateTransitions.add(t);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return stateTransitions;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Set<State> getNextStates(State currentState, Symbol acceptingSymbol) {
 | 
			
		||||
		Set<State> nextStates = new HashSet<>();
 | 
			
		||||
		for (Transition t : this.transitions) {
 | 
			
		||||
			if (t.getStartState().equals(currentState) && t.getAcceptingSymbol().equals(acceptingSymbol)) {
 | 
			
		||||
				nextStates.add(t.getEndState());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nextStates;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Set<State> getNextStates(Set<State> states, Symbol acceptingSymbol) {
 | 
			
		||||
		Set<State> nextStates = new HashSet<>();
 | 
			
		||||
		for (State state : states) {
 | 
			
		||||
			nextStates.addAll(this.getNextStates(state, acceptingSymbol));
 | 
			
		||||
		}
 | 
			
		||||
		return nextStates;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Set<State> getEpsilonClosure(State currentState) {
 | 
			
		||||
		Set<State> nextStates = this.getNextStates(currentState, Symbol.EMPTY);
 | 
			
		||||
		nextStates.add(currentState);
 | 
			
		||||
		return nextStates;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Set<State> getEpsilonClosure(Set<State> states) {
 | 
			
		||||
		Set<State> nextStates = this.getNextStates(states, Symbol.EMPTY);
 | 
			
		||||
		nextStates.addAll(states);
 | 
			
		||||
		return nextStates;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean isDeterministic() {
 | 
			
		||||
		for (State state : this.states) {
 | 
			
		||||
			for (Symbol symbol : this.alphabet) {
 | 
			
		||||
				if (this.getNextStates(state, symbol).size() > 1) {
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public FiniteStateMachine toDeterministic() {
 | 
			
		||||
		Set<State> finalStates = new HashSet<>();
 | 
			
		||||
		Set<Transition> transitions = new HashSet<>();
 | 
			
		||||
		Set<State> startClosure = this.getEpsilonClosure(this.startState);
 | 
			
		||||
		State startState = State.of(startClosure);
 | 
			
		||||
		Deque<Set<State>> stateQueue = new LinkedList<>();
 | 
			
		||||
		Set<Set<State>> visitedClosures = new HashSet<>();
 | 
			
		||||
		stateQueue.add(startClosure);
 | 
			
		||||
		while (!stateQueue.isEmpty()) {
 | 
			
		||||
			Set<State> currentClosure = stateQueue.pop();
 | 
			
		||||
			visitedClosures.add(currentClosure);
 | 
			
		||||
			State combinedState = State.of(currentClosure);
 | 
			
		||||
			for (State state : currentClosure) {
 | 
			
		||||
				if (this.finalStates.contains(state)) {
 | 
			
		||||
					finalStates.add(combinedState);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			for (Symbol symbol : this.alphabet) {
 | 
			
		||||
				if (symbol.isEmpty()) continue;
 | 
			
		||||
				Set<State> nextStates = this.getNextStates(currentClosure, symbol);
 | 
			
		||||
				Set<State> nextStateClosure = this.getEpsilonClosure(nextStates);
 | 
			
		||||
				if (nextStateClosure.isEmpty()) continue;
 | 
			
		||||
				State combinedNextState = State.of(nextStateClosure);
 | 
			
		||||
//				System.out.println(combinedState + " : " + "\"" + symbol + "\" -> " + combinedNextState);
 | 
			
		||||
				transitions.add(new Transition(combinedState, symbol, combinedNextState));
 | 
			
		||||
				if (!visitedClosures.contains(nextStateClosure)) {
 | 
			
		||||
					stateQueue.add(nextStateClosure);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return FiniteStateMachine.fromTransitions(startState, transitions, finalStates);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public boolean equals(Object o) {
 | 
			
		||||
		if (this == o) return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -93,37 +174,6 @@ public class FiniteStateMachine {
 | 
			
		|||
		return sb.toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Set<Transition> getTransitionsStartingAt(State state) {
 | 
			
		||||
		Set<Transition> stateTransitions = new HashSet<>();
 | 
			
		||||
		for (Transition t : this.transitions) {
 | 
			
		||||
			if (t.getStartState().equals(state)) {
 | 
			
		||||
				stateTransitions.add(t);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return stateTransitions;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Set<State> getNextStates(State currentState, Symbol acceptingSymbol) {
 | 
			
		||||
		Set<State> nextStates = new HashSet<>();
 | 
			
		||||
		for (Transition t : this.transitions) {
 | 
			
		||||
			if (t.getStartState().equals(currentState) && t.getAcceptingSymbol().equals(acceptingSymbol)) {
 | 
			
		||||
				nextStates.add(t.getEndState());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nextStates;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean isDeterministic() {
 | 
			
		||||
		for (State state : this.states) {
 | 
			
		||||
			for (Symbol symbol : this.alphabet) {
 | 
			
		||||
				if (this.getNextStates(state, symbol).size() > 1) {
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static FiniteStateMachine fromTransitions(State startState, Set<Transition> transitions, Set<State> finalStates) {
 | 
			
		||||
		Set<Symbol> alphabet = new HashSet<>();
 | 
			
		||||
		Set<State> states = new HashSet<>();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
package nl.andrewlalis.grammar_tool.machine;
 | 
			
		||||
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
public class State implements Comparable<State> {
 | 
			
		||||
	private final String name;
 | 
			
		||||
| 
						 | 
				
			
			@ -31,4 +33,11 @@ public class State implements Comparable<State> {
 | 
			
		|||
	public int compareTo(State o) {
 | 
			
		||||
		return this.name.compareTo(o.name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static State of(Set<State> states) {
 | 
			
		||||
		if (states.isEmpty()) throw new IllegalArgumentException("Cannot construct state of empty states.");
 | 
			
		||||
		if (states.size() == 1) return states.stream().findAny().get();
 | 
			
		||||
		String name = states.stream().sorted().map(State::toString).collect(Collectors.joining(", "));
 | 
			
		||||
		return new State("{" + name + "}");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue