非常勤医師の勤務形態により常勤医師は、30分ー90分の短時間宿直勤務がありえます。その短縮勤務を誰が行うかについて、常勤医師と非常勤医師とで出身医局が同じが望ましい、という制約があります。
具体的に決まっていますが、個人名で制約するのではなく、一旦グループ属性で表現して抽象化することをお勧めします。
非常勤医師の勤務形態により常勤医師は、30分ー90分の短時間宿直勤務がありえます。その短縮勤務を誰が行うかについて、常勤医師と非常勤医師とで出身医局が同じが望ましい、という制約があります。
具体的に決まっていますが、個人名で制約するのではなく、一旦グループ属性で表現して抽象化することをお勧めします。
このプロジェクトの列制約は、全てハード制約です。
まずは、簡単な制約から。休日のみに存在するシフトは、平日禁止にします。
1)日直・宿直・宿日直は、平日の勤務を除く時間帯であり、切れ目なく常に一人が勤
務していること。30分以下の空き・重複も許されない。
2)拘束は、平日の勤務を除く時間帯であり、内科及び整形外科の常勤医師一人が自宅
待機等していること。 30分以下の空き・重複も許されない。
3)日直、宿直又は宿日直を常勤医師が行った場合は、担当科の拘束医を兼ねる。
このプロジェクトは、スケジュールナース史上、最も複雑なプロジェクトですが、シフト、フェーズ、タスクを駆使することで、ほぼPythonで記述することなく出来ています。
重要視しているのが、下記の4項目らしいです。
休日宿直数
平日宿直数
休日拘束数
平日拘束数
これらが、フラットになるように平準化します。いつものスタッフプロパティで記述します。基本的には、最大と最小で記述します。
イメージ的には、24時間勤務である宿日直を3として、日直は、8時間なので、1、宿直は、16時間なので、2とした方が、勤務時間と比例するカウントとなるので合うような気がしますが、ユーザ指定の通りとしています。
マッピング、1→2,0.5→1は、必要になりますが、ご理解頂けるでしょう。
改めて、定義とルールを書き出します。
定義
1)日直は、休日の昼間時間帯の勤務である
2)宿直は、夜間帯の勤務である
3)宿日直は、日直と宿直を合わせた勤務である。
4)拘束は、日直、宿直又は宿日直の時間帯の自宅待機等である。
ルール
1)日直・宿直・宿日直は、平日の勤務を除く時間帯であり、切れ目なく常に一人が勤務していること。
30分以下の空き・重複も許されない。
2)拘束は、平日の勤務を除く時間帯であり、内科及び整形外科の常勤医師一人が自宅待機等していること。
30分以下の空き・重複も許されない。
3)日直、宿直又は宿日直を常勤医師が行った場合は、担当科の拘束医を兼ねる。
なお、宿直カウントと拘束カウントは、平準化するための制約で使用します。
勤務表制約で難しいのは、定義とルールを表により整理せずに、いきなり制約を書くことはできない、ということです。これらは、AIは決してやってはくれません。人間がやるべき作業になります。
シフトの自動アサインは、全てのスタッフが対象です。チェックを外すと全てのスタッフが自動アサインがオフになってしまいます。今回は、非常勤医のみ、予定だけの勤務となるようにしたい、ということです。
実装としては、以下のようなPythonになります。非常勤医師で、予定に何も入っていなかったら、「その他」にしてしまう、という単純な実装になります。簡単ですので、Pythonが分からなくとも、コピペして利用可能と思います。
import sc3
for person in 非常勤: for day in 今月: if shift_schedules[person][day][0]=='': v=sc3.GetShiftVar(person,day,'その他') s='非常勤は予定入力がないときはその他 '+staffdef[person]+' '+daydef[day] sc3.AddHard(v,s)
タスクは、診療科にします。これで、休日のフェーズ0/1/2,平日のフェーズ1/2に対して縦の列を制約します。診療科の設定は、自由ですので、将来の追加・変更は容易であり拡張性を有しています。これをシフトのみで行おうとすると破綻すると思います。
もう一つのポイントは、NoTaskVarを使用しない、ということです。これまでのフェーズモードを有する勤務表では、これを用いる例が殆どだったと思いますが今回は用いません。
この特殊タスクの説明は、難しいので割愛しますが、これを用いないということは、定義されている全てのフェーズでタスクがFillINされている必要がある、ということになります。例えば、宿日直というシフトのフェーズを見ると24時間、フェーズ0/1/2でチェックがされています。このときフェーズ0/1/2のいずれでも、以下のタスクのどれかが必ず割り当てられるという意味になります。空きや重複はありえません。必ず、定義したタスクのどれかが割り当てられる、という仕様になります。
シフトは、以下のように最終的になりました。拘束勤務をしつつ、日直や宿直、宿日直、短時間宿直があり得るので、どうしても状態数が増えてしまいますが、これ以下にはできません。通常の勤務や休みは全てまとめて、「その他」シフトにしています。このシフトは別な意味で便利で、当直したくない日には、予定を「その他」で埋めてしまえばよい訳です。「30分以下の空きや重複がない、切れ目なく」の実装は、シフトで保証します。縦の列はタスクで保証します。この病院では、後述するつなぎ宿直において、複数の診療科を担当することがあり得るので、フェーズモードのタスクにより特定する必要があります。タスクを用いるには、フェーズ設定が必要になります。1日を3つのフェーズに分けています。朝から始まる昼間帯の勤務がフェーズ0になります。本勤務表では、当直・拘束以外は、扱いませんが、通常の勤務は、フェーズ0となります。其のあと、夕方から夜間がフェーズ1、朝までをフェーズ2とします。深夜から翌朝までは、次の日になることに注意してください。つまり、今日のシフトは、明日の分まで含んでいます。
多くのシフトを掲載していますが、その胆は、次の3つです。