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>
|
<version>1.18.20</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</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>
|
</dependencies>
|
||||||
</project>
|
</project>
|
|
@ -46,6 +46,10 @@ public class FiniteStateMachine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getStateCount() {
|
||||||
|
return this.states.size();
|
||||||
|
}
|
||||||
|
|
||||||
public Set<Transition> getTransitionsStartingAt(State state) {
|
public Set<Transition> getTransitionsStartingAt(State state) {
|
||||||
Set<Transition> stateTransitions = new HashSet<>();
|
Set<Transition> stateTransitions = new HashSet<>();
|
||||||
for (Transition t : this.transitions) {
|
for (Transition t : this.transitions) {
|
||||||
|
@ -89,7 +93,7 @@ public class FiniteStateMachine {
|
||||||
public boolean isDeterministic() {
|
public boolean isDeterministic() {
|
||||||
for (State state : this.states) {
|
for (State state : this.states) {
|
||||||
for (Symbol symbol : this.alphabet) {
|
for (Symbol symbol : this.alphabet) {
|
||||||
if (this.getNextStates(state, symbol).size() > 1) {
|
if (this.getEpsilonClosure(this.getNextStates(state, symbol)).size() > 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,10 @@ public class State implements Comparable<State> {
|
||||||
return this.name.compareTo(o.name);
|
return this.name.compareTo(o.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static State of(String name) {
|
||||||
|
return new State(name);
|
||||||
|
}
|
||||||
|
|
||||||
public static State of(Set<State> states) {
|
public static State of(Set<State> states) {
|
||||||
if (states.isEmpty()) throw new IllegalArgumentException("Cannot construct state of empty states.");
|
if (states.isEmpty()) throw new IllegalArgumentException("Cannot construct state of empty states.");
|
||||||
if (states.size() == 1) return states.stream().findAny().get();
|
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