Showing posts with label predicate. Show all posts
Showing posts with label predicate. Show all posts

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.

Saturday, March 14, 2009

Using predicates with the boduch library

With the latest release of the boduch Python library, there are two new predicate classes available; Greater and Lesser. These predicates do exactly what the name says. The Greater predicate will evaluate to true if the first operand is greater than the second. The Lesser predicate will return true if the first operand is less than the operand. Here is an example of how we would use these predicates.
#Example; boduch predicates

from boduch.predicate import Greater, Lesser

if __name__=="__main__":
is_greater=Greater(2,1)
is_lesser=Lesser(1,2)

if is_greater:
print "is_greater is true."
else:
print "is_greater is false."
if is_lesser:
print "is_lesser is true."
else:
print "is_lesser is false"

Here, we have two predicate instances, is_greater and is_lesser. The is_greater variable is an instance of the Greater predicate and will evaluate to true in this case. The is_lesser variable is an instance of the Lesser predicate and will evaluate to true in this case.

With the latest release the library, predicate instances can also accept function objects as parameters. For example, consider the following modified example.
#Example; boduch predicates

from boduch.predicate import Greater, Lesser

number1=0
number2=0

def op1():
global number1
return number1

def op2():
global number2
return number2

def results():
global is_greater
global is_lesser
if is_greater:
print "is_greater is true."
else:
print "is_greater is false."
if is_lesser:
print "is_lesser is true."
else:
print "is_lesser is false"

if __name__=="__main__":
#Construct predicate instances using function objects as operands.
is_greater=Greater(op1,op2)
is_lesser=Lesser(op1,op2)

#Change the value of the operands.
number1=2
number2=1

#Print results.
results()

#Change the value of the operands.
number1=1
number2=2

#Print results.
results()

Here, we now have two variables, number1 and number2 that will act as operands. Next, we have two functions that will return these values, op1() and op2(). Next, the results() function simply prints the result of evaluating the predicates. In the main program, we construct the two predicate instances, passing the op1() and op2() functions as operand parameters. Next, we initialize the number1 and number2 variables and print the result of evaluating the predicates. Finally, we change the value of number1 and number2 and once more print the results. You'll notice that the results will have reflected the change in number1 and number2.

Wednesday, March 4, 2009

Using predicates with the boduch library

The boduch Python library has a new Predicate class that can be used to evaluate predicates. The Predicate class is meant to be an abstract super class. As of the 0.1.2 release of the library, there is only an Equal predicate. This predicate can be used to test the equality of two specified values. For example, consider the following.
#Example; Using the boduch.predicate.Equal predicate.

from boduch.predicate import Equal

if __name__=="__main__":
val1="My Value"
val2="My Value"
while Equal(val1, val2):
print "Changing val1 in order to exit our loop."
val1="Exit"
print val1
In this example, we define two string values; val1 and val2. We then use the Equal predicate as our loop condition. The Equal predicate will always evaluate to true as long as the two specified operators are equal. The Equal predicate uses the == Python operator to evaluate the result. So, why bother with the boduch predicates? One reason would be consistency if you are using the library elsewhere in the application. Another reason may be readability.

The Equal predicate is actually a Python class. Every time we instantiate Equal(), we are actually evaluating against an Equal instance. The equal predicate defines overloaded operators that handle the comparison when the instance is used in that context. There are also events and handles for predicates in the boduch library. If necessary, other handles may subscribe to these events. However, the events published by predicates in the boduch library are atomic. This means that no new threads will be started for these handles.

The next release of the library should have some more interesting predicates such as Greater and Less.