def test_change_trans_of_flat(self): glob.load(*self.counters()) glob.flatten_hierarchy() flat = glob.flat_hierarchy() self.assertIsNotNone(flat) trans = flat.trans choose_run = node.Expression.from_string("run = rc1") flat.trans = flat.trans & choose_run glob.compute_model() fsm = glob.prop_database().master.bddFsm self.assertEqual(fsm.count_states(fsm.reachable_states), 3)
def test_access_flat_hierarchy(self): glob.load(*self.counters()) glob.compute_model() flat = glob.flat_hierarchy() symb_table = glob.symb_table() self.assertIsNotNone(flat.init) self.assertIsNotNone(flat.trans) self.assertIsNone(flat.invar) self.assertIsNone(flat.justice) self.assertIsNone(flat.compassion) variables = flat.variables for variable in variables: var_type = symb_table.get_variable_type(variable) self.assertEqual(nssymb_table.SymbType_get_tag(var_type), nssymb_table.SYMB_TYPE_ENUM)
def jump_relation(mas): """ Return the transition relation corresponding to the "jump" relation of the given MAS. mas -- a multi-agents system. The returned value is a model-based relation encoding the fact that all original state variables of the given MAS stay the same, and other encoded variables are free to change. """ # Get the original state variables flat = glob.flat_hierarchy() symb_table = mas.bddEnc.symbTable original_variables = [ variable for variable in flat.variables if symb_table.is_state_var(variable) ] # Build the relation expression return reduce(operator.and_, (variable.next() == variable for variable in original_variables))
def encode_strategies(mas, agents, formula, filtered): """ Encode the strategies for agents, to check formula, given the filtered moves. mas -- a multi-agents system; agents -- a subset of agents of mas; formula -- an ATLK_irF strategic formula where the group is agents; filtered -- either the complete protocol of the agents, or the filtered moves for agents, for the given formula. The result is the presence, in mas.transitions[formula], of three relations under the "jump", "equiv", and "follow" keys, to perform the model checking: * the "jump" relation encode the fact that the original state stays the same and all strategies can change; * the "equiv" relation encode the fact that the states are equivalent for some agent in the group of formula, and the strategies of these agents are kept the same; * the "follow" relation encode the original transition relation with each agent of the group of formula following his strategy encoded in the current state (and that these strategies are kept the same). Note: mas.encoded is populated with intermediate cached information: * mas.encoded[(agent, filtered)] gives two (model-based) relations: + the relation encoding the fact that the encoded strategies of agent from filtered are kept the same; + the relation encoding the fact that the encoded strategies of agent are followed; they only depends on the agent and the filtered moves, thus if two sub-formulas have the same filtered moves (e.g., pre-filtering is not used), the relations are the same; * mas.encoded[agent] gives the relation encoding the equivalence for agent; it only depends on agent, since it only depends on what he observes; THIS RELATION DOES NOT ENCODE THE FACT THAT THE STRATEGIES DO NOT CHANGE; * mas.encoded["jump"] gives the relation encoding the fact that the state is the same but the strategies can change; it only depends on the MAS, since all strategies are free and only the state is kept identical. """ if not hasattr(mas, "transitions"): mas.transitions = {} if not hasattr(mas, "encoded"): mas.encoded = {} # if mas.encoded["jump"] does not exist, # encode it, based on the original state variables of the model if "jump" not in mas.encoded: jump = jump_relation(mas) mas.encoded["jump"] = jump # Encode each agent variables and relations if needed # for each agent in agents, # if (agent, filtered) is not in mas.encoded, # compute them for agent in agents: if (agent, filtered) not in mas.encoded: relations = strategy_relations(mas, agents, agent, filtered) mas.encoded[(agent, filtered)] = relations # for each agent in agents, # if mas.encoded[agent] is not present, # compute it for agent in agents: if agent not in mas.encoded: relation = equivalence_relation(mas, agent) mas.encoded[agent] = relation # Encode the transition relations if formula not in mas.transitions: mas.transitions[formula] = {} # the "jump" relation is just mas.encoded["jump"] if "jump" not in mas.transitions[formula]: jump = mas.encoded["jump"] trans = BddTrans.from_string(mas.bddEnc.symbTable, str(jump)) mas.transitions[formula]["jump"] = trans # the "equiv" relation is based on # * the "equiv" relations of each agent in agents # (disjunction, for group knowledge) # * the strategies of the agents are the same # (based on the variables of each agent, stored in # mas.encoded[(agent, filtered)]) if "equiv" not in mas.transitions[formula]: equiv = reduce(operator.or_, (mas.encoded[agent] for agent in agents), model.Falseexp()) equiv = reduce(operator.and_, (mas.encoded[(agent, filtered)][0] for agent in agents), equiv) trans = BddTrans.from_string(mas.bddEnc.symbTable, str(equiv)) mas.transitions[formula]["equiv"] = trans # the "follow" relation is based on # * the original transition relation of the MAS; # * the fact that the strategies of the agents are the same, # and that the strategies for agents are followed by these agents, # given by the variables in mas.encoded[(agent, filtered)] if "follow" not in mas.transitions[formula]: flat = glob.flat_hierarchy() follow = reduce(operator.and_, (mas.encoded[(agent, filtered)][0] & mas.encoded[(agent, filtered)][1] for agent in agents), flat.trans) trans = BddTrans.from_string(mas.bddEnc.symbTable, str(follow)) mas.transitions[formula]["follow"] = trans
def test_get_flat_hierarchy(self): with self.assertRaises(NuSMVNeedFlatHierarchyError): flat = glob.flat_hierarchy() glob.load_from_file("tests/pynusmv/models/counters.smv") glob.compute_model() flat = glob.flat_hierarchy()