Упрощение плоского конечного автомата с использованием иерархического конечного автомата - PullRequest
0 голосов
/ 22 января 2019

Я новичок в конечных автоматах и ​​пытаюсь понять, должен ли я использовать иерархический конечный автомат или придерживаться плоской структуры, которая мне нужна, чтобы смоделировать мою проблему самым простым способом.

У меня есть «анализатор», который может быть либо остановлен, либо проанализирован вход, проанализирован выход, проанализирован вход и выход или очищен. У меня есть некоторые состояния анализатора в enum, называемые analyzer_states, и переходы между состояниями в analyzer_transitions.

Вопрос в следующем: Могу ли я использовать иерархический конечный автомат для более простого моделирования? Или, может быть, FSM не помогает с этой проблемой?

#include <iostream>
#include <cstdlib>
#include <string>
#include "fsm.h"

enum class analyzer_transitions
{
    start_input,
    start_output,
    clear,
    stop_input,
    stop_output,
    resume
};

enum class analyzer_states
{
    analyzing_both,
    analyzing_input,
    analyzing_output,
    clearing_both,
    clearing_input,
    clearing_output,
    stopped,
};

inline auto output(std::string s)
{
    return [s]()
    {
        std::cout << s << std::endl;
    };
}

int main()
{
    fsm<analyzer_states, analyzer_transitions> machine{ analyzer_states::stopped };

    machine.add(
        analyzer_states::stopped, analyzer_transitions::start_input, analyzer_states::analyzing_input,
        output("-> analyzing_input"));

    machine.add(
        analyzer_states::stopped, analyzer_transitions::start_output, analyzer_states::analyzing_output,
        output("-> analyzing_output"));

    machine.add(
        analyzer_states::analyzing_input, analyzer_transitions::stop_input, analyzer_states::stopped, 
        output("-> stopped"));

    machine.add(
        analyzer_states::analyzing_output, analyzer_transitions::stop_output, analyzer_states::stopped, 
        output("-> stopped"));

    machine.add(
        analyzer_states::analyzing_both, analyzer_transitions::stop_input, analyzer_states::analyzing_output, 
        output("-> analyzing_output"));

    machine.add(
        analyzer_states::analyzing_both, analyzer_transitions::stop_output, analyzer_states::analyzing_input,
        output("-> analyzing_input"));

    machine.add(
        analyzer_states::analyzing_input, analyzer_transitions::start_output, analyzer_states::analyzing_both, 
        output("-> analyzing_both"));

    machine.add(
        analyzer_states::analyzing_output, analyzer_transitions::start_input, analyzer_states::analyzing_both,
        output("-> analyzing_both"));

    machine.add(
        analyzer_states::analyzing_input, analyzer_transitions::clear, analyzer_states::clearing_input,
        output("-> clearing_input"));

    machine.add(
        analyzer_states::analyzing_output, analyzer_transitions::clear, analyzer_states::clearing_output,
        output("-> clearing_output"));

    machine.add(
        analyzer_states::analyzing_both, analyzer_transitions::clear, analyzer_states::clearing_both,
        output("-> clearing_both"));

    machine.add(
        analyzer_states::clearing_input, analyzer_transitions::resume, analyzer_states::analyzing_input,
        output("-> analyzing_input"));

    machine.add(
        analyzer_states::clearing_output, analyzer_transitions::resume, analyzer_states::analyzing_output,
        output("-> analyzing_output"));

    machine.add(
        analyzer_states::clearing_both, analyzer_transitions::resume, analyzer_states::analyzing_both,
        output("-> analyzing_both"));

    machine.to(analyzer_transitions::start_input);
    machine.to(analyzer_transitions::start_output);
    machine.to(analyzer_transitions::stop_input);
    machine.to(analyzer_transitions::clear);
    machine.to(analyzer_transitions::resume);

    std::cout << "Done...";
    std::getchar();

    return EXIT_SUCCESS;
}

Вывод:

-> analyzing_input
-> analyzing_both
-> analyzing_output
-> clearing_output
-> analyzing_output

fsm.h:

#include <map>
#include <functional>
#include <atomic>

template <typename State, typename Transition>
class fsm
{
    using handler_t = std::function<void()>;

    class from_t
    {
        Transition transition_;
        State state_;

    public:
        from_t(Transition transition, State state) :
            transition_{ transition },
            state_{ state }
        {
        }

        bool operator<(const from_t& other) const
        {
            if (transition_ < other.transition_)
            {
                return true;
            }
            else if (transition_ > other.transition_)
            {
                return false;
            }
            else
            {
                return state_ < other.state_;
            }
        }
    };

    class to_t
    {
        State state_;
        handler_t handler_;

    public:
        to_t(State state, handler_t handler) :
            state_{ state },
            handler_{ handler }
        {
        }

        State state() const { return state_; }

        void operator()() const { handler_(); }
    };

    std::map<from_t, to_t> transitions_;
    std::atomic<State> state_;

public:
    fsm(State initial_state) :
        state_{ initial_state }
    {
    }

    void add(State from, Transition transition, State to, handler_t handler)
    {
        transitions_.insert({ { transition, from }, { to, handler } });
    }

    void add(State from, Transition transition, State to)
    {
        add(transition, to, from, [] {});
    }

    bool to(Transition transition)
    {
        auto found = transitions_.find({ transition, state_ });

        if (found != transitions_.end())
        {
            auto& to = found->second;

            state_ = to.state();

            to();

            return true;
        }
        else
        {
            return false;
        }
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...