Я новичок в конечных автоматах и пытаюсь понять, должен ли я использовать иерархический конечный автомат или придерживаться плоской структуры, которая мне нужна, чтобы смоделировать мою проблему самым простым способом.
У меня есть «анализатор», который может быть либо остановлен, либо проанализирован вход, проанализирован выход, проанализирован вход и выход или очищен. У меня есть некоторые состояния анализатора в 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;
}
}
};