# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/04_Optimizers.ipynb (unless otherwise specified).

__all__ = ['minimize_objective', 'minimize_simple_smoothing', 'minimize_double_smoothing']

# Cell
from os import path
import requests
import numpy as np
import pandas as pd
from typing import List, Callable, Tuple
from skopt import gp_minimize
from time_series_model_basics import moving_average, smoothing, metrics, simulate_data
from functools import partial

# Cell
def minimize_objective(
    objective: Callable,
    param_names: List[str],
    param_ranges: List[Tuple[float, float]],
    *,
    ts: np.array,
    score_f: Callable = metrics.__mean_absolute_error,
) -> Tuple[float, float]:

    def smoothing_partial(*args: List[float]) -> float:

        forecast = smoothing.__single(
            ts=ts,
            alpha=alpha[0],
        )
        val = score_f(ts=ts, f=forecast)
        return val

    res = gp_minimize(
        smoothing_partial,
        [(0.0, 1), (0.0, 1)],
        n_calls=20,
    )
    print("x*=%.2f f(x*)=%.2f" % (res.x[0], res.fun))
    return res.x[0]

# Cell
def minimize_simple_smoothing(
    ts: np.array,
    score_f=metrics.__mean_absolute_error,
) -> float:

    def smoothing_partial(alpha: List[float]) -> float:
        forecast = smoothing.__single(
            ts=ts,
            alpha=alpha[0],
        )
        val = score_f(ts=ts, f=forecast)
        return val

    res = gp_minimize(
        smoothing_partial,
        [(0.0, 1)],
        n_calls=20,
    )
    print("x*=%.2f f(x*)=%.2f" % (res.x[0], res.fun))
    return res.x[0]

# Cell
def minimize_double_smoothing(
    ts: np.array,
    score_f=metrics.__mean_absolute_error,
) -> float:

    def smoothing_partial(args: List[float]) -> float:

        forecast = smoothing.__double(
            ts=ts,
            alpha=args[0],
            beta=args[1],
        )
        val = score_f(ts=ts, f=forecast)
        return val

    res = gp_minimize(
        smoothing_partial,
        [(0.0, 1), (0.0, 1)],
        n_calls=20,
    )
    print("x*=%.2f, y*=%.2f, f(x*,y*)=%.2f" % (
        res.x[0],
        res.x[1],
        res.fun,
    ))
    return res.x