concurrency.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. from sccd.common.exceptions import *
  2. from sccd.statechart.static.tree import *
  3. from abc import *
  4. class SmallStepConsistency:
  5. @abstractmethod
  6. def can_fire_together(self, t1: Transition, t2: Transition) -> bool:
  7. pass
  8. class NoConcurrency(SmallStepConsistency):
  9. def can_fire_together(self, t1: Transition, t2: Transition) -> bool:
  10. return False
  11. class ArenaOrthogonal(SmallStepConsistency):
  12. def can_fire_together(self, t1: Transition, t2: Transition) -> bool:
  13. return not (t1.arena_bitmap & t2.arena_bitmap) # nonoverlapping arenas
  14. class SrcDstOrthogonal(SmallStepConsistency):
  15. def __init__(self, tree: StateTree):
  16. self.tree = tree
  17. def can_fire_together(self, t1: Transition, t2: Transition) -> bool:
  18. source_lca = self.tree.lca(t1.source, t2.source)
  19. target_lca = self.tree.lca(t1.target, t2.target)
  20. return isinstance(source_lca.type, AndState) and isinstance(target_lca.type, AndState)
  21. # Raises an exception if the given set of transitions can potentially be enabled simulatenously, wrt. their source states in the state tree.
  22. def check_nondeterminism(tree: StateTree, transitions: Iterable[Transition], consistency: SmallStepConsistency):
  23. pairs = itertools.combinations(transitions, 2)
  24. for t1, t2 in pairs:
  25. if consistency.can_fire_together(t1, t2):
  26. return # It's OK: if they are both enabled, they will fire together in a small step
  27. # They have the same source:
  28. if t1.source is t2.source:
  29. raise ModelStaticError("Nondeterminism! No priority between outgoing transitions of same state: %s, %s" % (t1, t2))
  30. # Their sources are orthogonal to each other:
  31. lca = tree.lca(t1.source, t2.source)
  32. if isinstance(lca.type, AndState):
  33. raise ModelStaticError("Nondeterminism! No priority between orthogonal transitions: %s, %s" % (t1, t2))
  34. # Their source states are ancestors of one another:
  35. if is_ancestor(t1.source, t2.source) or is_ancestor(t2.source, t1.source):
  36. raise ModelStaticError("Nondeterminism! No priority between ancestral transitions: %s, %s" % (t1, t2))