def correct(self): clauses = [] for m in self.messages.values(): clauses.append( logic.And(m.emission, m.reception, m.transmission, m.non_lossy)) for r in self.roles.values(): clauses.append( logic.And(r.nonsimultaneity(self), r.minimality(self))) return logic.And(*clauses)
def unsafe(self): clauses = [] for p in self.public_parameters: # only public out parameters can have safety conflicts sources = [ m for m in self.p_cover(p) if m.parameters[p].adornment == 'out' ] if len(sources) > 1: alts = [] for r in self.roles.values(): # assume an agent can choose between alternative messages msgs = [m.sent for m in sources if m.sender == r] if msgs: alts.append(or_(*msgs)) # at most one message producing this parameter can be sent more_than_one = or_(*pairwise(and_, alts)) # only consider cases where more than one at once is possible if more_than_one: clauses.append(logic.Name(more_than_one, p + "-unsafe")) if clauses: # at least one conflict return logic.And(self.correct, logic.Name(clauses, "unsafe")) else: # no conflicting pairs; automatically safe -> not unsafe return bx.ZERO
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 handle_enactability(protocol, args): reset_stats() e = protocol.is_enactable() print(" Enactable: ", bool(e)) if args.verbose or args.stats: print(" stats: ", stats) if not e and not args.quiet or args.verbose: print_formula(logic.And(protocol.correct, protocol.enactability)) if e and args.verbose: pp.pprint(e) return e
def dead_end(self): return logic.And(self.correct, self.maximal, self.incomplete)
def cover(self): return logic.And(*[ logic.Name(or_(*[m.received for m in self.p_cover(p)]), p.name + "-cover") for p in self.public_parameters.values() ])
def is_enactable(self): if self.enactable is None: self.enactable = consistent( logic.And(self.correct, self.enactability)) return self.enactable
def inner(q, r): formula = logic.And(c, m, r.enactability, q.incomplete) return formula
def atomicity(self): return [ logic.And(self.correct, self.maximal, r.enactability, q.incomplete) for q, r in self.refp ]