def __init__(self, term_signature, spec): super().__init__() self.term_signature = term_signature self.synth_funs = spec.synth_funs self.spec = spec self.syn_ctx = self.spec.syn_ctx self.point_var_exprs = [ exprs.VariableExpression(v) for v in spec.point_vars ] self.smt_ctx = z3smt.Z3SMTContext() self.eval_ctx = evaluation.EvaluationContext() self.canon_apps = [ self.spec.canon_application[sf] for sf in self.synth_funs ] self.outvars = [] for fn in self.synth_funs: self.outvars.append( exprs.VariableExpression(exprs.VariableInfo( exprtypes.IntType(), 'outvar_' + fn.function_name, len(self.point_var_exprs) + len(self.outvars)))) self.all_vars = self.point_var_exprs + self.outvars self.all_vars_z3 = [ _expr_to_smt(v, self.smt_ctx) for v in self.all_vars ] # self.clauses = spec.get_canon_clauses() self.lia_clauses = [ [ LIAInequality.from_expr(exprs.substitute_all(disjunct, list(zip(self.canon_apps, self.outvars)))) for disjunct in clause ] for clause in spec.get_canon_clauses() ] self.rewritten_spec = exprs.substitute_all( self.spec.get_canonical_specification(), list(zip(self.canon_apps, self.outvars)))
def to_template_expr(self): import random name = self.non_terminal + '_ph_' + str( NTRewrite.counter) # str(random.randint(1, 1000000)) NTRewrite.counter += 1 ph_var = exprs.VariableExpression(exprs.VariableInfo(self.type, name)) return [ph_var], [self.non_terminal], ph_var
def add_dummy_pred(expr): arg_var = exprs.VariableExpression( exprs.VariableInfo(exprtypes.BoolType(), 'd', 0)) dummy_macro_func = semantics_types.MacroFunction( dummy_pred_name, 1, (exprtypes.BoolType(), ), exprtypes.BoolType(), arg_var, [arg_var]) expr = exprs.FunctionExpression(dummy_macro_func, (expr, )) return expr
def _process_rule(non_terminals, nt_type, syn_ctx, arg_vars, var_map, synth_fun, rule_data): ph_let_bound_vars, let_bound_vars = [], [] if type(rule_data) == tuple: value = sexp_to_value(rule_data) ret = grammars.ExpressionRewrite(exprs.ConstantExpression(value)) elif rule_data[0] == 'Constant': typ = sexp_to_type(rule_data[1]) ret = grammars.NTRewrite('Constant' + str(typ), typ) elif rule_data[0] in [ 'Variable', 'InputVariable', 'LocalVariable' ]: raise NotImplementedError('Variable rules in grammars') elif type(rule_data) == str: if rule_data in [ a.variable_info.variable_name for a in arg_vars ]: (parameter_position, variable) = next((i, x) for (i, x) in enumerate(arg_vars) if x.variable_info.variable_name == rule_data) expr = exprs.FormalParameterExpression(synth_fun, variable.variable_info.variable_type, parameter_position) ret = grammars.ExpressionRewrite(expr) elif rule_data in non_terminals: ret = grammars.NTRewrite(rule_data, nt_type[rule_data]) elif rule_data in var_map: ret = grammars.ExpressionRewrite(var_map[rule_data]) else: # Could be a 0 arity function func = syn_ctx.make_function(rule_data) if func != None: ret = grammars.ExpressionRewrite(syn_ctx.make_function_expr(rule_data)) else: # Could be a let bound variable bound_var_ph = exprs.VariableExpression(exprs.VariableInfo(exprtypes.BoolType(), 'ph_' + rule_data)) ph_let_bound_vars.append(bound_var_ph) ret = grammars.ExpressionRewrite(bound_var_ph) elif type(rule_data) == list: function_name = rule_data[0] if function_name != 'let': function_args = [] for child in rule_data[1:]: ph_lbv, lbv, arg = _process_rule(non_terminals, nt_type, syn_ctx, arg_vars, var_map, synth_fun, child) ph_let_bound_vars.extend(ph_lbv) let_bound_vars.extend(lbv) function_args.append(arg) function_arg_types = tuple([ x.type for x in function_args ]) function = syn_ctx.make_function(function_name, *function_arg_types) else: def child_processing_func(rd, syn_ctx, new_var_map): ph_lbv, lbv, a = _process_rule(non_terminals, nt_type, syn_ctx, arg_vars, new_var_map, synth_fun, rd) ph_let_bound_vars.extend(ph_lbv) let_bound_vars.extend(lbv) return a def get_return_type(r): return r.type function, function_args = sexp_to_let(rule_data, syn_ctx, child_processing_func, get_return_type, var_map) let_bound_vars.extend(function.binding_vars) assert function is not None ret = grammars.FunctionRewrite(function, *function_args) else: raise Exception('Unknown right hand side: %s' % rule_data) return ph_let_bound_vars, let_bound_vars, ret
def _process_function_defintion(args_data, ret_type_data): return_type = sexp_to_type(ret_type_data) arg_vars = [] arg_var_map = {} arg_types = [] for (offset, (arg_name, arg_type_sexp)) in enumerate(args_data): arg_type = sexp_to_type(arg_type_sexp) arg_types.append(arg_type) arg_var = exprs.VariableExpression( exprs.VariableInfo(arg_type, arg_name)) arg_vars.append(arg_var) arg_var_map[arg_name] = arg_var return ((arg_vars, arg_types, arg_var_map), return_type)
def make_variable(self, var_type, var_name, var_eval_offset=exprs.VariableInfo._undefined_offset): """Makes a variable info of the given name and type.""" assert (isinstance(var_type, exprtypes.TypeBase)) existing = self.variables_map.get(var_name, None) if (existing != None and existing.variable_type == var_type): return existing elif (existing != None and existing.variable_type != var_type): raise ValueError(('Variable named \'%s\' has already ' + 'been created with type %s') % (var_name, str(existing.var_type))) else: retval = exprs.VariableInfo(var_type, var_name, var_eval_offset) retval.synthesis_ctx = self self.variables_map[var_name] = retval return retval
def decompose(self, macro_instantiator): start_nt = self.start reverse_mapping = [] term_productions = [] pred_productions = [] for rewrite in self.rules[start_nt]: ph_vars, nts, orig_expr_template = rewrite.to_template_expr() ph_var_nt_map = dict(zip(ph_vars, nts)) expr_template = macro_instantiator.instantiate_all( orig_expr_template) ifs = exprs.find_all_applications(expr_template, 'ite') # Either there are no ifs or it is an concrete expression if len(ifs) == 0 or len(nts) == 0: term_productions.append(rewrite) continue elif len(ifs) > 1 and ifs[0] != expr_template: return None [cond, thent, elset] = ifs[0].children cond_ph_vars = exprs.get_all_variables(cond) & set(ph_vars) then_ph_vars = exprs.get_all_variables(thent) & set(ph_vars) else_ph_vars = exprs.get_all_variables(elset) & set(ph_vars) if (len(cond_ph_vars & then_ph_vars) > 0 or len(cond_ph_vars & else_ph_vars) > 0 or len(else_ph_vars & then_ph_vars) > 0): return None if ( thent not in ph_vars or \ elset not in ph_vars or \ ph_var_nt_map[thent] != start_nt or \ ph_var_nt_map[elset] != start_nt): return None cond_rewrite = expr_template_to_rewrite(cond, ph_var_nt_map, self) # Make dummy function to recognize predicate arg_var = exprs.VariableExpression( exprs.VariableInfo(exprtypes.BoolType(), 'd', 0)) dummy_macro_func = semantics_types.MacroFunction( 'dummy_pred_id_' + str(random.randint(1, 1000000)), 1, (exprtypes.BoolType(), ), exprtypes.BoolType(), arg_var, [arg_var]) pred_production = FunctionRewrite(dummy_macro_func, cond_rewrite) pred_productions.append(pred_production) reverse_mapping.append( (dummy_macro_func, cond, orig_expr_template, expr_template)) if len(pred_productions) == 0: return None # Non-terminals [term_start, pred_start] = [x + start_nt for x in ['Term', 'Pred']] [term_nts, pred_nts ] = [self.non_terminals + [x] for x in [term_start, pred_start]] term_nts.remove(start_nt) pred_nts.remove(start_nt) # Non-terminal types term_nt_type, pred_nt_type = self.nt_type.copy(), self.nt_type.copy() term_nt_type.pop(start_nt) term_nt_type[term_start] = self.nt_type[start_nt] pred_nt_type.pop(start_nt) pred_nt_type[pred_start] = exprtypes.BoolType() # Rules term_rules = {} term_rules[term_start] = [ rew.rename_nt(start_nt, term_start) for rew in term_productions ] for nt in self.non_terminals: if nt != start_nt: term_rules[nt] = [ rew.rename_nt(start_nt, term_start) for rew in self.rules[nt] ] pred_rules = {} pred_rules[pred_start] = [ rew.rename_nt(start_nt, term_start) for rew in pred_productions ] for nt in self.non_terminals: if nt != start_nt: pred_rules[nt] = [ rew.rename_nt(start_nt, term_start) for rew in self.rules[nt] ] # pred_rules[term_start] = term_rules[term_start] # pred_nt_type[term_start] = term_nt_type[term_start] pred_rules = {**term_rules, **pred_rules} pred_nt_type = {**term_nt_type, **pred_nt_type} term_grammar = Grammar(term_nts, term_nt_type, term_rules, term_start) pred_grammar = Grammar(pred_nts + [term_start], pred_nt_type, pred_rules, pred_start) # print(pred_grammar) return term_grammar, pred_grammar, reverse_mapping
def dt_rewrite_boolean_combs(syn_ctx, sol, synth_fun): orig_sol = sol smt_ctx = z3smt.Z3SMTContext() vs = exprs.get_all_variables(sol) dummy_vars = [ exprs.VariableExpression( exprs.VariableInfo(v.variable_info.variable_type, "D" + v.variable_info.variable_name, i)) for (i, v) in enumerate(vs) ] argvars = [ semantics.semantics_types.expression_to_smt(v, smt_ctx) for v in dummy_vars ] sol = exprs.substitute_all(sol, list(zip(vs, dummy_vars))) preds = get_atomic_preds(sol) terms = get_terms(sol) points = [] from exprs import evaluation eval_ctx = evaluation.EvaluationContext() def add_point(point, pred_sig_list, term_sig_list): points.append(point) eval_ctx.set_valuation_map(point) solv = evaluation.evaluate_expression_raw(sol, eval_ctx) new_pred_sig_list = [ utils.bitset_extend( sig, evaluation.evaluate_expression_raw(pred, eval_ctx)) for (sig, pred) in zip(pred_sig_list, preds) ] new_term_sig_list = [ utils.bitset_extend( sig, solv == evaluation.evaluate_expression_raw(term, eval_ctx)) for (sig, term) in zip(term_sig_list, terms) ] return (new_pred_sig_list, new_term_sig_list) pred_sig_list = [BitSet(0) for p in preds] term_sig_list = [BitSet(0) for t in terms] expr = terms[0] fsol = None while True: z3point = exprs.sample(syn_ctx.make_function_expr('ne', expr, sol), smt_ctx, argvars) if z3point is None: fsol = expr break else: point = list( map(lambda v, d: z3smt.z3value_to_value(v, d.variable_info), z3point, dummy_vars)) (pred_sig_list, term_sig_list) = add_point(point, pred_sig_list, term_sig_list) dt = eusolver.eus_learn_decision_tree_for_ml_data( pred_sig_list, term_sig_list) expr = verifiers.naive_dt_to_expr(syn_ctx, dt, preds, terms) sol = exprs.substitute_all(fsol, list(zip(dummy_vars, vs))) return sol