def one_fun_boole():
    x0 = 0
    x1 = 10
    step_sizes = [0.025, 0.05, 0.075, 0.1, 0.15, 0.2, 0.25, 0.4]
    # step_sizes = [0.05, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.3, 0.4]
    dim_state = 5
    dim_action = len(step_sizes)
    memory = 1
    env = IntegrationEnv(fun=Sinus(),
                         max_iterations=256,
                         initial_step_size=0.1,
                         step_sizes=step_sizes,
                         error_tol=0.000001,
                         memory=memory,
                         nodes_per_integ=dim_state)
    predictor = PredictorQ(
        build_value_model(dim_state=dim_state,
                          dim_action=dim_action,
                          filename='predictor',
                          memory=memory), load('scaler_boole_mem1.bin'))
    # integrator = IntegratorLinReg(step_sizes, load('linreg_models.bin'), load('scaler.bin'))
    integrator = Boole()

    _, evals, x1, errors = integrate_env(predictor,
                                         integrator,
                                         env,
                                         x0,
                                         x1,
                                         plot=True)
    print('new x1: {}'.format(x1))
    print('Predictor error total: {}'.format(np.sum(errors)))
    print('Predictor error per step: {}'.format(np.mean(errors)))
    print('Predictor evals: {}'.format(evals))
    print('')

    env.reset(reset_params=False)
    booles = BoolesRule(env.fun, x0, x1)
    integ_simps, errors = booles(num_evals=evals, stepwise_error=True)
    print('Boole error total: {}'.format(np.sum(errors)))
    print('Boole error per step: {}'.format(np.mean(errors)))
    print('Boole evals: {}'.format(booles.evals))
    print('')
    booles.plot()

    env.reset(reset_params=False)
    simps = Simps(env.fun, x0, x1)
    integ_simps, errors = simps(num_evals=evals, stepwise_error=True)
    print('Simpson error total: {}'.format(np.sum(errors)))
    print('Simpson error per step: {}'.format(np.mean(errors)))
    print('Simpson evals: {}'.format(simps.evals))
    print('')
    simps.plot()

    env.reset(reset_params=False)
    rom = Romberg(env.fun, x0, x1, tol=0.0005, order=3)
    integ, errors = rom(0.15, stepwise_errors=True)
    print('Romberg error total: {}'.format(np.sum(errors)))
    print('Romberg error per step: {}'.format(np.mean(errors)))
    print('Romberg evals: {}'.format(rom.evals))
    rom.plot()
def pareto_model():
    x0 = -1
    x1 = 1
    num_samples = 500
    memory = 1

    # step_sizes = [0.025, 0.05, 0.075, 0.1, 0.15, 0.2, 0.25, 0.4]
    # step_sizes = [0.05, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.3, 0.4]
    # step_sizes = [0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.75]
    step_sizes = [0.05, 0.075, 0.1, 0.125, 0.15, 0.2, 0.3, 0.67]
    dim_state = 3
    dim_action = len(step_sizes)
    env = IntegrationEnv(fun=BrokenPolynomial(),
                         max_iterations=1000,
                         initial_step_size=0.075,
                         step_sizes=step_sizes,
                         error_tol=0.0005,
                         memory=memory,
                         nodes_per_integ=dim_state)
    predictor = PredictorQ(
        build_value_model(dim_state=dim_state,
                          dim_action=dim_action,
                          filename='predictor',
                          memory=memory), load('scaler_mem1.bin'))

    # integrator = IntegratorLinReg(step_sizes, load('linreg_models_estim.bin'))
    integrator = Simpson()
    # estimator = Estimator(build_estimator_model(dim_state, lr=0.0001, filename='estimator'), load('scaler.bin'),
    #                       threshold=100 * 7.5e-6)

    errors = []
    steps = []
    x1s = []
    for i in range(num_samples):
        if i % 10 == 0:
            print(i)

        env.reset()
        _, evals, this_x1, err = integrate_env(predictor, integrator, env, x0,
                                               x1)
        errors.append(np.mean(err))
        steps.append(evals)
        x1s.append(this_x1)

    print(np.mean(steps))
    print(np.mean(errors))
    print(np.mean(x1s))
    print(np.quantile(errors, 0.9))
    np.save('pareto_model_mem1.npy',
            np.array([np.mean(errors), np.mean(steps)]))

    plt.hist(errors, 25)
    plt.show()
def one_fun():
    x0 = -1
    x1 = 1
    # step_sizes = [0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.75]
    # step_sizes = [0.05, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.3, 0.4]
    step_sizes = [0.05, 0.075, 0.1, 0.125, 0.15, 0.2, 0.3, 0.67]
    dim_state = 3
    dim_action = len(step_sizes)
    memory = 1
    env = IntegrationEnv(fun=BrokenPolynomial(),
                         max_iterations=256,
                         initial_step_size=0.075,
                         step_sizes=step_sizes,
                         error_tol=7.5e-6,
                         memory=memory)
    predictor = PredictorQ(
        build_value_model(dim_state=dim_state,
                          dim_action=dim_action,
                          filename='predictor',
                          memory=memory), load('scaler_mem1.bin'))
    # integrator = IntegratorLinReg(step_sizes, load('linreg_models.bin'), load('scaler.bin'))
    integrator = Simpson()

    # _, evals, _, errors = integrate_env(predictor, Simpson(), env, x0, x1, plot=True)
    # print('new x1: {}'.format(x1))
    # print('Predictor error total: {}'.format(np.sum(errors)))
    # print('Predictor error per step: {}'.format(np.mean(errors)))
    # print('Predictor evals: {}'.format(evals))
    # print('')

    env.reset(reset_params=False)
    _, evals, x1, errors = integrate_env(predictor,
                                         integrator,
                                         env,
                                         x0,
                                         x1,
                                         plot=True)
    print('new x1: {}'.format(x1))
    print('Predictor error total: {}'.format(np.sum(errors)))
    print('Predictor error per step: {}'.format(np.mean(errors)))
    print('Predictor evals: {}'.format(evals))
    print('')

    env.reset(reset_params=False)
    asr = AdaptSimpsConstEvals(env.fun, x0, x1)
    asr(200)
    errors = asr.stepwise_errors
    print('ASR error total: {}'.format(np.sum(errors)))
    print('ASR error per step: {}'.format(np.mean(errors)))
    print('ASR evals: {}'.format(asr.evals))
    print('')
    asr.plot()

    env.reset(reset_params=False)
    simps = Simps(env.fun, x0, x1)
    integ_simps, errors = simps(num_evals=evals, stepwise_error=True)
    # integ_simps, errors = simps(step_size=0.11, stepwise_error=True)
    print('Simpson error total: {}'.format(np.sum(errors)))
    print('Simpson error per step: {}'.format(np.mean(errors)))
    print('Simpson evals: {}'.format(simps.evals))
    print('')
    simps.plot()

    env.reset(reset_params=False)
    rom = Romberg(env.fun, x0, x1, tol=0.0005, order=2)
    integ, errors = rom(0.15, stepwise_errors=True)
    print('Romberg error total: {}'.format(np.sum(errors)))
    print('Romberg error per step: {}'.format(np.mean(errors)))
    print('Romberg evals: {}'.format(rom.evals))
    rom.plot()
def compare_romberg():
    x0 = 0.0
    num_samples = 100
    error_predictor = []
    error_rom = []
    evals_rom = []
    evals_predictor = []

    step_sizes = [0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.75]
    # step_sizes = [0.05, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.3, 0.4]
    dim_state = 3
    dim_action = len(step_sizes)
    env = IntegrationEnv(fun=Sinus(),
                         max_iterations=256,
                         initial_step_size=0.15,
                         step_sizes=step_sizes,
                         error_tol=0.0005)
    predictor = PredictorQ(
        build_value_model(dim_state=dim_state,
                          dim_action=dim_action,
                          filename='predictor'), load('scaler.bin'))

    for i in range(num_samples):
        if i % 10 == 0:
            print(i)

        x1 = 20.0

        # model
        env.reset()
        _, evals, x1, errors = integrate_env(predictor, Simpson(), env, x0, x1)
        error_pred_step = np.mean(errors)
        env.reset(reset_params=False)

        # romberg
        tol = 0.0003

        rom = Romberg(env.fun, x0, x1, tol=tol, order=2)
        integ_rom, errors = rom(0.15, True)
        error_rom_step = np.mean(errors)
        evals_rom_step = rom.evals

        # for j in range(10):
        #     rom = Romberg(env.fun, x0, x1, tol=tol, order=2)
        #     integ_rom, errors = rom(0.15, True)
        #     error_rom_step = np.mean(errors)
        #     evals_rom_step = rom.evals
        #     if error_rom_step < 0.0001:
        #         tol *= 2.0
        #     elif error_rom_step > 0.0005:
        #         tol /= 3.0
        #     else:
        #         break

        error_predictor.append(error_pred_step)
        error_rom.append(error_rom_step)
        evals_predictor.append(evals)
        evals_rom.append(evals_rom_step)

    # error_rom = np.array(error_rom)
    # not_converged = np.concatenate((error_rom[error_rom > 0.0005], error_rom[error_rom < 0.0001]))
    # if len(not_converged > 0):
    #     print('romberg did not converge in some cases:')
    #     print(not_converged)

    mean_error_predictor = np.mean(error_predictor)
    var_error_predictor = np.var(error_predictor)

    mean_error_rom = np.mean(error_rom)
    var_error_rom = np.var(error_rom)

    mean_evals_predictor = np.mean(evals_predictor)
    var_evals_predictor = np.var(evals_predictor)

    mean_evals_rom = np.mean(evals_rom)
    var_evals_rom = np.var(evals_rom)

    print(
        'Avg. predictor number of function evaluations per episode: {}'.format(
            mean_evals_predictor))
    print('Avg. predictor error per step: {}'.format(mean_error_predictor))
    print('Avg. romberg number of function evaluations per episode: {}'.format(
        mean_evals_rom))
    print('Avg. romberg error per step: {}'.format(mean_error_rom))
    print('')
    print(
        'Variance of predictor number of function evaluations per episode: {}'.
        format(var_evals_predictor))
    print(
        'Variance of predictor error per step: {}'.format(var_error_predictor))
    print('Variance of rom number of function evaluations per episode: {}'.
          format(var_evals_rom))
    print('Variance of rom error per step: {}'.format(var_error_rom))
def compare_simps_tol():
    """ compare model to simpson rule, stepsize for simps is adapted to match tol. """
    x0 = 0.0
    num_samples = 2000
    error_predictor = []
    error_simps = []
    evals_simps = []
    evals_predictor = []

    step_sizes = [0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.75]
    # step_sizes = [0.05, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.3, 0.4]
    dim_state = 3
    dim_action = len(step_sizes)
    env = IntegrationEnv(fun=SuperposeSinus(5),
                         max_iterations=256,
                         initial_step_size=0.15,
                         step_sizes=step_sizes,
                         error_tol=0.0005)
    predictor = PredictorQ(
        build_value_model(dim_state=dim_state,
                          dim_action=dim_action,
                          filename='predictor'), load('scaler.bin'))

    for i in range(num_samples):
        if i % 10 == 0:
            print(i)

        x1 = 20.0

        # model
        env.reset()
        _, evals, x1, errors = integrate_env(predictor, Simpson(), env, x0, x1)
        error_pred_step = np.mean(errors)
        env.reset(reset_params=False)

        # simpson
        step_size = 0.177
        simp = Simps(env.fun, x0, x1)
        _, error_simps_step = simp(step_size=step_size, stepwise_error=True)
        error_simps_step = np.mean(error_simps_step)
        evals_simps_step = simp.evals
        # for j in range(10):
        #     simp = Simps(env.fun, x0, x1)
        #     integ_rom, error_simps_step = simp(step_size=step_size, stepwise_error=True)
        #     error_simps_step /= (simp.evals - 1.0) / 2.0
        #     evals_simps_step = simp.evals
        #     if error_simps_step < 0.0001:
        #         step_size *= 1.5
        #     elif error_simps_step > 0.0005:
        #         step_size /= 2.0
        #     else:
        #         break

        error_predictor.append(error_pred_step)
        error_simps.append(error_simps_step)
        evals_predictor.append(evals)
        evals_simps.append(evals_simps_step)

    error_simps = np.array(error_simps)
    not_converged = np.concatenate(
        (error_simps[error_simps > 0.0005], error_simps[error_simps < 0.0001]))
    if len(not_converged > 0):
        print('simps did not converge in some cases:')
        print(not_converged)

    mean_error_predictor = np.mean(error_predictor)
    var_error_predictor = np.var(error_predictor)

    mean_error_simps = np.mean(error_simps)
    var_error_simps = np.var(error_simps)

    mean_evals_predictor = np.mean(evals_predictor)
    var_evals_predictor = np.var(evals_predictor)

    mean_evals_simps = np.mean(evals_simps)
    var_evals_simps = np.var(evals_simps)

    print(
        'Avg. predictor number of function evaluations per episode: {}'.format(
            mean_evals_predictor))
    print('Avg. predictor error per step: {}'.format(mean_error_predictor))
    print('Avg. simpson number of function evaluations per episode: {}'.format(
        mean_evals_simps))
    print('Avg. simpson error per step: {}'.format(mean_error_simps))
    print('')
    print(
        'Variance of predictor number of function evaluations per episode: {}'.
        format(var_evals_predictor))
    print(
        'Variance of predictor error per step: {}'.format(var_error_predictor))
    print('Variance of simpson number of function evaluations per episode: {}'.
          format(var_evals_simps))
    print('Variance of simpson error per step: {}'.format(var_error_simps))