diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index a59a0a3..b8993e6 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,23 +4,14 @@
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
@@ -282,7 +273,23 @@
1704888180655
-
+
+
+ 1704914901826
+
+
+
+ 1704914901826
+
+
+
+ 1704914909876
+
+
+
+ 1704914909876
+
+
@@ -307,7 +314,8 @@
-
+
+
diff --git a/src/main/java/ab1/impl/GRUPPE/NFAImpl.java b/src/main/java/ab1/impl/gruppe10_aigensberger_dworski_walcher/NFAImpl.java
similarity index 84%
rename from src/main/java/ab1/impl/GRUPPE/NFAImpl.java
rename to src/main/java/ab1/impl/gruppe10_aigensberger_dworski_walcher/NFAImpl.java
index 15c1b90..08cfa8c 100644
--- a/src/main/java/ab1/impl/GRUPPE/NFAImpl.java
+++ b/src/main/java/ab1/impl/gruppe10_aigensberger_dworski_walcher/NFAImpl.java
@@ -1,4 +1,4 @@
-package ab1.impl.GRUPPE;
+package ab1.impl.gruppe10_aigensberger_dworski_walcher;
import ab1.FinalizedStateException;
import ab1.NFA;
@@ -7,6 +7,9 @@ import ab1.Transition;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
+/**
+ * Implementation of the NFA interface.
+ */
public class NFAImpl implements NFA {
private final Set states;
private final Set transitions;
@@ -39,14 +42,6 @@ public class NFAImpl implements NFA {
return this.states;
}
- /*
- public void safeAddStates(Set states, Set toCheck, NFAImpl nfa) {
- for (String state : states) {
- nfa.states.add(changeIfNecessary(state, toCheck));
- }
- }
- */
-
@Override
public Collection getTransitions() {
return this.transitions;
@@ -66,24 +61,35 @@ public class NFAImpl implements NFA {
return this.alphabet;
}
+
+ /**
+ * Adds a new transition to the automaton. If the automaton is already finalized, a FinalizedStateException is thrown.
+ * @param transition The transition to add
+ * @throws FinalizedStateException
+ */
@Override
public void addTransition(Transition transition) throws FinalizedStateException {
if (this.isFinalized) {
throw new FinalizedStateException();
}
- if (!states.contains(transition.fromState())) {
- this.states.add(transition.fromState());
+ if (transition == null || transition.fromState() == null || transition.toState() == null) {
+ throw new IllegalArgumentException();
}
- if (!states.contains(transition.toState())) {
- this.states.add(transition.toState());
+
+ states.add(transition.fromState());
+ states.add(transition.toState());
+
+ if (transition.readSymbol()!=null) {
+ alphabet.add(transition.readSymbol());
}
- // add symbol to alphabet. If it is already in the alphabet, nothing happens
- if (transition.readSymbol() != null) {
- this.alphabet.add(transition.readSymbol());
- }
- this.transitions.add(transition);
+ transitions.add(transition);
}
+ /**
+ * Adds all transitions to the automaton. If the automaton is already finalized, a FinalizedStateException is thrown.
+ * @param transitions The Set of transitions to add
+ * @throws FinalizedStateException
+ */
public void addAllTransitions(Set transitions) throws FinalizedStateException {
if (this.isFinalized) {
throw new FinalizedStateException();
@@ -93,49 +99,79 @@ public class NFAImpl implements NFA {
}
}
+ /**
+ * Adds a new accepting state to the automaton. If the automaton is already finalized, a FinalizedStateException is thrown.
+ * @param state The state to add as accepting state
+ * @throws FinalizedStateException
+ */
@Override
public void addAcceptingState(String state) throws FinalizedStateException {
if (this.isFinalized) {
throw new FinalizedStateException();
}
+ if (state == null) {
+ throw new IllegalArgumentException();
+ }
this.states.add(state);
this.acceptingStates.add(state);
}
+ /**
+ * Adds all accepting states to the automaton. If the automaton is already finalized, a FinalizedStateException is thrown.
+ * @param states The Set of states to add as accepting states
+ * @throws FinalizedStateException
+ */
public void addAllAcceptingStates(Set states) throws FinalizedStateException {
if (this.isFinalized) {
throw new FinalizedStateException();
}
+ if (states == null) {
+ throw new IllegalArgumentException();
+ }
for (String state : states) {
this.addAcceptingState(state);
}
}
+ /**
+ * Adds a new state to the automaton. If the automaton is already finalized, a FinalizedStateException is thrown.
+ * If the state already exists, the state is renamed to state1, state11, state111, etc. until a unique name is found.
+ * @param states The Set of states to add
+ * @param toCheck The Set of states to check for duplicates
+ * @param nfa The NFA to add the states to
+ */
public void safeAddAcceptingStates(Set states, Set toCheck, NFAImpl nfa) {
+ if (this.isFinalized) {
+ throw new FinalizedStateException();
+ }
+ if(states == null || toCheck == null || nfa == null){
+ throw new IllegalArgumentException();
+ }
for (String state : states) {
nfa.addAcceptingState(changeIfNecessary(state, toCheck));
}
}
- // #TODO
- // write more testcases
+ /**
+ * Creates a new NFA that is the union of this NFA and the other NFA. If either of the NFAs is not finalized, a FinalizedStateException is thrown.
+ * @param other The other NFA to union with
+ * @return The union of this NFA and the other NFA
+ * @throws FinalizedStateException
+ */
@Override
public NFA union(NFA other) throws FinalizedStateException {
if (!this.isFinalized || !other.isFinalized()) {
throw new FinalizedStateException();
}
- // new initialState with epsilon to initialState of this and other.
- // Problem: what if states are called the same in this and other + what do we use as initialState?
+
NFAImpl unionNFA = new NFAImpl(this.getInitialState());
unionNFA.states.addAll(this.states);
-
unionNFA.addAllAcceptingStates(this.acceptingStates);
Set otherAcceptingStates = new HashSet<>(other.getAcceptingStates());
unionNFA.safeAddAcceptingStates(this.acceptingStates, otherAcceptingStates, unionNFA);
-
Set newTransitions = new HashSet<>();
for (Transition transition : other.getTransitions()) {
Transition newTransition =
@@ -152,14 +188,9 @@ public class NFAImpl implements NFA {
unionNFA.acceptingStates.add(state);
}
} else {
- // a state of other has the same name as one in this.
- // change name of state and every Transition it is a part of in other
String newState = changeIfNecessary(state, unionNFA.states);
-
- // wieder a neues set
Set tempTransitions = new HashSet<>();
- // check each transition of other if start or to state was state
for (Transition transition : newTransitions) {
if (transition.fromState().equals(state)) {
transition = new Transition(newState, transition.readSymbol(), transition.toState());
@@ -169,16 +200,15 @@ public class NFAImpl implements NFA {
}
tempTransitions.add(transition);
}
+
for (String accState : other.getAcceptingStates()) {
if (accState.equals(state)) {
unionNFA.acceptingStates.add(newState);
}
}
- newTransitions = tempTransitions; // Replace the original set with the updated set
+ newTransitions = tempTransitions;
}
}
- // add, alphabet
-
Iterator iterator = newTransitions.iterator();
while (iterator.hasNext()){
Transition transition = iterator.next();
@@ -191,17 +221,18 @@ public class NFAImpl implements NFA {
}
unionNFA.addAllTransitions(newTransitions);
-
unionNFA.addAllTransitions(this.transitions);
-
unionNFA.finalizeAutomaton();
-
return unionNFA;
}
- // #TODO
- // needs to work with a DFA not NFA
+ /**
+ * Creates a new NFA that is the intersection of this NFA and the other NFA. If either of the NFAs is not finalized, a FinalizedStateException is thrown.
+ * @param other The other NFA to intersect with
+ * @return The intersection of this NFA and the other NFA
+ * @throws FinalizedStateException
+ */
@Override
public NFA intersection(NFA other) throws FinalizedStateException {
if (!this.isFinalized || !other.isFinalized()) {
@@ -213,6 +244,12 @@ public class NFAImpl implements NFA {
return unionNFA.complement();
}
+ /**
+ * Creates a new NFA that is the concatenation of this NFA and the other NFA. If either of the NFAs is not finalized, a FinalizedStateException is thrown.
+ * @param other The other NFA to concatenate with
+ * @return The concatenation of this NFA and the other NFA
+ * @throws FinalizedStateException
+ */
@Override
public NFA concatenation(NFA other) throws FinalizedStateException {
if (!this.isFinalized || !other.isFinalized()) {
@@ -221,10 +258,8 @@ public class NFAImpl implements NFA {
NFAImpl concatenationNFA = new NFAImpl(this.initialState);
- // Add states from 'this'
concatenationNFA.states.addAll(this.states);
- // Add states from 'other', with renaming if necessary
Map renamedStates = new HashMap<>();
for (String state : other.getStates()) {
String newState = changeIfNecessary(state, concatenationNFA.states);
@@ -232,10 +267,8 @@ public class NFAImpl implements NFA {
concatenationNFA.states.add(newState);
}
- // Add transitions from 'this'
concatenationNFA.transitions.addAll(this.transitions);
- // Add transitions from 'other', updating state names
for (Transition transition : other.getTransitions()) {
String newFromState = renamedStates.getOrDefault(transition.fromState(), transition.fromState());
String newToState = renamedStates.getOrDefault(transition.toState(), transition.toState());
@@ -243,14 +276,12 @@ public class NFAImpl implements NFA {
concatenationNFA.transitions.add(newTransition);
}
- // Connect accepting states of 'this' to the initial state of 'other' with epsilon transitions
String newOtherInitialState = renamedStates.getOrDefault(other.getInitialState(), other.getInitialState());
for (String acceptingState : this.acceptingStates) {
Transition epsilon = new Transition(acceptingState, null, newOtherInitialState);
concatenationNFA.transitions.add(epsilon);
}
- // Set accepting states of the concatenated NFA to be the accepting states of 'other'
concatenationNFA.acceptingStates.clear();
for (String acceptingState : other.getAcceptingStates()) {
concatenationNFA.acceptingStates.add(renamedStates.getOrDefault(acceptingState, acceptingState));
@@ -261,7 +292,11 @@ public class NFAImpl implements NFA {
return concatenationNFA;
}
-
+ /**
+ * Creates a new NFA that is the Kleene star of this NFA. If the NFA is not finalized, a FinalizedStateException is thrown.
+ * @return The Kleene star of this NFA
+ * @throws FinalizedStateException
+ */
@Override
public NFA kleeneStar() throws FinalizedStateException {
if (!this.isFinalized) {
@@ -270,17 +305,13 @@ public class NFAImpl implements NFA {
NFAImpl nfa = new NFAImpl(this.initialState);
- // copy, but without accepting states
nfa.states.addAll(this.states);
nfa.addAllTransitions(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.getAcceptingStates()) {
Transition loopBackTransition =
- // creating an epsilon transition (null) for each accepting state
new Transition(acceptingState, null, this.initialState);
nfa.transitions.add(loopBackTransition);
}
@@ -290,6 +321,11 @@ public class NFAImpl implements NFA {
return nfa;
}
+ /**
+ * Creates a new NFA that is the plus operator of this NFA. If the NFA is not finalized, a FinalizedStateException is thrown.
+ * @return The plus operator of this NFA
+ * @throws FinalizedStateException
+ */
@Override
public NFA plusOperator() throws FinalizedStateException {
if (!this.isFinalized) {
@@ -299,55 +335,41 @@ public class NFAImpl implements NFA {
String newInitialState = "newSTART";
NFAImpl nfa = new NFAImpl(newInitialState);
- // simple copy
nfa.states.addAll(this.states);
nfa.transitions.addAll(this.transitions);
nfa.acceptingStates.addAll(this.acceptingStates);
nfa.transitions.add(new Transition(newInitialState, null, this.initialState));
-
for (String acceptingState : this.acceptingStates) {
nfa.transitions.add(new Transition(acceptingState, null, newInitialState));
}
- /*
- // 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);
- }
- }
- */
-
nfa.finalizeAutomaton();
return nfa;
}
- // #TODO
+ /**
+ * Creates a new NFA that is the complement of this NFA. If the NFA is not finalized, a FinalizedStateException is thrown.
+ * @return The complement of this NFA
+ * @throws FinalizedStateException
+ */
@Override
public NFA complement() throws FinalizedStateException {
if (!this.isFinalized) {
throw new FinalizedStateException();
}
- // create a copy of this NFA
NFAImpl nfa = new NFAImpl(this.initialState);
nfa.states.addAll(this.states);
nfa.addAllTransitions(this.transitions);
nfa.addAllAcceptingStates(this.acceptingStates);
- nfaAddTrap(nfa); //error on last occasion
+ nfaAddTrap(nfa);
NFAImpl fakeNFA = convertNFAtoDFA(nfa);
- // state -> accepting
- // accepting -> state
-
Set newAcceptingState = new HashSet<>();
for (String state : fakeNFA.getStates()) {
@@ -355,38 +377,42 @@ public class NFAImpl implements NFA {
newAcceptingState.add(state);
}
}
+
fakeNFA.acceptingStates.clear();
fakeNFA.addAllAcceptingStates(newAcceptingState);
-
fakeNFA.finalizeAutomaton();
return fakeNFA;
}
+ /**
+ * Returns whether the automaton is finalized.
+ * @return Whether the automaton is finalized
+ */
@Override
public boolean isFinalized() {
return isFinalized;
}
+ /**
+ * Finalizes the automaton. After finalization, no further states or transitions can be added.
+ */
@Override
public void finalizeAutomaton() {
this.isFinalized = true;
}
- // #TODO
+ /**
+ * Returns whether the automaton is finite. An automaton is finite if it has a finite number of states and no loops, that have a path to an accepting state.
+ * @return Whether the automaton is finite
+ */
@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)
-
- //how do we get an infinite language?
- //we need to have a loop, how can we check:
List path = new ArrayList<>();
List transitions= new ArrayList<>(this.getTransitions());
- AtomicInteger finished = new AtomicInteger(0); //0=unfinished, 1=finite, 2 = infinite
- List letters = new ArrayList<>(this.alphabet); // letters is alphabet with epsilon (null)
+ AtomicInteger finished = new AtomicInteger(0);
+ List letters = new ArrayList<>(this.alphabet);
if(this.alphabet.isEmpty()){
return true;
}
@@ -394,7 +420,6 @@ public class NFAImpl implements NFA {
letters.add(null);
}
- // EndTuple hast firstElement = a //doesn´t matter at all aktually
path.add(new Tuple('a', this.initialState));
if(fillToEnd(path, transitions, letters, finished)){
return false;
@@ -409,7 +434,6 @@ public class NFAImpl implements NFA {
}
System.out.println("ERROR-isFinite method isn´t running right!");
return true;
- //return continueOnLastTuple(path, transitions, letters);
}
private void continueOnLastTuple(List path, List transitions, List letters, AtomicInteger finished) {
diff --git a/src/test/java/ab1/tests/GRUPPE/betterSimpleTests.java b/src/test/java/ab1/tests/GRUPPE/betterSimpleTests.java
index b529cec..ab93e24 100644
--- a/src/test/java/ab1/tests/GRUPPE/betterSimpleTests.java
+++ b/src/test/java/ab1/tests/GRUPPE/betterSimpleTests.java
@@ -18,8 +18,7 @@ public class betterSimpleTests {
@Test
public void invalidAcceptingState() {
var instance = factory.buildNFA("START");
- instance.addAcceptingState(null);
- assertEquals(0, instance.getAcceptingStates().size());
+ assertThrows(IllegalArgumentException.class, () -> instance.addAcceptingState(null));
}
@Test
diff --git a/target/classes/ab1/Transition$TransitionBuilder.class b/target/classes/ab1/Transition$TransitionBuilder.class
index 8deddb3..6a10a5f 100644
Binary files a/target/classes/ab1/Transition$TransitionBuilder.class and b/target/classes/ab1/Transition$TransitionBuilder.class differ
diff --git a/target/classes/ab1/Transition.class b/target/classes/ab1/Transition.class
index 55ad5d1..d83e6b5 100644
Binary files a/target/classes/ab1/Transition.class and b/target/classes/ab1/Transition.class differ
diff --git a/target/classes/ab1/impl/GRUPPE/NFAFactoryImpl.class b/target/classes/ab1/impl/GRUPPE/NFAFactoryImpl.class
deleted file mode 100644
index dab8ab8..0000000
Binary files a/target/classes/ab1/impl/GRUPPE/NFAFactoryImpl.class and /dev/null differ
diff --git a/target/test-classes/ab1/NFAProvider.class b/target/test-classes/ab1/NFAProvider.class
index 054610b..ad85577 100644
Binary files a/target/test-classes/ab1/NFAProvider.class and b/target/test-classes/ab1/NFAProvider.class differ
diff --git a/target/test-classes/ab1/tests/FinalizeTests.class b/target/test-classes/ab1/tests/FinalizeTests.class
index 17e959c..1057baf 100644
Binary files a/target/test-classes/ab1/tests/FinalizeTests.class and b/target/test-classes/ab1/tests/FinalizeTests.class differ