MBG0903 commited on
Commit
7330ce1
Β·
verified Β·
1 Parent(s): 5e044ad

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -143
app.py CHANGED
@@ -1,173 +1,143 @@
1
  import gradio as gr
2
  import pandas as pd
 
3
  import matplotlib.pyplot as plt
4
- import io
5
- import base64
6
-
7
- # ---------------------------------------------------
8
- # Helper: Generate Heatmap Image (Aisle Γ— Rack)
9
- # ---------------------------------------------------
10
- def generate_slotting_heatmap(df):
11
- plt.figure(figsize=(8, 6))
12
- plt.scatter(df["Suggested Aisle"], df["Suggested Rack"],
13
- c='orange', s=120, edgecolor='black')
14
-
15
- plt.title("SKU Slotting Heatmap (Aisle Γ— Rack)")
16
- plt.xlabel("Aisle Number")
17
- plt.ylabel("Rack Number")
18
- plt.grid(True, alpha=0.3)
19
-
20
- # Add SKU labels near points
21
- for i, sku in enumerate(df["SKU"]):
22
- plt.text(df["Suggested Aisle"][i] + 0.3,
23
- df["Suggested Rack"][i] + 0.3,
24
- sku, fontsize=9)
25
-
26
- buf = io.BytesIO()
27
- plt.savefig(buf, format="png", bbox_inches='tight')
28
- plt.close()
29
- buf.seek(0)
30
-
31
- encoded = base64.b64encode(buf.read()).decode()
32
- return "data:image/png;base64," + encoded
33
-
 
34
 
35
- # ---------------------------------------------------
36
- # Helper: Generate Before vs After Distance Chart
37
- # ---------------------------------------------------
38
- def generate_distance_chart(before_dist, after_dist):
39
- plt.figure(figsize=(7, 5))
40
 
41
- plt.bar(["Before", "After"], [before_dist, after_dist],
42
- color=["red", "green"])
 
 
43
 
44
- plt.title("Walking Distance Comparison")
45
- plt.ylabel("Distance (meters)")
46
 
47
- buf = io.BytesIO()
48
- plt.savefig(buf, format="png", bbox_inches='tight')
49
- plt.close()
50
- buf.seek(0)
51
 
52
- encoded = base64.b64encode(buf.read()).decode()
53
- return "data:image/png;base64," + encoded
54
 
 
 
 
 
55
 
56
- # ---------------------------------------------------
57
- # Core Slotting Engine
58
- # ---------------------------------------------------
59
- def optimize_slotting(sku_df):
60
- if sku_df is None or len(sku_df) == 0:
61
- return None, "No data provided.", None, None
62
 
63
- df = sku_df.copy()
 
 
 
 
64
 
65
- # Mapping velocities to warehouse zone logic
66
- velocity_zone_map = {
67
- "Fast": (3, 14), # near dispatch
68
- "Medium": (6, 20), # middle aisles
69
- "Slow": (20, 6) # far aisles
70
- }
71
 
72
- suggested_aisles = []
73
- suggested_racks = []
74
- reasons = []
 
75
 
76
- for i in range(len(df)):
77
- velocity = df.loc[i, "Velocity"]
78
- freq = df.loc[i, "Frequency"]
79
- sku = df.loc[i, "SKU"]
80
 
81
- if velocity not in velocity_zone_map:
82
- aisle, rack = (10, 10) # fallback
83
- reason = "Default placement due to unknown velocity."
84
- else:
85
- aisle, rack = velocity_zone_map[velocity]
86
- reason = f"{velocity}-moving SKU β€” placed strategically to reduce picker travel."
87
-
88
- suggested_aisles.append(aisle)
89
- suggested_racks.append(rack)
90
- reasons.append(reason)
91
-
92
- df["Suggested Aisle"] = suggested_aisles
93
- df["Suggested Rack"] = suggested_racks
94
- df["Reason"] = reasons
95
-
96
- # Business insight summary
97
- insight = (
98
- "πŸ“Œ **Business Insight Summary**\n"
99
- "- Fast movers placed closest to dispatch to minimize walking distance.\n"
100
- "- Medium movers placed in central aisles to balance traffic.\n"
101
- "- Slow movers placed in deep aisles to avoid congestion.\n\n"
102
- "**Operational Impact:**\n"
103
- "βœ” Walking distance reduction\n"
104
- "βœ” Faster order fulfillment\n"
105
- "βœ” Better warehouse throughput\n"
106
- "βœ” Lower aisle congestion\n"
107
- )
108
 
109
- # Generate visuals
110
- heatmap_img = generate_slotting_heatmap(df)
 
 
 
 
 
111
 
112
- before_distance = 300 # static demo number
113
- after_distance = 180 # static demo number
114
- distance_img = generate_distance_chart(before_distance, after_distance)
115
 
116
- return df, insight, heatmap_img, distance_img
 
 
 
 
 
 
 
 
 
 
117
 
118
 
119
- # ---------------------------------------------------
120
- # UI Layout
121
- # ---------------------------------------------------
122
  def build_ui():
123
  with gr.Blocks() as demo:
124
- gr.Markdown(
125
- "<h1>Procelevate Inventory Slotting Optimizer</h1>"
126
- "<p>AI-powered SKU placement engine to reduce picking time, congestion & improve throughput.</p>"
127
- )
128
 
129
- gr.Markdown("πŸ“¦ **Upload SKU File or Enter Data**")
130
-
131
- # Input table
132
- input_table = gr.Dataframe(
133
- headers=["SKU", "Velocity", "Frequency"],
134
- datatype=["str", "str", "number"],
135
- row_count=3,
136
- value=[
137
- ["A123", "Fast", 120],
138
- ["B555", "Medium", 60],
139
- ["C888", "Slow", 5]
140
- ],
141
- label="SKU Velocity Table"
142
  )
143
 
144
- submit_btn = gr.Button("Optimize Slotting", variant="primary")
145
-
146
- # Tabs for results
147
- with gr.Tabs():
148
- with gr.Tab("Optimized Slotting"):
149
- output_table = gr.Dataframe(
150
- headers=["SKU", "Velocity", "Frequency", "Suggested Aisle", "Suggested Rack", "Reason"],
151
- label="Optimized Slotting Table"
152
- )
153
-
154
- with gr.Tab("Heatmap Visualization"):
155
- heatmap_view = gr.Image(label="SKU Slotting Heatmap")
156
-
157
- with gr.Tab("Walking Distance Savings"):
158
- distance_view = gr.Image(label="Walking Distance Chart")
159
-
160
- with gr.Tab("Business Insights"):
161
- insight_box = gr.Markdown()
162
-
163
- submit_btn.click(
164
- optimize_slotting,
165
- inputs=[input_table],
166
- outputs=[output_table, insight_box, heatmap_view, distance_view]
167
- )
168
 
169
  return demo
170
 
171
 
172
  demo = build_ui()
173
- demo.launch()
 
 
 
1
  import gradio as gr
2
  import pandas as pd
3
+ import numpy as np
4
  import matplotlib.pyplot as plt
5
+ from io import BytesIO
6
+
7
+ PRIMARY_COLOR = "#0f2c59"
8
+
9
+
10
+ # -------------------------
11
+ # BUSINESS LOGIC
12
+ # -------------------------
13
+ def compute_slotting(df):
14
+ """
15
+ Determines aisle & rack suggestions based on SKU velocity.
16
+ """
17
+
18
+ results = []
19
+ for _, row in df.iterrows():
20
+ sku = row["SKU"]
21
+ vel = row["Velocity"]
22
+ freq = int(row["Frequency"])
23
+
24
+ if vel.lower() == "fast":
25
+ aisle = 3
26
+ rack = 14
27
+ reason = "Fast-moving SKU β€” Placed close to dispatch for quicker picking."
28
+ elif vel.lower() == "medium":
29
+ aisle = 6
30
+ rack = 20
31
+ reason = "Medium-moving SKU β€” Positioned in central aisles to balance travel distance."
32
+ else:
33
+ aisle = 20
34
+ rack = 6
35
+ reason = "Slow-moving SKU β€” Moved to back aisles to avoid congestion."
36
 
37
+ results.append([sku, vel, freq, aisle, rack, reason])
 
 
 
 
38
 
39
+ return pd.DataFrame(
40
+ results,
41
+ columns=["SKU", "Velocity", "Frequency", "Suggested Aisle", "Suggested Rack", "Reason"]
42
+ )
43
 
 
 
44
 
45
+ def generate_heatmap(slotting_df):
46
+ """
47
+ Generates a heatmap representing item placement (Aisle vs. Rack).
48
+ """
49
 
50
+ aisles = slotting_df["Suggested Aisle"].astype(int)
51
+ racks = slotting_df["Suggested Rack"].astype(int)
52
 
53
+ grid = np.zeros((25, 25))
54
+ for a, r in zip(aisles, racks):
55
+ if a < 25 and r < 25:
56
+ grid[a, r] = 1
57
 
58
+ fig, ax = plt.subplots(figsize=(6, 6))
59
+ ax.imshow(grid, cmap="Oranges", origin="lower")
60
+ ax.set_title("Warehouse Slotting Heatmap")
61
+ ax.set_xlabel("Rack Number")
62
+ ax.set_ylabel("Aisle Number")
 
63
 
64
+ buf = BytesIO()
65
+ plt.savefig(buf, format="png", dpi=120, bbox_inches="tight")
66
+ plt.close(fig)
67
+ buf.seek(0)
68
+ return buf
69
 
 
 
 
 
 
 
70
 
71
+ def business_summary(df):
72
+ fast = sum(df["Velocity"].str.lower() == "fast")
73
+ med = sum(df["Velocity"].str.lower() == "medium")
74
+ slow = sum(df["Velocity"].str.lower() == "slow")
75
 
76
+ summary = f"""
77
+ ### πŸ“Š Business Insight Summary
 
 
78
 
79
+ - **Fast Movers**: {fast} SKUs placed near dispatch β†’ reduces pick time.
80
+ - **Medium Movers**: {med} SKUs placed in central aisles β†’ balances travel.
81
+ - **Slow Movers**: {slow} SKUs placed in far aisles β†’ lowers congestion.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
+ #### This Improves:
84
+ - πŸšΆβ€β™‚οΈ Reduction in walking distance
85
+ - 🚚 Faster order fulfillment
86
+ - 🏭 Better warehouse space utilization
87
+ - πŸ”„ Reduced aisle congestion
88
+ """
89
+ return summary
90
 
 
 
 
91
 
92
+ # -------------------------
93
+ # GRADIO UI
94
+ # -------------------------
95
+ def process_slotting(input_df):
96
+ try:
97
+ slotting = compute_slotting(input_df)
98
+ heatmap = generate_heatmap(slotting)
99
+ insights = business_summary(slotting)
100
+ return slotting, heatmap, insights
101
+ except Exception as e:
102
+ return None, None, f"❌ Error: {e}"
103
 
104
 
 
 
 
105
  def build_ui():
106
  with gr.Blocks() as demo:
 
 
 
 
107
 
108
+ gr.Markdown(
109
+ "<h1 style='color:#FF6A00'>Procelevate Inventory Slotting Optimizer</h1>"
110
+ "AI-powered SKU placement engine to reduce picking time & congestion."
 
 
 
 
 
 
 
 
 
 
111
  )
112
 
113
+ with gr.Tab("Optimized Slotting"):
114
+ df_input = gr.DataFrame(
115
+ headers=["SKU", "Velocity", "Frequency"],
116
+ value=[
117
+ ["A123", "Fast", 120],
118
+ ["B555", "Medium", 60],
119
+ ["C888", "Slow", 5],
120
+ ],
121
+ label="SKU Velocity Table",
122
+ interactive=True
123
+ )
124
+
125
+ run_btn = gr.Button("Optimize Slotting", variant="primary")
126
+
127
+ slotting_table = gr.DataFrame(label="Optimized Slotting", interactive=False)
128
+ heatmap_output = gr.Image(type="numpy", label="Heatmap")
129
+ insights_output = gr.Markdown()
130
+
131
+ run_btn.click(
132
+ process_slotting,
133
+ inputs=df_input,
134
+ outputs=[slotting_table, heatmap_output, insights_output]
135
+ )
 
136
 
137
  return demo
138
 
139
 
140
  demo = build_ui()
141
+
142
+ if __name__ == "__main__":
143
+ demo.launch()