繁体   English   中英

Hopcroft的算法 - DFA最小化

[英]Hopcroft's algorithm - DFA Minimization

我想实现Hopcroft的算法来最小化DFA WIKIPEDIA 到现在为止,我可以删除不可达状态。 问题是我不理解这个算法。 我不知道如何实现它。 有人可以解释一下吗? 或者可以扩展算法,以便实现它更容易理解。 我根本得不到算法的以下部分:

 let X be the set of states for which a transition on c leads to a state in A
      for each set Y in P for which X ∩ Y is nonempty and Y \ X is nonempty do
           replace Y in P by the two sets X ∩ Y and Y \ X

算法如下:

在此输入图像描述

到目前为止我已经实现了(写得不好,一旦完成它就会清理):

    package dRegAut;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;


public class dfamin {

    // Global variables to hold data from the file
    private int numStates,numAlphabets,numFinalStates;
    private char alphabets[];
    private int finalStates[];
    private int [][] transitionTable;



    /**
     * @param args
     * @throws IOException 
     * @throws NumberFormatException 
     */
    public static void main(String[] args) throws NumberFormatException, IOException {

        int numStates,numAlphabets,numFinalStates;
        char alphabets[];
        int finalStates[];
        int [][] transitionTable;

        /*
         * INPUT FILE FORMAT: numberOfStates numberofAlphabets transitions1 transtions2 ... numberOfFianlStates FinalState(s)
         * Example: 
         *          8 2 1 5 6 2 0 2 2 6 7 5 2 6 6 4 6 2 2 2 6
         *          5 2 0 1 0 1 3 4 3 4 2 4 3 0 2 3
         *          8 2 1 0 0 2 3 1 3 0 3 5 6 4 5 6 6 3 1 3
         *          9 2 1 4 2 5 3 7 4 7 5 8 6 1 7 1 8 2 0 4 3 2 5 8
         */

        // Take file name and open a stream to read it
        FileInputStream fileStream = new FileInputStream("/path/to/file");
        BufferedReader br = new BufferedReader(new InputStreamReader(fileStream));

        // Store each line from the file
        String line;

        // Read each line from file
        while((line = br.readLine()) != null){

            // Read single spaced data from each line
            String [] splittedLine = line.split(" ");

            // Read numStates,numAlphabets from the line
            numStates = Integer.parseInt(splittedLine[0]);
            numAlphabets = Integer.parseInt(splittedLine[1]);
            //for(int a=0;a<numAlphabets;a++){
                //alphabets[a] = '0';
            //}
            transitionTable = new int[numStates][numAlphabets];
            int tt= 2;
            // Loop thorough the line and read transition table
            for(int row=0;row<numStates;row++){

                for(int col=0;col<numAlphabets;col++){
                    transitionTable[row][col] = Integer.parseInt(splittedLine[tt]);

                    tt++;

                }// End of for-loop to go thorough alphabets
            }// End of for-loop to go thorough states

            // Read number of final states
            numFinalStates = Integer.parseInt(splittedLine[2+numStates*numAlphabets]);
            //System.out.println(numFinalStates);
            // Read final states
            int z=0;
            finalStates = new int[numFinalStates];
            int start = 3+numStates*numAlphabets ;
            int end = (3+(numStates*numAlphabets))+numFinalStates;
            for(int fs=start;fs<end;fs++){
                finalStates[z] = Integer.parseInt(splittedLine[fs]);
                //System.out.println(finalStates[z]);
                z++;
            }// End of for-loop to read all final states
            dfamin x = new dfamin(numStates,numAlphabets,numFinalStates,finalStates,transitionTable);
            x.minimizer();
            System.out.println(x);



        }// End of while-loop to read file

        // Close the stream
        br.close();

    }

    dfamin(int nS,int nA,int nFS,int fS[], int [][] tT){
        numStates = nS;
        numAlphabets = nA;
        numFinalStates = nFS;
        //alphabets = a;
        finalStates = fS;
        transitionTable = tT;

    }// End of DFAMinimizer constructor

    /*
     * A method to minmize the dfa  
     */

    public void minimizer(){

        // Remove unreachable States
        ArrayList<Integer> reachableStates = reachableStates(numStates, numAlphabets,transitionTable);

        // Store all final states
        ArrayList<Integer> fStates = new ArrayList<Integer>();
        // Loop thorugh finalStates array and transfer its data to array list
        for(int fs:finalStates){
            fStates.add(fs);
        }// End of for-loop

        // Store all non final states
        ArrayList<Integer> nonFStates = new ArrayList<Integer>();

        // Store only non final states in nonFstates
        nonFStates = nonFinalStates(reachableStates,fStates);

        //TODO: IMPLEMENT HOPCROFT's ALGORITHM


    }// End of minimizer method

    /*
     * unreachableStates - A method to find unreachable states of a DFA 
     * 
     */
    public ArrayList<Integer> reachableStates(int numStates, int numAlphabets, int [][] transitionTable){

        // Initialize a list to hold temporary list of states in it
        ArrayList<Integer> reachableStates =new ArrayList();
        ArrayList<Integer> newStates = new ArrayList();


        // Start from the state zero
        reachableStates.add(0);
        newStates.add(0);
        // Temporary array to hold reachable states
        ArrayList<Integer> temp = new ArrayList();
        // Loop until there is data in newStates
        do{
            // Empty temp array
            temp.clear();
            // Loop thorough all the states, and check for {p such that p=δ(q,c)};
            for(int j=0;j<newStates.size();j++){

                for(int i=0; i<numAlphabets;i++){
                    // If found add it to the temp set
                    temp.add(transitionTable[newStates.get(j)][i]);

                } // End of for-loop to go thorough all characters

            }// End of for-loop to go thorough all elements of the newStates array list

            // Clear newStates list
            newStates.clear();

            // Add the elements that are in temp, but are not in reachableStates to newStates
            // new_states := temp \ reachable_states;
            for(int z=0;z<temp.size();z++){

                for(int z1=0; z1<reachableStates.size();z1++){


                    // If the state was already present, don't add
                    if(temp.get(z) == reachableStates.get(z1)){
                        break;
                    }
                    if(temp.get(z) != reachableStates.get(z1) && z1 == reachableStates.size()-1){
                        // Only from temp to newstates if its not in reachablestates currently
                        newStates.add(temp.get(z));

                    }


                }// End of for-loop to go thorough all reachableStates elements and check if a match
            }// End of for-loop thorugh all temp states

            // If newStates list is not empty then add it to the reachableStates
            if(!newStates.isEmpty()){
                // Add the newStates elements to reachable states
                for(int y=0;y<newStates.size();y++){
                    //System.out.printf("newStates:%d newStatesSize:%d in %d",newStates.get(y),newStates.size(),y);
                    reachableStates.add(newStates.get(y));
                }
            }

        }while(!newStates.isEmpty());

        reachableStates = removeDuplicate(reachableStates);

        return reachableStates;

    }// End of unreachableStates method

    /*
     * removeDuplicate - a function to remove duplicate entries from an ArrayList
     * 
     */
    ArrayList<Integer> removeDuplicate(ArrayList<Integer> input){

        // Remove duplicate entries from reachableStates list
        // Compare the first index, with all other indexes, compare the second with all other indexes
        for(int i=0;i<input.size()-1;i++){

            for(int j=i+1;j<input.size();j++){
                // If dupblicate states remove it
                if(input.get(i) == input.get(j)){
                    input.remove(j);
                }
            }
        }// End of for-loop to remove duplicate entries from reachableList

        // Sort the list before returning
        Collections.sort(input);
        // Return the list
        return input;
    }// End of removeDuplicate method


    /*
     * nonFinalStates - a method to return an array list of nonfinal states, given all and final states
     * 
     */
    ArrayList<Integer> nonFinalStates(ArrayList<Integer> allStates, ArrayList<Integer> finalStates){
        // All non final States
        ArrayList<Integer> nonFinalStates = new ArrayList<Integer>();
        // Loop thorough allStates, and compare each state with the list of finalstates
        for(int i=0; i<allStates.size();i++){
            // Loop thorough list of final states
            for(int j=0; j<finalStates.size();j++){
                // If a state is final state
                if(allStates.get(i) == finalStates.get(j)){
                    // Then remove it from the list
                    allStates.remove(i);
                }
            }// End of for-loop to travers finalstates
        }// End of for-loop to traverse allstates

        return nonFinalStates;

    }



    // returns a string that is compatible with our input file specification
    public String toString()    {
        StringBuffer buf = new StringBuffer();
        //buf.append(" "+ numStates +" ");
        //buf.append ( numAlphabets + " " );
        buf.append("Transition Table: ");
        for ( int i = 0; i < numStates; i++ )   {
            for ( int j = 0; j < numAlphabets; j++ )    {
                buf.append ( " "+ transitionTable[i][j] + " " );
            }
        }

        buf.append ( "Number of Final State(s): "+numFinalStates + " Final State(s): " );
        for ( int i = 0; i < numFinalStates; i++ )

                buf.append ( finalStates[i] + " " );
        return buf.toString();
    }

}

如果不能单独接受/拒绝其中DFA所处的行为,则称两个DFA状态等效 。对于每种语言,接受该语言的最小DFA没有等效状态。

Hopcroft的DFA最小化算法通过计算未最小化DFA的状态的等价类来工作。 这个计算的结点是一个迭代,其中,在每一步,我们都有一个比等价更粗糙的状态的分区(即,等效状态总是属于同一个分区集)。

  1. 初始分区是接受状态并拒绝状态。 显然这些并不等同。

  2. 假设我们在当前分区的同一组中有状态q1和q2。 让转换函数为delta,如果存在符号sigma使得delta(q1,sigma)和delta(q2,sigma)在分区的不同集合中,那么我们通过粗糙度不变量知道这些状态不相等,即,存在字符串x,使得delta(delta(q1,sigma),x)和delta(delta(q2,sigma),x)在它们是否接受/拒绝方面不同。 但delta(delta(q1,sigma),x)= delta(q1,sigma x),因此字符串sigma x在q1和q2之间进行区分。 您引用的逻辑是适当地拆分其中一个分区集。

  3. 正确性证明的有趣部分是,当第2步不可能时,我们已经达到了真正的等价类。

伪代码看起来比这更复杂,因为它关注我们可以找到第2步的应用程序的效率。

阅读原始论文中给出的示例可能有助于可视化该算法。

http://i.stanford.edu/pub/cstr/reports/cs/tr/71/190/CS-TR-71-190.pdf

在详细说明算法之前,我们通过一个例子来说明算法。大量使用列表处理来减少计算时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM