Почему в OpenFST нет команды «запустить», «принять» или «преобразовать»?

Я слышал много хорошего об OpenFST, но мне трудно заставить его работать. Я создаю автомат FST (fstcompile), который я хочу использовать в качестве акцептора для проверки соответствия набора строк (очень похоже на регулярные выражения, но с преимуществами, предоставляемыми оптимизацией автоматов, предоставляемых OpenFST). И вот в чем дело:
Как проверить, принимает ли полученный автомат строку?

Я нашел предложение превратить входную строку в простой автомат и составить ее с принимающий автомат для получения результата. Я нашел это очень громоздким и странным. Есть ли более простой способ (через строку cmd или Python/C++)?


person sophros    schedule 20.07.2017    source источник
comment
Не так уж сложно создать скрипт на Python, определяющий линейный автомат. Не уверен, почему он не был включен в сам OpenFST.   -  person qwr    schedule 26.09.2018
comment
Именно так! Документация написана в терминах абстрактной математики, что отпугивает новых пользователей. Было бы жаль отпугивать пользователей от очень хорошей библиотеки!   -  person sophros    schedule 29.09.2018


Ответы (1)


Вот краткий пример того, как вы можете проверить, принимает ли автомат строку, используя Open FST. Оболочка Python. Действительно, вы должны превратить свой ввод в автомат, а Open FST даже не создает для вас этот «линейный цепной автомат»! К счастью, этот процесс легко автоматизировать, как показано ниже:

def linear_fst(elements, automata_op, keep_isymbols=True, **kwargs):
    """Produce a linear automata."""
    compiler = fst.Compiler(isymbols=automata_op.input_symbols().copy(), 
                            acceptor=keep_isymbols,
                            keep_isymbols=keep_isymbols, 
                            **kwargs)

    for i, el in enumerate(elements):
        print >> compiler, "{} {} {}".format(i, i+1, el)
    print >> compiler, str(i+1)

    return compiler.compile()

def apply_fst(elements, automata_op, is_project=True, **kwargs):
    """Compose a linear automata generated from `elements` with `automata_op`.

    Args:
        elements (list): ordered list of edge symbols for a linear automata.
        automata_op (Fst): automata that will be applied.
        is_project (bool, optional): whether to keep only the output labels.
        kwargs:
            Additional arguments to the compiler of the linear automata .
    """
    linear_automata = linear_fst(elements, automata_op, **kwargs)
    out = fst.compose(linear_automata, automata_op)
    if is_project:
        out.project(project_output=True)
    return out

def accepted(output_apply):
    """Given the output of `apply_fst` for acceptor, return True is sting was accepted."""
    return output_apply.num_states() != 0

Давайте определим простой Acceptor, который принимает только серию «ab»:

f_ST = fst.SymbolTable()
f_ST.add_symbol("<eps>", 0)
f_ST.add_symbol("a", 1)
f_ST.add_symbol("b", 2)
compiler = fst.Compiler(isymbols=f_ST, osymbols=f_ST, keep_isymbols=True, keep_osymbols=True, acceptor=True)

print >> compiler, "0 1 a"
print >> compiler, "1 2 b"
print >> compiler, "2 0 <eps>"
print >> compiler, "2"
fsa_abs = compiler.compile()
fsa_abs

введите здесь описание изображения

Теперь мы можем просто применить Acceptor, используя:

accepted(apply_fst(list("abab"), fsa_abs))
# True
accepted(apply_fst(list("ba"), fsa_abs))
# False

Чтобы узнать, как использовать преобразователь, посмотрите мой другой ответ

person Yann Dubois    schedule 07.01.2019
comment
спасибо за подробный пример. Мне интересно, действительно ли необходимо добавление c в f_ST.add_symbol("c", 3) к словарю преобразователя? Мне это кажется несколько лишним. - person sophros; 07.01.2019
comment
@sophros хороший улов, я изменил свой пример, но забыл обновить таблицу символов. Я сейчас отредактировал его. - person Yann Dubois; 07.01.2019