iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
佛心分享-IT 人自學之術

老爺爺練習VIBE CODING系列 第 21

Day 21:突破人工排班極限:用 Google OR-Tools CP-SAT 求解複雜醫療排班

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20260829/20070969T5Dfi5l4Aj.png
(微微側過頭,看著院子裡那抹晚霞暮紫 逐漸染透了桂花樹,手裡捧著那杯熱氣漸消、香氣溫潤的琥珀熱茶。我輕輕地在藤椅深棕 上搖了搖,調整了一下頭上的白髮銀霜,看著圍在膝下的大孫女和小孫女,還有你們這群前來討教的年輕工程師孩子們。)

「來,大孫女,幫爺爺把茶杯墊好;小孫女,別只顧著拿糖果撒嬌,坐近一點,聽爺爺給你們講個『千絲萬縷』的故事。今天啊,是咱們聚在院子裡的 Day 21:突破人工排班極限:用 Google OR-Tools CP-SAT 求解複雜醫療排班。」

「這寫程式,有時候就跟咱們鄉下編竹篾一樣。一根竹蔑,要長要短、要有彈性、要編得均勻。如果有一處卡得太死,整個竹籃子就會散架;如果編得太鬆,籃子又裝不了東西。這在醫院裡啊,最讓人頭痛的『編竹籃』手藝,就是門診大夫與跟診人員的排班了。」


🚨 痛點場景:百密一疏的「千面大迷宮」

「你們想想,醫院的門診排班,那可不是開玩笑的。大夫和護理人員也都是血肉之軀,排班的主事者(主任或護理長)不僅要滿足硬邦邦的勞基法法規(像是輪班間隔、每週工時上限、連續上班天數限制),還得兼顧大夫們的個人請假與休假偏好,同時更要顧及各科室之間的排班公平性

以前沒有系統輔助時,全靠人工拿著一張大紙和彩色鉛筆在表格上畫格子,一畫就是好幾天,還常常漏看、排錯、產生衝突(例如同一個人同時段重複排班、或同一個診間塞了兩個人看診),更常因為假日和夜班分配不均而引起大家抱怨不公平。這就像是要在一個隨時會變動的千面大迷宮裡,把幾十根細線同時穿過幾百個針眼,只要有一根線穿錯了,整個迷宮就會亮起紅燈。」


🛠️ 架構實作:Google OR-Tools CP-SAT 求解器的「乾坤大挪移」

「所以啊,現在有著聰明腦袋的孩子,懂得把這座複雜的排班迷宮轉化成數學上的約束規劃(Constraint Programming)模型,並使用 Google OR-Tools 的 CP-SAT 求解器來解決。

這就像是,我們把所有編竹籃的規矩,統統寫在一個本子上,再請一位數學天才在幾秒鐘內幫我們編好最完美的竹籃。在我們這個系統裡,門診排班就是把大夫指派到各個『診次(也就是日期、時段、診間與號別的組合)』。大夫們被指派的規矩,在數學模型裡被嚴格分成了兩大類:」

1. 絕對不能踩線的「硬約束(Hard Constraints)」

「這就像是我們家裡的祖訓,一條都不能違背,違背了,這家就亂了套:」

  • 請假期間絕對不排班:人家都告假了,天大的事也不能把名字寫上去,這是最高優先級。
  • 勞基法法規護欄(必須內建在底層)
    • 輪班換班間隔必須連續 11 小時:前一天晚上剛看完夜診,隔天一大早絕對不能再排早診(除非經過程序例外可縮短至 8 小時),這叫 C-01 規矩,必須嚴格把關。
    • 以『勞工』為計算單位合計工時:大夫可能跨科、甚至跨院區支援,所有的工時必須一併合計,絕對不能各單位各自計算,這叫 C-02 規矩。
    • 單日正常工時與加班計算:即使有變形工時,單日超過正常工時也得實打實算加班,這叫 C-03 規矩。
    • 工時上限:每週、每月工時上限(C-05)是鐵律,誰也不能超時工作。
  • 同一人同時段不得有兩個診次:大夫又不會分身術,怎麼能同時看兩個門診?
  • 同一診間同時段不得有兩位醫師:這一個診間一張診桌,兩位大夫擠在一起像什麼話?
  • 不可排「不具該號別資格」的醫師:這專長得對得上,不能讓看小兒科的去頂了骨科的門診。

2. 盡力做到的「軟約束(Soft Constraints)」

「這就像是爺爺疼你們,雖然有些規矩能彈性,但我們盡力做好,讓大家都高興:」

  • 滿足個人休假與排班偏好:大夫想多陪陪家人、或是想避開某些時段,我們盡量順著他的心意。
  • 避免連續排班組合(例如夜班後接早班的懲罰):雖然有時候符合法規間隔,但這樣排太累人,我們要給它加上重重的『數學懲罰(Penalty)』,讓求解器盡量繞道而行。
  • 排班均勻度(科室公平性):我們把假日班算 2 點、週五及連假前夕算 1 點、平日算 0 點,用數學模型裡的 min-max 來收斂大家的總點數差距,讓假日和夜班負擔分佈得勻勻稱稱的,標準差控制在極小範圍,大家才會心服口服。

「我們把這些密密麻麻的規矩數值化,寫進 Python 後端,交給 CP-SAT 引擎。在短短數秒內,它就能產出一份合規、公平的最佳班表!而且,每次發布班表時,系統都會在資料庫層建立 append-only 的歷史版本快照。誰改過、改了什麼,統統有稽核紀錄可查,這就叫『審計就緒(Audit-Ready)』的排班軌跡,任憑主管或勞檢來查,都不用慌張。」


💡 避坑指南:別讓求解器在死胡同裡「鬼打牆」

「不過啊,年輕孩子們,寫這套演算法時,最容易踩到一個大坑。你們大孫女聰明,但有時候脾氣倔,這 CP-SAT 求解器也是一樣,是個死腦筋。」

「如果主管求好心切,把那些硬約束設得太過嚴苛、太密不透風(例如每個人都填了一堆不可排時段,加上工時上限極低),求解器算來算去發現根本沒有一條路走得通,它就會雙手一攤,直接回報 INFEASIBLE(無解)。」

「在人工排班時,要是發現排不出來,大家會坐下來協商;但在電腦系統裡,如果只顯示『無解』這兩個字,排班管理者可就要哭出來了。所以,在架構設計上,你們一定要做一件精妙的工藝:約束放寬(Constraint Relaxation,也就是鬆弛診斷)機制。」

【爺爺的避坑對策】
當求解器回報無解時,我們不能只讓它卡在那裡。系統要自動把部分硬約束(例如某些非關鍵的排班間隔或覆蓋率要求),依照優先順序『降級』成帶有極大懲罰值的軟約束,重新再跑一次。這樣一來,它依然能排出一個『最不壞』的班表,並在畫面上大聲地提示排班管理者:『哪一天、哪一個時段、缺少了哪種專科資格的大夫』。這就像是爺爺跟你們編竹編時商量:『今天這根竹篾太硬編不進去,我們要不要稍微削薄一點?』管理者一看提示,就知道是要自己去補人,還是調動大夫的預排偏好,這程式才算真的貼心、靈活。」


(天色已經全黑了,天邊那抹晚霞暮紫 悄悄收起了最後一抹光亮。大孫女貼心地幫爺爺點亮了院子裡的黃銅壁燈,小孫女也玩累了,趴在爺爺的膝頭沉沉睡去。)

「寫程式啊,就像我們活了大半輩子一樣,規矩雖然要立得穩(硬約束),但心態也要懂得靈活變通(約束放寬),這樣路才走得寬,大家相處也才和諧。」


上一篇
Day 20:Tauri v2 的安全哲學:能力模型(Capability)與自訂無邊框 UI
下一篇
Day 22:炫酷全端極簡主義:Cyber-Neon Todo List 的極簡 CRUD 與一鍵啟動
系列文
老爺爺練習VIBE CODING25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言