def process(): varA = Symbol("A") varB = Symbol("B") f = And(varA, Not(varB)) print(f) print(is_sat(f)) hello = [Symbol(s, INT) for s in "hello"] world = [Symbol(s, INT) for s in "world"] letters = set(hello + world) domains = And(And(LE(Int(1), l), GE(Int(10), l)) for l in letters) print(domains,'domain') sum_hello = Plus(hello) sum_world = Plus(world) problem = And(Equals(sum_hello, sum_world), Equals(sum_hello, Int(36))) formula = And(domains, problem) print("Serialization of the formula:") print(formula) print(formula.serialize()) print(is_sat(formula)) print(get_model(formula))
def _get_param_assignments(self, model, time, parameters, monotonic=True): p_ass = [] fwd = False for p in parameters: p_time = model[TS.get_ptimed(p, 0)] if p.symbol_type() == BOOL: if monotonic: if p_time == TRUE(): p_ass.append(p) else: p_ass.append(p if p_time == TRUE() else Not(p)) else: p_ass.append(EqualsOrIff(p, p_time)) p_ass = And(p_ass) self.region = simplify(Or(self.region, p_ass)) if self.models is None: self.models = [] self.models.append((model, time)) Logger.msg("+", 0, not (Logger.level(1))) self.cs_count += 1 Logger.log( "Found assignment \"%s\"" % (p_ass.serialize(threshold=100)), 1) return (p_ass, False)
def _get_param_assignments(self, model, time, parameters, monotonic=True): p_ass = [] fwd = False for p in parameters: # search the trace for any enabled faults ever_true = False for t in range(time + 1): p_time = model[TS.get_ptimed(p, 0)] if p.symbol_type() == BOOL: if p_time == TRUE(): ever_true = True break if ever_true: p_ass.append(p) elif not monotonic: p_ass.append(EqualsOrIff(p, FALSE())) p_ass = And(p_ass) self.region = simplify(Or(self.region, p_ass)) if self.models is None: self.models = [] self.models.append((model, time)) Logger.msg("+", 0, not (Logger.level(1))) self.cs_count += 1 Logger.log( "Found assignment \"%s\"" % (p_ass.serialize(threshold=100)), 1) return (p_ass, False)
def test_threshold_printing(self): x = Symbol("x") f = And(x,x) for _ in xrange(10): f = And(f,f) short_f_str = str(f) long_f_str = f.serialize() self.assertTrue(len(short_f_str) < len(long_f_str))
def test_threshold_printing(self): x = Symbol("x") f = And(x, x) for _ in range(10): f = And(f, f) short_f_str = str(f) long_f_str = f.serialize() self.assertTrue(len(short_f_str) < len(long_f_str))
class TransitionSystem: """ Symbolic transition system. All the objects are from PySMT (e.g. Symbols, formulas...) The TS is a tuple < state_var, init, trans > """ def __init__(self, env=None, helper=None): if env is None: self.env = get_env() self.helper = Helper(self.env) else: self.env = env self.helper = helper assert (self.helper.env == env) # internal representation of the transition system self.state_vars = set() self.var_types = {} self.init = TRUE_PYSMT() self.trans = TRUE_PYSMT() self.final = FALSE_PYSMT() def add_var(self, var): self.state_vars.add(var) def product(self, other_ts): """ Computes the synchronous product of self with other_ts, storing the product in self. Given TS1 = <V1, I1, T1> and TS2 = <V2, I2, T2> the product is the transition system TSP = <V1 union V2, I1 and I2, T1 and T2> (V are the state variables, I is the initial condition, T the transition relation) """ self.state_vars.update(other_ts.state_vars) self.init = And(self.init, other_ts.init) self.trans = And(self.trans, other_ts.trans) def __repr__(self): """ Not efficient, need to use a buffer...""" res = "State vars: " for v in self.state_vars: res += ", %s" % v res += "\nINIT: " res += str(self.init.serialize()) res += "\nTRANS: " res += str(self.trans.simplify().serialize()) return res
def generate_flipped_path(ppc): """ This function will check if a selected path is feasible ppc : partial path conditoin at chosen control loc chosen_control_loc: branch location selected for flip returns satisfiability of the negated path """ parser = SmtLibParser() script = parser.get_script(cStringIO(ppc)) formula = script.get_last_formula() prefix = formula.arg(0) constraint = formula.arg(1) new_path = And(prefix, Not(constraint)) assert str(new_path.serialize()) != str(formula.serialize()) return new_path
def select_new_input(patch_list=None): """ This function will select a new path for the next concolic execution and generate the inputs that satisfies the path log_path : log file for the previous concolic execution that captures PPC project_path: project path is the root directory of the program to filter PPC from libraries """ logger.info("generating new input for new path") global list_path_explored, list_path_inprogress, count_discovered # input_file_byte_list = list() # input_file_stat_byte_list = list() generated_path_list = values.LIST_GENERATED_PATH var_expr_map = reader.collect_symbolic_expression(values.FILE_EXPR_LOG) # generated_path_list = generate_new_symbolic_paths(constraint_list) # list_path_explored = list(set(list_path_explored + current_path_list)) selected_patch = None patch_constraint = TRUE new_path_count = 0 for (control_loc, generated_path, ppc_len), arg_list, poc_path, bin_path in generated_path_list: path_str = str(generated_path.serialize()) if path_str not in (list_path_detected + list_path_explored): reach_patch_loc = 100 - path_str.count("angelic!") reach_obs_loc = 100 - path_str.count("obs!") ppc_len = 10000 - ppc_len list_path_inprogress.append( (control_loc, generated_path, ppc_len, reach_patch_loc, reach_obs_loc, arg_list, poc_path, bin_path)) list_path_detected.append(str(generated_path.serialize())) new_path_count = new_path_count + 1 count_discovered = count_discovered + new_path_count emitter.highlight("\tidentified " + str(new_path_count) + " new path(s)") emitter.highlight("\ttotal discovered: " + str(count_discovered) + " path(s)") emitter.highlight("\ttotal remaining: " + str(len(list_path_inprogress)) + " path(s)") emitter.highlight("\ttotal infeasible: " + str(len(list_path_infeasible)) + " path(s)") if not list_path_inprogress: emitter.note("\t\tCount paths explored: " + str(len(list_path_explored))) emitter.note("\t\tCount paths remaining: " + str(len(list_path_inprogress))) return None, None, patch_list, None, None, None values.LIST_GENERATED_PATH = [] patch_constraint = None selected_new_path = "" selected_control_loc = "" if patch_list: while not patch_constraint: emitter.normal("\tfinding a feasible path for current patch set") if not list_path_inprogress: emitter.note("\t\tCount paths explored: " + str(len(list_path_explored))) emitter.note("\t\tCount paths remaining: " + str(len(list_path_inprogress))) return None, None, patch_list, None, None, None selected_new_path, selected_control_loc, argument_list, poc_path, bin_path = select_new_path_condition( ) patch_constraint = select_patch_constraint_for_input( patch_list, selected_new_path) if patch_constraint: list_path_explored.append(str(selected_new_path.serialize())) if is_sat(And(selected_new_path, patch_constraint)): selected_new_path = And(selected_new_path, patch_constraint) else: emitter.warning("\t[warning] no model generated") else: list_path_infeasible.append(str(selected_new_path.serialize())) else: selected_new_path, selected_control_loc, argument_list, poc_path, bin_path = select_new_path_condition( ) list_path_explored.append(str(selected_new_path.serialize())) emitter.highlight("\tSelected control location: " + selected_control_loc) emitter.highlight("\tSelected path: " + str(selected_new_path)) emitter.highlight("\tSelected binary: " + str(bin_path)) emitter.highlight("\tSelected arguments for mutation: " + str(argument_list)) if poc_path: emitter.highlight("\tSelected seed file: " + str(poc_path)) input_arg_list, input_var_list = generator.generate_new_input( selected_new_path, argument_list, poc_path) if input_arg_list is None and input_var_list is None: return None, None, patch_list, argument_list, poc_path, bin_path return input_arg_list, input_var_list, patch_list, argument_list, poc_path, bin_path
def findNashEquilibria(intents, queries, tuples, matches, strict, minReward, minRewardValue): userStrategy = dict() dbmsStrategy = dict() nashUserStrategy = dict() nashdbmsStrategy = dict() rewardMatrix = constructRewardMatrix(intents, tuples, matches) letters = set() nashRestrictions = list() #User Strategy matrix, each cell holds a variable for the SMT for intent in intents: if intent not in userStrategy: userStrategy[intent] = dict() for query in queries: userStrategy[intent][query] = Symbol('User['+intent + '][' + query + ']', REAL) letters.add(userStrategy[intent][query]) #DBMS Strategy matrix, each cell holds a variable for the SMT for query in queries: if query not in dbmsStrategy: dbmsStrategy[query] = dict() for tup in tuples: dbmsStrategy[query][tup] = Symbol('DBMS['+query + '][' + tup + ']', REAL) letters.add(dbmsStrategy[query][tup]) #We create a strategy for each move that can be made from the current position #This means that only a single row changes, the rest of the rows are the same as the strategies above #There also needs to be a strategy for each cell and a restriction only on the cell that this strategy belongs to for intent in intents: nashUserStrategy[intent] = dict() for query in queries: nashUserStrategy[intent][query] = copy.deepcopy(userStrategy) for query2 in copy.deepcopy(queries): nashUserStrategy[intent][query][intent][query2] = Symbol('Nash'+str(len(nashUserStrategy))+str(len(nashUserStrategy[intent]))+'User['+intent + '][' + query2 + ']', REAL) letters.add(nashUserStrategy[intent][query][intent][query2]) if query == query2: nashRestrictions.append(NotEquals(nashUserStrategy[intent][query][intent][query2], userStrategy[intent][query2])) #Same here except for DBMS for query in queries: nashdbmsStrategy[query] = dict() for tup in tuples: nashdbmsStrategy[query][tup] = copy.deepcopy(dbmsStrategy) for tup2 in tuples: nashdbmsStrategy[query][tup][query][tup2] = Symbol('Nash'+str(len(nashdbmsStrategy))+str(len(nashdbmsStrategy[query]))+'DBMS['+query + '][' + tup2 + ']', REAL) letters.add(nashdbmsStrategy[query][tup][query][tup2]) if tup == tup2: nashRestrictions.append(NotEquals(nashdbmsStrategy[query][tup][query][tup2], dbmsStrategy[query][tup2])) #Tells the range of values, for now set to Pure strategy so [0,1] domains = And([Or(Equals(l, Real(0)), Equals(l, Real(1))) for l in letters]) if DEBUG: print('\nDomain Serialization: ') print(domains) #Adds restriction that no value from the nashStrategies can be the same as the corresponding cell they are testing. This ensures a 'move' nashProblem = And(nashRestrictions) if DEBUG: print('\nNash Domain Serialization: ') print(nashProblem) #This is doing all the row stochastic stuff allEquals = [] #Adds each row of the user strategy stochasticMatrixUser = list() stochasticMatrixNashUser = list() for intent in intents: stochasticMatrixUser.append(Plus(userStrategy[intent].values())) for query in queries: allEquals.append(Equals(Plus(nashUserStrategy[intent][query][intent].values()), Real(1))) #Adds each row of the DBMS strategy stochasticMatrixdbms = list() stochasticMatrixNashdbms = list() for query in queries: stochasticMatrixdbms.append(Plus(dbmsStrategy[query].values())) for tup in tuples: allEquals.append(Equals(Plus(nashdbmsStrategy[query][tup][query].values()), Real(1))) #Checks the rows to make sure that the strategies are row stochastic stochUserEquals = [Equals(x, Real(1)) for x in stochasticMatrixUser] stochdbmsEquals = [Equals(x, Real(1)) for x in stochasticMatrixdbms] allEquals += stochUserEquals + stochdbmsEquals #Stochastic problem stochasticProblem = And(set(allEquals)) if DEBUG: print('\nStochastic Serialization: ') print(stochasticProblem.serialize()) #Uses Formula 1 from my paper to calculate the payoff, assuming uniform prior. reward = list() for intent in intents: for query in queries: for tup in tuples: reward.append(Times(Real(1/len(intents)), userStrategy[intent][query], dbmsStrategy[query][tup], rewardMatrix[intent][tup])) #Reward problem, requires a minimum reward. May not always be possible to achieve this reward rewardProblem = GE(Plus(reward), Real(minRewardValue)) if DEBUG: print('\nReward Serialization: ') print(rewardProblem) nashRewardUser = dict() nashRewardDbms = dict() #Again using Formula 1, but now we are creating one for each move to make sure that it is less than (Strict Nash) or less than or equal (Nash) for strat in nashUserStrategy: if strat not in nashRewardUser: nashRewardUser[strat] = dict() for strat2 in nashUserStrategy[strat]: if strat2 not in nashRewardUser[strat]: nashRewardUser[strat][strat2] = list() for intent in intents: for query in queries: for tup in tuples: nashRewardUser[strat][strat2].append(Times(Real(1/len(intents)), nashUserStrategy[strat][strat2][intent][query], dbmsStrategy[query][tup], rewardMatrix[intent][tup])) #Same, but for DBMS side. Just separated them to make it cleaner for strat in nashdbmsStrategy: if strat not in nashRewardDbms: nashRewardDbms[strat] = dict() for strat2 in nashdbmsStrategy[strat]: if strat2 not in nashRewardDbms[strat]: nashRewardDbms[strat][strat2] = list() for intent in intents: for query in queries: for tup in tuples: nashRewardDbms[strat][strat2].append(Times(Real(1/len(intents)), userStrategy[intent][query], nashdbmsStrategy[strat][strat2][query][tup], rewardMatrix[intent][tup])) if DEBUG: print('\nReward Serialization Nash: ') #Check user nash #This is where we actually perform the checking to see if it is less than or equal (or prep to be added to the solver) userNash = list() for intent in intents: for query in queries: if strict: userNash.append(Implies(NotEquals(nashUserStrategy[intent][query][intent][query], userStrategy[intent][query]), LT(Plus(nashRewardUser[intent][query]), Plus(reward)))) else: userNash.append(Implies(NotEquals(nashUserStrategy[intent][query][intent][query], userStrategy[intent][query]), LE(Plus(nashRewardUser[intent][query]), Plus(reward)))) userNashProblem = And(userNash) if DEBUG: print(userNashProblem.serialize()) #Check dbms nash dbmsNash = list() for query in queries: for tup in tuples: if strict: dbmsNash.append(Implies(NotEquals(dbmsStrategy[query][tup], nashdbmsStrategy[query][tup][query][tup]), LE(Plus(nashRewardDbms[query][tup]), Plus(reward)))) else: dbmsNash.append(Implies(NotEquals(dbmsStrategy[query][tup], nashdbmsStrategy[query][tup][query][tup]), LE(Plus(nashRewardDbms[query][tup]), Plus(reward)))) dbmsNashProblem = And(dbmsNash) if DEBUG: print(dbmsNashProblem.serialize()) #Add each component to the solver and test as we go #PySMT has another method where you just AND everything together, but they suggest #this method as it looks cleaner and you can see which one fails, if any with Solver(name="z3") as solver: solver.add_assertion(domains) if not solver.solve(): print('No solultion available (domains)') return print('Can satisfy domains') solver.add_assertion(nashProblem) if not solver.solve(): print('No solultion available (nash restrictions)') return print('Can satisfy nash domains') solver.add_assertion(stochasticProblem) if not solver.solve(): print('No sulution available (stochastic)') return print('Can satisfy stochastic') if minReward: solver.add_assertion(rewardProblem) if not solver.solve(): print('No solution available') return print('Can satisfy minimum reward') solver.add_assertion(userNashProblem) if not solver.solve(): print('No solution available (user nash)') return print('Can satisfy user nash') solver.add_assertion(dbmsNashProblem) if not solver.solve(): print('No solution available (dbms nash)') return print('Can satisfy dbms nash') #Print out the final assignments if it made it this far, as a solution exists for intent in intents: for query in queries: print("%s = %s" % (userStrategy[intent][query], solver.get_value(userStrategy[intent][query]))) for query in queries: for tup in tuples: print("%s = %s" % (dbmsStrategy[query][tup], solver.get_value(dbmsStrategy[query][tup])))
def iterate_to_find_satisfiable_solution(features, feature_implimentation_time, dependencies, sequential, developers, feature_developer, parallel_tasks, end_time): feature_time_map = {} i = 1 for fe in features: feature_time_map[fe] = { 'EndTime': Symbol('E' + str(i), INT), 'StartTime': Symbol('S' + str(i), INT), 'Duration': Int(feature_implimentation_time[i - 1]) } i += 1 b_greater = And( And(GE(feature_time_map[fe]['EndTime'], Int(0)), GE(feature_time_map[fe]['StartTime'], Int(0))) for fe in features) b_impli_time = And( Equals( Minus(feature_time_map[l]['EndTime'], feature_time_map[l] ['StartTime']), feature_time_map[l]['Duration']) for l in features) b_dependencies = And( GE(feature_time_map[depe[1]]['StartTime'], feature_time_map[depe[0]] ['EndTime']) for depe in dependencies) b_sequential = And( Or( GE(feature_time_map[seq[1]]['StartTime'], feature_time_map[seq[0]] ['EndTime']), GE(feature_time_map[seq[0]]['StartTime'], feature_time_map[seq[1]] ['EndTime'])) for seq in sequential) developer_feature_imp = {} for fet_dev in feature_developer: developer_feature_imp.setdefault(fet_dev[1], []).append(fet_dev[0]) and_relation = [] for val in developer_feature_imp.values(): if len(val) > 1: for comb in combinations(val, 2): and_relation.append( Or( GE(feature_time_map[comb[1]]['StartTime'], feature_time_map[comb[0]]['EndTime']), GE(feature_time_map[comb[0]]['StartTime'], feature_time_map[comb[1]]['EndTime']))) b_dev_pararale = And(and_relation) and_parallel = [] for val in parallel_tasks: and_parallel.append( And( LE(feature_time_map[val[0]]['StartTime'], feature_time_map[val[1]]['StartTime']), GE(feature_time_map[val[0]]['EndTime'], feature_time_map[val[1]]['StartTime']))) b_parallel = And(and_parallel) print('++++++++++++++Conditions++++++++++++++++') print('Start and End times should be grater than zero : ', b_greater) print('Difference between end and start times : ', b_impli_time) print('Some features should be implimented first : ', b_dependencies) print('Some features can not be executed parallelly : ', b_sequential) print('Some features need specific developers : ', b_dev_pararale) print('Some features need to be started before ending some features : ', b_parallel) print('++++++++++++++Release Dates++++++++++++++++') end_time = 1 max_end_time = sum(feature_implimentation_time) sloved = False for end in tqdm(range(max_end_time), 'running binary search to find shortest release date'): b_end_time = And( LE(fe['EndTime'], Int(end_time)) for fe in feature_time_map.values()) formula = And(b_greater, b_impli_time, b_dependencies, b_sequential, b_dev_pararale, b_end_time, b_parallel) if is_sat(formula): print('\n' + 'You have to spend at least', end_time, 'days to finish your next release') print('Therefore, the closest release date is :', (datetime.today() + timedelta(end_time)).strftime('%d/%m/%Y')) for key, val in feature_time_map.items(): print( 'Feature', key, ', Start Date :', (datetime.today() + timedelta( get_model(formula)[val['StartTime']].constant_value()) ).strftime('%d/%m/%Y'), '-> End Date : ', (datetime.today() + timedelta( get_model(formula)[val['EndTime']].constant_value()) ).strftime('%d/%m/%Y')) sloved = True break end_time += 1 if sloved == False: print("This problem is not solvable") # print(b_devlopers) # print(is_sat(b_devlopers)) return len(formula.serialize()), 'S' if is_sat(formula) else 'U'
class System(): def __init__(self): self.reset() def reset(self): self._init = set() self._axiom = set() self._prop = set() self._vars = set() self._axiomvars = set() self._states = set() self._nexstates = set() self._globals = set() self._le = set() self._others = set() self._pre2nex = dict() self._nex2pre = dict() self._trel = None self._actions = list() self._action_en2idx = dict() self._predicates = dict() self._helpers = dict() self._infers = dict() self._definitions = dict() self._definitionMap = dict() def copy(self, rhs): self._init = rhs._init self._axiom = rhs._axiom self._prop = rhs._prop self._vars = rhs._vars self._axiomvars = rhs._axiomvars self._states = rhs._states self._nexstates = rhs._nexstates self._globals = rhs._globals self._le = rhs._le self._others = rhs._others self._pre2nex = rhs._pre2nex self._nex2pre = rhs._nex2pre self._trel = rhs._trel self._actions = rhs._actions self._action_en2idx = rhs._action_en2idx self._predicates = rhs._predicates self._helpers = rhs._helpers self._infers = rhs._infers self._definitions = rhs._definitions self._definitionMap = rhs._definitionMap def add_helper(self, formula, name): self._helpers[formula] = "user_" + name def add_pred(self, formula, name): args = [] types = [] if formula.is_quantifier(): for a in formula.quantifier_vars(): args.append(a) types.append(a.symbol_type()) formula = formula.arg(0) ft = FunctionType(BOOL, tuple(types)) f = Symbol(name, ft) lhs = Function(f, args) self._predicates[lhs] = formula def add_init(self, formula): self._init.add(formula) def add_axiom(self, formula): if (formula.is_and()): for f in formula.args(): self._axiom.add(f) else: self._axiom.add(formula) def add_definition(self, formula, name): self._definitions[name] = formula def add_prop(self, formula): clauses = flatten_and(formula) for cl in clauses: self._prop.add(cl) def add_state(self, formula, fnex): if formula.is_function_application(): pre = formula.function_name() else: pre = formula self._states.add(pre) nex = Symbol(fnex, pre.symbol_type()) self._nexstates.add(nex) self._pre2nex[pre] = nex self._nex2pre[nex] = pre def add_global_state(self, formula): if formula.is_function_application(): pre = formula.function_name() pret = pre.symbol_type() paramt = pret.param_types if (len(paramt) == 2 and pret.return_type.is_bool_type() and paramt[0] == paramt[1]): name_pre = str(pre) if name_pre == "le" or name_pre.endswith(".le"): self.add_le_state(pre) else: pre = formula self._globals.add(pre) self._states.add(pre) self._nexstates.add(pre) def add_le_state(self, pre): self._le.add(pre) def is_ordered_state(self, s): res = s in self._le return res def add_other(self, formula): self._others.add(formula) def add_var(self, formula): pre = formula # if not(pre in self._nex2pre): self._vars.add(pre) # if not(pre in self._pre2nex): # pre_s = pre.symbol_name() # if pre_s.startswith("__"): # fnex = pre_s[2:] # else: # fnex = pre_s + "$next" # nex = Symbol(fnex, pre.symbol_type()) # self._pre2nex[pre] = nex # self._nex2pre[nex] = pre def action_noop(self): f = dict() for s in self._states: if s in self._pre2nex: n = self._pre2nex[s] s_type = s.symbol_type() args = [] if s_type.is_function_type(): i = 0 for paramt in s_type.param_types: i += 1 paramt_name = str(i) + ":" + str(paramt) args.append(Symbol(paramt_name, paramt)) lhs = Function(s, args) rhs = Function(n, args) eq = ForAll(args, EqualsOrIff(lhs, rhs)) f[n] = eq return f def noop_name(self): return "noop" def is_noop(self, name): return name == self.noop_name() def input_action_name(self): return "__input_action_" def get_action_noop(self): noop = self.action_noop() name = self.noop_name() return (name, noop) def add_action_noop(self): name, noop = self.get_action_noop() formula = And([i for i in noop.values()]) self.add_action(formula, name) return noop def add_action(self, formula, name): if name in self._actions: assert (0) action = formula if action.is_exists(): qvars = action.quantifier_vars() for v in qvars: self.add_var(v) self.add_other(v) action = action.arg(0) self._actions.append([action, name, None]) # def get_axiom_vars(self): # axiom_vars = set() # if len(self._axiom) != 0: # av = And(self._axiom).get_free_variables() # for v in av: # axiom_vars.add(v) # return axiom_vars def add_trel(self): eprint("\t(found #%d actions)" % len(self._actions)) print("\t(found #%d actions)" % len(self._actions)) if len(self._actions) == 0: eprint("\t(error: no action found)") print("\t(error: no action found)") assert (0) if len(self._axiom) != 0: ax = And(self._axiom) axvar = ax.get_free_variables() for v in axvar: self._axiomvars.add(v) noop_name, noop = self.get_action_noop() noop_all = And([i for i in noop.values()]) self._trel = noop_all self._input_action = Symbol(self.input_action_name(), INT) self.add_var(self._input_action) # axiom_vars = self.get_axiom_vars() # action_en = [] # self.add_action(noop_all, noop_name) for idx, f in enumerate(self._actions): action = f[0] action_name = f[1] # action_vars = axiom_vars.copy() # for v in action.get_free_variables(): # action_vars.add(v) action_vars = action.get_free_variables() qvars = None if action.is_exists(): qvars = action.quantifier_vars() action = action.arg(0) action_all = [action] missing_nex = [] for n in self._nex2pre.keys(): if n not in action_vars: if str(n) not in self._definitions: if True or (str(n) != "choosable"): action_all.append(noop[n]) missing_nex.append(n) if len(missing_nex) != 0: print("adding #%d noops to action %s" % (len(missing_nex), f[1])) for n in missing_nex: print("\tnoop(%s)" % n) action = And(action_all) if qvars != None: action = Exists(qvars, action) self._actions[idx][0] = action # self._trel = Or(action, self._trel) action_symbol = Int(idx) self._actions[idx][-1] = action_symbol cond = EqualsOrIff(self._input_action, action_symbol) self._trel = Ite(cond, action, self._trel) # action_symbol = Symbol("en_"+action_name) # action_en.append(action_symbol) # self._trel = Ite(action_symbol, action, self._trel) # action_cond = [] # action_cond.append(self._trel) # for i in range(len(action_en)-1): # fi = Not(action_en[i]) # for j in range(i+1, len(action_en)): # fj = Not(action_en[j]) # cond = Or(fi, fj) # action_cond.insert(0, cond) # self._trel = And(action_cond) # if len(self._axiom) != 0: # q = [] # q.extend(self._axiom) # # self.add_init(And(q)) # q.append(self._trel) # self._trel = And(q) self.add_action(noop_all, noop_name) def add_trel_new(self): eprint("\t(found #%d actions)" % len(self._actions)) print("\t(found #%d actions)" % len(self._actions)) if len(self._actions) == 0: eprint("\t(error: no action found)") print("\t(error: no action found)") assert (0) if len(self._axiom) != 0: ax = And(self._axiom) axvar = ax.get_free_variables() for v in axvar: self._axiomvars.add(v) tcond = [] enVar = [] enOr = [] noop = self.add_action_noop() for idx, f in enumerate(self._actions): action = f[0] action_name = f[1] action_vars = action.get_free_variables() en = Symbol("en_" + action_name, BOOL) self._action_en2idx[en] = idx enVar.append(en) qvars = None if action.is_exists(): qvars = action.quantifier_vars() action = action.arg(0) action_all = [action] missing_nex = [] for n in self._nex2pre.keys(): if n not in action_vars: if str(n) not in self._definitions: if True or (str(n) != "choosable"): action_all.append(noop[n]) missing_nex.append(n) if len(missing_nex) != 0: print("adding #%d noops to action %s" % (len(missing_nex), f[1])) for n in missing_nex: print("\tnoop(%s)" % n) action = And(action_all) if qvars != None: action = Exists(qvars, action) self._actions[idx][0] = action self._actions[idx][2] = en cond = Implies(en, action) tcond.append(cond) enOr.append(en) cond = Or(enOr) tcond.append(cond) for i in range(len(enVar) - 1): ei = enVar[i] for j in range(i + 1, len(enVar)): assert (i != j) ej = enVar[j] cond = Or(Not(ei), Not(ej)) tcond.append(cond) self._trel = And(tcond) def __str__(self): res = [] res.append( "-----------------------------------------------------------------" ) res.append("\nInit #") res.append(str(len(self._init)) + "\n") for f in self._init: res.append("\t" + str(f) + "\n\t\twith variables %s\n" % f.get_free_variables()) res.append("\nAxioms #") res.append(str(len(self._axiom)) + "\n") for f in self._axiom: res.append("\t" + f.serialize() + "\n\t\twith variables %s\n" % f.get_free_variables()) res.append("\nActions #") res.append(str(len(self._actions)) + "\n") for idx, f in enumerate(self._actions): res.append("\t" + str(idx) + ":\t" + f[1] + " (en: " + str(f[2]) + ")\t" + str(f[0]) + "\n\t\twith variables %s\n" % f[0].get_free_variables()) res.append("\nProperties #") res.append(str(len(self._prop)) + "\n") for f in self._prop: res.append("\t" + str(f) + "\n\t\twith variables %s\n" % f.get_free_variables()) res.append("\nVariables #") res.append(str(len(self._vars)) + "\n") for f in self._vars: res.append("\t" + str(f) + " of type %s\n" % f.symbol_type()) res.append("\nState variables #") res.append(str(len(self._states)) + "\n") for f in self._states: res.append("\t" + str(f) + " of type %s\n" % f.symbol_type()) res.append("\nNex state variables #") res.append(str(len(self._nexstates)) + "\n") for f in self._nexstates: res.append("\t" + str(f) + " of type %s\n" % f.symbol_type()) res.append("\nGlobal variables #") res.append(str(len(self._globals)) + "\n") for f in self._globals: res.append("\t" + str(f) + " of type %s\n" % f.symbol_type()) res.append("\nOrdered variables #") res.append(str(len(self._le)) + "\n") for f in self._le: res.append("\t" + str(f) + " of type %s\n" % f.symbol_type()) res.append("\nNex to pre #") res.append(str(len(self._nex2pre)) + "\n") for nex, pre in self._nex2pre.items(): res.append("\t" + str(nex) + " <- " + str(pre) + "\n") res.append("\nPre to nex #") res.append(str(len(self._pre2nex)) + "\n") for pre, nex in self._pre2nex.items(): res.append("\t" + str(pre) + " -> " + str(nex) + "\n") res.append("\nOther variables #") res.append(str(len(self._others)) + "\n") for f in self._others: res.append("\t" + str(f) + " of type %s\n" % f.symbol_type()) res.append("\nAxiom variables #") res.append(str(len(self._axiomvars)) + "\n") for f in self._axiomvars: res.append("\t" + str(f) + "\n") res.append("\nPredicates #") res.append(str(len(self._predicates)) + "\n") for k, v in self._predicates.items(): res.append("\t%s := %s\n\t\twith variables %s\n" % (str(k), str(v), v.get_free_variables())) res.append("\nHelpers #") res.append(str(len(self._helpers)) + "\n") for k, v in self._helpers.items(): res.append("\t%s := %s\n\t\twith variables %s\n" % (str(v), str(k), k.get_free_variables())) res.append("\nInferences #") res.append(str(len(self._infers)) + "\n") for k, v in self._infers.items(): res.append("\t%s := %s\n\t\twith variables %s\n" % (str(v), str(k), k.get_free_variables())) res.append("\nDefinitions #") res.append(str(len(self._definitions)) + "\n") for k, v in self._definitions.items(): res.append("\t%s := %s\n\t\twith variables %s\n" % (str(k), str(v), v.get_free_variables())) res.append("\nDefinition Map #") res.append(str(len(self._definitionMap)) + "\n") for k, v in self._definitionMap.items(): res.append("\t%s := %s\n\t\twith variables %s\n" % (str(k), str(v[0]), v[-1])) res.append("\nTrel:\n%s\n" % (self._trel.serialize())) res.append( "-----------------------------------------------------------------" ) return "".join(res)