https://schedule-nurse.blogspot.com/2024/02/excel.html
では、ソフト制約をわざわざハード制約にしましたが、この追加オプションによりその手間が不要になります。
ソフト予定部は、青で出力します。ハード予定は、赤になります。
https://schedule-nurse.blogspot.com/2024/02/excel.html
では、ソフト制約をわざわざハード制約にしましたが、この追加オプションによりその手間が不要になります。
ソフト予定部は、青で出力します。ハード予定は、赤になります。
Q.
1. 准看護師同士の夜勤は禁止にしているのですが、4/10のAさん(准看護師)とBさん(准看護師)が夜勤に自動的に割り当てられてしまう。
2.➁支援男性夜勤同士の夜勤は禁止にしているのですが、4/5 Cさん(A男性支援員集合)とDさん(B男性支援員集合)が夜勤に割り当てられてしまう。
Ans.
1.同じ集合、同じシフト同士の集合禁止は、列制約を用いてください。
2.ペア制約では、「かつ」ではなく、「または」で記述してください。
解説:
「または」を言い換えると、「少なくとも一人以上」 になります。つまり、准看護師の一人以上がペアになることを禁止する、という意味になり、ここまでは制約意図と一致すると思います。
しかし、准看護師の一人以上同士が、同じシフトである夜勤で禁止は、結局、准看護師の夜勤者数=0となってしまうので、意図と違うことになると思います。従い、ここでは、
「列制約を用いて准看護師の夜勤者数は、最大1名に制約する」が正解です。
一方「かつ」にすると、全員という意味になり、本例の場合、そもそも准看護師全員が夜勤に入ることはありえないので、制約自体が何も制約していないことになってしまいます。
2に関しては、集合またはシフトが異なるので、ペアで禁止は意味があります。従い、「または」で記述変更するだけでOKです。
言葉にすると、
A集合の少なくとも1人以上がB集合の少なくとも1人以上とペアになることを禁止
となります。こういう風に、「または」は、少なくとも1人以上、「かつ」は全員と置き換えて、言葉にして言ってみると、制約意図と合致しているかどうか分かると思います。
Q.ストア買い切り版を購入するする場合、ソフトウェアはどのような納入の形(Eメール等による送信など)となるのでしょうか?
また、もしこれから購入を希望した場合、来月(3月)末までに納品をいただくことは可能でしょうか?
Ans.
サブスクリプション版とは別の版になりますが、同じマイクロソフトストア上の製品です。
下は、私のWindows11上のアプリになります。3種ありますが、スケジュールナースPrivateというのが、買い切り版になります。
お求め頂くには、ストアに紐づけるマイクロソフトアカウント名が必要となります。送って頂くと、私の方でマイクロソフトサーバに登録すると一週間程度で使用可能になります。
インストール方法等は、サブスクリプションと同じですが、ストアURLが専用となっております。こちらは、マイクロソフトアカウント名を送って頂いた後のご案内となります。
ストアに紐づけるマイクロソフトアカウント名を送って頂いた後、1週間後に使用可能です。
公休をソフト制約にすると、リソース不足箇所を把握できる利点をお話ししました。
で、下のように、現実に公休数が足りなくなってしまいました。赤マーク箇所
しかし、幸いなことに、25日にリフレッシュ休暇を取っており、これを公休に置き換えれば、無事、公休数を満足できました。無論、スタッフの了解は要りますが、やむを得ぬ場合もあります。
で、置き換えた後の解は、次のようになりました。公休数だけでなく、夜勤数も同時に満足することが出来ました。
この例のように、一般に、リソース不足の改善は、一見関係とないと思われるスタッフのQOLにも影響を及ぼします。公休をソフト制約化し、リソース不足を顕在化させる手法は、重要です。次の制約は、早番2を今月毎日、2人を確保するソフト制約です。
残念ながら、2名のところ、1名しか確保できていない箇所が2か所あり、それが休日だったとします。
師長は、つぶやきました。「どうせなら休日ではなく、平日に欠員して欲しい」
<実装>
休日の優先度を上げる制約を追加します。制約を追加しても、この制約は、上の制約の特殊ケース(部分集合)です。なので上の制約と矛盾しません。矛盾しない制約は追加することができます。曜日集合とソフトレベルだけを変更、追加しています。
曜日集合は、マウスホイールボタンを押すことで、
確かに、下記5番の実装で防ぐことが出来ます。このパターンで問題ありません。
先月からの連続性においても完璧を期すには、最長パターン数ー1の先月分 が必要となります。
曜日タイプもそのようにした方がよいでしょう。次のように制約しました。
曜日集合は、以下で設定しています。後で述べるように第一火曜は、良い選択ではないので、希望日を可変選択できるようにしています。
<原因考察>
通常、そんな事は起こりえないと思いますが、確かに解を見ると、そのような例が見受けられます。
そこで、制約を見ると、次のように階の被りがないように制約されています。
<そもそも3回夜勤一緒になると何が問題なのか?>
という疑問が沸いてきます。夜勤経験のある方なら分かりますが、気の合うペアならば、何も問題ないです。しかし、気の合わないスタッフ、組みたくない相手である場合、3回の一緒、実質6日間も夜勤ペアならば、最悪の憂鬱となります。場合によっては、仕事を辞めたくなる要因になりえます。
従い、この問題は無視することが出来ない切実な問題、と考えられます。一方、一律で、1回に限定するとした場合、解空間を狭める、事が考えられます。この制約を入れたことによって、他の制約の成否に影響を与えたくありません。そこで、スタッフ毎に一緒になる回数を設定することにします。
一方「私は、誰とでもOKよ」というスタッフもいるでしょうし、上司からみて、皆から組むのを嫌がられているスタッフもいるでしょう。そこで、組むスタッフの一緒回数の最大をスタッフプロパティで設定するようにします。
選択は、1または2です。「私は、誰とでもOKよ」の人は、ブランクにします。どちらもブランクであれば、制約されません。どちらかが、ブランクでない場合は、ブランクでないスタッフの一緒回数で制約されます。どちらもブランクでないならば、小さいほうの数に制約されます。
def 夜勤一緒回数制約sub(p1,p2): min_num=最大夜勤一緒回数属性[p1]#p1のDICは、存在する p2のDICは、存在しないかもしれない for person in 最大夜勤一緒回数属性: if min_num> 最大夜勤一緒回数属性[p2]: min_num=最大夜勤一緒回数属性[p2] list=[] for day in 今月: v1=sc3.GetShiftVar(p1,day,'入り') v2=sc3.GetShiftVar(p2,day,'入り') list.append(v1&v2)#両方入りに入る s='夜勤一緒回数 '+staffdef[p1]+staffdef[p2] sc3.AddSoft(sc3.SeqError(0,min_num,2,list),s,5)#今月最大一緒回数 def 夜勤一緒回数制約(): for person in 最大夜勤一緒回数属性: if person in a_2F:#2階は、3階と4階を見る if person not in 入り: continue for ペア3F in b_3F: if ペア3F not in 入り: continue 夜勤一緒回数制約sub(person,ペア3F) for ペア4F in c_4F: if ペア4F not in 入り: continue 夜勤一緒回数制約sub(person,ペア4F) if person in b_3F:#3階は、4階だけ見れば十分 if person not in 入り: continue for ペア4F in c_4F: if ペア4F not in 入り: continue 夜勤一緒回数制約sub(person,ペア4F) #print(staffdef[person])夜勤ペアのうち、小さいほうの数を、一緒回数の最大回数として設定しています。こうすれば、どちらかが、1回であれば、一緒回数は最大1回に制約されます。
def check_夜勤一緒回数(): for p1 in 最大夜勤一緒回数属性: for p2 in 最大夜勤一緒回数属性: if p1==p2: continue count=0 max=最大夜勤一緒回数属性[p1] if max> 最大夜勤一緒回数属性[p2]: max=最大夜勤一緒回数属性[p2] for day in 今月: v1=shift_solution[p1][day] v2=shift_solution[p2][day] if v1=='入り' and v2=='入り': count+=1 if count>max: print("************Error",staffdef[p1],"と",staffdef[p2],"で夜勤一緒回数が、",count,"になっています。") else: print(staffdef[p1],"と",staffdef[p2],"で夜勤一緒回数が、",count,"になっています。") def post_main():#求解後、呼び出しルーチン if ダイナミック割り当てフロア長会議制約をEnable: check_フロア長会議(2) if 夜勤一緒回数制約をEnable: check_夜勤一緒回数()
_____________________________________ | | | | | Weight | Errors | Cost | |___________|___________|_____________| | | | | | 7 | 0 | 0 | | 6 | 0 | 0 | | 5 | 0 | 0 | | 3 | 2 | 6 | |___________|___________|_____________| | | | | Total | 6 | |_______________________|_____________| *********UB=6(0) 4.437(cpu sec) o 6(0) 解探索が終了しました。 5 (秒) 解が得られました。 ポスト処理を実行します。ソルバを呼び出し中です。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 1 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 1 になっています。 と で夜勤一緒回数が、 1 になっています。 と で夜勤一緒回数が、 2 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。 と で夜勤一緒回数が、 0 になっています。
ユーザフォーマットで出力するには、少し技が必要です。
Excelの出力が、難しい方は、次の方法をお勧めします。
解の画面で、右クリックし下のメニューを出します。
CSVファイルとして出力をクリックします。今回、シフト勤務表のままで行くか、タスク勤務表化するかで少し考えました。
これまで、何度も述べているように、シフト勤務表のままで行ければ、それがよいです。
シフトの数が多すぎたり、将来の拡張を考えるときは、タスク化も考慮する必要があります。
今回、シフトは、以下のようでした。
■日勤
■夜勤2交代
■早番1
■早番2
■遅番
これだけを見ると、シフト勤務表一択です。
しかし、勤務先として、2階と3階があり、各々各1名が必要というものです。プロパティで2階3階の各集合で表現することで分ける手段はあります。しかし、2階の人が3階で勤務したりすることを許しているシフトでは、シフトを分けることが必要になります。具体的には、今回日勤2、日勤3、早番22,早番23という風にシフトを分けて勤務先情報をそこに含めることで対応しました。今回は、日勤と早番2のみ、そうした対応が必要でした。つまりシフト勤務表のままです。
しかし、もしも、全てのシフトで、2階と3階に分ける必要があるのでしたら、勤務先というタスクを作ったと思います。つまり、夜勤も2階用3階用で別に確保が必要..という場合
シフトは、
■日勤
■夜勤2交代
■早番1
■早番2
■遅番
タスクは、勤務先
■2F
■3F
です。シフトとタスクは、独立に記述できるので、将来5F,6F(介護の場合4Fは無いことが多いです。)と増えても、タスクだけを追加すればよく、シフトは何も変更する必要がありません。これが、シフト勤務表のままだと、とんでもない状態数になることは、想像にかたくない、と思います。
看護勤務表の場合
シフトは、
■日勤
■夜勤2交代
■遅番
でありながら、応援先として、救急外来に行くケースは、ままあります。そこで、
タスクとして、
■自職場(NoTaskVar)
■救急外来
としておきます。通常は、NoTaskVarで、自職場になるのですが、応援先、救急外来に行く場合、シフト日勤、タスク救急外来と、二つで、シフトと勤務先が確定することになります。将来、応援先が増えたとしても、タスク追加だけで済みます。
ある介護施設での事例ですが、よくありそうな事例ですので、共有します。
3月は、リフレッシュ休暇の締めであり、期の最後である3月で、消滅してしまいます。
それで、皆さん、こぞって出してしまいます。
さらに、条件が悪いのは、3月の公休数が10個あり、休みに人が取られてしまって、夜勤、早番1・2、遅番、日勤リーダに人が廻らない、という問題が発生し易い、ということです。
看護師勤務表ならば、休日が多いと夜勤後の2連休が取りやすかったり、休日日勤者数が少なくてよいので、Welcomeな事の方が多いのですが、介護施設の場合、基本的に土日でも勤務者数は変わらず、公休数が多くて良いことはないように思います。
小手先の回避手段では、十分ではないので、なんとか改善することを考えます。
まずは、赤マークがついているところの原因を調べます。
予定を見ると、明らかに当該日の23日は、予定が詰まっていて夜勤の捻出が出来ないことが分かります。
物理的に不可能は、明らかです。グレーの日早は、公的行事日用で割り当てていますが、この部分をソフト制約化することで、赤の夜勤不足は解消できると考えられます。
次に行うことは、最低限譲れないラインを決め、ハード制約化します。
今、多くの列制約を満足出来ていません。現状は、全てソフト制約としていますが、
最低限、これは譲れないという制約は、ハード制約に変更します。
次が、譲れない線をハード制約化したものです。
次に、公休数をソフト制約化します。公休数は、本来ハード制約です。上でハード制約、予定もほぼハード制約では、解があるはずがありません。そこで、公休数をソフト制約化することで、人員の欠如を顕在化させます。
数を数える制約を基数制約、最近は、不等式制約という呼び名で呼んでいます。
レベル7なので、赤マークとなり、次のようにエラーが出ています。本来10回のところ、
8や、9になっています。
この制約で重要なのは、ソフト化する範囲指定です。範囲指定は、許容エラー数で指定します。今、2に設定しているので、10に対して±2,8から12までがソフト範囲となります。7以下および、13以上は許容しない(ハード制約と同じ)という意味です。2までは、解が存在したのですが、これを1にすると、解はありませんでした。つまり、公休10に対して、どうしても、公休8まで許さないと解が存在しないということです。つまり、リソースが足りていない、ということを意味しています。
列制約、予定制約、行制約、全てがハード制約ならば、解はありません。今、最低限必要な列制約をハード制約としました。予定も23日を除けば、ハード制約のままです。従い、行制約のリソースに関わる制約、公休数制約をソフト化することによって、解を出現させるようにします。全部が公休10に限定するならば、それは、ハード制約と同じ、許容エラー0ということであり、やはり解はありません。許容エラー1、つまり、公休数を9まで許すとしたときも解はありませんでした。公休数を8まで許す(許容エラー2)のとき、初めて解が出現しました。つまり、リソースが足りてないということが、ここで理解できます。
ところで、赤マーキングが出ているのは、下に集中していることに気づきます。
プロパティの選択を変えてみると、明らかに、人員不足は、3階に集中していることが分かります。逆にいうと、2階は、全く充足しています。
ということは、2階の人員を3月だけ3階に回せば、廻るのではないか?という発想が当然出てきます。そこで、2階の人員の一人を3階に回すと以下のとおり、公休エラーも無くなりました。解があるということは、全てのハード制約は満たすということです。(列制約部分は表示していませんが、解がある→自動的にハード制約は全て満たすなので、問題なく目的部は満たしています。)
夜勤後の休みが確保できていない箇所がありますが、この程度ならば、当該エラー箇所の予定を変更で対処できるでしょう。以上のようにして、当初の、「どうにもならない」かに見えた勤務表も、何とかなる形に持っていくことが出来ました。人力では、どうしようもない大量の希望休もスケジュールナースでは、なんとかなってしまいました。
指針として、
1)必要最低限を定めハード制約とする
2)しわ寄せ解析、リソースのどこが足りていないのかを解析する
3)部分的なリソース不足であれば、手はあるかもしれない(2階から3階に回す 等)
ということだと思います。最悪の最悪は、公休を借金する手もあるでしょう。
いずれにせよ、きちんと問題と向き合って、一体何が起きているか?どこが足りていないのか?を解析することは、必要な作業です。人的リソースを極限まで使いきるのであれば、それなりのスキルが必要になってくる、ということだと思います。(リソースに余裕がある職場では不要な作業です。)
私は、以上の解析を15分位で行いました。慣れれば、誰でも出来るようになると思いますが、車の免許と同じで、やはり十時間程度の教習は必要と思います。
ちなみに2月の勤務表では、全く上記の作業は必要なく予定を含む全ての制約を満たしていました。大量リフレッシュ休暇+3月の10日公休、という月の環境要件による違いだけで、これだけの差になってくるのか?という思いは私も同じです。
一方、施設側としては、比較的楽な月もあり、楽でない月もあります。リフレッシュ休暇は、比較的楽な月に消費させないと、今月みたく廻らない可能性が高くなる、ということだと思います。今回は、前任管理者の問題でお気の毒に思いますが、全ての管理者が、心得ておくべきことではないかと思います。
自分で言うのも何ですが、ベンチマーク性能上は勿論のこと、実使用上も世界最高のソルバーだと思います。ただ、現在、上のレベルで出来る方は、それ程多くはありません。当たり前のスキルとなる日が来ることを望んで止みません。本稿がその一助となれば幸いです。
→本稿での経験を基にトレーニングプロジェクトを作成してみました。リソースが殆どないところでどうやって捻りだすかについて、トレーニングするプロジェクトです。これが出来れば、スケジュールナースを自在に操れる有段者と認定出来ます。
schedule_nurse_practical_training.pdf (nurse-scheduling-software.com)
介護系のお客さまのシフトパターンを作成中、昨日のご質問のパターンがそのまま適用可能であったので利用させていただきました。
パターンの、詳しい解説は、昨日のブログをご参照ください。
Q.これを回避する方法はありますか?
※上記の動きを行う背景として、メモ的に予定入力でシフトを入力しておきたいが、シフト作成の途中の段階では、解の画面でシフトを反映させたくない。
Ans.申し訳ありません。仕様です。(詳しい仕様は、後述します)直接的な回避手段はありません。
適用に✓を入れて、次の代替え手段をお試しください。
1)代替え案1 Excelに予定入力を保存
一般には、予定入力の取り消しで戻ればよいのですが、制約をいじるとスタックの内容もクリアされるので、その手段は使えません。代替えとしては、予定入力の保存機能を使います。
ウィンドゥの設定→Excel取り込み..で、シフトタスク予定をExcelに出力で、そのときの状態を保存することが出来ます。Excel表の読み出しで、元に戻すことが出来ます。ソフト予定もその状態で元に戻すことができます。
2)代替え案2 ロック機能
入力が確定した段階で、ロックを行います。(黄色部がロックした部分)
試し入力は、そのまま入力頂いて、
ロック時点まで戻るには、全クリアを行います。ロックされた部分は、クリアされないので、ロック時点まで戻ることが出来ます。これもソフト状態は保存されます。
仕様:
Solve画面の適用:ソフト制約を適用するという意味になります。具体的には、ソフト制約に対してコストが発生します。これにより、予定入力に反する入力はコストが発生する機構が働くので、予定入力を維持しようとする力が働く、ことになります。適用を外すということは、コストが発生しない、つまり、予定を維持しようとする力が働らかない、という意味になります。
予定入力のソフト化:スタッフ毎のシフトを保った上で、それ以外は、あり得るという意味になります。(自動アサインを無視する、ということと同じです。)
Q.以下の画像の行制約において、No8の制約ではNo9・No10を合わせた制約と同じ効果を発揮しない。以下のようなパターンが解として出現してしまうのは、何故?
Q.予定入力の画面において、ソフト制約したい予定に対して、それぞれ違うレベルを設定したが、
求解の画面上は全て同じ項目に表示されます。それぞれのソフト制約の重みによる優先順位は機能していますか?
Ans.申し訳ございません。バグです。
GUI系ツールチップ表示のバグで、ソルバーの動作に問題はありません。次回リリースで修正を行います。(2月下旬予定)