fork download
  1. import math
  2. from collections import defaultdict
  3. import json
  4.  
  5. # ============================================================
  6. # ALL DATA
  7. # ============================================================
  8.  
  9. quarters = ['Q1_26','Q2_26','Q3_26','Q4_26','Q1_27','Q2_27','Q3_27','Q4_27']
  10. qlabels = ["Q1'26","Q2'26","Q3'26","Q4'26","Q1'27","Q2'27","Q3'27","Q4'27"]
  11. nodes = [1, 2, 3]
  12. fabs = [1, 2, 3]
  13.  
  14. loading = {
  15. (1,'Q1_26'):12000,(1,'Q2_26'):10000,(1,'Q3_26'):8500,(1,'Q4_26'):7500,
  16. (1,'Q1_27'):6000,(1,'Q2_27'):5000,(1,'Q3_27'):4000,(1,'Q4_27'):2000,
  17. (2,'Q1_26'):5000,(2,'Q2_26'):5200,(2,'Q3_26'):5400,(2,'Q4_26'):5600,
  18. (2,'Q1_27'):6000,(2,'Q2_27'):6500,(2,'Q3_27'):7000,(2,'Q4_27'):7500,
  19. (3,'Q1_26'):3000,(3,'Q2_26'):4500,(3,'Q3_26'):7000,(3,'Q4_26'):8000,
  20. (3,'Q1_27'):9000,(3,'Q2_27'):11000,(3,'Q3_27'):13000,(3,'Q4_27'):16000,
  21. }
  22.  
  23. nsteps = {1:11, 2:15, 3:17}
  24.  
  25. recipe = {
  26. (1,1):('D',14,'D+',12),(1,2):('F',25,'F+',21),(1,3):('F',27,'F+',23),
  27. (1,4):('A',20,'A+',16),(1,5):('F',12,'F+',9),(1,6):('D',27,'D+',21),
  28. (1,7):('D',17,'D+',13),(1,8):('A',18,'A+',16),(1,9):('A',16,'A+',13),
  29. (1,10):('D',14,'D+',11),(1,11):('F',18,'F+',16),
  30. (2,1):('F',19,'F+',16),(2,2):('B',20,'B+',18),(2,3):('E',10,'E+',7),
  31. (2,4):('B',25,'B+',19),(2,5):('B',15,'B+',11),(2,6):('F',16,'F+',14),
  32. (2,7):('F',17,'F+',15),(2,8):('B',22,'B+',16),(2,9):('E',7,'E+',6),
  33. (2,10):('E',9,'E+',7),(2,11):('E',20,'E+',19),(2,12):('F',21,'F+',18),
  34. (2,13):('E',12,'E+',9),(2,14):('E',15,'E+',12),(2,15):('E',13,'E+',10),
  35. (3,1):('C',21,'C+',20),(3,2):('D',9,'D+',7),(3,3):('E',24,'E+',23),
  36. (3,4):('E',15,'E+',11),(3,5):('F',16,'F+',14),(3,6):('D',12,'D+',11),
  37. (3,7):('C',24,'C+',21),(3,8):('C',19,'C+',13),(3,9):('D',15,'D+',13),
  38. (3,10):('D',24,'D+',20),(3,11):('E',17,'E+',15),(3,12):('E',18,'E+',13),
  39. (3,13):('F',20,'F+',18),(3,14):('C',12,'C+',11),(3,15):('D',11,'D+',10),
  40. (3,16):('C',25,'C+',20),(3,17):('F',14,'F+',13),
  41. }
  42.  
  43. # (utilization, capex_M$, space_m2)
  44. ws = {
  45. 'A':(0.78,4.5,6.78),'B':(0.76,6.0,3.96),'C':(0.80,2.2,5.82),
  46. 'D':(0.80,4.0,5.61),'E':(0.76,3.5,4.65),'F':(0.80,6.0,3.68),
  47. 'A+':(0.84,6.0,6.93),'B+':(0.81,8.0,3.72),'C+':(0.86,3.2,5.75),
  48. 'D+':(0.88,5.5,5.74),'E+':(0.84,5.8,4.80),'F+':(0.90,8.0,3.57),
  49. }
  50.  
  51. init_tools = {
  52. (1,'A'):0,(1,'B'):0,(1,'C'):40,(1,'D'):35,(1,'E'):16,(1,'F'):36,
  53. (2,'A'):50,(2,'B'):25,(2,'C'):0,(2,'D'):50,(2,'E'):40,(2,'F'):90,
  54. (3,'A'):35,(3,'B'):30,(3,'C'):0,(3,'D'):50,(3,'E'):30,(3,'F'):60,
  55. }
  56. for f in fabs:
  57. for w in ['A+','B+','C+','D+','E+','F+']:
  58. init_tools[(f,w)] = 0
  59.  
  60. fab_space = {1:1500, 2:1300, 3:700}
  61. XFER_COST = 50 # $/wafer/transfer
  62. WKS = 13 # weeks per quarter
  63. MO_COST = 1_000_000 # $1M per tool moveout
  64. MPW = 10080 # minutes per week = 7*24*60
  65.  
  66. mintech_ws = ['A','B','C','D','E','F']
  67. tor_ws = ['A+','B+','C+','D+','E+','F+']
  68. all_ws_list = mintech_ws + tor_ws
  69. m2t = {'A':'A+','B':'B+','C':'C+','D':'D+','E':'E+','F':'F+'}
  70.  
  71. def treq(load, rpt, util):
  72. """Tool requirement (fractional)"""
  73. if load <= 0: return 0.0
  74. return (load * rpt) / (MPW * util)
  75.  
  76. def treq_ceil(load, rpt, util):
  77. """Tool requirement (integer, rounded up)"""
  78. return math.ceil(treq(load, rpt, util))
  79.  
  80. # ============================================================
  81. # ANALYSIS PHASE
  82. # ============================================================
  83.  
  84. print("="*80)
  85. print("MICRON NUS-ISE BACC 2026 - QUESTION 1")
  86. print("COMPLETE SOLUTION WITH ANALYTICAL OPTIMIZATION")
  87. print("="*80)
  88.  
  89. # Compute aggregate tool requirements per WS per quarter
  90. print("\n" + "="*80)
  91. print("1. AGGREGATE TOOL REQUIREMENTS (Mintech Only)")
  92. print("="*80)
  93.  
  94. ws_node_req = {} # (ws, node, quarter) -> fractional tool req
  95. ws_total_req = {} # (ws, quarter) -> fractional total
  96.  
  97. for w in mintech_ws:
  98. for t in quarters:
  99. total = 0
  100. for i in nodes:
  101. L = loading[(i,t)]
  102. req = 0
  103. for j in range(1, nsteps[i]+1):
  104. mw,mr,tw,tr = recipe[(i,j)]
  105. if mw == w:
  106. req += treq(L, mr, ws[w][0])
  107. ws_node_req[(w,i,t)] = req
  108. total += req
  109. ws_total_req[(w,t)] = total
  110.  
  111. # Print summary table
  112. print(f"\n{'WS':<3}", end="")
  113. for t in qlabels:
  114. print(f" {t:>7}", end="")
  115. print(f" {'Avail':>6} {'PkGap':>6}")
  116.  
  117. for w in mintech_ws:
  118. print(f"{w:<3}", end="")
  119. peak = 0
  120. for t in quarters:
  121. r = math.ceil(ws_total_req[(w,t)])
  122. peak = max(peak, r)
  123. print(f" {r:>7}", end="")
  124. avail = sum(init_tools.get((f,w),0) for f in fabs)
  125. gap = max(0, peak - avail)
  126. print(f" {avail:>6} {gap:>6}")
  127.  
  128. # Also compute TOR equivalent
  129. print(f"\n{'WS':<3}", end="")
  130. for t in qlabels:
  131. print(f" {t:>7}", end="")
  132. print(" (if all TOR)")
  133.  
  134. for wt in tor_ws:
  135. print(f"{wt:<3}", end="")
  136. for t in quarters:
  137. total = 0
  138. for i in nodes:
  139. L = loading[(i,t)]
  140. for j in range(1, nsteps[i]+1):
  141. mw,mr,tw,tr = recipe[(i,j)]
  142. if tw == wt:
  143. total += treq(L, tr, ws[wt][0])
  144. print(f" {math.ceil(total):>7}", end="")
  145. print()
  146.  
  147. # ============================================================
  148. # SPACE ANALYSIS
  149. # ============================================================
  150.  
  151. print("\n" + "="*80)
  152. print("2. INITIAL SPACE ANALYSIS")
  153. print("="*80)
  154.  
  155. for f in fabs:
  156. used = sum(init_tools.get((f,w),0) * ws[w][2] for w in all_ws_list)
  157. remain = fab_space[f] - used
  158. print(f"\n Fab {f}: {used:.1f} / {fab_space[f]} m² used ({remain:.1f} m² free)")
  159. for w in all_ws_list:
  160. cnt = init_tools.get((f,w),0)
  161. if cnt > 0:
  162. print(f" {w}: {cnt} × {ws[w][2]}m² = {cnt*ws[w][2]:.1f}m²")
  163.  
  164. # ============================================================
  165. # KEY INSIGHT: Which nodes use which workstations
  166. # ============================================================
  167.  
  168. print("\n" + "="*80)
  169. print("3. NODE-WORKSTATION MAPPING")
  170. print("="*80)
  171.  
  172. for i in nodes:
  173. ws_used = defaultdict(list)
  174. for j in range(1, nsteps[i]+1):
  175. mw,mr,tw,tr = recipe[(i,j)]
  176. ws_used[mw].append((j, mr))
  177. print(f"\n Node {i} ({nsteps[i]} steps):")
  178. for w in mintech_ws:
  179. if w in ws_used:
  180. steps_str = ", ".join(f"S{s}({r}min)" for s,r in ws_used[w])
  181. total_rpt = sum(r for _,r in ws_used[w])
  182. print(f" {w}: {steps_str} [total RPT={total_rpt} min]")
  183.  
  184. # ============================================================
  185. # CRITICAL: C workstation only in Fab 1
  186. # B workstation only in Fab 2 and Fab 3
  187. # This constrains where nodes can run
  188. # ============================================================
  189.  
  190. print("\n" + "="*80)
  191. print("4. CRITICAL CONSTRAINTS")
  192. print("="*80)
  193. print(" - C tools ONLY in Fab 1 (40 tools) → Node 3 C-steps MUST run in Fab 1")
  194. print(" - B tools ONLY in Fab 2 (25) and Fab 3 (30) → Node 2 B-steps in Fab 2/3")
  195. print(" - A tools ONLY in Fab 2 (50) and Fab 3 (35) → Node 1 A-steps in Fab 2/3")
  196. print(" - Node 3 uses C heavily (steps 1,7,8,14,16) - C is bottleneck")
  197.  
  198. # ============================================================
  199. # GREEDY OPTIMIZATION ALGORITHM
  200. # ============================================================
  201.  
  202. print("\n" + "="*80)
  203. print("5. OPTIMIZATION: CONSTRUCTING FEASIBLE SOLUTION")
  204. print("="*80)
  205.  
  206. # Strategy:
  207. # 1. For each quarter, determine which fabs can process which nodes based on WS availability
  208. # 2. Assign loading to minimize transfers (keep wafers in same fab across steps)
  209. # 3. Purchase tools only when existing capacity insufficient
  210. # 4. Prefer mintech (cheaper) unless space forces TOR (more efficient per m²)
  211.  
  212. # Track state
  213. tool_count = {} # (f,w,t) -> count
  214. tool_purchases = {} # (f,w,t) -> purchased count
  215. flow = {} # (i,j,f,t) -> wafers/week
  216. transfers = {} # (i,j,f1,f2,t) -> wafers/week transferred
  217.  
  218. total_capex = 0
  219. total_xfer_cost = 0
  220.  
  221. # Initialize tool counts
  222. for f in fabs:
  223. for w in all_ws_list:
  224. tool_count[(f,w)] = init_tools.get((f,w), 0)
  225.  
  226. def get_space_used(f, t_tools):
  227. """Compute space used in fab f given tool counts dict"""
  228. return sum(t_tools.get((f,w), 0) * ws[w][2] for w in all_ws_list)
  229.  
  230. def get_space_remaining(f, t_tools):
  231. return fab_space[f] - get_space_used(f, t_tools)
  232.  
  233. def get_ws_capacity(f, w_type, t_tools):
  234. """Get capacity in wafers*minutes/week for workstation type in fab"""
  235. cnt = t_tools.get((f, w_type), 0)
  236. return cnt * MPW * ws[w_type][0]
  237.  
  238. # For each quarter, determine optimal allocation
  239. for t_idx, t in enumerate(quarters):
  240. print(f"\n{'='*60}")
  241. print(f"Quarter: {qlabels[t_idx]}")
  242. print(f"{'='*60}")
  243.  
  244. # Current tool state
  245. cur_tools = {}
  246. for f in fabs:
  247. for w in all_ws_list:
  248. cur_tools[(f,w)] = tool_count[(f,w)]
  249.  
  250. # Compute what each node needs on each WS type
  251. # For each (node, mintech_ws), compute total RPT*loading
  252. node_ws_demand = {} # (node, mintech_ws) -> minutes/week needed
  253. for i in nodes:
  254. L = loading[(i,t)]
  255. for w in mintech_ws:
  256. total_min = 0
  257. for j in range(1, nsteps[i]+1):
  258. mw,mr,tw,tr = recipe[(i,j)]
  259. if mw == w:
  260. total_min += L * mr
  261. node_ws_demand[(i,w)] = total_min
  262.  
  263. # Step 1: Determine fab assignment for each node
  264. # Constraint: Node 3 C-steps must be in Fab 1 (only fab with C tools)
  265. # Constraint: Node 2 B-steps must be in Fab 2 or 3
  266. # Constraint: Node 1 A-steps must be in Fab 2 or 3
  267.  
  268. # Strategy: Assign each node's loading across fabs proportional to
  269. # available capacity on the BOTTLENECK workstation for that node
  270.  
  271. # For simplicity and to minimize transfers: try to keep entire node in one fab
  272. # where possible, or split at natural breakpoints
  273.  
  274. # Node 3: MUST go through Fab 1 for C steps, but D/E/F steps can go elsewhere
  275. # Node 2: MUST go through Fab 2 or 3 for B steps
  276. # Node 1: MUST go through Fab 2 or 3 for A steps
  277.  
  278. # Approach: Run all of Node 3's C steps in Fab 1,
  279. # check if Fab 1 has enough D/E/F for non-C steps too
  280.  
  281. # First check C capacity for Node 3
  282. L3 = loading[(3,t)]
  283. c_demand_min = node_ws_demand[(3,'C')] # total C-minutes needed
  284. c_capacity = get_ws_capacity(1, 'C', cur_tools) # Fab 1 C capacity
  285.  
  286. # Also check if we need C+ tools
  287. c_steps_for_n3 = [(j, recipe[(3,j)][1], recipe[(3,j)][3])
  288. for j in range(1, nsteps[3]+1) if recipe[(3,j)][0] == 'C']
  289. c_mintech_treq = sum(treq(L3, mr, ws['C'][0]) for _, mr, _ in c_steps_for_n3)
  290. c_tor_treq = sum(treq(L3, tr, ws['C+'][0]) for _, _, tr in c_steps_for_n3)
  291.  
  292. print(f"\n Node 3 C requirement: {c_mintech_treq:.1f} tools (mintech) or "
  293. f"{c_tor_treq:.1f} (TOR)")
  294. print(f" Fab 1 C tools available: {cur_tools.get((1,'C'),0)}")
  295.  
  296. # Check if we need more C tools
  297. c_available = cur_tools.get((1,'C'), 0)
  298. c_needed = math.ceil(c_mintech_treq)
  299.  
  300. if c_needed > c_available:
  301. # Need to buy C or C+ tools for Fab 1
  302. c_gap = c_needed - c_available
  303. space_rem = get_space_remaining(1, cur_tools)
  304.  
  305. # Compare: buy C (cheaper, 2.2M, 5.82m²) vs C+ (3.2M, 5.75m², faster)
  306. # C+ is slightly smaller and faster - better for space-constrained situations
  307.  
  308. # Check if C fits
  309. c_space_needed = c_gap * ws['C'][2]
  310. cp_equiv = math.ceil(c_tor_treq) - 0 # no existing C+ tools
  311. cp_space_needed = cp_equiv * ws['C+'][2]
  312.  
  313. # Try mintech C first
  314. if c_space_needed <= space_rem:
  315. cur_tools[(1,'C')] += c_gap
  316. cost = c_gap * ws['C'][1] * 1e6
  317. total_capex += cost
  318. tool_purchases[(1,'C',t)] = tool_purchases.get((1,'C',t),0) + c_gap
  319. print(f" -> Purchase {c_gap} C tools for Fab 1 (${cost/1e6:.1f}M)")
  320. else:
  321. # Try C+ (faster, less tools needed, slightly smaller)
  322. cp_needed = math.ceil(c_tor_treq)
  323. cp_space = cp_needed * ws['C+'][2]
  324. if cp_space <= space_rem:
  325. cur_tools[(1,'C+')] += cp_needed
  326. cost = cp_needed * ws['C+'][1] * 1e6
  327. total_capex += cost
  328. tool_purchases[(1,'C+',t)] = tool_purchases.get((1,'C+',t),0) + cp_needed
  329. print(f" -> Purchase {cp_needed} C+ tools for Fab 1 (${cost/1e6:.1f}M)")
  330. else:
  331. # Buy mix
  332. max_c = int(space_rem / ws['C'][2])
  333. cur_tools[(1,'C')] += max_c
  334. if max_c > 0:
  335. cost = max_c * ws['C'][1] * 1e6
  336. total_capex += cost
  337. tool_purchases[(1,'C',t)] = tool_purchases.get((1,'C',t),0) + max_c
  338. print(f" -> Purchase {max_c} C tools for Fab 1 (${cost/1e6:.1f}M)")
  339.  
  340. space_rem2 = get_space_remaining(1, cur_tools)
  341. remaining_c_demand = c_mintech_treq - (c_available + max_c) * MPW * ws['C'][0]
  342. if remaining_c_demand > 0:
  343. cp_needed2 = math.ceil(remaining_c_demand / (MPW * ws['C+'][0]))
  344. cp_needed2 = min(cp_needed2, int(space_rem2 / ws['C+'][2]))
  345. if cp_needed2 > 0:
  346. cur_tools[(1,'C+')] += cp_needed2
  347. cost = cp_needed2 * ws['C+'][1] * 1e6
  348. total_capex += cost
  349. tool_purchases[(1,'C+',t)] = cp_needed2
  350. print(f" -> Purchase {cp_needed2} C+ for Fab 1 (${cost/1e6:.1f}M)")
  351.  
  352. # Now handle all other workstations for all nodes
  353. # For each WS type, compute total demand across all nodes, check against supply
  354.  
  355. for w in mintech_ws:
  356. total_demand = sum(node_ws_demand[(i,w)] for i in nodes) # minutes/week
  357. total_supply = sum(get_ws_capacity(f, w, cur_tools) for f in fabs)
  358. tor_w = m2t[w]
  359. total_supply_tor = sum(get_ws_capacity(f, tor_w, cur_tools) for f in fabs)
  360.  
  361. demand_tools = sum(treq(loading[(i,t)], recipe[(i,j)][1], ws[w][0])
  362. for i in nodes for j in range(1, nsteps[i]+1)
  363. if recipe[(i,j)][0] == w)
  364.  
  365. supply_tools = sum(cur_tools.get((f,w),0) for f in fabs)
  366. supply_tor = sum(cur_tools.get((f,tor_w),0) for f in fabs)
  367.  
  368. needed = math.ceil(demand_tools)
  369.  
  370. if needed > supply_tools + supply_tor:
  371. gap = needed - supply_tools - supply_tor
  372.  
  373. # Find best fab to add tools (most space remaining)
  374. fab_space_rem = [(get_space_remaining(f, cur_tools), f) for f in fabs]
  375. fab_space_rem.sort(reverse=True)
  376.  
  377. remaining_gap = gap
  378. for space_r, f in fab_space_rem:
  379. if remaining_gap <= 0:
  380. break
  381.  
  382. # Decide mintech vs TOR
  383. # Compare cost-effectiveness: cost per unit capacity
  384. # Mintech: cost/tool / (MPW * util / avg_rpt)
  385. # Just compare raw CapEx since we want min cost
  386.  
  387. mintech_can_fit = int(space_r / ws[w][2])
  388. tor_can_fit = int(space_r / ws[tor_w][2])
  389.  
  390. # Prefer mintech (cheaper) if it fits
  391. add_mintech = min(remaining_gap, mintech_can_fit)
  392. if add_mintech > 0:
  393. cur_tools[(f,w)] = cur_tools.get((f,w),0) + add_mintech
  394. cost = add_mintech * ws[w][1] * 1e6
  395. total_capex += cost
  396. tool_purchases[(f,w,t)] = tool_purchases.get((f,w,t),0) + add_mintech
  397. remaining_gap -= add_mintech
  398. print(f" -> Purchase {add_mintech} {w} for Fab {f} (${cost/1e6:.1f}M)")
  399.  
  400. if remaining_gap > 0:
  401. space_r2 = get_space_remaining(f, cur_tools)
  402. add_tor = min(remaining_gap, int(space_r2 / ws[tor_w][2]))
  403. if add_tor > 0:
  404. cur_tools[(f,tor_w)] = cur_tools.get((f,tor_w),0) + add_tor
  405. cost = add_tor * ws[tor_w][1] * 1e6
  406. total_capex += cost
  407. tool_purchases[(f,tor_w,t)] = tool_purchases.get((f,tor_w,t),0) + add_tor
  408. remaining_gap -= add_tor
  409. print(f" -> Purchase {add_tor} {tor_w} for Fab {f} (${cost/1e6:.1f}M)")
  410.  
  411. if remaining_gap > 0:
  412. print(f" WARNING: Cannot fit {remaining_gap} more {w} tools!")
  413.  
  414. # Step 2: Assign flows
  415. # For each node, assign all loading to the fab(s) that have capacity
  416. # Try to keep entire node in one fab to minimize transfers
  417.  
  418. for i in nodes:
  419. L = loading[(i,t)]
  420.  
  421. # Determine which fabs can handle this node
  422. # A fab can handle a node if it has capacity for ALL WS types used by that node
  423. ws_used_by_node = set()
  424. for j in range(1, nsteps[i]+1):
  425. mw,mr,tw,tr = recipe[(i,j)]
  426. ws_used_by_node.add(mw)
  427.  
  428. # Check capacity per fab
  429. fab_feasible = {}
  430. for f in fabs:
  431. max_load = float('inf')
  432. for w in ws_used_by_node:
  433. # How many wafers/week can this fab handle for this WS?
  434. cap_m = get_ws_capacity(f, w, cur_tools)
  435. cap_t = get_ws_capacity(f, m2t[w], cur_tools)
  436. # Total capacity in minutes, convert to wafers
  437. # Total RPT for this node on this WS
  438. total_rpt = sum(recipe[(i,j)][1] for j in range(1, nsteps[i]+1)
  439. if recipe[(i,j)][0] == w)
  440. if total_rpt > 0:
  441. max_wafers = (cap_m + cap_t) / total_rpt if total_rpt > 0 else float('inf')
  442. else:
  443. max_wafers = float('inf')
  444. max_load = min(max_load, max_wafers)
  445. fab_feasible[f] = max_load
  446.  
  447. # Distribute loading across fabs proportionally to capacity
  448. total_cap = sum(fab_feasible.values())
  449.  
  450. if total_cap <= 0:
  451. print(f" ERROR: No capacity for Node {i}!")
  452. for j in range(1, nsteps[i]+1):
  453. for f in fabs:
  454. flow[(i,j,f,t)] = L if f == 1 else 0
  455. continue
  456.  
  457. # Allocate
  458. alloc = {}
  459. remaining = L
  460. fab_sorted = sorted(fabs, key=lambda f: fab_feasible[f], reverse=True)
  461.  
  462. for idx, f in enumerate(fab_sorted):
  463. if idx < len(fabs) - 1:
  464. share = min(remaining, int(L * fab_feasible[f] / total_cap))
  465. alloc[f] = share
  466. remaining -= share
  467. else:
  468. alloc[f] = remaining
  469.  
  470. # Assign all steps to same fab allocation (no transfers within a node)
  471. for j in range(1, nsteps[i]+1):
  472. for f in fabs:
  473. flow[(i,j,f,t)] = alloc.get(f, 0)
  474.  
  475. nonzero = [(f, alloc[f]) for f in fabs if alloc.get(f,0) > 0]
  476. alloc_str = ", ".join(f"Fab{f}={v}" for f,v in nonzero)
  477. print(f" Node {i} ({L} wfr/wk): {alloc_str}")
  478.  
  479. # Check if any steps need cross-fab transfer due to WS availability
  480. # E.g., Node 3 C-steps MUST be in Fab 1, but D/E/F steps might be elsewhere
  481.  
  482. for i in nodes:
  483. L = loading[(i,t)]
  484. for j in range(1, nsteps[i]+1):
  485. mw,mr,tw,tr = recipe[(i,j)]
  486. for f in fabs:
  487. assigned = flow.get((i,j,f,t), 0)
  488. if assigned > 0:
  489. # Check if this fab has the WS
  490. has_mintech = cur_tools.get((f,mw),0) > 0
  491. has_tor = cur_tools.get((f,m2t[mw]),0) > 0
  492. if not has_mintech and not has_tor:
  493. # Need to transfer this to a fab that has the WS
  494. # Find target fab
  495. for f2 in fabs:
  496. if f2 != f and (cur_tools.get((f2,mw),0) > 0 or
  497. cur_tools.get((f2,m2t[mw]),0) > 0):
  498. # Transfer from f to f2
  499. # Move the load for this step
  500. old_val = flow[(i,j,f,t)]
  501. flow[(i,j,f,t)] = 0
  502. flow[(i,j,f2,t)] = flow.get((i,j,f2,t), 0) + old_val
  503.  
  504. # Record transfer (between previous step and this one)
  505. if j > 1:
  506. transfers[(i,j-1,f,f2,t)] = transfers.get((i,j-1,f,f2,t),0) + old_val
  507. xfer_c = old_val * XFER_COST * WKS
  508. total_xfer_cost += xfer_c
  509.  
  510. # Also need to transfer back for next step if next step's WS
  511. # is in original fab - handled in next iteration
  512. break
  513.  
  514. # Update tool counts for next quarter
  515. for f in fabs:
  516. for w in all_ws_list:
  517. tool_count[(f,w)] = cur_tools.get((f,w), 0)
  518.  
  519. # Record for this quarter
  520. for f in fabs:
  521. for w in all_ws_list:
  522. tool_count[(f,w,t)] = cur_tools.get((f,w), 0)
  523.  
  524. # Print space usage
  525. print(f"\n Space usage:")
  526. for f in fabs:
  527. used = get_space_used(f, cur_tools)
  528. print(f" Fab {f}: {used:.1f}/{fab_space[f]} m² ({used/fab_space[f]*100:.0f}%)")
  529.  
  530. # ============================================================
  531. # OUTPUT: COMPLETE RESULTS
  532. # ============================================================
  533.  
  534. print("\n\n" + "="*80)
  535. print("6. PART A RESULTS SUMMARY")
  536. print("="*80)
  537.  
  538. print(f"\n Total CapEx: ${total_capex:>15,.0f} ({total_capex/1e6:.1f}M)")
  539. print(f" Total Transfer: ${total_xfer_cost:>15,.0f} ({total_xfer_cost/1e6:.1f}M)")
  540. print(f" GRAND TOTAL: ${total_capex+total_xfer_cost:>15,.0f} "
  541. f"({(total_capex+total_xfer_cost)/1e6:.1f}M)")
  542.  
  543. # ============================================================
  544. # TOOL ALLOCATION TABLES
  545. # ============================================================
  546.  
  547. print("\n" + "="*80)
  548. print("7. TOOL ALLOCATION PLAN (For Excel Answer Template)")
  549. print("="*80)
  550.  
  551. for t_idx, t in enumerate(quarters):
  552. print(f"\n--- {qlabels[t_idx]} ---")
  553. print(f" {'WS':<4} {'Fab1':>6} {'Fab2':>6} {'Fab3':>6} {'Total':>6} {'NewPur':>7}")
  554.  
  555. for w in all_ws_list:
  556. vals = [tool_count.get((f,w,t), tool_count.get((f,w),0)) for f in fabs]
  557. total = sum(vals)
  558. new_pur = sum(tool_purchases.get((f,w,t),0) for f in fabs)
  559. if total > 0 or new_pur > 0:
  560. print(f" {w:<4} {vals[0]:>6} {vals[1]:>6} {vals[2]:>6} {total:>6} {new_pur:>7}")
  561.  
  562. # ============================================================
  563. # FLOW DISTRIBUTION TABLES
  564. # ============================================================
  565.  
  566. print("\n" + "="*80)
  567. print("8. FLOW DISTRIBUTION TABLES (For Excel Answer Template)")
  568. print("="*80)
  569.  
  570. for t_idx, t in enumerate(quarters):
  571. print(f"\n--- {qlabels[t_idx]} ---")
  572.  
  573. for i in nodes:
  574. L = loading[(i,t)]
  575. print(f"\n Node {i} (Loading={L}):")
  576. print(f" {'Step':>4} {'WS':>3}", end="")
  577. for f in fabs:
  578. print(f" {'Fab'+str(f):>7}", end="")
  579. print(f" {'Total':>7}")
  580.  
  581. for j in range(1, nsteps[i]+1):
  582. mw = recipe[(i,j)][0]
  583. print(f" {j:>4} {mw:>3}", end="")
  584. step_total = 0
  585. for f in fabs:
  586. v = flow.get((i,j,f,t), 0)
  587. step_total += v
  588. print(f" {v:>7.0f}", end="")
  589. print(f" {step_total:>7.0f}", end="")
  590.  
  591. # Check for transfers
  592. if j < nsteps[i]:
  593. for f1 in fabs:
  594. for f2 in fabs:
  595. if f1 != f2:
  596. tv = transfers.get((i,j,f1,f2,t), 0)
  597. if tv > 0:
  598. print(f" [F{f1}->F{f2}:{tv:.0f}]", end="")
  599. print()
  600.  
  601. # ============================================================
  602. # PURCHASE SCHEDULE
  603. # ============================================================
  604.  
  605. print("\n" + "="*80)
  606. print("9. TOOL PURCHASE SCHEDULE")
  607. print("="*80)
  608.  
  609. for t_idx, t in enumerate(quarters):
  610. any_pur = False
  611. for f in fabs:
  612. for w in all_ws_list:
  613. p = tool_purchases.get((f,w,t), 0)
  614. if p > 0:
  615. if not any_pur:
  616. print(f"\n {qlabels[t_idx]}:")
  617. any_pur = True
  618. cost = p * ws[w][1]
  619. print(f" Fab{f} {w}: {p} tools (${cost:.1f}M)")
  620.  
  621. # ============================================================
  622. # CAPACITY VERIFICATION
  623. # ============================================================
  624.  
  625. print("\n" + "="*80)
  626. print("10. CAPACITY & DEMAND VERIFICATION")
  627. print("="*80)
  628.  
  629. all_verified = True
  630. for t_idx, t in enumerate(quarters):
  631. issues = []
  632.  
  633. # Check each WS in each fab
  634. for f in fabs:
  635. for w in mintech_ws:
  636. cnt = tool_count.get((f,w,t), tool_count.get((f,w),0))
  637. cap = cnt * MPW * ws[w][0] # minutes available
  638.  
  639. # Demand on this WS in this fab
  640. demand = 0
  641. for i in nodes:
  642. for j in range(1, nsteps[i]+1):
  643. mw,mr,tw,tr = recipe[(i,j)]
  644. if mw == w:
  645. demand += flow.get((i,j,f,t), 0) * mr
  646.  
  647. if demand > cap + 0.1 and cap > 0:
  648. issues.append(f" Fab{f} {w}: demand={demand:.0f}min > cap={cap:.0f}min")
  649. elif demand > 0 and cap == 0:
  650. # Check if TOR handles it
  651. tor_w = m2t[w]
  652. cnt_t = tool_count.get((f,tor_w,t), tool_count.get((f,tor_w),0))
  653. if cnt_t == 0:
  654. issues.append(f" Fab{f} {w}: demand={demand:.0f}min but NO tools!")
  655.  
  656. # Check demand fulfillment
  657. for i in nodes:
  658. L = loading[(i,t)]
  659. for j in range(1, nsteps[i]+1):
  660. total_assigned = sum(flow.get((i,j,f,t),0) for f in fabs)
  661. if abs(total_assigned - L) > 0.5:
  662. issues.append(f" Node{i} Step{j}: assigned={total_assigned:.0f} != loading={L}")
  663.  
  664. if issues:
  665. print(f"\n {qlabels[t_idx]}: ISSUES FOUND")
  666. for iss in issues:
  667. print(iss)
  668. all_verified = False
  669. else:
  670. print(f" {qlabels[t_idx]}: OK")
  671.  
  672. if all_verified:
  673. print("\n ALL QUARTERS VERIFIED SUCCESSFULLY!")
  674. else:
  675. print("\n SOME ISSUES FOUND - Review needed")
  676.  
  677. # ============================================================
  678. # SPACE VERIFICATION
  679. # ============================================================
  680.  
  681. print("\n" + "="*80)
  682. print("11. SPACE VERIFICATION")
  683. print("="*80)
  684.  
  685. for t_idx, t in enumerate(quarters):
  686. line = f" {qlabels[t_idx]}: "
  687. all_ok = True
  688. for f in fabs:
  689. used = sum(tool_count.get((f,w,t), tool_count.get((f,w),0)) * ws[w][2]
  690. for w in all_ws_list)
  691. ok = used <= fab_space[f] + 0.01
  692. if not ok: all_ok = False
  693. line += f"F{f}={used:.0f}/{fab_space[f]}m² "
  694. line += "OK" if all_ok else "EXCEEDED!"
  695. print(line)
  696.  
  697. print("\n" + "="*80)
  698. print("SOLUTION COMPLETE")
  699. print("="*80)
  700.  
Success #stdin #stdout 0.15s 16084KB
stdin
Standard input is empty
stdout
================================================================================
MICRON NUS-ISE BACC 2026 - QUESTION 1
COMPLETE SOLUTION WITH ANALYTICAL OPTIMIZATION
================================================================================

================================================================================
1. AGGREGATE TOOL REQUIREMENTS (Mintech Only)
================================================================================

WS    Q1'26   Q2'26   Q3'26   Q4'26   Q1'27   Q2'27   Q3'27   Q4'27  Avail  PkGap
A        83      69      59      52      42      35      28      14     85      0
B        54      56      58      60      65      70      75      81     55     26
C        38      57      88     101     113     138     163     201     40    161
D       134     129     138     138     133     142     151     159    135     24
E        86     102     129     141     155     180     205     239     86    153
F       186     177     179     177     172     178     185     188    186      2

WS    Q1'26   Q2'26   Q3'26   Q4'26   Q1'27   Q2'27   Q3'27   Q4'27 (if all TOR)
A+       64      54      46      40      32      27      22      11
B+       40      41      43      44      48      51      55      59
C+       30      45      69      79      89     108     128     157
D+       98      96     103     104     101     108     116     123
E+       64      76      96     105     116     135     154     180
F+      141     135     137     136     132     138     144     147

================================================================================
2. INITIAL SPACE ANALYSIS
================================================================================

  Fab 1: 636.0 / 1500 m² used (864.0 m² free)
    C: 40 × 5.82m² = 232.8m²
    D: 35 × 5.61m² = 196.4m²
    E: 16 × 4.65m² = 74.4m²
    F: 36 × 3.68m² = 132.5m²

  Fab 2: 1235.7 / 1300 m² used (64.3 m² free)
    A: 50 × 6.78m² = 339.0m²
    B: 25 × 3.96m² = 99.0m²
    D: 50 × 5.61m² = 280.5m²
    E: 40 × 4.65m² = 186.0m²
    F: 90 × 3.68m² = 331.2m²

  Fab 3: 996.9 / 700 m² used (-296.9 m² free)
    A: 35 × 6.78m² = 237.3m²
    B: 30 × 3.96m² = 118.8m²
    D: 50 × 5.61m² = 280.5m²
    E: 30 × 4.65m² = 139.5m²
    F: 60 × 3.68m² = 220.8m²

================================================================================
3. NODE-WORKSTATION MAPPING
================================================================================

  Node 1 (11 steps):
    A: S4(20min), S8(18min), S9(16min) [total RPT=54 min]
    D: S1(14min), S6(27min), S7(17min), S10(14min) [total RPT=72 min]
    F: S2(25min), S3(27min), S5(12min), S11(18min) [total RPT=82 min]

  Node 2 (15 steps):
    B: S2(20min), S4(25min), S5(15min), S8(22min) [total RPT=82 min]
    E: S3(10min), S9(7min), S10(9min), S11(20min), S13(12min), S14(15min), S15(13min) [total RPT=86 min]
    F: S1(19min), S6(16min), S7(17min), S12(21min) [total RPT=73 min]

  Node 3 (17 steps):
    C: S1(21min), S7(24min), S8(19min), S14(12min), S16(25min) [total RPT=101 min]
    D: S2(9min), S6(12min), S9(15min), S10(24min), S15(11min) [total RPT=71 min]
    E: S3(24min), S4(15min), S11(17min), S12(18min) [total RPT=74 min]
    F: S5(16min), S13(20min), S17(14min) [total RPT=50 min]

================================================================================
4. CRITICAL CONSTRAINTS
================================================================================
  - C tools ONLY in Fab 1 (40 tools) → Node 3 C-steps MUST run in Fab 1
  - B tools ONLY in Fab 2 (25) and Fab 3 (30) → Node 2 B-steps in Fab 2/3
  - A tools ONLY in Fab 2 (50) and Fab 3 (35) → Node 1 A-steps in Fab 2/3
  - Node 3 uses C heavily (steps 1,7,8,14,16) - C is bottleneck

================================================================================
5. OPTIMIZATION: CONSTRUCTING FEASIBLE SOLUTION
================================================================================

============================================================
Quarter: Q1'26
============================================================

  Node 3 C requirement: 37.6 tools (mintech) or 29.4 (TOR)
  Fab 1 C tools available: 40
  Node 1 (12000 wfr/wk): Fab1=1, Fab2=6282, Fab3=5717
  Node 2 (5000 wfr/wk): Fab1=1, Fab2=2331, Fab3=2668
  Node 3 (3000 wfr/wk): Fab1=3000

  Space usage:
    Fab 1: 636.0/1500 m² (42%)
    Fab 2: 1235.7/1300 m² (95%)
    Fab 3: 996.9/700 m² (142%)

============================================================
Quarter: Q2'26
============================================================

  Node 3 C requirement: 56.4 tools (mintech) or 44.1 (TOR)
  Fab 1 C tools available: 40
  -> Purchase 17 C tools for Fab 1 ($37.4M)
  -> Purchase 1 B for Fab 1 ($6.0M)
  -> Purchase 16 E for Fab 1 ($56.0M)
  Node 1 (10000 wfr/wk): Fab1=1, Fab2=5235, Fab3=4764
  Node 2 (5200 wfr/wk): Fab1=96, Fab2=2380, Fab3=2724
  Node 3 (4500 wfr/wk): Fab1=4500

  Space usage:
    Fab 1: 813.3/1500 m² (54%)
    Fab 2: 1235.7/1300 m² (95%)
    Fab 3: 996.9/700 m² (142%)

============================================================
Quarter: Q3'26
============================================================

  Node 3 C requirement: 87.7 tools (mintech) or 68.6 (TOR)
  Fab 1 C tools available: 57
  -> Purchase 31 C tools for Fab 1 ($68.2M)
  -> Purchase 2 B for Fab 1 ($12.0M)
  -> Purchase 3 D for Fab 1 ($12.0M)
  -> Purchase 27 E for Fab 1 ($94.5M)
  Node 1 (8500 wfr/wk): Fab1=1, Fab2=4450, Fab3=4049
  Node 2 (5400 wfr/wk): Fab1=288, Fab2=2384, Fab3=2728
  Node 3 (7000 wfr/wk): Fab1=7000

  Space usage:
    Fab 1: 1144.1/1500 m² (76%)
    Fab 2: 1235.7/1300 m² (95%)
    Fab 3: 996.9/700 m² (142%)

============================================================
Quarter: Q4'26
============================================================

  Node 3 C requirement: 100.2 tools (mintech) or 78.4 (TOR)
  Fab 1 C tools available: 88
  -> Purchase 13 C tools for Fab 1 ($28.6M)
  -> Purchase 2 B for Fab 1 ($12.0M)
  -> Purchase 12 E for Fab 1 ($42.0M)
  Node 1 (7500 wfr/wk): Fab1=1, Fab2=3926, Fab3=3573
  Node 2 (5600 wfr/wk): Fab1=479, Fab2=2388, Fab3=2733
  Node 3 (8000 wfr/wk): Fab1=8000

  Space usage:
    Fab 1: 1283.4/1500 m² (86%)
    Fab 2: 1235.7/1300 m² (95%)
    Fab 3: 996.9/700 m² (142%)

============================================================
Quarter: Q1'27
============================================================

  Node 3 C requirement: 112.7 tools (mintech) or 88.2 (TOR)
  Fab 1 C tools available: 101
  -> Purchase 12 C tools for Fab 1 ($26.4M)
  -> Purchase 5 B for Fab 1 ($30.0M)
  -> Purchase 14 E for Fab 1 ($49.0M)
  Node 1 (6000 wfr/wk): Fab1=1, Fab2=3141, Fab3=2858
  Node 2 (6000 wfr/wk): Fab1=944, Fab2=2358, Fab3=2698
  Node 3 (9000 wfr/wk): Fab1=9000

  Space usage:
    Fab 1: 1438.2/1500 m² (96%)
    Fab 2: 1235.7/1300 m² (95%)
    Fab 3: 996.9/700 m² (142%)

============================================================
Quarter: Q2'27
============================================================

  Node 3 C requirement: 137.8 tools (mintech) or 107.9 (TOR)
  Fab 1 C tools available: 113
  -> Purchase 10 C tools for Fab 1 ($22.0M)
  -> Purchase 5 B for Fab 2 ($30.0M)
  -> Purchase 7 C for Fab 2 ($15.4M)
  WARNING: Cannot fit 8 more C tools!
  WARNING: Cannot fit 4 more D tools!
  WARNING: Cannot fit 25 more E tools!
  Node 1 (5000 wfr/wk): Fab1=1, Fab2=2617, Fab3=2382
  Node 2 (6500 wfr/wk): Fab1=948, Fab2=2842, Fab3=2710
  Node 3 (11000 wfr/wk): Fab1=9738, Fab2=1261, Fab3=1

  Space usage:
    Fab 1: 1496.4/1500 m² (100%)
    Fab 2: 1296.2/1300 m² (100%)
    Fab 3: 996.9/700 m² (142%)

============================================================
Quarter: Q3'27
============================================================

  Node 3 C requirement: 162.8 tools (mintech) or 127.5 (TOR)
  Fab 1 C tools available: 123
  -> Purchase 1 B+ for Fab 2 ($8.0M)
  WARNING: Cannot fit 4 more B tools!
  WARNING: Cannot fit 33 more C tools!
  WARNING: Cannot fit 13 more D tools!
  WARNING: Cannot fit 50 more E tools!
  Node 1 (4000 wfr/wk): Fab1=1, Fab2=2094, Fab3=1905
  Node 2 (7000 wfr/wk): Fab1=1006, Fab2=3121, Fab3=2873
  Node 3 (13000 wfr/wk): Fab1=11509, Fab2=1490, Fab3=1

  Space usage:
    Fab 1: 1496.4/1500 m² (100%)
    Fab 2: 1300.0/1300 m² (100%)
    Fab 3: 996.9/700 m² (142%)

============================================================
Quarter: Q4'27
============================================================

  Node 3 C requirement: 200.4 tools (mintech) or 156.9 (TOR)
  Fab 1 C tools available: 123
  WARNING: Cannot fit 10 more B tools!
  WARNING: Cannot fit 71 more C tools!
  WARNING: Cannot fit 21 more D tools!
  WARNING: Cannot fit 84 more E tools!
  -> Purchase 1 F+ for Fab 1 ($8.0M)
  WARNING: Cannot fit 1 more F tools!
  Node 1 (2000 wfr/wk): Fab1=1, Fab2=1047, Fab3=952
  Node 2 (7500 wfr/wk): Fab1=1077, Fab2=3344, Fab3=3079
  Node 3 (16000 wfr/wk): Fab1=14165, Fab2=1834, Fab3=1

  Space usage:
    Fab 1: 1499.9/1500 m² (100%)
    Fab 2: 1300.0/1300 m² (100%)
    Fab 3: 996.9/700 m² (142%)


================================================================================
6. PART A RESULTS SUMMARY
================================================================================

  Total CapEx:       $    557,500,000 (557.5M)
  Total Transfer:    $         26,000 (0.0M)
  GRAND TOTAL:       $    557,526,000 (557.5M)

================================================================================
7. TOOL ALLOCATION PLAN (For Excel Answer Template)
================================================================================

--- Q1'26 ---
  WS     Fab1   Fab2   Fab3  Total  NewPur
  A         0     50     35     85       0
  B         0     25     30     55       0
  C        40      0      0     40       0
  D        35     50     50    135       0
  E        16     40     30     86       0
  F        36     90     60    186       0

--- Q2'26 ---
  WS     Fab1   Fab2   Fab3  Total  NewPur
  A         0     50     35     85       0
  B         1     25     30     56       1
  C        57      0      0     57      17
  D        35     50     50    135       0
  E        32     40     30    102      16
  F        36     90     60    186       0

--- Q3'26 ---
  WS     Fab1   Fab2   Fab3  Total  NewPur
  A         0     50     35     85       0
  B         3     25     30     58       2
  C        88      0      0     88      31
  D        38     50     50    138       3
  E        59     40     30    129      27
  F        36     90     60    186       0

--- Q4'26 ---
  WS     Fab1   Fab2   Fab3  Total  NewPur
  A         0     50     35     85       0
  B         5     25     30     60       2
  C       101      0      0    101      13
  D        38     50     50    138       0
  E        71     40     30    141      12
  F        36     90     60    186       0

--- Q1'27 ---
  WS     Fab1   Fab2   Fab3  Total  NewPur
  A         0     50     35     85       0
  B        10     25     30     65       5
  C       113      0      0    113      12
  D        38     50     50    138       0
  E        85     40     30    155      14
  F        36     90     60    186       0

--- Q2'27 ---
  WS     Fab1   Fab2   Fab3  Total  NewPur
  A         0     50     35     85       0
  B        10     30     30     70       5
  C       123      7      0    130      17
  D        38     50     50    138       0
  E        85     40     30    155       0
  F        36     90     60    186       0

--- Q3'27 ---
  WS     Fab1   Fab2   Fab3  Total  NewPur
  A         0     50     35     85       0
  B        10     30     30     70       0
  C       123      7      0    130       0
  D        38     50     50    138       0
  E        85     40     30    155       0
  F        36     90     60    186       0
  B+        0      1      0      1       1

--- Q4'27 ---
  WS     Fab1   Fab2   Fab3  Total  NewPur
  A         0     50     35     85       0
  B        10     30     30     70       0
  C       123      7      0    130       0
  D        38     50     50    138       0
  E        85     40     30    155       0
  F        36     90     60    186       0
  B+        0      1      0      1       0
  F+        1      0      0      1       1

================================================================================
8. FLOW DISTRIBUTION TABLES (For Excel Answer Template)
================================================================================

--- Q1'26 ---

  Node 1 (Loading=12000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   D       1    6282    5717   12000
     2   F       1    6282    5717   12000
     3   F       1    6282    5717   12000 [F1->F2:1]
     4   A       0    6283    5717   12000
     5   F       1    6282    5717   12000
     6   D       1    6282    5717   12000
     7   D       1    6282    5717   12000 [F1->F2:1]
     8   A       0    6283    5717   12000 [F1->F2:1]
     9   A       0    6283    5717   12000
    10   D       1    6282    5717   12000
    11   F       1    6282    5717   12000

  Node 2 (Loading=5000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   F       1    2331    2668    5000 [F1->F2:1]
     2   B       0    2332    2668    5000
     3   E       1    2331    2668    5000 [F1->F2:1]
     4   B       0    2332    2668    5000 [F1->F2:1]
     5   B       0    2332    2668    5000
     6   F       1    2331    2668    5000
     7   F       1    2331    2668    5000 [F1->F2:1]
     8   B       0    2332    2668    5000
     9   E       1    2331    2668    5000
    10   E       1    2331    2668    5000
    11   E       1    2331    2668    5000
    12   F       1    2331    2668    5000
    13   E       1    2331    2668    5000
    14   E       1    2331    2668    5000
    15   E       1    2331    2668    5000

  Node 3 (Loading=3000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   C    3000       0       0    3000
     2   D    3000       0       0    3000
     3   E    3000       0       0    3000
     4   E    3000       0       0    3000
     5   F    3000       0       0    3000
     6   D    3000       0       0    3000
     7   C    3000       0       0    3000
     8   C    3000       0       0    3000
     9   D    3000       0       0    3000
    10   D    3000       0       0    3000
    11   E    3000       0       0    3000
    12   E    3000       0       0    3000
    13   F    3000       0       0    3000
    14   C    3000       0       0    3000
    15   D    3000       0       0    3000
    16   C    3000       0       0    3000
    17   F    3000       0       0    3000

--- Q2'26 ---

  Node 1 (Loading=10000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   D       1    5235    4764   10000
     2   F       1    5235    4764   10000
     3   F       1    5235    4764   10000 [F1->F2:1]
     4   A       0    5236    4764   10000
     5   F       1    5235    4764   10000
     6   D       1    5235    4764   10000
     7   D       1    5235    4764   10000 [F1->F2:1]
     8   A       0    5236    4764   10000 [F1->F2:1]
     9   A       0    5236    4764   10000
    10   D       1    5235    4764   10000
    11   F       1    5235    4764   10000

  Node 2 (Loading=5200):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   F      96    2380    2724    5200
     2   B      96    2380    2724    5200
     3   E      96    2380    2724    5200
     4   B      96    2380    2724    5200
     5   B      96    2380    2724    5200
     6   F      96    2380    2724    5200
     7   F      96    2380    2724    5200
     8   B      96    2380    2724    5200
     9   E      96    2380    2724    5200
    10   E      96    2380    2724    5200
    11   E      96    2380    2724    5200
    12   F      96    2380    2724    5200
    13   E      96    2380    2724    5200
    14   E      96    2380    2724    5200
    15   E      96    2380    2724    5200

  Node 3 (Loading=4500):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   C    4500       0       0    4500
     2   D    4500       0       0    4500
     3   E    4500       0       0    4500
     4   E    4500       0       0    4500
     5   F    4500       0       0    4500
     6   D    4500       0       0    4500
     7   C    4500       0       0    4500
     8   C    4500       0       0    4500
     9   D    4500       0       0    4500
    10   D    4500       0       0    4500
    11   E    4500       0       0    4500
    12   E    4500       0       0    4500
    13   F    4500       0       0    4500
    14   C    4500       0       0    4500
    15   D    4500       0       0    4500
    16   C    4500       0       0    4500
    17   F    4500       0       0    4500

--- Q3'26 ---

  Node 1 (Loading=8500):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   D       1    4450    4049    8500
     2   F       1    4450    4049    8500
     3   F       1    4450    4049    8500 [F1->F2:1]
     4   A       0    4451    4049    8500
     5   F       1    4450    4049    8500
     6   D       1    4450    4049    8500
     7   D       1    4450    4049    8500 [F1->F2:1]
     8   A       0    4451    4049    8500 [F1->F2:1]
     9   A       0    4451    4049    8500
    10   D       1    4450    4049    8500
    11   F       1    4450    4049    8500

  Node 2 (Loading=5400):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   F     288    2384    2728    5400
     2   B     288    2384    2728    5400
     3   E     288    2384    2728    5400
     4   B     288    2384    2728    5400
     5   B     288    2384    2728    5400
     6   F     288    2384    2728    5400
     7   F     288    2384    2728    5400
     8   B     288    2384    2728    5400
     9   E     288    2384    2728    5400
    10   E     288    2384    2728    5400
    11   E     288    2384    2728    5400
    12   F     288    2384    2728    5400
    13   E     288    2384    2728    5400
    14   E     288    2384    2728    5400
    15   E     288    2384    2728    5400

  Node 3 (Loading=7000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   C    7000       0       0    7000
     2   D    7000       0       0    7000
     3   E    7000       0       0    7000
     4   E    7000       0       0    7000
     5   F    7000       0       0    7000
     6   D    7000       0       0    7000
     7   C    7000       0       0    7000
     8   C    7000       0       0    7000
     9   D    7000       0       0    7000
    10   D    7000       0       0    7000
    11   E    7000       0       0    7000
    12   E    7000       0       0    7000
    13   F    7000       0       0    7000
    14   C    7000       0       0    7000
    15   D    7000       0       0    7000
    16   C    7000       0       0    7000
    17   F    7000       0       0    7000

--- Q4'26 ---

  Node 1 (Loading=7500):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   D       1    3926    3573    7500
     2   F       1    3926    3573    7500
     3   F       1    3926    3573    7500 [F1->F2:1]
     4   A       0    3927    3573    7500
     5   F       1    3926    3573    7500
     6   D       1    3926    3573    7500
     7   D       1    3926    3573    7500 [F1->F2:1]
     8   A       0    3927    3573    7500 [F1->F2:1]
     9   A       0    3927    3573    7500
    10   D       1    3926    3573    7500
    11   F       1    3926    3573    7500

  Node 2 (Loading=5600):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   F     479    2388    2733    5600
     2   B     479    2388    2733    5600
     3   E     479    2388    2733    5600
     4   B     479    2388    2733    5600
     5   B     479    2388    2733    5600
     6   F     479    2388    2733    5600
     7   F     479    2388    2733    5600
     8   B     479    2388    2733    5600
     9   E     479    2388    2733    5600
    10   E     479    2388    2733    5600
    11   E     479    2388    2733    5600
    12   F     479    2388    2733    5600
    13   E     479    2388    2733    5600
    14   E     479    2388    2733    5600
    15   E     479    2388    2733    5600

  Node 3 (Loading=8000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   C    8000       0       0    8000
     2   D    8000       0       0    8000
     3   E    8000       0       0    8000
     4   E    8000       0       0    8000
     5   F    8000       0       0    8000
     6   D    8000       0       0    8000
     7   C    8000       0       0    8000
     8   C    8000       0       0    8000
     9   D    8000       0       0    8000
    10   D    8000       0       0    8000
    11   E    8000       0       0    8000
    12   E    8000       0       0    8000
    13   F    8000       0       0    8000
    14   C    8000       0       0    8000
    15   D    8000       0       0    8000
    16   C    8000       0       0    8000
    17   F    8000       0       0    8000

--- Q1'27 ---

  Node 1 (Loading=6000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   D       1    3141    2858    6000
     2   F       1    3141    2858    6000
     3   F       1    3141    2858    6000 [F1->F2:1]
     4   A       0    3142    2858    6000
     5   F       1    3141    2858    6000
     6   D       1    3141    2858    6000
     7   D       1    3141    2858    6000 [F1->F2:1]
     8   A       0    3142    2858    6000 [F1->F2:1]
     9   A       0    3142    2858    6000
    10   D       1    3141    2858    6000
    11   F       1    3141    2858    6000

  Node 2 (Loading=6000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   F     944    2358    2698    6000
     2   B     944    2358    2698    6000
     3   E     944    2358    2698    6000
     4   B     944    2358    2698    6000
     5   B     944    2358    2698    6000
     6   F     944    2358    2698    6000
     7   F     944    2358    2698    6000
     8   B     944    2358    2698    6000
     9   E     944    2358    2698    6000
    10   E     944    2358    2698    6000
    11   E     944    2358    2698    6000
    12   F     944    2358    2698    6000
    13   E     944    2358    2698    6000
    14   E     944    2358    2698    6000
    15   E     944    2358    2698    6000

  Node 3 (Loading=9000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   C    9000       0       0    9000
     2   D    9000       0       0    9000
     3   E    9000       0       0    9000
     4   E    9000       0       0    9000
     5   F    9000       0       0    9000
     6   D    9000       0       0    9000
     7   C    9000       0       0    9000
     8   C    9000       0       0    9000
     9   D    9000       0       0    9000
    10   D    9000       0       0    9000
    11   E    9000       0       0    9000
    12   E    9000       0       0    9000
    13   F    9000       0       0    9000
    14   C    9000       0       0    9000
    15   D    9000       0       0    9000
    16   C    9000       0       0    9000
    17   F    9000       0       0    9000

--- Q2'27 ---

  Node 1 (Loading=5000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   D       1    2617    2382    5000
     2   F       1    2617    2382    5000
     3   F       1    2617    2382    5000 [F1->F2:1]
     4   A       0    2618    2382    5000
     5   F       1    2617    2382    5000
     6   D       1    2617    2382    5000
     7   D       1    2617    2382    5000 [F1->F2:1]
     8   A       0    2618    2382    5000 [F1->F2:1]
     9   A       0    2618    2382    5000
    10   D       1    2617    2382    5000
    11   F       1    2617    2382    5000

  Node 2 (Loading=6500):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   F     948    2842    2710    6500
     2   B     948    2842    2710    6500
     3   E     948    2842    2710    6500
     4   B     948    2842    2710    6500
     5   B     948    2842    2710    6500
     6   F     948    2842    2710    6500
     7   F     948    2842    2710    6500
     8   B     948    2842    2710    6500
     9   E     948    2842    2710    6500
    10   E     948    2842    2710    6500
    11   E     948    2842    2710    6500
    12   F     948    2842    2710    6500
    13   E     948    2842    2710    6500
    14   E     948    2842    2710    6500
    15   E     948    2842    2710    6500

  Node 3 (Loading=11000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   C    9739    1261       0   11000
     2   D    9738    1261       1   11000
     3   E    9738    1261       1   11000
     4   E    9738    1261       1   11000
     5   F    9738    1261       1   11000
     6   D    9738    1261       1   11000 [F3->F1:1]
     7   C    9739    1261       0   11000 [F3->F1:1]
     8   C    9739    1261       0   11000
     9   D    9738    1261       1   11000
    10   D    9738    1261       1   11000
    11   E    9738    1261       1   11000
    12   E    9738    1261       1   11000
    13   F    9738    1261       1   11000 [F3->F1:1]
    14   C    9739    1261       0   11000
    15   D    9738    1261       1   11000 [F3->F1:1]
    16   C    9739    1261       0   11000
    17   F    9738    1261       1   11000

--- Q3'27 ---

  Node 1 (Loading=4000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   D       1    2094    1905    4000
     2   F       1    2094    1905    4000
     3   F       1    2094    1905    4000 [F1->F2:1]
     4   A       0    2095    1905    4000
     5   F       1    2094    1905    4000
     6   D       1    2094    1905    4000
     7   D       1    2094    1905    4000 [F1->F2:1]
     8   A       0    2095    1905    4000 [F1->F2:1]
     9   A       0    2095    1905    4000
    10   D       1    2094    1905    4000
    11   F       1    2094    1905    4000

  Node 2 (Loading=7000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   F    1006    3121    2873    7000
     2   B    1006    3121    2873    7000
     3   E    1006    3121    2873    7000
     4   B    1006    3121    2873    7000
     5   B    1006    3121    2873    7000
     6   F    1006    3121    2873    7000
     7   F    1006    3121    2873    7000
     8   B    1006    3121    2873    7000
     9   E    1006    3121    2873    7000
    10   E    1006    3121    2873    7000
    11   E    1006    3121    2873    7000
    12   F    1006    3121    2873    7000
    13   E    1006    3121    2873    7000
    14   E    1006    3121    2873    7000
    15   E    1006    3121    2873    7000

  Node 3 (Loading=13000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   C   11510    1490       0   13000
     2   D   11509    1490       1   13000
     3   E   11509    1490       1   13000
     4   E   11509    1490       1   13000
     5   F   11509    1490       1   13000
     6   D   11509    1490       1   13000 [F3->F1:1]
     7   C   11510    1490       0   13000 [F3->F1:1]
     8   C   11510    1490       0   13000
     9   D   11509    1490       1   13000
    10   D   11509    1490       1   13000
    11   E   11509    1490       1   13000
    12   E   11509    1490       1   13000
    13   F   11509    1490       1   13000 [F3->F1:1]
    14   C   11510    1490       0   13000
    15   D   11509    1490       1   13000 [F3->F1:1]
    16   C   11510    1490       0   13000
    17   F   11509    1490       1   13000

--- Q4'27 ---

  Node 1 (Loading=2000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   D       1    1047     952    2000
     2   F       1    1047     952    2000
     3   F       1    1047     952    2000 [F1->F2:1]
     4   A       0    1048     952    2000
     5   F       1    1047     952    2000
     6   D       1    1047     952    2000
     7   D       1    1047     952    2000 [F1->F2:1]
     8   A       0    1048     952    2000 [F1->F2:1]
     9   A       0    1048     952    2000
    10   D       1    1047     952    2000
    11   F       1    1047     952    2000

  Node 2 (Loading=7500):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   F    1077    3344    3079    7500
     2   B    1077    3344    3079    7500
     3   E    1077    3344    3079    7500
     4   B    1077    3344    3079    7500
     5   B    1077    3344    3079    7500
     6   F    1077    3344    3079    7500
     7   F    1077    3344    3079    7500
     8   B    1077    3344    3079    7500
     9   E    1077    3344    3079    7500
    10   E    1077    3344    3079    7500
    11   E    1077    3344    3079    7500
    12   F    1077    3344    3079    7500
    13   E    1077    3344    3079    7500
    14   E    1077    3344    3079    7500
    15   E    1077    3344    3079    7500

  Node 3 (Loading=16000):
  Step  WS    Fab1    Fab2    Fab3   Total
     1   C   14166    1834       0   16000
     2   D   14165    1834       1   16000
     3   E   14165    1834       1   16000
     4   E   14165    1834       1   16000
     5   F   14165    1834       1   16000
     6   D   14165    1834       1   16000 [F3->F1:1]
     7   C   14166    1834       0   16000 [F3->F1:1]
     8   C   14166    1834       0   16000
     9   D   14165    1834       1   16000
    10   D   14165    1834       1   16000
    11   E   14165    1834       1   16000
    12   E   14165    1834       1   16000
    13   F   14165    1834       1   16000 [F3->F1:1]
    14   C   14166    1834       0   16000
    15   D   14165    1834       1   16000 [F3->F1:1]
    16   C   14166    1834       0   16000
    17   F   14165    1834       1   16000

================================================================================
9. TOOL PURCHASE SCHEDULE
================================================================================

  Q2'26:
    Fab1 B: 1 tools ($6.0M)
    Fab1 C: 17 tools ($37.4M)
    Fab1 E: 16 tools ($56.0M)

  Q3'26:
    Fab1 B: 2 tools ($12.0M)
    Fab1 C: 31 tools ($68.2M)
    Fab1 D: 3 tools ($12.0M)
    Fab1 E: 27 tools ($94.5M)

  Q4'26:
    Fab1 B: 2 tools ($12.0M)
    Fab1 C: 13 tools ($28.6M)
    Fab1 E: 12 tools ($42.0M)

  Q1'27:
    Fab1 B: 5 tools ($30.0M)
    Fab1 C: 12 tools ($26.4M)
    Fab1 E: 14 tools ($49.0M)

  Q2'27:
    Fab1 C: 10 tools ($22.0M)
    Fab2 B: 5 tools ($30.0M)
    Fab2 C: 7 tools ($15.4M)

  Q3'27:
    Fab2 B+: 1 tools ($8.0M)

  Q4'27:
    Fab1 F+: 1 tools ($8.0M)

================================================================================
10. CAPACITY & DEMAND VERIFICATION
================================================================================

  Q1'26: ISSUES FOUND
  Fab1 E: demand=222086min > cap=122573min
  Fab2 D: demand=452304min > cap=403200min
  Fab3 A: demand=308718min > cap=275184min
  Fab3 D: demand=411624min > cap=403200min
  Fab3 F: demand=663558min > cap=483840min

  Q2'26: ISSUES FOUND
  Fab1 B: demand=7872min > cap=7661min
  Fab1 D: demand=319572min > cap=282240min
  Fab1 E: demand=341256min > cap=245146min
  Fab2 B: demand=195160min > cap=191520min
  Fab3 E: demand=234264min > cap=229824min
  Fab3 F: demand=589500min > cap=483840min

  Q3'26: ISSUES FOUND
  Fab1 B: demand=23616min > cap=22982min
  Fab1 D: demand=497072min > cap=306432min
  Fab1 E: demand=542768min > cap=451987min
  Fab1 F: demand=371106min > cap=290304min
  Fab2 B: demand=195488min > cap=191520min
  Fab3 E: demand=234608min > cap=229824min
  Fab3 F: demand=531162min > cap=483840min

  Q4'26: ISSUES FOUND
  Fab1 B: demand=39278min > cap=38304min
  Fab1 D: demand=568072min > cap=306432min
  Fab1 E: demand=633194min > cap=543917min
  Fab1 F: demand=435049min > cap=290304min
  Fab2 B: demand=195816min > cap=191520min
  Fab3 E: demand=235038min > cap=229824min
  Fab3 F: demand=492495min > cap=483840min

  Q1'27: ISSUES FOUND
  Fab1 B: demand=77408min > cap=76608min
  Fab1 D: demand=639072min > cap=306432min
  Fab1 E: demand=747184min > cap=651168min
  Fab1 F: demand=518994min > cap=290304min
  Fab2 B: demand=193356min > cap=191520min
  Fab3 E: demand=232028min > cap=229824min

  Q2'27: ISSUES FOUND
  Fab1 B: demand=77736min > cap=76608min
  Fab1 D: demand=691470min > cap=306432min
  Fab1 E: demand=802140min > cap=651168min
  Fab1 F: demand=556186min > cap=290304min
  Fab2 B: demand=233044min > cap=229824min
  Fab2 C: demand=127361min > cap=56448min
  Fab2 E: demand=337726min > cap=306432min
  Fab3 E: demand=233134min > cap=229824min

  Q3'27: ISSUES FOUND
  Fab1 B: demand=82492min > cap=76608min
  Fab1 C: demand=1162510min > cap=991872min
  Fab1 D: demand=817211min > cap=306432min
  Fab1 E: demand=938182min > cap=651168min
  Fab1 F: demand=648970min > cap=290304min
  Fab2 B: demand=255922min > cap=229824min
  Fab2 C: demand=150490min > cap=56448min
  Fab2 E: demand=378666min > cap=306432min
  Fab3 B: demand=235586min > cap=229824min
  Fab3 E: demand=247152min > cap=229824min

  Q4'27: ISSUES FOUND
  Fab1 B: demand=88314min > cap=76608min
  Fab1 C: demand=1430766min > cap=991872min
  Fab1 D: demand=1005787min > cap=306432min
  Fab1 E: demand=1140832min > cap=651168min
  Fab1 F: demand=786953min > cap=290304min
  Fab2 B: demand=274208min > cap=229824min
  Fab2 C: demand=185234min > cap=56448min
  Fab2 E: demand=423300min > cap=306432min
  Fab3 B: demand=252478min > cap=229824min
  Fab3 E: demand=264868min > cap=229824min

  SOME ISSUES FOUND - Review needed

================================================================================
11. SPACE VERIFICATION
================================================================================
  Q1'26: F1=636/1500m² F2=1236/1300m² F3=997/700m² EXCEEDED!
  Q2'26: F1=813/1500m² F2=1236/1300m² F3=997/700m² EXCEEDED!
  Q3'26: F1=1144/1500m² F2=1236/1300m² F3=997/700m² EXCEEDED!
  Q4'26: F1=1283/1500m² F2=1236/1300m² F3=997/700m² EXCEEDED!
  Q1'27: F1=1438/1500m² F2=1236/1300m² F3=997/700m² EXCEEDED!
  Q2'27: F1=1496/1500m² F2=1296/1300m² F3=997/700m² EXCEEDED!
  Q3'27: F1=1496/1500m² F2=1300/1300m² F3=997/700m² EXCEEDED!
  Q4'27: F1=1500/1500m² F2=1300/1300m² F3=997/700m² EXCEEDED!

================================================================================
SOLUTION COMPLETE
================================================================================