zoukankan      html  css  js  c++  java
  • DFA最小化 -- Hopcroft算法 Python实现


    wiki 伪代码看上去一直以为怪。发现葡萄牙语和俄罗斯语那里的 if 推断都还缺少一个条件。


    国内的资料比較少。这几份学习资料不错。比我稀里糊涂的思路要好,分享下:

    http://www.liafa.univ-paris-diderot.fr/~carton/Enseignement/Complexite/

    ENS/Redaction/2008-2009/yingjie.xu.pdf

    http://www8.cs.umu.se/kurser/TDBC92/VT06/final/1.pdf

    http://arxiv.org/pdf/1010.5318.pdf



    对于一个确定型自己主动机 D = (Q, Σ, δ, q0, F)。Q 的一系列恒等关系 ρi (i ≥ 0) 被定义为:

    ρ0 = {(p, q)|p, q ∈ F} ∪ {(p, q)|p, q ∈ Q − F},

    ρi+1 = {(p, q) ∈ ρi|(∀a ∈ Σ)(δ(p, a), δ(q, a)) ∈ ρi}.


    ρi有例如以下关系:

    ρ0 ⊇ ρ1 ⊇ · · · .

    若 ρi = ρi+1 则对于 ρi = ρj (j > i).

    存在 0 ≤ k ≤ |Q| 满足 ρk = ρk+1.


    对于 ρi ≠ ρi+1,存在下面性质Equation 1

    ρi ≠ ρi+1    ⇔ (∃p, q ∈ Q, a ∈ Σ) (p, q) ∈ ρi and (δ(p, a), δ(q, a)) ∉ ρi

    ⇔ (∃U ∈ Q/ρi , a ∈ Σ) p, q ∈ U and (δ(p, a), δ(q, a)) ∉ ρi

    ⇔ (∃U, V ∈ Q/ρi , a ∈ Σ) p, q ∈ U and δ(p, a) ∈ V and δ(q, a) ∉ V

    ⇔ (∃U, V ∈ Q/ρi , a ∈ Σ) δ(U, a) ∩ V ≠ ∅ and δ(U, a) ∉ V



    算法抽象:

    1: Q/θ ← {F, Q − F}
    2: while (∃U, V ∈ Q/θ, a ∈ Σ) s.t.
    Equation 1 holds do
    3: Q/θ ← (Q/θ − {U}) ∪ {U ∩ δ^-1(V, a), U − U ∩ δ^-1(V, a)}
    4: end while


    算法细化:

    1:W ← {F, Q − F}    # 有些版本号上仅仅是 W ← {F }

    2: P ← {F, Q − F}

    3: while W is not empty do

    4:     select and remove S from W

    5:     for all a ∈ Σ do

    6:         la ← δ^-1(S, a)

    7:         for all R in P such that R ∩ la ≠ ∅ and R ∉ la do

    8:             partition R into R1 and R2: R1 ← R ∩ la and R2 ← R − R1

    9:             replace R in P with R1 and R2

    10:           if R ∈ W then

    11:               replace R in W with R1 and R2

    12:           else

    13:                 if |R1| ≤ |R2| then

    14:                     add R1 to W

    15:                 else

    16:                     add R2 to W

    17:                 end if

    18:             end if

    19:         end for

    20:     end for

    21: end while


    复杂度:

    O(n log n)


    另一个优化的代码:

    1: P = {F, Q − F}

    2:     for all a ∈ A do

    3:         Add((min(F, Q − F), a), S)

    4:     while S ≠ ∅ do

    5:         get (C, a) from S (we extract (C, a) according to the

    strategy associated with S: FIFO/LIFO/...)

    6:         for each B ∈ P split by (C, a) do

    7:             B′, B′′ are the sets resulting from splitting of B w.r.t. (C, a)

    8:             Replace B in P with both B′ and B′′

    9:             for all b ∈ A do

    10:                if (B, b) ∈ S then

    11:                    Replace (B, b) by (B′, b) and (B′′, b) in S

    12:                else

    13:                    Add((min(B′,B′′), b), S)



    找出无用状态:

    state_graph1 = {
        'total_states': [ 'A', 'B', 'C', 'D', 'E' ],
        'initial_states': [ 'A' ],
        'termination_states': [ 'D' ],
        'state_transition_map': {
            'A': { 'a': 'B', 'b': 'C' },
            'B': { 'a': 'B', 'b': 'D' },
            'C': { 'a': 'B' },
            'E': { 'a': 'E', 'b': 'E', },
            'D': { 'a': 'B' },
        },
        'cins': [ 'a', 'b' ],
    }
    
    
    def get_unreachable_states( G ):
        reachable_states      = set( G['initial_states'] )
        new_states            = set( G['initial_states'] )
        total_states          = set( G['total_states'] )
        cins                  = G['cins']
        state_transition_map  = G['state_transition_map']
        
        while True:
            temp_set = set()
            for state in new_states:
                for char in cins:
                    try:
                        next_state = state_transition_map[state][char]
                        temp_set.update( next_state )
                    except KeyError:
                        pass
    
            new_states = temp_set - reachable_states
            reachable_states.update( temp_set )
            if new_states == set():
                break
    
        unreachable_states = total_states - reachable_states
        return unreachable_states
    
    
    print get_unreachable_states( state_graph1 )
    

    Hopcroft:

    import random
    from copy import deepcopy
    
    state_graph1 = {
        'total_states': [ '1', '2', '3', '4', '5', '6', '7' ],
        'initial_states': [ '1' ],
        'termination_states': [ '6', '7' ],
        'state_transition_map': {
            '1': { 'a': '3', 'b': '2' },
            '2': { 'a': '4', 'b': '2' },
            '3': { 'c': '3', 'b': '6', 'd': '5' },
            '4': { 'b': '7', 'd': '5', 'c': '3' },
            '5': { 'a': '4' },
            '6': { 'b': '6' },
            '7': { 'b': '6' },
        },
        'cins': [ 'a', 'b', 'c', 'd' ],    
    }
    
    state_graph2 = {
        'total_states': [ 'A', 'B', 'C', 'D', 'E', 'F', 'S' ],
        'initial_states': [ 'A' ],
        'termination_states': [ 'C', 'D', 'E', 'F' ],
        'state_transition_map': {
            'S': { 'a': 'A', 'b': 'B' },
            'A': { 'a': 'C', 'b': 'B' },
            'B': { 'a': 'A', 'b': 'D' },
            'C': { 'a': 'C', 'b': 'E' },
            'D': { 'a': 'F', 'b': 'D' },
            'E': { 'a': 'F', 'b': 'D' },
            'F': { 'a': 'C', 'b': 'E' },
        },
        'cins': [ 'a', 'b' ],    
    }
    
    
    state_graph3 = {
        'total_states': [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' ],
        'initial_states': [ 'A' ],
        'termination_states': [ 'C' ],
        'state_transition_map': {
            'A': { '0': 'B', '1': 'F' },
            'B': { '0': 'G', '1': 'C' },
            'C': { '0': 'A', '1': 'C' },
            'D': { '0': 'C', '1': 'G' },
            'E': { '0': 'H', '1': 'F' },
            'F': { '0': 'C', '1': 'G' },
            'G': { '0': 'G', '1': 'E' },
            'H': { '0': 'G', '1': 'C' }
        },
        'cins': [ '0', '1' ],    
    }
    
    
    def hopcroft_algorithm( G ):
        cins                   = set( G['cins'] )
        termination_states     = set( G['termination_states'] ) 
        total_states           = set( G['total_states'] )
        state_transition_map   = G['state_transition_map']
        not_termination_states = total_states - termination_states
    
        def get_source_set( target_set, char ):
            source_set = set()
            for state in total_states:
                try:
                    if state_transition_map[state][char] in target_set:
                        source_set.update( state )
                except KeyError:
                    pass
            return source_set
    
        P = [ termination_states, not_termination_states ]
        W = [ termination_states, not_termination_states ]
    
        while W:
            
            A = random.choice( W )
            W.remove( A )
    
            for char in cins:
                X = get_source_set( A, char )
                P_temp = []
                
                for Y in P:
                    S  = X & Y
                    S1 = Y - X
                    
                    if len( S ) and len( S1 ):
                        P_temp.append( S )
                        P_temp.append( S1 )
                        
                        if Y in W:
                            W.remove( Y )    
                            W.append( S )
                            W.append( S1 )
                        else:
                            if len( S ) <= len( S1 ):
                                W.append( S )
                            else:
                                W.append( S1 )
                    else:
                        P_temp.append( Y )
                P = deepcopy( P_temp )
        return P
    
    
    print hopcroft_algorithm( state_graph1 )
    print hopcroft_algorithm( state_graph2 )
    print hopcroft_algorithm( state_graph3 )


    岛津义弘:

    “真田幸村,这片 ‘ 战国 ’ 的土地上有太多的冷漠和争斗。

    一个人想要在这种 ‘ 乱世 ’ 中心存温和。他前进的道路定然会非常痛苦,

    可是最后能走到 ‘ 武 ’ 之巅峰的人,却往往又都是那样内心温和的人。

    由于这份温和可以让人变得非常强壮。

    希望你即便面对的是你的敌人,挥舞自己的 ‘ 双枪 ’ 时,也不要失去这份温和。”




    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    (文章转载)GetTextMetrics与GetTextExtent的区别
    (文章转载)
    (文章转载)在刷新窗口时经常要调用重绘函数
    (文章转载)MCI编程
    Visual C#的Excel编程
    EXCEL中合并单元格
    Excel、Exchange 和 C# (摘要)
    C# 查询一个值方法ExecuteScalar()
    如何用C#在Excel中生成图表?
    javascript 常用方法
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4721341.html
Copyright © 2011-2022 走看看