Showing posts with label statemachine. Show all posts
Showing posts with label statemachine. Show all posts

Friday, October 2, 2009

Python State Machine

State machines are handy during software development to help visualize the changing states of either a single instance, or a group of instances over time. Modeling state machines is also useful for visualizing the events that cause instances to change state. It is for this reason that the UML includes states and state machines.

State machines aren't limited to visualizations. They can also be directly implemented. The StatePy Python package provides a basic set of abstractions that developers can use to implement such a state machine. The elements include states and machines. Also included are events that trigger state transitions. There is currently no support for defining composite states but this package seems to be early on in development. Below is a simple example of how to setup a state machine.
#Example; Creating Python States.

#Do imports.
from statepy.state import State, Machine, Event

#Printing state.
class StatePrinting(State):

#Constructor. Initialize the State.
def __init__(self, *args, **kw):
State.__init__(self, *args, **kw)

#On state entry.
def enter(self):
print "Printing..."

#On state exit.
def exit(self):
print "Finished printing..."

#Sorting state.
class StateSorting(State):

#Constructor. Initialize the State.
def __init__(self, *args, **kw):
State.__init__(self, *args, **kw)

#On state entry.
def enter(self):
print "Sorting..."

#On state exit.
def exit(self):
print "Finished sorting..."

#Provided state transitions.
@staticmethod
def transitions():
return {"FINISHED_SORTING":StatePrinting}

#Building state.
class StateBuilding(State):

#Constructor. Initialize the State.
def __init__(self, *args, **kw):
State.__init__(self, *args, **kw)

#On state entry.
def enter(self):
print "Building..."

#On state exit.
def exit(self):
print "Finished building..."

#Provided state transitions.
@staticmethod
def transitions():
return {"FINISHED_BUILDING":StateSorting}

#Main.
if __name__=="__main__":

#Initialize the machine.
machine_obj=Machine()

#Start the machine in a building state.
machine_obj.start(StateBuilding)

#Pass the transition events to the machine.
machine_obj.injectEvent(Event("FINISHED_BUILDING"))
machine_obj.injectEvent(Event("FINISHED_SORTING"))

Wednesday, May 6, 2009

Creating State Machines in Python

In the UML, state machines help modelers understand the various states the system in question goes through. When the system is in one state, the available behavior differs from when the system is in another state. Visualizing these states by drawing them as UML elements is an extremely powerful tool. State machines are not only powerful for examining the potential states of a given system, but also in helping to understand the transitions that could potentially take place between these states. In object-orientated systems, the concept of objects being in one state or another is often implemented in code, even if implicitly. Given that this is object-oriented code we are working with, and the whole idea behind object orientation is to assist with creating realistic abstractions, why not use the concept of state machines directly in code? The 0.1.6 version of the boduch Python library tries to realize this possibility. Although this is the first iteration of this new feature, with lots of work left to do, it seems promising. Below is an example of the new StateMachine class in use.

#Example; Using boduch state machines.

from boduch.state import StateMachine
from boduch.predicate import Equal

#Define two predicate functions used to return
#the predicate variables.
def get_o1():
return o1

def get_o2():
return o2

#The two predicate variables. Notice they
#aren't equal.
o1=1
o2=2

#Construct a state machine instance.
state_obj=StateMachine()

#Construct a predicate instance using the
#two previously defined predicate functions.
predicate_obj=Equal(get_o1, get_o2)

#Populate the state machine with two states.
state_obj.add_state("RUNNING")
state_obj.add_state("STOPPED")

#Add a state transition to the machine using
#the previously defined predicate. Once true,
#the machine will be in the target state.
state_obj.add_transition("STOPPED", predicate_obj)

if __name__=="__main__":
#Change the machine to a RUNNING state.
state_obj.change_state("RUNNING")
print state_obj.current_state

#Change the value of the predicate variable.
o2=1
print "o2 now equals o1"

#Check for any state changes.
state_obj.transition()
print state_obj.current_state

Be brief overview of the above code follows below.
  • Import the classes required. There are StateMachine and Equal.
  • Define the predicate functions. These functions are used by the predicate associated with the state machine. They are invoked each time the predicate is evaluated.
  • Define the predicate variables. These variables are global and are returned by the predicate functions. Any changes to these variables are reflected by invoking the predicate functions.
  • Create a new StateMachine instance. This is the main state machine involved in the example.
  • Create a new Equal predicate instance and use the predicate functions as operands.
  • Populate the state machine instance with some states. A state can be any Python object.
  • Add a new transition to the state machine using the previously defined Equal instance. When this predicate instance evaluates to true, the target state, in this case, "STOPPED", will become the active state.
  • Set the initial state to "RUNNING".
  • Change the value of one of the predicate variables. The predicate can now be considered equal.
  • Test the state machine for any state changes. Here, there are changes because the transition that was previously added to the state machine will evaluate to true, causing the target of the transition to become the active state.
  • The state machine is now in a "STOPPED" state.