def trap_predicate(self, number: int) -> mona.Formula: guard = self.guard_as_mona() variables = sorted([cast(mona.Variable, v.as_mona()) for v in self.free_variables], key=str) ports = self.ports.predicates free_pre = mona.Disjunction([p.hit_pre() for p in ports]) free_post = mona.Disjunction([p.hit_post() for p in ports]) safe_post: List[mona.Formula] = [free_post] broadcast_local: List[mona.Formula] = [] if self.broadcasts: broadcasts_one_post = mona.Disjunction([b.one_post() for b in self.broadcasts]) safe_post.append(broadcasts_one_post) broadcasts_vertical = mona.Conjunction( [cast(mona.Formula, mona.Negation(free_pre))] + [b.vertical_hit() for b in self.broadcasts]) broadcast_local.append(broadcasts_vertical) inner = mona.Disjunction([ mona.Disjunction(safe_post), mona.Conjunction([mona.Negation(free_pre), mona.Conjunction(broadcast_local)]) ]) formula = mona.UniversalFirstOrder(variables, mona.Implication(guard, inner)) return mona.PredicateDefinition(f"trap_transition_{number}", self.system.state_variables, [], formula).simplify()
def unique_intersection_predicate(self) -> mona.Formula: x = mona.Variable("x") y = mona.Variable("y") one_states = [mona.Variable(f"one{s}") for s in self.system.states] two_states = [mona.Variable(f"two{s}") for s in self.system.states] pairs = list(zip(one_states, two_states)) statements: List[mona.Formula] = [] # fix x in intersection of one state: for pair in pairs: pos = [cast(mona.Formula, mona.ElementIn(x, state)) for state in pair] different_pairs = [p for p in pairs if p != pair] neg = [ # negated statement from above cast(mona.Formula, mona.Negation( mona.Conjunction( [mona.ElementIn(x, state) for state in pair]))) # for all other pairs for pair in different_pairs] statements.append(mona.Conjunction(pos + neg)) fix_x = mona.Disjunction(statements) # make sure x is unique: # y is in intersection y_in_intersection = mona.Disjunction([ mona.Conjunction([mona.ElementIn(y, state) for state in pair]) for pair in pairs]) # y is x if y is in intersection unique_x = mona.UniversalFirstOrder( [y], mona.Implication(y_in_intersection, mona.Equal(x, y))) formula = mona.ExistentialFirstOrder([x], mona.Conjunction([fix_x, unique_x])) return mona.PredicateDefinition( "unique_intersection", one_states + two_states, [], formula).simplify()
def marking_predicate(self) -> mona.Formula: m = mona.Variable("m") unique_in_component = mona.UniversalFirstOrder( [m], mona.Conjunction([ mona.Disjunction([ mona.Conjunction( [cast(mona.Formula, mona.ElementIn(m, pos))] + [cast(mona.Formula, mona.ElementNotIn(m, neg)) for neg in c.state_variables if neg != pos]) for pos in c.state_variables]) for c in self.system.components])) flow_invariant = mona.PredicateCall("flow_invariant", self.system.state_variables) trap_invariant = mona.PredicateCall("trap_invariant", self.system.state_variables) return mona.PredicateDefinition( "marking", self.system.state_variables, [], mona.Conjunction([ unique_in_component, flow_invariant, trap_invariant, ])).simplify()
def intersects_initial_predicate(self) -> mona.Formula: x = mona.Variable("x") initial_states = [mona.Variable(c.initial_state) for c in self.system.components] x_initial = mona.Disjunction( [mona.ElementIn(x, init) for init in initial_states]) formula = mona.ExistentialFirstOrder([x], x_initial) return mona.PredicateDefinition("intersects_initial", self.system.state_variables, [], formula).simplify()
def deadlock_predicate(self) -> mona.Formula: inner = mona.Conjunction( [mona.PredicateCall(f"dead_transition_{number}", self.system.state_variables) for number in range(1, len(self.clauses) + 1)]) return mona.PredicateDefinition( "deadlock", self.system.state_variables, [], inner).simplify()
def initially_marked_trap_predicate(self) -> mona.Formula: inner = mona.Conjunction([ mona.PredicateCall("trap", self.system.state_variables), mona.PredicateCall("intersects_initial", self.system.state_variables)]) return mona.PredicateDefinition( "initially_marked_trap", self.system.state_variables, [], inner).simplify()
def intersection_predicate(self) -> mona.Formula: x = mona.Variable("x") one_states = [mona.Variable(f"one{s}") for s in self.system.states] two_states = [mona.Variable(f"two{s}") for s in self.system.states] in_both_states = cast(List[mona.Formula], [mona.Conjunction([mona.ElementIn(x, o), mona.ElementIn(x, t)]) for o, t in zip(one_states, two_states)]) quantified_formula = mona.ExistentialFirstOrder( [x], mona.Disjunction(in_both_states)) return mona.PredicateDefinition("intersection", one_states + two_states, [], quantified_formula ).simplify()
def trap_invariant_predicate(self) -> mona.Formula: trap_states = [mona.Variable(f"T{s}") for s in self.system.states] precondition = mona.PredicateCall("initially_marked_trap", trap_states) postcondition = mona.PredicateCall( "intersection", trap_states + self.system.state_variables) return mona.PredicateDefinition( "trap_invariant", self.system.state_variables, [], mona.UniversalSecondOrder(trap_states, mona.Implication(precondition, postcondition)) ).simplify()
def flow_invariant_predicate(self) -> mona.Formula: flow_states = [mona.Variable(f"F{s}") for s in self.system.states] precondition = mona.PredicateCall( "initially_uniquely_marked_flow", flow_states) postcondition = mona.PredicateCall( "unique_intersection", flow_states + self.system.state_variables) return mona.PredicateDefinition( "flow_invariant", self.system.state_variables, [], mona.UniversalSecondOrder( flow_states, mona.Implication(precondition, postcondition)) ).simplify()
def is_dead_predicate(self, number: int) -> mona.Formula: dead_free = mona.Disjunction( [p.miss_pre() for p in self.ports.predicates]) dead_broadcasts = mona.Disjunction( [b.is_dead() for b in self.broadcasts]) guard = self.guard_as_mona() inner = mona.Implication( guard, mona.Disjunction([dead_free, dead_broadcasts])) formula = mona.UniversalFirstOrder([cast(mona.Variable, v.as_mona()) for v in self.free_variables], inner) return mona.PredicateDefinition(f"dead_transition_{number}", self.system.state_variables, [], formula).simplify()
def invariant_predicate(self, number: int) -> mona.Formula: inner = mona.Disjunction([ # disjoint pre and post mona.Conjunction([self.disjoint_all_pre(), self.disjoint_all_post()]), # unique pre and post mona.Conjunction([self.one_in_pre(), self.one_in_post()]), # more than one in pre mona.Conjunction([mona.Negation(self.disjoint_all_pre()), mona.Negation(self.one_in_pre())]), ]) variables = sorted([cast(mona.Variable, v.as_mona()) for v in self.free_variables], key=str) guard = self.guard_as_mona() quantification = mona.UniversalFirstOrder( variables, mona.Implication(guard, inner)) return mona.PredicateDefinition( f"invariant_transition_{number}", self.system.state_variables, [], quantification).simplify()
def uniquely_intersects_initial_predicate(self) -> mona.Formula: x = mona.Variable("x") y = mona.Variable("y") initial_states = [mona.Variable(c.initial_state) for c in self.system.components] statements: List[mona.Formula] = [] for init in initial_states: other_initial_states = [i for i in initial_states if i != init] x_only_in_init = mona.Conjunction( [cast(mona.Formula, mona.ElementIn(x, init))] + [cast(mona.Formula, mona.ElementNotIn(x, i)) for i in other_initial_states]) statements.append(x_only_in_init) x_in_only_one_initial = mona.Disjunction(statements) y_in_initial = mona.Disjunction( [mona.ElementIn(y, i) for i in initial_states]) x_unique = mona.UniversalFirstOrder([y], mona.Implication( y_in_initial, mona.Equal(x, y))) formula = mona.ExistentialFirstOrder( [x], mona.Conjunction([x_in_only_one_initial, x_unique])) return mona.PredicateDefinition( "uniquely_intersects_initial", self.system.state_variables, [], formula).simplify()
def custom_property(self, name: str, formula: str) -> mona.Formula: return mona.PredicateDefinition( name, self.system.state_variables, [], mona.RawFormula(formula)).simplify()