def get_equivalent_restricted_formula(self): ''' Return a equivalent formula in the restricted syntax. This method returns a formula that avoids "and", "implies", "A", "F", and "R" and that is equivalent to this formula. :param self: this formula :type self: E :returns: a formula that avoids "and", "implies", "A", "F", and "R" and that is equivalent to this formula :rtype: StateFormula ''' p_formula = self.subformula(0) sf0 = p_formula.subformula(0).get_equivalent_restricted_formula() if (isinstance(p_formula, CTLS.X)): return EX(sf0) if (isinstance(p_formula, CTLS.F)): return EU(True, sf0) if (isinstance(p_formula, CTLS.G)): return EG(sf0) sf1 = p_formula.subformula(1).get_equivalent_restricted_formula() if (isinstance(p_formula, CTLS.U)): return EU(sf0, sf1) if (isinstance(p_formula, CTLS.R)): neg_sf1 = LNot(sf1) neg_sf0 = LNot(sf0) return Or(EU(sf1, Not(Or(neg_sf0, neg_sf1))), EG(sf1)) raise TypeError('%s is not a CTL formula' % (self))
def get_closure(formula): closure=set() T=[formula] Lang=sys.modules[formula.__module__] while len(T)>0: phi=T.pop() if hash(phi) not in [hash(o) for o in closure]: closure.add(phi) T.append(LNot(phi)) if isinstance(phi,CTLS.X): T.append(phi.subformula(0)) else: if (isinstance(phi,CTLS.Not) and isinstance(phi.subformula(0),CTLS.X)): sf=phi.subformula(0).subformula(0) T.append(Lang.X(LNot(sf))) else: if isinstance(phi,CTLS.Or): T.append(phi.subformula(0)) T.append(phi.subformula(1)) else: if isinstance(phi,CTLS.U): T.append(phi.subformula(0)) T.append(phi.subformula(1)) T.append(Lang.X(phi)) else: if not (isinstance(phi,CTLS.Not) or isinstance(phi,CTLS.AtomicProposition) or isinstance(phi,CTLS.Bool)): raise TypeError('expected a LTL path formula ' + 'restricted to "or", "not", '+ '"U" and "X", got %s' % (phi)) return closure
def modelcheck(kripke, formula, parser=None, F=None): ''' Model checks any LTL formula on a Kripke structure. This method performs LTL model checking of a formula on a given Kripke structure. :param kripke: a Kripke structure. :type kripke: Kripke :param formula: the formula to model check. :type formula: a type castable in a LTL.Formula or a string representing a LTL formula :param parser: a parser to parse a string into a LTL.Formula. :type parser: LTL.Parser :param F: a list of fair states :type F: Container :returns: a list of the Kripke structure states that satisfy the formula. ''' if isinstance(formula, str): if parser is None: parser = Parser() formula = parser(formula) if not (isinstance(formula, CTLS.A)): raise TypeError('expected a LTL state formula, got {}'.format(formula)) if not isinstance(kripke, Kripke): raise TypeError('expected a Kripke structure, got {}'.format(kripke)) try: p_formula = LNot(formula.subformula(0)) p_formula = p_formula.get_equivalent_restricted_formula() if F is not None: kripke = kripke.clone() fair_label = kripke.label_fair_states(F) p_formula = p_formula.get_equivalent_non_fair_formula(fair_label) p_formula = And(fair_label, p_formula) return set(kripke.states()) - _checkE_path_formula(kripke, p_formula) except TypeError: raise TypeError('expected a LTL formula, got {}'.format(formula))
def modelcheck(kripke,formula,F=None): if not (isinstance(formula,CTLS.A)): raise TypeError('expected a LTL state formula, got %s' % (formula)) if not isinstance(kripke,Kripke): raise TypeError('expected a Kripke structure, got %s' % (kripke)) try: p_formula=LNot(formula.subformula(0)).get_equivalent_restricted_formula() if F!=None: kripke=kripke.copy() fair_label=kripke.label_fair_states(F) p_formula=p_formula.get_equivalent_non_fair_formula(fair_label) p_formula=And(fair_label,p_formula) return set(kripke.states())-checkE_path_formula(kripke,p_formula) except TypeError: raise TypeError('expected a LTL formula, got %s' % (formula))
def _get_closure(formula): closure = set() T = [formula] Lang = sys.modules[formula.__module__] while len(T) > 0: phi = T.pop() if phi not in closure: closure.add(phi) T.append(LNot(phi)) if isinstance(phi, CTLS.X): T.append(phi.subformula(0)) else: if (isinstance(phi, CTLS.Not) and isinstance(phi.subformula(0), CTLS.X)): sf = phi.subformula(0).subformula(0) T.append(Lang.X(LNot(sf))) else: if isinstance(phi, CTLS.Or): for sf in phi.subformulas(): T.append(sf) else: if isinstance(phi, CTLS.U): T.append(phi.subformula(0)) T.append(phi.subformula(1)) T.append(Lang.X(phi)) else: if not (isinstance(phi, CTLS.Not) or isinstance(phi, CTLS.AtomicProposition) or isinstance(phi, CTLS.Bool)): raise TypeError('expected a LTL path ' + 'formula restricted to ' + '"or", "not", ' + '"U" and "X", got ' + '{}'.format(phi)) return closure
def get_equivalent_non_fair_formula(self, fairAP): p_formula = self.subformula(0) sf0 = p_formula.subformula(0).get_equivalent_non_fair_formula(fairAP) if (isinstance(p_formula, CTLS.X)): return EX(And(sf0, fairAP)) if (isinstance(p_formula, CTLS.F)): return EU(True, And(sf0, fairAP)) if (isinstance(p_formula, CTLS.G)): return EG(And(sf0, fairAP)) sf1 = p_formula.subformula(1).get_equivalent_non_fair_formula(fairAP) if (isinstance(p_formula, CTLS.U)): return EU(sf0, And(sf1, fairAP)) if (isinstance(p_formula, CTLS.R)): neg_sf1 = LNot(sf1) neg_sf0 = LNot(sf0) return Or(EU(sf1, And(Not(Or(neg_sf0, neg_sf1))), fairAP), EG(And(sf1, fairAP))) raise TypeError('%s is not a CTL formula' % (self))
def _build_atoms(K, closure): A = [] for state in K.states(): A.append(_TableuAtom(state)) # this is to avoid issues with the "not X" case cl_list = sorted(list(closure), key=(lambda a: a.height if not (isinstance(a, CTLS.Not) and isinstance( a.subformula(0), CTLS.X)) else a.height - 1)) for phi in cl_list: Lang = sys.modules[phi.__module__] if phi != Lang.Not(True) and phi != Lang.Bool(False): neg_phi = LNot(phi) A_tail = [] if isinstance(phi, CTLS.Bool): for atom in A: atom.add(phi) else: if isinstance(phi, CTLS.AtomicProposition): for atom in A: if phi in K.labels(atom.state): atom.add(phi) else: atom.add(neg_phi) if (isinstance(phi, CTLS.Or)): sf = phi.subformulas() for atom in A: if sum([f in atom for f in sf]): atom.add(phi) else: atom.add(neg_phi) if (isinstance(phi, CTLS.Not) and isinstance(phi.subformula(0), CTLS.X)): sf = phi.subformula(0).subformula(0) for atom in A: if phi.subformula(0) not in atom: if phi not in atom: new_atom = atom | set([phi, Lang.X(LNot(sf))]) A_tail.append(new_atom) atom.add(phi.subformula(0)) else: atom.add(Lang.X(LNot(sf))) if isinstance(phi, CTLS.U): sf = phi.subformulas() for atom in A: if (sf[1] in atom): atom.add(phi) A_tail.append(atom | set([Lang.X(phi)])) else: if (sf[0] in atom): A_tail.append(atom | set([phi, Lang.X(phi)])) atom.add(neg_phi) atom.add(Lang.Not(Lang.X(phi))) A.extend(A_tail) for atom in A: if phi not in atom and neg_phi not in atom: A.append(atom | set([phi])) atom.add(neg_phi) return A
def build_atoms(K, closure): A = [] for state in K.states(): A.append(TableuAtom(state)) for phi in sorted(list(closure), key=lambda a: a.height): Lang = sys.modules[phi.__module__] if phi != Lang.Not(True) and phi != Lang.Bool(False): neg_phi = LNot(phi) A_tail = [] if isinstance(phi, CTLS.Bool): for atom in A: atom.add(phi) else: if isinstance(phi, CTLS.AtomicProposition): for atom in A: if phi in K.labels(atom.state): atom.add(phi) else: atom.add(neg_phi) if (isinstance(phi, CTLS.Or)): sf = phi.subformulas() neg_sf = [LNot(p) for p in sf] for atom in A: if (sf[0] in atom or sf[1] in atom): atom.add(phi) else: atom.add(neg_phi) if (isinstance(phi, CTLS.Not) and isinstance(phi.subformula(0), CTLS.X)): sf = phi.subformula(0).subformula(0) for atom in A: if phi.subformula(0) not in atom: if phi not in atom: new_atom = atom | set([phi, Lang.X(LNot(sf))]) A_tail.append(new_atom) atom.add(phi.subformula(0)) else: atom.add(Lang.X(LNot(sf))) if isinstance(phi, CTLS.U): sf = phi.subformulas() neg_sf = [LNot(p) for p in sf] for atom in A: if (sf[1] in atom): atom.add(phi) A_tail.append(atom | set([Lang.X(phi)])) else: if (sf[0] in atom): A_tail.append(atom | set([phi, Lang.X(phi)])) atom.add(neg_phi) atom.add(Lang.Not(Lang.X(phi))) A.extend(A_tail) for atom in A: if phi not in atom and neg_phi not in atom: A.append(atom | set([phi])) atom.add(neg_phi) return A