Пример #1
0
 def test_explain(self):
     fsm = self.init_model()
     
     initState = fsm.pick_one_state(fsm.init)
     adminNone = eval_ctl_spec(fsm, atom("admin = none"))
     adminAlice = eval_ctl_spec(fsm, atom("admin = alice"))
     egAlice = eval_ctl_spec(fsm, eg(atom("admin = alice")))
     euNoneUAlice = eval_ctl_spec(fsm, eu(atom("admin = none"),
                                          atom("admin = alice")))
     
     spec = Spec(parse_ctl_spec("EX admin = none"))
     path = explain(fsm, initState, spec)
     self.assertEqual(initState, path[0])
     self.assertTrue(path[2] <= adminNone)
     
     state = fsm.pick_one_state(egAlice)
     spec = Spec(parse_ctl_spec("EG admin = alice"))
     path = explain(fsm, state, spec)
     self.assertEqual(state, path[0])
     self.assertIn(path[-1], path[:-1])
     for i in range(0,len(path), 2):
         self.assertTrue(path[i] <= adminAlice)
     self.assertTrue(path[-1] <= adminAlice)
     self.assertTrue(initState <= euNoneUAlice)
     
     spec = Spec(parse_ctl_spec("E[admin = none U admin = alice]"))
     path = explain(fsm, initState, spec)
     self.assertEqual(initState, path[0])
     for i in range(2,len(path)-2,2):
         self.assertTrue(path[i] <= adminNone)
     self.assertTrue(path[-1] <= adminAlice)
Пример #2
0
 def test_explain_ex(self):
     fsm = self.init_model()
     manager = fsm.bddEnc.DDmanager
     init = fsm.init
     
     initState = fsm.pick_one_state(init)
     
     adminNone = eval_ctl_spec(fsm, atom("admin = none"))
     exAdminNone = eval_ctl_spec(fsm, ex(atom("admin = none")))
     self.assertTrue(initState <= exAdminNone)
     
     path = explainEX(fsm, initState, adminNone)
     self.assertEqual(initState, path[0])
     self.assertTrue(path[2] <= adminNone)
Пример #3
0
def witness(fsm, state, spec, context):
    """
    Return a TLACE node explaining why state of fsm satisfies spec.
    
    fsm -- a pynusmv.fsm.BddFsm representing the system.
    state -- a pynusmv.dd.BDD representing a state of fsm.
    spec -- a pynusmv.spec.spec.Spec node representing the specification.
    context -- a pynusmv.spec.spec.Spec representing the context of spec in fsm.
    
    Return a tlacenode.Tlacenode explaining why state of fsm satisfies spec.
    """

    if spec.type == parser.CONTEXT:
        return witness(fsm, state, spec.cdr, spec.car)

    elif spec.type == parser.TRUEEXP:
        return Tlacenode(state, None, None, None)

    elif spec.type == parser.NOT:
        return countex(fsm, state, spec.car, context)

    elif spec.type == parser.OR:
        if state.entailed(eval_ctl_spec(fsm, spec.car, context)):
            return witness(fsm, state, spec.car, context)
        else:
            return witness(fsm, state, spec.cdr, context)

    elif spec.type == parser.AND:
        n1 = witness(fsm, state, spec.car, context)
        n2 = witness(fsm, state, spec.cdr, context)
        return Tlacenode(state, n1.atomics + n2.atomics,
                         n1.branches + n2.branches,
                         n1.universals + n2.universals)

    elif spec.type == parser.IMPLIES:
        newspec = (~spec.car) | spec.cdr
        return witness(fsm, state, newspec, context)

    elif spec.type == parser.IFF:
        newspec = (spec.car & spec.cdr) | ((~spec.car) & (~spec.cdr))
        return witness(fsm, state, newspec, context)

    elif (spec.type == parser.EX or spec.type == parser.EF
          or spec.type == parser.EG or spec.type == parser.EU
          or spec.type == parser.EW):
        return Tlacenode(state, None,
                         (witness_branch(fsm, state, spec, context, spec), ),
                         None)

    elif (spec.type == parser.AX or spec.type == parser.AF
          or spec.type == parser.AG or spec.type == parser.AU
          or spec.type == parser.AW):
        return Tlacenode(state, None, None, (spec, ))

    else:
        # deal with unmanaged formulas by returning a single
        # TLACE node. This includes the case of atomic propositions.
        # All unrecognized operators are considered as atomics
        return Tlacenode(state, (spec, ), None, None)
Пример #4
0
    def test_explain_eg_first_state(self):
        fsm = self.inputs_model()
        manager = fsm.bddEnc.DDmanager
        init = fsm.init

        p = eval_ctl_spec(fsm, atom("p"))
        egp = eval_ctl_spec(fsm, eg(atom("p")))
        self.assertTrue(egp <= p)

        state = fsm.pick_one_state(egp)
        path, (inloop, loop) = explainEG(fsm, state, p)
        self.assertEqual(state, path[0])
        self.assertIn(loop, path)
        self.assertEqual(len(path), 1)
        for i in range(0, len(path), 2):
            self.assertTrue(path[i] <= p)
        self.assertTrue(path[-1] <= p)
Пример #5
0
    def test_ex(self):
        glob.load("tests/pynusmv/models/admin.smv")
        glob.compute_model()
        fsm = glob.prop_database().master.bddFsm

        alice = mc.eval_simple_expression(fsm, "admin = alice")
        spec = prop.Spec(parser.parse_ctl_spec("EX admin = alice"))
        exalice = mc.eval_ctl_spec(fsm, spec)
        self.assertEqual(mc.ex(fsm, alice), exalice)
Пример #6
0
 def test_explain_eu(self):
     fsm = self.init_model()
     manager = fsm.bddEnc.DDmanager
     init = fsm.init
     
     initState = fsm.pick_one_state(init)
     
     adminNone = eval_ctl_spec(fsm, atom("admin = none"))
     adminAlice = eval_ctl_spec(fsm, atom("admin = alice"))
     euNoneUAlice = eval_ctl_spec(fsm, eu(atom("admin = none"),
                                          atom("admin = alice")))
     self.assertTrue(initState <= euNoneUAlice)
     
     path = explainEU(fsm, initState, adminNone, adminAlice)
     self.assertEqual(initState, path[0])
     for i in range(2,len(path)-2,2):
         self.assertTrue(path[i] <= adminNone)
     self.assertTrue(path[-1] <= adminAlice)
Пример #7
0
def _boundary(fsm, gamma, phi, states):
    """
    Third auxiliary set, as defined by Chan at CAV 2000.

    :param fsm: the concerned FSM
    :param gamma: an AST-based CTL query
    :param phi: an AST-based CTL formula
    :param states: a set of states
    :return: the boundary of the first auxiliary set (that is, the first states
        on each path starting from `states` that are not in the first auxiliary
        set and at which `gamma[False]` does not hold)
    :rtype: :class:`pynusmv.dd.BDD`
    """
    psi = replace_placeholder(gamma, FalseExp())
    new_phi = And(phi, Not(psi))
    return ((states | fsm.post(_reachable(fsm, new_phi, states)))
            - (eval_ctl_spec(fsm, ast_to_spec(phi))
               | eval_ctl_spec(fsm, ast_to_spec(psi))))
Пример #8
0
 def test_explain_eg(self):
     fsm = self.init_model()
     manager = fsm.bddEnc.DDmanager
     init = fsm.init
     
     adminAlice = eval_ctl_spec(fsm, atom("admin = alice"))
     egAlice = eval_ctl_spec(fsm, eg(atom("admin = alice")))
     self.assertTrue(egAlice <= adminAlice)
     
     state = fsm.pick_one_state(egAlice)
     self.assertTrue(BDD.false(manager) < state <= adminAlice)
     self.assertTrue(state <= egAlice)
     
     path, (inloop, loop) = explainEG(fsm, state, adminAlice)
     self.assertEqual(state, path[0])
     self.assertIn(loop, path)
     for i in range(0,len(path), 2):
         self.assertTrue(path[i] <= adminAlice)
     self.assertTrue(path[-1] <= adminAlice)
Пример #9
0
 def test_eval_atom(self):
     fsm = self.init_model()
     manager = fsm.bddEnc.DDmanager
     init = fsm.init
     
     initState = fsm.pick_one_state(init)
     
     adminNone = eval_ctl_spec(fsm, atom("admin = none"))
     self.assertTrue((initState & adminNone).isnot_false())
     self.assertTrue(init <= adminNone)
Пример #10
0
    def test_au(self):
        glob.load("tests/pynusmv/models/admin.smv")
        glob.compute_model()
        fsm = glob.prop_database().master.bddFsm

        none = mc.eval_simple_expression(fsm, "admin = none")
        alice = mc.eval_simple_expression(fsm, "admin = alice")
        spec = prop.Spec(
            parser.parse_ctl_spec("A[admin = none U admin = alice]"))
        aunonealice = mc.eval_ctl_spec(fsm, spec)
        self.assertEqual(mc.au(fsm, none, alice), aunonealice)
Пример #11
0
def _f_sol(fsm, gamma, phi, states, cycle):
    """
    Find the states of `fsm` with highest indices among the states at which
    `gamma` has a solution, as defined by Samer and Veith at TIME'05.

    :param fsm: the concerned FSM
    :param gamma: an AST-based CTL query
    :param phi: an AST-based CTL formula
    :param states: a set of states
    :param cycle: True if there is a cycle, False otherwise
    :return: the states of `fsm` with highest indices among the states at which
        `gamma` has a solution
    :rtype: :class:`pynusmv.dd.BDD`
    """
    if cycle:
        c = _cycle(fsm, gamma, phi, states)
    else:
        c = BDD.false(fsm.bddEnc.DDmanager)

    chi = replace_placeholder(gamma, TrueExp())
    psi = replace_placeholder(gamma, FalseExp())
    new_phi = And(phi, Not(psi))

    u_1 = fixpoint(lambda z: ((c - eval_ctl_spec(fsm, ast_to_spec(chi)))
                              & fsm.post(z)),
                   BDD.true(fsm.bddEnc.DDmanager))  # Greatest fixed point.

    u_2 = u_1 | (_boundary(fsm, gamma, phi, states)
                 - eval_ctl_spec(fsm, ast_to_spec(chi)))

    u_3 = fixpoint(lambda z: (((u_2 | fsm.pre(z))
                               & _reachable(fsm, new_phi, states))
                              - eval_ctl_spec(fsm, ast_to_spec(chi))),
                   BDD.false(fsm.bddEnc.DDmanager))  # Least fixed point.

    return (((fsm.pre(u_3) & _reachable(fsm, new_phi, states))
             | _boundary(fsm, gamma, phi, states) | c)
            & eval_ctl_spec(fsm, ast_to_spec(chi)))
Пример #12
0
def _reachable(fsm, phi, states):
    """
    First auxiliary set, as defined by Chan at CAV 2000.

    :param fsm: the concerned FSM
    :param phi: an AST-based CTL formula
    :param states: a set of states
    :return: the states of `fsm` that are reachable from states in `states` by
        going only through states at which `phi` holds
    :rtype: :class:`pynusmv.dd.BDD`
    """
    return fixpoint(lambda z: ((states | fsm.post(z))
                               & eval_ctl_spec(fsm, ast_to_spec(phi))),
                    BDD.false(fsm.bddEnc.DDmanager))  # Least fixed point.
Пример #13
0
    def test_eg(self):
        glob.load("tests/pynusmv/models/admin.smv")
        glob.compute_model()
        fsm = glob.prop_database().master.bddFsm

        alice = mc.eval_simple_expression(fsm, "admin = alice")
        spec = prop.Spec(parser.parse_ctl_spec("EG admin = alice"))
        egalice = mc.eval_ctl_spec(fsm, spec)
        self.assertEqual(mc.eg(fsm, alice), egalice)

        self.assertEqual(
            egalice,
            fixpoint(lambda Z: alice & fsm.pre(Z), BDD.true())
            & fsm.reachable_states)
Пример #14
0
def solve_ctlqx(fsm, query):
    """
    Compute the unique set of solution states of `fsm` to `query` at the
    initial states of `fsm`, as defined by Samer and Veith at TIME'05.

    :param fsm: the concerned FSM
    :param query: an AST-based CTL query **that belongs to fragment CTLQx**
    :return: the unique set of solution states of `fsm` to `query` at the
        initial states of `fsm` if there is a solution, None otherwise
    :rtype: :class:`pynusmv.dd.BDD`

    .. note:: The characteristic function of the output is an exact solution to
        `query` in `fsm`.
    .. note:: See :func:`pytlq.checker.check_ctlqx` for the verification that
        `query` belongs to fragment CTLQx.
    """
    if (eval_ctl_spec(fsm, ast_to_spec(replace_placeholder(query, TrueExp())))
            .is_true()):
        return _e_sol(fsm, query, fsm.init)

    else:
        return None
Пример #15
0
def check(fsm, spec):
    """
    Check whether fsm satisfies spec or not.
    
    Return (True, None) if spec is satisfied,
    and (False, cntex) otherwise,
    where cntex is TLACE node explaining the violation.
    """
    
    initbdd = fsm.init
    specbdd = eval_ctl_spec(fsm, spec)
    
    # Get violating states
    violating = initbdd & ~specbdd
    
    # If some initial states are not in specbdd, the spec if violated
    if violating.isnot_false():
        # Compute a counter-example
        state = fsm.pick_one_state(violating)
        return (False, explain(fsm, state, spec))
        
    # Otherwise, it is satisfied
    else:
        return (True, None)
Пример #16
0
def check(fsm, spec):
    """
    Check whether fsm satisfies spec or not.
    
    Return (True, None) if spec is satisfied,
    and (False, cntex) otherwise,
    where cntex is TLACE node explaining the violation.
    """

    initbdd = fsm.init
    specbdd = eval_ctl_spec(fsm, spec)

    # Get violating states
    violating = initbdd & ~specbdd

    # If some initial states are not in specbdd, the spec if violated
    if violating.isnot_false():
        # Compute a counter-example
        state = fsm.pick_one_state(violating)
        return (False, explain(fsm, state, spec))

    # Otherwise, it is satisfied
    else:
        return (True, None)
Пример #17
0
def _e_sol(fsm, gamma, states):
    """
    Compute the unique set of solution states of `fsm` to `gamma` at `states`,
    as defined by Samer and Veith at TIME'05.

    :param fsm: the concerned FSM
    :param gamma: an AST-based CTL query that belongs to fragment CTLQx
    :param states: a set of states
    :return: the unique set of solution states of `fsm` to `gamma` at `states`
    :rtype: :class:`pynusmv.dd.BDD`

    .. note:: Samer and Veith's algorithm has been extended to support the
        negation in front of the placeholder.
    """
    if isinstance(gamma, Placeholder):
        return states

    # Extension to support the negation in front of the placeholder.
    elif isinstance(gamma, Not) and isinstance(gamma.child, Placeholder):
        return fsm.reachable_states - states

    elif isinstance(gamma, And):
        if count_placeholders(gamma.left):
            return _e_sol(fsm, gamma.left, states)
        elif count_placeholders(gamma.right):
            return _e_sol(fsm, gamma.right, states)

    elif isinstance(gamma, Or):
        if count_placeholders(gamma.left):
            return _e_sol(fsm, gamma.left, states
                          - eval_ctl_spec(fsm, ast_to_spec(gamma.right)))
        elif count_placeholders(gamma.right):
            return _e_sol(fsm, gamma.right, states
                          - eval_ctl_spec(fsm, ast_to_spec(gamma.left)))

    elif isinstance(gamma, AX):
        return _e_sol(fsm, gamma.child, fsm.post(states))

    elif isinstance(gamma, AF):
        return _e_sol(fsm, AU(TrueExp(), gamma.child), states)

    elif isinstance(gamma, AG):
        return _e_sol(fsm, AoW(gamma.child, FalseExp()), states)

    elif isinstance(gamma, AU):
        if count_placeholders(gamma.left):
            return _e_sol(fsm, AoW(Or(gamma.right, gamma.left), gamma.right),
                          states)
        elif count_placeholders(gamma.right):
            return _e_sol(fsm, gamma.right,
                          _f_sol(fsm, gamma.right, gamma.left, states, True))

    elif isinstance(gamma, AoU):
        if count_placeholders(gamma.left):
            return _e_sol(fsm, AoW(gamma.left, gamma.right), states)
        elif count_placeholders(gamma.right):
            return _e_sol(fsm, AU(gamma.left, And(gamma.left, gamma.right)),
                          states)

    elif isinstance(gamma, AdU):
        return _e_sol(fsm, AdW(gamma.left, gamma.right), states)

    elif isinstance(gamma, AW):
        if count_placeholders(gamma.left):
            return _e_sol(fsm, AoW(Or(gamma.right, gamma.left), gamma.right),
                          states)
        elif count_placeholders(gamma.right):
            return _e_sol(fsm, gamma.right,
                          _f_sol(fsm, gamma.right, gamma.left, states, False))

    elif isinstance(gamma, AoW):
        if count_placeholders(gamma.left):
            return _e_sol(fsm, gamma.left, states
                          | fsm.post(_reachable(fsm, Not(gamma.right),
                                                states)))
        elif count_placeholders(gamma.right):
            return _e_sol(fsm, AW(gamma.left, And(gamma.left, gamma.right)),
                          states)

    elif isinstance(gamma, AdW):
        return _e_sol(fsm, gamma.right,
                      ((states | fsm.post(_reachable(fsm, gamma.left, states)))
                       - eval_ctl_spec(fsm, ast_to_spec(gamma.left))))
Пример #18
0
def witness(fsm, state, spec, context):
    """
    Return a TLACE node explaining why state of fsm satisfies spec.
    
    fsm -- a pynusmv.fsm.BddFsm representing the system.
    state -- a pynusmv.dd.BDD representing a state of fsm.
    spec -- a pynusmv.spec.spec.Spec node representing the specification.
    context -- a pynusmv.spec.spec.Spec representing the context of spec in fsm.
    
    Return a tlacenode.Tlacenode explaining why state of fsm satisfies spec.
    """

    if spec.type == parser.CONTEXT:
        return witness(fsm, state, spec.cdr, spec.car)
        
    elif spec.type == parser.TRUEEXP:
        return Tlacenode(state, None, None, None)
        
    elif spec.type == parser.NOT:
        return countex(fsm, state, spec.car, context)
        
    elif spec.type == parser.OR:
        if state.entailed(eval_ctl_spec(fsm, spec.car, context)):
            return witness(fsm, state, spec.car, context)
        else:
            return witness(fsm, state, spec.cdr, context)
    
    elif spec.type == parser.AND:
        n1 = witness(fsm, state, spec.car, context)
        n2 = witness(fsm, state, spec.cdr, context)
        return Tlacenode(state,
                         n1.atomics + n2.atomics,
                         n1.branches + n2.branches,
                         n1.universals + n2.universals)
    
    elif spec.type == parser.IMPLIES:
        newspec = (~spec.car) | spec.cdr
        return witness(fsm, state, newspec, context)
                            
    elif spec.type == parser.IFF:
        newspec = (spec.car & spec.cdr) | ((~spec.car) & (~spec.cdr))
        return witness(fsm, state, newspec, context)
                    
    elif (spec.type == parser.EX or
          spec.type == parser.EF or
          spec.type == parser.EG or
          spec.type == parser.EU or
          spec.type == parser.EW):
        return Tlacenode(state, None,
                         (witness_branch(fsm, state, spec, context, spec),),
                         None)
                    
    elif (spec.type == parser.AX or
          spec.type == parser.AF or
          spec.type == parser.AG or
          spec.type == parser.AU or
          spec.type == parser.AW):
        return Tlacenode(state, None, None, (spec,))
                        
    else:
        # deal with unmanaged formulas by returning a single
        # TLACE node. This includes the case of atomic propositions.
        # All unrecognized operators are considered as atomics
        return Tlacenode(state, (spec,), None, None)
Пример #19
0
def witness_branch(fsm, state, spec, context, originalspec):
    """
    Return a TLACE branch explaining why state of fsm satisfies spec.

    fsm -- a pynusmv.fsm.BddFsm representing the system.
    state -- a pynusmv.dd.BDD representing a state of fsm.
    spec -- a pynusmv.spec.spec.Spec node representing the specification.
    context -- a pynusmv.spec.spec.Spec representing the context of spec in fsm.
    originalspec -- a pynusmv.spec.spec.Spec representing the original spec;
                    used to annotate the produced branch, despite updated
                    specs.

    Return a tlacebranch.Tlacebranch explaining why state of fsm satisfies spec.
    
    Throw a NonExistentialSpecError if spec is not existential.
    """
    
    if spec.type == parser.EX:
        f = eval_ctl_spec(fsm, spec.car, context)
        path = explainEX(fsm, state, f)
        branch = (Tlacenode(path[0]),
                  path[1],
                  witness(fsm, path[2], spec.car, context))
        return Tlacebranch(originalspec, branch)
        
    elif spec.type == parser.EF:
        newspec = eu(sptrue(), spec.car)
        return witness_branch(fsm, state, newspec, context, originalspec)
        
    elif spec.type == parser.EG:
        f = eval_ctl_spec(fsm, spec.car, context)
        (path, (inloop, loopstate)) = explainEG(fsm, state, f)
        
        branch = []
        # intermediate states
        for s, i in zip(path[::2], path[1::2]):
            wit = witness(fsm, s, spec.car, context)
            branch.append(wit)
            branch.append(i)
            # manage the loop
            if s == loopstate:
                loop = wit
        # last state
        branch.append(witness(fsm, path[-1], spec.car, context))
        
        return Tlacebranch(originalspec, tuple(branch), (inloop, loop))
        
    elif spec.type == parser.EU:
        f = eval_ctl_spec(fsm, spec.car, context)
        g = eval_ctl_spec(fsm, spec.cdr, context)
        path = explainEU(fsm, state, f, g)
        
        branch = []
        # intermediate states
        for s, i in zip(path[::2], path[1::2]):
            branch.append(witness(fsm, s, spec.car, context))
            branch.append(i)
        # last state
        branch.append(witness(fsm, path[-1], spec.cdr, context))
        
        return Tlacebranch(originalspec, tuple(branch))
        
    elif spec.type == parser.EW:
        euspec = eu(spec.car, spec.cdr)
        egspec = eg(spec.car)
        if state.entailed(eval_ctl_spec(fsm, euspec, context)):
            return witness_branch(fsm, state, euspec, context, originalspec)
        else:
            return witness_branch(fsm, state, egspec, context, originalspec)
        
    else:
        # Default case, throw an exception because spec is not existential
        raise NonExistentialSpecError()
Пример #20
0
 def test_wrong_type(self):
     fsm, _, _ = self.init_model()
     spec = atom("admin = starting")
     specbdd = eval_ctl_spec(fsm, spec)
     self.assertTrue(specbdd.is_false())
Пример #21
0
def witness_branch(fsm, state, spec, context, originalspec):
    """
    Return a TLACE branch explaining why state of fsm satisfies spec.

    fsm -- a pynusmv.fsm.BddFsm representing the system.
    state -- a pynusmv.dd.BDD representing a state of fsm.
    spec -- a pynusmv.spec.spec.Spec node representing the specification.
    context -- a pynusmv.spec.spec.Spec representing the context of spec in fsm.
    originalspec -- a pynusmv.spec.spec.Spec representing the original spec;
                    used to annotate the produced branch, despite updated
                    specs.

    Return a tlacebranch.Tlacebranch explaining why state of fsm satisfies spec.
    
    Throw a NonExistentialSpecError if spec is not existential.
    """

    if spec.type == parser.EX:
        f = eval_ctl_spec(fsm, spec.car, context)
        path = explainEX(fsm, state, f)
        branch = (Tlacenode(path[0]), path[1],
                  witness(fsm, path[2], spec.car, context))
        return Tlacebranch(originalspec, branch)

    elif spec.type == parser.EF:
        newspec = eu(sptrue(), spec.car)
        return witness_branch(fsm, state, newspec, context, originalspec)

    elif spec.type == parser.EG:
        f = eval_ctl_spec(fsm, spec.car, context)
        (path, (inloop, loopstate)) = explainEG(fsm, state, f)

        branch = []
        # intermediate states
        for s, i in zip(path[::2], path[1::2]):
            wit = witness(fsm, s, spec.car, context)
            branch.append(wit)
            branch.append(i)
            # manage the loop
            if s == loopstate:
                loop = wit
        # last state
        branch.append(witness(fsm, path[-1], spec.car, context))

        return Tlacebranch(originalspec, tuple(branch), (inloop, loop))

    elif spec.type == parser.EU:
        f = eval_ctl_spec(fsm, spec.car, context)
        g = eval_ctl_spec(fsm, spec.cdr, context)
        path = explainEU(fsm, state, f, g)

        branch = []
        # intermediate states
        for s, i in zip(path[::2], path[1::2]):
            branch.append(witness(fsm, s, spec.car, context))
            branch.append(i)
        # last state
        branch.append(witness(fsm, path[-1], spec.cdr, context))

        return Tlacebranch(originalspec, tuple(branch))

    elif spec.type == parser.EW:
        euspec = eu(spec.car, spec.cdr)
        egspec = eg(spec.car)
        if state.entailed(eval_ctl_spec(fsm, euspec, context)):
            return witness_branch(fsm, state, euspec, context, originalspec)
        else:
            return witness_branch(fsm, state, egspec, context, originalspec)

    else:
        # Default case, throw an exception because spec is not existential
        raise NonExistentialSpecError()
Пример #22
0
def eval_ctl(fsm, spec, context = None):
    """
    Evaluate spec in fsm.
    
    Return the BDD representing all states of fsm satisfying spec.
    """
    
    if spec.type == parser.CONTEXT:
        return eval_ctl(fsm, spec.cdr, spec.car)
        
    elif spec.type == parser.FALSEEXP:
        return BDD.false(fsm.bddEnc.DDmanager)
        
    elif spec.type == parser.TRUEEXP:
        return BDD.true(fsm.bddEnc.DDmanager)
        
    elif spec.type == parser.NOT:
        return ~eval_ctl(fsm, spec.car, context)
        
    elif spec.type == parser.OR:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return left | right
    
    elif spec.type == parser.AND:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return left & right
    
    elif spec.type == parser.IMPLIES:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return ~left | right
                            
    elif spec.type == parser.IFF:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return (left & right) | (~left & ~right)
                    
    elif spec.type == parser.EX:
        return ex(fsm, eval_ctl(fsm, spec.car, context))
                                 
    elif spec.type == parser.EF:
        left = BDD.true(fsm.bddEnc.DDmanager)
        right = eval_ctl(fsm, spec.car, context)
        return eu(fsm, left, right)
                                 
    elif spec.type == parser.EG:
        return eg(fsm, eval_ctl(fsm, spec.car, context))
                                 
    elif spec.type == parser.EU:
        return eu(fsm,
                  eval_ctl(fsm, spec.car, context),
                  eval_ctl(fsm, spec.cdr, context))
                    
    elif spec.type == parser.EW:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return eg(fsm, left) | eu(fsm, left, right)
                    
    elif spec.type == parser.AX:
        left = eval_ctl(fsm, spec.car, context)
        return ~ex(fsm, ~left)        
        
    elif spec.type == parser.AF:
        left = eval_ctl(fsm, spec.car, context)
        return ~eg(fsm, ~left)
                                 
    elif spec.type == parser.AG:
        left = eval_ctl(fsm, spec.car, context)
        true = BDD.true(fsm.bddEnc.DDmanager)
        return ~eu(fsm, true, ~left)
                                 
    elif spec.type == parser.AU:
        # A[p U q] = ¬E[¬q W (¬p & ¬q)] = ¬(E[¬q U (¬p & ¬q)] | EG ¬q)
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return ~(eu(fsm, ~right, ~left & ~right) | eg(fsm, ~right))
                        
    elif spec.type == parser.AW:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return ~eu(fsm, ~right, ~left & ~right)
    
    else:
        return eval_ctl_spec(fsm, spec)
Пример #23
0
 def test_success_or(self):    
     fsm, _, _ = self.init_model()
     spec = atom("admin = alice | admin = bob")
     specbdd = eval_ctl_spec(fsm, spec)
     self.assertTrue((specbdd & fsm.init).is_false())
Пример #24
0
def eval_ctl(fsm, spec, context=None):
    """
    Evaluate spec in fsm.
    
    Return the BDD representing all states of fsm satisfying spec.
    """

    if spec.type == parser.CONTEXT:
        return eval_ctl(fsm, spec.cdr, spec.car)

    elif spec.type == parser.FALSEEXP:
        return BDD.false(fsm.bddEnc.DDmanager)

    elif spec.type == parser.TRUEEXP:
        return BDD.true(fsm.bddEnc.DDmanager)

    elif spec.type == parser.NOT:
        return ~eval_ctl(fsm, spec.car, context)

    elif spec.type == parser.OR:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return left | right

    elif spec.type == parser.AND:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return left & right

    elif spec.type == parser.IMPLIES:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return ~left | right

    elif spec.type == parser.IFF:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return (left & right) | (~left & ~right)

    elif spec.type == parser.EX:
        return ex(fsm, eval_ctl(fsm, spec.car, context))

    elif spec.type == parser.EF:
        left = BDD.true(fsm.bddEnc.DDmanager)
        right = eval_ctl(fsm, spec.car, context)
        return eu(fsm, left, right)

    elif spec.type == parser.EG:
        return eg(fsm, eval_ctl(fsm, spec.car, context))

    elif spec.type == parser.EU:
        return eu(fsm, eval_ctl(fsm, spec.car, context),
                  eval_ctl(fsm, spec.cdr, context))

    elif spec.type == parser.EW:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return eg(fsm, left) | eu(fsm, left, right)

    elif spec.type == parser.AX:
        left = eval_ctl(fsm, spec.car, context)
        return ~ex(fsm, ~left)

    elif spec.type == parser.AF:
        left = eval_ctl(fsm, spec.car, context)
        return ~eg(fsm, ~left)

    elif spec.type == parser.AG:
        left = eval_ctl(fsm, spec.car, context)
        true = BDD.true(fsm.bddEnc.DDmanager)
        return ~eu(fsm, true, ~left)

    elif spec.type == parser.AU:
        # A[p U q] = ¬E[¬q W (¬p & ¬q)] = ¬(E[¬q U (¬p & ¬q)] | EG ¬q)
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return ~(eu(fsm, ~right, ~left & ~right) | eg(fsm, ~right))

    elif spec.type == parser.AW:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        return ~eu(fsm, ~right, ~left & ~right)

    else:
        return eval_ctl_spec(fsm, spec)
Пример #25
0
def eval_ctl(fsm, spec, context=None):
    """
    Evaluate spec in fsm.
    
    Return the BDD representing all reachable states of fsm satisfying spec.
    """
    
    if spec.type == parser.CONTEXT:
        sat = eval_ctl(fsm, spec.cdr, spec.car)
        
    elif spec.type == parser.FALSEEXP:
        sat = BDD.false(fsm.bddEnc.DDmanager)
        
    elif spec.type == parser.TRUEEXP:
        sat = BDD.true(fsm.bddEnc.DDmanager)
        
    elif spec.type == parser.NOT:
        sat = ~eval_ctl(fsm, spec.car, context)
        
    elif spec.type == parser.OR:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = left | right
    
    elif spec.type == parser.AND:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = left & right
    
    elif spec.type == parser.IMPLIES:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = ~left | right
        
    elif spec.type == parser.IFF:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = (left & right) | (~left & ~right)
        
    elif spec.type == parser.EX:
        sat = ex(fsm, eval_ctl(fsm, spec.car, context))
        
    elif spec.type == parser.EF:
        left = BDD.true(fsm.bddEnc.DDmanager)
        right = eval_ctl(fsm, spec.car, context)
        sat = eu(fsm, left, right)
        
    elif spec.type == parser.EG:
        sat = eg(fsm, eval_ctl(fsm, spec.car, context))
        
    elif spec.type == parser.EU:
        sat = eu(fsm,
                 eval_ctl(fsm, spec.car, context),
                 eval_ctl(fsm, spec.cdr, context))
        
    elif spec.type == parser.EW:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = eg(fsm, left) | eu(fsm, left, right)
        
    elif spec.type == parser.AX:
        left = eval_ctl(fsm, spec.car, context)
        sat = ~ex(fsm, ~left)
        
    elif spec.type == parser.AF:
        left = eval_ctl(fsm, spec.car, context)
        sat = ~eg(fsm, ~left)
        
    elif spec.type == parser.AG:
        left = eval_ctl(fsm, spec.car, context)
        true = BDD.true(fsm.bddEnc.DDmanager)
        sat = ~eu(fsm, true, ~left)
        
    elif spec.type == parser.AU:
        # A[p U q] = !E[!q W (!p & !q)] = !(E[!q U (!p & !q)] | EG !q)
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = ~(eu(fsm, ~right, ~left & ~right) | eg(fsm, ~right))
        
    elif spec.type == parser.AW:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = ~eu(fsm, ~right, ~left & ~right)
    
    else:
        sat = eval_ctl_spec(fsm, spec)
    
    return sat & fsm.reachable_states
Пример #26
0
def eval_ctl(fsm, spec, context=None):
    """
    Evaluate spec in fsm.
    
    Return the BDD representing all reachable states of fsm satisfying spec.
    """
    
    if spec.type == parser.CONTEXT:
        sat = eval_ctl(fsm, spec.cdr, spec.car)
        
    elif spec.type == parser.FALSEEXP:
        sat = BDD.false(fsm.bddEnc.DDmanager)
        
    elif spec.type == parser.TRUEEXP:
        sat = BDD.true(fsm.bddEnc.DDmanager)
        
    elif spec.type == parser.NOT:
        sat = ~eval_ctl(fsm, spec.car, context)
        
    elif spec.type == parser.OR:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = left | right
    
    elif spec.type == parser.AND:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = left & right
    
    elif spec.type == parser.IMPLIES:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = ~left | right
        
    elif spec.type == parser.IFF:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = (left & right) | (~left & ~right)
        
    elif spec.type == parser.EX:
        sat = ex(fsm, eval_ctl(fsm, spec.car, context))
        
    elif spec.type == parser.EF:
        left = BDD.true(fsm.bddEnc.DDmanager)
        right = eval_ctl(fsm, spec.car, context)
        sat = eu(fsm, left, right)
        
    elif spec.type == parser.EG:
        sat = eg(fsm, eval_ctl(fsm, spec.car, context))
        
    elif spec.type == parser.EU:
        sat = eu(fsm,
                 eval_ctl(fsm, spec.car, context),
                 eval_ctl(fsm, spec.cdr, context))
        
    elif spec.type == parser.EW:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = eg(fsm, left) | eu(fsm, left, right)
        
    elif spec.type == parser.AX:
        left = eval_ctl(fsm, spec.car, context)
        sat = ~ex(fsm, ~left)
        
    elif spec.type == parser.AF:
        left = eval_ctl(fsm, spec.car, context)
        sat = ~eg(fsm, ~left)
        
    elif spec.type == parser.AG:
        left = eval_ctl(fsm, spec.car, context)
        true = BDD.true(fsm.bddEnc.DDmanager)
        sat = ~eu(fsm, true, ~left)
        
    elif spec.type == parser.AU:
        # A[p U q] = !E[!q W (!p & !q)] = !(E[!q U (!p & !q)] | EG !q)
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = ~(eu(fsm, ~right, ~left & ~right) | eg(fsm, ~right))
        
    elif spec.type == parser.AW:
        left = eval_ctl(fsm, spec.car, context)
        right = eval_ctl(fsm, spec.cdr, context)
        sat = ~eu(fsm, ~right, ~left & ~right)
    
    else:
        sat = eval_ctl_spec(fsm, spec)
    
    return sat & fsm.reachable_states
Пример #27
0
 def test_success_or(self):
     fsm, _, _ = self.init_model()
     spec = atom("admin = alice | admin = bob")
     specbdd = eval_ctl_spec(fsm, spec)
     self.assertTrue((specbdd & fsm.init).is_false())
Пример #28
0
 def test_wrong_type(self):
     fsm, _, _ = self.init_model()
     spec = atom("admin = starting")
     specbdd = eval_ctl_spec(fsm, spec)
     self.assertTrue(specbdd.is_false())
Пример #29
0
spec = prop.expr
print(spec)
# print(fsm.count_states(fsm.init))
# for state in fsm.pick_all_states(fsm.init):
#     print(state.get_str_values())

# for state in fsm.pick_all_states(fsm.post(fsm.init)):
#     print(state.get_str_values())

# trans = BddTrans.from_string(fsm.bddEnc.symbTable,"next(time) = 0")
# for state in fsm.pick_all_states(trans.post(fsm.init)):
#     print(state.get_str_values())

bdd = pynusmv.mc.eval_ctl_spec(fsm, spec)  # & fsm.reachable_states
explanation = explain(fsm, fsm.init & ~eval_ctl_spec(fsm, spec), spec)
# print(explanation)
for state, inputs in zip(explanation[::2], explanation[1::2]):
    if state == explanation[-1]:
        print("-- Loop starts here")
    print(state.get_str_values())
    print(inputs.get_str_values())

# satstates = fsm.pick_all_states(bdd)
# # print(satstates)
#
# for state in satstates:
#    print(state.get_str_values())

# trans = BddTrans.from_string(fsm.bddEnc.symbTable)
# for state in fsm.pick_all_states(trans.post(fsm.init)):