def emission(self): """Sending a message must be preceded by observation of its ins, but cannot be preceded by observation of any nils or outs""" s = partial(observe, self.sender) ins = [impl(self.sent, sequential(s(p), self.sent)) for p in self.ins] nils = [impl(and_(self.sent, s(p)), sequential(self.sent, s(p))) for p in self.nils] outs = [impl(self.sent, simultaneous(s(p), self.sent)) for p in self.outs] return and_(*(ins + nils + outs))
def minimality(self, protocol): """Every parameter observed by a role must have a corresponding message transmission or reception""" sources = {} def add(m, p): if p in sources: sources[p].append(m) else: sources[p] = [m] outgoing = set() for m in self.messages(protocol).values(): if m.recipient == self: for p in m.ins.union(m.outs): add(m, p) else: for p in m.outs: add(m, p) for p in m.ins: outgoing.add(p) # keep track of 'in' parameters being sent without sources # unsourced parameters cannot be observed unsourced = [logic.Name(~self.observe(p), p) for p in outgoing - set(sources.keys())] # sourced parameters must be received or sent to be observed sourced = [logic.Name(impl(self.observe(p), or_(*[simultaneous(self.observe(m), self.observe(p)) for m in sources[p]])), p) for p in sources] return logic.And(*(unsourced + sourced))
def reception(self): "Each message reception is accompanied by the observation of its parameters; either they are observed, or the message itself is not" clauses = [impl(self.received, or_(sequential(p, self.received), simultaneous(p, self.received))) for p in map(partial(observe, self.recipient), self.ins | self.outs)] return and_(*clauses)
def non_lossy(self): "Each message emission results in reception" return impl(self.sent, self.received)
def transmission(self): "Each message reception is causally preceded by its emission" return impl(self.received, sequential(self.sent, self.received))