def merge(self, net, nodes, name=None): """Merge `nodes` in `net` Safe buffers places with the status `Safebuffer('safebuffer', None)` are not merged. Other safe buffers places are merged if they all have the same marking, which becomes the marking of the resulting place. Otherwise, `ConstraintError` is raised. If `name` is `None` the name generated is a concatenation of the nodes names separated by '+', with parenthesis outside. @param net: the Petri net where places should be merged @type net: `PetriNet` @param nodes: a collection of place names to be merged @type nodes: iterable of `str` @param name: the name of the new place or `Node` if it should be generated @type name: `str` """ if self._value is None: return marking = net.place(nodes[0]).tokens for node in nodes[1:]: if net.place(node).tokens != marking: raise ConstraintError("incompatible markings") if name is None: name = "(%s)" % "+".join(sorted(nodes)) net.merge_places(name, nodes, status=self) for src in nodes: net.remove_place(src) net.set_status(name, self) net.place(name).reset(marking)
def __init__(self, pid, counter, new_pids, components): if len(components) == 0: raise ConstraintError("missing tuple components") self.pid = pid self.counter = counter self.new_pids = new_pids self.components = components self.input_allowed = False
def remove(self, tokens): """Remove tokens from the place. @param tokens: a collection of tokens to be removed from the place, note that `str` are not considered as iterable and used a a single value instead of as a collection @type tokens: `collection` """ if len(self.tokens) - len(list(iterate(tokens))) < self._bound_min: raise ConstraintError( "lower bound of place %r reached" % self.name) module.Place.remove(self, tokens)
def reset(self, tokens): """Replace the marking with `tokens`. @param tokens: a collection of tokens to be removed from the place, note that `str` are not considered as iterable and used a a single value instead of as a collection @type tokens: `collection` """ count = len(list(iterate(tokens))) bmax = count if self._bound_max is None else self._bound_max if not (self._bound_min <= count <= bmax): raise ConstraintError( "not within bounds of place %r" % self.name) module.Place.reset(self, tokens)
def add(self, tokens): """Add tokens to the place. @param tokens: a collection of tokens to be added to the place, note that `str` are not considered as iterable and used a a single value instead of as a collection @type tokens: `collection` """ if (self._bound_max is not None and len(self.tokens) + len(list(iterate(tokens))) > self._bound_max): raise ConstraintError( "upper bound of place %r reached" % self.name) module.Place.add(self, tokens)
def add(self, action): """Add an action to the multiaction. This may raise `ConstraintError` if the added action is conjugated to one that already belongs to the multiaction. @param action: the action to add @type action: `Action` """ if self._sndrcv.get(action.name, action.send) != action.send: raise ConstraintError("conjugated actions in the same multiaction") self._sndrcv[action.name] = action.send self._count[action.name] = self._count.get(action.name, 0) + 1 self._actions.append(action)
def __add__(self, other): if self == other: return self.copy() else: raise ConstraintError("incompatible status")
def __and__(self, other): """Compute an unification of two conjugated actions. An unification is a `Substitution` that maps variable names to `Variable` or `Values`. If both actions are substituted by this unification, their parameters lists become equal. If no unification can be found, `ConstraintError` is raised (or, rarely, `DomainError` depending on the cause of the failure). >>> s = Action('a', True, [Value(3), Variable('x'), Variable('y'), Variable('x')]) >>> r = Action('a', False, [Value(3), Value(2), Variable('t'), Variable('z')]) >>> u = s & r >>> u == Substitution(y=Variable('t'), x=Value(2), z=Value(2)) True >>> s.substitute(u) >>> r.substitute(u) >>> s.params == r.params True >>> s.params [Value(3), Value(2), Variable('t'), Value(2)] >>> s = Action('a', True, [Value(2), Variable('x'), Variable('y'), Variable('x')]) >>> r = Action('a', False, [Value(3), Value(2), Variable('t'), Variable('z')]) >>> try : s & r ... except ConstraintError : print(sys.exc_info()[1]) incompatible values >>> r = Action('a', False, [Value(2), Value(2), Variable('t')]) >>> try : s & r ... except ConstraintError : print(sys.exc_info()[1]) arities do not match >>> r = Action('b', False, [Value(3), Value(2), Variable('t'), Variable('z')]) >>> try : s & r ... except ConstraintError : print(sys.exc_info()[1]) actions not conjugated >>> r = Action('a', True, [Value(3), Value(2), Variable('t'), Variable('z')]) >>> try : s & r ... except ConstraintError : print(sys.exc_info()[1]) actions not conjugated @param other: the other action to unify with @type other: `Action` @return: a substitution that unify both actions @rtype: `Substitution` """ if (self.name != other.name) or (self.send == other.send): raise ConstraintError("actions not conjugated") elif len(self) != len(other): raise ConstraintError("arities do not match") result = Substitution() for x, y in zip(self.params, other.params): # apply the unifier already computed if isinstance(x, Variable) and x.name in result: x = result(x.name) if isinstance(y, Variable) and y.name in result: y = result(y.name) # unify the current pair of parameters if isinstance(x, Value) and isinstance(y, Value): if x.value != y.value: raise ConstraintError("incompatible values") elif isinstance(x, Variable) and isinstance(y, Value): result += Substitution({x.name: y.copy()}) elif isinstance(x, Value) and isinstance(y, Variable): result += Substitution({y.name: x.copy()}) elif isinstance(x, Variable) and isinstance(y, Variable): if x.name != y.name: result += Substitution({x.name: y.copy()}) else: raise ConstraintError("unexpected action parameter") return result