Конечный автомат пример python

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Конечный автомат (Finite State Machine) для ботов на базе библиотеки pybotx

License

ExpressApp/pybotx-fsm

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

Конечный автомат (Finite state machine) для ботов на базе библиотеки pybotx.

  • Лёгкое создание графа состояний и их переключений.
  • Передача данных в следующее состояние при явном вызове перехода.

Для работы библиотеки необходим Redis, который уже встроен в последние версии коробки.

Работа с графом состояний

from enum import Enum, auto from pybotx_fsm import FSMCollector class LoginStates(Enum): enter_email = auto() enter_password = auto() fsm = FSMCollector(LoginStates)
Bot( collectors=[ myfile.collector, ], bot_accounts=[ BotAccountWithSecret( # Не забудьте заменить эти учётные данные на настоящие, # когда создадите бота в панели администратора. id=UUID("123e4567-e89b-12d3-a456-426655440000"), host="cts.example.com", secret_key="e29b417773f2feab9dac143ee3da20c5", ), ], middlewares=[ FSMMiddleware([myfile.fsm], state_repo_key="redis_repo"), ], )
bot.state.redis_repo = await RedisRepo.init(. )
@fsm.on(LoginStates.enter_email) async def enter_email(message: IncomingMessage, bot: Bot) -> None: email = message.body if not check_user_exist(email): await bot.answer_message("Wrong email, try again") return await message.state.fsm.change_state(LoginStates.enter_password, email=email) await bot.answer_message("Enter your password") @fsm.on(LoginStates.enter_password) async def enter_password(message: IncomingMessage, bot: Bot) -> None: email = message.state.fsm_storage.email password = message.body try: login(email, password) except IncorrectPasswordError: await bot.answer_message("Wrong password, try again") return await message.state.fsm.drop_state() await bot.answer_message("Success!")
@collector.command("/login") async def start_login(message: IncomingMessage, bot: Bot) -> None: await bot.answer_message("Enter your email") await message.state.fsm.change_state(LoginStates.enter_email)

Минимальный пример бота с конечным автоматом

# Здесь и далее будут пропущены импорты и код, не затрагивающий # непосредственно pybotx_fsm class FsmStates(Enum): EXAMPLE_STATE = auto() fsm = FSMCollector(FsmStates) @collector.command("/echo", description="Echo command") async def help_command(message: IncomingMessage, bot: Bot) -> None: await message.state.fsm.change_state(FsmStates.EXAMPLE_STATE) await bot.answer_message("Input your text:") @fsm.on(FsmStates.EXAMPLE_STATE) async def example_state(message: IncomingMessage, bot: Bot) -> None: user_text = message.body await message.state.fsm.drop_state() await bot.answer_message(f"Your text is user_text>") bot = Bot( collectors=[ collector, ], bot_accounts=[ BotAccountWithSecret( # Не забудьте заменить эти учётные данные на настоящие, # когда создадите бота в панели администратора. id=UUID("123e4567-e89b-12d3-a456-426655440000"), host="cts.example.com", secret_key="e29b417773f2feab9dac143ee3da20c5", ), ], middlewares=[ FSMMiddleware([fsm], state_repo_key="redis_repo"), ], )

Передача данных между состояниями

@fsm.on(FsmStates.INPUT_FIRST_NAME) async def input_first_name(message: IncomingMessage, bot: Bot) -> None: first_name = message.body await message.state.fsm.change_state( FsmStates.INPUT_LAST_NAME, first_name=first_name, ) await bot.answer_message("Input your last name:") @fsm.on(FsmStates.INPUT_LAST_NAME) async def input_last_name(message: IncomingMessage, bot: Bot) -> None: first_name = message.state.fsm_storage.first_name last_name = message.body await message.state.fsm.drop_state() await bot.answer_message(f"Hello first_name> last_name>!")

About

Конечный автомат (Finite State Machine) для ботов на базе библиотеки pybotx

Источник

Как создать и использовать конечные автоматы в Python

Изучите создание и использование конечных автоматов в Python с помощью простого примера и улучшите свои навыки программирования!

Конечные автоматы — это математическая модель, представляющая систему, имеющую ограниченное количество состояний и переходов между ними. В этой статье мы рассмотрим, как создать и использовать конечные автоматы в Python.

Что такое конечный автомат?

Конечный автомат (Finite State Machine, FSM) — это абстрактная модель, описывающая поведение системы с фиксированным количеством состояний и правилами перехода между этими состояниями. Конечные автоматы используются во множестве приложений, таких как парсеры, компиляторы, сетевые протоколы и других.

Основные компоненты конечного автомата:

  • состояния (states)
  • переходы (transitions)
  • начальное состояние (initial state)
  • допускающие состояния (accepting states)

Создание конечного автомата в Python

Для создания конечного автомата в Python, можно использовать словари для хранения состояний и переходов. Вот пример конечного автомата, который распознает последовательность символов «ab»:

Использование конечного автомата в Python

Теперь, когда у нас есть конечный автомат, давайте напишем функцию, которая будет использовать его для проверки входной строки:

def fsm_accepts(fsm, input_str): current_state = fsm['initial'] for symbol in input_str: if symbol in fsm['transitions'][current_state]: current_state = fsm['transitions'][current_state][symbol] else: return False return current_state in fsm['accepting']

Теперь мы можем использовать данную функцию для тестирования нашего конечного автомата:

input_str = "ab" result = fsm_accepts(fsm, input_str) print(f"Input string '' is accepted: ") # Output: Input string 'ab' is accepted: True

Вывод

В этой статье мы рассмотрели, как создать и использовать конечные автоматы в Python. Это мощный инструмент для моделирования систем с ограниченным количеством состояний и переходов между ними. Теперь вы можете применить этот подход в своих проектах на Python. Удачи вам в изучении Python и создании своих проектов! 😉

Источник

Конечные автоматы и морфологизаторы

Морфологические анализаторы (они же морфологизаторы) в NLP выполняют базовые задачи, а именно определяют грамматические характеристики отдельных слов. На сегодня самые популярные python морфологизаторы это pymorphy и mystem.

По своей сути морфологизатор это словарь слов и их характеристик, это означает, что каждая словоформа каждого слова должна быть в нем представлена (для справки, в русском языке около 5 млн. словоформ). Сразу встает вопрос о структуре данных: как хранить данные используя меньше памяти и как быстро получать характеристики слов по ключам (словам). Упомянутый ранее pymorphy основан на конечных автоматах, а mystem – на префиксных деревьях. Ниже речь пойдёт о конечных автоматах.

Конечный автомат — это абстракция, состоящая из набора состояний (узлов) и переходов между ними. В один момент времени активным может быть только одно состояние, условия смены состояний представлены ребрами и помечаются меткой. Различают детерминированные и недетерминированные автоматы. В детерминированном по одной метке возможен переход только в одно состояние, в недетерминированном же наоборот – на одну метку может приходиться более одного перехода.

Автомат состоит из трёх видов состояний:

1) Начальное, круг с номером 0 – с него начинается работа автомата, может быть только одно;

2) Финальные, двойной круг – на них заканчивается работа конечного автомата (в них мы будем хранить информацию о слове);

3) Простые, обозначены кругом – промежуточные состояния.

Рассмотрим небольшой пример детерминированного конечного автомата, реализующего хранение трёх слов: деревня, дерево и дебри.

Как видно из рисунка слова «деревня» и «дерево» имеют общее начало «дерев», что позволяет «сэкономить» на хранении, также слово «дебри» имеет общую часть «де» с двумя другими. В финальных состояниях 6, 8 и 11 можно возможно хранение морфологической информации слов, если она общая для всех слов (например, мы храним только часть речи), то состояния 6, 8 и 11 можно заменить одним. Функционал конечных автоматов для языка python реализован в модуле DAWG. Установка модуля выполняется командой:

Ниже будет приведена реализация простого морфологизатора при помощи DAWG, который будет для слова, переданного на вход, возвращать его нормальную форму и часть речи. Для наполнения конечно автомата будет использован открытый корпус русского языка OpenCorpora, из которого возьмем все словоформы, их нормальных формы и части речи (список частей речи).

from dawg import BytesDAWG import xml.etree.ElementTree as ET 

ElementTree используется для считывания файла xml в котором хранится корпуса текста. Чтобы не считывать файл целиком, реализуем генератор, возвращающий кортеж. Первый элемент кортежа — словоформа, второе – строка с нормальной формой слова и его частью речи, разделённые нижним подчёркиванием. Например, (“деревом”, “дерево_NOUN”), где NOUN – существительное.

def fill_dawg(fpath): for event, elem in ET.iterparse(fpath): if elem.tag == 'lemma': lemma_node = [node for node in elem if node.tag == 'l'][0] lemma = lemma_node.get('t') gramemma = lemma_node[0].get('v') for ch_node in elem: if ch_node.tag == 'f': word = ch_node.get('t') yield word, bytes(str(f'_'), 'utf8') 

где fpath – путь к корпусу текста.

Создание конечного автомата и его наполнение реализует следующий код:

bytes_dawg = BytesDAWG(fill_dawg (fpath))

Класс BytesDAWG принимает на вход итерируемые объекты, состоящие из пар ключ-значение. Теперь можем протестировать автомат. Посмотрим выдачу на одну из форм слова «деревня»:

[b’\xd0\xb4\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb2\xd0\xbd\xd1\x8f_NOUN’]

Результат храниться в байтах, поэтому применим метод decode:

bytes_dawg[‘деревней’][0].decode(‘utf8’)

Результат соответствует ожиданиям: нормальная форма – деревня, часть речи – существительное.

Модуль DAWG можно использовать и в более практических задачах, например, для хранения больших словарей. Модуль оптимизирует хранение за счёт исключения дублей общих частей слов. Кроме того, в DAWG предоставляет возможность выполнять и другие операции, например, поиск по префиксу или поиск с заменами. Применение конечных автоматов не ограничивается морфологизаторами: они лежат в основе регулярных выражений, применяются в прописывание логики искусственного интеллекта в играх, используют в валидации UI моделей и т.д.

Источник

Читайте также:  Объединение ячеек
Оцените статью