def __init__(self, name, guard=None, **args): self.pids = PidEnv(args.pop("pids", "")) vars = WordSet(self.pids.vars()) if self.pids.spawned: assign = [] for parent, children in self.pids.spawned.items(): pidcount = vars.fresh(add=True, base="next_%s" % parent) self.pids.next[parent] = pidcount for n, child in enumerate(children): assign.append("%s=%s.next(%s+%s)" % (child, parent, n, pidcount)) if guard is None: guard = snk.Expression("newpids(%s)" % ", ".join(assign)) else: guard = guard & snk.Expression("newpids(%s)" % ", ".join(assign)) snk.Transition.__init__(self, name, guard, **args)
def __init__(self, name, guard=None, **args): self.pids = PidEnv(args.pop("pids", "")) vars = WordSet(self.pids.vars()) if self.pids.spawned: assign = [] for parent, children in self.pids.spawned.items(): pidcount = vars.fresh(add=True, base="next_%s" % parent) self.pids.next[parent] = pidcount for n, child in enumerate(children): assign.append("%s=%s.next(%s+%s)" % (child, parent, n, pidcount)) if guard is None: guard = snk.Expression("newpids(%s)" % ", ".join(assign)) else: guard = guard & snk.Expression( "newpids(%s)" % ", ".join(assign)) snk.Transition.__init__(self, name, guard, **args)
def synchronise (self, other, name, common, allnames) : """Search all the possible synchronisation on an action name with another multiaction. This method returns an iterator that yields for each possible synchronisation a 4-tuple whose components are: * the sending action that did synchronise, it is already unified, so the corresponding receiving action is just the same with the reversed send flag * the multiaction resulting from the synchronisation that is also unified * the substitution that must be applied to the transition that provided the sending action * the substitution that must be applied to the transition that provided the receiving action >>> m = MultiAction([Action('a', True, [Variable('x'), Value(2)]), ... Action('a', True, [Value(3), Variable('y')]), ... Action('b', False, [Variable('x'), Variable('y')])]) >>> n = MultiAction([Action('a', False, [Variable('w'), Variable('y')]), ... Action('c', False, [Variable('y')])]) >>> _m, _n = m.vars(), n.vars() >>> for a, x, u, v in m.synchronise(n, 'a', _m & _n, _m | _n) : ... print('%s %s' % (str(a), str(x))) ... print(list(sorted(u.items()))) ... print(list(sorted(v.items()))) a!(w,2) [a!(3,d), b?(w,d), c?(2)] [('x', Variable('w')), ('y', Variable('d'))] [('x', Variable('w')), ('y', Value(2))] a!(3,y) [a!(x,2), b?(x,y), c?(y)] [('d', Variable('y')), ('w', Value(3)), ('y', Variable('d'))] [('d', Variable('y')), ('w', Value(3))] @param other: the other multiaction to synchronise with @type other: `MultiAction` @param name: the name of the action to synchronise on @type name: `str` @param common: the set of names in common on both transitions @type common: `set` @param allnames: the set of all names involved in the transitions @type allnames: `set` @return: an iterator over the possible synchronisations @rtype: iterator of `tuple(Action, MultiAction, Substitution, Substitution)` """ renamer = Substitution() if common : names = WordSet(set(allnames) | self.names() | other.names()) for var in common : renamer += Substitution({var : Variable(names.fresh(add=True))}) for left in (act for act in self._actions if act.name == name) : for right in (act for act in other._actions if act.name == name if act.send != left.send) : _left = left.copy(renamer) try : unifier = _left & right except : continue _self = self.copy(renamer) - _left _self.substitute(unifier) _other = other - right _other.substitute(unifier) yield (_left.copy(unifier), _self + _other, unifier * renamer, unifier)
def synchronise(self, other, name, common, allnames): """Search all the possible synchronisation on an action name with another multiaction. This method returns an iterator that yields for each possible synchronisation a 4-tuple whose components are: * the sending action that did synchronise, it is already unified, so the corresponding receiving action is just the same with the reversed send flag * the multiaction resulting from the synchronisation that is also unified * the substitution that must be applied to the transition that provided the sending action * the substitution that must be applied to the transition that provided the receiving action >>> m = MultiAction([Action('a', True, [Variable('x'), Value(2)]), ... Action('a', True, [Value(3), Variable('y')]), ... Action('b', False, [Variable('x'), Variable('y')])]) >>> n = MultiAction([Action('a', False, [Variable('w'), Variable('y')]), ... Action('c', False, [Variable('y')])]) >>> _m, _n = m.vars(), n.vars() >>> for a, x, u, v in m.synchronise(n, 'a', _m & _n, _m | _n) : ... print('%s %s' % (str(a), str(x))) ... print(list(sorted(u.items()))) ... print(list(sorted(v.items()))) a!(w,2) [a!(3,d), b?(w,d), c?(2)] [('x', Variable('w')), ('y', Variable('d'))] [('x', Variable('w')), ('y', Value(2))] a!(3,y) [a!(x,2), b?(x,y), c?(y)] [('d', Variable('y')), ('w', Value(3)), ('y', Variable('d'))] [('d', Variable('y')), ('w', Value(3))] @param other: the other multiaction to synchronise with @type other: `MultiAction` @param name: the name of the action to synchronise on @type name: `str` @param common: the set of names in common on both transitions @type common: `set` @param allnames: the set of all names involved in the transitions @type allnames: `set` @return: an iterator over the possible synchronisations @rtype: iterator of `tuple(Action, MultiAction, Substitution, Substitution)` """ renamer = Substitution() if common: names = WordSet(set(allnames) | self.names() | other.names()) for var in common: renamer += Substitution({var: Variable(names.fresh(add=True))}) for left in (act for act in self._actions if act.name == name): for right in (act for act in other._actions if act.name == name if act.send != left.send): _left = left.copy(renamer) try: unifier = _left & right except: continue _self = self.copy(renamer) - _left _self.substitute(unifier) _other = other - right _other.substitute(unifier) yield (_left.copy(unifier), _self + _other, unifier * renamer, unifier)