Пример #1
0
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)])))
Пример #2
0
 def writeSExpr(self, list):
     self.writeOut(sexpr.sexpr2str(list))
Пример #3
0
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)])))