コード例 #1
0
    def shortage_cost(shortage_cost, shortage_quantity):
        """
        Calculate the shortage cost - the total cost of not having units in stock,
        including costs due to backorder, lost sales, lost customers, and operational
        disruptions.

        Parameters
        ----------
        shortage_cost : int or float
            Cost per unit of shortage, in dollars
        shortage_quantity : int
            The number of units of shortage, in units

        Returns
        -------
        shortage_cost : float
        """

        Validate.required(shortage_cost, "shortage_cost")
        Validate.non_negative(shortage_cost, "shortage_cost")

        Validate.required(shortage_quantity, "shortage_quantity")
        Validate.non_negative(shortage_quantity, "shortage_quantity")

        return shortage_cost * shortage_quantity
コード例 #2
0
    def __init__(self, quantity, time_unit='Y'):
        Validate.required(quantity, "quantity")
        Validate.non_negative(quantity, "quantity")
        self.quantity = quantity

        Validate.one_of_allowable(time_unit, ['Y', 'M', 'W', 'D'], "time_unit")
        self.time_unit = time_unit
コード例 #3
0
ファイル: eoq.py プロジェクト: rickhaffey/supply-chain-python
    def optimal_order_quantity(raw_costs, demand):
        """
        Calculate economic order quantity (optimal Q*) given raw costs and demand.

        Parameters
        ----------
        raw_costs : RawCosts
            A `RawCosts` object, containing a set of raw cost values
        demand : Demand
            A `Demand` object, containing demand quantity and time frame

        Returns
        -------
        optimal_order_quantity: float
        """

        Validate.required(raw_costs, "raw_costs")
        Validate.required(demand, "demand")

        # if holding cost is 0, optimal Q would be D (i.e.
        # minimize ordering cost with one order across all demand)
        if raw_costs.holding_cost == 0.0:
            return demand.quantity
        else:
            numerator = 2 * raw_costs.ordering_cost * demand.quantity
            denominator = raw_costs.holding_cost

            return math.sqrt(numerator / denominator)
コード例 #4
0
ファイル: eoq.py プロジェクト: rickhaffey/supply-chain-python
    def optimal_cycle_time(raw_costs, demand):
        """
        Calculate optimal cycle time (T*) given raw costs and demand.

        Parameters
        ----------
        raw_costs : RawCosts
            A `RawCosts` object, containing a set of raw cost values
        demand : Demand
            A `Demand` object, containing demand quantity and time frame

        Returns
        -------
        optimal_cycle_time: float
        """

        Validate.required(raw_costs, "raw_costs")
        Validate.required(demand, "demand")
        Validate.positive(demand.quantity, "demand.quantity")
        Validate.positive(raw_costs.holding_cost, "raw_costs.holding_cost")

        numerator = 2 * raw_costs.ordering_cost
        denominator = demand.quantity * raw_costs.holding_cost

        return math.sqrt(numerator / denominator)
コード例 #5
0
    def total_cost(raw_costs, demand, order_quantity, expected_shortage=0):
        """
        Calculate total inventory cost - the combination of purchase,
        ordering, holding, and shortage cost components.

        Parameters
        ----------
        raw_costs : RawCosts
            A `RawCosts` object, containing a set of raw cost values
        demand : Demand
            A `Demand` object, containing demand quantity and time frame
        order_quantity : int
            The number of units purchased with each order
        expected_shortage : int, default 0
            The expected value of the number of units short

        Returns
        -------
        total_cost : float
        """

        Validate.required(raw_costs, "raw_costs")
        Validate.required(demand, "demand")
        Validate.required(order_quantity, "order_quantity")
        Validate.required(expected_shortage, "expected_shortage")

        return (
            Costs.purchase_cost(raw_costs.unit_cost, demand.quantity) +
            Costs.total_relevant_cost(raw_costs, demand, order_quantity) +
            Costs.shortage_cost(raw_costs.shortage_cost, expected_shortage))
コード例 #6
0
    def __validate__(x, a, b, c):
        # todo: revisit these: not always necessary
        # e.g. if x < a or > b, then pdf/cdf evaluate to 0 or 1
        for (var, name) in [(x, "x"), (a, "a"), (b, "b"), (c, "c")]:
            v.required(var, name)

        if a >= b:
            raise ValueError("a must be less than b")

        if c < a or c > b:
            raise ValueError("c must be between a and b")

        if x < a or x > b:
            raise ValueError("x must be between a and b")
コード例 #7
0
ファイル: eoq.py プロジェクト: rickhaffey/supply-chain-python
    def optimal_total_cost(raw_costs, demand):
        """
        Calculate optimal total cost. (TC(Q*))

        Parameters
        ----------
        raw_costs : RawCosts
            A `RawCosts` object, containing a set of raw cost values
        demand : Demand
            A `Demand` object, containing demand quantity and time frame

        Returns
        -------
        optimal_total_cost: float
        """

        Validate.required(raw_costs, "raw_costs")
        Validate.required(demand, "demand")

        return (raw_costs.unit_cost * demand.quantity +
                EOQ.optimal_relevant_cost(raw_costs=raw_costs, demand=demand))
コード例 #8
0
ファイル: eoq.py プロジェクト: rickhaffey/supply-chain-python
    def optimal_relevant_cost(raw_costs, demand):
        """
        Calculate optimal relevant cost. (TRC(Q*))

        Parameters
        ----------
        raw_costs : RawCosts
            A `RawCosts` object, containing a set of raw cost values
        demand : Demand
            A `Demand` object, containing demand quantity and time frame

        Returns
        -------
        optimal_relevant_cost: float
        """

        Validate.required(raw_costs, "raw_costs")
        Validate.required(demand, "demand")

        return math.sqrt(2 * raw_costs.ordering_cost * raw_costs.holding_cost *
                         demand.quantity)
コード例 #9
0
    def ordering_cost(ordering_cost, demand_quantity, order_quantity):
        """
        Calculate the ordering cost - the total cost of placing, receiving,
        and processing orders needed to fulfill a given amount of demand.

        Parameters
        ----------
        ordering_cost : int or float
            Cost per order, in dollars
        demand_quantity : int
            The amount of demand, in units
        order_quantity : int
            The number of units purchased per order, in units

        Returns
        -------
        ordering_cost: float
        """

        Validate.required(ordering_cost, "ordering_cost")
        Validate.non_negative(ordering_cost, "ordering_cost")

        Validate.required(demand_quantity, "demand_quantity")
        Validate.non_negative(demand_quantity, "demand_quantity")

        Validate.required(order_quantity, "order_quantity")
        Validate.positive(order_quantity, "order_quantity")

        return ordering_cost * (demand_quantity / order_quantity)
コード例 #10
0
    def total_relevant_cost(raw_costs, demand, order_quantity):
        """
        Calculate total inventory cost relevant to the calculation of economic order
        quantity.

        Note: The relevant cost components are those that change as a function of
        order quantity: ordering cost and holding cost.

        Parameters
        ----------
        raw_costs : RawCosts
            A `RawCosts` object, containing a set of raw cost values
        demand : Demand
            A `Demand` object, containing demand order_quantity and time frame
        order_quantity : int
            The number of units purchased with each order

        Returns
        -------
        total_relevant_cost : float
        """

        Validate.required(raw_costs, "raw_costs")
        Validate.required(demand, "demand")
        Validate.required(order_quantity, "order_quantity")

        return (Costs.ordering_cost(raw_costs.ordering_cost, demand.quantity,
                                    order_quantity) +
                Costs.holding_cost(raw_costs.holding_cost, order_quantity))
コード例 #11
0
    def holding_cost(holding_cost, order_quantity):
        """
        Calculate the holding cost - the total cost of holding excess inventory,
        including storage, service costs, risk costs, and capital costs.

        Parameters
        ----------
        holding_cost : int or float
            Cost per unit of inventory per time period, in dollars
        order_quantity : int
            The number of units purchased per order, in units

        Returns
        -------
        holding_cost: float
        """

        Validate.required(holding_cost, "holding_cost")
        Validate.non_negative(holding_cost, "holding_cost")

        Validate.required(order_quantity, "order_quantity")
        Validate.non_negative(order_quantity, "order_quantity")

        return holding_cost * (order_quantity / 2)
コード例 #12
0
    def purchase_cost(unit_cost, demand_quantity):
        """
        Calculate the purchase cost - the total landed cost for acquiring
        product needed to satisfy a given amount of demand.

        Parameters
        ----------
        unit_cost : int or float
            Cost per unit, in dollars
        demand_quantity : int
            The amount of demand, in units

        Returns
        -------
        purchase_cost: float
        """

        Validate.required(unit_cost, "unit_cost")
        Validate.non_negative(unit_cost, "unit_cost")

        Validate.required(demand_quantity, "demand_quantity")
        Validate.non_negative(demand_quantity, "demand_quantity")

        return unit_cost * demand_quantity
コード例 #13
0
    def validate_init_values(unit_cost, ordering_cost, holding_rate,
                             holding_cost, holding_time_unit, shortage_cost):
        Validate.required(unit_cost, "unit_cost")
        Validate.non_negative(unit_cost, "unit_cost")

        Validate.required(ordering_cost, "ordering_cost")
        Validate.non_negative(ordering_cost, "ordering_cost")

        # accept holding_rate or holding_cost, but not both
        # (at least one is required)
        Validate.one_only([holding_rate, holding_cost],
                          ["holding_rate", "holding_cost"])
        if holding_rate is not None:
            Validate.non_negative(holding_rate, "holding_rate")
        else:
            Validate.non_negative(holding_cost, holding_cost)

        Validate.one_of_allowable(holding_time_unit,
                                  RawCosts.supported_time_units,
                                  "holding_time_unit")

        Validate.required(shortage_cost, "shortage_cost")
        Validate.non_negative(shortage_cost, "shortage_cost")