def test_normal_distribution_mean(self):
        """ Verifies mean and variance for random normal distribution.
        """
        # arrange
        app_dir = os.path.dirname(__file__, )
        rel_path = 'supplychainpy/data.csv'
        abs_file_path = os.path.abspath(os.path.join(app_dir, '..', rel_path))
        # act
        orders_analysis = model_inventory.analyse_orders_abcxyz_from_file(
            file_path=abs_file_path,
            z_value=Decimal(1.28),
            reorder_cost=Decimal(5000),
            file_type="csv")

        sim = monte_carlo.SetupMonteCarlo(
            analysed_orders=orders_analysis.orders, period_length=1)
        for sku in orders_analysis.orders:
            item = sku.orders_summary()
            if item['sku'] == 'KR202-209':
                # assertd
                diff = abs(
                    float(item['average_order']) - float(
                        np.mean(sim.normal_random_distribution[0]['KR202-209']
                                [0][0])))
                self.assertLess(diff, float(item['standard_deviation']))
예제 #2
0
 def test_build_window(self):
     """Test building simulation window, a transactioin block
         for the discrete events simulation."""
     sim_dict = {}
     period_length = 12
     sim_collection = []
     simulation = monte_carlo.SetupMonteCarlo(
         analysed_orders=self.__orders_analysis)
     random_demand = simulation.generate_normal_random_distribution(
         period_length=period_length)
     for sim_window in simulation.build_window(
             random_normal_demand=random_demand,
             period_length=period_length):
         sim_dict = {
             "index": "{:.0f}".format(sim_window.index),
             "period": "{:.0f}".format(sim_window.position),
             "sku_id": sim_window.sku_id,
             "opening_stock": "{:.0f}".format(sim_window.opening_stock),
             "demand": "{:.0f}".format(sim_window.demand),
             "closing_stock": "{:.0f}".format(sim_window.closing_stock),
             "delivery":
             "{:.0f}".format(sim_window.purchase_order_receipt_qty),
             "backlog": "{:.0f}".format(sim_window.backlog)
         }
     sim_collection.append([sim_dict])
     self.assertEqual(len(sim_collection), 1)
예제 #3
0
 def test_variance(self):
     """ Verifies mean and variance for random normal distribution."""
     sim = monte_carlo.SetupMonteCarlo(analysed_orders=self.__orders_analysis, period_length=1)
     for sku in self.__orders_analysis:
         item = sku.orders_summary()
         if item['sku'] == 'KR202-209':
             self.assertLess((float(item['standard_deviation']) - \
             float(sim.normal_random_distribution[0]['KR202-209'][0][0])),
                             Decimal(item['standard_deviation']))
예제 #4
0
    def setUp(self):
        self.__skus = ['KR202-209', 'KR202-210', 'KR202-211']

        self.__orders_analysis = analyse_orders_abcxyz_from_file(
            file_path=ABS_FILE_PATH['COMPLETE_CSV_SM'],
            z_value=Decimal(1.28),
            reorder_cost=Decimal(5000),
            file_type="csv",
            length=12)

        self.__sim = monte_carlo.SetupMonteCarlo(
            analysed_orders=self.__orders_analysis, period_length=10)
    def test_build_window(self):

        app_dir = os.path.dirname(__file__, )
        rel_path = 'supplychainpy/data.csv'
        abs_file_path = os.path.abspath(os.path.join(app_dir, '..', rel_path))

        orders_analysis = model_inventory.analyse_orders_abcxyz_from_file(
            file_path=abs_file_path,
            z_value=Decimal(1.28),
            reorder_cost=Decimal(5000),
            file_type="csv")
        period_length = 12
        sim_collection = []
        for k in range(0, 1):
            simulation = monte_carlo.SetupMonteCarlo(
                analysed_orders=orders_analysis.orders)
            random_demand = simulation.generate_normal_random_distribution(
                period_length=period_length)
            for sim_window in simulation.build_window(
                    random_normal_demand=random_demand,
                    period_length=period_length):
                sim_dict = {
                    "index":
                    "{:.0f}".format(sim_window.index),
                    "period":
                    "{:.0f}".format(sim_window.position),
                    "sku_id":
                    sim_window.sku_id,
                    "opening_stock":
                    "{:.0f}".format(sim_window.opening_stock),
                    "demand":
                    "{:.0f}".format(sim_window.demand),
                    "closing_stock":
                    "{:.0f}".format(sim_window.closing_stock),
                    "delivery":
                    "{:.0f}".format(sim_window.purchase_order_receipt_qty),
                    "backlog":
                    "{:.0f}".format(sim_window.backlog)
                }
            sim_collection.append([sim_dict])
            self.assertEqual(len(sim_collection), 1)
예제 #6
0
def run_monte_carlo(orders_analysis: list,
                    runs: int,
                    period_length: int = 12) -> list:
    """Runs monte carlo simulation.

    Generates random distribution for demand over period specified and creates a simulation window for opening_stock,
    demand, closing_stock, delivery and backlog for each sku in the data set. Creates a transaction summary window
    for inventory movements.

    Args:
        orders_analysis (list): list of UncertainDemand objects, containing the results of inventory analysis.
        period_length (int):    The number of periods define the simulation window e.g. 12 weeks, months etc.
        runs (int):             The number of times to run the simulation.

    Returns:
        list:       A list containing the transaction summary for each period.
                    [[{'closing_stock': '0', 'backlog': '240', 'po_quantity': '6009', 'po_raised': 'PO 49', 'revenue':
                    '1145799', 'opening_stock': '1700', 'index': '9', 'period': '1', 'shortage_units': '240.4612',
                    'po_received': '', 'delivery': '0', 'shortage_cost': '48621', 'demand': '1940',
                    'quantity_sold': '1699', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '240', 'backlog': '852', 'po_quantity': '6380', 'po_raised':
                    'PO 59', 'revenue': '0', 'opening_stock': '0', 'index': '9', 'period': '2',
                    'shortage_units': '611.5989', 'po_received': '', 'delivery': '0', 'shortage_cost': '123665',
                    'demand': '612', 'quantity_sold': '0', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '0', 'backlog': '383', 'po_quantity': '6152', 'po_raised':
                    'PO 69', 'revenue': '162070', 'opening_stock': '240', 'index': '9', 'period': '3',
                    'shortage_units': '383.4993', 'po_received': '', 'delivery': '0', 'shortage_cost': '77543',
                    'demand': '624', 'quantity_sold': '240', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '4463', 'backlog': '383', 'po_quantity': '1689', 'po_raised': 'PO 79',
                    'revenue': '2749508', 'opening_stock': '0', 'index': '9', 'period': '4',
                    'shortage_units': '0.000000', 'po_received': 'PO 49', 'delivery': '6010',
                    'shortage_cost': '0', 'demand': '1547', 'quantity_sold': '4079', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '8002', 'backlog': '0', 'po_quantity': '0', 'po_raised': '',
                    'revenue': '5393458', 'opening_stock': '4463', 'index': '9', 'period': '5',
                    'shortage_units': '0.000000', 'po_received': 'PO 59', 'delivery': '6381',
                    'shortage_cost': '0', 'demand': '2841', 'quantity_sold': '8002', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '13594', 'backlog': '0', 'po_quantity': '0', 'po_raised': '',
                    'revenue': '9162457', 'opening_stock': '8002', 'index': '9', 'period': '6',
                    'shortage_units': '0.000000', 'po_received': 'PO 69', 'delivery': '6153',
                    'shortage_cost': '0', 'demand': '561', 'quantity_sold': '13594', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '13144', 'backlog': '0', 'po_quantity': '0', 'po_raised': '',
                    'revenue': '8859056', 'opening_stock': '13594', 'index': '9', 'period': '7',
                    'shortage_units': '0.000000', 'po_received': 'PO 79', 'delivery': '1690',
                    'shortage_cost': '0', 'demand': '2140', 'quantity_sold': '13144', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '11666', 'backlog': '0', 'po_quantity': '0', 'po_raised': '',
                    'revenue': '7862688', 'opening_stock': '13144', 'index': '9', 'period': '8',
                    'shortage_units': '0.000000', 'po_received': '', 'delivery': '0', 'shortage_cost': '0',
                    'demand': '1478', 'quantity_sold': '11665', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '8542', 'backlog': '0', 'po_quantity': '0', 'po_raised': '',
                    'revenue': '5757540', 'opening_stock': '11666', 'index': '9', 'period': '9',
                    'shortage_units': '0.000000', 'po_received': '', 'delivery': '0', 'shortage_cost': '0',
                    'demand': '3123', 'quantity_sold': '8542', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '7832', 'backlog': '0', 'po_quantity': '0', 'po_raised': '',
                    'revenue': '5278665', 'opening_stock': '8542', 'index': '9', 'period': '10',
                    'shortage_units': '0.000000', 'po_received': '', 'delivery': '0', 'shortage_cost': '0',
                    'demand': '710', 'quantity_sold': '7831', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '5379', 'backlog': '0', 'po_quantity': '389', 'po_raised': 'PO 149',
                    'revenue': '3625634', 'opening_stock': '7832', 'index': '9', 'period': '11', 'shortage_units':
                    '0.000000', 'po_received': '', 'delivery': '0', 'shortage_cost': '0', 'demand': '2453',
                    'quantity_sold': '5379', 'sku_id': 'KR202-217'}]
                    [{'closing_stock': '3799', 'backlog': '0', 'po_quantity': '1969', 'po_raised': 'PO 159',
                    'revenue': '2560610', 'opening_stock': '5379', 'index': '9', 'period': '12',
                    'shortage_units': '0.000000', 'po_received': '', 'delivery': '0', 'shortage_cost': '0',
                    'demand': '1580', 'quantity_sold': '3799', 'sku_id': 'KR202-217'}],...]

    """

    Transaction_report = []
    # add shortage cost,
    for k in range(0, runs):
        simulation = monte_carlo.SetupMonteCarlo(
            analysed_orders=orders_analysis)
        random_demand = simulation.generate_normal_random_distribution(
            period_length=period_length)
        for sim_window in simulation.build_window(
                random_normal_demand=random_demand,
                period_length=period_length):
            sim_dict = {
                "index":
                "{}".format(sim_window.index),
                "period":
                "{}".format(sim_window.position),
                "sku_id":
                sim_window.sku_id,
                "opening_stock":
                "{}".format(round(sim_window.opening_stock)),
                "demand":
                "{}".format(round(sim_window.demand)),
                "closing_stock":
                "{}".format(round(sim_window.closing_stock)),
                "delivery":
                "{}".format(round(sim_window.purchase_order_receipt_qty)),
                "backlog":
                "{:.0f}".format(sim_window.backlog),
                "po_raised":
                "{}".format(sim_window.po_number_raised),
                "po_received":
                "{}".format(sim_window.po_number_received),
                "po_quantity":
                "{:.0f}".format(int(sim_window.purchase_order_raised_qty)),
                "shortage_cost":
                "{:.0f}".format(Decimal(sim_window.shortage_cost)),
                "revenue":
                "{:.0f}".format(sim_window.revenue),
                "quantity_sold":
                "{:0.0f}".format(sim_window.sold),
                "shortage_units":
                "{:.0f}".format(sim_window.shortage_units)
            }
            Transaction_report.append([sim_dict])

    return Transaction_report
예제 #7
0
def random_demand(orders_analysis=None, period_length=None)->list:
    """"""
    simulation = monte_carlo.SetupMonteCarlo(analysed_orders=orders_analysis)
    r_demand = simulation.generate_normal_random_distribution(period_length=period_length)
    return r_demand