-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata_pipeline.py
More file actions
281 lines (233 loc) · 11.9 KB
/
Copy pathdata_pipeline.py
File metadata and controls
281 lines (233 loc) · 11.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import json
from typing import Dict, List, Tuple
import warnings
warnings.filterwarnings('ignore')
class LineOptimizationPipeline:
def __init__(self, dataset_path: str = "dataset/"):
self.dataset_path = dataset_path
self.students_data = None
self.class_data = None
self.swipe_data = None
self.processed_data = {}
def load_data(self):
"""Load all datasets"""
print("Loading datasets...")
# Combine all student files
student_files = ['students_1.csv', 'students_2.csv', 'students_3.csv']
student_dfs = []
for file in student_files:
df = pd.read_csv(f"{self.dataset_path}{file}")
student_dfs.append(df)
self.students_data = pd.concat(student_dfs, ignore_index=True)
# Load other datasets
self.class_data = pd.read_csv(f"{self.dataset_path}class_enrollments.csv")
self.swipe_data = pd.read_csv(f"{self.dataset_path}swipes_data.csv")
print(f"Loaded {len(self.students_data)} students")
print(f"Loaded {len(self.class_data)} classes")
print(f"Loaded {len(self.swipe_data)} swipe records")
def preprocess_data(self):
"""Clean and preprocess all datasets"""
print("Preprocessing data...")
# Process student data
self.students_data['has_dietary_restriction'] = self.students_data['dietary_restrictions'] != 'None'
self.students_data['meal_plan_tier'] = self.students_data['meal_plan'].map({
'Unlimited': 3,
'14 Meals': 2,
'10 Meals': 1
})
# Process swipe data
self.swipe_data['swipe_timestamp'] = pd.to_datetime(self.swipe_data['swipe_timestamp'])
self.swipe_data['hour'] = self.swipe_data['swipe_timestamp'].dt.hour
self.swipe_data['day_of_week'] = self.swipe_data['swipe_timestamp'].dt.dayofweek
# Process class data
self.class_data['enrollment_list'] = self.class_data['enrollment'].apply(self._parse_enrollment)
def _parse_enrollment(self, enrollment_str):
"""Parse enrollment list from string format"""
try:
# Remove brackets and split by comma
clean_str = enrollment_str.strip('[]')
return [s.strip() for s in clean_str.split(',')]
except:
return []
def generate_features(self):
"""Generate features for AI optimization"""
print("Generating features for AI optimization...")
# Student dining patterns
student_patterns = self.swipe_data.groupby('student_id').agg({
'swipe_timestamp': ['count', 'min', 'max'],
'hour': ['mean', 'std'],
'meal_period': lambda x: x.mode().iloc[0] if len(x) > 0 else 'Lunch'
}).round(2)
student_patterns.columns = ['total_swipes', 'first_swipe', 'last_swipe',
'avg_hour', 'hour_std', 'preferred_meal']
# Dining rush hours analysis
rush_analysis = self.swipe_data.groupby(['hour', 'meal_period']).size().reset_index(name='volume')
peak_hours = rush_analysis.nlargest(5, 'volume')
# Student-class schedule mapping
student_schedule = {}
for _, row in self.class_data.iterrows():
for student in row['enrollment_list']:
if student not in student_schedule:
student_schedule[student] = []
student_schedule[student].append({
'course': row['course_code'],
'days': row['days_of_week'],
'start_time': row['start_time'],
'end_time': row['end_time']
})
self.processed_data = {
'student_patterns': student_patterns,
'rush_analysis': rush_analysis,
'peak_hours': peak_hours,
'student_schedule': student_schedule
}
print(f"Generated features for {len(student_patterns)} students")
print(f"Identified {len(peak_hours)} peak dining periods")
def calculate_priority_scores(self):
"""Calculate token priority scores for students"""
print("Calculating priority scores...")
priority_scores = []
for _, student in self.students_data.iterrows():
student_id = student['student_id']
score = 0
reasoning = []
# Meal plan tier weight (higher tier = more priority)
meal_tier_weight = student['meal_plan_tier'] * 10
score += meal_tier_weight
reasoning.append(f"Meal plan tier: +{meal_tier_weight}")
# Dietary restrictions weight
if student['has_dietary_restriction']:
dietary_weight = 15
score += dietary_weight
reasoning.append(f"Dietary restriction: +{dietary_weight}")
# Distance from dining hall (residence hall proxy)
residence_distance = {
'Thornton Hall': 5, # Close to dining
'Morrison Tower': 15, # Medium distance
'Riverside Dorms': 25, # Far
'North Campus': 20, # Medium-far
'Sunset Village': 10 # Close-medium
}
distance_penalty = residence_distance.get(student['residence_hall'], 15)
score += distance_penalty
reasoning.append(f"Residence proximity: +{distance_penalty}")
# Class schedule conflicts (if student has back-to-back classes)
if student_id in self.processed_data['student_schedule']:
schedule = self.processed_data['student_schedule'][student_id]
if len(schedule) >= 3: # Heavy course load
schedule_weight = 10
score += schedule_weight
reasoning.append(f"Heavy schedule: +{schedule_weight}")
# GPA-based fairness (lower GPA gets slight boost)
gpa_boost = max(0, (4.0 - student['gpa']) * 5)
score += gpa_boost
reasoning.append(f"GPA fairness: +{gpa_boost:.1f}")
priority_scores.append({
'student_id': student_id,
'priority_score': round(score, 1),
'reasoning': '; '.join(reasoning),
'meal_plan': student['meal_plan'],
'dietary_restrictions': student['dietary_restrictions'],
'residence_hall': student['residence_hall']
})
self.processed_data['priority_scores'] = pd.DataFrame(priority_scores)
print(f"Calculated priority scores for {len(priority_scores)} students")
def predict_demand(self):
"""Predict dining demand patterns"""
print("Analyzing demand patterns...")
# Time-based demand prediction
hourly_demand = self.swipe_data.groupby('hour').size()
meal_period_demand = self.swipe_data.groupby('meal_period').size()
# Day of week patterns
dow_demand = self.swipe_data.groupby('day_of_week').size()
dow_labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
demand_insights = {
'peak_hour': int(hourly_demand.idxmax()),
'peak_volume': int(hourly_demand.max()),
'busiest_meal': meal_period_demand.idxmax(),
'busiest_day': dow_labels[dow_demand.idxmax()],
'hourly_demand': hourly_demand.to_dict(),
'meal_demand': meal_period_demand.to_dict()
}
self.processed_data['demand_insights'] = demand_insights
print(f"Peak dining hour: {demand_insights['peak_hour']}:00 ({demand_insights['peak_volume']} students)")
print(f"Busiest meal period: {demand_insights['busiest_meal']}")
def optimize_token_distribution(self, daily_tokens_per_student=3):
"""Optimize token distribution algorithm"""
print("Optimizing token distribution...")
# Sort students by priority score
priority_df = self.processed_data['priority_scores'].sort_values('priority_score', ascending=False)
# Token distribution tiers
total_students = len(priority_df)
tier_1_cutoff = int(total_students * 0.3) # Top 30%
tier_2_cutoff = int(total_students * 0.7) # Next 40%
token_allocation = []
for i, row in priority_df.iterrows():
if i < tier_1_cutoff:
tokens = daily_tokens_per_student + 2 # Tier 1: +2 bonus tokens
tier = "Tier 1 (High Priority)"
elif i < tier_2_cutoff:
tokens = daily_tokens_per_student + 1 # Tier 2: +1 bonus token
tier = "Tier 2 (Medium Priority)"
else:
tokens = daily_tokens_per_student # Tier 3: Base tokens
tier = "Tier 3 (Standard)"
token_allocation.append({
'student_id': row['student_id'],
'daily_tokens': tokens,
'priority_tier': tier,
'priority_score': row['priority_score']
})
self.processed_data['token_allocation'] = pd.DataFrame(token_allocation)
# Summary stats
tier_stats = self.processed_data['token_allocation'].groupby('priority_tier')['daily_tokens'].agg(['count', 'mean'])
print("\nToken Distribution Summary:")
print(tier_stats)
def generate_insights(self):
"""Generate actionable insights for the demo"""
print("\nGenerating insights...")
insights = []
# Token fairness insight
dietary_priority = self.processed_data['priority_scores'][
self.processed_data['priority_scores']['dietary_restrictions'] != 'None'
]['priority_score'].mean()
regular_priority = self.processed_data['priority_scores'][
self.processed_data['priority_scores']['dietary_restrictions'] == 'None'
]['priority_score'].mean()
insights.append({
'category': 'Fairness',
'insight': f"Students with dietary restrictions get {dietary_priority - regular_priority:.1f} higher priority scores on average",
'impact': 'Ensures equitable access to specialized food options'
})
# Demand optimization insight
peak_info = self.processed_data['demand_insights']
insights.append({
'category': 'Operations',
'insight': f"Peak demand at {peak_info['peak_hour']}:00 with {peak_info['peak_volume']} students",
'impact': 'Token system can distribute this load across 30min windows'
})
# Schedule conflict insight
heavy_schedule_students = len([s for s in self.processed_data['student_schedule']
if len(self.processed_data['student_schedule'][s]) >= 3])
insights.append({
'category': 'Academic Impact',
'insight': f"{heavy_schedule_students} students have 3+ classes (need priority tokens)",
'impact': 'Prevents academic schedule conflicts with dining'
})
self.processed_data['insights'] = insights
for insight in insights:
print(f"• {insight['category']}: {insight['insight']}")
print(f" Impact: {insight['impact']}\n")
if __name__ == "__main__":
pipeline = LineOptimizationPipeline()
pipeline.load_data()
pipeline.preprocess_data()
pipeline.generate_features()
pipeline.calculate_priority_scores()
pipeline.predict_demand()
pipeline.optimize_token_distribution()
pipeline.generate_insights()
print("\n✅ AI Line Optimization Pipeline Complete!")