예제 #1
0
    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))
예제 #2
0
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
예제 #3
0
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))
예제 #4
0
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))
예제 #5
0
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
예제 #6
0
    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))
예제 #7
0
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
예제 #8
0
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