def cegis(smt, params, k, r, statistics = {}): global RESTART_THRESHOLD print('===== CEGIS[k={0},r={1}] ====='.format(k,r)) ### Initial values for statistics statistics['time'] = 0 statistics['#smt_calls'] = 0 statistics['#restarts'] = 0 statistics['#parameter_candidates'] = 0 statistics['parameter_synthesis.time'] = [] statistics['parameter_synthesis.model'] = [] statistics['#counterexamples'] = 0 statistics['correctness_check.time'] = [] statistics['correctness_check.model'] = [] statistics['#randomizations'] = 0 statistics['counterexample_randomization.time'] = [] statistics['counterexample_randomization.model'] = [] total_time_start = time.time() ### Build correctness formula init_smt = (smt + build_correctness_formula(k)).format(*params).split('\n') ### Remove parameters from SMT instance prepared_smt = [] for line in init_smt: matched = False for p in params: if line.strip().startswith('(define-fun ' + p): a,b,c,d,e = line.split(' ') prepared_smt.append('(declare-fun {0} {1} {2})'.format(b,c,d)) matched = True if not matched: prepared_smt.append(line) init_smt = prepared_smt count_no_progress = 0 while True: ### Restart the engine if CEGIS does not make progress if r >= 3 and len(statistics['parameter_synthesis.model']) > 1: total_progress = 0 for key in statistics['parameter_synthesis.model'][-2:][0]: new_value = sexpr.str2sexpr(statistics['parameter_synthesis.model'][-2:][1][key]) # print(new_value) if isinstance(new_value,list): new_value = new_value[0] new_value = eval_expression(new_value) old_value = sexpr.str2sexpr(statistics['parameter_synthesis.model'][-2:][0][key]) # print(old_value) if isinstance(old_value,list): old_value = old_value[0] old_value = eval_expression(old_value) # print(new_value) # print(old_value) assert new_value[0] == True assert old_value[0] == True progress = new_value[1] - old_value[1] total_progress += abs(progress) if total_progress < 0.0000001: print("N",end='') count_no_progress += 1 if count_no_progress > 10: print("R",end='') count_no_progress = 0 statistics['#restarts'] += 1 check_smt = list(init_smt) ### Restart the engine (and forget all previously learned counterexamples) if statistics['#counterexamples'] % RESTART_THRESHOLD == 0: print("R",end='') statistics['#restarts'] += 1 RESTART_THRESHOLD += 16*statistics['#restarts'] check_smt = list(init_smt) else: # print(statistics['#counterexamples']) # print(RESTART_THRESHOLD) # print(statistics['#counterexamples'] % RESTART_THRESHOLD == 0) print('.',end='') sys.stdout.flush() ### Compute parameters compute_smt = list(check_smt) statistics['#smt_calls'] += 1 statistics['#parameter_candidates'] += 1 ts = time.time() (sat,model) = SMTsolve(compute_smt,params) te = time.time() statistics['parameter_synthesis.time'].append(te - ts) statistics['parameter_synthesis.model'].append(model if sat else {}) if not sat: total_time_end = time.time() statistics['cegis.time'] = total_time_end - total_time_start return False, {} ### Check k-correctness correct_smt = [] for line in check_smt: matched = False for p in params: if line.strip().startswith('(declare-fun ' + p): a,b,c,d = line.split(' ') correct_smt.append('(define-fun {0} {1} {2} {3})'.format(b,c,d[:-1],model[p])) matched = True if not matched: correct_smt.append(line) correct_smt.append('(declare-fun s0 () state)') for i in range(0,k): correct_smt.append('(declare-fun i{0} () input)'.format(i)) correct_smt.append('(assert (not (correct{0} s0 {1})))' .format(k, ' '.join("i{0}".format(cnt) for cnt in range(0,k)))) statistics['#smt_calls'] += 1 statistics['#counterexamples'] += 1 ts = time.time() (sat, cex) = SMTsolve(correct_smt, ['s0'] + ['i{0}'.format(j) for j in range(0,k)]) te = time.time() statistics['correctness_check.time'].append(te - ts) statistics['correctness_check.model'].append(cex if sat else {}) if not sat: total_time_end = time.time() statistics['cegis.time'] = total_time_end - total_time_start return True, model ### Make counterexamples as nasty as possible if r == 1 or (r >= 2 and statistics['#counterexamples'] % 2 == 0): state = sexpr.str2sexpr(cex['s0'])[0][1:] for i in range(0,len(state)): try_state = [] for j in range(0,len(state)): if i == j: ok, value = randomize_if_necessary(state[i]) try_state.append(value) else: try_state.append(state[j]) state_sexpr = sexpr.str2sexpr(cex['s0'])[0] state_sexpr[1:] = try_state if state_sexpr == sexpr.str2sexpr(cex['s0'])[0]: continue # skip the SMT check if no randomization happened state_sexpr = sexpr.sexpr2str(state_sexpr) nasty_check_smt = list(check_smt) nasty_check_smt.append('(assert (not (correct{0} {1} {2})))' .format(k, state_sexpr, " ".join([cex["i" + str(cnt)] for cnt in range(0,k)]))) statistics['#smt_calls'] += 1 statistics['#randomizations'] += 1 ts = time.time() (sat, model) = SMTsolve(nasty_check_smt,params) te = time.time() statistics['counterexample_randomization.time'].append(te - ts) statistics['counterexample_randomization.model'].append(cex if sat else {}) if sat: # print("changed",state[i],"to",try_state[i]) state[i] = try_state[i] state_sexpr = sexpr.str2sexpr(cex['s0'])[0] state_sexpr[1:] = state if cex['s0'] != sexpr.sexpr2str(state_sexpr): print('G',end='') cex['s0'] = sexpr.sexpr2str(state_sexpr) ### Make sure that the next parameters are better check_smt.append('(assert (correct{0} {1} {2}))'.format(k, cex['s0'], " ".join([cex["i" + str(cnt)] for cnt in range(0,k)])))
def writeSExpr(self, list): self.writeOut(sexpr.sexpr2str(list))
def cegis(smt, params, k, r, statistics={}): global RESTART_THRESHOLD print('===== CEGIS[k={0},r={1}] ====='.format(k, r)) ### Initial values for statistics statistics['time'] = 0 statistics['#smt_calls'] = 0 statistics['#restarts'] = 0 statistics['#parameter_candidates'] = 0 statistics['parameter_synthesis.time'] = [] statistics['parameter_synthesis.model'] = [] statistics['#counterexamples'] = 0 statistics['correctness_check.time'] = [] statistics['correctness_check.model'] = [] statistics['#randomizations'] = 0 statistics['counterexample_randomization.time'] = [] statistics['counterexample_randomization.model'] = [] total_time_start = time.time() ### Build correctness formula init_smt = (smt + build_correctness_formula(k)).format(*params).split('\n') ### Remove parameters from SMT instance prepared_smt = [] for line in init_smt: matched = False for p in params: if line.strip().startswith('(define-fun ' + p): a, b, c, d, e = line.split(' ') prepared_smt.append('(declare-fun {0} {1} {2})'.format( b, c, d)) matched = True if not matched: prepared_smt.append(line) init_smt = prepared_smt count_no_progress = 0 while True: ### Restart the engine if CEGIS does not make progress if r >= 3 and len(statistics['parameter_synthesis.model']) > 1: total_progress = 0 for key in statistics['parameter_synthesis.model'][-2:][0]: new_value = sexpr.str2sexpr( statistics['parameter_synthesis.model'][-2:][1][key]) # print(new_value) if isinstance(new_value, list): new_value = new_value[0] new_value = eval_expression(new_value) old_value = sexpr.str2sexpr( statistics['parameter_synthesis.model'][-2:][0][key]) # print(old_value) if isinstance(old_value, list): old_value = old_value[0] old_value = eval_expression(old_value) # print(new_value) # print(old_value) assert new_value[0] == True assert old_value[0] == True progress = new_value[1] - old_value[1] total_progress += abs(progress) if total_progress < 0.0000001: print("N", end='') count_no_progress += 1 if count_no_progress > 10: print("R", end='') count_no_progress = 0 statistics['#restarts'] += 1 check_smt = list(init_smt) ### Restart the engine (and forget all previously learned counterexamples) if statistics['#counterexamples'] % RESTART_THRESHOLD == 0: print("R", end='') statistics['#restarts'] += 1 RESTART_THRESHOLD += 16 * statistics['#restarts'] check_smt = list(init_smt) else: # print(statistics['#counterexamples']) # print(RESTART_THRESHOLD) # print(statistics['#counterexamples'] % RESTART_THRESHOLD == 0) print('.', end='') sys.stdout.flush() ### Compute parameters compute_smt = list(check_smt) statistics['#smt_calls'] += 1 statistics['#parameter_candidates'] += 1 ts = time.time() (sat, model) = SMTsolve(compute_smt, params) te = time.time() statistics['parameter_synthesis.time'].append(te - ts) statistics['parameter_synthesis.model'].append(model if sat else {}) if not sat: total_time_end = time.time() statistics['cegis.time'] = total_time_end - total_time_start return False, {} ### Check k-correctness correct_smt = [] for line in check_smt: matched = False for p in params: if line.strip().startswith('(declare-fun ' + p): a, b, c, d = line.split(' ') correct_smt.append('(define-fun {0} {1} {2} {3})'.format( b, c, d[:-1], model[p])) matched = True if not matched: correct_smt.append(line) correct_smt.append('(declare-fun s0 () state)') for i in range(0, k): correct_smt.append('(declare-fun i{0} () input)'.format(i)) correct_smt.append('(assert (not (correct{0} s0 {1})))'.format( k, ' '.join("i{0}".format(cnt) for cnt in range(0, k)))) statistics['#smt_calls'] += 1 statistics['#counterexamples'] += 1 ts = time.time() (sat, cex) = SMTsolve(correct_smt, ['s0'] + ['i{0}'.format(j) for j in range(0, k)]) te = time.time() statistics['correctness_check.time'].append(te - ts) statistics['correctness_check.model'].append(cex if sat else {}) if not sat: total_time_end = time.time() statistics['cegis.time'] = total_time_end - total_time_start return True, model ### Make counterexamples as nasty as possible if r == 1 or (r >= 2 and statistics['#counterexamples'] % 2 == 0): state = sexpr.str2sexpr(cex['s0'])[0][1:] for i in range(0, len(state)): try_state = [] for j in range(0, len(state)): if i == j: ok, value = randomize_if_necessary(state[i]) try_state.append(value) else: try_state.append(state[j]) state_sexpr = sexpr.str2sexpr(cex['s0'])[0] state_sexpr[1:] = try_state if state_sexpr == sexpr.str2sexpr(cex['s0'])[0]: continue # skip the SMT check if no randomization happened state_sexpr = sexpr.sexpr2str(state_sexpr) nasty_check_smt = list(check_smt) nasty_check_smt.append( '(assert (not (correct{0} {1} {2})))'.format( k, state_sexpr, " ".join([cex["i" + str(cnt)] for cnt in range(0, k)]))) statistics['#smt_calls'] += 1 statistics['#randomizations'] += 1 ts = time.time() (sat, model) = SMTsolve(nasty_check_smt, params) te = time.time() statistics['counterexample_randomization.time'].append(te - ts) statistics['counterexample_randomization.model'].append( cex if sat else {}) if sat: # print("changed",state[i],"to",try_state[i]) state[i] = try_state[i] state_sexpr = sexpr.str2sexpr(cex['s0'])[0] state_sexpr[1:] = state if cex['s0'] != sexpr.sexpr2str(state_sexpr): print('G', end='') cex['s0'] = sexpr.sexpr2str(state_sexpr) ### Make sure that the next parameters are better check_smt.append('(assert (correct{0} {1} {2}))'.format( k, cex['s0'], " ".join([cex["i" + str(cnt)] for cnt in range(0, k)])))