def _ses_forecast(smoothing_level_constant: float, forecast_demand: Forecast,
                  forecast_length: int, orders_length: int) -> dict:
    """ Private function for executing the simple exponential smoothing forecast.
    """
    forecast_breakdown = [
        i for i in forecast_demand.simple_exponential_smoothing(
            smoothing_level_constant)
    ]
    ape = LinearRegression(forecast_breakdown)
    mape = forecast_demand.mean_aboslute_percentage_error_opt(
        forecast_breakdown)
    stats = ape.least_squared_error()
    simple_forecast = forecast_demand.simple_exponential_smoothing_forecast(
        forecast=forecast_breakdown, forecast_length=forecast_length)

    sum_squared_error = forecast_demand.sum_squared_errors(
        simple_forecast, smoothing_level_constant)
    standard_error = forecast_demand.standard_error(sum_squared_error,
                                                    orders_length,
                                                    smoothing_level_constant)
    regression_line = _regr_ln(stats=stats)
    log.log(
        logging.WARNING,
        "A STANDARD simple exponential smoothing forecast has been completed.")
    return {
        'forecast_breakdown': forecast_breakdown,
        'mape': mape,
        'statistics': stats,
        'forecast': simple_forecast,
        'alpha': smoothing_level_constant,
        'standard_error': standard_error,
        'regression': [i for i in regression_line.get('regression')]
    }
    def test_htces(self):
        forecast_demand = Forecast(self.__orders_ex)

        ses_forecast = [
            i for i in forecast_demand.simple_exponential_smoothing(
                *(self.__smoothing_level_constant, ))
        ]

        sum_squared_error = forecast_demand.sum_squared_errors(
            ses_forecast, self.__smoothing_level_constant)

        standard_error = forecast_demand.standard_error(
            sum_squared_error, len(self.__orders_ex),
            self.__smoothing_level_constant)
        total_orders = 0

        for order in self.__orders_ex[:self.__initial_estimate_period]:
            total_orders += order

        avg_orders = total_orders / self.__initial_estimate_period

        evo_mod = OptimiseSmoothingLevelGeneticAlgorithm(
            orders=self.__orders_ex,
            average_order=avg_orders,
            smoothing_level=self.__smoothing_level_constant,
            population_size=10,
            standard_error=standard_error,
            recombination_type='two_point')

        ses_evo_forecast = evo_mod.simple_exponential_smoothing_evo(
            smoothing_level_constant=self.__smoothing_level_constant,
            initial_estimate_period=self.__initial_estimate_period)
        self.assertEqual(7, len(ses_evo_forecast))
 def test_simple_exponential_smoothing(self):
     total_orders = 0
     for order in self.__orders_ex[:12]:
         total_orders += order
     avg_orders = total_orders / 12
     f = Forecast(self.__orders_ex, avg_orders)
     alpha = [0.2, 0.3, 0.4, 0.5, 0.6]
     s = [i for i in f.simple_exponential_smoothing(*alpha)]
     sum_squared_error = f.sum_squared_errors(s, 0.5)
     self.assertEqual(28447.178137569197, sum_squared_error[0.5])
Beispiel #4
0
 def test_simple_exponential_smoothing(self):
     total_orders = 0
     for order in self.__orders_ex[:12]:
         total_orders += order
     avg_orders = total_orders / 12
     f = Forecast(self.__orders_ex, avg_orders)
     alpha = [0.2, 0.3, 0.4, 0.5, 0.6]
     s = [i for i in f.simple_exponential_smoothing(*alpha)]
     sum_squared_error = f.sum_squared_errors(s, 0.5)
     self.assertEqual(28447.178137569197, sum_squared_error[0.5])
 def test_standard_error(self):
     total_orders = 0
     for order in self.__orders_ex[:12]:
         total_orders += order
     avg_orders = total_orders / 12
     f = Forecast(self.__orders_ex, avg_orders)
     alpha = [0.2, 0.3, 0.4, 0.5, 0.6]
     s = [i for i in f.simple_exponential_smoothing(*alpha)]
     sum_squared_error = f.sum_squared_errors(s, 0.5)
     standard_error = f.standard_error(sum_squared_error, len(self.__orders_ex), 0.5)
     self.assertEqual(29, round(standard_error))
Beispiel #6
0
 def test_standard_error(self):
     total_orders = 0
     for order in self.__orders_ex[:12]:
         total_orders += order
     avg_orders = total_orders / 12
     f = Forecast(self.__orders_ex, avg_orders)
     alpha = [0.2, 0.3, 0.4, 0.5, 0.6]
     s = [i for i in f.simple_exponential_smoothing(*alpha)]
     sum_squared_error = f.sum_squared_errors(s, 0.5)
     standard_error = f.standard_error(sum_squared_error, len(self.__orders_ex), 0.5)
     self.assertEqual(29, round(standard_error))
Beispiel #7
0
    def _run_exponential_smoothing_forecast(self, individual: tuple) -> dict:

        f = Forecast(self.__orders, self.__average_order)
        simple_expo_smoothing = []
        for sm_lvl in individual:
            p = [i for i in f.simple_exponential_smoothing(sm_lvl)]
            # print(p)
            simple_expo_smoothing.append(p)

        appraised_individual = {}
        for smoothing_level in individual:
            sum_squared_error = f.sum_squared_errors_indi(
                simple_expo_smoothing, smoothing_level)
            standard_error = f.standard_error(sum_squared_error,
                                              len(self.__orders),
                                              smoothing_level)
            appraised_individual.update({smoothing_level: standard_error})
        # print('The standard error as a trait has been calculated {}'.format(appraised_individual))
        return appraised_individual
    def test_optimise_smoothing_level_genetic_algorithm(self):
        total_orders = 0
        for order in self.__orders_ex[:12]:
            total_orders += order
        avg_orders = total_orders / 12
        f = Forecast(self.__orders_ex, avg_orders)
        alpha = [0.2, 0.3, 0.4, 0.5, 0.6]
        s = [i for i in f.simple_exponential_smoothing(*alpha)]
        sum_squared_error = f.sum_squared_errors(s, 0.5)
        standard_error = f.standard_error(sum_squared_error, len(self.__orders_ex), 0.5, 2)
        evo_mod = OptimiseSmoothingLevelGeneticAlgorithm(orders=self.__orders_ex,
                                                         average_order=avg_orders,
                                                         smoothing_level=0.5,
                                                         population_size=10,
                                                         standard_error=standard_error,
                                                         recombination_type='single_point')
        pop = evo_mod.initial_population()

        self.assertGreaterEqual(len(pop), 2)
        self.assertNotAlmostEqual(pop[0], 20.72, places=3)
        self.assertNotAlmostEqual(pop[1], 0.73, places=3)
Beispiel #9
0
    def test_optimise_smoothing_level_genetic_algorithm(self):
        total_orders = 0
        for order in self.__orders_ex[:12]:
            total_orders += order
        avg_orders = total_orders / 12
        f = Forecast(self.__orders_ex, avg_orders)
        alpha = [0.2, 0.3, 0.4, 0.5, 0.6]
        s = [i for i in f.simple_exponential_smoothing(*alpha)]
        sum_squared_error = f.sum_squared_errors(s, 0.5)
        standard_error = f.standard_error(sum_squared_error, len(self.__orders_ex), 0.5, 2)
        evo_mod = OptimiseSmoothingLevelGeneticAlgorithm(orders=self.__orders_ex,
                                                         average_order=avg_orders,
                                                         smoothing_level=0.5,
                                                         population_size=10,
                                                         standard_error=standard_error,
                                                         recombination_type='single_point')
        pop = evo_mod.initial_population()

        self.assertGreaterEqual(len(pop), 2)
        self.assertNotAlmostEqual(pop[0], 20.72, places=3)
        self.assertNotAlmostEqual(pop[1], 0.73, places=3)
Beispiel #10
0
    def simple_exponential_smoothing_evo(
            self,
            smoothing_level_constant: float,
            initial_estimate_period: int,
            recombination_type: str = 'single_point',
            population_size: int = 10,
            forecast_length: int = 5) -> dict:
        """ Simple exponential smoothing using evolutionary algorithm for optimising smoothing level constant (alpha value)

            Args:
                initial_estimate_period (int):      The number of previous data points required for initial level estimate.
                smoothing_level_constant (float):   Best guess at smoothing level constant appropriate for forecast.

           Returns:
               dict:

            Example:

        """
        log.log(
            logging.INFO, "Executing simple exponential smoothing. "
            "SMOOTHING_LEVEL: {} "
            "INITIAL_ESTIMATE_PERIOD: {} "
            "RECOMBINATION_TYPE: {} "
            "POPULATION_SIZE: {} "
            "FORECAST_LENGTH: {}".format(smoothing_level_constant,
                                         initial_estimate_period,
                                         recombination_type, population_size,
                                         forecast_length))
        if None != self.__recombination_type:
            recombination_type = self.__recombination_type

        sum_orders = 0

        for demand in self.__orders[:initial_estimate_period]:
            sum_orders += demand

        avg_orders = sum_orders / initial_estimate_period

        forecast_demand = Forecast(self.__orders, avg_orders)

        #calls simple_exponential_smoothing method from Forecast object
        ses_forecast = [
            i for i in forecast_demand.simple_exponential_smoothing(
                *(smoothing_level_constant, ))
        ]

        sum_squared_error = forecast_demand.sum_squared_errors(
            ses_forecast, smoothing_level_constant)

        standard_error = forecast_demand.standard_error(
            sum_squared_error, len(self.__orders), smoothing_level_constant)

        evo_mod = OptimiseSmoothingLevelGeneticAlgorithm(
            orders=self.__orders,
            average_order=avg_orders,
            smoothing_level=smoothing_level_constant,
            population_size=population_size,
            standard_error=standard_error,
            recombination_type=recombination_type)

        optimal_alpha = evo_mod.initial_population()

        optimal_ses_forecast = [
            i for i in forecast_demand.simple_exponential_smoothing(
                optimal_alpha[1])
        ]

        ape = LinearRegression(optimal_ses_forecast)
        mape = forecast_demand.mean_aboslute_percentage_error_opt(
            optimal_ses_forecast)
        stats = ape.least_squared_error()
        simple_forecast = forecast_demand.simple_exponential_smoothing_forecast(
            forecast=optimal_ses_forecast, forecast_length=forecast_length)

        sum_squared_error = forecast_demand.sum_squared_errors(
            optimal_ses_forecast, optimal_alpha[1])
        standard_error = forecast_demand.standard_error(
            sum_squared_error, len(self.__orders), optimal_alpha[1])
        regression = {
            'regression': [(stats.get('slope') * i) + stats.get('intercept')
                           for i in range(0, 12)]
        }

        log.log(
            logging.INFO,
            "An OPTIMISED simple exponential smoothing forecast has been completed"
        )
        return {
            'forecast_breakdown': optimal_ses_forecast,
            'mape': mape,
            'statistics': stats,
            'forecast': simple_forecast,
            'optimal_alpha': optimal_alpha[1],
            'standard_error': standard_error,
            'regression': [i for i in regression.get('regression')]
        }
def simple_exponential_smoothing_forecast(demand: list = None, smoothing_level_constant: float = 0.5,
                                          forecast_length: int = 5, initial_estimate_period: int = 6, **kwargs) -> dict:
    """ Performs a simple exoponential smoothing forecast on

    Args:
        forecast_length (int):              Number of periods to extend the forecast.
        demand (list):                      Original historical demand.
        smoothing_level_constant (float):   Alpha value
        initial_estimate_period (int):      Number of period to use to derive an average for the initial estimate.
        **ds (pd.DataFrame):                Data frame with raw data.
        **optimise (bool)                   Optimisation flag for exponential smoothing forecast.

    Returns:
        dict:       Simple exponential forecast

    Examples:

    >>> from supplychainpy.model_demand import simple_exponential_smoothing_forecast
    >>> orders = [165, 171, 147, 143, 164, 160, 152, 150, 159, 169, 173, 203, 169, 166, 162, 147, 188, 161, 162,
    ...           169, 185, 188, 200, 229, 189, 218, 185, 199, 210, 193, 211, 208, 216, 218, 264, 304]
    >>> ses = simple_exponential_smoothing_forecast(demand=orders, alpha=0.5, forecast_length=6, initial_period=18)


    """
    ds = kwargs.get('ds', 'UNKNOWN')
    if ds is not UNKNOWN:
        orders = list(kwargs.get('ds', "UNKNOWN"))
    else:
        orders = [int(i) for i in demand]
    forecast_demand = Forecast(orders)

    # optimise, population_size, genome_length, mutation_probability, recombination_types
    if len(kwargs) != 0:
        optimise_flag = kwargs.get('optimise', "UNKNOWN")
        if optimise_flag is not UNKNOWN:

            ses_forecast = [i for i in forecast_demand.simple_exponential_smoothing(*(smoothing_level_constant,))]

            sum_squared_error = forecast_demand.sum_squared_errors(ses_forecast, smoothing_level_constant)

            standard_error = forecast_demand.standard_error(sum_squared_error, len(orders), smoothing_level_constant)
            total_orders = 0

            for order in orders[:initial_estimate_period]:
                total_orders += order

            avg_orders = total_orders / initial_estimate_period

            evo_mod = OptimiseSmoothingLevelGeneticAlgorithm(orders=orders,
                                                             average_order=avg_orders,
                                                             smoothing_level=smoothing_level_constant,
                                                             population_size=10,
                                                             standard_error=standard_error,
                                                             recombination_type='single_point')

            ses_evo_forecast = evo_mod.simple_exponential_smoothing_evo(
                smoothing_level_constant=smoothing_level_constant,
                initial_estimate_period=initial_estimate_period)

            return ses_evo_forecast
        else:
            return _ses_forecast(smoothing_level_constant=smoothing_level_constant,
                                 forecast_demand=forecast_demand,
                                 forecast_length=forecast_length)
    else:
        return _ses_forecast(smoothing_level_constant=smoothing_level_constant,
                             forecast_demand=forecast_demand,
                             forecast_length=forecast_length)
def simple_exponential_smoothing_forecast(
        demand: list,
        smoothing_level_constant: float = 0.5,
        optimise: bool = True,
        forecast_length: int = 5,
        initial_estimate_period: int = 6,
        **kwargs) -> dict:
    """ Performs a simple exponential smoothing forecast on historical demand.

    Args:
        forecast_length (int):              Number of periods to extend the forecast.
        demand (list):                      Original historical demand.
        smoothing_level_constant (float):   Alpha value
        initial_estimate_period (int):      Number of period to use to derive an average for the initial estimate.
        **ds (pd.DataFrame):                Data frame with raw data.
        **optimise (bool)                   Optimisation flag for exponential smoothing forecast.

    Returns:
        dict: Simple exponential forecast

    Examples:

    >>> from supplychainpy.model_demand import simple_exponential_smoothing_forecast
    >>> orders = [165, 171, 147, 143, 164, 160, 152, 150, 159, 169, 173, 203, 169, 166, 162, 147, 188, 161, 162,
    ...           169, 185, 188, 200, 229, 189, 218, 185, 199, 210, 193, 211, 208, 216, 218, 264, 304]
    >>> ses = simple_exponential_smoothing_forecast(demand=orders, alpha=0.5, forecast_length=6, initial_period=18)


    """
    try:
        ds = kwargs.get('ds', 'UNKNOWN')
        if ds is not UNKNOWN:
            orders = list(kwargs.get('ds', "UNKNOWN"))
        else:
            orders = [int(i) for i in demand]
            forecast_demand = Forecast(orders)

            log.log(logging.INFO, "Started simple exponential smoothing")
            # optimise, population_size, genome_length, mutation_probability, recombination_types
            if optimise:
                log.log(logging.INFO, "Using solver version to find alpha.")
                ses_forecast = [
                    i for i in forecast_demand.simple_exponential_smoothing(
                        *(smoothing_level_constant, ))
                ]
                sum_squared_error = forecast_demand.sum_squared_errors(
                    ses_forecast, smoothing_level_constant)
                standard_error = forecast_demand.standard_error(
                    sum_squared_error, len(orders), smoothing_level_constant)
                total_orders = 0
                for order in orders[:initial_estimate_period]:
                    total_orders += order
                avg_orders = total_orders // initial_estimate_period
                evo_mod = OptimiseSmoothingLevelGeneticAlgorithm(
                    orders=orders,
                    average_order=avg_orders,
                    smoothing_level=smoothing_level_constant,
                    population_size=10,
                    standard_error=standard_error,
                    recombination_type='single_point')

                ses_evo_forecast = evo_mod.simple_exponential_smoothing_evo(
                    smoothing_level_constant=smoothing_level_constant,
                    initial_estimate_period=initial_estimate_period)
                return ses_evo_forecast
            else:
                orders = [int(i) for i in demand]
                return _ses_forecast(
                    smoothing_level_constant=smoothing_level_constant,
                    forecast_demand=forecast_demand,
                    forecast_length=forecast_length,
                    orders_length=len(orders))

    except TypeError as e:
        if demand is None:
            print(
                "Please supply a list of demand values. Use the keyword \'demand=\'\n{}"
                .format(e))
    except OSError as e:
        print(e)