from types import * def sequence_p( sequence ): return type( sequence ) is ListType or type( sequence ) is TupleType True = 1 False = 0 class Predicate: """ Base class for predicate module """ def __call__( self, **truth_assignment ): pass def get_literals( self ): pass def toList( self ): pass def __str__( self ): return "__STRING__" class BooleanPredicate( Predicate ): """ This is the general interface through which to interact with the Predicate module This class supports the compositional evaluation of a predicate """ def __init__( self, predicate ): """ @param predicate: the initial predicate @type predicate: Any Predicate subclass """ self.predicate = predicate def get_literals( self ): unique_literals = {} for literal in self.predicate.get_literals(): if not unique_literals.has_key( literal ): unique_literals[literal] = 1 return unique_literals.keys() def _and( self, predicate ): """ @param predicate: one or more predicate objects @type predicate: list @returns: the conjuction of the Boolean Predicate with the predicate objects @rtype: And Predicate subtype """ predicate_list = [ self.predicate ] if sequence_p( predicate ): predicate_list.extend( predicate ) else: predicate_list.append( predicate ) return BooleanPredicate( And( predicate_list ) ) def _or( self, predicate ): """ @param predicate: one or more predicate objects @type predicate: list of Predicates @returns: the disjunction of the Boolean Predicate with the predicate objects @rtype: Or Predicate subtype """ predicate_list = [ self.predicate ] if sequence_p( predicate ): predicate_list.extend( predicate ) else: predicate_list.append( predicate ) return BooleanPredicate( Or( predicate_list ) ) def _not( self ): """ @returns: The negation of the Boolean Predicate @rtype: Not Predicate subtype """ return BooleanPredicate( Not( self.predicate ) ) def __call__( self, truth_assignment ): """ @param truth_assignment: Literal truth assignments @type truth_assignment: a dictionary of Literal names associated with True or False values @returns: The evaluated Boolean expression @rtype: boolean """ return self.predicate( truth_assignment ) def __repr__( self ): return str( self.predicate ) def __str__( self ): """ @returns: A string representation of the boolean predicate @rtype: string """ return str( self.predicate ) def toList( self ): return self.predicate.toList() def replace( self, replacement ): self.predicate.replace( replacement ) class Literal( Predicate ): """ A Literal is anything that can be directly assigned a truth value. """ def __init__( self, atom ): self.atom = atom def __call__( self, truth_assignment ): if self.atom == '': return False elif not truth_assignment.has_key( self.atom ): return False else: return truth_assignment[ self.atom ] def __str__( self ): return str( self.atom ) def __eq__( self, literal ): if isinstance( literal, Literal ): return self.atom == literal.atom else: return str( self.atom ) == str( literal ) def __repr__( self ): return str( self.atom ) def get_literals( self ): return [ str( self.atom ) ] def toList( self ): return str( self.atom ) class PolyadicPredicate( Predicate ): """ An abstract class to factor out methods common to And and Or. """ def __init__( self, operands ): self.operands = [] if sequence_p( operands ): for operand in operands: if isinstance( operand, Predicate ): self.operands.append( operand ) else: self.operands.append( Literal( operand ) ) else: self.operands = [ operands ] def get_literals( self ): literals = [] for operand in self.operands: literals.extend( operand.get_literals() ) return literals def replace( self, replacement ): i = 0 for operand in self.operands: if isinstance( operand, Literal ): if replacement.has_key( `operand` ): self.operands[i] = replacement[`operand`] else: operand.replace( replacement ) i = i+1 class And( PolyadicPredicate ): """ And is the conjuction of one or more predicates """ def __call__( self, truth_assignment ): for operand in self.operands: if not operand( truth_assignment ): return False return True def toList( self ): return ['and', self.operands.toList() ] def __str__( self ): return "(AND " + ' '.join( map( str, self.operands ) ) + ")" class Or( PolyadicPredicate ): """ Or is the disjunction of one or more predicates """ def __call__( self, truth_assignment ): for operand in self.operands: if operand( truth_assignment ): return True return False def __str__( self ): return "(OR " + ' '.join( map( str, self.operands ) ) + ")" def toList( self ): [operand.toList() for operand in self.operands()] return class Not( Predicate ): """ Not is the negation of a predicate """ def __init__( self, operand ): self.operand = operand def __call__( self, truth_assignment ): return not self.operand( truth_assignment ) def __str__( self ): return "(NOT %s)" % str( self.operand ) def get_literals( self ): return [ str( self.operand ) ] def replace( self, replacement ): if isinstance( self.operand, Literal ): if replacement.has_key( `self.operand` ): self.operand = replacement[`self.operand`] else: self.operand.replace( replacement )