This repository has been archived on 2026-04-20. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
theorethische-informatik-gr.../src/main/java/ab1/impl/GRUPPE/NFAImpl.java
2024-01-08 12:02:10 +01:00

405 lines
13 KiB
Java

package ab1.impl.GRUPPE;
import ab1.FinalizedStateException;
import ab1.NFA;
import ab1.NFAFactory;
import ab1.Transition;
import lombok.Getter;
import java.util.*;
public class NFAImpl implements NFA {
private Set<String> states;
private Set<Transition> transitions;
private String initialState;
private Set<String> acceptingStates;
@Getter
private Set<Character> alphabet;
private boolean isFinalized;
public NFAImpl(String startState) {
this.initialState = startState;
this.states = new HashSet<>();
this.states.add(startState);
this.transitions = new HashSet<>();
this.acceptingStates = new HashSet<>();
this.alphabet = new HashSet<>();
this.isFinalized = false;
}
@Override
public Set<String> getStates() {
return this.states;
}
@Override
public Collection<Transition> getTransitions() {
return this.transitions;
}
@Override
public Set<String> getAcceptingStates() {
return this.acceptingStates;
}
@Override
public String getInitialState() {
return this.initialState;
}
@Override
public void addTransition(Transition transition) throws FinalizedStateException {
if (this.isFinalized) {
throw new FinalizedStateException();
} else if (!this.transitions.contains(transition)) {
// add symbol to alphabet. If it is already in the alphabet, nothing happens
this.alphabet.add(transition.readSymbol());
this.transitions.add(transition);
}
}
@Override
public void addAcceptingState(String state) throws FinalizedStateException {
if (this.isFinalized) {
throw new FinalizedStateException();
} else if (!this.states.contains(state)) {
this.states.add(state);
this.acceptingStates.add(state);
}
}
// #TODO
@Override
public NFA union(NFA other) throws FinalizedStateException {
if(!this.isFinalized || !other.isFinalized()){
throw new FinalizedStateException();
}
NFAImpl unionNFA = new NFAImpl(this.initialState);
unionNFA.states.addAll(this.states);
unionNFA.states.addAll(other.getStates());
unionNFA.transitions.addAll(this.transitions);
unionNFA.transitions.addAll(other.getTransitions());
return unionNFA;
}
// #TODO
@Override
public NFA intersection(NFA other) throws FinalizedStateException {
if(!this.isFinalized || !other.isFinalized()){
throw new FinalizedStateException();
}
NFAImpl intersectionNFA = new NFAImpl(this.initialState);
intersectionNFA.states.addAll(this.states);
intersectionNFA.states.retainAll(other.getStates());
intersectionNFA.transitions.addAll(this.transitions);
intersectionNFA.transitions.retainAll(other.getTransitions());
return intersectionNFA;
}
// #TODO
@Override
public NFA concatenation(NFA other) throws FinalizedStateException {
if(!this.isFinalized || !other.isFinalized()){
throw new FinalizedStateException();
}
NFAImpl concatenationNFA = new NFAImpl(this.initialState);
concatenationNFA.states.addAll(this.states);
concatenationNFA.states.addAll(other.getStates());
concatenationNFA.transitions.addAll(this.transitions);
concatenationNFA.transitions.addAll(other.getTransitions());
for(String accceptingState : this.acceptingStates){
Transition epsilon = new Transition(accceptingState, null, other.getInitialState());
concatenationNFA.transitions.add(epsilon);
}
return concatenationNFA;
}
@Override
public NFA kleeneStar() throws FinalizedStateException {
if (!this.isFinalized) {
throw new FinalizedStateException();
}
NFAImpl nfa = new NFAImpl(this.initialState);
// copy, but without accepting states
nfa.states.addAll(this.states);
nfa.transitions.addAll(this.transitions);
// adding the initial state as accepting state because we have to accept the empty string
nfa.acceptingStates.add(this.initialState);
// for each accepting state
for (String acceptingState : this.acceptingStates) {
Transition loopBackTransition =
// creating an epsilon transition (null) for each accepting state
new Transition(acceptingState, null, this.initialState);
if (!nfa.transitions.contains(loopBackTransition)) {
nfa.transitions.add(loopBackTransition);
}
}
return nfa;
}
@Override
public NFA plusOperator() throws FinalizedStateException {
if (!this.isFinalized) {
throw new FinalizedStateException();
}
NFAImpl nfa = new NFAImpl(this.initialState);
// simple copy
nfa.states.addAll(this.states);
nfa.transitions.addAll(this.transitions);
nfa.acceptingStates.addAll(this.acceptingStates);
// for each accepting state
for (String acceptingState : this.acceptingStates) {
Transition loopBackTransition =
// creating an epsilon transition (null) for each accepting state
new Transition(acceptingState, null, this.initialState);
if (!nfa.transitions.contains(loopBackTransition)) {
nfa.transitions.add(loopBackTransition);
}
}
return nfa;
}
// #TODO
@Override
public NFA complement() throws FinalizedStateException {
if(!this.isFinalized){
throw new FinalizedStateException();
}
NFAImpl complementNFA = new NFAImpl(this.initialState);
complementNFA.states.addAll(this.states);
complementNFA.transitions.addAll(this.transitions);
/*
for(String state : this.states){
}
*/
return null;
}
@Override
public boolean isFinalized() {
return isFinalized;
}
@Override
public void finalizeAutomaton() {
this.isFinalized = true;
}
// #TODO
@Override
public boolean isFinite() {
//transitions={fromState==toState}
//states={A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}
//obergrenze = anzahl der states (26)
return false;
}
// #TODO
@Override
public boolean acceptsWord(String word) throws FinalizedStateException {
//check if word is accepted
return false;
}
public NFA convertNFAtoDFA (NFAImpl input){
/*
What do we need to do?
Helper Methods:
- epsilonClosure
- getStateAfterTransition
- determineAcceptingStates
*/
// all states of the DFA
List<Set<String>> dfaStates = new ArrayList<>();
// all transitions of the DFA
Set<Transition> dfaTransitions = new HashSet<>();
// all states of the NFA
Set<String> startState = new HashSet<>();
startState.add(input.getInitialState());
// getting the epsilon closure of the start state
startState = epsilonClosure(startState, input);
dfaStates.add(startState);
// find all letters in transitions
// obsolete, added alphabet to NFA which stores all read symbols
/*
Set<Character> possibleLetters = new HashSet<>();
Set<Transition> possibleTransitions = new HashSet<>();
for(Transition transition : input.transitions){
for(String state : states) {
if (state.equals(transition.fromState())){
if(transition.readSymbol() != null){
possibleLetters.add(transition.readSymbol());
possibleTransitions.add(transition);
}
break;
}
}
}
*/
// do the above with each DFA state
Queue<Set<String>> queue = new LinkedList<>();
queue.add(startState);
// iterate each Letter
while (!queue.isEmpty()){
Set<String> currentState = queue.poll();
// for each possible Letter
for (char letter : input.getAlphabet()) {
// get the new state after the transition
Set<String> newState = epsilonClosure(getStateAfterTransition(currentState, letter, input), input);
if (!dfaStates.contains(newState)) {
queue.add(newState);
dfaStates.add(newState);
// build new Transition
}
// build new Transition
dfaTransitions.add(new Transition(Integer.toString(dfaStates.indexOf(currentState)), letter, Integer.toString(dfaStates.indexOf(newState))));
// we gotta change this to only a string is given
//dfaTransitions.add(new Transition(currentState, letter, newState));
}
}
/*
for(Character letter : possibleLetters){
Set<String> newState = new HashSet<>();
for(Transition trans : possibleTransitions){
if(trans.readSymbol().equals(letter)){
// is every transition fromState = state from states? Hoffentlich ja :')
newState.add(trans.toState());
}
}
//deal with newState + new Transitions
if(DFA_states.contains(newState)){
Transition newtrans = new Transition(DFA_states.get(index), letter, DFA_states.get(DFA_states.indexOf(newState)));
}
}
*/
// what we gonna do now?
return null;
// return new DFA(dfaStates, dfaTransitions, startState, determineAcceptingStates(dfaStates, input));
}
private Set<String> epsilonClosure(Set<String> states, NFA nfa) {
/*
Original:
boolean isAccepting = false;
int index = 0;
List<Set<String>> DFA_states = new ArrayList<>();
Set<Transition> DFA_transitions = new HashSet<>();
// start state alle verbindungen mit epsilon als set
for(String state : states) {
for (Transition transition : input.transitions) {
if (state.equals(transition.fromState()) && transition.readSymbol() == null) {
if(!isAccepting) {
for (String acceptingState : acceptingStates)
if (transition.toState().equals(acceptingState)) {
isAccepting = true;
break;
}
}
states.add(transition.toState());
// funktioniert immer noch, wenn w epsilon Übergänge hintereinander?
}
}
}
DFA_states.add(new HashSet<>(states));
*/
Set<String> closure = new HashSet<>(states);
Stack<String> stack = new Stack<>();
stack.addAll(states);
while (!stack.isEmpty()) {
String state = stack.pop();
for (Transition transition : nfa.getTransitions()) {
if (transition.fromState().equals(state) && transition.readSymbol() == null) {
if (closure.add(transition.toState())) {
stack.push(transition.toState());
}
}
}
}
return closure;
}
private Set<String> getStateAfterTransition(Set<String> states, char symbol, NFA nfa) {
Set<String> result = new HashSet<>();
for (String state : states) {
for (Transition transition : nfa.getTransitions()) {
if (transition.fromState().equals(state) && transition.readSymbol() != null && transition.readSymbol() == symbol) {
result.add(transition.toState());
}
}
}
return result;
}
private Set<Set<String>> determineAcceptingStates(Set<Set<String>> dfaStates, NFA nfa) {
Set<Set<String>> acceptingStates = new HashSet<>();
for (Set<String> dfaState : dfaStates) {
for (String nfaState : dfaState) {
if (nfa.getAcceptingStates().contains(nfaState)) {
acceptingStates.add(dfaState);
break;
}
}
}
return acceptingStates;
}
public void test(){
final NFAFactory factory = new NFAFactoryImpl();
var instance = factory.buildNFA("START");
instance.addTransition(
Transition.builder()
.fromState("START")
.readSymbol('a')
.toState("ACCEPT")
.build()
);
instance.addAcceptingState("ACCEPT");
instance.finalizeAutomaton();
}
}