Code re-formatting

This commit is contained in:
Artur Meski
2019-02-23 14:41:36 +00:00
parent 59cbc00e7f
commit c3a19d81dc
21 changed files with 1333 additions and 1016 deletions

View File

@@ -10,18 +10,23 @@ C_UNDERLINE = '\033[4m'
C_MARK_INFO = C_BOLD + "[" + C_GREEN + "*" + C_ENDC + C_BOLD + "]" + C_ENDC C_MARK_INFO = C_BOLD + "[" + C_GREEN + "*" + C_ENDC + C_BOLD + "]" + C_ENDC
C_MARK_ERROR = C_BOLD + "[" + C_RED + "!" + C_ENDC + C_BOLD + "]" + C_ENDC C_MARK_ERROR = C_BOLD + "[" + C_RED + "!" + C_ENDC + C_BOLD + "]" + C_ENDC
def colour_str(col, s): def colour_str(col, s):
return col + s + C_ENDC return col + s + C_ENDC
def green_str(s): def green_str(s):
return C_GREEN + s + C_ENDC return C_GREEN + s + C_ENDC
def print_error(s): def print_error(s):
print(C_MARK_ERROR + " " + C_RED + s + C_ENDC) print(C_MARK_ERROR + " " + C_RED + s + C_ENDC)
def print_info(s): def print_info(s):
print("[" + colour_str(C_BOLD, "i") + "] {:s}".format(s)) print("[" + colour_str(C_BOLD, "i") + "] {:s}".format(s))
def print_positive(s): def print_positive(s):
print("[" + colour_str(C_BOLD, "+") + "] {:s}".format(s)) print("[" + colour_str(C_BOLD, "+") + "] {:s}".format(s))

View File

@@ -2,4 +2,4 @@ from logics.rsltl import Formula_rsLTL
from logics.bags import BagDescription from logics.bags import BagDescription
from logics.param_constr import ParamConstraint from logics.param_constr import ParamConstraint
from logics.rsltl_encoder import rsLTL_Encoder from logics.rsltl_encoder import rsLTL_Encoder
from logics.param_constr_encoder import ParamConstr_Encoder from logics.param_constr_encoder import ParamConstr_Encoder

View File

@@ -1,6 +1,7 @@
from enum import Enum from enum import Enum
ParamConstraint_oper = Enum( ParamConstraint_oper = Enum(
'ParamConstraint_oper', 'param_entity true l_and l_or l_not lt le eq ge gt') 'ParamConstraint_oper',
'param_entity true l_and l_or l_not lt le eq ge gt')
class ParamConstraint(object): class ParamConstraint(object):
@@ -49,7 +50,8 @@ class ParamConstraint(object):
@classmethod @classmethod
def f_param_ent(cls, param, entity_name): def f_param_ent(cls, param, entity_name):
return cls(ParamConstraint_oper.param_entity, param=param, entity=entity_name) return cls(ParamConstraint_oper.param_entity, param=param,
entity=entity_name)
@classmethod @classmethod
def f_TRUE(cls): def f_TRUE(cls):
@@ -64,25 +66,32 @@ class ParamConstraint(object):
return cls(ParamConstraint_oper.l_not, L_oper=arg) return cls(ParamConstraint_oper.l_not, L_oper=arg)
def __lt__(self, other): def __lt__(self, other):
return ParamConstraint(ParamConstraint_oper.lt, L_oper=self, R_oper=other) return ParamConstraint(
ParamConstraint_oper.lt, L_oper=self, R_oper=other)
def __le__(self, other): def __le__(self, other):
return ParamConstraint(ParamConstraint_oper.le, L_oper=self, R_oper=other) return ParamConstraint(
ParamConstraint_oper.le, L_oper=self, R_oper=other)
def __eq__(self, other): def __eq__(self, other):
return ParamConstraint(ParamConstraint_oper.eq, L_oper=self, R_oper=other) return ParamConstraint(
ParamConstraint_oper.eq, L_oper=self, R_oper=other)
def __ge__(self, other): def __ge__(self, other):
return ParamConstraint(ParamConstraint_oper.ge, L_oper=self, R_oper=other) return ParamConstraint(
ParamConstraint_oper.ge, L_oper=self, R_oper=other)
def __gt__(self, other): def __gt__(self, other):
return ParamConstraint(ParamConstraint_oper.gt, L_oper=self, R_oper=other) return ParamConstraint(
ParamConstraint_oper.gt, L_oper=self, R_oper=other)
def __and__(self, other): def __and__(self, other):
return ParamConstraint(ParamConstraint_oper.l_and, L_oper=self, R_oper=other) return ParamConstraint(
ParamConstraint_oper.l_and, L_oper=self, R_oper=other)
def __or__(self, other): def __or__(self, other):
return ParamConstraint(ParamConstraint_oper.l_or, L_oper=self, R_oper=other) return ParamConstraint(
ParamConstraint_oper.l_or, L_oper=self, R_oper=other)
def __invert__(self): def __invert__(self):
return ParamConstraint(ParamConstraint_oper.l_not, L_oper=self) return ParamConstraint(ParamConstraint_oper.l_not, L_oper=self)

View File

@@ -1,9 +1,10 @@
from logics.param_constr import * from logics.param_constr import *
from z3 import And, Not, Or from z3 import And, Not, Or
class ParamConstr_Encoder(object): class ParamConstr_Encoder(object):
"""Class for encoding parameter constraints""" """Class for encoding parameter constraints"""
def __init__(self, smt_checker): def __init__(self, smt_checker):
self.smt_checker = smt_checker self.smt_checker = smt_checker
self.rs = smt_checker.rs self.rs = smt_checker.rs
@@ -11,49 +12,59 @@ class ParamConstr_Encoder(object):
# self.v = None # self.v = None
# self.v_ctx = None # self.v_ctx = None
# self.loop_position = None # self.loop_position = None
def load_variables(self, var_rs, var_ctx, var_loop_pos): def load_variables(self, var_rs, var_ctx, var_loop_pos):
self.v = var_rs self.v = var_rs
self.v_ctx = var_ctx self.v_ctx = var_ctx
self.loop_position = var_loop_pos self.loop_position = var_loop_pos
def encode(self, param_constr): def encode(self, param_constr):
if not param_constr: if not param_constr:
raise RuntimeError("param_constr is None") raise RuntimeError("param_constr is None")
if param_constr.f_type == ParamConstraint_oper.param_entity: if param_constr.f_type == ParamConstraint_oper.param_entity:
return self.smt_checker.get_enc_param(param_constr.param.name, param_constr.entity) return self.smt_checker.get_enc_param(
param_constr.param.name, param_constr.entity)
if param_constr.f_type == ParamConstraint_oper.true: if param_constr.f_type == ParamConstraint_oper.true:
return True return True
if param_constr.f_type == ParamConstraint_oper.l_and: if param_constr.f_type == ParamConstraint_oper.l_and:
return And(self.encode(param_constr.left_operand), return And(self.encode(param_constr.left_operand),
self.encode(param_constr.right_operand)) self.encode(param_constr.right_operand))
if param_constr.f_type == ParamConstraint_oper.l_or: if param_constr.f_type == ParamConstraint_oper.l_or:
return Or(self.encode(param_constr.left_operand), return Or(self.encode(param_constr.left_operand),
self.encode(param_constr.right_operand)) self.encode(param_constr.right_operand))
if param_constr.f_type == ParamConstraint_oper.l_not: if param_constr.f_type == ParamConstraint_oper.l_not:
return Not(self.encode(param_constr.left_operand)) return Not(self.encode(param_constr.left_operand))
if param_constr.f_type == ParamConstraint_oper.lt: if param_constr.f_type == ParamConstraint_oper.lt:
return self.encode(param_constr.left_operand) < int(param_constr.right_operand) return self.encode(
param_constr.left_operand) < int(
param_constr.right_operand)
if param_constr.f_type == ParamConstraint_oper.le: if param_constr.f_type == ParamConstraint_oper.le:
return self.encode(param_constr.left_operand) <= int(param_constr.right_operand) return self.encode(
param_constr.left_operand) <= int(
param_constr.right_operand)
if param_constr.f_type == ParamConstraint_oper.eq: if param_constr.f_type == ParamConstraint_oper.eq:
return self.encode(param_constr.left_operand) == int(param_constr.right_operand) return self.encode(
param_constr.left_operand) == int(
param_constr.right_operand)
if param_constr.f_type == ParamConstraint_oper.ge: if param_constr.f_type == ParamConstraint_oper.ge:
return self.encode(param_constr.left_operand) >= int(param_constr.right_operand) return self.encode(
param_constr.left_operand) >= int(
param_constr.right_operand)
if param_constr.f_type == ParamConstraint_oper.gt: if param_constr.f_type == ParamConstraint_oper.gt:
return self.encode(param_constr.left_operand) > int(param_constr.right_operand) return self.encode(
param_constr.left_operand) > int(
param_constr.right_operand)
assert False, "Unsupported case {:s}".format(param_constr.f_type) assert False, "Unsupported case {:s}".format(param_constr.f_type)

View File

@@ -27,7 +27,7 @@ class Formula_rsLTL(object):
self.left_operand = Formula_rsLTL.f_bag(self.left_operand) self.left_operand = Formula_rsLTL.f_bag(self.left_operand)
if isinstance(self.right_operand, BagDescription): if isinstance(self.right_operand, BagDescription):
self.right_operand = Formula_rsLTL.f_bag(self.right_operand) self.right_operand = Formula_rsLTL.f_bag(self.right_operand)
if self.sub_operand is True: if self.sub_operand is True:
self.sub_operand = BagDescription.f_TRUE() self.sub_operand = BagDescription.f_TRUE()

View File

@@ -1,11 +1,13 @@
from logics.rsltl import * from logics.rsltl import *
def simplify(x): def simplify(x):
return x return x
class rsLTL_Encoder(object): class rsLTL_Encoder(object):
"""Class for encoding rsLTL formulae for a given smt_checker instance""" """Class for encoding rsLTL formulae for a given smt_checker instance"""
def __init__(self, smt_checker): def __init__(self, smt_checker):
self.smt_checker = smt_checker self.smt_checker = smt_checker
self.rs = smt_checker.rs self.rs = smt_checker.rs
@@ -13,20 +15,20 @@ class rsLTL_Encoder(object):
self.v = None self.v = None
self.v_ctx = None self.v_ctx = None
self.loop_position = None self.loop_position = None
# self.load_variables( # self.load_variables(
# var_rs=smt_checker.v, # var_rs=smt_checker.v,
# var_ctx=smt_checker.v_ctx, # var_ctx=smt_checker.v_ctx,
# var_loop_pos=smt_checker.loop_position) # var_loop_pos=smt_checker.loop_position)
self.init_ncalls() self.init_ncalls()
def load_variables(self, var_rs, var_ctx, var_loop_pos): def load_variables(self, var_rs, var_ctx, var_loop_pos):
self.v = var_rs self.v = var_rs
self.v_ctx = var_ctx self.v_ctx = var_ctx
self.loop_position = var_loop_pos self.loop_position = var_loop_pos
def get_encoding(self, formula, bound): def get_encoding(self, formula, bound):
assert self.v is not None assert self.v is not None
@@ -35,27 +37,27 @@ class rsLTL_Encoder(object):
self.cache_init(bound) self.cache_init(bound)
self.init_ncalls() self.init_ncalls()
return self.encode(formula, 0, bound) return self.encode(formula, 0, bound)
def init_ncalls(self): def init_ncalls(self):
self.ncalls_encode = 0 self.ncalls_encode = 0
self.ncalls_encode_approx = 0 self.ncalls_encode_approx = 0
def cache_init(self, bound): def cache_init(self, bound):
""" """
Cache for formulae encodings Cache for formulae encodings
""" """
self.cache_hits = 0 self.cache_hits = 0
self.enc_fcache = [{} for level in range(0,bound+1)] self.enc_fcache = [{} for level in range(0, bound+1)]
self.enc_fcache_approx = [{} for level in range(0,bound+1)] self.enc_fcache_approx = [{} for level in range(0, bound+1)]
def cache_save(self, formula, level, formula_encoding): def cache_save(self, formula, level, formula_encoding):
self.enc_fcache[level][formula] = formula_encoding self.enc_fcache[level][formula] = formula_encoding
def cache_approx_save(self, formula, level, formula_encoding): def cache_approx_save(self, formula, level, formula_encoding):
self.enc_fcache_approx[level][formula] = formula_encoding self.enc_fcache_approx[level][formula] = formula_encoding
def cache_query(self, formula, level): def cache_query(self, formula, level):
if formula in self.enc_fcache[level]: if formula in self.enc_fcache[level]:
self.cache_hits += 1 self.cache_hits += 1
@@ -72,16 +74,16 @@ class rsLTL_Encoder(object):
def get_cache_hits(self): def get_cache_hits(self):
return self.cache_hits return self.cache_hits
def flush_cache(self): def flush_cache(self):
self.enc_fcache = None self.enc_fcache = None
self.enc_fcache_approx = None self.enc_fcache_approx = None
def get_ncalls(self): def get_ncalls(self):
return (self.ncalls_encode, self.ncalls_encode_approx) return (self.ncalls_encode, self.ncalls_encode_approx)
def encode_bag(self, bag_formula, level, context=False): def encode_bag(self, bag_formula, level, context=False):
if not bag_formula: if not bag_formula:
raise RuntimeError("bag_formula is None") raise RuntimeError("bag_formula is None")
@@ -91,64 +93,79 @@ class rsLTL_Encoder(object):
return self.v_ctx[level][entity_id] return self.v_ctx[level][entity_id]
else: else:
return self.v[level][entity_id] return self.v[level][entity_id]
if bag_formula.f_type == BagDesc_oper.true: if bag_formula.f_type == BagDesc_oper.true:
return True return True
if bag_formula.f_type == BagDesc_oper.l_and: if bag_formula.f_type == BagDesc_oper.l_and:
return And(self.encode_bag(bag_formula.left_operand, level, context), return And(
self.encode_bag(bag_formula.left_operand, level, context),
self.encode_bag(bag_formula.right_operand, level, context)) self.encode_bag(bag_formula.right_operand, level, context))
if bag_formula.f_type == BagDesc_oper.l_or: if bag_formula.f_type == BagDesc_oper.l_or:
return Or(self.encode_bag(bag_formula.left_operand, level, context), return Or(
self.encode_bag(bag_formula.left_operand, level, context),
self.encode_bag(bag_formula.right_operand, level, context)) self.encode_bag(bag_formula.right_operand, level, context))
if bag_formula.f_type == BagDesc_oper.l_not: if bag_formula.f_type == BagDesc_oper.l_not:
return Not(self.encode_bag(bag_formula.left_operand, level, context)) return Not(self.encode_bag(
bag_formula.left_operand, level, context))
if bag_formula.f_type == BagDesc_oper.lt: if bag_formula.f_type == BagDesc_oper.lt:
return self.encode_bag(bag_formula.left_operand, level, context) < int(bag_formula.right_operand) return self.encode_bag(
bag_formula.left_operand, level, context) < int(
bag_formula.right_operand)
if bag_formula.f_type == BagDesc_oper.le: if bag_formula.f_type == BagDesc_oper.le:
return self.encode_bag(bag_formula.left_operand, level, context) <= int(bag_formula.right_operand) return self.encode_bag(
bag_formula.left_operand, level, context) <= int(
bag_formula.right_operand)
if bag_formula.f_type == BagDesc_oper.eq: if bag_formula.f_type == BagDesc_oper.eq:
return self.encode_bag(bag_formula.left_operand, level, context) == int(bag_formula.right_operand) return self.encode_bag(
bag_formula.left_operand, level, context) == int(
bag_formula.right_operand)
if bag_formula.f_type == BagDesc_oper.ge: if bag_formula.f_type == BagDesc_oper.ge:
return self.encode_bag(bag_formula.left_operand, level, context) >= int(bag_formula.right_operand) return self.encode_bag(
bag_formula.left_operand, level, context) >= int(
bag_formula.right_operand)
if bag_formula.f_type == BagDesc_oper.gt: if bag_formula.f_type == BagDesc_oper.gt:
return self.encode_bag(bag_formula.left_operand, level, context) > int(bag_formula.right_operand) return self.encode_bag(
bag_formula.left_operand, level, context) > int(
bag_formula.right_operand)
assert False, "Unsupported case {:s}".format(bag_formula.f_type) assert False, "Unsupported case {:s}".format(bag_formula.f_type)
def encode_bag_state(self, bag_formula, level): def encode_bag_state(self, bag_formula, level):
res = self.encode_bag(bag_formula, level) res = self.encode_bag(bag_formula, level)
assert res is not None assert res is not None
return res return res
def encode_bag_ctx(self, bag_formula, level): def encode_bag_ctx(self, bag_formula, level):
res = self.encode_bag(bag_formula, level, context=True) res = self.encode_bag(bag_formula, level, context=True)
assert res is not None assert res is not None
return res return res
def encode(self, formula, level, bound): def encode(self, formula, level, bound):
self.ncalls_encode += 1 self.ncalls_encode += 1
from_cache = self.cache_query(formula, level) from_cache = self.cache_query(formula, level)
if from_cache is not None: if from_cache is not None:
return from_cache return from_cache
enc = None enc = None
if not isinstance(formula, Formula_rsLTL): if not isinstance(formula, Formula_rsLTL):
raise NotImplementedError("Unsupported formula type: " + str(type(formula))) raise NotImplementedError(
"Unsupported formula type: " + str(type(formula)))
if level > bound: if level > bound:
raise RuntimeError("level > bound. Unexpected behaviour. The encoding does not support levels higher than a bound.") raise RuntimeError(
"level > bound. Unexpected behaviour. The encoding does not support levels higher than a bound.")
if formula.f_type == rsLTL_form_type.bag: if formula.f_type == rsLTL_form_type.bag:
enc = self.encode_bag_state(formula.bag_descr, level) enc = self.encode_bag_state(formula.bag_descr, level)
@@ -158,140 +175,140 @@ class rsLTL_Encoder(object):
enc = Not(self.encode_bag_state(subform, level)) enc = Not(self.encode_bag_state(subform, level))
else: else:
raise RuntimeError("Negation can be applied to bags only") raise RuntimeError("Negation can be applied to bags only")
elif formula.f_type == rsLTL_form_type.l_and: elif formula.f_type == rsLTL_form_type.l_and:
enc = And( enc = And(
self.encode(formula.left_operand, level, bound), self.encode(formula.left_operand, level, bound),
self.encode(formula.right_operand, level, bound) self.encode(formula.right_operand, level, bound)
) )
elif formula.f_type == rsLTL_form_type.l_or: elif formula.f_type == rsLTL_form_type.l_or:
enc = Or( enc = Or(
self.encode(formula.left_operand, level, bound), self.encode(formula.left_operand, level, bound),
self.encode(formula.right_operand, level, bound) self.encode(formula.right_operand, level, bound)
) )
elif formula.f_type == rsLTL_form_type.l_implies: elif formula.f_type == rsLTL_form_type.l_implies:
enc = Implies( enc = Implies(
self.encode(formula.left_operand, level, bound), self.encode(formula.left_operand, level, bound),
self.encode(formula.right_operand, level, bound) self.encode(formula.right_operand, level, bound)
) )
elif formula.f_type == rsLTL_form_type.t_next: elif formula.f_type == rsLTL_form_type.t_next:
if level < bound: if level < bound:
enc = And( enc = And(
self.encode(formula.left_operand, level + 1, bound), self.encode(formula.left_operand, level + 1, bound),
self.encode_bag_ctx(formula.sub_operand, level) self.encode_bag_ctx(formula.sub_operand, level)
) )
else: else:
# level == bound # level == bound
enc = False enc = False
for loop_level in range(1, bound+1): for loop_level in range(1, bound+1):
enc = simplify(Or(enc, And(self.loop_position == loop_level, enc = simplify(Or(enc, And(self.loop_position == loop_level, self.encode(
self.encode(formula.left_operand, loop_level, bound)))) formula.left_operand, loop_level, bound))))
enc = And(enc, self.encode_bag_ctx(formula.sub_operand, level)) enc = And(enc, self.encode_bag_ctx(formula.sub_operand, level))
enc = simplify(enc) enc = simplify(enc)
elif formula.f_type == rsLTL_form_type.t_globally: elif formula.f_type == rsLTL_form_type.t_globally:
if level < bound: if level < bound:
enc = And( enc = And(
self.encode(formula.left_operand, level, bound), self.encode(formula.left_operand, level, bound),
self.encode_bag_ctx(formula.sub_operand, level), self.encode_bag_ctx(formula.sub_operand, level),
self.encode(formula, level + 1, bound) self.encode(formula, level + 1, bound)
) )
else: else:
# level == bound # level == bound
enc_loops = False enc_loops = False
for loop_level in range(1, bound+1): for loop_level in range(1, bound+1):
enc_loops = simplify(Or(enc_loops, enc_loops = simplify(Or(enc_loops,
And( And(
self.loop_position == loop_level, self.loop_position == loop_level,
self.encode_approx(formula, loop_level, bound), self.encode_approx(formula, loop_level, bound),
) )
)) ))
enc = And( enc = And(
self.encode(formula.left_operand, bound, bound), self.encode(formula.left_operand, bound, bound),
enc_loops, enc_loops,
self.encode_bag_ctx(formula.sub_operand, level) self.encode_bag_ctx(formula.sub_operand, level)
) )
enc = simplify(enc) enc = simplify(enc)
elif formula.f_type == rsLTL_form_type.t_finally: elif formula.f_type == rsLTL_form_type.t_finally:
if level < bound: if level < bound:
enc = Or( enc = Or(
self.encode(formula.left_operand, level, bound), self.encode(formula.left_operand, level, bound),
And( And(
self.encode_bag_ctx(formula.sub_operand, level), self.encode_bag_ctx(formula.sub_operand, level),
self.encode(formula, level + 1, bound) self.encode(formula, level + 1, bound)
)
) )
)
else: else:
# level == bound # level == bound
enc_loops = False enc_loops = False
for loop_level in range(1, bound+1): for loop_level in range(1, bound+1):
enc_loops = simplify(Or(enc_loops, enc_loops = simplify(Or(enc_loops,
And( And(
self.loop_position == loop_level, self.loop_position == loop_level,
self.encode_approx(formula, loop_level, bound), self.encode_approx(formula, loop_level, bound),
) )
)) ))
#print(enc) # print(enc)
enc = Or(self.encode(formula.left_operand, bound, bound), enc = Or(self.encode(formula.left_operand, bound, bound),
And( And(
enc_loops, enc_loops,
self.encode_bag_ctx(formula.sub_operand, level) self.encode_bag_ctx(formula.sub_operand, level)
) )
) )
enc = simplify(enc) enc = simplify(enc)
elif formula.f_type == rsLTL_form_type.t_until: elif formula.f_type == rsLTL_form_type.t_until:
if level < bound: if level < bound:
inner_enc = self.encode(formula, level + 1, bound) inner_enc = self.encode(formula, level + 1, bound)
else: else:
# level == bound # level == bound
inner_enc = False inner_enc = False
for loop_level in range(1, bound+1): for loop_level in range(1, bound+1):
inner_enc = simplify(Or(inner_enc, inner_enc = simplify(Or(inner_enc,
And( And(
self.loop_position == loop_level, self.loop_position == loop_level,
self.encode_approx(formula, loop_level, bound) self.encode_approx(formula, loop_level, bound)
) )
)) ))
enc = Or( enc = Or(
self.encode(formula.right_operand, level, bound), self.encode(formula.right_operand, level, bound),
And(
self.encode(formula.left_operand, level, bound),
inner_enc,
self.encode_bag_ctx(formula.sub_operand, level)
)
)
elif formula.f_type == rsLTL_form_type.t_release:
if level < bound:
inner_enc = self.encode(formula, level + 1, bound)
else:
# level == bound
inner_enc = False
for loop_level in range(1, bound+1):
inner_enc = simplify(Or(inner_enc,
And(
self.loop_position == loop_level,
self.encode_approx(formula, loop_level, bound)
)
))
enc = And(
self.encode(formula.right_operand, level, bound),
Or(
self.encode(formula.left_operand, level, bound),
And( And(
self.encode(formula.left_operand, level, bound),
inner_enc, inner_enc,
self.encode_bag_ctx(formula.sub_operand, level) self.encode_bag_ctx(formula.sub_operand, level)
) )
) )
)
elif formula.f_type == rsLTL_form_type.t_release:
if level < bound:
inner_enc = self.encode(formula, level + 1, bound)
else:
# level == bound
inner_enc = False
for loop_level in range(1, bound+1):
inner_enc = simplify(Or(inner_enc,
And(
self.loop_position == loop_level,
self.encode_approx(formula, loop_level, bound)
)
))
enc = And(
self.encode(formula.right_operand, level, bound),
Or(
self.encode(formula.left_operand, level, bound),
And(
inner_enc,
self.encode_bag_ctx(formula.sub_operand, level)
)
)
)
else: else:
raise NotImplementedError("Unsupported operator") raise NotImplementedError("Unsupported operator")
@@ -305,55 +322,55 @@ class rsLTL_Encoder(object):
def encode_approx(self, formula, level, bound): def encode_approx(self, formula, level, bound):
"""Provides the approximation-encoding """Provides the approximation-encoding
Used by encode() Used by encode()
""" """
self.ncalls_encode_approx += 1 self.ncalls_encode_approx += 1
enc = None enc = None
from_cache = self.cache_query_approx(formula, level) from_cache = self.cache_query_approx(formula, level)
if from_cache is not None: if from_cache is not None:
return from_cache return from_cache
if formula.f_type == rsLTL_form_type.t_until: if formula.f_type == rsLTL_form_type.t_until:
if level < bound: if level < bound:
enc = Or( enc = Or(
self.encode(formula.right_operand, level, bound), self.encode(formula.right_operand, level, bound),
And(
self.encode(formula.left_operand, level, bound),
self.encode_approx(formula, level + 1, bound),
self.encode_bag_ctx(formula.sub_operand, level)
)
)
else:
# level == bound
enc = self.encode(formula.right_operand, bound, bound)
elif formula.f_type == rsLTL_form_type.t_release:
if level < bound:
enc = And(
self.encode(formula.right_operand, level, bound),
Or(
self.encode(formula.left_operand, level, bound),
And( And(
self.encode(formula.left_operand, level, bound),
self.encode_approx(formula, level + 1, bound), self.encode_approx(formula, level + 1, bound),
self.encode_bag_ctx(formula.sub_operand, level) self.encode_bag_ctx(formula.sub_operand, level)
) )
) )
else: )
# level == bound else:
enc = self.encode(formula.right_operand, bound, bound)
elif formula.f_type == rsLTL_form_type.t_release:
if level < bound:
enc = And(
self.encode(formula.right_operand, level, bound),
Or(
self.encode(formula.left_operand, level, bound),
And(
self.encode_approx(formula, level + 1, bound),
self.encode_bag_ctx(formula.sub_operand, level)
)
)
)
else:
# level == bound # level == bound
enc = self.encode(formula.right_operand, bound, bound) enc = self.encode(formula.right_operand, bound, bound)
elif formula.f_type == rsLTL_form_type.t_globally: elif formula.f_type == rsLTL_form_type.t_globally:
if level < bound: if level < bound:
enc = And( enc = And(
self.encode(formula.left_operand, level, bound), self.encode(formula.left_operand, level, bound),
self.encode_bag_ctx(formula.sub_operand, level), self.encode_bag_ctx(formula.sub_operand, level),
self.encode_approx(formula, level + 1, bound) self.encode_approx(formula, level + 1, bound)
) )
else: else:
# level == bound # level == bound
enc = self.encode(formula.left_operand, bound, bound) enc = self.encode(formula.left_operand, bound, bound)
@@ -361,22 +378,23 @@ class rsLTL_Encoder(object):
elif formula.f_type == rsLTL_form_type.t_finally: elif formula.f_type == rsLTL_form_type.t_finally:
if level < bound: if level < bound:
enc = Or( enc = Or(
self.encode(formula.left_operand, level, bound), self.encode(formula.left_operand, level, bound),
And( And(
self.encode_bag_ctx(formula.sub_operand, level), self.encode_bag_ctx(formula.sub_operand, level),
self.encode_approx(formula, level + 1, bound) self.encode_approx(formula, level + 1, bound)
)
) )
)
else: else:
# level == bound # level == bound
enc = self.encode(formula.left_operand, bound, bound) enc = self.encode(formula.left_operand, bound, bound)
else: else:
raise NotImplementedError("Unsupported operator in approximation encoding") raise NotImplementedError(
"Unsupported operator in approximation encoding")
if enc is None: if enc is None:
raise RuntimeError("Encoding is NONE. Should never happen") raise RuntimeError("Encoding is NONE. Should never happen")
self.cache_approx_save(formula, level, enc) self.cache_approx_save(formula, level, enc)
return enc return enc

View File

@@ -1,8 +1,9 @@
from sys import exit from sys import exit
from colour import * from colour import *
class ContextAutomaton(object): class ContextAutomaton(object):
def __init__(self, reaction_system): def __init__(self, reaction_system):
self._states = [] self._states = []
self._transitions = [] self._transitions = []
@@ -10,41 +11,41 @@ class ContextAutomaton(object):
self._reaction_system = reaction_system self._reaction_system = reaction_system
self._name = "" self._name = ""
self._prod_entities = set() self._prod_entities = set()
@property @property
def states(self): def states(self):
return self._states return self._states
@property @property
def transitions(self): def transitions(self):
return self._transitions return self._transitions
@property @property
def prod_entities(self): def prod_entities(self):
return self._prod_entities return self._prod_entities
@property @property
def reaction_system(self): def reaction_system(self):
return self._reaction_system return self._reaction_system
@property @property
def name(self): def name(self):
return self._name return self._name
@name.setter @name.setter
def name(self, automaton_name): def name(self, automaton_name):
self._name = automaton_name self._name = automaton_name
def add_state(self, name): def add_state(self, name):
if name not in self._states: if name not in self._states:
self._states.append(name) self._states.append(name)
else: else:
print("\'%s\' already added. skipping..." % (name,)) print("\'%s\' already added. skipping..." % (name,))
def add_states(self, states_set): def add_states(self, states_set):
for st in states_set: for st in states_set:
self.add_state(st) self.add_state(st)
def add_init_state(self, name): def add_init_state(self, name):
self.add_state(name) self.add_state(name)
self._init_state = self._states.index(name) self._init_state = self._states.index(name)
@@ -72,48 +73,53 @@ class ContextAutomaton(object):
def get_init_state_id(self): def get_init_state_id(self):
return self._init_state return self._init_state
def print_states(self): def print_states(self):
for state in self._states: for state in self._states:
print(state) print(state)
def is_valid_rs_set(self, elements): def is_valid_rs_set(self, elements):
if set(elements).issubset(self._reaction_system.background_set): if set(elements).issubset(self._reaction_system.background_set):
return True return True
else: else:
return False return False
def is_valid_context(self, context): def is_valid_context(self, context):
return self.is_valid_rs_set(context) return self.is_valid_rs_set(context)
def get_set_of_ids(self, elements): def get_set_of_ids(self, elements):
"""Converts a set/list/tuple of entities into a set of their ids""" """Converts a set/list/tuple of entities into a set of their ids"""
new_set = set() new_set = set()
for e in set(elements): for e in set(elements):
new_set.add(self._reaction_system.get_entity_id(e)) new_set.add(self._reaction_system.get_entity_id(e))
return new_set return new_set
def add_transition(self, src, context_set, dst): def add_transition(self, src, context_set, dst):
if not type(context_set) is set and not type(context_set) is list: if not type(context_set) is set and not type(context_set) is list:
print("Contexts set must be of type set or list") print("Contexts set must be of type set or list")
if not self.is_valid_context(context_set): if not self.is_valid_context(context_set):
raise RuntimeError("one of the entities in the context set is unknown (undefined)!") raise RuntimeError(
"one of the entities in the context set is unknown (undefined)!")
if not self.is_state(src): if not self.is_state(src):
raise RuntimeError("\"" + src + "\" is an unknown (undefined) state") raise RuntimeError(
"\"" + src + "\" is an unknown (undefined) state")
if not self.is_state(dst): if not self.is_state(dst):
raise RuntimeError("\"" + dst + "\" is an unknown (undefined) state") raise RuntimeError(
"\"" + dst + "\" is an unknown (undefined) state")
new_context_set = set() new_context_set = set()
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._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):
"""Converts the set of entities ids into the string with their names""" """Converts the set of entities ids into the string with their names"""
@@ -121,13 +127,13 @@ class ContextAutomaton(object):
return "0" return "0"
s = "{" s = "{"
for c in elements: for c in elements:
s += " " + self._reaction_system.get_entity_name(c) s += " " + self._reaction_system.get_entity_name(c)
s += " }" s += " }"
return s return s
def context2str(self, ctx): def context2str(self, ctx):
return self.rsset2str(ctx) return self.rsset2str(ctx)
def show_transitions(self): def show_transitions(self):
print(C_MARK_INFO + " Context automaton transitions:") print(C_MARK_INFO + " Context automaton transitions:")
for transition in self._transitions: for transition in self._transitions:
@@ -135,7 +141,7 @@ class ContextAutomaton(object):
str_transition += self.context2str(transition[1]) str_transition += self.context2str(transition[1])
str_transition += " )--> " + str(transition[2]) str_transition += " )--> " + str(transition[2])
print(" - " + str_transition) print(" - " + str_transition)
def show_states(self): def show_states(self):
init_state_name = self.get_init_state_name() init_state_name = self.get_init_state_name()
print(C_MARK_INFO + " Context automaton states:") print(C_MARK_INFO + " Context automaton states:")
@@ -149,13 +155,13 @@ class ContextAutomaton(object):
def show_header(self): def show_header(self):
if self.name: if self.name:
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): def show_prod_entities(self):
print(C_MARK_INFO + " Context automaton possible products:") print(C_MARK_INFO + " Context automaton possible products:")
for entity in self._prod_entities: for entity in self._prod_entities:
print(" - " + self._reaction_system.get_entity_name(entity)) 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()

View File

@@ -2,66 +2,79 @@ from sys import exit
from colour import * from colour import *
from rs.context_automaton import ContextAutomaton from rs.context_automaton import ContextAutomaton
class ContextAutomatonWithConcentrations(ContextAutomaton): class ContextAutomatonWithConcentrations(ContextAutomaton):
def __init__(self, reaction_system): def __init__(self, reaction_system):
super(ContextAutomatonWithConcentrations, self).__init__(reaction_system) super(ContextAutomatonWithConcentrations,
self).__init__(reaction_system)
def is_valid_context(self, context): def is_valid_context(self, context):
if set([e for e,lvl in context]).issubset(self._reaction_system.background_set): if set(
[e for e, lvl in context]).issubset(
self._reaction_system.background_set):
return True return True
else: else:
return False return False
def context2str(self, ctx): def context2str(self, ctx):
if len(ctx) == 0: if len(ctx) == 0:
return "0" return "0"
s = "{" s = "{"
for ent,lvl in ctx: for ent, lvl in ctx:
s += " " + str((self._reaction_system.get_entity_name(ent),lvl)) s += " " + str((self._reaction_system.get_entity_name(ent), lvl))
s += " }" s += " }"
return s return s
def add_transition(self, src, context_set, dst): def add_transition(self, src, context_set, dst):
if not type(context_set) is set and not type(context_set) is list: if not type(context_set) is set and not type(context_set) is list:
print("Contexts set must be of type set or list") print("Contexts set must be of type set or list")
if not self.is_valid_context(context_set): if not self.is_valid_context(context_set):
raise RuntimeError("one of the entities in the context set is unknown (undefined)!") raise RuntimeError(
"one of the entities in the context set is unknown (undefined)!")
if not self.is_state(src): if not self.is_state(src):
raise RuntimeError("\"" + src + "\" is an unknown (undefined) state") raise RuntimeError(
"\"" + src + "\" is an unknown (undefined) state")
if not self.is_state(dst): if not self.is_state(dst):
raise RuntimeError("\"" + dst + "\" is an unknown (undefined) state") raise RuntimeError(
"\"" + dst + "\" is an unknown (undefined) state")
new_context_set = set() new_context_set = set()
for ent,lvl in set(context_set): for ent, lvl in set(context_set):
new_context_set.add((self._reaction_system.get_entity_id(ent),lvl)) new_context_set.add(
(self._reaction_system.get_entity_id(ent), lvl))
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 get_automaton_with_flat_contexts(self, ordinary_reaction_system): def get_automaton_with_flat_contexts(self, ordinary_reaction_system):
ca = ContextAutomaton(ordinary_reaction_system) ca = ContextAutomaton(ordinary_reaction_system)
ca._states = self._states ca._states = self._states
ca._init_state = self._init_state ca._init_state = self._init_state
for src,ctx,dst in self._transitions: for src, ctx, dst in self._transitions:
new_ctx = set() new_ctx = set()
for ent,conc in ctx: for ent, conc in ctx:
for i in range(1,conc+1): for i in range(1, conc+1):
n = self._reaction_system.get_entity_name(ent) + "#" + str(i) n = self._reaction_system.get_entity_name(
ent) + "#" + str(i)
ca._reaction_system.ensure_bg_set_entity(n) ca._reaction_system.ensure_bg_set_entity(n)
new_ctx.add(n) new_ctx.add(n)
ca.add_transition(ca.get_state_name(src),new_ctx,ca.get_state_name(dst)) ca.add_transition(
ca.get_state_name(src),
new_ctx, ca.get_state_name(dst))
return ca return ca
def show(self): def show(self):
self.show_header() self.show_header()
self.show_states() self.show_states()

View File

@@ -3,14 +3,15 @@ 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. Supports transitions with actions.
Each transitions is additionally guarded with Each transitions is additionally guarded with
reactants and inhibitors. reactants and inhibitors.
The provided context entities are the products The provided context entities are the products
of the reactions labelling the transition taken. of the reactions labelling the transition taken.
""" """
@@ -20,36 +21,36 @@ class ExtendedContextAutomaton(ContextAutomaton):
self._actions = [] self._actions = []
self._transitions_for_products = dict() self._transitions_for_products = dict()
self._actions_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 @property
def actions(self): def actions(self):
return self._actions return self._actions
def has_action(self, action): def has_action(self, action):
"""Checks if the automaton supports a given action""" """Checks if the automaton supports a given action"""
return action in self._actions return action in self._actions
def get_transitions_producing_entity(self, entity): def get_transitions_producing_entity(self, entity):
"""Returns the transitions that produce a given entity""" """Returns the transitions that produce a given entity"""
if entity in self._transitions_for_products: if entity in self._transitions_for_products:
return self._transitions_for_products[entity] return self._transitions_for_products[entity]
else: else:
return [] return []
def get_actions_producing_entity(self, entity): def get_actions_producing_entity(self, entity):
"""Returns the actions that produce a given entity""" """Returns the actions that produce a given entity"""
if entity in self._actions_for_products: if entity in self._actions_for_products:
return self._actions_for_products[entity] return self._actions_for_products[entity]
else: else:
return set() return set()
def can_produce_entity(self, entity): def can_produce_entity(self, entity):
"""Check if the automaton can produce an entity""" """Check if the automaton can produce an entity"""
@@ -57,35 +58,40 @@ class ExtendedContextAutomaton(ContextAutomaton):
return True return True
else: else:
return False return False
def add_transition(self, src, actions, ctx_reaction, dst): def add_transition(self, src, actions, ctx_reaction, dst):
"""Adds a transition """Adds a transition
src: is the source state name src: is the source state name
dst: is the destination state name dst: is the destination state name
actions: is the set of actions with which the transitions is synchronised actions: is the set of actions with which the transitions is synchronised
ctx_reaction: is the context reaction associated with the transition ctx_reaction: is the context reaction associated with the transition
""" """
ctx_reactants, ctx_inhibitors, ctx_products = ctx_reaction ctx_reactants, ctx_inhibitors, ctx_products = ctx_reaction
if not type(ctx_products) is set and not type(ctx_products) is list: if not type(ctx_products) is set and not type(ctx_products) is list:
print("Contexts set (context products) must be of type set or list") print("Contexts set (context products) must be of type set or list")
if not self.is_valid_rs_set(ctx_reactants): if not self.is_valid_rs_set(ctx_reactants):
raise RuntimeError("one of the entities in the reactants set is unknown (undefined)!") raise RuntimeError(
"one of the entities in the reactants set is unknown (undefined)!")
if not self.is_valid_rs_set(ctx_inhibitors): if not self.is_valid_rs_set(ctx_inhibitors):
raise RuntimeError("one of the entities in the inhibitors set is unknown (undefined)!") raise RuntimeError(
"one of the entities in the inhibitors set is unknown (undefined)!")
if not self.is_valid_rs_set(ctx_products): if not self.is_valid_rs_set(ctx_products):
raise RuntimeError("one of the entities in the context set is unknown (undefined)!") raise RuntimeError(
"one of the entities in the context set is unknown (undefined)!")
if not self.is_state(src): if not self.is_state(src):
raise RuntimeError("\"" + src + "\" is an unknown (undefined) state") raise RuntimeError(
"\"" + src + "\" is an unknown (undefined) state")
if not self.is_state(dst): if not self.is_state(dst):
raise RuntimeError("\"" + dst + "\" is an unknown (undefined) state") raise RuntimeError(
"\"" + dst + "\" is an unknown (undefined) state")
src_id = self.get_state_id(src) src_id = self.get_state_id(src)
dst_id = self.get_state_id(dst) dst_id = self.get_state_id(dst)
@@ -93,76 +99,78 @@ class ExtendedContextAutomaton(ContextAutomaton):
r_ids = self.get_set_of_ids(ctx_reactants) r_ids = self.get_set_of_ids(ctx_reactants)
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)
new_transition = (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: for product_id in p_ids:
self._transitions_for_products.setdefault(product_id, []) self._transitions_for_products.setdefault(product_id, [])
self._transitions_for_products[product_id].append(new_transition) self._transitions_for_products[product_id].append(new_transition)
self._actions_for_products.setdefault(product_id, set()) self._actions_for_products.setdefault(product_id, set())
self._actions_for_products[product_id] |= set(actions) self._actions_for_products[product_id] |= set(actions)
self._prod_entities |= p_ids self._prod_entities |= p_ids
self._transitions.append(new_transition) 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) + " --( "
str_transition += "<" + self.get_actions_str(act_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.rsset2str(reaction[0]) + "," + self.rsset2str(
reaction[1]) + "," + self.rsset2str(reaction[2]) + " )"
str_transition += " )--> " + self.get_state_name(dst_id) str_transition += " )--> " + self.get_state_name(dst_id)
print(" - " + str_transition) print(" - " + str_transition)
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:
print("\'%s\' already added. skipping..." % (action_name,)) print("\'%s\' already added. skipping..." % (action_name,))
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:
print_error("Undefined context automaton action: " + repr(action_name)) print_error("Undefined context automaton action: " +
repr(action_name))
exit(1) exit(1)
def get_action_name(self, action_id): def get_action_name(self, action_id):
return self._actions[action_id] return self._actions[action_id]
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))
return act_ids return act_ids
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) + ", "
s = s[:-2] s = s[:-2]
return s return s
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)) + ")")
def show(self): def show(self):
super(ExtendedContextAutomaton, self).show() super(ExtendedContextAutomaton, self).show()
self.show_actions() self.show_actions()
# EOF # EOF

View File

@@ -1,8 +1,9 @@
from sys import exit from sys import exit
from colour import * from colour import *
class NetworkOfContextAutomata(object): class NetworkOfContextAutomata(object):
def __init__(self, reaction_system, context_automata): def __init__(self, reaction_system, context_automata):
self.automata = [] self.automata = []
self._reaction_system = reaction_system self._reaction_system = reaction_system
@@ -14,7 +15,7 @@ class NetworkOfContextAutomata(object):
if len(context_automata) < 1: if len(context_automata) < 1:
print("Context automata network must contain at least one automaton!") print("Context automata network must contain at least one automaton!")
exit(1) exit(1)
for automaton in context_automata: for automaton in context_automata:
self.add(automaton) self.add(automaton)
@@ -39,14 +40,18 @@ class NetworkOfContextAutomata(object):
def sanity_check(self): def sanity_check(self):
"""Performs a sanity check of the network of automata""" """Performs a sanity check of the network of automata"""
for automaton in self.automata: for automaton in self.automata:
if automaton.reaction_system != self._reaction_system: if automaton.reaction_system != self._reaction_system:
print_error("Mismatching reaction system used in \"" + str(automaton.name) + "\"!!!") print_error(
"Mismatching reaction system used in \"" +
str(automaton.name) + "\"!!!")
exit(1) exit(1)
def show_prod_entities(self): def show_prod_entities(self):
print(C_MARK_INFO + " Possible context-products for the network of automata:") print(
C_MARK_INFO +
" Possible context-products for the network of automata:")
for entity in self.prod_entities: for entity in self.prod_entities:
print(" - " + self._reaction_system.get_entity_name(entity)) print(" - " + self._reaction_system.get_entity_name(entity))
@@ -57,22 +62,22 @@ class NetworkOfContextAutomata(object):
def register_action(self, action, aut): def register_action(self, action, aut):
"""Associates an action with an automaton""" """Associates an action with an automaton"""
self._automata_for_actions.setdefault(action, set()) self._automata_for_actions.setdefault(action, set())
aut_index = self.automata.index(aut) aut_index = self.automata.index(aut)
self._automata_for_actions[action].add(aut_index) self._automata_for_actions[action].add(aut_index)
def get_actions_producing_entity(self, entity): def get_actions_producing_entity(self, entity):
"""Returns the set of actions producing an entity""" """Returns the set of actions producing an entity"""
if entity in self._actions_for_products: if entity in self._actions_for_products:
return self._actions_for_products[entity] return self._actions_for_products[entity]
else: else:
return set() return set()
def get_automata_with_action(self, action): def get_automata_with_action(self, action):
"""Returns the set of automata that support an action""" """Returns the set of automata that support an action"""
if action in self._automata_for_actions: if action in self._automata_for_actions:
return self._automata_for_actions[action] return self._automata_for_actions[action]
else: else:
@@ -80,17 +85,18 @@ class NetworkOfContextAutomata(object):
def add(self, aut): def add(self, aut):
"""Adds an automaton to the network""" """Adds an automaton to the network"""
self.automata.append(aut) self.automata.append(aut)
self._prod_entities |= aut.prod_entities self._prod_entities |= aut.prod_entities
self._actions |= set(aut.actions) self._actions |= set(aut.actions)
for action in aut.actions: for action in aut.actions:
self.register_action(action, aut) self.register_action(action, aut)
for entity in aut.prod_entities: for entity in aut.prod_entities:
self._actions_for_products.setdefault(entity, set()) self._actions_for_products.setdefault(entity, set())
self._actions_for_products[entity] |= aut.get_actions_producing_entity(entity) self._actions_for_products[entity] |= aut.get_actions_producing_entity(
entity)
def show(self): def show(self):
print() print()
@@ -102,4 +108,4 @@ class NetworkOfContextAutomata(object):
self.show_prod_entities() self.show_prod_entities()
self.show_actions() self.show_actions()
# EOF # EOF

View File

@@ -1,6 +1,7 @@
from sys import exit from sys import exit
from colour import * from colour import *
class ReactionSystem(object): class ReactionSystem(object):
def __init__(self): def __init__(self):
@@ -8,17 +9,17 @@ class ReactionSystem(object):
self.reactions = [] self.reactions = []
self.background_set = [] self.background_set = []
#self.reactions_by_agents = [] # each element is 'reactions_by_prod' # self.reactions_by_agents = [] # each element is 'reactions_by_prod'
self.reactions_by_prod = None self.reactions_by_prod = None
## legacy: # legacy:
self.init_contexts = [] self.init_contexts = []
self.context_entities = [] self.context_entities = []
@property @property
def background_set_size(self): def background_set_size(self):
return len(self.background_set) return len(self.background_set)
@property @property
def set_of_bgset_ids(self): def set_of_bgset_ids(self):
return set(range(self.background_set_size)) return set(range(self.background_set_size))
@@ -29,12 +30,13 @@ class ReactionSystem(object):
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")
def add_bg_set_entity(self, name): def add_bg_set_entity(self, name):
self.assume_not_in_bgset(name) self.assume_not_in_bgset(name)
self.background_set.append(name) self.background_set.append(name)
def ensure_bg_set_entity(self, name): def ensure_bg_set_entity(self, name):
if not self.is_in_background_set(name): if not self.is_in_background_set(name):
self.background_set.append(name) self.background_set.append(name)
@@ -70,7 +72,7 @@ class ReactionSystem(object):
def add_reaction(self, R, I, P): def add_reaction(self, R, I, P):
"""Adds a reaction""" """Adds a reaction"""
if R == [] or P == []: if R == [] or P == []:
raise RuntimeError("No reactants or products defined") raise RuntimeError("No reactants or products defined")
@@ -122,34 +124,38 @@ class ReactionSystem(object):
s += self.get_entity_name(entity) + ", " s += self.get_entity_name(entity) + ", "
s = s[:-2] s = s[:-2]
return s return s
def state_to_str(self, state): def state_to_str(self, state):
return self.entities_ids_set_to_str(state) return self.entities_ids_set_to_str(state)
def show_reactions(self, soft=False): def show_reactions(self, soft=False):
print(C_MARK_INFO + " Reactions:") print(C_MARK_INFO + " Reactions:")
if soft and len(self.reactions) > 50: if soft and len(self.reactions) > 50:
print(" -> there are more than 50 reactions (" + str(len(self.reactions)) + ")") print(" -> there are more than 50 reactions (" +
str(len(self.reactions)) + ")")
else: else:
print(" "*4 + "{0: ^35}{1: ^25}{2: ^15}".format("reactants"," inhibitors"," products")) print(
" "*4 + "{0: ^35}{1: ^25}{2: ^15}".format("reactants", " inhibitors", " products"))
for reaction in self.reactions: for reaction in self.reactions:
# print("\t( R={" + self.state_to_str(reaction[0]) + "}, I={" + self.state_to_str(reaction[1]) + "}, P={" + self.state_to_str(reaction[2]) + "} )") # print("\t( R={" + self.state_to_str(reaction[0]) + "}, I={" + self.state_to_str(reaction[1]) + "}, P={" + self.state_to_str(reaction[2]) + "} )")
print(" " + "- {0: ^35}{1: ^25}{2: ^15}".format("{ " + self.state_to_str(reaction[0]) + " }", print(" " + "- {0: ^35}{1: ^25}{2: ^15}".format("{ " + self.state_to_str(reaction[0]) + " }",
" { " + self.state_to_str(reaction[1]) + " }", " { " + self.state_to_str(reaction[1]) + " }",
" { " + self.state_to_str(reaction[2]) + " }")) " { " + self.state_to_str(reaction[2]) + " }"))
def show_background_set(self): def show_background_set(self):
print(C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}") print(
C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}")
def show_initial_contexts(self): def show_initial_contexts(self):
if len(self.init_contexts) > 0: if len(self.init_contexts) > 0:
print(C_MARK_INFO + " Initial context sets:") print(C_MARK_INFO + " Initial context sets:")
for ctx in self.init_contexts: for ctx in self.init_contexts:
print(" - {" + self.entities_ids_set_to_str(ctx) + "}") print(" - {" + self.entities_ids_set_to_str(ctx) + "}")
def show_context_entities(self): def show_context_entities(self):
if len(self.context_entities) > 0: if len(self.context_entities) > 0:
print(C_MARK_INFO + " Context entities: " + self.entities_ids_set_to_str(self.context_entities)) print(
C_MARK_INFO + " Context entities: " + self.entities_ids_set_to_str(self.context_entities))
def show(self, soft=False): def show(self, soft=False):
@@ -157,7 +163,7 @@ class ReactionSystem(object):
self.show_initial_contexts() self.show_initial_contexts()
self.show_reactions(soft) self.show_reactions(soft)
self.show_context_entities() self.show_context_entities()
def get_reactions_by_product(self): def get_reactions_by_product(self):
"""Sorts reactions by their products and returns a dictionary of products""" """Sorts reactions by their products and returns a dictionary of products"""
@@ -169,13 +175,14 @@ class ReactionSystem(object):
for reaction in self.reactions: for reaction in self.reactions:
producible_entities = producible_entities.union(set(reaction[2])) producible_entities = producible_entities.union(set(reaction[2]))
reactions_by_prod = {} reactions_by_prod = {}
for prod_entity in producible_entities: for prod_entity in producible_entities:
reactions_by_prod[prod_entity] = [] reactions_by_prod[prod_entity] = []
for reaction in self.reactions: for reaction in self.reactions:
if prod_entity in reaction[2]: if prod_entity in reaction[2]:
reactions_by_prod[prod_entity].append([reaction[0],reaction[1]]) reactions_by_prod[prod_entity].append(
[reaction[0], reaction[1]])
# save in cache # save in cache
self.reactions_by_prod = reactions_by_prod self.reactions_by_prod = reactions_by_prod

View File

@@ -1,6 +1,6 @@
class ReactionSystemWithNetworkOfAutomata(object): class ReactionSystemWithNetworkOfAutomata(object):
def __init__(self, reaction_system, context_automata): def __init__(self, reaction_system, context_automata):
self.rs = reaction_system self.rs = reaction_system
self.cas = context_automata self.cas = context_automata
@@ -9,4 +9,4 @@ class ReactionSystemWithNetworkOfAutomata(object):
self.rs.show(soft) self.rs.show(soft)
self.cas.show() self.cas.show()
# EOF # EOF

View File

@@ -2,8 +2,9 @@ from rs.reaction_system_with_concentrations import ReactionSystemWithConcentrati
from rs.reaction_system_with_concentrations_param import ReactionSystemWithConcentrationsParam from rs.reaction_system_with_concentrations_param import ReactionSystemWithConcentrationsParam
from rs.context_automaton_with_concentrations import ContextAutomatonWithConcentrations from rs.context_automaton_with_concentrations import ContextAutomatonWithConcentrations
class ReactionSystemWithAutomaton(object): class ReactionSystemWithAutomaton(object):
def __init__(self, reaction_system, context_automaton): def __init__(self, reaction_system, context_automaton):
self.rs = reaction_system self.rs = reaction_system
self.ca = context_automaton self.ca = context_automaton
@@ -11,7 +12,7 @@ class ReactionSystemWithAutomaton(object):
def show(self, soft=False): def show(self, soft=False):
self.rs.show(soft) self.rs.show(soft)
self.ca.show() self.ca.show()
def is_concentr_and_param_compatible(self): def is_concentr_and_param_compatible(self):
""" """
Checks if the underlying RS/CA are compatible Checks if the underlying RS/CA are compatible
@@ -22,7 +23,7 @@ class ReactionSystemWithAutomaton(object):
if not isinstance(self.ca, ContextAutomatonWithConcentrations): if not isinstance(self.ca, ContextAutomatonWithConcentrations):
return False return False
return True return True
def is_with_concentrations(self): def is_with_concentrations(self):
if not isinstance(self.rs, ReactionSystemWithConcentrations): if not isinstance(self.rs, ReactionSystemWithConcentrations):
return False return False
@@ -32,14 +33,13 @@ class ReactionSystemWithAutomaton(object):
def sanity_check(self): def sanity_check(self):
pass pass
def get_ordinary_reaction_system_with_automaton(self): def get_ordinary_reaction_system_with_automaton(self):
if not self.is_with_concentrations(): if not self.is_with_concentrations():
raise RuntimeError("Not RS/CA with concentrations") raise RuntimeError("Not RS/CA with concentrations")
ors = self.rs.get_reaction_system() ors = self.rs.get_reaction_system()
oca = self.ca.get_automaton_with_flat_contexts(ors) oca = self.ca.get_automaton_with_flat_contexts(ors)
return ReactionSystemWithAutomaton(ors, oca) return ReactionSystemWithAutomaton(ors, oca)

View File

@@ -3,29 +3,31 @@ from colour import *
from rs.reaction_system import ReactionSystem from rs.reaction_system import ReactionSystem
class ReactionSystemWithConcentrations(ReactionSystem): class ReactionSystemWithConcentrations(ReactionSystem):
def __init__(self): def __init__(self):
self.reactions = [] self.reactions = []
self.meta_reactions = dict() self.meta_reactions = dict()
self.permanent_entities = dict() self.permanent_entities = dict()
self.background_set = [] self.background_set = []
self.context_entities = [] # legacy. to be removed self.context_entities = [] # legacy. to be removed
self.reactions_by_prod = None self.reactions_by_prod = None
self.max_concentration = 0 self.max_concentration = 0
self.max_conc_per_ent = dict() self.max_conc_per_ent = dict()
def add_bg_set_entity(self, e): def add_bg_set_entity(self, e):
name = "" name = ""
def_max_conc = -1 def_max_conc = -1
if type(e) is tuple and len(e) == 2: if type(e) is tuple and len(e) == 2:
name,def_max_conc = e name, def_max_conc = e
elif type(e) is str: elif type(e) is str:
name = e name = e
print("\nWARNING: no maximal concentration level specified for:", e, "\n") print("\nWARNING: no maximal concentration level specified for:", e, "\n")
else: else:
raise RuntimeError("Bad entity type when adding background set element") raise RuntimeError(
"Bad entity type when adding background set element")
self.assume_not_in_bgset(name) self.assume_not_in_bgset(name)
self.background_set.append(name) self.background_set.append(name)
@@ -39,7 +41,7 @@ class ReactionSystemWithConcentrations(ReactionSystem):
self.max_concentration = def_max_conc self.max_concentration = def_max_conc
def get_max_concentration_level(self, e): def get_max_concentration_level(self, e):
if e in self.max_conc_per_ent: if e in self.max_conc_per_ent:
return self.max_conc_per_ent[e] return self.max_conc_per_ent[e]
else: else:
@@ -47,102 +49,108 @@ class ReactionSystemWithConcentrations(ReactionSystem):
def is_valid_entity_with_concentration(self, e): def is_valid_entity_with_concentration(self, e):
"""Sanity check for entities with concentration""" """Sanity check for entities with concentration"""
if type(e) is tuple: if type(e) is tuple:
if len(e) == 2 and type(e[1]) is int: if len(e) == 2 and type(e[1]) is int:
return True return True
if type(e) is list: if type(e) is list:
if len(e) == 2 and type(e[1]) is int: if len(e) == 2 and type(e[1]) is int:
return True return True
print("FATAL. Invalid entity+concentration: {:s}".format(e)) print("FATAL. Invalid entity+concentration: {:s}".format(e))
exit(1) exit(1)
return False return False
def get_state_ids(self, state): def get_state_ids(self, state):
"""Returns entities of the given state without levels""" """Returns entities of the given state without levels"""
return [e for e,c in state] return [e for e, c in state]
def has_non_zero_concentration(self, elem): def has_non_zero_concentration(self, elem):
if elem[1] < 1: if elem[1] < 1:
raise RuntimeError("Unexpected concentration level in state: " + str(elem)) raise RuntimeError(
"Unexpected concentration level in state: " + str(elem))
def process_rip(self, R, I, P, ignore_empty_R=False): def process_rip(self, R, I, P, ignore_empty_R=False):
"""Chcecks concentration levels and converts entities names into their ids""" """Chcecks concentration levels and converts entities names into their ids"""
if R == [] and not ignore_empty_R: if R == [] and not ignore_empty_R:
raise RuntimeError("No reactants defined") raise RuntimeError("No reactants defined")
reactants = [] reactants = []
for r in R: for r in R:
self.is_valid_entity_with_concentration(r) self.is_valid_entity_with_concentration(r)
self.has_non_zero_concentration(r) self.has_non_zero_concentration(r)
entity,level = r entity, level = r
reactants.append((self.get_entity_id(entity),level)) reactants.append((self.get_entity_id(entity), level))
if self.max_concentration < level: if self.max_concentration < level:
self.max_concentration = level self.max_concentration = level
inhibitors = [] inhibitors = []
for i in I: for i in I:
self.is_valid_entity_with_concentration(i) self.is_valid_entity_with_concentration(i)
self.has_non_zero_concentration(i) self.has_non_zero_concentration(i)
entity,level = i entity, level = i
inhibitors.append((self.get_entity_id(entity),level)) inhibitors.append((self.get_entity_id(entity), level))
if self.max_concentration < level: if self.max_concentration < level:
self.max_concentration = level self.max_concentration = level
products = [] products = []
for p in P: for p in P:
self.is_valid_entity_with_concentration(p) self.is_valid_entity_with_concentration(p)
self.has_non_zero_concentration(p) self.has_non_zero_concentration(p)
entity,level = p entity, level = p
products.append((self.get_entity_id(entity),level)) products.append((self.get_entity_id(entity), level))
return reactants,inhibitors,products return reactants, inhibitors, products
def add_reaction(self, R, I, P): def add_reaction(self, R, I, P):
"""Adds a reaction""" """Adds a reaction"""
if P == []: if P == []:
raise RuntimeError("No products defined") raise RuntimeError("No products defined")
reaction = self.process_rip(R,I,P) reaction = self.process_rip(R, I, P)
self.reactions.append(reaction) self.reactions.append(reaction)
def add_reaction_without_reactants(self, R, I, P): def add_reaction_without_reactants(self, R, I, P):
"""Adds a reaction""" """Adds a reaction"""
if P == []: if P == []:
raise RuntimeError("No products defined") raise RuntimeError("No products defined")
reaction = self.process_rip(R,I,P,ignore_empty_R=True) reaction = self.process_rip(R, I, P, ignore_empty_R=True)
self.reactions.append(reaction) self.reactions.append(reaction)
def add_reaction_inc(self, incr_entity, incrementer, R, I): def add_reaction_inc(self, incr_entity, incrementer, R, I):
"""Adds a macro/meta reaction for increasing the value of incr_entity""" """Adds a macro/meta reaction for increasing the value of incr_entity"""
reactants,inhibitors,products = self.process_rip(R,I,[],ignore_empty_R=True) reactants, inhibitors, products = self.process_rip(
R, I, [], ignore_empty_R=True)
incr_entity_id = self.get_entity_id(incr_entity) incr_entity_id = self.get_entity_id(incr_entity)
self.meta_reactions.setdefault(incr_entity_id,[]) self.meta_reactions.setdefault(incr_entity_id, [])
self.meta_reactions[incr_entity_id].append(("inc", self.get_entity_id(incrementer), reactants, inhibitors)) self.meta_reactions[incr_entity_id].append(
("inc", self.get_entity_id(incrementer), reactants, inhibitors))
def add_reaction_dec(self, decr_entity, decrementer, R, I): def add_reaction_dec(self, decr_entity, decrementer, R, I):
"""Adds a macro/meta reaction for decreasing the value of incr_entity""" """Adds a macro/meta reaction for decreasing the value of incr_entity"""
reactants,inhibitors,products = self.process_rip(R,I,[],ignore_empty_R=True) reactants, inhibitors, products = self.process_rip(
R, I, [], ignore_empty_R=True)
decr_entity_id = self.get_entity_id(decr_entity) decr_entity_id = self.get_entity_id(decr_entity)
self.meta_reactions.setdefault(decr_entity_id,[]) self.meta_reactions.setdefault(decr_entity_id, [])
self.meta_reactions[decr_entity_id].append(("dec", self.get_entity_id(decrementer), reactants, inhibitors)) self.meta_reactions[decr_entity_id].append(
("dec", self.get_entity_id(decrementer), reactants, inhibitors))
def add_permanency(self, ent, I): def add_permanency(self, ent, I):
"""Sets entity to be permanent unless it is inhibited""" """Sets entity to be permanent unless it is inhibited"""
ent_id = self.get_entity_id(ent) ent_id = self.get_entity_id(ent)
if ent_id in self.permanent_entities: if ent_id in self.permanent_entities:
raise RuntimeError("Permanency for {0} already defined.".format(ent)) raise RuntimeError(
"Permanency for {0} already defined.".format(ent))
inhibitors = self.process_rip([],I,[],ignore_empty_R=True)[1]
inhibitors = self.process_rip([], I, [], ignore_empty_R=True)[1]
self.permanent_entities[ent_id] = inhibitors self.permanent_entities[ent_id] = inhibitors
def set_context_entities(self, entities): def set_context_entities(self, entities):
raise NotImplementedError raise NotImplementedError
@@ -162,33 +170,38 @@ class ReactionSystemWithConcentrations(ReactionSystem):
def state_to_str(self, state): def state_to_str(self, state):
s = "" s = ""
for ent,level in state: for ent, level in state:
s += self.get_entity_name(ent) + "=" + str(level) + ", " s += self.get_entity_name(ent) + "=" + str(level) + ", "
s = s[:-2] s = s[:-2]
return s return s
def show_background_set(self): def show_background_set(self):
print(C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}") print(
C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}")
def show_meta_reactions(self): def show_meta_reactions(self):
print(C_MARK_INFO + " Meta reactions:") print(C_MARK_INFO + " Meta reactions:")
for param_ent,reactions in self.meta_reactions.items(): for param_ent, reactions in self.meta_reactions.items():
for r_type,command,reactants,inhibitors in reactions: for r_type, command, reactants, inhibitors in reactions:
if r_type == "inc" or r_type == "dec": if r_type == "inc" or r_type == "dec":
print(" - [ Type=" + repr(r_type) + " Operand=( " + self.get_entity_name(param_ent) + \ print(" - [ Type=" + repr(r_type) + " Operand=( " + self.get_entity_name(param_ent) + " ) Command=( " + self.get_entity_name(
" ) Command=( " + self.get_entity_name(command) + " ) ] -- ( R={" + self.state_to_str(reactants) + "}, I={" + self.state_to_str(inhibitors) + "} )") command) + " ) ] -- ( R={" + self.state_to_str(reactants) + "}, I={" + self.state_to_str(inhibitors) + "} )")
else: else:
raise RuntimeError("Unknown meta-reaction type: " + repr(r_type)) raise RuntimeError(
"Unknown meta-reaction type: " + repr(r_type))
def show_max_concentrations(self): def show_max_concentrations(self):
print(C_MARK_INFO + " Maximal allowed concentration levels (for optimized translation to RS):") print(
for e,max_conc in self.max_conc_per_ent.items(): C_MARK_INFO +
print(" - {0:^20} = {1:<6}".format(self.get_entity_name(e),max_conc)) " Maximal allowed concentration levels (for optimized translation to RS):")
for e, max_conc in self.max_conc_per_ent.items():
print(" - {0:^20} = {1:<6}".format(self.get_entity_name(e), max_conc))
def show_permanent_entities(self): def show_permanent_entities(self):
print(C_MARK_INFO + " Permanent entities:") print(C_MARK_INFO + " Permanent entities:")
for e,inhibitors in self.permanent_entities.items(): for e, inhibitors in self.permanent_entities.items():
print(" - {0:^20}{1:<6}".format(self.get_entity_name(e) + ": ","I={" + self.state_to_str(inhibitors) + "}")) print(" - {0:^20}{1:<6}".format(self.get_entity_name(e) + ": ",
"I={" + self.state_to_str(inhibitors) + "}"))
def show(self, soft=False): def show(self, soft=False):
self.show_background_set() self.show_background_set()
@@ -196,7 +209,7 @@ class ReactionSystemWithConcentrations(ReactionSystem):
self.show_permanent_entities() self.show_permanent_entities()
self.show_meta_reactions() self.show_meta_reactions()
self.show_max_concentrations() self.show_max_concentrations()
def get_reactions_by_product(self): def get_reactions_by_product(self):
"""Sorts reactions by their products and returns a dictionary of products""" """Sorts reactions by their products and returns a dictionary of products"""
@@ -206,8 +219,9 @@ class ReactionSystemWithConcentrations(ReactionSystem):
producible_entities = set() producible_entities = set()
for reaction in self.reactions: for reaction in self.reactions:
product_entities = [e for e,c in reaction[2]] product_entities = [e for e, c in reaction[2]]
producible_entities = producible_entities.union(set(product_entities)) producible_entities = producible_entities.union(
set(product_entities))
reactions_by_prod = {} reactions_by_prod = {}
@@ -216,29 +230,30 @@ class ReactionSystemWithConcentrations(ReactionSystem):
rcts_for_p_e = reactions_by_prod[p_e] rcts_for_p_e = reactions_by_prod[p_e]
for r in self.reactions: for r in self.reactions:
product_entities = [e for e,c in r[2]] product_entities = [e for e, c in r[2]]
if p_e in product_entities: if p_e in product_entities:
reactants = r[0] reactants = r[0]
inhibitors = r[1] inhibitors = r[1]
products = [(e,c) for e,c in r[2] if e == p_e] products = [(e, c) for e, c in r[2] if e == p_e]
prod_conc = products[0][1] prod_conc = products[0][1]
insert_place = None insert_place = None
# we need to order the reactions w.r.t. the concentration levels produced (increasing order) # we need to order the reactions w.r.t. the concentration levels produced (increasing order)
for i in range(0,len(rcts_for_p_e)): for i in range(0, len(rcts_for_p_e)):
checked_conc = rcts_for_p_e[i][2][0][1] checked_conc = rcts_for_p_e[i][2][0][1]
if prod_conc <= checked_conc: if prod_conc <= checked_conc:
insert_place = i insert_place = i
break break
if insert_place == None: # empty or the is only one element which is smaller than the element being added if insert_place == None: # empty or the is only one element which is smaller than the element being added
rcts_for_p_e.append((reactants, inhibitors, products)) # we append (to the end) # we append (to the end)
rcts_for_p_e.append((reactants, inhibitors, products))
else: else:
rcts_for_p_e.insert(insert_place,(reactants, inhibitors, products)) rcts_for_p_e.insert(
insert_place, (reactants, inhibitors, products))
# save in cache # save in cache
self.reactions_by_prod = reactions_by_prod self.reactions_by_prod = reactions_by_prod
@@ -246,47 +261,47 @@ class ReactionSystemWithConcentrations(ReactionSystem):
return reactions_by_prod return reactions_by_prod
def get_reaction_system(self): def get_reaction_system(self):
rs = ReactionSystem() rs = ReactionSystem()
for reactants,inhibitors,products in self.reactions: for reactants, inhibitors, products in self.reactions:
new_reactants = [] new_reactants = []
new_inhibitors = [] new_inhibitors = []
new_products = [] new_products = []
for ent,conc in reactants: for ent, conc in reactants:
n = self.get_entity_name(ent) + "#" + str(conc) n = self.get_entity_name(ent) + "#" + str(conc)
rs.ensure_bg_set_entity(n) rs.ensure_bg_set_entity(n)
new_reactants.append(n) new_reactants.append(n)
for ent,conc in inhibitors: for ent, conc in inhibitors:
n = self.get_entity_name(ent) + "#" + str(conc) n = self.get_entity_name(ent) + "#" + str(conc)
rs.ensure_bg_set_entity(n) rs.ensure_bg_set_entity(n)
new_inhibitors.append(n) new_inhibitors.append(n)
for ent,conc in products: for ent, conc in products:
for i in range(1,conc+1): for i in range(1, conc+1):
n = self.get_entity_name(ent) + "#" + str(i) n = self.get_entity_name(ent) + "#" + str(i)
rs.ensure_bg_set_entity(n) rs.ensure_bg_set_entity(n)
new_products.append(n) new_products.append(n)
rs.add_reaction(new_reactants,new_inhibitors,new_products) rs.add_reaction(new_reactants, new_inhibitors, new_products)
for param_ent,reactions in self.meta_reactions.items(): for param_ent, reactions in self.meta_reactions.items():
for r_type,command,reactants,inhibitors in reactions: for r_type, command, reactants, inhibitors in reactions:
param_ent_name = self.get_entity_name(param_ent) param_ent_name = self.get_entity_name(param_ent)
new_reactants = [] new_reactants = []
new_inhibitors = [] new_inhibitors = []
for ent,conc in reactants: for ent, conc in reactants:
n = self.get_entity_name(ent) + "#" + str(conc) n = self.get_entity_name(ent) + "#" + str(conc)
rs.ensure_bg_set_entity(n) rs.ensure_bg_set_entity(n)
new_reactants.append(n) new_reactants.append(n)
for ent,conc in inhibitors: for ent, conc in inhibitors:
n = self.get_entity_name(ent) + "#" + str(conc) n = self.get_entity_name(ent) + "#" + str(conc)
rs.ensure_bg_set_entity(n) rs.ensure_bg_set_entity(n)
new_inhibitors.append(n) new_inhibitors.append(n)
@@ -295,84 +310,97 @@ class ReactionSystemWithConcentrations(ReactionSystem):
if command in self.max_conc_per_ent: if command in self.max_conc_per_ent:
max_cmd_c = self.max_conc_per_ent[command] max_cmd_c = self.max_conc_per_ent[command]
else: else:
print("WARNING:\n\tThere is no maximal concentration level defined for " + self.get_entity_name(command)) print(
"WARNING:\n\tThere is no maximal concentration level defined for "
+ self.get_entity_name(command))
print("\tThis is a very bad idea -- expect degraded performance\n") print("\tThis is a very bad idea -- expect degraded performance\n")
for l in range(1,max_cmd_c+1): for l in range(1, max_cmd_c+1):
cmd_ent = self.get_entity_name(command) + "#" + str(l) cmd_ent = self.get_entity_name(command) + "#" + str(l)
rs.ensure_bg_set_entity(cmd_ent) rs.ensure_bg_set_entity(cmd_ent)
if r_type == "inc": if r_type == "inc":
# pre_conc -- predecessor concentration # pre_conc -- predecessor concentration
# succ_conc -- successor concentration concentration # succ_conc -- successor concentration concentration
for i in range(1,self.max_concentration): for i in range(1, self.max_concentration):
pre_conc = param_ent_name + "#" + str(i) pre_conc = param_ent_name + "#" + str(i)
rs.ensure_bg_set_entity(pre_conc) rs.ensure_bg_set_entity(pre_conc)
new_products = [] new_products = []
succ_value = i+l succ_value = i+l
for j in range(1,succ_value+1): for j in range(1, succ_value+1):
if j > self.max_concentration: break if j > self.max_concentration:
break
new_p = param_ent_name + "#" + str(j) new_p = param_ent_name + "#" + str(j)
rs.ensure_bg_set_entity(new_p) rs.ensure_bg_set_entity(new_p)
new_products.append(new_p) new_products.append(new_p)
if new_products != []: if new_products != []:
rs.add_reaction(set(new_reactants + [pre_conc,cmd_ent]), set(new_inhibitors), set(new_products)) rs.add_reaction(
set(new_reactants + [pre_conc, cmd_ent]),
set(new_inhibitors),
set(new_products))
elif r_type == "dec": elif r_type == "dec":
for i in range(1,self.max_concentration+1): for i in range(1, self.max_concentration+1):
pre_conc = param_ent_name + "#" + str(i) pre_conc = param_ent_name + "#" + str(i)
rs.ensure_bg_set_entity(pre_conc) rs.ensure_bg_set_entity(pre_conc)
new_products = [] new_products = []
succ_value = i-l succ_value = i-l
for j in range(1,succ_value+1): for j in range(1, succ_value+1):
if j > self.max_concentration: break if j > self.max_concentration:
break
new_p = param_ent_name + "#" + str(j) new_p = param_ent_name + "#" + str(j)
rs.ensure_bg_set_entity(new_p) rs.ensure_bg_set_entity(new_p)
new_products.append(new_p) new_products.append(new_p)
if new_products != []: if new_products != []:
rs.add_reaction(set(new_reactants + [pre_conc,cmd_ent]), set(new_inhibitors), set(new_products)) rs.add_reaction(
set(new_reactants + [pre_conc, cmd_ent]),
set(new_inhibitors),
set(new_products))
else: else:
raise RuntimeError("Unknown meta-reaction type: " + repr(r_type)) raise RuntimeError(
"Unknown meta-reaction type: " + repr(r_type))
for ent,inhibitors in self.permanent_entities.items():
for ent, inhibitors in self.permanent_entities.items():
max_c = self.max_concentration max_c = self.max_concentration
if ent in self.max_conc_per_ent: if ent in self.max_conc_per_ent:
max_c = self.max_conc_per_ent[ent] max_c = self.max_conc_per_ent[ent]
else: else:
print("WARNING:\n\tThere is no maximal concentration level defined for " + self.get_entity_name(ent)) print(
"WARNING:\n\tThere is no maximal concentration level defined for "
+ self.get_entity_name(ent))
print("\tThis is a very bad idea -- expect degraded performance\n") print("\tThis is a very bad idea -- expect degraded performance\n")
def e_value(i): def e_value(i):
return self.get_entity_name(ent) + "#" + str(i) return self.get_entity_name(ent) + "#" + str(i)
for value in range(1,max_c+1): for value in range(1, max_c+1):
new_reactants = [] new_reactants = []
new_inhibitors = [] new_inhibitors = []
new_products = [] new_products = []
new_reactants = [e_value(value)] new_reactants = [e_value(value)]
for e_inh,conc in inhibitors: for e_inh, conc in inhibitors:
n = self.get_entity_name(e_inh) + "#" + str(conc) n = self.get_entity_name(e_inh) + "#" + str(conc)
rs.ensure_bg_set_entity(n) rs.ensure_bg_set_entity(n)
new_inhibitors.append(n) new_inhibitors.append(n)
for i in range(1,value+1): for i in range(1, value+1):
new_products.append(e_value(i)) new_products.append(e_value(i))
rs.add_reaction(new_reactants,new_inhibitors,new_products) rs.add_reaction(new_reactants, new_inhibitors, new_products)
return rs return rs
class ReactionSystemWithAutomaton(object): class ReactionSystemWithAutomaton(object):
def __init__(self, reaction_system, context_automaton): def __init__(self, reaction_system, context_automaton):
self.rs = reaction_system self.rs = reaction_system
self.ca = context_automaton self.ca = context_automaton
@@ -380,7 +408,7 @@ class ReactionSystemWithAutomaton(object):
def show(self, soft=False): def show(self, soft=False):
self.rs.show(soft) self.rs.show(soft)
self.ca.show() self.ca.show()
def is_with_concentrations(self): def is_with_concentrations(self):
if not isinstance(self.rs, ReactionSystemWithConcentrations): if not isinstance(self.rs, ReactionSystemWithConcentrations):
return False return False
@@ -390,17 +418,16 @@ class ReactionSystemWithAutomaton(object):
def sanity_check(self): def sanity_check(self):
pass pass
def get_ordinary_reaction_system_with_automaton(self): def get_ordinary_reaction_system_with_automaton(self):
if not self.is_with_concentrations(): if not self.is_with_concentrations():
raise RuntimeError("Not RS/CA with concentrations") raise RuntimeError("Not RS/CA with concentrations")
ors = self.rs.get_reaction_system() ors = self.rs.get_reaction_system()
oca = self.ca.get_automaton_with_flat_contexts(ors) oca = self.ca.get_automaton_with_flat_contexts(ors)
return ReactionSystemWithAutomaton(ors, oca) return ReactionSystemWithAutomaton(ors, oca)
# EOF # EOF

View File

@@ -3,20 +3,23 @@ from colour import *
from rs.reaction_system import ReactionSystem from rs.reaction_system import ReactionSystem
class ParameterObj(object): class ParameterObj(object):
def __init__(self, name): def __init__(self, name):
self.name = name self.name = name
def __repr__(self): def __repr__(self):
return "@{0}".format(self.name) return "@{0}".format(self.name)
def is_param(some_object): def is_param(some_object):
if isinstance(some_object, ParameterObj): if isinstance(some_object, ParameterObj):
return True return True
else: else:
return False return False
class ReactionSystemWithConcentrationsParam(ReactionSystem): class ReactionSystemWithConcentrationsParam(ReactionSystem):
def __init__(self): def __init__(self):
@@ -124,7 +127,7 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
reactants.append((self.get_entity_id(entity), level)) reactants.append((self.get_entity_id(entity), level))
if self.max_concentration < level: if self.max_concentration < level:
self.max_concentration = level self.max_concentration = level
# #
# INHIBITORS # INHIBITORS
# #
@@ -139,7 +142,7 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
inhibitors.append((self.get_entity_id(entity), level)) inhibitors.append((self.get_entity_id(entity), level))
if self.max_concentration < level: if self.max_concentration < level:
self.max_concentration = level self.max_concentration = level
# #
# PRODUCTS # PRODUCTS
# #
@@ -161,51 +164,56 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
def add_reaction(self, R, I, P): def add_reaction(self, R, I, P):
"""Adds a reaction """Adds a reaction
R, I, and P are sets of entities (not their IDs) R, I, and P are sets of entities (not their IDs)
""" """
if P == []: if P == []:
raise RuntimeError("No products defined") raise RuntimeError("No products defined")
reaction = self.process_rip(R,I,P) reaction = self.process_rip(R, I, P)
self.reactions.append(reaction) self.reactions.append(reaction)
def add_reaction_without_reactants(self, R, I, P): def add_reaction_without_reactants(self, R, I, P):
"""Adds a reaction""" """Adds a reaction"""
if P == []: if P == []:
raise RuntimeError("No products defined") raise RuntimeError("No products defined")
reaction = self.process_rip(R,I,P,ignore_empty_R=True) reaction = self.process_rip(R, I, P, ignore_empty_R=True)
self.reactions.append(reaction) self.reactions.append(reaction)
def add_reaction_inc(self, incr_entity, incrementer, R, I): def add_reaction_inc(self, incr_entity, incrementer, R, I):
"""Adds a macro/meta reaction for increasing the value of incr_entity""" """Adds a macro/meta reaction for increasing the value of incr_entity"""
reactants,inhibitors,products = self.process_rip(R,I,[],ignore_empty_R=True) reactants, inhibitors, products = self.process_rip(
R, I, [], ignore_empty_R=True)
incr_entity_id = self.get_entity_id(incr_entity) incr_entity_id = self.get_entity_id(incr_entity)
self.meta_reactions.setdefault(incr_entity_id,[]) self.meta_reactions.setdefault(incr_entity_id, [])
self.meta_reactions[incr_entity_id].append(("inc", self.get_entity_id(incrementer), reactants, inhibitors)) self.meta_reactions[incr_entity_id].append(
("inc", self.get_entity_id(incrementer), reactants, inhibitors))
def add_reaction_dec(self, decr_entity, decrementer, R, I): def add_reaction_dec(self, decr_entity, decrementer, R, I):
"""Adds a macro/meta reaction for decreasing the value of incr_entity""" """Adds a macro/meta reaction for decreasing the value of incr_entity"""
reactants,inhibitors,products = self.process_rip(R,I,[],ignore_empty_R=True) reactants, inhibitors, products = self.process_rip(
R, I, [], ignore_empty_R=True)
decr_entity_id = self.get_entity_id(decr_entity) decr_entity_id = self.get_entity_id(decr_entity)
self.meta_reactions.setdefault(decr_entity_id,[]) self.meta_reactions.setdefault(decr_entity_id, [])
self.meta_reactions[decr_entity_id].append(("dec", self.get_entity_id(decrementer), reactants, inhibitors)) self.meta_reactions[decr_entity_id].append(
("dec", self.get_entity_id(decrementer), reactants, inhibitors))
def add_permanency(self, ent, I): def add_permanency(self, ent, I):
"""Sets entity to be permanent unless it is inhibited""" """Sets entity to be permanent unless it is inhibited"""
ent_id = self.get_entity_id(ent) ent_id = self.get_entity_id(ent)
if ent_id in self.permanent_entities: if ent_id in self.permanent_entities:
raise RuntimeError("Permanency for {0} already defined.".format(ent)) raise RuntimeError(
"Permanency for {0} already defined.".format(ent))
inhibitors = self.process_rip([],I,[],ignore_empty_R=True)[1]
inhibitors = self.process_rip([], I, [], ignore_empty_R=True)[1]
self.permanent_entities[ent_id] = inhibitors self.permanent_entities[ent_id] = inhibitors
def set_context_entities(self, entities): def set_context_entities(self, entities):
raise NotImplementedError raise NotImplementedError
@@ -233,33 +241,36 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
return str(state) return str(state)
else: else:
s = "" s = ""
for ent,level in state: for ent, level in state:
s += self.get_entity_name(ent) + "=" + str(level) + ", " s += self.get_entity_name(ent) + "=" + str(level) + ", "
s = s[:-2] s = s[:-2]
return s return s
def show_background_set(self): def show_background_set(self):
print(C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}") print(
C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}")
def show_meta_reactions(self): def show_meta_reactions(self):
print(C_MARK_INFO + " Meta reactions:") print(C_MARK_INFO + " Meta reactions:")
for param_ent,reactions in self.meta_reactions.items(): for param_ent, reactions in self.meta_reactions.items():
for r_type,command,reactants,inhibitors in reactions: for r_type, command, reactants, inhibitors in reactions:
if r_type == "inc" or r_type == "dec": if r_type == "inc" or r_type == "dec":
print(" - [ Type=" + repr(r_type) + " Operand=( " + self.get_entity_name(param_ent) + \ print(" - [ Type=" + repr(r_type) + " Operand=( " + self.get_entity_name(param_ent) + " ) Command=( " + self.get_entity_name(
" ) Command=( " + self.get_entity_name(command) + " ) ] -- ( R={" + self.state_to_str(reactants) + "}, I={" + self.state_to_str(inhibitors) + "} )") command) + " ) ] -- ( R={" + self.state_to_str(reactants) + "}, I={" + self.state_to_str(inhibitors) + "} )")
else: else:
raise RuntimeError("Unknown meta-reaction type: " + repr(r_type)) raise RuntimeError(
"Unknown meta-reaction type: " + repr(r_type))
def show_max_concentrations(self): def show_max_concentrations(self):
print(C_MARK_INFO + " Maximal allowed concentration levels:") print(C_MARK_INFO + " Maximal allowed concentration levels:")
for e,max_conc in self.max_conc_per_ent.items(): for e, max_conc in self.max_conc_per_ent.items():
print(" - {0:^20} = {1:<6}".format(self.get_entity_name(e),max_conc)) print(" - {0:^20} = {1:<6}".format(self.get_entity_name(e), max_conc))
def show_permanent_entities(self): def show_permanent_entities(self):
print(C_MARK_INFO + " Permanent entities:") print(C_MARK_INFO + " Permanent entities:")
for e,inhibitors in self.permanent_entities.items(): for e, inhibitors in self.permanent_entities.items():
print(" - {0:^20}{1:<6}".format(self.get_entity_name(e) + ": ","I={" + self.state_to_str(inhibitors) + "}")) print(" - {0:^20}{1:<6}".format(self.get_entity_name(e) + ": ",
"I={" + self.state_to_str(inhibitors) + "}"))
def show(self, soft=False): def show(self, soft=False):
self.show_background_set() self.show_background_set()
@@ -268,21 +279,22 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
self.show_permanent_entities() self.show_permanent_entities()
self.show_meta_reactions() self.show_meta_reactions()
self.show_max_concentrations() self.show_max_concentrations()
def get_producible_entities(self): def get_producible_entities(self):
""" """
Returns the set of entities that appear as products of Returns the set of entities that appear as products of
reactions. reactions.
""" """
producible_entities = set() producible_entities = set()
for reaction in self.reactions: for reaction in self.reactions:
product_entities = [e for e,c in reaction[2] if c > 0] product_entities = [e for e, c in reaction[2] if c > 0]
producible_entities = producible_entities.union(set(product_entities)) producible_entities = producible_entities.union(
set(product_entities))
return producible_entities return producible_entities
def get_reaction_system(self): def get_reaction_system(self):
""" """
Translates RSC into RS Translates RSC into RS

View File

@@ -1,23 +1,28 @@
from logics import * from logics import *
##### SHORTCUTS # SHORTCUTS
def bag_True(): def bag_True():
return BagDescription.f_TRUE() return BagDescription.f_TRUE()
def bag_entity(name): def bag_entity(name):
return BagDescription.f_entity(name) return BagDescription.f_entity(name)
def get_bag_if_str(arg): def get_bag_if_str(arg):
if isinstance(arg, str): if isinstance(arg, str):
return bag_entity(arg) > 0 return bag_entity(arg) > 0
else: else:
return arg return arg
def bag_Not(a0): def bag_Not(a0):
a0 = get_bag_if_str(a0) a0 = get_bag_if_str(a0)
return BagDescription.f_Not(a0) return BagDescription.f_Not(a0)
def bag_And(*args): def bag_And(*args):
assert len(args) > 1 assert len(args) > 1
last = get_bag_if_str(args[0]) last = get_bag_if_str(args[0])
@@ -25,7 +30,8 @@ def bag_And(*args):
last = BagDescription.f_And( last = BagDescription.f_And(
last, get_bag_if_str(arg)) last, get_bag_if_str(arg))
return last return last
def exact_state(contained_entities, all_entities): def exact_state(contained_entities, all_entities):
""" """
Assumes 0 concentration level for all the Assumes 0 concentration level for all the
@@ -40,32 +46,37 @@ def exact_state(contained_entities, all_entities):
expr.append(ent == 0) expr.append(ent == 0)
if len(expr) > 0: if len(expr) > 0:
last = expr[0] last = expr[0]
for e in expr[1:]: for e in expr[1:]:
last = BagDescription.f_And(last, e) last = BagDescription.f_And(last, e)
return last return last
else: else:
assert False assert False
def ltl_F(ctx_arg, a0): def ltl_F(ctx_arg, a0):
a0 = get_bag_if_str(a0) a0 = get_bag_if_str(a0)
return Formula_rsLTL.f_F(ctx_arg, a0) return Formula_rsLTL.f_F(ctx_arg, a0)
def ltl_G(ctx_arg, a0): def ltl_G(ctx_arg, a0):
a0 = get_bag_if_str(a0) a0 = get_bag_if_str(a0)
return Formula_rsLTL.f_G(ctx_arg, a0) return Formula_rsLTL.f_G(ctx_arg, a0)
def ltl_X(ctx_arg, a0): def ltl_X(ctx_arg, a0):
a0 = get_bag_if_str(a0) a0 = get_bag_if_str(a0)
return Formula_rsLTL.f_X(ctx_arg, a0) return Formula_rsLTL.f_X(ctx_arg, a0)
def ltl_U(ctx_arg, a0, a1): def ltl_U(ctx_arg, a0, a1):
a0 = get_bag_if_str(a0) a0 = get_bag_if_str(a0)
a1 = get_bag_if_str(a1) a1 = get_bag_if_str(a1)
return Formula_rsLTL.f_U(ctx_arg, a0, a1) return Formula_rsLTL.f_U(ctx_arg, a0, a1)
def ltl_And(*args): def ltl_And(*args):
assert len(args) > 1 assert len(args) > 1
last = get_bag_if_str(args[0]) last = get_bag_if_str(args[0])
@@ -73,22 +84,25 @@ def ltl_And(*args):
last = Formula_rsLTL.f_And(last, get_bag_if_str(arg)) last = Formula_rsLTL.f_And(last, get_bag_if_str(arg))
return last return last
def ltl_Not(a0): def ltl_Not(a0):
a0 = get_bag_if_str(a0) a0 = get_bag_if_str(a0)
return Formula_rsLTL.f_Not(a0) return Formula_rsLTL.f_Not(a0)
def ltl_Implies(a0, a1): def ltl_Implies(a0, a1):
a0 = get_bag_if_str(a0) a0 = get_bag_if_str(a0)
a1 = get_bag_if_str(a1) a1 = get_bag_if_str(a1)
return Formula_rsLTL.f_Implies(a0, a1) return Formula_rsLTL.f_Implies(a0, a1)
def param_entity(param, entity_name): def param_entity(param, entity_name):
return ParamConstraint.f_param_ent(param, entity_name) return ParamConstraint.f_param_ent(param, entity_name)
def param_And(*args): def param_And(*args):
assert len(args) > 1 assert len(args) > 1
last = args[0] last = args[0]
for arg in args[1:]: for arg in args[1:]:
last = ParamConstraint.f_And(last, arg) last = ParamConstraint.f_And(last, arg)
return last return last

View File

@@ -48,14 +48,16 @@ def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", parser.add_argument("-v", "--verbose",
help="turn verbosity on", action="store_true") help="turn verbosity on", action="store_true")
parser.add_argument("-o", "--optimise", parser.add_argument("-o", "--optimise",
help="minimise the parametric computation result", action="store_true") help="minimise the parametric computation result",
parser.add_argument("-n", "--scaling-parameter", action="store_true")
parser.add_argument(
"-n", "--scaling-parameter",
help="scaling parameter value (used in some benchmarks)") help="scaling parameter value (used in some benchmarks)")
parser.add_argument("-s", "--special_mode", parser.add_argument("-s", "--special_mode",
help="special mode (used in some benchmarks)") help="special mode (used in some benchmarks)")
args = parser.parse_args() args = parser.parse_args()
@@ -64,6 +66,7 @@ def main():
################################################################## ##################################################################
if __name__ == "__main__": if __name__ == "__main__":
try: try:
if profiling: if profiling:

View File

@@ -3,8 +3,9 @@
import sys import sys
from os import listdir from os import listdir
def proc_files(files): def proc_files(files):
fs = [] fs = []
for f in files: for f in files:
try: try:
@@ -12,14 +13,14 @@ def proc_files(files):
except Exception as exct: except Exception as exct:
print("Failed to read file {:s}".format(f)) print("Failed to read file {:s}".format(f))
sys.exit(1) sys.exit(1)
done = False done = False
result = [] result = []
while not done: while not done:
index = "NONE" index = "NONE"
val_sum = 0 val_sum = 0
for f in fs: for f in fs:
try: try:
line = f.__next__() line = f.__next__()
@@ -28,16 +29,16 @@ def proc_files(files):
break break
sline = line.split() sline = line.split()
assert(len(sline) == 2) assert(len(sline) == 2)
index, value = sline index, value = sline
value = float(value) value = float(value)
val_sum += value val_sum += value
# print(sline) # print(sline)
else: else:
val_avg = val_sum/len(fs) val_avg = val_sum/len(fs)
result.append("{:s}\t{:f}".format(index, val_avg)) result.append("{:s}\t{:f}".format(index, val_avg))
@@ -45,23 +46,24 @@ def proc_files(files):
result.append("") result.append("")
return result return result
def proc_dirs(dirs): def proc_dirs(dirs):
first_dir = dirs[0] first_dir = dirs[0]
for f in listdir(first_dir): for f in listdir(first_dir):
avg_out = proc_files(["{:s}/{:s}".format(d, f) for d in dirs]) avg_out = proc_files(["{:s}/{:s}".format(d, f) for d in dirs])
with open(f, "w") as outfile: with open(f, "w") as outfile:
outfile.write("\n".join(avg_out)) outfile.write("\n".join(avg_out))
def main(): def main():
proc_dirs(sys.argv[1:]) proc_dirs(sys.argv[1:])
# proc_files(sys.argv[1:]) # proc_files(sys.argv[1:])
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -7,14 +7,15 @@ from time import time
from sys import stdout from sys import stdout
import resource import resource
class SmtCheckerRS(object): class SmtCheckerRS(object):
def __init__(self, rsca): def __init__(self, rsca):
rsca.sanity_check() rsca.sanity_check()
self.rs = rsca.rs self.rs = rsca.rs
self.ca = rsca.ca self.ca = rsca.ca
self.v = [] self.v = []
self.v_ctx = [] self.v_ctx = []
@@ -22,7 +23,7 @@ class SmtCheckerRS(object):
self.next_level_to_encode = 0 self.next_level_to_encode = 0
self.solver = Solver() self.solver = Solver()
self.verification_time = None self.verification_time = None
def prepare_all_variables(self): def prepare_all_variables(self):
@@ -31,7 +32,7 @@ class SmtCheckerRS(object):
self.prepare_state_variables() self.prepare_state_variables()
self.prepare_context_variables() self.prepare_context_variables()
self.next_level_to_encode += 1 self.next_level_to_encode += 1
def prepare_context_variables(self): def prepare_context_variables(self):
"""Encodes all the context variables""" """Encodes all the context variables"""
@@ -45,44 +46,46 @@ class SmtCheckerRS(object):
def prepare_rs_state_variables(self): def prepare_rs_state_variables(self):
"""Encodes all the state variables of the reaction system""" """Encodes all the state variables of the reaction system"""
level = self.next_level_to_encode level = self.next_level_to_encode
variables = [] variables = []
for entity in self.rs.background_set: for entity in self.rs.background_set:
variables.append(Bool("L"+str(level)+"_"+entity)) variables.append(Bool("L"+str(level)+"_"+entity))
self.v.append(variables) self.v.append(variables)
def prepare_context_controller_variables(self): def prepare_context_controller_variables(self):
"""Encodes all the variables required for controlling context sequences""" """Encodes all the variables required for controlling context sequences"""
level = self.next_level_to_encode level = self.next_level_to_encode
self.ca_state.append(Int("CA"+str(level)+"_state")) self.ca_state.append(Int("CA"+str(level)+"_state"))
def prepare_state_variables(self): def prepare_state_variables(self):
"""Encodes all the state variables""" """Encodes all the state variables"""
self.prepare_rs_state_variables() self.prepare_rs_state_variables()
self.prepare_context_controller_variables() self.prepare_context_controller_variables()
def enc_rs_init_state(self, level): def enc_rs_init_state(self, level):
"""Encodes the initial state for the reaction system""" """Encodes the initial state for the reaction system"""
rs_init_state_enc = True rs_init_state_enc = True
for v in self.v[level]: for v in self.v[level]:
rs_init_state_enc = simplify(And(rs_init_state_enc, Not(v))) # the initial state is empty # the initial state is empty
rs_init_state_enc = simplify(And(rs_init_state_enc, Not(v)))
return rs_init_state_enc return rs_init_state_enc
def enc_context_controller_init_state(self, level): def enc_context_controller_init_state(self, level):
"""Encodes the initial state for controlling context sequences""" """Encodes the initial state for controlling context sequences"""
return self.ca_state[level] == self.ca.get_init_state_id() return self.ca_state[level] == self.ca.get_init_state_id()
def enc_init_state(self, level): def enc_init_state(self, level):
"""Encodes the initial state at the given level""" """Encodes the initial state at the given level"""
init_state_enc = simplify(And(self.enc_rs_init_state(level), self.enc_context_controller_init_state(level))) init_state_enc = simplify(And(self.enc_rs_init_state(
level), self.enc_context_controller_init_state(level)))
return init_state_enc return init_state_enc
@@ -95,17 +98,18 @@ class SmtCheckerRS(object):
return False return False
enc_rct_prod = False enc_rct_prod = False
for reactants,inhibitors in rcts_for_prod_entity: for reactants, inhibitors in rcts_for_prod_entity:
enc_reactants = True enc_reactants = True
enc_inhibitors = True enc_inhibitors = True
for reactant in reactants: for reactant in reactants:
enc_reactants = simplify(And(enc_reactants, enc_reactants = simplify(And(enc_reactants, Or(
Or(self.v[level][reactant], self.v_ctx[level][reactant]))) self.v[level][reactant], self.v_ctx[level][reactant])))
for inhibitor in inhibitors: for inhibitor in inhibitors:
enc_inhibitors = simplify(And(enc_inhibitors, enc_inhibitors = simplify(And(enc_inhibitors, Not(
Not(Or(self.v[level][inhibitor], self.v_ctx[level][inhibitor])))) Or(self.v[level][inhibitor], self.v_ctx[level][inhibitor]))))
enc_rct_prod = simplify(Or(enc_rct_prod, And(enc_reactants, enc_inhibitors))) enc_rct_prod = simplify(
Or(enc_rct_prod, And(enc_reactants, enc_inhibitors)))
return enc_rct_prod return enc_rct_prod
@@ -114,15 +118,19 @@ class SmtCheckerRS(object):
enc_enab_cond = self.enc_enabledness(level, prod_entity) enc_enab_cond = self.enc_enabledness(level, prod_entity)
enc_ent_prod = Or(And(enc_enab_cond, self.v[level+1][prod_entity]), enc_ent_prod = Or(
And(Not(enc_enab_cond), Not(self.v[level+1][prod_entity]))) And(enc_enab_cond, self.v[level + 1][prod_entity]),
And(Not(enc_enab_cond),
Not(self.v[level + 1][prod_entity])))
return simplify(enc_ent_prod) return simplify(enc_ent_prod)
def enc_transition_relation(self, level): def enc_transition_relation(self, level):
"""Encodes the combined transition relation""" """Encodes the combined transition relation"""
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_rs_trans(self, level): def enc_rs_trans(self, level):
"""Encodes the transition relation""" """Encodes the transition relation"""
@@ -133,43 +141,46 @@ class SmtCheckerRS(object):
for prod_entity in self.rs.get_reactions_by_product(): for prod_entity in self.rs.get_reactions_by_product():
unused_entities.remove(prod_entity) unused_entities.remove(prod_entity)
enc_trans = simplify(And(enc_trans, self.enc_entity_production(level, prod_entity))) enc_trans = simplify(
And(enc_trans, self.enc_entity_production(level, prod_entity)))
for prod_entity in unused_entities: for prod_entity in unused_entities:
enc_trans = simplify(And(enc_trans, Not(self.v[level+1][prod_entity]))) enc_trans = simplify(
And(enc_trans, Not(self.v[level+1][prod_entity])))
return enc_trans return enc_trans
def enc_automaton_single_trans(self, level, transition): def enc_automaton_single_trans(self, level, transition):
src,ctx,dst = transition src, ctx, dst = transition
src_enc = self.ca_state[level] == src src_enc = self.ca_state[level] == src
dst_enc = self.ca_state[level+1] == dst dst_enc = self.ca_state[level+1] == dst
all_ent = set(range(len(self.rs.background_set))) all_ent = set(range(len(self.rs.background_set)))
incl_ctx = ctx incl_ctx = ctx
excl_ctx = all_ent - incl_ctx excl_ctx = all_ent - incl_ctx
ctx_enc = True ctx_enc = True
for c in incl_ctx: for c in incl_ctx:
ctx_enc = simplify(And(ctx_enc, self.v_ctx[level][c])) ctx_enc = simplify(And(ctx_enc, self.v_ctx[level][c]))
for c in excl_ctx: for c in excl_ctx:
ctx_enc = simplify(And(ctx_enc, Not(self.v_ctx[level][c]))) ctx_enc = simplify(And(ctx_enc, Not(self.v_ctx[level][c])))
enc_single_trans = simplify(And(src_enc, ctx_enc, dst_enc)) enc_single_trans = simplify(And(src_enc, ctx_enc, dst_enc))
return enc_single_trans return enc_single_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_trans = False enc_trans = False
for transition in self.ca.transitions: for transition in self.ca.transitions:
enc_trans = simplify(Or(enc_trans, self.enc_automaton_single_trans(level, transition))) enc_trans = simplify(
Or(enc_trans, self.enc_automaton_single_trans(level, transition)))
return enc_trans return enc_trans
def enc_state(self, level, state): def enc_state(self, level, state):
@@ -201,14 +212,14 @@ class SmtCheckerRS(object):
enc = And(enc, self.v[level][entity]) enc = And(enc, self.v[level][entity])
return enc return enc
def enc_state_with_blocking(self, level, prop): def enc_state_with_blocking(self, level, prop):
"""Encodes the state at the given level with blocking certain concentrations""" """Encodes the state at the given level with blocking certain concentrations"""
required,blocked = prop required, blocked = prop
enc = True enc = True
required_ids = self.rs.get_state_ids(required) required_ids = self.rs.get_state_ids(required)
blocked_ids = self.rs.get_state_ids(blocked) blocked_ids = self.rs.get_state_ids(blocked)
@@ -219,7 +230,6 @@ class SmtCheckerRS(object):
return simplify(enc) return simplify(enc)
def decode_witness(self, max_level, print_model=False): def decode_witness(self, max_level, print_model=False):
m = self.solver.model() m = self.solver.model()
@@ -245,11 +255,12 @@ class SmtCheckerRS(object):
print(" " + self.rs.get_entity_name(var_id), end="") print(" " + self.rs.get_entity_name(var_id), end="")
print(" }") print(" }")
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):
"""Main testing function""" """Main testing function"""
if not type(state) is tuple: if not type(state) is tuple:
state = (state,[]) state = (state, [])
if print_time: if print_time:
# start = time() # start = time()
@@ -266,9 +277,9 @@ class SmtCheckerRS(object):
self.prepare_all_variables() self.prepare_all_variables()
# reachability test: # reachability test:
print("[i] Adding the reachability test...") print("[i] Adding the reachability test...")
self.solver.push() self.solver.push()
self.solver.add(self.enc_state_with_blocking(current_level,state)) self.solver.add(self.enc_state_with_blocking(current_level, state))
result = self.solver.check() result = self.solver.check()
if result == sat: if result == sat:
@@ -278,7 +289,7 @@ class SmtCheckerRS(object):
break break
else: else:
self.solver.pop() self.solver.pop()
print("[i] Unrolling the transition relation") print("[i] Unrolling the transition relation")
self.solver.add(self.enc_transition_relation(current_level)) self.solver.add(self.enc_transition_relation(current_level))
@@ -291,9 +302,13 @@ class SmtCheckerRS(object):
self.verification_time = stop-start self.verification_time = stop-start
print() print()
print("[i] Time: " + repr(self.verification_time)) print("[i] Time: " + repr(self.verification_time))
if print_mem: if print_mem:
print("[i] Memory: " + repr(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/(1024*1024)) + " MB") print(
"[i] Memory: " +
repr(
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss /
(1024 * 1024)) + " MB")
def get_verification_time(self): def get_verification_time(self):
return self.verification_time return self.verification_time

View File

@@ -14,6 +14,7 @@ from logics import rsLTL_Encoder
# def simplify(x): # def simplify(x):
# return x # return x
class SmtCheckerRSC(object): class SmtCheckerRSC(object):
def __init__(self, rsca): def __init__(self, rsca):
@@ -22,38 +23,38 @@ class SmtCheckerRSC(object):
if not rsca.is_with_concentrations(): if not rsca.is_with_concentrations():
raise RuntimeError("RS and CA with concentrations expected") raise RuntimeError("RS and CA with concentrations expected")
self.rs = rsca.rs self.rs = rsca.rs
self.ca = rsca.ca self.ca = rsca.ca
self.initialise() self.initialise()
def initialise(self): def initialise(self):
"""Initialises all the variables used by the checker""" """Initialises all the variables used by the checker"""
self.v = [] self.v = []
self.v_ctx = [] self.v_ctx = []
self.ca_state = [] self.ca_state = []
self.next_level_to_encode = 0 self.next_level_to_encode = 0
self.loop_position = Int("loop_position") self.loop_position = Int("loop_position")
self.solver = Solver() #For("QF_FD") self.solver = Solver() # For("QF_FD")
self.verification_time = None self.verification_time = None
def reset(self): def reset(self):
"""Reinitialises the state of the checker""" """Reinitialises the state of the checker"""
self.initialise() self.initialise()
def prepare_all_variables(self): def prepare_all_variables(self):
"""Encodes all the variables""" """Encodes all the variables"""
self.prepare_state_variables() self.prepare_state_variables()
self.prepare_context_variables() self.prepare_context_variables()
self.next_level_to_encode += 1 self.next_level_to_encode += 1
def prepare_context_variables(self): def prepare_context_variables(self):
"""Encodes all the context variables""" """Encodes all the context variables"""
@@ -74,24 +75,25 @@ class SmtCheckerRSC(object):
for entity in self.rs.background_set: for entity in self.rs.background_set:
variables.append(Int("L"+str(level)+"_"+entity)) variables.append(Int("L"+str(level)+"_"+entity))
self.v.append(variables) self.v.append(variables)
self.ca_state.append(Int("CA"+str(level)+"_state")) self.ca_state.append(Int("CA"+str(level)+"_state"))
def enc_concentration_levels_assertion(self, level): def enc_concentration_levels_assertion(self, level):
"""Encodes assertions that (some) variables need to be >0 """Encodes assertions that (some) variables need to be >0
We do not need to actually control all the variables, We do not need to actually control all the variables,
only those that can possibly go below 0. only those that can possibly go below 0.
""" """
enc_nz = True enc_nz = True
for e_i in range(len(self.rs.background_set)): for e_i in range(len(self.rs.background_set)):
v = self.v[level][e_i] v = self.v[level][e_i]
v_ctx = self.v_ctx[level][e_i] v_ctx = self.v_ctx[level][e_i]
e_max = self.rs.get_max_concentration_level(e_i) e_max = self.rs.get_max_concentration_level(e_i)
enc_nz = simplify(And(enc_nz, v >= 0, v_ctx >= 0, v <= e_max, v_ctx <= e_max)) enc_nz = simplify(
And(enc_nz, v >= 0, v_ctx >= 0, v <= e_max, v_ctx <= e_max))
return enc_nz return enc_nz
def enc_init_state(self, level): def enc_init_state(self, level):
@@ -100,10 +102,11 @@ class SmtCheckerRSC(object):
rs_init_state_enc = True rs_init_state_enc = True
for v in self.v[level]: for v in self.v[level]:
rs_init_state_enc = simplify(And(rs_init_state_enc, v == 0)) # the initial concentration levels are zeroed # the initial concentration levels are zeroed
rs_init_state_enc = simplify(And(rs_init_state_enc, v == 0))
ca_init_state_enc = self.ca_state[level] == self.ca.get_init_state_id() ca_init_state_enc = self.ca_state[level] == self.ca.get_init_state_id()
init_state_enc = simplify(And(rs_init_state_enc, ca_init_state_enc)) init_state_enc = simplify(And(rs_init_state_enc, ca_init_state_enc))
return init_state_enc return init_state_enc
@@ -113,112 +116,155 @@ class SmtCheckerRSC(object):
rcts_for_prod_entity = [] rcts_for_prod_entity = []
if prod_entity in self.rs.get_reactions_by_product(): if prod_entity in self.rs.get_reactions_by_product():
rcts_for_prod_entity = self.rs.get_reactions_by_product()[prod_entity] rcts_for_prod_entity = self.rs.get_reactions_by_product()[
prod_entity]
meta_reactions = [] meta_reactions = []
if prod_entity in self.rs.meta_reactions: if prod_entity in self.rs.meta_reactions:
meta_reactions = self.rs.meta_reactions[prod_entity] meta_reactions = self.rs.meta_reactions[prod_entity]
permanency_inhibition = None permanency_inhibition = None
if prod_entity in self.rs.permanent_entities: if prod_entity in self.rs.permanent_entities:
permanency_inhibition = self.rs.permanent_entities[prod_entity] permanency_inhibition = self.rs.permanent_entities[prod_entity]
if rcts_for_prod_entity == [] and meta_reactions == []: if rcts_for_prod_entity == [] and meta_reactions == []:
return simplify(self.v[level+1][prod_entity] == 0) # this should never happen # this should never happen
return simplify(self.v[level+1][prod_entity] == 0)
enc_enabledness = False enc_enabledness = False
# ----------- ordinary reactions -------------------------------------------- # ----------- ordinary reactions --------------------------------------------
enc_rct_prod = False enc_rct_prod = False
enc_ordinary_reactions_enabledness = False enc_ordinary_reactions_enabledness = False
for reactants,inhibitors,products in rcts_for_prod_entity:
enc_reactants = True for reactants, inhibitors, products in rcts_for_prod_entity:
for reactant,concentration in reactants:
enc_reactants = simplify(And(enc_reactants, enc_reactants = True
Or(self.v[level][reactant] >= concentration, self.v_ctx[level][reactant] >= concentration))) for reactant, concentration in reactants:
enc_reactants = simplify(And(enc_reactants, Or(
self.v[level][reactant] >= concentration, self.v_ctx[level][reactant] >= concentration)))
enc_inhibitors = True
for inhibitor, concentration in inhibitors:
enc_inhibitors = simplify(And(enc_inhibitors, And(
self.v[level][inhibitor] < concentration, self.v_ctx[level][inhibitor] < concentration)))
enc_inhibitors = True
for inhibitor,concentration in inhibitors:
enc_inhibitors = simplify(And(enc_inhibitors,
And(self.v[level][inhibitor] < concentration, self.v_ctx[level][inhibitor] < concentration)))
enc_rct_enabled = And(enc_reactants, enc_inhibitors) enc_rct_enabled = And(enc_reactants, enc_inhibitors)
enc_products = self.v[level+1][products[0][0]] == products[0][1] enc_products = self.v[level+1][products[0][0]] == products[0][1]
enc_rct_prod = simplify(If(enc_rct_enabled, enc_products, enc_rct_prod)) enc_rct_prod = simplify(
If(enc_rct_enabled, enc_products, enc_rct_prod))
enc_enabledness = simplify(Or(enc_enabledness, enc_rct_enabled)) enc_enabledness = simplify(Or(enc_enabledness, enc_rct_enabled))
enc_ordinary_reactions_enabledness = simplify(Or(enc_ordinary_reactions_enabledness,enc_rct_enabled)) enc_ordinary_reactions_enabledness = simplify(
Or(enc_ordinary_reactions_enabledness, enc_rct_enabled))
# -------- meta reactions --------------------------------------------------- # -------- meta reactions ---------------------------------------------------
for r_type,command_entity,reactants,inhibitors in meta_reactions: for r_type, command_entity, reactants, inhibitors in meta_reactions:
# command entity is e.g. 'inc' for incrementation operation # command entity is e.g. 'inc' for incrementation operation
# (inc,W) gives us the value W by which the given entity's value should be incremented # (inc,W) gives us the value W by which the given entity's value should be incremented
enc_reactants = True enc_reactants = True
enc_inhibitors = True enc_inhibitors = True
for reactant,concentration in reactants: for reactant, concentration in reactants:
enc_reactants = simplify(And(enc_reactants, enc_reactants = simplify(And(enc_reactants, Or(
Or(self.v[level][reactant] >= concentration, self.v_ctx[level][reactant] >= concentration))) self.v[level][reactant] >= concentration, self.v_ctx[level][reactant] >= concentration)))
# command entity needs to be present (with concentration level > 0) in order to perform the operation # command entity needs to be present (with concentration level > 0) in order to perform the operation
enc_reactants = simplify(And(enc_reactants, enc_reactants = simplify(And(enc_reactants, Or(
Or(self.v[level][command_entity] > 0, self.v_ctx[level][command_entity] > 0))) self.v[level][command_entity] > 0, self.v_ctx[level][command_entity] > 0)))
for inhibitor, concentration in inhibitors:
enc_inhibitors = simplify(And(enc_inhibitors, And(
self.v[level][inhibitor] < concentration, self.v_ctx[level][inhibitor] < concentration)))
for inhibitor,concentration in inhibitors:
enc_inhibitors = simplify(And(enc_inhibitors,
And(self.v[level][inhibitor] < concentration, self.v_ctx[level][inhibitor] < concentration)))
if r_type == "inc": if r_type == "inc":
value_after_inc = If(self.v[level][prod_entity]>self.v_ctx[level][prod_entity],self.v[level][prod_entity],self.v_ctx[level][prod_entity]) + \ value_after_inc = If(
If(self.v[level][command_entity]>self.v_ctx[level][command_entity],self.v[level][command_entity],self.v_ctx[level][command_entity]) self.v[level][prod_entity] > self.v_ctx[level]
[prod_entity],
self.v[level][prod_entity],
self.v_ctx[level][prod_entity]) + If(
self.v[level][command_entity] > self.
v_ctx[level][command_entity],
self.v[level][command_entity],
self.v_ctx[level][command_entity])
enc_products = self.v[level+1][prod_entity] == value_after_inc enc_products = self.v[level+1][prod_entity] == value_after_inc
elif r_type == "dec": elif r_type == "dec":
value_after_dec = simplify(If(self.v[level][prod_entity]>self.v_ctx[level][prod_entity],self.v[level][prod_entity],self.v_ctx[level][prod_entity]) - \ value_after_dec = simplify(
If(self.v[level][command_entity]>self.v_ctx[level][command_entity],self.v[level][command_entity],self.v_ctx[level][command_entity])) If(
enc_products = self.v[level+1][prod_entity] == If(value_after_dec < 0, 0, value_after_dec) self.v[level][prod_entity] >
self.v_ctx[level]
[prod_entity],
self.v[level][prod_entity],
self.v_ctx[level]
[prod_entity]) -
If(
self.v[level]
[command_entity] > self.
v_ctx[level][command_entity],
self.v[level]
[command_entity],
self.v_ctx[level]
[command_entity]))
enc_products = self.v[level+1][prod_entity] == If(
value_after_dec < 0, 0, value_after_dec)
else: else:
raise RuntimeError("Unknown meta-reaction type: " + repr(r_type)) raise RuntimeError(
"Unknown meta-reaction type: " + repr(r_type))
enc_meta_reaction_enabledness = And(enc_reactants, enc_inhibitors, Not(enc_ordinary_reactions_enabledness)) enc_meta_reaction_enabledness = And(
enc_enabledness = simplify(Or(enc_enabledness, enc_meta_reaction_enabledness)) enc_reactants, enc_inhibitors,
enc_rct_prod = simplify(Or(enc_rct_prod, And(enc_meta_reaction_enabledness, enc_products))) Not(enc_ordinary_reactions_enabledness))
enc_enabledness = simplify(
Or(enc_enabledness, enc_meta_reaction_enabledness))
enc_rct_prod = simplify(Or(enc_rct_prod, And(
enc_meta_reaction_enabledness, enc_products)))
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
if not permanency_inhibition == None: if not permanency_inhibition == None:
enc_reactants = Or(self.v[level][prod_entity] >= concentration, self.v_ctx[level][prod_entity] >= concentration) enc_reactants = Or(self.v[level][prod_entity] >= concentration,
self.v_ctx[level][prod_entity] >= concentration)
enc_inhibitors = True enc_inhibitors = True
for inhibitor,concentration in permanency_inhibition: for inhibitor, concentration in permanency_inhibition:
enc_inhibitors = simplify(And(enc_inhibitors, enc_inhibitors = simplify(And(enc_inhibitors, And(
And(self.v[level][inhibitor] < concentration, self.v_ctx[level][inhibitor] < concentration))) self.v[level][inhibitor] < concentration, self.v_ctx[level][inhibitor] < concentration)))
enc_products = simplify(self.v[level+1][prod_entity] == \ enc_products = simplify(
If(self.v[level][prod_entity] > self.v_ctx[level][prod_entity],self.v[level][prod_entity],self.v_ctx[level][prod_entity])) self.v[level + 1][prod_entity] ==
If(
self.v[level][prod_entity] > self.v_ctx[level]
[prod_entity],
self.v[level][prod_entity],
self.v_ctx[level][prod_entity]))
enc_permanency_enabledness = And(enc_reactants, enc_inhibitors, Not(enc_ordinary_reactions_enabledness)) enc_permanency_enabledness = And(
enc_enabledness = simplify(Or(enc_enabledness, enc_permanency_enabledness)) enc_reactants, enc_inhibitors,
Not(enc_ordinary_reactions_enabledness))
enc_enabledness = simplify(
Or(enc_enabledness, enc_permanency_enabledness))
enc_permanency = And(enc_permanency_enabledness, enc_products) enc_permanency = And(enc_permanency_enabledness, enc_products)
enc_rct_prod = simplify(Or(enc_rct_prod, enc_permanency)) enc_rct_prod = simplify(Or(enc_rct_prod, enc_permanency))
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
enc_when_to_produce_zero_conc = simplify(And(Not(enc_enabledness), self.v[level+1][prod_entity] == 0)) enc_when_to_produce_zero_conc = simplify(
And(Not(enc_enabledness), self.v[level+1][prod_entity] == 0))
enc_rct_prod = Or(enc_rct_prod, enc_when_to_produce_zero_conc) enc_rct_prod = Or(enc_rct_prod, enc_when_to_produce_zero_conc)
return enc_rct_prod return enc_rct_prod
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_rs_trans(self, level): def enc_rs_trans(self, level):
"""Encodes the transition relation""" """Encodes the transition relation"""
@@ -232,38 +278,40 @@ class SmtCheckerRSC(object):
for prod_entity in chain(reactions, meta_reactions): for prod_entity in chain(reactions, meta_reactions):
unused_entities.discard(prod_entity) unused_entities.discard(prod_entity)
enc_trans = simplify(And(enc_trans, self.enc_produced_concentration(level, prod_entity))) enc_trans = simplify(
And(enc_trans, self.enc_produced_concentration(level, prod_entity)))
for prod_entity in unused_entities: for prod_entity in unused_entities:
enc_trans = simplify(And(enc_trans, self.v[level+1][prod_entity] == 0)) enc_trans = simplify(
And(enc_trans, self.v[level+1][prod_entity] == 0))
return enc_trans return enc_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_trans = False enc_trans = False
for src,ctx,dst in self.ca.transitions: for src, ctx, dst in self.ca.transitions:
src_enc = self.ca_state[level] == src src_enc = self.ca_state[level] == src
dst_enc = self.ca_state[level+1] == dst dst_enc = self.ca_state[level+1] == dst
all_ent = set(range(len(self.rs.background_set))) all_ent = set(range(len(self.rs.background_set)))
incl_ctx = set([e for e,c in ctx]) incl_ctx = set([e for e, c in ctx])
excl_ctx = all_ent - incl_ctx excl_ctx = all_ent - incl_ctx
ctx_enc = True ctx_enc = True
for e,c in ctx: for e, c in ctx:
ctx_enc = simplify(And(ctx_enc, self.v_ctx[level][e] == c)) ctx_enc = simplify(And(ctx_enc, self.v_ctx[level][e] == c))
for e in excl_ctx: for e in excl_ctx:
ctx_enc = simplify(And(ctx_enc, self.v_ctx[level][e] == 0)) ctx_enc = simplify(And(ctx_enc, self.v_ctx[level][e] == 0))
cur_trans = simplify(And(src_enc, ctx_enc, dst_enc)) cur_trans = simplify(And(src_enc, ctx_enc, dst_enc))
enc_trans = simplify(Or(enc_trans, cur_trans)) enc_trans = simplify(Or(enc_trans, cur_trans))
return enc_trans return enc_trans
def enc_exact_state(self, level, state): def enc_exact_state(self, level, state):
@@ -275,7 +323,7 @@ class SmtCheckerRSC(object):
"""Encodes the state at the given level with the minimal required concentration levels""" """Encodes the state at the given level with the minimal required concentration levels"""
enc = True enc = True
for ent,conc in state: for ent, conc in state:
e_id = self.rs.get_entity_id(ent) e_id = self.rs.get_entity_id(ent)
enc = And(enc, self.v[level][e_id] >= conc) enc = And(enc, self.v[level][e_id] >= conc)
@@ -284,16 +332,16 @@ class SmtCheckerRSC(object):
def enc_state_with_blocking(self, level, prop): def enc_state_with_blocking(self, level, prop):
"""Encodes the state at the given level with blocking certain concentrations""" """Encodes the state at the given level with blocking certain concentrations"""
required,blocked = prop required, blocked = prop
enc = True enc = True
for ent,conc in required: for ent, conc in required:
e_id = self.rs.get_entity_id(ent) e_id = self.rs.get_entity_id(ent)
enc = And(enc, self.v[level][e_id] >= conc) enc = And(enc, self.v[level][e_id] >= conc)
for ent,conc in blocked: for ent, conc in blocked:
e_id = self.rs.get_entity_id(ent) e_id = self.rs.get_entity_id(ent)
enc = And(enc, self.v[level][e_id] < conc) enc = And(enc, self.v[level][e_id] < conc)
return simplify(enc) return simplify(enc)
@@ -312,9 +360,12 @@ class SmtCheckerRSC(object):
for var_id in range(len(self.v[level])): for var_id in range(len(self.v[level])):
var_rep = repr(m[self.v[level][var_id]]) var_rep = repr(m[self.v[level][var_id]])
if not var_rep.isdigit(): if not var_rep.isdigit():
raise RuntimeError("unexpected: representation is not a positive integer") raise RuntimeError(
"unexpected: representation is not a positive integer")
if int(var_rep) > 0: if int(var_rep) > 0:
print(" " + self.rs.get_entity_name(var_id) + "=" + var_rep, end="") print(
" " + self.rs.get_entity_name(var_id) + "=" + var_rep,
end="")
# print(" " + repr(m[self.v[level][var_id]]), end="") # print(" " + repr(m[self.v[level][var_id]]), end="")
print(" }") print(" }")
@@ -324,19 +375,25 @@ class SmtCheckerRSC(object):
for var_id in range(len(self.v[level])): for var_id in range(len(self.v[level])):
var_rep = repr(m[self.v_ctx[level][var_id]]) var_rep = repr(m[self.v_ctx[level][var_id]])
if not var_rep.isdigit(): if not var_rep.isdigit():
raise RuntimeError("unexpected: representation is not a positive integer") raise RuntimeError(
"unexpected: representation is not a positive integer")
if int(var_rep) > 0: if int(var_rep) > 0:
print(" " + self.rs.get_entity_name(var_id) + "=" + var_rep, end="") print(
" " + self.rs.get_entity_name(var_id) + "=" + var_rep,
end="")
print(" }") print(" }")
def check_rsltl(self, formula, print_witness=True, print_time=True, print_mem=True, max_level=None): def check_rsltl(
self, formula, print_witness=True, print_time=True, print_mem=True,
max_level=None):
"""Bounded Model Checking for rsLTL properties""" """Bounded Model Checking for rsLTL properties"""
self.reset() self.reset()
print("[" + colour_str(C_BOLD, "i") + "] Running rsLTL bounded model checking") print("[" + colour_str(C_BOLD, "i") +
"] Running rsLTL bounded model checking")
print("[" + colour_str(C_BOLD, "i") + "] Formula: " + str(formula)) print("[" + colour_str(C_BOLD, "i") + "] Formula: " + str(formula))
if print_time: if print_time:
# start = time() # start = time()
start = resource.getrusage(resource.RUSAGE_SELF).ru_utime start = resource.getrusage(resource.RUSAGE_SELF).ru_utime
@@ -346,42 +403,53 @@ class SmtCheckerRSC(object):
self.current_level = 0 self.current_level = 0
self.prepare_all_variables() self.prepare_all_variables()
self.solver.add(self.enc_concentration_levels_assertion(0)) self.solver.add(self.enc_concentration_levels_assertion(0))
encoder = rsLTL_Encoder(self) encoder = rsLTL_Encoder(self)
encoder.load_variables( encoder.load_variables(
var_rs=self.v, var_rs=self.v,
var_ctx=self.v_ctx, var_ctx=self.v_ctx,
var_loop_pos=self.loop_position) var_loop_pos=self.loop_position)
while True: while True:
self.prepare_all_variables() self.prepare_all_variables()
self.solver.add(self.enc_concentration_levels_assertion(self.current_level+1)) self.solver.add(
self.enc_concentration_levels_assertion(
print("\n{:-^70}".format("[ Working at level=" + str(self.current_level) + " ]")) self.current_level + 1))
print(
"\n{:-^70}".format("[ Working at level=" + str(self.current_level) + " ]"))
stdout.flush() stdout.flush()
# reachability test: # reachability test:
self.solver.push() self.solver.push()
print("[" + colour_str(C_BOLD, "i") + "] Generating the formula encoding...") print("[" + colour_str(C_BOLD, "i") +
"] Generating the formula encoding...")
f = encoder.get_encoding(formula, self.current_level) f = encoder.get_encoding(formula, self.current_level)
ncalls = encoder.get_ncalls() ncalls = encoder.get_ncalls()
print("[" + colour_str(C_BOLD, "i") + "] Cache hits: " + str(encoder.get_cache_hits()) + ", encode calls: " + str(ncalls[0]) + " (approx: " + str(ncalls[1]) + ")") print("[" + colour_str(C_BOLD, "i") + "] Cache hits: " +
print("[" + colour_str(C_BOLD, "i") + "] Adding the formula to the solver...") str(encoder.get_cache_hits()) + ", encode calls: " +
str(ncalls[0]) + " (approx: " + str(ncalls[1]) + ")")
print("[" + colour_str(C_BOLD, "i") +
"] Adding the formula to the solver...")
encoder.flush_cache() encoder.flush_cache()
self.solver.add(f) self.solver.add(f)
print("[" + colour_str(C_BOLD, "i") + "] Adding the loops encoding...") print("[" + colour_str(C_BOLD, "i") +
"] Adding the loops encoding...")
self.solver.add(self.get_loop_encodings()) self.solver.add(self.get_loop_encodings())
result = self.solver.check() result = self.solver.check()
if result == sat: if result == sat:
print("[" + colour_str(C_BOLD, "+") + "] " + colour_str(C_GREEN, "SAT at level=" + str(self.current_level))) print(
"[" + colour_str(C_BOLD, "+") + "] " +
colour_str(
C_GREEN, "SAT at level=" + str(self.current_level)))
if print_witness: if print_witness:
print("\n{:=^70}".format("[ WITNESS ]")) print("\n{:=^70}".format("[ WITNESS ]"))
self.decode_witness(self.current_level) self.decode_witness(self.current_level)
@@ -389,10 +457,12 @@ class SmtCheckerRSC(object):
else: else:
self.solver.pop() self.solver.pop()
print("[" + colour_str(C_BOLD, "i") + "] Unrolling the transition relation") print("[" + colour_str(C_BOLD, "i") +
"] Unrolling the transition relation")
self.solver.add(self.enc_transition_relation(self.current_level)) self.solver.add(self.enc_transition_relation(self.current_level))
print("{:->70}".format("[ level=" + str(self.current_level) + " done ]")) print(
"{:->70}".format("[ level=" + str(self.current_level) + " done ]"))
self.current_level += 1 self.current_level += 1
if not max_level is None and self.current_level > max_level: if not max_level is None and self.current_level > max_level:
@@ -404,26 +474,33 @@ class SmtCheckerRSC(object):
stop = resource.getrusage(resource.RUSAGE_SELF).ru_utime stop = resource.getrusage(resource.RUSAGE_SELF).ru_utime
self.verification_time = stop-start self.verification_time = stop-start
print() print()
print("\n[i] {: >60}".format(" Time: " + repr(self.verification_time) + " s")) print(
"\n[i] {: >60}".format(
" Time: " + repr(self.verification_time) + " s"))
if print_mem: if print_mem:
print("[i] {: >60}".format(" Memory: " + repr(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/(1024*1024)) + " MB")) print(
"[i] {: >60}".format(
" Memory: " +
repr(
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss /
(1024 * 1024)) + " MB"))
def dummy_unroll(self, levels): def dummy_unroll(self, levels):
"""Unrolls the variables for testing purposes""" """Unrolls the variables for testing purposes"""
self.current_level = -1 self.current_level = -1
for i in range(levels+1): for i in range(levels+1):
self.prepare_all_variables() self.prepare_all_variables()
self.current_level += 1 self.current_level += 1
print(C_MARK_INFO + " Dummy Unrolling done.") print(C_MARK_INFO + " Dummy Unrolling done.")
def state_equality(self, level_A, level_B): def state_equality(self, level_A, level_B):
"""Encodes equality of two states at two different levels""" """Encodes equality of two states at two different levels"""
eq_enc = True eq_enc = True
for e_i in range(len(self.rs.background_set)): for e_i in range(len(self.rs.background_set)):
e_i_equality = self.v[level_A][e_i] == self.v[level_B][e_i] e_i_equality = self.v[level_A][e_i] == self.v[level_B][e_i]
eq_enc = simplify(And(eq_enc, e_i_equality)) eq_enc = simplify(And(eq_enc, e_i_equality))
@@ -432,27 +509,28 @@ class SmtCheckerRSC(object):
eq_enc = simplify(And(eq_enc, eq_enc_ctxaut)) eq_enc = simplify(And(eq_enc, eq_enc_ctxaut))
return eq_enc return eq_enc
def get_loop_encodings(self): def get_loop_encodings(self):
k = self.current_level k = self.current_level
loop_var = self.loop_position loop_var = self.loop_position
loop_enc = True loop_enc = True
""" """
(loop_var == i) means that there is a loop taking back to the state (i-1) (loop_var == i) means that there is a loop taking back to the state (i-1)
Therefore, the encoding starts at 1, not at 0. Therefore, the encoding starts at 1, not at 0.
""" """
for i in range(1,k+1): for i in range(1, k+1):
loop_enc = simplify(And(loop_enc, Implies( loop_var == i, self.state_equality(i-1, k) ))) loop_enc = simplify(And(loop_enc, Implies(
loop_var == i, self.state_equality(i-1, k))))
return loop_enc return loop_enc
def check_reachability(self, state, print_witness=True, def check_reachability(self, state, print_witness=True,
print_time=True, print_mem=True, max_level=1000): print_time=True, print_mem=True, max_level=1000):
"""Main testing function""" """Main testing function"""
self.reset() self.reset()
@@ -466,25 +544,33 @@ class SmtCheckerRSC(object):
self.current_level = 0 self.current_level = 0
self.prepare_all_variables() self.prepare_all_variables()
self.solver.add(self.enc_concentration_levels_assertion(0)) self.solver.add(self.enc_concentration_levels_assertion(0))
while True: while True:
self.prepare_all_variables() self.prepare_all_variables()
self.solver.add(self.enc_concentration_levels_assertion(self.current_level+1)) self.solver.add(
self.enc_concentration_levels_assertion(
print("\n{:-^70}".format("[ Working at level=" + str(self.current_level) + " ]")) self.current_level + 1))
print(
"\n{:-^70}".format("[ Working at level=" + str(self.current_level) + " ]"))
stdout.flush() stdout.flush()
# reachability test: # reachability test:
print("[" + colour_str(C_BOLD, "i") + "] Adding the reachability test...") print("[" + colour_str(C_BOLD, "i") +
"] Adding the reachability test...")
self.solver.push() self.solver.push()
self.solver.add(self.enc_state_with_blocking(self.current_level,state)) self.solver.add(self.enc_state_with_blocking(
self.current_level, state))
result = self.solver.check() result = self.solver.check()
if result == sat: if result == sat:
print("[" + colour_str(C_BOLD, "+") + "] " + colour_str(C_GREEN, "SAT at level=" + str(self.current_level))) print(
"[" + colour_str(C_BOLD, "+") + "] " +
colour_str(
C_GREEN, "SAT at level=" + str(self.current_level)))
if print_witness: if print_witness:
print("\n{:=^70}".format("[ WITNESS ]")) print("\n{:=^70}".format("[ WITNESS ]"))
self.decode_witness(self.current_level) self.decode_witness(self.current_level)
@@ -492,10 +578,12 @@ class SmtCheckerRSC(object):
else: else:
self.solver.pop() self.solver.pop()
print("[" + colour_str(C_BOLD, "i") + "] Unrolling the transition relation") print("[" + colour_str(C_BOLD, "i") +
"] Unrolling the transition relation")
self.solver.add(self.enc_transition_relation(self.current_level)) self.solver.add(self.enc_transition_relation(self.current_level))
print("{:->70}".format("[ level=" + str(self.current_level) + " done ]")) print(
"{:->70}".format("[ level=" + str(self.current_level) + " done ]"))
self.current_level += 1 self.current_level += 1
if self.current_level > max_level: if self.current_level > max_level:
@@ -507,16 +595,23 @@ class SmtCheckerRSC(object):
stop = resource.getrusage(resource.RUSAGE_SELF).ru_utime stop = resource.getrusage(resource.RUSAGE_SELF).ru_utime
self.verification_time = stop-start self.verification_time = stop-start
print() print()
print("\n[i] {: >60}".format(" Time: " + repr(self.verification_time) + " s")) print(
"\n[i] {: >60}".format(
" Time: " + repr(self.verification_time) + " s"))
if print_mem: if print_mem:
print("[i] {: >60}".format(" Memory: " + repr(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/(1024*1024)) + " MB")) print(
"[i] {: >60}".format(
" Memory: " +
repr(
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss /
(1024 * 1024)) + " MB"))
def get_verification_time(self): def get_verification_time(self):
return self.verification_time return self.verification_time
def show_encoding(self, state, print_witness=True, def show_encoding(self, state, print_witness=True,
print_time=False, print_mem=False, max_level=100): print_time=False, print_mem=False, max_level=100):
"""Encoding debug function""" """Encoding debug function"""
self.reset() self.reset()
@@ -528,25 +623,29 @@ class SmtCheckerRSC(object):
self.current_level = 0 self.current_level = 0
self.prepare_all_variables() self.prepare_all_variables()
while True: while True:
self.prepare_all_variables() self.prepare_all_variables()
print("-----[ Working at level=" + str(self.current_level) + " ]-----") print(
"-----[ Working at level=" + str(self.current_level) + " ]-----")
stdout.flush() stdout.flush()
# reachability test: # reachability test:
print("[i] Adding the reachability test...") print("[i] Adding the reachability test...")
self.solver.push() self.solver.push()
s = self.enc_min_state(self.current_level,state) s = self.enc_min_state(self.current_level, state)
print("Test: ", s) print("Test: ", s)
self.solver.add(s) self.solver.add(s)
result = self.solver.check() result = self.solver.check()
if result == sat: if result == sat:
print("\n[+] " + colour_str(C_RED, "SAT at level=" + str(self.current_level))) print(
"\n[+] " +
colour_str(
C_RED, "SAT at level=" + str(self.current_level)))
if print_witness: if print_witness:
self.decode_witness(self.current_level) self.decode_witness(self.current_level)
break break
@@ -565,8 +664,7 @@ class SmtCheckerRSC(object):
print("Stopping at level=" + str(max_level)) print("Stopping at level=" + str(max_level))
break break
else: else:
x=input("Next level? ") x = input("Next level? ")
x=x.lower() x = x.lower()
if not (x == "y" or x == "yes"): if not (x == "y" or x == "yes"):
break break

File diff suppressed because it is too large Load Diff