|
|
import pandas as pd |
|
|
import numpy as np |
|
|
import matplotlib.pyplot as plt |
|
|
import io |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run_slotting_analysis(message, slotting_df): |
|
|
reasoning_steps = [] |
|
|
|
|
|
df = slotting_df.copy() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
velocity_map = { |
|
|
"fast": 3, |
|
|
"medium": 2, |
|
|
"slow": 1 |
|
|
} |
|
|
|
|
|
df["VelocityNorm"] = df["Velocity"].str.lower().map(velocity_map) |
|
|
reasoning_steps.append("Mapped velocity categories to numerical weights.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df["FreqNorm"] = (df["Frequency"] - df["Frequency"].min()) / ( |
|
|
df["Frequency"].max() - df["Frequency"].min() + 1e-8 |
|
|
) |
|
|
reasoning_steps.append("Normalized frequency to 0–1 scale.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df["Score"] = (0.6 * df["VelocityNorm"]) + (0.4 * df["FreqNorm"]) |
|
|
reasoning_steps.append("Computed weighted slotting score (60% velocity, 40% frequency).") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df = df.sort_values("Score", ascending=False).reset_index(drop=True) |
|
|
|
|
|
aisles = np.arange(1, len(df) + 1) |
|
|
racks = np.linspace(1, 20, len(df)).astype(int) |
|
|
|
|
|
df["Aisle"] = aisles |
|
|
df["Rack"] = racks |
|
|
reasoning_steps.append("Assigned optimal aisle & rack positions based on ranking.") |
|
|
|
|
|
explanation = ( |
|
|
"### 📦 Slotting Optimization\n" |
|
|
"The SKUs were evaluated using a weighted model combining velocity and picking frequency.\n" |
|
|
"High-velocity & high-frequency items are placed closer to prime aisles.\n\n" |
|
|
"#### 🔍 Key Reasoning Steps:\n" |
|
|
+ "\n".join([f"- {r}" for r in reasoning_steps]) |
|
|
) |
|
|
|
|
|
return explanation, df |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run_picking_optimization(message, picking_df): |
|
|
reasoning_steps = [] |
|
|
|
|
|
df = picking_df.copy() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df["x"] = df["Aisle"] |
|
|
df["y"] = df["Rack"] |
|
|
reasoning_steps.append("Converted Aisle–Rack values into x–y coordinate grid.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
df["Distance"] = df["x"].abs() + df["y"].abs() |
|
|
df = df.sort_values("Distance").reset_index(drop=True) |
|
|
reasoning_steps.append("Calculated Manhattan distance and sorted for optimal walk order.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.figure(figsize=(6, 6)) |
|
|
plt.plot(df["x"], df["y"], marker="o", linestyle="-") |
|
|
plt.title("Optimized Picking Route") |
|
|
plt.xlabel("Aisle") |
|
|
plt.ylabel("Rack") |
|
|
|
|
|
|
|
|
buffer = io.BytesIO() |
|
|
plt.savefig(buffer, format="png") |
|
|
buffer.seek(0) |
|
|
plt.close() |
|
|
|
|
|
reasoning_steps.append("Generated optimized walking path visualization.") |
|
|
|
|
|
explanation = ( |
|
|
"### 🚚 Picking Route Optimization\n" |
|
|
"Using Manhattan distance and spatial ordering, an optimal walking sequence was generated.\n\n" |
|
|
"#### 🔍 Key Reasoning Steps:\n" |
|
|
+ "\n".join([f"- {r}" for r in reasoning_steps]) |
|
|
) |
|
|
|
|
|
return explanation, buffer |
|
|
|