def test_occurrence(): occ = occurrence(relationships([simultaneous('a', 'b')])) print('occurrence: ', occ) formula = and_(simultaneous('a', 'b'), not_(var('a')), *occ) print('formula: ', formula) s = formula.sat()[1] if s: print('solution: ', [k for k, v in s.items() if v]) assert not s
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 blocked(self): s = partial(observe, self.sender) ins = [~s(p) for p in self.ins] nils = [and_(s(p), ~(sequential(s(p), self.sent) | simultaneous(s(p), self.sent))) for p in self.nils] outs = [s(p) for p in self.outs] return or_(*(nils + outs + ins))
def test_timeline(): statements = [simultaneous('a', 'b'), sequential('b', 'a')] t = timeline(relationships(statements)) print('timeline: ', t) formula = and_(var('a'), var('b'), *(t + statements)) print('formula: ', formula) s = formula.sat()[1] if s: print('solution: ', [k for k, v in s.items() if v]) assert not s
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 uniqueness(self, key): "Bindings to key parameters uniquely identify enactments, so there should never be multiple messages with the same out key in the same enactment" candidates = set() for m in self.messages.values(): if key in m.outs: candidates.add(simultaneous( m.sent, observe(m.sender, key))) if candidates: return onehot0(*candidates) else: return True
def test_relationships(): statements = [simultaneous('a', 'b'), sequential('a', 'b')] rs = relationships(statements) assert ('a', 'b') in rs and len(rs[('a', 'b')]) == 2