Skip to content

Commit

Permalink
feat: implement NFA class with acceptance checking and transition han…
Browse files Browse the repository at this point in the history
…dling
  • Loading branch information
Tony0380 committed Nov 3, 2024
1 parent 0ff5fdf commit f8508c7
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 3 deletions.
6 changes: 3 additions & 3 deletions app/src/main/java/computability/calculation/model/DFA.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import java.util.List;

public class DFA implements Serializable{
final private List<State> States;
final private List<Transiction> Transictions;
private State startState;
final protected List<State> States;
final protected List<Transiction> Transictions;
protected State startState;

/**
* Create a new DFA with no states or transictions.
Expand Down
56 changes: 56 additions & 0 deletions app/src/main/java/computability/calculation/model/NFA.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,61 @@
package computability.calculation.model;

import java.util.ArrayList;
import java.util.List;

public class NFA extends DFA {


@Override
/**
* Check if the given string is accepted by the NFA.
* @param input The string to check.
*/
public boolean accepts(String input) {
if (startState == null || Transictions.isEmpty() || States.isEmpty()) {
if (startState == null) {
System.out.println("Start state is not set");
}
return false;
}
State currentState = startState;
return accept(input, currentState);
}


/**
* Check if the given string is accepted by the NFA.
* @param input The string to check.
* @param state The current state of the NFA.
* @return True if the string is accepted, false otherwise.
*/
public boolean accept(String input, State state) {
if (input.isEmpty()) {
return state.isAccepting();
}
List<State> nextStates = getNexStates(state, input.charAt(0));
for (State nextState : nextStates) {
if (accept(input.substring(1), nextState)) {
return true;
}
}
return false;
}

/**
* Get the next states of the given state and symbol.
* @param state The state to get the next states for.
* @param symbol The symbol to get the next states for.
* @return The next states of the given state and symbol.
*/
public List<State> getNexStates(State state, char symbol) {
List<State> nextStates = new ArrayList<>();
for (Transiction t : Transictions) {
if (t.getStart().equals(state) && (t.getSymbol() == symbol || t.getSymbol() == '$')) {
nextStates.add(t.getEnd());
}
}
return nextStates;
}

}
62 changes: 62 additions & 0 deletions app/src/test/java/computability/nfaTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package computability;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import computability.calculation.model.NFA;
import computability.calculation.model.State;


/**
* Test class for the NFA class.
* This class test the regular language {@code {a,b}* | w ends with abb} using a NFA.
*/
public class nfaTest {

private NFA nfa;

@BeforeEach
public void setUp() {
nfa = new NFA();
State q0 = new State("q0");
State q1 = new State("q1");
State q2 = new State("q2");
State q3 = new State("q3");

q3.setAccepting(true);

nfa.setStartState(q0);
nfa.addState(q1);
nfa.addState(q2);
nfa.addState(q3);

nfa.addTransiction(q0, q0, 'a');
nfa.addTransiction(q0, q0, 'b');
nfa.addTransiction(q0, q0, 'c');

nfa.addTransiction(q0, q1, 'a');
nfa.addTransiction(q1, q2, 'b');
nfa.addTransiction(q2, q3, 'b');



}

@Test
public void testNFA() {
assert(nfa.accepts("abb"));
assert(nfa.accepts("ababb"));
assert(nfa.accepts("abababb"));
assert(nfa.accepts("ababababb"));
assert(nfa.accepts("abababababb"));


assert(!nfa.accepts("a"));
assert(!nfa.accepts("b"));
assert(!nfa.accepts("ab"));
assert(!nfa.accepts("ba"));
assert(!nfa.accepts("abab"));
assert(!nfa.accepts("abba"));
}

}

0 comments on commit f8508c7

Please sign in to comment.