getters for the used actions, automata supporting actions, transitions for actions, etc.
This commit is contained in:
@@ -9,6 +9,7 @@ class ContextAutomaton(object):
|
|||||||
self._init_state = None
|
self._init_state = None
|
||||||
self._reaction_system = reaction_system
|
self._reaction_system = reaction_system
|
||||||
self._name = ""
|
self._name = ""
|
||||||
|
self._prod_entities = set()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def states(self):
|
def states(self):
|
||||||
@@ -18,6 +19,14 @@ class ContextAutomaton(object):
|
|||||||
def transitions(self):
|
def transitions(self):
|
||||||
return self._transitions
|
return self._transitions
|
||||||
|
|
||||||
|
@property
|
||||||
|
def prod_entities(self):
|
||||||
|
return self._prod_entities
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reaction_system(self):
|
||||||
|
return self._reaction_system
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self._name
|
return self._name
|
||||||
@@ -102,6 +111,8 @@ class ContextAutomaton(object):
|
|||||||
for e in set(context_set):
|
for e in set(context_set):
|
||||||
new_context_set.add(self._reaction_system.get_entity_id(e))
|
new_context_set.add(self._reaction_system.get_entity_id(e))
|
||||||
|
|
||||||
|
self._prod_entities |= new_context_set
|
||||||
|
|
||||||
self._transitions.append((self.get_state_id(src),new_context_set,self.get_state_id(dst)))
|
self._transitions.append((self.get_state_id(src),new_context_set,self.get_state_id(dst)))
|
||||||
|
|
||||||
def rsset2str(self, elements):
|
def rsset2str(self, elements):
|
||||||
@@ -140,8 +151,14 @@ class ContextAutomaton(object):
|
|||||||
name_string = ": " + colour_str(C_BOLD, self.name)
|
name_string = ": " + colour_str(C_BOLD, self.name)
|
||||||
print(C_MARK_INFO + " Context automaton" + name_string)
|
print(C_MARK_INFO + " Context automaton" + name_string)
|
||||||
|
|
||||||
|
def show_prod_entities(self):
|
||||||
|
print(C_MARK_INFO + " Context automaton possible products:")
|
||||||
|
for entity in self._prod_entities:
|
||||||
|
print(" - " + self._reaction_system.get_entity_name(entity))
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
self.show_header()
|
self.show_header()
|
||||||
self.show_states()
|
self.show_states()
|
||||||
self.show_transitions()
|
self.show_transitions()
|
||||||
|
self.show_prod_entities()
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,52 @@ from colour import *
|
|||||||
from rs.context_automaton import ContextAutomaton
|
from rs.context_automaton import ContextAutomaton
|
||||||
|
|
||||||
class ExtendedContextAutomaton(ContextAutomaton):
|
class ExtendedContextAutomaton(ContextAutomaton):
|
||||||
"""Extended Context Automaton"""
|
"""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):
|
def __init__(self, reaction_system):
|
||||||
self._actions = []
|
|
||||||
super(ExtendedContextAutomaton, self).__init__(reaction_system)
|
super(ExtendedContextAutomaton, self).__init__(reaction_system)
|
||||||
|
self._actions = []
|
||||||
|
self._transitions_for_products = dict()
|
||||||
|
self._actions_for_products = dict()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def number_of_actions(self):
|
def number_of_actions(self):
|
||||||
return len(self._actions)
|
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 add_transition(self, src, actions, ctx_reaction, dst):
|
def add_transition(self, src, actions, ctx_reaction, dst):
|
||||||
"""Adds a transition
|
"""Adds a transition
|
||||||
|
|
||||||
@@ -49,10 +86,21 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
i_ids = self.get_set_of_ids(ctx_inhibitors)
|
i_ids = self.get_set_of_ids(ctx_inhibitors)
|
||||||
p_ids = self.get_set_of_ids(ctx_products)
|
p_ids = self.get_set_of_ids(ctx_products)
|
||||||
|
|
||||||
self._transitions.append((src_id, act_ids, (r_ids, i_ids, p_ids), dst_id))
|
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):
|
def show_transitions(self):
|
||||||
"""Prints the set of registered transitions"""
|
"""Prints the set of registered transitions"""
|
||||||
|
|
||||||
print(C_MARK_INFO + " Context automaton transitions:")
|
print(C_MARK_INFO + " Context automaton transitions:")
|
||||||
for src_id, act_id, reaction, dst_id in self._transitions:
|
for src_id, act_id, reaction, dst_id in self._transitions:
|
||||||
str_transition = self.get_state_name(src_id) + " --( "
|
str_transition = self.get_state_name(src_id) + " --( "
|
||||||
@@ -63,6 +111,7 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
|
|
||||||
def add_action(self, action_name):
|
def add_action(self, action_name):
|
||||||
"""Registers an action"""
|
"""Registers an action"""
|
||||||
|
|
||||||
if action_name not in self._actions:
|
if action_name not in self._actions:
|
||||||
self._actions.append(action_name)
|
self._actions.append(action_name)
|
||||||
else:
|
else:
|
||||||
@@ -70,6 +119,7 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
|
|
||||||
def get_action_id(self, action_name):
|
def get_action_id(self, action_name):
|
||||||
"""For an action name returns its id"""
|
"""For an action name returns its id"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self._actions.index(action_name)
|
return self._actions.index(action_name)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -81,6 +131,7 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
|
|
||||||
def get_set_of_action_ids(self, actions):
|
def get_set_of_action_ids(self, actions):
|
||||||
"""Converts a set of actions into the set of their ids"""
|
"""Converts a set of actions into the set of their ids"""
|
||||||
|
|
||||||
act_ids = set()
|
act_ids = set()
|
||||||
for act in actions:
|
for act in actions:
|
||||||
act_ids.add(self.get_action_id(act))
|
act_ids.add(self.get_action_id(act))
|
||||||
@@ -88,6 +139,7 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
|
|
||||||
def get_actions_str(self, actions):
|
def get_actions_str(self, actions):
|
||||||
"""Returns the string for the set of action ids given by actions"""
|
"""Returns the string for the set of action ids given by actions"""
|
||||||
|
|
||||||
s = ""
|
s = ""
|
||||||
for act in actions:
|
for act in actions:
|
||||||
s += self.get_action_name(act) + ", "
|
s += self.get_action_name(act) + ", "
|
||||||
@@ -96,6 +148,7 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
|
|
||||||
def show_actions(self):
|
def show_actions(self):
|
||||||
"""Prints all the actions"""
|
"""Prints all the actions"""
|
||||||
|
|
||||||
print(C_MARK_INFO + " Context automaton actions:")
|
print(C_MARK_INFO + " Context automaton actions:")
|
||||||
for act in self._actions:
|
for act in self._actions:
|
||||||
print(" - " + act + " (id=" + str(self.get_action_id(act)) + ")")
|
print(" - " + act + " (id=" + str(self.get_action_id(act)) + ")")
|
||||||
@@ -103,3 +156,4 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
def show(self):
|
def show(self):
|
||||||
super(ExtendedContextAutomaton, self).show()
|
super(ExtendedContextAutomaton, self).show()
|
||||||
self.show_actions()
|
self.show_actions()
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,100 @@
|
|||||||
from sys import exit
|
from sys import exit
|
||||||
|
from colour import *
|
||||||
|
|
||||||
class NetworkOfContextAutomata(object):
|
class NetworkOfContextAutomata(object):
|
||||||
|
|
||||||
def __init__(self, context_automata):
|
def __init__(self, reaction_system, context_automata):
|
||||||
self.automata = list(context_automata)
|
self.automata = []
|
||||||
|
self._reaction_system = reaction_system
|
||||||
|
self._actions = set()
|
||||||
|
self._prod_entities = set()
|
||||||
|
self._automata_for_actions = dict()
|
||||||
|
self._actions_for_products = dict()
|
||||||
|
|
||||||
|
if len(context_automata) < 1:
|
||||||
|
print("Context automata network must contain at least one automaton!")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
for automaton in context_automata:
|
||||||
|
self.add(automaton)
|
||||||
|
|
||||||
|
self.sanity_check()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def number_of_automata(self):
|
def number_of_automata(self):
|
||||||
return len(self.automata)
|
return len(self.automata)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reaction_system(self):
|
||||||
|
return self._reaction_system
|
||||||
|
|
||||||
|
@property
|
||||||
|
def prod_entities(self):
|
||||||
|
"""Returns the set of entities that can potentially be produced by the automata in the network"""
|
||||||
|
return self._prod_entities
|
||||||
|
|
||||||
|
def sanity_check(self):
|
||||||
|
"""Performs a sanity check of the network of automata"""
|
||||||
|
|
||||||
|
for automaton in self.automata:
|
||||||
|
if automaton.reaction_system != self._reaction_system:
|
||||||
|
print_error("Mismatching reaction system used in \"" + str(automaton.name) + "\"!!!")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def show_prod_entities(self):
|
||||||
|
print(C_MARK_INFO + " Possible context-products for the network of automata:")
|
||||||
|
for entity in self.prod_entities:
|
||||||
|
print(" - " + self._reaction_system.get_entity_name(entity))
|
||||||
|
|
||||||
|
def show_actions(self):
|
||||||
|
print(C_MARK_INFO + " Actions of the network:")
|
||||||
|
for action in self._actions:
|
||||||
|
print(" - " + action)
|
||||||
|
|
||||||
|
def register_action(self, action, aut):
|
||||||
|
"""Associates an action with an automaton"""
|
||||||
|
|
||||||
|
self._automata_for_actions.setdefault(action, set())
|
||||||
|
aut_index = self.automata.index(aut)
|
||||||
|
self._automata_for_actions[action].add(aut_index)
|
||||||
|
|
||||||
|
def get_actions_producing_entity(self, entity):
|
||||||
|
"""Returns the set of actions producing an entity"""
|
||||||
|
|
||||||
|
if entity in self._actions_for_products:
|
||||||
|
return self._actions_for_products[entity]
|
||||||
|
else:
|
||||||
|
return set()
|
||||||
|
|
||||||
|
def get_automata_with_action(self, action):
|
||||||
|
"""Returns the set of automata that support an action"""
|
||||||
|
|
||||||
|
if action in self._automata_for_actions:
|
||||||
|
return self._automata_for_actions[action]
|
||||||
|
else:
|
||||||
|
return set()
|
||||||
|
|
||||||
|
def add(self, aut):
|
||||||
|
"""Adds an automaton to the network"""
|
||||||
|
|
||||||
|
self.automata.append(aut)
|
||||||
|
self._prod_entities |= aut.prod_entities
|
||||||
|
self._actions |= set(aut.actions)
|
||||||
|
|
||||||
|
for action in aut.actions:
|
||||||
|
self.register_action(action, aut)
|
||||||
|
|
||||||
|
for entity in aut.prod_entities:
|
||||||
|
self._actions_for_products.setdefault(entity, set())
|
||||||
|
self._actions_for_products[entity] |= aut.get_actions_producing_entity(entity)
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
|
print()
|
||||||
|
print(C_MARK_INFO + " NETWORK OF CONTEXT AUTOMATA")
|
||||||
for ca in self.automata:
|
for ca in self.automata:
|
||||||
print()
|
print()
|
||||||
ca.show()
|
ca.show()
|
||||||
|
print()
|
||||||
|
self.show_prod_entities()
|
||||||
|
self.show_actions()
|
||||||
|
|
||||||
def add(self, aut):
|
|
||||||
self.automata.append(aut)
|
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ class ReactionSystem(object):
|
|||||||
self.init_contexts = []
|
self.init_contexts = []
|
||||||
self.context_entities = []
|
self.context_entities = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def background_set_size(self):
|
||||||
|
return len(self.background_set)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def set_of_bgset_ids(self):
|
||||||
|
return set(range(self.background_set_size))
|
||||||
|
|
||||||
def assume_not_in_bgset(self, name):
|
def assume_not_in_bgset(self, name):
|
||||||
if self.is_in_background_set(name):
|
if self.is_in_background_set(name):
|
||||||
raise RuntimeError("The entity " + name + " is already on the list")
|
raise RuntimeError("The entity " + name + " is already on the list")
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ def test_extended_automaton():
|
|||||||
r = ReactionSystem()
|
r = ReactionSystem()
|
||||||
r.add_bg_set_entity("inc")
|
r.add_bg_set_entity("inc")
|
||||||
r.add_bg_set_entity("dec")
|
r.add_bg_set_entity("dec")
|
||||||
|
r.add_bg_set_entity("decx")
|
||||||
|
|
||||||
|
|
||||||
c1 = ExtendedContextAutomaton(r)
|
c1 = ExtendedContextAutomaton(r)
|
||||||
c1.add_init_state("init")
|
c1.add_init_state("init")
|
||||||
@@ -19,19 +21,44 @@ def test_extended_automaton():
|
|||||||
c1.add_state("working")
|
c1.add_state("working")
|
||||||
c1.add_action("act1")
|
c1.add_action("act1")
|
||||||
c1.add_action("act2")
|
c1.add_action("act2")
|
||||||
c1.add_transition("init", ["act1", "act2"], ([],[],["inc"]), "working")
|
c1.add_transition("init", ["act1", "act2"], ([],[],["inc","dec"]), "working")
|
||||||
c1.add_transition("working", ["act2"], ([],[],["inc"]), "working")
|
c1.add_transition("working", ["act2"], ([],[],["inc"]), "working")
|
||||||
|
|
||||||
c2 = ExtendedContextAutomaton(r)
|
c2 = ExtendedContextAutomaton(r)
|
||||||
c2.add_init_state("init")
|
c2.add_init_state("init")
|
||||||
c2.name = "cxxxx"
|
c2.name = "c2"
|
||||||
c2.add_state("working")
|
c2.add_state("working")
|
||||||
c2.add_action("act1")
|
c2.add_action("act1")
|
||||||
c2.add_action("act2")
|
c2.add_action("act2")
|
||||||
c2.add_transition("init", ["act1", "act2"], ([],[],["inc"]), "working")
|
c2.add_transition("init", ["act1", "act2"], ([],[],["inc"]), "working")
|
||||||
c2.add_transition("working", ["act2"], ([],[],["inc"]), "working")
|
c2.add_transition("working", ["act2"], ([],[],["inc"]), "working")
|
||||||
|
|
||||||
na = NetworkOfContextAutomata([c1,c2])
|
c3 = ExtendedContextAutomaton(r)
|
||||||
|
c3.add_init_state("init")
|
||||||
|
c3.name = "c3"
|
||||||
|
c3.add_state("working")
|
||||||
|
c3.add_action("act1")
|
||||||
|
c3.add_transition("init", ["act1"], ([],[],["inc"]), "working")
|
||||||
|
#
|
||||||
|
# c4 = ExtendedContextAutomaton(r)
|
||||||
|
# c4.add_init_state("init")
|
||||||
|
# c4.name = "c4"
|
||||||
|
# c4.add_state("working")
|
||||||
|
# c4.add_action("act1")
|
||||||
|
# c4.add_action("act42")
|
||||||
|
# c4.add_transition("init", ["act1", "act42"], ([],[],["inc"]), "working")
|
||||||
|
# c4.add_transition("working", ["act42"], ([],[],["inc"]), "working")
|
||||||
|
#
|
||||||
|
# c5 = ExtendedContextAutomaton(r)
|
||||||
|
# c5.add_init_state("init")
|
||||||
|
# c5.name = "c5"
|
||||||
|
# c5.add_state("working")
|
||||||
|
# c5.add_action("act1")
|
||||||
|
# c5.add_action("act2")
|
||||||
|
# c5.add_transition("init", ["act1", "act2"], ([],[],["inc"]), "working")
|
||||||
|
# c5.add_transition("working", ["act2"], ([],[],["inc"]), "working")
|
||||||
|
|
||||||
|
na = NetworkOfContextAutomata(r, [c1,c2,c3])
|
||||||
|
|
||||||
rna = ReactionSystemWithNetworkOfAutomata(r,na)
|
rna = ReactionSystemWithNetworkOfAutomata(r,na)
|
||||||
|
|
||||||
|
|||||||
4
rssmt.py
4
rssmt.py
@@ -24,8 +24,8 @@ version = "2016/12/28/00"
|
|||||||
rsmc_banner = """
|
rsmc_banner = """
|
||||||
Reaction Systems SMT-Based Model Checking
|
Reaction Systems SMT-Based Model Checking
|
||||||
|
|
||||||
Version: """ + version + """
|
Version: """ + version + """
|
||||||
Author: Artur Męski <meski@ipipan.waw.pl> / <artur.meski@ncl.ac.uk>
|
Author: Artur Męski <meski@ipipan.waw.pl> / <artur.meski@ncl.ac.uk>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
##################################################################
|
##################################################################
|
||||||
|
|||||||
@@ -60,44 +60,25 @@ class SmtCheckerRSNA(SmtCheckerRS):
|
|||||||
def enc_transition_relation(self, level):
|
def enc_transition_relation(self, level):
|
||||||
return simplify(And(self.enc_rs_trans(level), self.enc_automaton_trans(level)))
|
return simplify(And(self.enc_rs_trans(level), self.enc_automaton_trans(level)))
|
||||||
|
|
||||||
def enc_automaton_single_trans(self, level, transition):
|
|
||||||
|
|
||||||
src,actions,ctx_reaction,dst = transition
|
|
||||||
|
|
||||||
src_enc = self.ca_state[level] == src
|
|
||||||
dst_enc = self.ca_state[level+1] == dst
|
|
||||||
|
|
||||||
all_ent = set(range(len(self.rs.background_set)))
|
|
||||||
incl_ctx = ctx
|
|
||||||
excl_ctx = all_ent - incl_ctx
|
|
||||||
|
|
||||||
ctx_enc = True
|
|
||||||
|
|
||||||
for c in incl_ctx:
|
|
||||||
ctx_enc = simplify(And(ctx_enc, self.v_ctx[level][c]))
|
|
||||||
for c in excl_ctx:
|
|
||||||
ctx_enc = simplify(And(ctx_enc, Not(self.v_ctx[level][c])))
|
|
||||||
|
|
||||||
enc_single_trans = simplify(And(src_enc, ctx_enc, dst_enc))
|
|
||||||
|
|
||||||
return enc_single_trans
|
|
||||||
|
|
||||||
def enc_single_automaton_trans(self, level, automaton):
|
|
||||||
|
|
||||||
enc_aut_trans = False
|
|
||||||
for transition in automaton.transitions:
|
|
||||||
enc_aut_trans = simplify(Or(enc_aut_trans, self.enc_automaton_single_trans(level, transition)))
|
|
||||||
|
|
||||||
return enc_aut_trans
|
|
||||||
|
|
||||||
def enc_automaton_trans(self, level):
|
def enc_automaton_trans(self, level):
|
||||||
"""Encodes the transition relation for the context automaton"""
|
"""Encodes the transition relation for the context automaton"""
|
||||||
|
|
||||||
enc_canet = True
|
enc_trans = True
|
||||||
for aut in self.canet:
|
|
||||||
enc_canet = simplify(And(enc_canet, self.enc_single_automaton_trans(level, aut)))
|
|
||||||
|
|
||||||
return enc_canet
|
prod_context = self.canet.prod_entities
|
||||||
|
never_produced_context = self.rs.set_of_bgset_ids - prod_context
|
||||||
|
|
||||||
|
# producible entities:
|
||||||
|
for ent in prod_context:
|
||||||
|
actions_producing_ent = self.canet.get_actions_producing_entity(ent)
|
||||||
|
for act in actions_producing_ent:
|
||||||
|
automata_with_act = self.canet.get_automata_with_action(act)
|
||||||
|
for aut_id in automata_with_act:
|
||||||
|
aut = self.canet.automata[aut_id]
|
||||||
|
|
||||||
|
# entities that are never produced:
|
||||||
|
|
||||||
|
return enc_trans
|
||||||
|
|
||||||
def check_reachability(self, state, print_witness=True, print_time=True, print_mem=True):
|
def check_reachability(self, state, print_witness=True, print_time=True, print_mem=True):
|
||||||
|
|
||||||
@@ -109,3 +90,5 @@ class SmtCheckerRSNA(SmtCheckerRS):
|
|||||||
self.prepare_all_variables()
|
self.prepare_all_variables()
|
||||||
self.prepare_all_variables()
|
self.prepare_all_variables()
|
||||||
|
|
||||||
|
print(self.enc_automaton_trans(0))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user