问题描述
给定字母表 {0,1} 上的 5 个状态,可以构造多少个 DFA。鉴于初始状态不是固定的。
解决方法
对于字母表中的每个符号,DFA 最多可以有一个转换。因此,我们可以通过为状态分配所有有效选项来枚举 DFA。
我将使用以下表示法,例如,一个 2 元组的 5 元组,其目标是 {0,1}
中的符号。
((None,4),(4,3),(1,None),(None,0),(3,3))
这给你一个 FST,它从状态 0 进入状态 4(符号 1),从状态 4 可以进入状态 3 到状态(符号 0 或 1),然后从那里回到状态 0(符号 1) 1)。但这并没有连接,没有使用所有的5个状态。如果您计算所有此类 DFA,答案是 (6^2)^5 = 60466176
,因为对于每个符号都可以带您进入 5 个状态之一或从给定状态(公式中的 6 个)中丢失,有两个符号(公式中为2),并且有5个状态(公式中为5个指数)。
严格的 5 个州
如果我们想要一个可以生成 5 个状态的 FST,并且所有状态都可以到达,那么我们可以生成上述 FST 并过滤那些连接的。
def is_connected(dfa):
N = len(dfa)
reached = [False] * N
nReached = 0
stack = [0]
while len(stack):
s = stack.pop()
if not reached[s]:
reached[s] = True
nReached += 1
if nReached == N:
return True
t,u = dfa[s]
if t is not None:
stack.append(t)
if u is not None:
stack.append(u)
return False
import itertools
all_dfas = list(itertools.product(
list(itertools.product([None,1,2,3,4],repeat=2)
),repeat=5))
num_connected = sum(1 if is_connected(dfa) else 0 for dfa in all_dfas[:])
它给出了 15184800
。
同构
您可以尝试找到与重新标记状态相同的 DFA,因为这不会改变 DFA 定义的语言,通常我们只关注转换而不是状态,但情况似乎并非如此因为您要求考虑所有可能的初始状态。