Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

kondalrao/fsm_engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

18 Commits

Repository files navigation

Finite State Machine (FSM) Engine

This is an implementation of Finite State Machine in Python. There are many versions of this model but here is another version.

The idea here to view each FSM as an independent container for processing events. These FSM containers can run in different threads/processes/nodes. Since the data and event are together, the event dispatch can send the pair to any FSM container. The trick here is to make sure that the FSM container doesn't maintiain any context of the data. So there is a centralized data/context repository which is used by the FSM containers and the event dispatch would just pick the context-event pair and send it to a free FSM container.

The order of state, event matching is done as following sequence. (state, event) -> (action, next_state) (state, any) -> (action, next_state) (any, event) -> (action, next_state) (any, any) -> (action, next_state)

A lot of work and change of design is needed. Any help/suggestions are very helpful.

TODO:

  • Use other FSM containers other than XML like yaml/json.
  • Enhance the event dispatch mechanism.

###Simply create an fsm in XML.

<?xml version="1.0"?>
<fsm name='calc'>
 <import>simple_calc_actions</import>
 <states prefix="">
 <init>DIGIT1</init>
 <state>DIGIT1</state>
 <state>DIGIT2</state>
 </states>
 <events prefix="">
 <event>DIGIT</event>
 <event>OPERATOR</event>
 <event>WS</event>
 <event>RESULT</event>
 </events>
 <actions prefix="">
 <action>operand1</action>
 <action>operand2</action>
 <action>operator</action>
 <action>result</action>
 </actions>
 <tables>
 <table state='DIGIT1' event='DIGIT' action='operand1' next_state='DIGIT1'/>
 <table state='DIGIT1' event='OPERATOR' action='operator' next_state='DIGIT2'/>
 <table state='DIGIT2' event='DIGIT' action='operand2' next_state='DIGIT2'/>
 <table state='DIGIT2' event='RESULT' action='result' next_state='DIGIT1'/>
 <table state='Any' event='WS' action='null' next_state='Same'/>
 <table state='Any' event='Any' action='log' next_state='Same'/>
 </tables>
</fsm>

###Define actions

num1 = 0
num2 = 0
oper = ''
res = ''
def log(context):
 print ("Error Event Received.")
def null(context):
 pass
def operand1(context):
 global num1
 
 num1 = (num1 * 10) + int(context.data)
def operand2(context):
 global num2
 num2 = (num2 * 10) + int(context.data)
def operator(context):
 global oper
 oper = context.data
def result(context):
 global num1, num2, oper, res
 res = 'NOP'
 if oper == '+':
 res = num1 + num2
 elif oper == '-':
 res = num1 - num2
 elif oper == '*':
 res = num1 * num2
 elif oper == '/':
 if num2 == 0:
 res = 'NOP'
 else:
 res = float(num1) / num2
 print (' ' + str(res))
 # resetting data holders
 num1 = num2 = 0
 oper = ''

###Register and Fire events

import sys
sys.path.append('../..')
from fsm_engine import FSM
fsm_obj = None
def get_datatype(data):
 if data in ['+', '-', '*', '/']:
 return 'OPERATOR'
 elif data.isdigit():
 return 'DIGIT'
 elif data.isspace():
 return 'WS'
 elif data == '=' or data == '\n':
 return 'RESULT'
def initialize():
 global fsm_obj
 fsm_obj = FSM('calc.xml')
def main():
 initialize()
 fd = open('calc.txt')
 for line in fd.readlines():
 print (line.strip('\n'), end=''),
 for ch in line:
 if ch is not '\n':
 ev = get_datatype(ch)
 if ev is not 'WS' or ev is not 'RESULT':
 fsm_obj.dispatch(event=ev, data=ch)
 else:
 fsm_obj.dispatch(event=ev)
if __name__ == '__main__':
 main()

######Sample text file used (calc.txt)

1 +たす 2 =
123 +たす 321 =
10/2=
10/0=

About

FSM_Engine

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

AltStyle によって変換されたページ (->オリジナル) /