import joblib import pandas as pd import numpy as np from scipy.stats import poisson model = joblib.load("inventory_model.pkl") # Load trained model INDUSTRIAL_PARAMS = { "service_levels": {"A": 2.33, "B": 1.65, "C": 1.28}, "risk_thresholds": {"Low": 15, "Medium": 40, "High": 100} } def predict_stockout(order_quantity: float, lead_time: float, safety_stock: float, product_class: str) -> str: if not (0 <= order_quantity <= 10000 and 0 <= lead_time <= 90 and 0 <= safety_stock <= 10000): return "Error: Inputs out of range (Demand: 0-10,000, Lead Time: 0-90 days, Safety Stock: 0-10,000)." if any(x < 0 for x in [order_quantity, lead_time, safety_stock]): return "Error: Negative values not allowed." if product_class not in INDUSTRIAL_PARAMS["service_levels"]: return "Error: Invalid product class. Use A, B, or C." daily_demand = order_quantity / 30 expected_demand = daily_demand * lead_time poisson_risk = max(0, min(1, 1 - poisson.cdf(safety_stock, max(1, expected_demand)))) safety_stock_impact = safety_stock / (order_quantity + 1e-6) lead_time_impact = lead_time / 90 order_quantity_impact = order_quantity / 10000 ml_input = pd.DataFrame({"safety_stock_impact": [safety_stock_impact], "lead_time_impact": [lead_time_impact], "order_quantity_impact": [order_quantity_impact]}) ml_risk = max(0, min(1, model.predict(ml_input)[0])) weight_poisson = min(1, max(0, 1 - (order_quantity / 1000))) weight_ml = 1 - weight_poisson blended_risk = (weight_poisson * poisson_risk + weight_ml * ml_risk) risk_percentage = np.clip(blended_risk * 100, 0, 100) thresholds = INDUSTRIAL_PARAMS["risk_thresholds"] if risk_percentage < thresholds["Low"]: return f"