Finite state machine: Difference between revisions

From Rosetta Code
Content added Content deleted
mNo edit summary
No edit summary
Line 1: Line 1:
{{task|Finite state machine}}
{{task}}


A [[wp:Finite state machine|Finite state machine]] (FSM) is computational abstraction which maps a finite number of states to other states in the same set via transitions. Transitions can either be explicit or implicit (ie: "automatic"/sequenced). An FSM can only be in one state at any given moment.
A [[wp:Finite state machine|Finite state machine]] (FSM) is computational abstraction which maps a finite number of states to other states in the same set via transitions. Transitions can either be explicit or implicit (ie: "automatic"/sequenced). An FSM can only be in one state at any given moment.

Revision as of 05:01, 24 August 2017

Task
Finite state machine
You are encouraged to solve this task according to the task description, using any language you may know.

A Finite state machine (FSM) is computational abstraction which maps a finite number of states to other states in the same set via transitions. Transitions can either be explicit or implicit (ie: "automatic"/sequenced). An FSM can only be in one state at any given moment.

Task

Implement a simple finite state machine which handles both explicit and implicit transitions. Then demonstrate an example which models some real-world process (such as a vending machine).


See also

C++

<lang C>

  1. include <map>

template <typename State, typename Transition = State> class finite_state_machine { protected: std::map<State, std::map<Transition, State>> database; State stored; public: finite_state_machine() { set(State()); } void set(State const& state) { stored = state; } State get() const { return stored; } void add(State const& state, Transition const& transition, State const& next) { database[state][transition] = next; } /* Add a state which is also it's own transition (and thus a link in a chain of sequences)

  • /

void add(State const& state_and_transition, State const& next) { add(state_and_transition, state_and_transition, next); } bool process(Transition const& transition) { auto const& transitions = database[stored], found = transitions.find(transition); if(found == transitions.end()) return false; auto const& next = found->second; set(next); return true; } /* Process so-called "automatic transitions" (ie: sequencing)

  • /

bool process() { return process(get()); } /* A set of utility functions that may be helpful for displaying valid transitions to the user, etc...

  • /

template <typename Container> bool get_valid_transitions(State const& state, Container& container) { container.clear(); auto const& states = database.find(state); if(states == database.end()) return false; auto const& transitions = states->second; if(transitions.size() == 0) return false; for(auto const& next : transitions) container.push_back(next.first); return true; } template <typename Container> bool get_valid_transitions(Container& container) { return get_valid_transitions(get(), container); } void clear() { database.clear(); } };

/* Example usage: a simple vending machine

  • /
  1. include <string>
  2. include <vector>
  3. include <iostream>

using namespace std; void print(string const& message) { cout << message << endl; } int main() { finite_state_machine<string> machine; machine.add("ready", "quit", "exit"); machine.add("ready", "deposit", "waiting"); machine.add("waiting", "selection", "dispense"); machine.add("waiting", "refund", "refunding"); machine.add("dispense", "remove", "ready"); machine.add("dispense", "stuck", "refunding"); machine.add("refunding", "ready"); machine.set("ready"); for(;;) { string state = machine.get(); if(state == "ready") print("Please deposit coins."); else if(state == "waiting") print("Please make a selection!"); else if(state == "dispense") print("Dispensed...please remove product from tray."); else if(state == "refunding") print("Refunding money..."); else if(state == "exit") break; /* Handle "automatic" transitions */ if(machine.process()) continue; vector<string> transitions; machine.get_valid_transitions(transitions); string options; for(auto const& text : transitions) { if(!options.empty()) options += ", "; options += text; } print("[" + machine.get() + "] Enter next transition (" + options + "): "); string transition; cout << " > "; cin >> transition; if(!machine.process(transition)) print( "Error: invalid transition!"); } } </lang>

Output:
Please deposit coins.
[ready] Enter next transition (deposit, quit): 
 > deposit
Please make a selection!
[waiting] Enter next transition (refund, selection): 
 > selection
Dispensed...please remove product from tray.
[dispense] Enter next transition (remove, stuck): 
 > stuck
Refunding money...
Please deposit coins.
[ready] Enter next transition (deposit, quit): 
 > deposit
Please make a selection!
[waiting] Enter next transition (refund, selection): 
 > refund
Refunding money...
Please deposit coins.
[ready] Enter next transition (deposit, quit): 
 > deposit
Please make a selection!
[waiting] Enter next transition (refund, selection): 
 > selection
Dispensed...please remove product from tray.
[dispense] Enter next transition (remove, stuck): 
 > remove
Please deposit coins.
[ready] Enter next transition (deposit, quit): 
 > quit