- numpy - matplotlib

Global Operation Management - Inventory Management

Focuses on inventory management, helping users understand essential inventory control strategies within logistics. Provides training on various inventory management models, including EOQ, Optimal Reorder Point for Instantaneous Resupply, and Optimal Reorder Point for Non-Instantaneous Resupply. The tutorial provides clear explanations and hands-on applications, enabling users to effectively solve real-life inventory challenges.

Pull inventory control - single (Economic order quantity EOQ) Watch Tutorial
def on_eoq(event): D = float(Element("D").element.value) S = float(Element("S").element.value) C = float(Element("C").element.value) I = float(Element("I").element.value) result = eoq(D,S,C,I) Element("out_eoq").element.innerHTML = result Element("button_EOQ").element.onclick = on_eoq
OUTPUT
Optimal Reorder Point - Instantaneous Resupply Watch Tutorial
def get_plot_string(Q_star, R_star, D, LT): plt = plot_inventory_wave(Q_star, R_star, D, LT) buf = io.BytesIO() plt.savefig(buf, format='png') plt.close() buf.seek(0) string = base64.b64encode(buf.read()).decode('utf-8') # output pic return "data:image/png;base64,"+ string def on_instant(event): try: D = float(Element("D1").element.value) S = float(Element("S1").element.value) C = float(Element("C1").element.value) I = float(Element("I1").element.value) / 100 LT = float(Element("LT1").element.value) Q_star, R_star = instant_order(D, S, C, I, LT) if Q_star is not None and R_star is not None: Element("instant_result").element.innerHTML = order(D, S, C, I, LT) img_data = get_plot_string(Q_star, R_star, D, LT) Element("out_instant").element.innerHTML = "Plot generated!" Element("plot_image").element.src = img_data Element("plot_image").element.style.display = "block" except ValueError: Element("out_instant").element.innerHTML = "Invalid input. Please enter numeric values." Element("button_instant").element.onclick = on_instant
OUTPUT
Inventory Plot
Optimal Reorder Point - NON - Instantaneous Resupply Watch Tutorial
import math import numpy as np import matplotlib.pyplot as plt def noninstant1(D, S, C, I, LT, P): try: numerator = 2 * D * S denominator = I * C Q_squared = numerator / denominator Q = math.sqrt(Q_squared) Q_up = math.ceil(Q) R_square = (D / 52) * LT R_up = math.ceil(R_square) Q_square = Q_up * math.sqrt(P / (P - D / 52)) round_Q = math.ceil(Q_square) max_inventory = (round_Q / P) * (P - D / 52) print(f"When the inventory level drops to {R_up} units, place a replenishment order for {round_Q}.") return round_Q, max_inventory, R_up except ValueError: Element("out_noninstant").element.innerHTML = "Invalid input. Please enter positive values." return None, None, None def plot_inventory_wave2(round_Q, max_inventory, R_up): # repeat 3 times repetitions = 3 time_period = 10 # Total time for one cycle t = np.linspace(0, time_period * repetitions, 1000) inventory_levels = np.zeros_like(t) # Generate the sawtooth wave for i in range(len(t)): cycle_position = t[i] % time_period # Position within the current cycle if cycle_position < time_period / 2: inventory_levels[i] = (max_inventory / (time_period / 2)) * cycle_position # Linear up else: inventory_levels[i] = max_inventory - ((max_inventory / (time_period / 2)) * (cycle_position - time_period / 2)) # Linear down # Plot plt.figure(figsize=(10, 6)) plt.plot(t, inventory_levels, label='Inventory Level', color='blue') # label line here plt.axhline(y=round_Q, color='green', linestyle='--', label=f'Q*: {round_Q}') plt.axhline(y=max_inventory, color='red', linestyle='--', label=f'Max Inventory: {max_inventory:.2f}') plt.axhline(y=R_up, color='orange', linestyle='--', label=f'Reordering Quantity: {R_up}') plt.ylim(0, max(round_Q, max_inventory) * 1.1) # Enlarged to the value of Q* plt.title('Sawtooth Wave of Inventory Levels (3 Cycles)') plt.xlabel('Time') plt.ylabel('Inventory Level') plt.xlim(0, time_period * repetitions) plt.grid() plt.legend() plt.text(0, round_Q + 0.05 * max(round_Q, max_inventory), f'Q*: {round_Q}', color='green') plt.text(0, max_inventory + 0.05 * max(round_Q, max_inventory), f'Max Inventory: {max_inventory:.2f}', color='red') plt.text(0, R_up + 0.05 * max(round_Q, max_inventory), f'Reordering Quantity: {R_up}', color='orange') return plt def get_plot_string2(round_Q, max_inventory, R_up): plt = plot_inventory_wave2(round_Q, max_inventory, R_up) buf = io.BytesIO() plt.savefig(buf, format='png') plt.close() buf.seek(0) string = base64.b64encode(buf.read()).decode('utf-8') # output pic return "data:image/png;base64,"+ string def on_noninstant(event): try: D = float(Element("D2").element.value) S = float(Element("S2").element.value) C = float(Element("C2").element.value) I = float(Element("I2").element.value) LT = float(Element("LT2").element.value) P = float(Element("P2").element.value) round_Q, max_inventory, R_up = noninstant1(D, S, C, I, LT, P) result = noninstant(D,S,C,I,LT,P) Element("non_result").element.innerHTML = result if round_Q is not None: img_data = get_plot_string2(round_Q, max_inventory, R_up) Element("out_noninstant").element.innerHTML = "Plot generated!" Element("plot_image_non").element.src = img_data Element("plot_image_non").element.style.display = "block" except ValueError: Element("out_noninstant").element.innerHTML = "Invalid input. Please enter numeric values." Element("button_noninstant").element.onclick = on_noninstant
OUTPUT
Inventory Plot