haileyhalimj@gmail.com commited on
Commit
d8fcfd0
ยท
1 Parent(s): 951e634

clean code for optimizer

Browse files
Files changed (1) hide show
  1. src/models/optimizer_real.py +32 -28
src/models/optimizer_real.py CHANGED
@@ -26,7 +26,6 @@ from src.config.optimization_config import (
26
  get_max_hour_per_shift_per_person, # DYNAMIC: {1: hours, 2: hours, 3: hours}
27
  get_per_product_speed, # DYNAMIC: {6: cap_units_per_hour, 7: cap_units_per_hour}
28
  get_max_parallel_workers, # DYNAMIC: {6: max_workers, 7: max_workers}
29
- DAILY_WEEKLY_SCHEDULE, # 'daily' or 'weekly'
30
  FIXED_STAFF_CONSTRAINT_MODE, # not used in fixed-team model (๋™์‹œ ํˆฌ์ž…์ด๋ผ ๋ฌด์˜๋ฏธ)
31
  get_team_requirements, # DYNAMIC: {emp_type: {product: team_size}} from Kits_Calculation.csv
32
  get_payment_mode_config, # DYNAMIC: {shift: 'bulk'/'partial'} payment mode configuration
@@ -41,9 +40,6 @@ from src.config.optimization_config import (
41
  get_fixed_min_unicef_per_day, # DYNAMIC: Minimum UNICEF employees required per day
42
  )
43
 
44
- # -----------------------------------------
45
- # ์ถ”๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ • (config์— ์—†๋˜ ๊ฒƒ๋“ค) - TODO: ์‹ค์ œ ๊ฐ’ ์ฑ„์šฐ์„ธ์š”
46
- # -----------------------------------------
47
 
48
 
49
  # 2) kit_line_match
@@ -98,39 +94,51 @@ def sort_products_by_hierarchy(product_list):
98
  in_degree[product] = 0
99
 
100
  # Build edges based on actual dependencies
101
- dependency_count = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  for product in products_with_hierarchy:
103
- deps = KIT_DEPENDENCIES.get(product, [])
104
  for dep in deps:
105
  if dep in products_with_hierarchy: # Only if dependency is in our production list
106
- graph[dep].append(product) # dep -> product
 
 
 
107
  in_degree[product] += 1
108
- dependency_count += 1
109
-
110
- print(f"[HIERARCHY] Found {dependency_count} dependency relationships in production list")
111
 
112
  # Topological sort with hierarchy level priority
113
  sorted_products = []
 
114
  queue = deque()
115
 
116
- # Start with products that have no dependencies, prioritized by hierarchy level
117
- no_deps = [(KIT_LEVELS.get(p, 999), p) for p in products_with_hierarchy if in_degree[p] == 0]
118
- no_deps.sort() # Sort by (level, product_id)
119
-
120
- for _, product in no_deps:
121
- queue.append(product)
122
 
123
  while queue:
124
  current = queue.popleft()
125
  sorted_products.append(current)
126
 
127
- # Process dependents
128
- dependents = [(KIT_LEVELS.get(dep, 999), dep) for dep in graph[current]]
129
- dependents.sort() # Sort by hierarchy level first
130
-
131
- for _, dependent in dependents:
132
- in_degree[dependent] -= 1
133
- if in_degree[dependent] == 0:
134
  queue.append(dependent)
135
 
136
  # Check for cycles (shouldn't happen with proper hierarchy)
@@ -141,7 +149,7 @@ def sort_products_by_hierarchy(product_list):
141
  remaining_sorted = sorted(remaining, key=lambda p: (KIT_LEVELS.get(p, 999), p))
142
  sorted_products.extend(remaining_sorted)
143
 
144
- # Add products without hierarchy at the end
145
  sorted_products.extend(sorted(products_without_hierarchy))
146
 
147
  print(f"[HIERARCHY] Dependency-aware production order: {len(sorted_products)} products")
@@ -249,10 +257,6 @@ def solve_fixed_team_weekly():
249
  print(f" RECOMMENDATION: Change EVENING_SHIFT_MODE to 'activate_evening' to enable evening shift")
250
  print(f" This will add shift 3 to increase capacity\n")
251
 
252
- # 3) DAILY_WEEKLY_SCHEDULE warning (current model only enforces weekly demand)
253
- if DAILY_WEEKLY_SCHEDULE.lower() == "daily":
254
- print("[INFO] DAILY_WEEKLY_SCHEDULE='daily' but this model only enforces weekly demand. "
255
- "If daily demand decomposition is needed, please let us know.")
256
 
257
  # --- Solver ---
258
  solver = pywraplp.Solver.CreateSolver('CBC')
 
26
  get_max_hour_per_shift_per_person, # DYNAMIC: {1: hours, 2: hours, 3: hours}
27
  get_per_product_speed, # DYNAMIC: {6: cap_units_per_hour, 7: cap_units_per_hour}
28
  get_max_parallel_workers, # DYNAMIC: {6: max_workers, 7: max_workers}
 
29
  FIXED_STAFF_CONSTRAINT_MODE, # not used in fixed-team model (๋™์‹œ ํˆฌ์ž…์ด๋ผ ๋ฌด์˜๋ฏธ)
30
  get_team_requirements, # DYNAMIC: {emp_type: {product: team_size}} from Kits_Calculation.csv
31
  get_payment_mode_config, # DYNAMIC: {shift: 'bulk'/'partial'} payment mode configuration
 
40
  get_fixed_min_unicef_per_day, # DYNAMIC: Minimum UNICEF employees required per day
41
  )
42
 
 
 
 
43
 
44
 
45
  # 2) kit_line_match
 
94
  in_degree[product] = 0
95
 
96
  # Build edges based on actual dependencies
97
+ # KIT_DEPENDENCIES = {product: [dependencies]} - "What does THIS product need?"
98
+ # graph = {dependency: [products]} - "What depends on THIS dependency?"
99
+ #
100
+ # Example transformation:
101
+ # KIT_DEPENDENCIES = {'subkit_A': ['prepack_1'], 'master_B': ['subkit_A']}
102
+ # After building: graph = {'prepack_1': ['subkit_A'], 'subkit_A': ['master_B']}
103
+ # This means: prepack_1 is needed by subkit_A, subkit_A is needed by master_B
104
+ #
105
+ # Example:
106
+ # 1. product='subkit_A', deps=['prepack_1']
107
+ # โ†’ graph['prepack_1'].append('subkit_A')
108
+ # โ†’ graph = {'prepack_1': ['subkit_A']}
109
+ # 2. product='master_B', deps=['subkit_A']
110
+ # โ†’ graph['subkit_A'].append('master_B')
111
+ # โ†’ graph = {'prepack_1': ['subkit_A'], 'subkit_A': ['master_B']}
112
+
113
+
114
  for product in products_with_hierarchy:
115
+ deps = KIT_DEPENDENCIES.get(product, []) #dependencies = products that has to be packed first
116
  for dep in deps:
117
  if dep in products_with_hierarchy: # Only if dependency is in our production list
118
+ # REVERSE THE RELATIONSHIP:
119
+ # KIT_DEPENDENCIES says: "product needs dep"
120
+ # graph says: "dep is needed by product"
121
+ graph[dep].append(product) # dep -> product (reverse the relationship!)
122
  in_degree[product] += 1
 
 
 
123
 
124
  # Topological sort with hierarchy level priority
125
  sorted_products = []
126
+ #queue = able to remove from both sides
127
  queue = deque()
128
 
129
+ # Start with products that have no dependencies
130
+ for product in products_with_hierarchy:
131
+ if in_degree[product] == 0:
132
+ queue.append(product)
 
 
133
 
134
  while queue:
135
  current = queue.popleft()
136
  sorted_products.append(current)
137
 
138
+ # Process dependents - sort by hierarchy level first
139
+ for dependent in sorted(graph[current], key=lambda p: (KIT_LEVELS.get(p, 999), p)):
140
+ in_degree[dependent] -= 1 #decrement the in_degree of the dependent
141
+ if in_degree[dependent] == 0: #if the in_degree of the dependent is 0, add it to the queue so that it can be processed
 
 
 
142
  queue.append(dependent)
143
 
144
  # Check for cycles (shouldn't happen with proper hierarchy)
 
149
  remaining_sorted = sorted(remaining, key=lambda p: (KIT_LEVELS.get(p, 999), p))
150
  sorted_products.extend(remaining_sorted)
151
 
152
+ # Add products without hierarchy information at the end
153
  sorted_products.extend(sorted(products_without_hierarchy))
154
 
155
  print(f"[HIERARCHY] Dependency-aware production order: {len(sorted_products)} products")
 
257
  print(f" RECOMMENDATION: Change EVENING_SHIFT_MODE to 'activate_evening' to enable evening shift")
258
  print(f" This will add shift 3 to increase capacity\n")
259
 
 
 
 
 
260
 
261
  # --- Solver ---
262
  solver = pywraplp.Solver.CreateSolver('CBC')