Переход из состояния в состояние в этом автомате через HashMap

Я использую этот метод для перехода от состояния к следующему на этом симуляторе автомата:

public void processString (String string){


StringBuilder stepString= new StringBuilder (string);


int actualStateIntIndex;





 System.out.println("THE FOUND INITIAL ONE IS "+ theInitialStateIntIndex);


   State firstState = allStates.get(theInitialStateIntIndex);

  actualState = firstState;

   while (stepString.length()>0){

       Character characterToProcess = stepString.charAt(0);
       stepString.deleteCharAt(0);

       State nextState;
       nextState = ((State)actualState.get(characterToProcess)); // pasa al siguiente State
   actualState = nextState;

   actualStateIntIndex=allStates.indexOf(actualState);


   System.out.println("the actual state for " + stepString + " is " + actualStateIntIndex);

   if ((actualState.isFinal==true) && (stepString.length()==0))
      {
          System.out.println("THE STRING " + string + " IS ACCEPTED AT STATE " + actualStateIntIndex );

      }

   else if (stepString.length()==0 && (actualState.isFinal==false)){
          System.out.println("THE STRING " + string + " IS REJECTED AT STATE " + actualStateIntIndex);

      }

   }

}

Здесь:

State nextState;
nextState = ((State)actualState.get(characterToProcess)); 

Может я что-то не так делаю, но я не понимаю.

Автомат всегда зависает в состоянии 0, хотя StringBuilder правильно обрабатывается, почему?

Вот полный код:

       package afd;

        import java.io.*;
        import java.util.*;

        /**
         *
         * @author Administrator
         */
        public class Main {

        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) throws IOException {
            // TODO code application logic here

            FileReader fr = new FileReader("E://Documents and Settings//Administrator//My Documents//NetBeansProjects//AFD//src//afd//dfa.in");


            BufferedReader br = new BufferedReader(fr);

            String firstLine= br.readLine();


            String [] firstLineSplitted = firstLine.split(" ");

            /*debug*/
            //System.out.println("firstLine is " + firstLine);

            int numberOfTestCases = Integer.parseInt(firstLine);

            for (int indexOfTestCases =0; indexOfTestCases < numberOfTestCases; indexOfTestCases++  ){

                int aux;
                System.out.println("Case Number " +  (aux = indexOfTestCases+1));

                String caseStartLine = br.readLine();

                /*debug*/
                //System.out.println("caseStarLine is " + caseStartLine);
                String [] caseStartLineSplitted = caseStartLine.split(" ");

                int numberOfStates;
                int numberOfAlphabetSymbols;
                int numberOfFinalStates;


                numberOfStates = Integer.parseInt(caseStartLineSplitted[0]);

                numberOfAlphabetSymbols = Integer.parseInt(caseStartLineSplitted[1]);

                numberOfFinalStates = Integer.parseInt(caseStartLineSplitted[2]);




                Automaton automaton = new Automaton();


                automaton.setAllStates(numberOfStates);

      //          automaton.size = numberOfStates;
     //           automaton.numberOfAlphabetSymbols = numberOfAlphabetSymbols;
     //           automaton.numberOfFinalStates = numberOfFinalStates;
                //Automaton a = new Automaton(numberOfStates);


                String alphabetLine = br.readLine();
                System.out.println("alphabetLine is " + alphabetLine);

                automaton.setAlphabet (alphabetLine);

    //            automaton.alphabetSymbols =new StringBuffer(alphabetLine);

                for (int indexOfStates = 0; indexOfStates < numberOfStates; indexOfStates++){

                      String transitionsLine = br.readLine();
                       /*debug*/
                       System.out.println("for the state " + indexOfStates + " transitionsLine is " + transitionsLine);

                       automaton.setTransitions(indexOfStates,transitionsLine);

                      /*String [] ijLineSplitted = ijLine.split(" ");

                      int i = Integer.parseInt(ijLineSplitted[0]);
                      int j = Integer.parseInt(ijLineSplitted[1]);
                        */

                }

                String finalStatesLine = br.readLine();
                /*debug*/
                System.out.println("finalStatesLine is " + finalStatesLine);
                String finalStatesLineSplitted [] = finalStatesLine.split(" ");

                automaton.markFinalStates(finalStatesLineSplitted);



                String initialStateAndNumberOfStringsLine = br.readLine();

                /*debug*/
                //System.out.println("initialStateAndNumberOfStringsLine  is " +initialStateAndNumberOfStringsLine);
                String [] splittedInitialStateLine = initialStateAndNumberOfStringsLine.split(" ");

                int initialState = Integer.parseInt(splittedInitialStateLine[0]);
                int numberOfStrings = Integer.parseInt(splittedInitialStateLine[1]);

                automaton.markInitialState(initialState);

                for (int stringIndex =0; stringIndex<numberOfStrings; stringIndex++){

                     String stringToProcess = br.readLine();
                     /*debug*/
                System.out.println("stringToProcess is " + stringToProcess);

                    automaton.processString(stringToProcess);


                }


             }
            }







    }


    class State extends HashMap<Character, State>{

    boolean isFinal;
    boolean isInitial;
    int stateId;

    State () {
        isInitial=false;
        isFinal = false;

        }

    public boolean equals (Object o){




        boolean isEqual = false;

        State compare = (State)o;

        if ((compare.stateId)==this.stateId)
        {

            return true;
        }

        return isEqual;

    }

    public int hashCode() {

        int theHashCode = stateId%7;

        return theHashCode;

    }


    }

      class Automaton{
         List <State> allStates;
        //private List<State> finalStates;
         int  theInitialStateIntIndex;
         State actualState;
          char [] alphabet;




        Automaton() {


            allStates = new ArrayList<State>();


        }public void setAllStates (int numberOfStates)  {

        for (int i =0; i <numberOfStates; i++) {

            State newState = new State();
            newState.stateId = i;
            allStates.add(newState);

         }

    }


    public void setAlphabet (String alphabetLine){

        alphabet = alphabetLine.toCharArray();




    }

    public void markFinalStates (String [] finalStates){

        for (int index =0; index<finalStates.length; index++) {

            int aFinalStateId = Integer.parseInt(finalStates[index]);

            State aFinalState = allStates.get(aFinalStateId);
            aFinalState.isFinal = true;
            allStates.add(aFinalStateId, aFinalState);


            /*DEBUG*/
            aFinalState = allStates.get(aFinalStateId);
            if ((aFinalState.isFinal)==true)
            System.out.println("THE STATE " + aFinalStateId + " IS MARKED AS FINAL");

        }

    }

    public void markInitialState (int initialStateId) {

            State theInitialState = allStates.get(initialStateId);
            theInitialState.isInitial=true;
            allStates.add(initialStateId, theInitialState);

            theInitialStateIntIndex = initialStateId;

            /*DEBUG*/

            System.out.println("THE INITIAL STATE ID IS " + initialStateId);

            theInitialState = allStates.get(initialStateId);
            if ((theInitialState.isInitial)==true)
            System.out.println("THE STATE " + initialStateId + " IS MARKED AS INITIAL");

    }


    public void setTransitions(int stateId, String transitionsLine){


            State theOneToChange = allStates.get(stateId);

            String [] statesToReachStringSplitted = transitionsLine.split(" ");

            for (int symbolIndex=0; symbolIndex<statesToReachStringSplitted.length;symbolIndex++){

                int reachedState= Integer.parseInt(statesToReachStringSplitted[symbolIndex]);

                theOneToChange.put(alphabet[symbolIndex],allStates.get(reachedState));

                System.out.println("THE STATE " + stateId + " REACHES THE STATE " + reachedState + " WITH THE SYMBOL " + alphabet[symbolIndex]);

            }

            allStates.add(stateId, theOneToChange);

    }


    public int findInitialState(){


        int index =0;

       cycle: for (; index<allStates.size(); index++){

            State s = allStates.get(index);

            if (s.isInitial==true) {

                break cycle;



           }
        } return index;

}



    public void processString (String string)
    {


        StringBuilder stepString= new StringBuilder (string);


        int actualStateIntIndex;



       System.out.println("THE FOUND INITIAL ONE IS "+ theInitialStateIntIndex);


       State firstState = allStates.get(theInitialStateIntIndex);

      actualState = firstState;

       while (stepString.length()>0){

           Character characterToProcess = stepString.charAt(0);
           stepString.deleteCharAt(0);

           State nextState;
           nextState = ((State)actualState.get(characterToProcess)); // pasa al siguiente State

           actualState = nextState;

           actualStateIntIndex=allStates.indexOf(actualState);


           System.out.println("the actual state for " + stepString + " is " + actualStateIntIndex);

           if ((actualState.isFinal==true) && (stepString.length()==0))
              {
                  System.out.println("THE STRING " + string + " IS ACCEPTED AT STATE " + actualStateIntIndex );

              }

           else if (stepString.length()==0 && (actualState.isFinal==false)){
                  System.out.println("THE STRING " + string + " IS REJECTED AT STATE " + actualStateIntIndex);

              }

           }



       }




    }

Вот входной файл:

4
3 2 1
ab
1 0
2 0
2 0
2
0 3
abaa
aab
aba
3 3 2
ade
0 1 2
1 2 0
2 1 0
1 2
2 2
a
de
3 2 1
ab
1 0
2 0
2 0
2
0 3
abaa
aab
aba
3 3 2
ade
0 1 2
1 2 0
2 1 0
1 2
2 2
a
de

Изменить: здесь я объясню формат этого входного файла.

Первая строка представляет количество тестовых случаев.

Каждый тестовый пример начинается с 3 целых чисел, первое — это номер состояния автомата, затем — количество символов в алфавите, а затем — количество конечных состояний.

Следующая строка — алфавит. Символы появляются вместе.

Затем идет количество строк, равное количеству состояний, описывающих функцию перехода. Первая строка этой группы строк представляет функцию перехода для первого состояния автомата (qo), первый элемент представляет состояние, которое достигается, когда первый символ в алфавите переходит в это состояние, и так далее. У меня были проблемы с пониманием этого из исходной постановки задачи. Это самый простой способ, которым я пришел, чтобы увидеть это:

Линии:

1 0
2 0
2 0

равный:

            AlphabetSymbol0        AlphabetSymbol1
State0         State1                State0
State1         State2                State0
State2         State2                State0

Затем есть строка, в которой говорится, какие состояния автомата являются конечными.

Затем идет строка, в которой говорится, какое начальное состояние и сколько входных строк будет получено.

Затем идут строки с входными строками.

Вывод этой программы должен быть:

C

ase Number 1
alphabetLine is ab
for the state 0 transitionsLine is 1 0
THE STATE 0 REACHES THE STATE 1 WITH THE SYMBOL a
THE STATE 0 REACHES THE STATE 0 WITH THE SYMBOL b
for the state 1 transitionsLine is 2 0
THE STATE 1 REACHES THE STATE 2 WITH THE SYMBOL a
THE STATE 1 REACHES THE STATE 0 WITH THE SYMBOL b
for the state 2 transitionsLine is 2 0
THE STATE 2 REACHES THE STATE 2 WITH THE SYMBOL a
THE STATE 2 REACHES THE STATE 0 WITH THE SYMBOL b
finalStatesLine is 2
THE STATE 2 IS MARKED AS FINAL
THE INITIAL STATE ID IS 0
THE STATE 0 IS MARKED AS INITIAL
stringToProcess is abaa
THE FOUND INITIAL ONE IS 0
the actual state for baa is 0
the actual state for aa is 0
the actual state for a is 0
the actual state for  is 0
**THE STRING abaa IS ACCEPTED AT STATE 2**
stringToProcess is aab
THE FOUND INITIAL ONE IS 0
the actual state for ab is 0
the actual state for b is 0
the actual state for  is 0
**THE STRING aab IS REJECTED AT STATE 0**
stringToProcess is aba
THE FOUND INITIAL ONE IS 0
the actual state for ba is 0
the actual state for a is 0
the actual state for  is 0
**THE STRING aba IS ACCEPTED AT STATE 1**
Case Number 2
alphabetLine is ade
for the state 0 transitionsLine is 0 1 2
THE STATE 0 REACHES THE STATE 0 WITH THE SYMBOL a
THE STATE 0 REACHES THE STATE 1 WITH THE SYMBOL d
THE STATE 0 REACHES THE STATE 2 WITH THE SYMBOL e
for the state 1 transitionsLine is 1 2 0
THE STATE 1 REACHES THE STATE 1 WITH THE SYMBOL a
THE STATE 1 REACHES THE STATE 2 WITH THE SYMBOL d
THE STATE 1 REACHES THE STATE 0 WITH THE SYMBOL e
for the state 2 transitionsLine is 2 1 0
THE STATE 2 REACHES THE STATE 2 WITH THE SYMBOL a
THE STATE 2 REACHES THE STATE 1 WITH THE SYMBOL d
THE STATE 2 REACHES THE STATE 0 WITH THE SYMBOL e
finalStatesLine is 1 2
THE STATE 1 IS MARKED AS FINAL
THE STATE 2 IS MARKED AS FINAL
THE INITIAL STATE ID IS 2
THE STATE 2 IS MARKED AS INITIAL
stringToProcess is a
THE FOUND INITIAL ONE IS 2
the actual state for  is 0
**THE STRING a IS ACCEPTED AT STATE 2** 
stringToProcess is de
THE FOUND INITIAL ONE IS 2
the actual state for e is 0
the actual state for  is 0
**THE STRING de IS REJECTED AT STATE 0** 

Я ошибаюсь во всех строках, написанных жирным шрифтом.

Я собираюсь:

Case Number 1

THE STRING abaa IS ACCEPTED AT STATE 0
THE STRING aab IS ACCEPTED AT STATE 0
THE STRING aba IS ACCEPTED AT STATE 0


Case Number 2
THE STRING a IS ACCEPTED AT STATE 0
THE STRING de IS ACCEPTED AT STATE 0

Мой автомат все принимает и застревает на состоянии 0, почему?


person andandandand    schedule 09.12.2009    source источник
comment
Предоставленный вами код не компилируется... некоторые вещи отсутствуют. Однако можете ли вы сказать мне, сколько существует состояний и имеет ли значение значение stateID или может ли оно быть чем угодно?   -  person TofuBeer    schedule 09.12.2009
comment
Фиксированный. На каждом тесткейсе есть 3 состояния, есть два тесткейса.   -  person andandandand    schedule 09.12.2009


Ответы (2)


Я почти уверен, что проблема в том, что State необходимо переопределить .equals(Object) и .hashCode(). Я считаю, что allStates - это List<State>, и для вызова get(State) в этом списке равно необходимо переопределить.

person TofuBeer    schedule 09.12.2009
comment
Да, allStates — это ArrayList‹State›. У меня нет опыта работы с коллекциями, как должны быть переопределены методы equals() и hashCode()? - person andandandand; 09.12.2009
comment
Я исправил код, чтобы он компилировался. Я не понимаю, почему я должен переопределять equals и hasCode здесь. Не могли бы вы уточнить, пожалуйста? - person andandandand; 09.12.2009
comment
когда объект просматривается в коллекции, он вызывает метод .equals. Вы можете считать, что .equals из Object возвращает true тогда и только тогда, когда два объекта являются одним и тем же (по сути, o == o или физическое равенство). Чтобы проверить логическое равенство (одинаковые ли элементы данных), вам необходимо переопределить .equals. Когда вы переопределяете .equals, вы должны переопределять .hashCode(), который используется в Картах вместе с .equals. - person TofuBeer; 09.12.2009

Ну, во-первых, похоже, что метод processState вообще не обновляет поле currentState автомата. На самом деле, вы, кажется, нигде не изменяете это.

Было бы полезно, если бы вы объяснили, что вы делаете немного лучше. Вы только что сбросили много некомментированного исходного кода и говорите, что «он застревает в состоянии 0», хотя мы не знаем, что такое состояние 0 или как это состояние может быть обнаружено. Я предполагаю, что currentState указывает на это, хотя у State экземпляров тоже нет номеров, поэтому трудно понять, с чего начать анализ этого...

По крайней мере, предоставьте два бита информации (хотя больше было бы намного лучше):

  1. Значения полей/вывод, которые вы ожидаете увидеть, чтобы указать на успех, и то, что вы видите в настоящее время (будьте явными в отношении конкретных значений определенных полей);
  2. Где вы ожидаете, что эти поля будут обновлены, и при каких условиях.
person Andrzej Doyle    schedule 09.12.2009
comment
Спасибо, я изменил код и вопрос на основе ваших предложений. Про equals и hashCode читал по вашим ссылкам, но так и не понял, как заставить их работать, чтобы автомат не застрял на state0. - person andandandand; 09.12.2009