DFA 最小化(python 暴力)

https://rusunoi.github.io/books/National-Team-Thesis/2021.pdf

#!/bin/env python3
from collections import defaultdict, deque


def rebuild(tr, P, q0):
    tot = 0
    drn = {}
    for S in P:
        for nd in S:
            drn[nd] = tot
        tot += 1
    newtr = {}
    tot = 0
    for S in P:
        for nd in S:
            acc, trs = tr[nd]
            break
        newtr[tot] = acc, tuple(map(lambda nd: drn[nd], trs))
        tot += 1
    return newtr, drn[q0]


def search_dfa(tr, st):
    q = [st]
    vis = {st}
    l = 0
    while l < len(q):
        u = q[l]
        l += 1
        for v in tr[u][1]:
            if v not in vis:
                vis.add(v)
                q.append(v)
    return {nd: tr[nd] for nd in q}


def hopcroft(tr):
    sgm = 0
    for nd, (acc, trs) in tr.items():
        sgm = len(trs)
        break
    Q = frozenset({nd for nd, (acc, trs) in tr.items()})
    F = frozenset({nd for nd, (acc, trs) in tr.items() if acc})
    P = {F, Q - F}
    W = {F}
    while W:
        A = W.pop()
        for c in range(sgm):
            X = {nd for nd, (acc, trs) in tr.items() if trs[c] in A}
            Ys = {(Y, U, V) for Y in P if (U := Y - X) and (V := Y & X)}
            for Y, U, V in Ys:
                P.remove(Y)
                P.add(U)
                P.add(V)
                if Y in W:
                    W.remove(Y)
                    W.add(U)
                    W.add(V)
                else:
                    if len(U) < len(V):
                        W.add(U)
                    else:
                        W.add(V)
    return P


def solve(tr, q0):
    tr = search_dfa(tr, q0)
    P0 = [frozenset({nd}) for nd, (acc, trs) in tr.items()]
    tr, q0 = rebuild(tr, P0, q0)
    P = hopcroft(tr)
    return rebuild(tr, P, q0)


def print_dfa(tr, q0):
    F = []
    print("{", end="")
    for i in range(len(tr)):
        acc, trs = tr[i]
        if acc:
            F.append(i)
        print("{", end="")
        print(*trs, sep=",", end="},")
    print("}")
    print("q0:", q0)
    print("ACC:", end=" ")
    print(*F, sep=",")

一个 dfa 是一个 dict,键为结点,值是元组套元组 (acc, (tr[0], tr[1], ...)),acc 表示该状态是否是接受状态,tr[0] 那些就是转移状态。

solve(tr, q0) 用于化简 dfa,q0 是初始状态。print_dfa(tr, q0) 输出一个被 solve 过的 dfa。

posted @ 2025-04-22 21:45  caijianhong  阅读(195)  评论(0)    收藏  举报