fsaclasses.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import numpy
  2. from operator import attrgetter
  3. ############### runtime classes
  4. class RunTimeEvent:
  5. def __init__(self, name, time):
  6. self.name = name
  7. self.time = time
  8. self.processed = False
  9. class Events:
  10. def __init__(self, events):
  11. self.events = sorted(events, key=attrgetter('time'))
  12. '''
  13. Returns the most recent event with the timestamp smaller than time.
  14. '''
  15. def getInputAt(self,time):
  16. event = None
  17. if self.events != []:
  18. # Claudio: this approach is assuming that the queue is sorted according the time of the events.
  19. for e in self.events:
  20. if e.time < time or numpy.isclose(e.time, time, 1e-05, 1e-08):
  21. event = e
  22. else:
  23. # stop at the first event that satisfies e.time > time
  24. break
  25. return event
  26. '''
  27. Removes event all other older events from the queue.
  28. '''
  29. def popEvent(self, event):
  30. if event == None:
  31. return
  32. assert event in self.events
  33. # Claudio: this approach is assuming that the queue is sorted according the time of the events.
  34. # first collect list of events to be removed.
  35. # then remove them.
  36. eventsToBeRemoved = []
  37. for e in self.events:
  38. eventsToBeRemoved.append(e)
  39. if e == event:
  40. break
  41. assert len(eventsToBeRemoved)>0
  42. for e in eventsToBeRemoved:
  43. self.events.remove(e)
  44. ############### static classes - invariants
  45. class Expression:
  46. def __init__(self):
  47. pass
  48. class FSAModel:
  49. def __init__(self,states,transitions):
  50. self.transitions = transitions
  51. self.states = states
  52. self.initialState = None
  53. def getTransitionFrom(self, state, event, elapsed):
  54. assert state != None
  55. assert elapsed >= 0.0
  56. # Priotiry goes to event.
  57. selectedTransition = None
  58. if event!=None:
  59. selectedTransition = self.getTriggeredTransition(state, event)
  60. # Then to after
  61. if (selectedTransition == None):
  62. selectedTransition = self.getTransitionAfter(state, elapsed)
  63. # And finally to default transitions
  64. if (selectedTransition == None):
  65. selectedTransition = self.getDefaultTransition(state)
  66. return selectedTransition
  67. def getDefaultTransition(self, state):
  68. assert state != None
  69. for t in self.transitions:
  70. if t.source == state and t.trigger == None:
  71. return t
  72. return None
  73. def getTriggeredTransition(self, state, event):
  74. assert event != None
  75. for t in self.transitions:
  76. if t.source == state and isinstance(t.trigger,Event) and t.trigger.name == event.name:
  77. return t
  78. return None
  79. def getTransitionAfter(self, state, elapsed):
  80. for t in self.transitions:
  81. if t.source == state and isinstance(t.trigger,After):
  82. if ExpressionVisitor(t.trigger.after).visit() <= elapsed:
  83. return t
  84. return None
  85. class ExpressionVisitor:
  86. def __init__(self, expression):
  87. self.expression = expression
  88. def visit(self):
  89. if(isinstance(self.expression,AtomValue)):
  90. return self.expression.value
  91. if(isinstance(self.expression,Operation)):
  92. left = ExpressionVisitor(self.expression.left).visit()
  93. right = ExpressionVisitor(self.expression.right).visit()
  94. if(self.expression.op == '+'):
  95. return left + right
  96. if(self.expression.op == '-'):
  97. return left - right
  98. if(self.expression.op == '*'):
  99. return left * right
  100. if(self.expression.op == '/'):
  101. return left / right
  102. if(self.expression.op == 'and'):
  103. return left and right
  104. if(self.expression.op == 'or'):
  105. return left or right
  106. if(isinstance(self.expression,Not)):
  107. return not ExpressionVisitor(self.expression.expression).visit()
  108. class State:
  109. def __init__(self, name, final = False):
  110. self.name = name
  111. self.final = final
  112. def getName(self):
  113. return self.name
  114. def __str__(self):
  115. return self.name
  116. class Operation(Expression):
  117. def __init__(self, left, right, op):
  118. self.op = op
  119. self.left = left
  120. self.right = right
  121. class Transition:
  122. def __init__(self,name, source,target):
  123. self.name = name
  124. self.source = source
  125. self.target = target
  126. self.trigger = None
  127. self.guard = None
  128. def __str__(self):
  129. return str(self.source) + "--" + self.name + ": " + str(self.trigger) + "-->" + str(self.target)
  130. class Trigger:
  131. def __init__(self):
  132. pass
  133. class Event(Trigger):
  134. def __init__(self,name):
  135. self.name = name
  136. def __str__(self):
  137. return self.name
  138. class After(Trigger):
  139. def __init__(self, expression):
  140. self.after = expression
  141. def __str__(self):
  142. return "after("+ str(self.after) + ")"
  143. class Guard:
  144. def __init__(self, expression):
  145. self.expression = expression
  146. class And(Operation):
  147. def __init__(self, lexpression, rexpression):
  148. self.left = lexpression
  149. self.right = rexpression
  150. self.op = "and"
  151. class Or(Operation):
  152. def __init__(self, lexpression, rexpression):
  153. self.left = lexpression
  154. self.right = rexpression
  155. self.op = "or"
  156. class Not(Expression):
  157. def __init__(self, expression):
  158. self.expression = expression
  159. class Variable(Expression):
  160. def __init__(self, varname):
  161. self.name = varname
  162. class AtomValue(Expression):
  163. def __init__(self, value):
  164. self.value = value
  165. def __str__(self):
  166. return str(self.value)
  167. class Integer(AtomValue):
  168. def __init__(self, value):
  169. self.value = value
  170. class Float(AtomValue):
  171. def __init__(self, value):
  172. self.value = value
  173. class String(AtomValue):
  174. def __init__(self, value):
  175. self.value = value