def check_cex(self, fsm, explanation, agents, phi):
     """Check that the explanation is correct."""
     # Get the cubes
     gamma_cube = fsm.inputs_cube_for_agents(agents)
     ngamma_cube = fsm.bddEnc.inputsCube - gamma_cube
     
     # The first state satisfies the spec
     self.assertTrue(explanation.state <= cex(fsm, agents, phi))
     acts = BDD.false(fsm.bddEnc.DDmanager)
     states = BDD.false(fsm.bddEnc.DDmanager)
     for (act, succ) in explanation.successors:
         ag_action = act.forsome(ngamma_cube)
         # The successor satisfies phi
         self.assertTrue(succ.state <= phi)
         # The action is effectively possible
         self.assertTrue(act <= fsm.get_inputs_between_states(
                                              explanation.state, succ.state))
         # Accumulate states and actions
         acts = acts | act
         states = states | succ.state
     
     # The reached states are effectively the reachable states
     # through the action
     self.assertTrue(states <= fsm.post(explanation.state, ag_action))
     self.assertTrue(states >= fsm.post(explanation.state, ag_action)
                                                     & fsm.bddEnc.statesMask)
                                                     
     # The actions are effectively all the possible actions completing ag_act
     self.assertTrue(acts <= ag_action)
     self.assertTrue(acts >= ag_action & 
                   fsm.get_inputs_between_states(explanation.state, states) &
                   fsm.bddEnc.inputsMask)
Example #2
0
    def check_free_choice(self):
        """
        Check whether this MAS satisfies the free-choice property, that is,
        in every state, the choices of actions for each agent is not
        constrained by the choices of other agents.
        
        Return the set of moves that are not present in the MAS and should,
        or that are present but should not.
        """

        if len(self.agents) <= 0:
            return BDD.false(self.bddEnc.DDmanager)

        true = BDD.true(self.bddEnc.DDmanager)
        protocols = {agent: self.protocol({agent}) for agent in self.agents}
        enabled = (self.weak_pre(self.reachable_states) & self.reachable_states
                   & self.bddEnc.statesInputsMask)

        for s in self.pick_all_states(self.reachable_states):
            product = self.bddEnc.statesInputsMask
            for agent in self.agents:
                product &= protocols[agent] & s
            if (enabled & s) != product:
                return product.xor(enabled & s)
        return BDD.false(self.bddEnc.DDmanager)
Example #3
0
 def test_get_false(self):
     (fsm, enc, manager) = self.init_model()
     
     false = BDD.false(manager)
     self.assertIsNotNone(false)
     self.assertTrue(false.is_false())
     self.assertFalse(false.is_true())
     self.assertTrue(false.isnot_true())
     self.assertFalse(false.isnot_false())
     self.assertTrue(false.isnot_true())
     
     false = BDD.false()
     self.assertIsNotNone(false)
     self.assertTrue(false.is_false())
     self.assertFalse(false.is_true())
     self.assertTrue(false.isnot_true())
     self.assertFalse(false.isnot_false())
     self.assertTrue(false.isnot_true())
     
     false = BDD.false()
     self.assertIsNotNone(false)
     self.assertTrue(false.is_false())
     self.assertFalse(false.is_true())
     self.assertTrue(false.isnot_true())
     self.assertFalse(false.isnot_false())
     self.assertTrue(false.isnot_true())
Example #4
0
def nfair_gamma_states(fsm, agents):
    """
    Return the set of states in which agents cann avoid fair paths.
    
    fsm -- the model
    agents -- a list of agents names
    """
    # NFair_Gamma = not([Gamma] G True) = <Gamma> F False
    agents = frozenset(agents)
    if agents not in __nfair_gamma_states:
        if len(fsm.fairness_constraints) == 0:
            __nfair_gamma_states[agents] = BDD.false(fsm.bddEnc.DDmanager)
        else:
            def inner(Z):
                res = BDD.false(fsm.bddEnc.DDmanager)
                for f in fsm.fairness_constraints:
                    nf = ~f #& fsm.bddEnc.statesMask
                    res = res | fsm.pre_strat(fp(lambda Y :
                                                 (Z | nf) &
                                                 fsm.pre_strat(Y, agents),
                                                BDD.true(fsm.bddEnc.DDmanager)),
                                              agents)
                return res
            __nfair_gamma_states[agents] = fp(inner, 
                                              BDD.false(fsm.bddEnc.DDmanager))
    return __nfair_gamma_states[agents]
Example #5
0
    def test_get_false(self):
        (fsm, enc, manager) = self.init_model()

        false = BDD.false(manager)
        self.assertIsNotNone(false)
        self.assertTrue(false.is_false())
        self.assertFalse(false.is_true())
        self.assertTrue(false.isnot_true())
        self.assertFalse(false.isnot_false())
        self.assertTrue(false.isnot_true())

        false = BDD.false()
        self.assertIsNotNone(false)
        self.assertTrue(false.is_false())
        self.assertFalse(false.is_true())
        self.assertTrue(false.isnot_true())
        self.assertFalse(false.isnot_false())
        self.assertTrue(false.isnot_true())

        false = BDD.false()
        self.assertIsNotNone(false)
        self.assertTrue(false.is_false())
        self.assertFalse(false.is_true())
        self.assertTrue(false.isnot_true())
        self.assertFalse(false.isnot_false())
        self.assertTrue(false.isnot_true())
Example #6
0
def nfair_gamma_si(fsm, agents, strat=None):
    """
    Return the set of state/inputs pairs of strat
    in which agents can avoid a fair path in strat.
    If strat is None, it is considered true.
    
    fsm -- the model
    agents -- a list of agents names
    strat -- a BDD representing allowed state/inputs pairs, or None
    
    """
    if not strat:
        strat = BDD.true(fsm.bddEnc.DDmanager)
    
    if len(fsm.fairness_constraints) == 0:
        return BDD.false(fsm.bddEnc.DDmanager)
    else:
        def inner(Z):
            res = BDD.false(fsm.bddEnc.DDmanager)
            for f in fsm.fairness_constraints:
                nf = ~f & fsm.bddEnc.statesMask & strat
                res = res | fsm.pre_strat_si(fp(lambda Y :
                                                 (Z | nf) &
                                                 fsm.pre_strat_si(Y, agents,
                                                                  strat),
                                             BDD.true(fsm.bddEnc.DDmanager)),
                                             agents, strat)
            return res
        return fp(inner, BDD.false(fsm.bddEnc.DDmanager))
Example #7
0
def ceu(fsm, agents, phi, psi):
    """
    Return the set of states of fsm satisfying <agents>[phi U psi].
    
    fsm -- a MAS representing the system
    agents -- a list of agents names
    phi -- a BDD representing the set of states of fsm satisfying phi
    psi -- a BDD representing the set of states of fsm satisfying psi
    """
    # phi = phi & fsm.bddEnc.statesInputsMask
    # psi = psi & fsm.bddEnc.statesInputsMask

    if len(fsm.fairness_constraints) == 0:
        return fp(lambda Z: psi | (phi & fsm.pre_strat(Z, agents)), BDD.false(fsm.bddEnc.DDmanager))
    else:
        nfair = nfair_gamma_states(fsm, agents)

        def inner(Z):
            res = psi
            for f in fsm.fairness_constraints:
                nf = ~f  # & fsm.bddEnc.statesMask
                res = res | fsm.pre_strat(
                    fp(
                        lambda Y: (phi | psi | nfair) & (Z | nf) & (psi | fsm.pre_strat(Y, agents)),
                        BDD.true(fsm.bddEnc.DDmanager),
                    ),
                    agents,
                )
            return (psi | phi | nfair) & res

        return fp(inner, BDD.false(fsm.bddEnc.DDmanager))
Example #8
0
 def check_cex(self, fsm, explanation, agents, phi):
     """Check that the explanation is correct."""
     # Get the cubes
     gamma_cube = fsm.inputs_cube_for_agents(agents)
     ngamma_cube = fsm.bddEnc.inputsCube - gamma_cube
     
     # The first state satisfies the spec
     self.assertTrue(explanation.state <= cex(fsm, agents, phi))
     acts = BDD.false(fsm.bddEnc.DDmanager)
     states = BDD.false(fsm.bddEnc.DDmanager)
     for (act, succ) in explanation.successors:
         ag_action = act.forsome(ngamma_cube)
         # The successor satisfies phi
         self.assertTrue(succ.state <= phi)
         # The action is effectively possible
         self.assertTrue(act <= fsm.get_inputs_between_states(
                                              explanation.state, succ.state))
         # Accumulate states and actions
         acts = acts | act
         states = states | succ.state
     
     # The reached states are effectively the reachable states
     # through the action
     self.assertTrue(states <= fsm.post(explanation.state, ag_action))
     self.assertTrue(states >= fsm.post(explanation.state, ag_action)
                                                     & fsm.bddEnc.statesMask)
                                                     
     # The actions are effectively all the possible actions completing ag_act
     self.assertTrue(acts <= ag_action)
     self.assertTrue(acts >= ag_action & 
                   fsm.get_inputs_between_states(explanation.state, states) &
                   fsm.bddEnc.inputsMask)
Example #9
0
def ceu(fsm, agents, phi, psi):
    """
    Return the set of states of fsm satisfying <agents>[phi U psi].
    
    fsm -- a MAS representing the system
    agents -- a list of agents names
    phi -- a BDD representing the set of states of fsm satisfying phi
    psi -- a BDD representing the set of states of fsm satisfying psi
    """
    #phi = phi & fsm.bddEnc.statesInputsMask
    #psi = psi & fsm.bddEnc.statesInputsMask
    
    if len(fsm.fairness_constraints) == 0:
        return fp(lambda Z : psi | (phi & fsm.pre_strat(Z, agents)),
                  BDD.false(fsm.bddEnc.DDmanager))
    else:
        nfair = nfair_gamma_states(fsm, agents)
        def inner(Z):
            res = psi
            for f in fsm.fairness_constraints:
                nf = ~f #& fsm.bddEnc.statesMask
                res = res | fsm.pre_strat(fp(lambda Y :
                                             (phi | psi | nfair) &
                                              (Z | nf) &
                                              (psi | fsm.pre_strat(Y, agents)),
                                              BDD.true(fsm.bddEnc.DDmanager)),
                                              agents)
            return (psi | phi | nfair) & res
        return fp(inner, BDD.false(fsm.bddEnc.DDmanager))
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
 def check_cax(self, fsm, explanation, agents, phi):
     """Check that the explanation is correct."""
     # Get the cubes
     gamma_cube = fsm.inputs_cube_for_agents(agents)
     ngamma_cube = fsm.bddEnc.inputsCube - gamma_cube
     
     # The first state satisfies the spec
     self.assertTrue(explanation.state <= ~cex(fsm, agents, ~phi))
     acts = BDD.false(fsm.bddEnc.DDmanager)
     states = BDD.false(fsm.bddEnc.DDmanager)
     for (act, succ) in explanation.successors:
         # The successor satisfies phi
         self.assertTrue(succ.state <= phi)
         # The action is effectively possible
         self.assertTrue(act <= fsm.get_inputs_between_states(
                                              explanation.state, succ.state))
         # Accumulate states and actions
         acts = acts | act
         states = states | succ.state
     
     # The actions are effectively all the possible ones
     self.assertEqual((fsm.protocol(agents) &
                       explanation.state).forsome(fsm.bddEnc.statesCube).
                       forsome(ngamma_cube) &
                      fsm.bddEnc.statesMask,
                      acts.forsome(ngamma_cube) & fsm.bddEnc.statesMask)
Example #12
0
def ceu(fsm, agents, phi, psi, strat=None):
    """
    Return the set of states of strat satisfying <agents>[phi U psi]
    under full observability in strat.
    If strat is None, strat is considered true.
    
    fsm -- a MAS representing the system
    agents -- a list of agents names
    phi -- a BDD representing the set of states of fsm satisfying phi
    psi -- a BDD representing the set of states of fsm satisfying psi
    strat -- a BDD representing allowed state/inputs pairs, or None
    
    """
    
    if len(fsm.fairness_constraints) == 0:
        return fp(lambda Z : psi | (phi & fsm.pre_strat(Z, agents, strat)),
                  BDD.false(fsm.bddEnc.DDmanager))
    else:
        nfair = nfair_gamma(fsm, agents, strat)
        def inner(Z):
            res = psi
            for f in fsm.fairness_constraints:
                nf = ~f
                res = res | fsm.pre_strat(fp(lambda Y :
                                             (phi | psi | nfair) &
                                             (Z | nf) &
                                             (psi |
                                              fsm.pre_strat(Y, agents, strat)),
                                             BDD.true(fsm.bddEnc.DDmanager)),
                                              agents, strat)
            return (psi | phi | nfair) & res
        return fp(inner, BDD.false(fsm.bddEnc.DDmanager))
Example #13
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))
Example #14
0
def nfair_gamma_si(fsm, agents, strat=None):
    """
    Return the set of state/inputs pairs of strat
    in which agents can avoid a fair path in strat.
    If strat is None, it is considered true.
    
    fsm -- the model
    agents -- a list of agents names
    strat -- a BDD representing allowed state/inputs pairs, or None
    
    """
    if not strat:
        strat = BDD.true(fsm.bddEnc.DDmanager)

    if len(fsm.fairness_constraints) == 0:
        return BDD.false(fsm.bddEnc.DDmanager)
    else:

        def inner(Z):
            res = BDD.false(fsm.bddEnc.DDmanager)
            for f in fsm.fairness_constraints:
                nf = ~f & fsm.bddEnc.statesMask & strat
                res = res | fsm.pre_strat_si(
                    fp(lambda Y: (Z | nf) & fsm.pre_strat_si(Y, agents, strat),
                       BDD.true(fsm.bddEnc.DDmanager)), agents, strat)
            return res

        return fp(inner, BDD.false(fsm.bddEnc.DDmanager))
Example #15
0
def nfair_gamma_states(fsm, agents):
    """
    Return the set of states in which agents cann avoid fair paths.
    
    fsm -- the model
    agents -- a list of agents names
    """
    # NFair_Gamma = not([Gamma] G True) = <Gamma> F False
    agents = frozenset(agents)
    if agents not in __nfair_gamma_states:
        if len(fsm.fairness_constraints) == 0:
            __nfair_gamma_states[agents] = BDD.false(fsm.bddEnc.DDmanager)
        else:

            def inner(Z):
                res = BDD.false(fsm.bddEnc.DDmanager)
                for f in fsm.fairness_constraints:
                    nf = ~f  # & fsm.bddEnc.statesMask
                    res = res | fsm.pre_strat(
                        fp(lambda Y: (Z | nf) & fsm.pre_strat(Y, agents), BDD.true(fsm.bddEnc.DDmanager)), agents
                    )
                return res

            __nfair_gamma_states[agents] = fp(inner, BDD.false(fsm.bddEnc.DDmanager))
    return __nfair_gamma_states[agents]
Example #16
0
 def check_free_choice(self):
     """
     Check whether this MAS satisfies the free-choice property, that is,
     in every state, the choices of actions for each agent is not
     constrained by the choices of other agents.
     
     Return the set of moves that are not present in the MAS and should,
     or that are present but should not.
     """
     
     if len(self.agents) <= 0:
         return BDD.false(self.bddEnc.DDmanager)
     
     true = BDD.true(self.bddEnc.DDmanager)
     protocols = {agent: self.protocol({agent}) for agent in self.agents}
     enabled = (self.weak_pre(self.reachable_states) &
                self.reachable_states & self.bddEnc.statesInputsMask)
     
     for s in self.pick_all_states(self.reachable_states):
         product = self.bddEnc.statesInputsMask
         for agent in self.agents:
             product &= protocols[agent] & s
         if (enabled & s) != product:
             return product.xor(enabled & s)
     return BDD.false(self.bddEnc.DDmanager)
Example #17
0
 def check_cax(self, fsm, explanation, agents, phi):
     """Check that the explanation is correct."""
     # Get the cubes
     gamma_cube = fsm.inputs_cube_for_agents(agents)
     ngamma_cube = fsm.bddEnc.inputsCube - gamma_cube
     
     # The first state satisfies the spec
     self.assertTrue(explanation.state <= ~cex(fsm, agents, ~phi))
     acts = BDD.false(fsm.bddEnc.DDmanager)
     states = BDD.false(fsm.bddEnc.DDmanager)
     for (act, succ) in explanation.successors:
         # The successor satisfies phi
         self.assertTrue(succ.state <= phi)
         # The action is effectively possible
         self.assertTrue(act <= fsm.get_inputs_between_states(
                                              explanation.state, succ.state))
         # Accumulate states and actions
         acts = acts | act
         states = states | succ.state
     
     # The actions are effectively all the possible ones
     self.assertEqual((fsm.protocol(agents) &
                       explanation.state).forsome(fsm.bddEnc.statesCube).
                       forsome(ngamma_cube) &
                      fsm.bddEnc.statesMask,
                      acts.forsome(ngamma_cube) & fsm.bddEnc.statesMask)
Example #18
0
 def inner(Z):
     res = BDD.false(mas)
     for fc in mas.fairness_constraints:
         fc = fc.forsome(mas.bddEnc.inputsCube)
         nfc = ~fc & mas.bddEnc.statesMask
         states = stay_ce(mas, agents, Z | nfc, BDD.false(mas), moves)
         res |= pre_ce(mas, agents, states, moves)
     return res
Example #19
0
 def test_init(self):
     fsm = self.init_model()
     manager = fsm.bddEnc.DDmanager
     init = fsm.init
     
     initState = fsm.pick_one_state(init)
     
     self.assertTrue(BDD.false(manager) <= init <= BDD.true(manager))
     self.assertTrue(BDD.false(manager) < initState <= init)
Example #20
0
def eval_strat_FSF(fsm, spec):
    """
    Return the BDD representing the set of states of fsm satisfying spec.
    spec is a strategic operator <G> pi.
    
    Implement a variant of the algorithm that
    filters, splits and then filters.
    
    fsm -- a MAS representing the system;
    spec -- an AST-based ATLK specification with a top strategic operator.
    
    """
    
    if type(spec) is CAX:
        # [g] X p = ~<g> X ~p
        newspec = CEX(spec.group, Not(spec.child))
        return ~eval_strat_FSF(fsm, newspec)
        
    elif type(spec) is CAG:
        # [g] G p = ~<g> F ~p
        newspec = CEF(spec.group, Not(spec.child))
        return ~eval_strat_FSF(fsm, newspec)
        
    elif type(spec) is CAU:
        # [g][p U q] = ~<g>[ ~q W ~p & ~q ]
        newspec = CEW(spec.group,
                      Not(spec.right),
                      And(Not(spec.left), Not(spec.right)))
        return ~eval_strat_FSF(fsm, newspec)
        
    elif type(spec) is CAF:
        # [g] F p = ~<g> G ~p
        newspec = CEG(spec.group, Not(spec.child))
        return ~eval_strat_FSF(fsm, newspec)
        
    elif type(spec) is CAW:
        # [g][p W q] = ~<g>[~q U ~p & ~q]
        newspec = CEU(spec.group,
                      Not(spec.right),
                      And(Not(spec.left), Not(spec.right)))
        return ~eval_strat_FSF(fsm, newspec)
        
        
    sat = BDD.false(fsm.bddEnc.DDmanager)
    agents = {atom.value for atom in spec.group}
    
    # First filtering
    winning = filter_strat(fsm, spec, variant="FSF")
    
    if winning.is_false(): # no state/inputs pairs are winning => return false
        return winning
    
    return split_eval(fsm, spec, BDD.false(fsm.bddEnc.DDmanager),
                      winning)
Example #21
0
 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
Example #22
0
def eval_strat_FSF(fsm, spec):
    """
    Return the BDD representing the set of states of fsm satisfying spec.
    spec is a strategic operator <G> pi.
    
    Implement a variant of the algorithm that
    filters, splits and then filters.
    
    fsm -- a MAS representing the system;
    spec -- an AST-based ATLK specification with a top strategic operator.
    
    """

    if type(spec) is CAX:
        # [g] X p = ~<g> X ~p
        newspec = CEX(spec.group, Not(spec.child))
        return ~eval_strat_FSF(fsm, newspec)

    elif type(spec) is CAG:
        # [g] G p = ~<g> F ~p
        newspec = CEF(spec.group, Not(spec.child))
        return ~eval_strat_FSF(fsm, newspec)

    elif type(spec) is CAU:
        # [g][p U q] = ~<g>[ ~q W ~p & ~q ]
        newspec = CEW(spec.group, Not(spec.right),
                      And(Not(spec.left), Not(spec.right)))
        return ~eval_strat_FSF(fsm, newspec)

    elif type(spec) is CAF:
        # [g] F p = ~<g> G ~p
        newspec = CEG(spec.group, Not(spec.child))
        return ~eval_strat_FSF(fsm, newspec)

    elif type(spec) is CAW:
        # [g][p W q] = ~<g>[~q U ~p & ~q]
        newspec = CEU(spec.group, Not(spec.right),
                      And(Not(spec.left), Not(spec.right)))
        return ~eval_strat_FSF(fsm, newspec)

    sat = BDD.false(fsm.bddEnc.DDmanager)
    agents = {atom.value for atom in spec.group}

    # First filtering
    winning = filter_strat(fsm, spec, variant="FSF")

    if winning.is_false():  # no state/inputs pairs are winning => return false
        return winning

    return split_eval(fsm, spec, BDD.false(fsm.bddEnc.DDmanager), winning)
Example #23
0
def split_eval(fsm, spec, common, rest):
    """
    Split strats into all its non-conflicting greatest subsets and compute
    the states that satisfy spec in strats.
    
    fsm -- the model
    strats -- a BDD representing a set of states/inputs pairs
    spec -- an AST-based ATLK specification with a top strategic operator.
    
    """    
    if (common | rest).is_false():
        return common | rest
    else:
        gamma = {atom.value for atom in spec.group}
        sat = BDD.false(fsm.bddEnc.DDmanager)
        
        for newcommon, splitted, newrest in split_one(fsm, rest, gamma):
            if splitted.is_false():
                # newcommon contains a partial uniform strategy
                # we can extract the winning states
                # from newcommon | common
                
                # first, filter
                winning = (filter_strat(fsm, spec, common | newcommon, "SF")
                           .forsome(fsm.bddEnc.inputsCube))
                
                # then, get equiv sat
                sat = sat | all_equiv_sat(fsm, winning, gamma)
                gc.collect()
            else:
                sat = sat | split_eval(fsm, spec, common | newcommon | splitted,
                                       newrest)
        return sat
Example #24
0
 def test_size(self):
     (fsm, enc, manager) = self.init_model()
     true = BDD.true(manager)
     false = BDD.false(manager)
     init = fsm.init
     noadmin = eval_simple_expression(fsm, "admin = none")
     alice = eval_simple_expression(fsm, "admin = alice")
     processing = eval_simple_expression(fsm, "state = processing")
     
     self.assertEqual(BDD.true().size, 1)
     self.assertEqual(BDD.false().size, 1)
     self.assertEqual(fsm.pick_one_state(BDD.true()).size,
                      len(fsm.bddEnc.get_variables_ordering("bits")) + 1)
     self.assertEqual(init.size, 5)
     self.assertEqual(processing.size, 3)
     
Example #25
0
def get_equiv_class(fsm, gamma, state, semantics="group"):
    """
    Return the equivalence class for gamma state belongs to. The equivalence
    class depends on semantics; if semantics is individual, the common
    knowledge based equivalence class for gamma containing state is returned;
    otherwise (assuming semantics is group), the distributed knowledge based
    equivalence fo gamma containing state is returned.
    
    fsm -- the model
    gamma -- a set of agents of fsm
    semantics -- the semantic to use (group or individual);
                 if not "individual", "group" semantics is used
    """
    if semantics == "individual":
        old = BDD.false(fsm.bddEnc.DDmanager)
        eq = state
        while old != eq:
            old = eq
            for agent in gamma:
                eq |= (fsm.equivalent_states(old, {agent}) &
                       fsm.reachable_states)
            
        return eq
    else:
        return fsm.equivalent_states(state, gamma) & fsm.reachable_states
Example #26
0
 def inner(Z):
     res = phi
     for f in fsm.fairness_constraints:
         res = res & fsm.pre(fp(lambda Y : (Z & f) |
                                (phi & fsm.pre(Y)),
                                BDD.false(fsm.bddEnc.DDmanager)))
     return res
Example #27
0
def get_equiv_class(fsm, gamma, state, semantics="group"):
    """
    Return the equivalence class for gamma state belongs to. The equivalence
    class depends on semantics; if semantics is individual, the common
    knowledge based equivalence class for gamma containing state is returned;
    otherwise (assuming semantics is group), the distributed knowledge based
    equivalence fo gamma containing state is returned.
    
    fsm -- the model
    gamma -- a set of agents of fsm
    semantics -- the semantic to use (group or individual);
                 if not "individual", "group" semantics is used
    """
    if semantics == "individual":
        old = BDD.false(fsm.bddEnc.DDmanager)
        eq = state
        while old != eq:
            old = eq
            for agent in gamma:
                eq |= (fsm.equivalent_states(old, {agent}) &
                       fsm.reachable_states)
            
        return eq
    else:
        return fsm.equivalent_states(state, gamma) & fsm.reachable_states
def split_one_all(mas, agents, agent, moves):
    """
    Split one equivalence class of moves and return couples composed of
    a split and the rest of moves to split; the last couple is the rest of
    moves to split only, the split being empty.
    
    mas -- a multi-agents system;
    agents -- a subset of agents of mas;
    agent -- an agent of agents;
    moves -- a subset of moves for agents.
    
    Return a generator of all couples of splits and rest of moves, the last
    couple containing an empty split.
    
    """
    if moves.is_false():
        yield (moves, moves)
        return

    else:
        # Get one equivalence class
        si = mas.pick_one_state_inputs(moves)
        s = si.forsome(mas.bddEnc.inputsCube)
        eqs = get_equiv_class(mas, [agent], s)
        eqcl = moves & eqs

        # Remove it from strats
        moves = moves - eqcl

        # The current equivalence class is conflicting
        for non_conflicting in split_conflicting(mas, agents, agent, eqcl):
            yield (non_conflicting, moves)
        yield (BDD.false(mas.bddEnc.DDmanager), moves)
        return
Example #29
0
 def inner(Z):
     res = phi
     for f in fsm.fairness_constraints:
         res = res & fsm.pre_nstrat(
             fp(lambda Y: (Z & f) | (phi & fsm.pre_nstrat(Y, agents)), BDD.false(fsm.bddEnc.DDmanager)), agents
         )
     return res
Example #30
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))
Example #31
0
    def test_size(self):
        (fsm, enc, manager) = self.init_model()
        true = BDD.true(manager)
        false = BDD.false(manager)
        init = fsm.init
        noadmin = eval_simple_expression(fsm, "admin = none")
        alice = eval_simple_expression(fsm, "admin = alice")
        processing = eval_simple_expression(fsm, "state = processing")

        self.assertEqual(BDD.true().size, 1)
        self.assertEqual(BDD.false().size, 1)
        self.assertEqual(
            fsm.pick_one_state(BDD.true()).size,
            len(fsm.bddEnc.get_variables_ordering("bits")) + 1)
        self.assertEqual(init.size, 5)
        self.assertEqual(processing.size, 3)
Example #32
0
 def test_false(self):
     ast = negation_normal_form(
         parse_ctlq("A['admin = bob' oW A['admin = alice' oU AG ?]]"))
     self.assertTrue(check_ctlqx(ast))
     fsm = self.init_model()
     self.assertEqual(solve_ctlqx(fsm, ast),
                      BDD.false(fsm.bddEnc.DDmanager))
Example #33
0
def split_eval(fsm, spec, common, rest):
    """
    Split strats into all its non-conflicting greatest subsets and compute
    the states that satisfy spec in strats.
    
    fsm -- the model
    strats -- a BDD representing a set of states/inputs pairs
    spec -- an AST-based ATLK specification with a top strategic operator.
    
    """
    if (common | rest).is_false():
        return common | rest
    else:
        gamma = {atom.value for atom in spec.group}
        sat = BDD.false(fsm.bddEnc.DDmanager)

        for newcommon, splitted, newrest in split_one(fsm, rest, gamma):
            if splitted.is_false():
                # newcommon contains a partial uniform strategy
                # we can extract the winning states
                # from newcommon | common

                # first, filter
                winning = (filter_strat(fsm, spec, common | newcommon,
                                        "SF").forsome(fsm.bddEnc.inputsCube))

                # then, get equiv sat
                sat = sat | all_equiv_sat(fsm, winning, gamma)
                gc.collect()
            else:
                sat = sat | split_eval(fsm, spec,
                                       common | newcommon | splitted, newrest)
        return sat
 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
Example #35
0
 def test_false(self):
     ast = negation_normal_form(
         parse_ctlq("A['admin = bob' oW A['admin = alice' oU AG ?]]")
     )
     self.assertTrue(check_ctlqx(ast))
     fsm = self.init_model()
     self.assertEqual(solve_ctlqx(fsm, ast),
                      BDD.false(fsm.bddEnc.DDmanager))
def eg(fsm, phi):
    res = BDD.true(fsm.bddEnc.DDmanager)
    old = BDD.false(fsm.bddEnc.DDmanager)
    while res != old:
        old = res
        new = ex(fsm, res)
        res = res & new & phi & fsm.reachable_states
    return res
Example #37
0
def eg(fsm, phi):
    res = BDD.true(fsm.bddEnc.DDmanager)
    old = BDD.false(fsm.bddEnc.DDmanager)
    while res != old:
        old = res
        new = ex(fsm, res)
        res = res & new & phi & fsm.reachable_states
    return res
Example #38
0
 def inner(Z):
     res = BDD.false(fsm.bddEnc.DDmanager)
     for f in fsm.fairness_constraints:
         nf = ~f  # & fsm.bddEnc.statesMask
         res = res | fsm.pre_strat(
             fp(lambda Y: (Z | nf) & fsm.pre_strat(Y, agents), BDD.true(fsm.bddEnc.DDmanager)), agents
         )
     return res
Example #39
0
 def inner(Z):
     res = BDD.false(fsm.bddEnc.DDmanager)
     for f in fsm.fairness_constraints:
         nf = ~f & fsm.bddEnc.statesMask & strat
         res = res | fsm.pre_strat_si(
             fp(lambda Y: (Z | nf) & fsm.pre_strat_si(Y, agents, strat),
                BDD.true(fsm.bddEnc.DDmanager)), agents, strat)
     return res
Example #40
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))
Example #41
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))
 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 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
Example #44
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))))))
Example #46
0
def eval_strat(fsm, spec):
    """
    Return the BDD representing the set of states of fsm satisfying spec.
    spec is a strategic operator <G> pi.
    
    fsm -- a MAS representing the system;
    spec -- an AST-based ATLK specification with a top strategic operator.
    
    """
    if type(spec) is CAX:
        # [g] X p = ~<g> X ~p
        newspec = CEX(spec.group, Not(spec.child))
        return ~eval_strat(fsm, newspec)
        
    elif type(spec) is CAG:
        # [g] G p = ~<g> F ~p
        newspec = CEF(spec.group, Not(spec.child))
        return ~eval_strat(fsm, newspec)
        
    elif type(spec) is CAU:
        # [g][p U q] = ~<g>[ ~q W ~p & ~q ]
        newspec = CEW(spec.group,
                      Not(spec.right),
                      And(Not(spec.left), Not(spec.right)))
        return ~eval_strat(fsm, newspec)
        
    elif type(spec) is CAF:
        # [g] F p = ~<g> G ~p
        newspec = CEG(spec.group, Not(spec.child))
        return ~eval_strat(fsm, newspec)
        
    elif type(spec) is CAW:
        # [g][p W q] = ~<g>[~q U ~p & ~q]
        newspec = CEU(spec.group,
                      Not(spec.right),
                      And(Not(spec.left), Not(spec.right)))
        return ~eval_strat(fsm, newspec)
    
    sat = BDD.false(fsm.bddEnc.DDmanager)
    agents = {atom.value for atom in spec.group}
    
    return split_eval(fsm, spec, BDD.false(fsm.bddEnc.DDmanager),
                      fsm.protocol(agents) & fsm.reachable_states)
Example #47
0
def ceu(fsm, agents, phi, psi):
    """
    Return the set of states of fsm satisfying <agents>[phi U psi].
    
    fsm -- a MAS representing the system
    agents -- a list of agents names
    phi -- a BDD representing the set of states of fsm satisfying phi
    psi -- a BDD representing the set of states of fsm satisfying psi
    """
    return fp(lambda Y: psi | (phi & fsm.pre_strat(Y, agents)), BDD.false(fsm.bddEnc.DDmanager))
Example #48
0
def eu(fsm, phi, psi):
    """
    Return the set of states of fsm satisfying E[ phi U psi ].
    
    fsm -- a MAS representing the system
    phi -- a BDD representing the set of states of fsm satisfying phi
    psi -- a BDD representing the set of states of fsm satisfying psi
    """
    return fp(lambda Z: (psi | (phi & fsm.pre(Z))),
              BDD.false(fsm.bddEnc.DDmanager))
Example #49
0
def eu(fsm, phi, psi):
    """
    Return the set of states of fsm satisfying E[ phi U psi ].
    
    fsm -- a MAS representing the system
    phi -- a BDD representing the set of states of fsm satisfying phi
    psi -- a BDD representing the set of states of fsm satisfying psi
    """
    return fp(lambda Z: (psi | (phi & fsm.pre(Z))),
               BDD.false(fsm.bddEnc.DDmanager))
Example #50
0
def explain_ceu(fsm, state, agents, phi, psi, states=None):
    """
    Explain why state of fsm satisfies <agents> phi U psi.
    
    fsm -- the fsm;
    state -- a state of fsm satisfying <agents> phi U psi;
    agents -- the agents of the specification;
    phi -- the set of states of fsm satifying phi;
    psi -- the set of states of fsm satifying psi;
    states -- a dictionary of state->explanation pairs.
    """
    # <agents> phi U psi = mu Y. psi | (phi & fsm.pre_strat(Y, agents))
    
    # To show that state satisfies <agents> phi U psi
    #   if state in psi, return Explanation(state) because state is its own
    #   explanation
    #   otherwise, compute the fixpoint, until state is in the last set
    #   then choose one action always leading to states of the previous set
    #   (it is possible because state is added because it can go one step in
    #   the right direction), and recursively explain why the found states
    #   satisfy <agents> phi U psi.
    
    # states is used to store already explained states and create a directed
    # acyclic graph instead of the pure execution tree, to avoid a blow up
    # in terms of number of states.
    
    if states is None:
        states = {}
    
    if state in states:
        return states[state]
    
    if state <= psi:
        new = Explanation(state)
        states[state] = new
        return new
        
    else:
        f = lambda Y : psi | (phi & fsm.pre_strat(Y, agents))
        old = BDD.false(fsm.bddEnc.DDmanager)
        new = psi
        while not state <= new:
            old = new
            new = f(old)
        
        expl = explain_cex(fsm, state, agents, old)
        
        successors = set()
        for action, succ in expl.successors:
            successors.add((action,
                            explain_ceu(fsm, succ.state, agents,
                                        phi, psi, states)))
        new = Explanation(state, successors)
        states[state] = new
        return new
Example #51
0
 def test_true_false_equalities(self):
     (fsm, enc, manager) = self.init_model()
     
     true = BDD.true(manager)
     false = BDD.false(manager)
     
     self.assertTrue(false != true)        
     self.assertFalse(false == true)
     self.assertTrue(false == false)
     self.assertTrue(true == true)
     self.assertTrue((false != true) == (not false == true))
Example #52
0
 def inner(Z):
     res = phi
     for f in fsm.fairness_constraints:
         res = res & fsm.pre_nstrat(
             fp(
                 lambda Y: (psi & fair_gamma_states(fsm, agents)) | (Z & f) | (phi & fsm.pre_nstrat(Y, agents)),
                 BDD.false(fsm.bddEnc.DDmanager),
             ),
             agents,
         )
     return (psi & fair_gamma_states(fsm, agents)) | res
Example #53
0
 def test_true_false_xor(self):
     (fsm, enc, manager) = self.init_model()
     
     true = BDD.true(manager)
     false = BDD.false(manager)
     init = fsm.init
     
     self.assertTrue(true ^ false == true)
     self.assertTrue(true ^ true == false)
     self.assertTrue(false ^ false == false)
     self.assertTrue(init ^ true == ~init)
     self.assertTrue(init ^ false == init)
Example #54
0
 def test_true_false_not(self):
     (fsm, enc, manager) = self.init_model()
     
     true = BDD.true(manager)
     false = BDD.false(manager)
     init = fsm.init
     
     self.assertTrue(~true == -true)
     self.assertTrue(~false == -false)
     self.assertTrue(~true == false)
     self.assertTrue(~false == true)
     self.assertTrue(false < ~init < true)
Example #55
0
 def test_true_false_or(self):
     (fsm, enc, manager) = self.init_model()
     
     true = BDD.true(manager)
     false = BDD.false(manager)
     init = fsm.init        
     
     self.assertTrue((true | false) == (true + false))
     self.assertTrue(true | false == true)
     self.assertTrue(true | true == true)
     self.assertTrue(false | false == false)
     self.assertTrue(init | true == true)
     self.assertTrue(init | false == init)
Example #56
0
 def test_true_false_and(self):
     (fsm, enc, manager) = self.init_model()
     
     true = BDD.true(manager)
     false = BDD.false(manager)
     init = fsm.init
     
     self.assertTrue((true & false) == (true * false))
     self.assertTrue(true & false == false)
     self.assertTrue(true & true == true)
     self.assertTrue(false & false == false)
     self.assertTrue(init & true == init)
     self.assertTrue(init & false == false)
Example #57
0
 def test_pick_states_inputs(self):
     fsm = self.model()
     
     false = BDD.false(fsm.bddEnc.DDmanager)
     true = BDD.true(fsm.bddEnc.DDmanager)
     p = evalSexp(fsm, "p")
     q = evalSexp(fsm, "q")
     a = evalSexp(fsm, "a")
     
     pstates = fsm.pick_all_states_inputs(p & a)
     self.assertEqual(len(pstates), 2)
     for pstate in pstates:
         self.assertTrue(false < pstate < p)
Example #58
0
 def test_fairness(self):
     fsm = BddFsm.from_filename("tests/pynusmv/models/counters-fair.smv")
     self.assertIsNotNone(fsm)
     
     false = BDD.false(fsm.bddEnc.DDmanager)
     true = BDD.true(fsm.bddEnc.DDmanager)
     rc1 = evalSexp(fsm, "run = rc1")
     rc2 = evalSexp(fsm, "run = rc2")
     
     fairBdds = fsm.fairness_constraints
     self.assertEqual(len(fairBdds), 2)
     for fair in fairBdds:
         self.assertTrue(fair == rc1 or fair == rc2)