from sys import exit from colour import * from rs.context_automaton import ContextAutomaton class ExtendedContextAutomaton(ContextAutomaton): """Extended Context Automaton Supports transitions with actions. Each transitions is additionally guarded with reactants and inhibitors. The provided context entities are the products of the reactions labelling the transition taken. """ def __init__(self, reaction_system): super(ExtendedContextAutomaton, self).__init__(reaction_system) self._actions = [] self._transitions_for_products = dict() self._actions_for_products = dict() @property def number_of_actions(self): return len(self._actions) @property def actions(self): return self._actions def has_action(self, action): """Checks if the automaton supports a given action""" return action in self._actions def get_transitions_producing_entity(self, entity): """Returns the transitions that produce a given entity""" if entity in self._transitions_for_products: return self._transitions_for_products[entity] else: return [] def get_actions_producing_entity(self, entity): """Returns the actions that produce a given entity""" if entity in self._actions_for_products: return self._actions_for_products[entity] else: return set() def can_produce_entity(self, entity): """Check if the automaton can produce an entity""" if entity in self._actions_for_products: return True else: return False def add_transition(self, src, actions, ctx_reaction, dst): """Adds a transition src: is the source state name dst: is the destination state name actions: is the set of actions with which the transitions is synchronised ctx_reaction: is the context reaction associated with the transition """ ctx_reactants, ctx_inhibitors, ctx_products = ctx_reaction if not isinstance(ctx_products, (set, list)): print("Contexts set (context products) must be of type set or list") if not self.is_valid_rs_set(ctx_reactants): raise RuntimeError( "one of the entities in the reactants set is unknown (undefined)!" ) if not self.is_valid_rs_set(ctx_inhibitors): raise RuntimeError( "one of the entities in the inhibitors set is unknown (undefined)!" ) if not self.is_valid_rs_set(ctx_products): raise RuntimeError( "one of the entities in the context set is unknown (undefined)!" ) if not self.is_state(src): raise RuntimeError('"' + src + '" is an unknown (undefined) state') if not self.is_state(dst): raise RuntimeError('"' + dst + '" is an unknown (undefined) state') src_id = self.get_state_id(src) dst_id = self.get_state_id(dst) act_ids = self.get_set_of_action_ids(actions) r_ids = self.get_set_of_ids(ctx_reactants) i_ids = self.get_set_of_ids(ctx_inhibitors) p_ids = self.get_set_of_ids(ctx_products) new_transition = (src_id, act_ids, (r_ids, i_ids, p_ids), dst_id) for product_id in p_ids: self._transitions_for_products.setdefault(product_id, []) self._transitions_for_products[product_id].append(new_transition) self._actions_for_products.setdefault(product_id, set()) self._actions_for_products[product_id] |= set(actions) self._prod_entities |= p_ids self._transitions.append(new_transition) def show_transitions(self): """Prints the set of registered transitions""" print(C_MARK_INFO + " Context automaton transitions:") for src_id, act_id, reaction, dst_id in self._transitions: str_transition = self.get_state_name(src_id) + " --( " str_transition += "<" + self.get_actions_str(act_id) + "> | " str_transition += ( "( " + self.rsset2str(reaction[0]) + "," + self.rsset2str(reaction[1]) + "," + self.rsset2str(reaction[2]) + " )" ) str_transition += " )--> " + self.get_state_name(dst_id) print(" - " + str_transition) def add_action(self, action_name): """Registers an action""" if action_name not in self._actions: self._actions.append(action_name) else: print("'%s' already added. skipping..." % (action_name,)) def get_action_id(self, action_name): """For an action name returns its id""" try: return self._actions.index(action_name) except ValueError: print_error("Undefined context automaton action: " + repr(action_name)) exit(1) def get_action_name(self, action_id): return self._actions[action_id] def get_set_of_action_ids(self, actions): """Converts a set of actions into the set of their ids""" act_ids = set() for act in actions: act_ids.add(self.get_action_id(act)) return act_ids def get_actions_str(self, actions): """Returns the string for the set of action ids given by actions""" s = "" for act in actions: s += self.get_action_name(act) + ", " s = s[:-2] return s def show_actions(self): """Prints all the actions""" print(C_MARK_INFO + " Context automaton actions:") for act in self._actions: print(" - " + act + " (id=" + str(self.get_action_id(act)) + ")") def show(self): super(ExtendedContextAutomaton, self).show() self.show_actions() # EOF