Added FiniteStateMachineTest
This commit is contained in:
		
							parent
							
								
									d58c4d8d3b
								
							
						
					
					
						commit
						0f6aa288d6
					
				
							
								
								
									
										8
									
								
								pom.xml
								
								
								
								
							
							
						
						
									
										8
									
								
								pom.xml
								
								
								
								
							| 
						 | 
				
			
			@ -20,5 +20,13 @@
 | 
			
		|||
            <version>1.18.20</version>
 | 
			
		||||
            <scope>provided</scope>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.junit.jupiter</groupId>
 | 
			
		||||
            <artifactId>junit-jupiter-engine</artifactId>
 | 
			
		||||
            <version>5.7.1</version>
 | 
			
		||||
            <scope>test</scope>
 | 
			
		||||
        </dependency>
 | 
			
		||||
    </dependencies>
 | 
			
		||||
</project>
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +46,10 @@ public class FiniteStateMachine {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public int getStateCount() {
 | 
			
		||||
		return this.states.size();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Set<Transition> getTransitionsStartingAt(State state) {
 | 
			
		||||
		Set<Transition> stateTransitions = new HashSet<>();
 | 
			
		||||
		for (Transition t : this.transitions) {
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +93,7 @@ public class FiniteStateMachine {
 | 
			
		|||
	public boolean isDeterministic() {
 | 
			
		||||
		for (State state : this.states) {
 | 
			
		||||
			for (Symbol symbol : this.alphabet) {
 | 
			
		||||
				if (this.getNextStates(state, symbol).size() > 1) {
 | 
			
		||||
				if (this.getEpsilonClosure(this.getNextStates(state, symbol)).size() > 1) {
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,10 @@ public class State implements Comparable<State> {
 | 
			
		|||
		return this.name.compareTo(o.name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static State of(String name) {
 | 
			
		||||
		return new State(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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,98 @@
 | 
			
		|||
package nl.andrewlalis.grammar_tool.machine;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.grammar_tool.grammar.Symbol;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import static org.junit.jupiter.api.Assertions.*;
 | 
			
		||||
 | 
			
		||||
public class FiniteStateMachineTest {
 | 
			
		||||
	private static final String fsm1 = """
 | 
			
		||||
			-> q0 : "a" -> q1
 | 
			
		||||
			 * q1
 | 
			
		||||
			""";
 | 
			
		||||
	private static final String fsm2 = """
 | 
			
		||||
			-> q0 : "a" -> q1, "b" -> q2
 | 
			
		||||
			   q1 : "a" -> q0, "" -> q2
 | 
			
		||||
			 * q2 : "c" -> q2
 | 
			
		||||
			""";
 | 
			
		||||
	private static final String fsm3 = """
 | 
			
		||||
			-> q0 : "a" -> q1, "b" -> q2
 | 
			
		||||
			   q1 : "a" -> q0, "" -> q2, "c" -> q3
 | 
			
		||||
			 * q2 : "c" -> q2
 | 
			
		||||
			   q3 : "b" -> q2, "" -> q0
 | 
			
		||||
			""";
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testFromString() {
 | 
			
		||||
		FiniteStateMachine f1 = FiniteStateMachine.fromString(fsm1);
 | 
			
		||||
		FiniteStateMachine f1Eq = FiniteStateMachine.fromTransitions(
 | 
			
		||||
				State.of("q0"),
 | 
			
		||||
				Set.of(new Transition(State.of("q0"), Symbol.of("a"), State.of("q1"))),
 | 
			
		||||
				Set.of(State.of("q1"))
 | 
			
		||||
		);
 | 
			
		||||
		assertEquals(f1, f1Eq);
 | 
			
		||||
		FiniteStateMachine f2 = FiniteStateMachine.fromString(fsm2);
 | 
			
		||||
		FiniteStateMachine f2Eq = FiniteStateMachine.fromTransitions(
 | 
			
		||||
				State.of("q0"),
 | 
			
		||||
				Set.of(
 | 
			
		||||
						new Transition(State.of("q0"), Symbol.of("a"), State.of("q1")),
 | 
			
		||||
						new Transition(State.of("q0"), Symbol.of("b"), State.of("q2")),
 | 
			
		||||
						new Transition(State.of("q1"), Symbol.of("a"), State.of("q0")),
 | 
			
		||||
						new Transition(State.of("q1"), Symbol.EMPTY, State.of("q2")),
 | 
			
		||||
						new Transition(State.of("q2"), Symbol.of("c"), State.of("q2"))
 | 
			
		||||
				),
 | 
			
		||||
				Set.of(State.of("q2"))
 | 
			
		||||
		);
 | 
			
		||||
		assertEquals(f2, f2Eq);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testGetTransitionsStartingAt() {
 | 
			
		||||
		FiniteStateMachine f1 = FiniteStateMachine.fromString(fsm1);
 | 
			
		||||
		Set<Transition> t0 = f1.getTransitionsStartingAt(State.of("q0"));
 | 
			
		||||
		assertEquals(t0, Set.of(new Transition(State.of("q0"), Symbol.of("a"), State.of("q1"))));
 | 
			
		||||
		Set<Transition> t1 = f1.getTransitionsStartingAt(State.of("q1"));
 | 
			
		||||
		assertEquals(t1, Set.of());
 | 
			
		||||
		FiniteStateMachine f2 = FiniteStateMachine.fromString(fsm2);
 | 
			
		||||
		Set<Transition> t2 = f2.getTransitionsStartingAt(State.of("q0"));
 | 
			
		||||
		assertEquals(t2, Set.of(
 | 
			
		||||
				new Transition(State.of("q0"), Symbol.of("a"), State.of("q1")),
 | 
			
		||||
				new Transition(State.of("q0"), Symbol.of("b"), State.of("q2"))
 | 
			
		||||
		));
 | 
			
		||||
		assertEquals(2, f2.getTransitionsStartingAt(State.of("q1")).size());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testIsDeterministic() {
 | 
			
		||||
		assertTrue(FiniteStateMachine.fromString(fsm1).isDeterministic());
 | 
			
		||||
		assertFalse(FiniteStateMachine.fromString(fsm2).isDeterministic());
 | 
			
		||||
		assertFalse(FiniteStateMachine.fromString(fsm3).isDeterministic());
 | 
			
		||||
		assertTrue(FiniteStateMachine.fromString(fsm2).toDeterministic().isDeterministic());
 | 
			
		||||
		assertTrue(FiniteStateMachine.fromString(fsm3).toDeterministic().isDeterministic());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testToDeterministic() {
 | 
			
		||||
		String nfsm1 = """
 | 
			
		||||
				-> q0 : "" -> q1, "b" -> q2
 | 
			
		||||
				   q1 : "a" -> q2, "c" -> q1
 | 
			
		||||
				   q2 : "d" -> q2, "d" -> q3
 | 
			
		||||
				 * q3 : "c" -> q0
 | 
			
		||||
				""";
 | 
			
		||||
		String dfsm1 = """
 | 
			
		||||
				-> q0 : "a" -> q2, "b" -> q2, "c" -> q1
 | 
			
		||||
				q1 : "a" -> q2, "c" -> q1
 | 
			
		||||
				q2 : "d" -> q3
 | 
			
		||||
				* q3 : "c" -> q0, "d" -> q3
 | 
			
		||||
				""";
 | 
			
		||||
		FiniteStateMachine f1 = FiniteStateMachine.fromString(nfsm1);
 | 
			
		||||
		assertFalse(f1.isDeterministic());
 | 
			
		||||
		FiniteStateMachine d1 = FiniteStateMachine.fromString(dfsm1);
 | 
			
		||||
		assertTrue(d1.isDeterministic());
 | 
			
		||||
		FiniteStateMachine f1ToD1 = f1.toDeterministic();
 | 
			
		||||
		assertEquals(d1.getStateCount(), f1ToD1.getStateCount());
 | 
			
		||||
		assertTrue(f1ToD1.isDeterministic());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue