File size: 2,337 Bytes
b13fa7f
 
 
 
 
56146fe
b13fa7f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cb82053
b13fa7f
 
 
 
 
 
 
 
cb82053
b13fa7f
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from abc import abstractmethod, ABC
import numpy as np
from scipy.stats import norm
from config import LEAD_TIME, DEFAULT_SERVICE_LEVEL, MC_SIMS, HISTO_DAYS

#Base Agent Environment
class Agent(ABC):
    def __init__(self, daily_demand_distribution):
        self.daily_demand_distribution = daily_demand_distribution

    @abstractmethod
    def compute_reorder_point(self, time_period) -> float:
        pass

    def get_historical_demand(self, time_period):
        start_time = time_period - HISTO_DAYS
        demand_list = self.daily_demand_distribution.daily_demand_distribution
        return [d.actual_demand for d in demand_list[start_time:time_period]]

class BaseAgent(Agent):

    def compute_reorder_point(self, time_period):
        historical_demand = self.get_historical_demand(time_period)
        demand_mean = np.mean(historical_demand)
        return demand_mean * LEAD_TIME

class SafetyStockAgent(Agent):

    def compute_reorder_point(self, time_period) -> float:
        historical_demand = self.get_historical_demand(time_period)

        demand_mean = np.mean(historical_demand)
        demand_std = np.std(historical_demand, ddof=1)  # sample standard deviation

        safety_stock = norm.ppf(DEFAULT_SERVICE_LEVEL) * demand_std * np.sqrt(LEAD_TIME)
        return demand_mean * LEAD_TIME + safety_stock

class ForecastAgent(Agent):
    def __init__(self, daily_demand_distribution, demand_mean, demand_std):
        super().__init__(daily_demand_distribution)
        self.demand_mean = demand_mean
        self.demand_std = demand_std

    def compute_reorder_point(self, time_period) -> float:
        safety_stock = norm.ppf(DEFAULT_SERVICE_LEVEL) * self.demand_std[time_period] * np.sqrt(LEAD_TIME)
        return self.demand_mean[time_period] * LEAD_TIME + safety_stock


class MonteCarloAgent(Agent):
    def __init__(self, daily_demand_distribution):
        super().__init__(daily_demand_distribution)
        self.q = DEFAULT_SERVICE_LEVEL

    def compute_reorder_point(self, time_period) -> float:
        samples = self.daily_demand_distribution.sample_lead_time_demand(
            time_period=time_period,
            daily_demand_distribution=self.daily_demand_distribution.daily_demand_distribution,
            mc_sims=MC_SIMS
        )
        return float(np.quantile(samples, self.q))