Beispiel #1
0
def filter_cew_moves(mas, agents, moves_1, moves_2, moves):
    """
    mas -- a multi-agent system;
    agents -- a subset of agents of mas;
    moves_1 -- a subset of moves for agents;
    moves_2 -- a subset of moves for agents;
    moves -- a closed set of moves for agents.
    """
    # Abstract away actions of states
    states_1 = moves_1.forsome(mas.bddEnc.inputsCube)
    states_2 = moves_2.forsome(mas.bddEnc.inputsCube)
    
    states_1 = states_1 & mas.bddEnc.statesMask
    states_2 = states_2 & mas.bddEnc.statesMask
    
    moves_1 = states_1 & mas.protocol(agents)
    moves_2 = states_2 & mas.protocol(agents)
    
    # If there are no fairness constraints, the computation is simpler
    if not mas.fairness_constraints:
        # nu Q'. moves_2 & moves | (moves_1 & moves & pre_ce(Q'))
        return fixpoint(lambda Z: moves_2 & moves |
                                  (moves_1 & moves &
                                  pre_ce_moves(mas, agents, Z, moves)),
                        BDD.true(mas))
    
    else:
        moves_1_2_n = moves_1 | moves_2 | nfair_ce_moves(mas, agents, moves)
        moves_1_2_n = moves_1_2_n & moves
        return stay_ce_moves(mas, agents, moves_1_2_n, states_2 & moves, moves)
def _nfair(mas, formula, agents):
    """
    Return the set of states in which the given agents cannot avoid a fair path
    by using the strategy encoded in these states.
    """
    jump = mas.transitions[formula]["jump"]
    equiv = mas.transitions[formula]["equiv"]
    follow = mas.transitions[formula]["follow"]

    if not mas.fairness_constraints:
        return BDD.false(mas)

    else:
        # nfair =
        # mu Z. \/_fc []_group_follow(nu Y. (Z \/ ~fc) /\ []_group_follow(Y))
        def inner(Z):
            # \/_fc []_group_follow(nu Y. (Z \/ ~fc) /\ []_group_follow(Y))
            res = BDD.false(mas)
            for fc in mas.fairness_constraints:
                fc = fc.forsome(mas.bddEnc.inputsCube)
                nfc = ~fc
                res = res | ~follow.pre(~fixpoint(
                    lambda Y: (Z | nfc) & ~follow.pre(~Y), BDD.true(mas)))
            return res

        res = fixpoint(inner, BDD.false(mas))
        return res
Beispiel #3
0
def filter_cew(mas, agents, states_1, states_2, moves):
    """
    Return the set of states of mas for which there exists a strategy for
    agents compatible with moves such that all fair paths enforced by the
    strategy reach a state of states_2 through states of states_1, or stay in
    states_1 forever.
    
    mas -- a multi-agent system;
    agents -- a subset of agents of mas;
    states_1 -- a subset of states of mas;
    states_2 -- a subset of states of mas;
    moves -- a closed set of moves for agents.
    """
    # Abstract away actions of states
    states_1 = states_1.forsome(mas.bddEnc.inputsCube)
    states_2 = states_2.forsome(mas.bddEnc.inputsCube)
    
    states_1 = states_1 & mas.bddEnc.statesMask
    states_2 = states_2 & mas.bddEnc.statesMask
    
    # If there are no fairness constraints, the computation is simpler
    if not mas.fairness_constraints:
        # nu Q'. states_2 | (states_1 & pre_ce(Q'))
        return fixpoint(lambda Z: states_2 |
                                  (states_1 & pre_ce(mas, agents, Z, moves)),
                        BDD.true(mas))
    
    else:
        states_1_2_n = states_1 | states_2 | nfair_ce(mas, agents, moves)
        return stay_ce(mas, agents, states_1_2_n, states_2, moves)
Beispiel #4
0
def nfair_ce_moves(mas, agents, moves):
    """
    mas -- a multi-agent system;
    agents -- a subset of agents of mas;
    moves -- a closed set of moves for agents.
    """
    # If there are no fairness constraints, there are no nfair states.
    if not mas.fairness_constraints:
        return BDD.false(mas)
    
    else:
        def inner(Z):
            res = BDD.false(mas)
            for fc in mas.fairness_constraints:
                fc = fc.forsome(mas.bddEnc.inputsCube)
                nfc = ~fc & mas.bddEnc.statesMask
                nfc_moves = nfc & mas.protocol(agents) & moves
                m = stay_ce_moves(mas,
                                  agents,
                                  Z | nfc_moves,
                                  BDD.false(mas),
                                  moves)
                res |= pre_ce_moves(mas, agents, m, moves)
            return res
        return fixpoint(inner, BDD.false(mas))
 def inner(Z):
     res = BDD.true(mas)
     for fc in mas.fairness_constraints:
         fc = fc.forsome(mas.bddEnc.inputsCube)
         res = res & run.pre(
             fixpoint(lambda Y: (Z & fc) | run.pre(Y), BDD.false(mas)))
     return res
Beispiel #6
0
 def inner(Z):
     res = Z
     for f in fsm.fairness_constraints:
         res = res & fixpoint(lambda Y : (Z & f) | (phi & 
                             fsm.weak_pre(Y.forsome(fsm.bddEnc.inputsCube))),
                              BDD.false(fsm.bddEnc.DDmanager))
     return phi & fsm.weak_pre(res.forsome(fsm.bddEnc.inputsCube))
Beispiel #7
0
 def inner(Z):
     res = Z
     for f in fsm.fairness_constraints:
         res = res & fixpoint(
             lambda Y: (Z & f) |
             (phi & fsm.weak_pre(Y.forsome(fsm.bddEnc.inputsCube))),
             BDD.false(fsm.bddEnc.DDmanager))
     return phi & fsm.weak_pre(res.forsome(fsm.bddEnc.inputsCube))
Beispiel #8
0
def reach(mas, states):
    """
    Return the set of states reachable from states in mas.
    
    mas -- a multi-agents system;
    states -- a subset of states of mas.
    """
    return fixpoint(lambda Z: states | mas.post(Z), BDD.false(mas))
 def inner(Z):
     # \/_fc []_group_follow(nu Y. (Z \/ ~fc) /\ []_group_follow(Y))
     res = BDD.false(mas)
     for fc in mas.fairness_constraints:
         fc = fc.forsome(mas.bddEnc.inputsCube)
         nfc = ~fc
         res = res | ~follow.pre(~fixpoint(
             lambda Y: (Z | nfc) & ~follow.pre(~Y), BDD.true(mas)))
     return res
 def inner(Z):
     res = BDD.true(mas)
     for fc in mas.fairness_constraints:
         fc = fc.forsome(mas.bddEnc.inputsCube)
         res = res & run.pre(
             fixpoint(
                 lambda Y: (states_2 & _fair(mas))
                 | (Z & fc) | (states_1 & run.pre(Y)), BDD.false(mas)))
     return (res & states_1) | (states_2 & _fair(mas))
def ew(mas, states_1, states_2):
    run = mas.trans
    if not mas.fairness_constraints:
        return fixpoint(lambda Z: states_2 | (states_1 & run.pre(Z)),
                        BDD.true(mas))
    else:

        def inner(Z):
            res = BDD.true(mas)
            for fc in mas.fairness_constraints:
                fc = fc.forsome(mas.bddEnc.inputsCube)
                res = res & run.pre(
                    fixpoint(
                        lambda Y: (states_2 & _fair(mas))
                        | (Z & fc) | (states_1 & run.pre(Y)), BDD.false(mas)))
            return (res & states_1) | (states_2 & _fair(mas))

        return fixpoint(inner, BDD.true(mas))
Beispiel #12
0
def filter_ceu_moves(mas, agents, moves_1, moves_2, moves):
    """
    mas -- a multi-agent system;
    agents -- a subset of agents of mas;
    moves_1 -- a subset of moves for agents;
    moves_2 -- a subset of moves for agents;
    moves -- a closed set of moves for agents.
    """
    # Abstract away actions of states
    states_1 = moves_1.forsome(mas.bddEnc.inputsCube)
    states_2 = moves_2.forsome(mas.bddEnc.inputsCube)
    
    states_1 = states_1 & mas.bddEnc.statesMask
    states_2 = states_2 & mas.bddEnc.statesMask
    
    moves_1 = states_1 & mas.protocol(agents)
    moves_2 = states_2 & mas.protocol(agents)
    
    # If there are no fairness constraints, the computation is simpler
    if not mas.fairness_constraints:
        # mu Q'. moves_2 & moves | (moves_1 & moves & pre_ce_moves(Q'))
        return fixpoint(lambda Z: moves_2 & moves |
                                  (moves_1 &
                                   moves &
                                   pre_ce_moves(mas, agents, Z, moves)),
                        BDD.false(mas))
    
    else:
        moves_1_2_n = moves_1 | moves_2 | nfair_ce_moves(mas, agents, moves)
        moves_1_2_n = moves_1_2_n & moves
        def inner(Z):
            res = moves_2 & moves
            for fc in mas.fairness_constraints:
                fc = fc.forsome(mas.bddEnc.inputsCube)
                nfc = ~fc & mas.bddEnc.statesMask
                moves_nfc = nfc & mas.protocol(agents) & moves
                m = stay_ce_moves(mas,
                                  agents,
                                  moves_1_2_n & (Z | moves_nfc),
                                  moves_2 & moves & (Z | moves_nfc),
                                  moves)
                res |= pre_ce_moves(mas, agents, m, moves)
            return res & moves_1_2_n
        return fixpoint(inner, BDD.false(mas))
def eval_ceu(mas, formula, agents, states_1, states_2):
    jump = mas.transitions[formula]["jump"]
    equiv = mas.transitions[formula]["equiv"]
    follow = mas.transitions[formula]["follow"]
    reachable = mas.reachable_states

    if not mas.fairness_constraints:
        # <group>i[p U q] =
        # <>_group_jump []_group_equiv
        # (reachable => mu Z . q \/ (p /\ []_group_follow Z))
        return jump.pre(~equiv.pre(~(reachable.imply(
            fixpoint(lambda Z: states_2 |
                     (states_1 & ~follow.pre(~Z)), BDD.false(mas))))))
    else:
        nfair = _nfair(mas, formula, agents)

        # <group>i fair [p U q] =
        # <>_group_jump []_group_equiv
        # reachable =>
        # mu Z. (p \/ q \/ ~ifair) /\
        #       (q \/_fc []_group_follow
        #                (nu Y. (Z \/ ~fc) /\
        #                              (p \/ q \/ ~ifair) /\
        #                              (q \/ []_group_follow(Y))))
        def inner(Z):
            # (p \/ q \/ ~ifair) /\
            # (q \/_fc []_group_follow
            #          (nu Y. (Z \/ ~fc) /\
            #                        (p \/ q \/ ~ifair) /\
            #                        (q \/ []_group_follow(Y))))
            res = BDD.false(mas)
            for fc in mas.fairness_constraints:
                fc = fc.forsome(mas.bddEnc.inputsCube)
                nfc = ~fc
                # []_group_follow (nu Y. (Z \/ ~fc) /\
                #                        (p \/ q \/ ~ifair) /\
                #                        (q \/ []_group_follow(Y)))
                res = res | ~follow.pre(~(fixpoint(
                    lambda Y: ((Z | nfc) & (states_1 | states_2 | nfair) &
                               (states_2 | ~follow.pre(~Y))), BDD.true(mas))))
            return ((states_1 | states_2 | nfair) & (states_2 | res))

        return jump.pre(
            ~equiv.pre(~(reachable.imply(fixpoint(inner, BDD.false(mas))))))
Beispiel #14
0
def Cequiv(mas, agents, states):
    """
    Return the set of states of mas that are equivalent to some state in states
    w.r.t. common knowledge of agents.
    
    mas -- a multi-agent system;
    agents -- a set of agents;
    states -- a subset of states of mas.
    """
    return fixpoint(lambda Z: Eequiv(mas, agents, states | Z),
                    BDD.false(fsm.bddEnc.DDmanager))
Beispiel #15
0
def filter_ceu(mas, agents, states_1, states_2, moves):
    """
    Return the set of states of mas for which there exists a strategy for
    agents compatible with moves such that all fair paths enforced by the
    strategy reach a state of states_2 through states of states_1.
    
    mas -- a multi-agent system;
    agents -- a subset of agents of mas;
    states_1 -- a subset of states of mas;
    states_2 -- a subset of states of mas;
    moves -- a closed set of moves for agents.
    """
    # Abstract away actions of states
    states_1 = states_1.forsome(mas.bddEnc.inputsCube)
    states_2 = states_2.forsome(mas.bddEnc.inputsCube)
    
    states_1 = states_1 & mas.bddEnc.statesMask
    states_2 = states_2 & mas.bddEnc.statesMask
    
    # If there are no fairness constraints, the computation is simpler
    if not mas.fairness_constraints:
        # mu Q'. states_2 | (states_1 & pre_ce(Q'))
        return fixpoint(lambda Z: states_2 |
                                  (states_1 & pre_ce(mas, agents, Z, moves)),
                        BDD.false(mas))
    
    else:
        states_1_2_n = states_1 | states_2 | nfair_ce(mas, agents, moves)
        def inner(Z):
            res = states_2
            for fc in mas.fairness_constraints:
                fc = fc.forsome(mas.bddEnc.inputsCube)
                nfc = ~fc & mas.bddEnc.statesMask
                states = stay_ce(mas,
                                 agents,
                                 states_1_2_n & (Z | nfc),
                                 states_2 & (Z | nfc),
                                 moves)
                res |= pre_ce(mas, agents, states, moves)
            return res & states_1_2_n
        return fixpoint(inner, BDD.false(mas))
Beispiel #16
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)))
Beispiel #17
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.
Beispiel #18
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)
Beispiel #19
0
def eg(fsm, phi):    
    # EG p = nu Z . p & &_(f in F) Pre( mu Y . (Z & f) | (p & Pre(Y)) )
    #      = nu Z . p & &_(f in F) EX( mu Y . (Z & f) | (p & EX(Y)))
    
    def inner(Z):
        res = Z
        for f in fsm.fairness_constraints:
            res = res & fixpoint(lambda Y : (Z & f) | (phi & 
                                fsm.weak_pre(Y.forsome(fsm.bddEnc.inputsCube))),
                                 BDD.false(fsm.bddEnc.DDmanager))
        return phi & fsm.weak_pre(res.forsome(fsm.bddEnc.inputsCube))
        
    r = fixpoint(inner, BDD.true(fsm.bddEnc.DDmanager))
    return r.forsome(fsm.bddEnc.inputsCube)
Beispiel #20
0
def _cycle(fsm, gamma, phi, states):
    """
    Second 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: all states within a cycle in the first auxiliary set
    :rtype: :class:`pynusmv.dd.BDD`
    """
    psi = replace_placeholder(gamma, FalseExp())
    new_phi = And(phi, Not(psi))
    return fixpoint(lambda z: _reachable(fsm, new_phi, states) & fsm.post(z),
                    BDD.true(fsm.bddEnc.DDmanager))  # Greatest fixed point.
Beispiel #21
0
def eg(fsm, phi):
    # EG p = nu Z . p & &_(f in F) Pre( mu Y . (Z & f) | (p & Pre(Y)) )
    #      = nu Z . p & &_(f in F) EX( mu Y . (Z & f) | (p & EX(Y)))

    def inner(Z):
        res = Z
        for f in fsm.fairness_constraints:
            res = res & fixpoint(
                lambda Y: (Z & f) |
                (phi & fsm.weak_pre(Y.forsome(fsm.bddEnc.inputsCube))),
                BDD.false(fsm.bddEnc.DDmanager))
        return phi & fsm.weak_pre(res.forsome(fsm.bddEnc.inputsCube))

    r = fixpoint(inner, BDD.true(fsm.bddEnc.DDmanager))
    return r.forsome(fsm.bddEnc.inputsCube)
def eval_cew(mas, formula, agents, states_1, states_2):
    jump = mas.transitions[formula]["jump"]
    equiv = mas.transitions[formula]["equiv"]
    follow = mas.transitions[formula]["follow"]
    reachable = mas.reachable_states

    if not mas.fairness_constraints:
        # <group>i[p W q] =
        # <>_group_jump []_group_equiv
        # (reachable => nu Z . q \/ (p /\ []_group_follow Z))
        return jump.pre(~equiv.pre(~(reachable.imply(
            fixpoint(lambda Z: states_2 |
                     (states_1 & ~follow.pre(~Z)), BDD.true(mas))))))
    else:
        nfair = _nfair(mas, formula, agents)
        # <group>i fair [p W q] =
        # <>_group_jump []_group_equiv
        # reachable =>
        # nu Z. (p \/ q \/ ~ifair) /\ (q \/ []_group_follow(Z))
        res = jump.pre(~equiv.pre(~(reachable.imply(
            fixpoint(
                lambda Z: ((states_1 | states_2 | nfair) &
                           (states_2 | ~follow.pre(~Z))), BDD.true(mas))))))
        return res
def _fair(mas):
    if not mas.fairness_constraints:
        return BDD.true(mas)
    else:
        run = mas.trans

        # fair = nu Z. /\_fc pre(mu Y. (Z /\ fc) \/ pre(Y))
        def inner(Z):
            res = BDD.true(mas)
            for fc in mas.fairness_constraints:
                fc = fc.forsome(mas.bddEnc.inputsCube)
                res = res & run.pre(
                    fixpoint(lambda Y: (Z & fc) | run.pre(Y), BDD.false(mas)))
            return res

        return fixpoint(inner, BDD.true(mas))
 def inner(Z):
     # (p \/ q \/ ~ifair) /\
     # (q \/_fc []_group_follow
     #          (nu Y. (Z \/ ~fc) /\
     #                        (p \/ q \/ ~ifair) /\
     #                        (q \/ []_group_follow(Y))))
     res = BDD.false(mas)
     for fc in mas.fairness_constraints:
         fc = fc.forsome(mas.bddEnc.inputsCube)
         nfc = ~fc
         # []_group_follow (nu Y. (Z \/ ~fc) /\
         #                        (p \/ q \/ ~ifair) /\
         #                        (q \/ []_group_follow(Y)))
         res = res | ~follow.pre(~(fixpoint(
             lambda Y: ((Z | nfc) & (states_1 | states_2 | nfair) &
                        (states_2 | ~follow.pre(~Y))), BDD.true(mas))))
     return ((states_1 | states_2 | nfair) & (states_2 | res))
Beispiel #25
0
def stay_ce(mas, agents, states_1, states_2, moves):
    """
    mas -- a multi-agent system;
    agents -- a subset of agents of mas;
    states_1 -- a subset of states of mas;
    states_2 -- a subset of states of mas;
    moves -- a set of moves for agents.
    """
    # Abstract away actions of states
    states_1 = states_1.forsome(mas.bddEnc.inputsCube)
    states_2 = states_2.forsome(mas.bddEnc.inputsCube)
    
    states_1 = states_1 & mas.bddEnc.statesMask
    states_2 = states_2 & mas.bddEnc.statesMask
    
    return fixpoint(lambda Z: states_2 |
                              (states_1 & pre_ce(mas, agents, Z, moves)),
                    BDD.true(mas))
Beispiel #26
0
def stay_ce_moves(mas, agents, moves_1, moves_2, moves):
    """
    mas -- a multi-agent system;
    agents -- a subset of agents of mas;
    moves_1 -- a subset of moves for agents;
    moves_2 -- a subset of moves for agents;
    moves -- a set of moves for agents.
    """
    agents_cube = mas.inputs_cube_for_agents(agents)
    others_cube = mas.bddEnc.inputsCube - agents_cube
    
    # Abstract away actions of states
    moves_1 = moves_1.forsome(others_cube)
    moves_2 = moves_2.forsome(others_cube)
    
    moves_1 = moves_1 & mas.bddEnc.statesInputsMask
    moves_2 = moves_2 & mas.bddEnc.statesInputsMask
    
    return fixpoint(lambda Z: moves_2 |
                              (moves_1 & pre_ce_moves(mas, agents, Z, moves)),
                    BDD.true(mas))
Beispiel #27
0
def eu(fsm, phi, psi):
    # E[p U q] = q | (p & EX E[p U q]) = mu Z . q | (p & Pre(Z))
    return fixpoint(
        lambda X:
        (psi & fair_states(fsm) & fsm.reachable_states) | (phi & ex(fsm, X)),
        BDD.false(fsm.bddEnc.DDmanager))
Beispiel #28
0
def eu(fsm, phi, psi):
    # E[p U q] = q | (p & EX E[p U q]) = mu Z . q | (p & Pre(Z))
    return fixpoint(lambda X : (psi & fair_states(fsm) & fsm.reachable_states) |
                               (phi & ex(fsm, X)),
                    BDD.false(fsm.bddEnc.DDmanager))
def eu(mas, states_1, states_2):
    run = mas.trans
    return fixpoint(
        lambda Y: (states_2 & _fair(mas)) | (states_1 & run.pre(Y)),
        BDD.false(mas))