You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

有限状态自动机(FSA)重复输出问题:原因分析与修复求助

问题描述

我正在构建一款有限状态自动机(FSA),用于识别绵羊叫声字符串“baa...!”或奶牛叫声字符串“moo...!”,要求仅接受包含偶数个元音的输入。但当前实现的FSA存在异常:当输入字符串中的元音数量超过2个时,已接受的结果会出现重复输出。

实现代码

工具导入与FSA创建函数

import openfst_python

import sys
sys.path.append('/usr/local/lib/python2.7/site-packages/')
import pywrapfst as fst
from fststr import fststr

# 可视化FSA
import graphviz
from IPython.display import display

def create_fsa(alphabet, fsa_str):
    """Create and compile an FSA given an alphabet and string representation
    
    Params
    ------
    alphabet: `List[str]` 
        Input alphabet of the FSA
    fsa_str: str 
        String representation of the FSA 
        
    Returns the FSA object
    """
    st = fststr.symbols_table_from_alphabet(alphabet)
    compiler = fst.Compiler(isymbols=st, osymbols=st, keep_isymbols=True, keep_osymbols=True)
    compiler.write(fsa_str)
    fsa = compiler.compile()
    
    return fsa

FSA定义与测试代码

sheepcow_alphabet = ['a', 'b', 'm', 'o', '!']
sheepcow_fsa_str = """
0 1 b b 
1 2 a a
2 1 a a
2 3 a a
3 2 a a
1 4 ! !
4
0 5 m m
5 6 o o
6 5 o o
6 7 o o
7 6 o o
5 4 ! !
4
""" 


sheepcow_fsa = create_fsa(alphabet=sheepcow_alphabet, fsa_str=sheepcow_fsa_str)

# 可视化FSA
sheepcow_fsa.draw("FSAs/sheepcow_fsa.dot", portrait=True)
src = graphviz.Source.from_file("FSAs/sheepcow_fsa.dot")
display(src)

# 测试用例
accepted_strings = ['baa!', 'moo!', 'baaaa!', 'moooooo!']
rejected_strings = ['b', '!', 'oo!', 'baaa!', 'maa!', 'baaa!']

# 处理接受列表
for s in accepted_strings:
    print('SheepCow FSA processes string %s: %s' % (s, fststr.apply(s, sheepcow_fsa)))

# 处理拒绝列表
for s in rejected_strings:
    print('SheepCow FSA processes string %s: %s' % (s, fststr.apply(s, sheepcow_fsa)))

测试输出

SheepCow FSA processes string baa!: ['baa!']
SheepCow FSA processes string moo!: ['moo!']
SheepCow FSA processes string baaaa!: ['baaaa!', 'baaaa!']. # 重复输出
SheepCow FSA processes string moooooo!: ['moooooo!', 'moooooo!', 'moooooo!', 'moooooo!']. # 重复输出
SheepCow FSA processes string b: []
SheepCow FSA processes string !: []
SheepCow FSA processes string oo!: []
SheepCow FSA processes string baaa!: []
SheepCow FSA processes string maa!: []
SheepCow FSA processes string baaa!: []
问题原因分析

当前FSA设计存在冗余的等价路径:

  • 绵羊部分:同时设计了1↔2和2↔3两组循环来处理a的输入,这两组循环都能实现偶数个元音的计数,但它们是并行的独立路径。当输入4个a时,存在两条不同的路径可以到达接受状态,且输出完全相同,导致fststr.apply返回重复结果。
  • 奶牛部分:同理,5↔6和6↔7两组循环造成了更多的路径组合,输入6个o时会产生4条等价路径,因此输出4次重复结果。
修复方案

简化FSA结构,仅保留一套用于切换元音奇偶计数的状态循环,去掉冗余状态和边:

修复后的FSA定义

sheepcow_fsa_str_fixed = """
# 绵羊叫声路径:b + 偶数个a + !
0 1 b b 
1 2 a a
2 1 a a
1 4 ! !
# 奶牛叫声路径:m + 偶数个o + !
0 5 m m
5 6 o o
6 5 o o
5 4 ! !
# 接受状态
4
""" 

修复后的测试输出

替换原FSA定义为上述代码后,测试输出将变为:

SheepCow FSA processes string baa!: ['baa!']
SheepCow FSA processes string moo!: ['moo!']
SheepCow FSA processes string baaaa!: ['baaaa!']
SheepCow FSA processes string moooooo!: ['moooooo!']
SheepCow FSA processes string b: []
SheepCow FSA processes string !: []
SheepCow FSA processes string oo!: []
SheepCow FSA processes string baaa!: []
SheepCow FSA processes string maa!: []
SheepCow FSA processes string baaa!: []

修复后的FSA逻辑:

  • 绵羊部分:状态1表示已输入b且元音数为偶数,状态2表示元音数为奇数;每输入一个a,在状态1和2之间切换,只有处于状态1(偶数元音)时输入!才能到达接受状态4。
  • 奶牛部分:状态5表示已输入m且元音数为偶数,状态6表示元音数为奇数;每输入一个o,在状态5和6之间切换,只有处于状态5(偶数元音)时输入!才能到达接受状态4。

这样每个合法输入都只有唯一的路径到达接受状态,不会产生重复输出,同时满足仅接受偶数个元音的需求。

内容的提问来源于stack exchange,提问作者Pargins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:25:37