2023年12月29日金曜日

ペア制約再考

 ずっとこの問題を考えてきて、一つの方策がリニア化だったのですが、十分でないどころか、殆ど寄与できないことが明らかになり、どうしても再考せざるを得ません。(リニアペア制約が失敗という訳ではなく、前回の会議の日は日勤増みたい制約で威力を発揮しています。)
幸いにしてこの時期は、サポート関係の仕事が入ってこないので、深く思索する時間が持てます。加えて、単にペア制約というだけでなく、ペア制約の一般化を考える必要があるということがあります。ライフワークとして取り組んでいるナーススケジューリング問題ですが、実際的によく起きる問題でありながら、誰もこの問題について指摘・改善に取り組んでいません。孤峰に独り挑む気分です。

一般化ペア制約の定義

スタッフ間でリニア制約以外の関係があるときの制約とします。リニア制約とは、

ΣCoffA[i]*A[i]=[max,min]

という制約で表現できるときは、 リニア制約です。そのスタッフ内でクローズした制約、例えば、公休回数や、夜勤回数は、そのスタッフ内でクローズしているので、ペア制約にはなりません。スタッフ間で、上記制約で表現できない関係があるときに一般化ペア制約と定義します。

これによれば、ペア禁止は、一般化ペア制約ではありません。ペア禁止は、リニア制約で表現できるので、一般化ペア制約ではありません。また列制約の全ては、上記リニア制約で表現出来ます。

プリセプタプリセプティの関係は、リニアです。会議の制約で、シフトを専用に割り振れば、リニアになります。CCと新人の関係もそうです。

専用シフトを設けない会議、CCと新人、助産師と看護師がいて看護師のみペアの夜勤連続不可、といった制約も、一般化ペア制約の範疇ということになります。これらは、AL3/4では、苦手もしくは扱いきれない問題、ということが出来ます。

逆に言えば、専用シフト・タスクを設ければ、大半の問題をリニアに出来るということではないかと思います。





2023年12月28日木曜日

会議の日は、日勤者数を増やす ダイナミック版

というご要望があったので、とりあえずダイナミック版を作成してみました。

ポイントは二つあります。

会議は、ダイナミックにアサインしますが、その際に、日勤者を増員するというものです。

(1)インタラクティブに増員数を決める

増員する度合いが分からないので、そこは、インタラクティブに聞くダイアログを作成しました。pywin32でそのものズバリのダイアログがあったのでそれを使います。列制約で、日勤者数という制約があり、最小2以上を制約しています。それをソース全体から拾ってきて、増員数をインタラクティブに決めています。



(2)看護師長が会議ならば、日勤者数を増やす

これは、SoftLinerCompで実装できます。看護師長が会議という状態をブール変数vとして

Σv*CoffA <= ΣListB[i]*CoffB

とすれば、自由に増員できます。ここで、CoffAは、会議の日における増員後の日勤者数です。

看護師長に会議がアサインされないときは、0<=Σ

となり常に成立しますから、悪さはしません。

実装してみたら、そもそも会議で、日勤者が増えているので、制約することの程でもないような...というオチでした。



import sc3
import pywin.dialogs.list




def 会議の日は日勤者数を増やす(会議シフト名):
    min_day_workers=日勤数[8]#min
    print(min_day_workers)
    title=会議シフト名+'日は日勤者を何人にしますか?'
    s0='通常日勤者数'+str(min_day_workers)+'人に同じ'
    s1='増員1人 '+str(min_day_workers+1)+'人以上'
    s2='増員2人 '+str(min_day_workers+2)+'人以上'
    s3='増員3人 '+str(min_day_workers+3)+'人以上'
    s4='増員4人 '+str(min_day_workers+4)+'人以上'
    s5='増員5人 '+str(min_day_workers+5)+'人以上'
    s6='増員6人 '+str(min_day_workers+6)+'人以上'
    result=pywin.dialogs.list.SelectFromList(title, [s0, s1,s2,s3,s4,s5,s6])
    print(result)
    if result==None or result==0:#同じなら制約しなくてよい
        return
 
    for day in 今月:
        v=sc3.GetShiftVar(0,day,会議シフト名)#看護師長
        listA=[]
        listA.append(v)
        s=会議シフト名+'SLC '+daydef[day]
        mode=-1#mode=1 >=  mode=0 ==  mode=-1 <=
        CoffA=result+min_day_workers
        CoffB=1
        offset=0
        allowable_errors=3
        listB=[]
        for person in 日勤要員:
            v=sc3.GetShiftVar(person,day,'日勤')
            listB.append(v)
        print(daydef[day],CoffA,len(日勤要員))
        sc3.AddSoft(sc3.SoftLinearComp(mode,CoffA,CoffB,offset,allowable_errors,listA,listB),s,5)#level 5
    

会議の日は日勤者数を増やす('リーダ会議')
会議の日は日勤者数を増やす('副看護師長会議')

    

2023年12月27日水曜日

手動Updateの仕方

本ブログ等で、リリースしたとの情報があるにも拘わらず、アップデートされないときは、

以下の手順で更新します。 この手順がもっとも安定しているようです。

(1)ストアにマイクロソフトアカウントを開く







 (2) ストアにサインインする

(3)更新をクリックする


注意:

ストアをサインアウトすると使えません。使用時は、購入時のマイクロソフトアカウントでサインインしてください。

2023年12月25日月曜日

DEC252023BUILD内容

 買い切り版(DEC202023BUILD)内容に同じです。

現在審査中なのでリリースは年末だと思います。

   1)StaffPropertySheet frozen

スケジュールナースのブログ: 細かな改善 (schedule-nurse.blogspot.com)

2)add_fm_solution実装

スケジュールナースのブログ: 選択部を予定に送る (schedule-nurse.blogspot.com)

スケジュールナースのブログ: 「予定に送る」と「選択部を予定に送る」の違い (schedule-nurse.blogspot.com)

3)Python レベル7エラーの色が黄色ー>赤に修正

4)Excelからのインポートでロックが残ってしまう問題の修正

5)入力へ送るで、ロックが解除されるように修正

6)フィルタフォント修正

スケジュールナースのブログ: 細かな改善 (schedule-nurse.blogspot.com)

     7)予定シフト・タスクのみExcelに出力

スケジュールナースのブログ: 予定シフト・タスクのみをExcelに出力 (schedule-nurse.blogspot.com)

2023年12月24日日曜日

スタッフに忖度した勤務表作成の仕方

手動だと、どうしても、こういう作り方になると思います。

人生初の勤務表作成 勤務表作成に、これもありか、という考え方 (nurse-scheduling-software.com)

自動にしてから、それは無くなったとおっしゃっていましたので、自動の常識とあてはまらない世界にいたのだな、と思います。公平・公正・公明が当たり前で、そうあるべきと思っていたのですが、現場の管理者の実際は、もっとドロドロとした世界なのかな?と思います。少し反省し寄り添ってみました。


大学病院での講義ノートとセットでご覧ください

 スケジュールナース講義ノート

2023年12月23日土曜日

細かな改善

1)フィルタの文字が小さすぎる⇒小さくならないようにしました


2)コメント列までFrozen
コメント行が常に見えるようにしました

 いずれも年末のリリースから適用です

2023年12月22日金曜日

「予定に送る」と「選択部を予定に送る」の違い

 予定に送る時は、ロックを全て外します(DEC2023以降のビルド)

これは、次月への移行時のみ使う機能です。予定にロックが残っていると、スタッフ毎の予定でConlfictした予定をSoft化して回避している機構が働かないため、そのように変更しました。

一方、「選択部を予定に送る」は、未だ予定のEdit中を想定しています。そのためUndo/Redoスタックも動作しますし、ロックされたところには書き込めないのは、通常のコピペ動作と同じです。