2023年11月30日木曜日

Zoom Meetingについて

ご希望のあるお客さまには、Zoomで操作方法等をお教えしています。(プロジェクト作成サービスのお客さまは無料です。)お客さまのビデオをオフとすることも可能です。

Q.その日までこちらで整えておく設備は何かありますでしょうか?

サブスクはそれまでに入っておきます。zoomは使用したことがありません。

Ans.



■事前準備について、

当日時刻になりましたら、上のURLをクリックすればよいのですが、参考までに、ZOOM Meetingの参考になるサイトをご案内します。ZOOMは、無料版でOKです。


https://yogashare.info/blog/zoom-macbook-2/


サイトで言っているとおり、事前にインストールして、カメラとマイクのテストを行っておくとよいでしょう。


■設備について

マイクは、必須です。カメラは、必須ではないと思いますが、なしで行ったことがないので、WEBカメラを購入されることをお勧めします。

ZOOMミーティング用途だけでしたら、高いのは必要ありません。


https://kakakumag.com/camera/?id=16484


また、NotePCでしたら、購入しなくとも備わっていると思います。



■サブスクのインストール


ダウンロードに時間がかかる場合がございます。当日までに、ZOOMミーミーティング用のPCにインストールをお願いします。

稼働PCとは違っても構わないのですが、説明する画面を共有する関係で同じPCで説明した方が都合がよいです。(同じマイクロソフトアカウントで10台まで使用できますが各々インストールが必要となります。)

以上です。


2023年11月29日水曜日

Pythonの必要性

Q.スケジュールナースはノーコードで論理式を組んで、演算させるソフトなので

それなりに複雑な条件式を仕様書から落とし込まないと実用的なシフト自動作成にはならず、

ノーコードで対応できない部分はPythonのプログラム記述で対応となっていると思います。

なので、買取や月額だけで動くソフトではなく論理式を組む必要があるのですが、その実績もありますか?

A.

恐れ入りますが同意致しかねます。

スケジュールナースは、「集合」を用いたハード制約・ソフト制約という制約で記述するスタイルが、他のソフトと明確に異なります。

雛形はありません。汎用的であり、微細な制約も記述可能な反面、プログラミングスキルに似た一定のバリアが存在し、それさえも面倒で難しいと感じる方が少なくありません。

また、過去にPythonでしか記述出来なかったコードもバージョンアップによりGUI化での記述を促進しており、看護師・介護士勤務表に関しては、GUIのみプロジェクトが大半となっております。


参考:以下のお客さまもPythonなしですが、前述の理由から、菅原システムズのプロジェクト作成サービスを利用されています。


https://www.nurse-scheduling-software.com/japanese/nurse_scheduling_problem/chapter30/

Pythonは、組み込み版(3.10)を採用しています。他の環境は使用しません(出来ません)。


以下は、制約の記述例です。ご利用されている実際のお客さまのプロジェクトの断片を切り取ったものが殆どですが、どのようなときにPythonを使わざるを得ないか?の参考にはなるかと思います。



実績という意味において、看護師・介護士勤務表については、前述の通りです。
その他のプロジェクト作成サービスでPythonを使う頻度は、2-3割程度と思います。
独自言語からPythonに移行して数年経ちますが過去のPythonコードは全て継承するというポリシーは貫いておりますので、ご安心ください。

2023年11月26日日曜日

Nov252023 Release

 1)予定縮小時の不具合改善

https://schedule-nurse.blogspot.com/2023/11/blog-post_15.html

2)UnaryCounterの実装

https://schedule-nurse.blogspot.com/2023/11/blog-post_21.html

https://schedule-nurse.blogspot.com/2023/11/blog-post_17.html

3)Python許容エラーオーバライド

https://schedule-nurse.blogspot.com/2023/11/python.html

UnaryCounter

 「半人前」を実現するために導入した制約関数であり、通常の制約関数とは異なります。

この関数は、2種類のリストの一部としか機能しません。2種類のリストとは、


■sc3.SeqError(min,max,allowable_errors,list)

■sc3.SoftLinearComp(eq_mode, CoffA, CoffB,  offset,  allowable_errors,listA,listB); 


です。この2種類しかサポートしません。

パラメータは、二つしかなく、

■sc3.UnaryCounter(bitstart,bit_interval)

です。

UnaryCounterとは、1進加算器のことであり、ビットの桁数は、入力の個数だけあります。

つまり桁上がりがないカウンタになります。


ビットスタート0、ビットインターバル1だと、そのままの出力になります。

 ビットインターバル2だと、一つ飛びに出力されます。/2されるイメージです。

ビットスタートは、mod演算に対応します。下図は、bit interval=2のときの様子ですが、

同じbit interval=2でも、bitstartによって、エンコードの様子が異なります。


余りがないときは、どちらも同じですが、一人のときを1人と数えるか0人と数えるかの違いがあります。どちらのエンコードを指定するかは、bit_startを指定すれば決まります。

この論理構造は、次で実現できます。

これは、アルゴリズム3/4でのグラフ構造になります。アルゴリズム1は、同じ1進加算を使いますが、また別の構造により実現します。

アルゴリズム2と3/4の数理表現では、次のような記述になっています。
上のような回路構造の記述と異なり、数理的な表現になります。

ip.add_constraint(num_working <= (bit_interval) * x+bit_start, x);
ip.add_constraint(num_working >= (bit_interval) * x-(bit_interval-1-bit_start), x);

つまり、同じUnaryCouter機能を実現するのに、アルゴリズム毎に記述を変える必要があります。どれも、同じ機能には違いないのですが、テクノロジーが違うと全く違う表現になる様子を紹介しました。
組み合わせ最適化は、一つのテクノロジだけでは、網羅できません。広範囲のテクノロジーを組み合わせて、スケジュールナース最適化は成っているのです。




2023年11月25日土曜日

python許容エラーオーバライド

 Nov.End.2023リリースの新機能です。

次のPython制約関数において、allowable errorsは、言語で固定されていて変更することは出来ませんでした。

■sc3.SeqError(min,max,allowable_errors,list)

■sc3.SoftSeqComp(offset,allowable_errors,listA,listB)

■sc3.SoftLinearComp(eq_mode, CoffA, CoffB,  offset,  allowable_errors,listA,listB); 

しかし、Python許容エラーオーバライドをオンすると、求解パラメータの許容エラーの値が

オーバライドされます。これにより、Pythonソースをいじらなくても、許容エラーを可変することのが可能になります。


例えば、次の例では、解がないエラーが生じています。
このとき、許容エラーは、言語により3となっています。

しかし、Python許容エラーオーバライドをオンすると、求解パラメータの方が優先され、許容値を5することができます。(0としてハード制約にすることも出来ます。)
その結果として、解が存在できるようになりました。




2023年11月24日金曜日

旧版のストア版への移行について

 Q.2020年にスケジュールナースを購入し、利用させていただいております。

当時、買い切り版で購入しました。

今回、他のPCにソフトのインストールを試みたのですが、サブスク版に導かれます。

ホームページ上では「紐づいたマイクロソフトアカウント上でPC10台まで同時使用可能です。」となっておりますが、インストール方法がわかりませんでした。


サブスク版ではないインストール方法を、教えていただきたいです。

A.

ストア版に移行の際、不通か何かでご案内できませんでした。恐れ入ります。下記の買い切り版対応とさせて頂きます。

https://www.nurse-scheduling-software.com/japanese/service2/onetime_purchase/

勿論、無料にて発行しますが、唯一、手続きとして、マイクロソフトアカウント名を、スケジュールナースストア版と紐づける必要がございます。

アカウント名をお送り頂くと、マイクロソフトのサーバに登録します。登録には、1週間程度見ていただきます。登録完了後は、永続的に使えるようになります。

2023年11月21日火曜日

数を数えるということ

 各テクノロジーのバックグランドが異なるので、実は、数え方は一つではありません。

正確には、アルゴリズム1,2,3毎に違う数え方をしています。数を数えるということは、組み合わせ最適化において、本質的なことではありますが、数理的な数え方と、論理的な数え方の違いということがあります。本質的には、数理的な数え方と論理的な数え方は、同じはずですが、算法的には、違います。汎用問題を考えたとき、有利なのは、数理的解法になります。一方、数が少ないときの組み合わせ最適化を考えたときは、論理的解法の方が有利なような気がします。従い、数が少ない場合の組み合わせ最適化問題、ナーススケジューリング問題では、論理的解法であるアルゴリズム1が一般的には優勢になるのだ、という理解をしています。しかし、問題規模が大きくなってくると、論理的に扱うには、複雑になりすぎ、その場合は、数理解法が有利になってくる、ということではないでしょうか?

それでは、一体、数理解法と論理解法では何が違うか?ということについて考えてみましょう。一番の違いは、論理解法の場合は、何進法を使うか?ということが効いてきます。ところが、数理解法の場合は、それが明示されずに意識されることはほぼありません。論理解法の場合、コンピュータ上のハードウェア資源である乗算器を使うことはほぼないのですが、数理解法の場合は、無しでは考えられません。つまり、ハードウェア資源である乗算器の使用の有無が、大いに関係しています。

乗算器をブール代数でグラフ化したものを見たことがあるでしょうか?16x16bitでさえ、トンでもない規模のグラフとなります。乗算器というのは、組わせ回路の塊であり、AND/OR/INVの回路からのみ成りますが、大きな数を表すといることは、それだけ多くの組み合わせがある、ということの裏返しということでしょう。そういう場合には、直接にPC資源を利用した方がよい、ということではないかと思います。(昨今の人口知能における機械学習において、この乗算器の存在は必須です。)

論理的解法と数理解法について言及しましたが、もう少し正確に言うと、論理解法は、アルゴリズム1、数理解法は、アルゴリズム2、両者のハイブリッド解法が、アルゴリズム3/4ということになります。最初に説明した通り、各々、数の数え方が違うので、「半人前」の実装において違いを見ていきたいと思います。

https://schedule-nurse.blogspot.com/2023/11/unarycounter.html



2023年11月19日日曜日

委員会のチェック

 9つある委員会は、全て日勤です。解から、開催日を人手が割り出すのは手間です。また、ソフトエラーがあった場合、必ずしも、目的の人数が確保できている訳ではありませんので、最大確保できた日を報告することとします。また、確保できなかった場合、長日勤を含めてカウントするとどうなるかも報告しています。

このプロジェクトは、多人数かつタイトなプロジェクトで時間がかなりかかっています。


import sc3
import itertools
import ctypes

def 委員会制約():
    MessageBox = ctypes.windll.user32.MessageBoxW
    res=MessageBox(HWND, '委員会に長日を含めますか?(推奨)', '長日を含める選択', 3)
    include_long=False
    if res==6:
        include_long=True
    use_hard_constraint=False
    res=MessageBox(HWND, '委員会制約をハード制約にしますか?(推奨)', '委員会制約をハード制約にする選択', 3)
    if res==6:
        use_hard_constraint=True
    global_vars = globals()
    print("グローバル変数一覧:")
    for var_name, var_value in global_vars.items():
        if '委員会' in var_name and isinstance(var_value,list):#委員会という名前を持つリストオブジェクトのみリストアップ
            assign_comittee(var_name,var_value[0],include_long,use_hard_constraint)# ":", var_value)

def assign_comittee(name,vars_list,include_long,use_hard_constraint):
    print(name,vars_list,include_long)
    day_end=100
    if name=='現任教育委員会' or name=='新任教育委員会':#10日までに開催委員会
        day_end=制約開始日+10
    day_list=[]
    for day in 今月稼働日:
        and_list=[]
        for person in vars_list:
            v=sc3.GetShiftVar(person,day,'日勤')
            if include_long:
                v2=sc3.GetShiftVar(person,day,'ロング日勤')
                and_list.append(v2|v)
            else:
                and_list.append(v)
        vx=sc3.And(and_list)
        day_list.append(vx)
        if day>day_end:
            break
    if use_hard_constraint:
        sc3.AddHard(sc3.Or(day_list),name)
    else :
        sc3.AddSoft(sc3.Or(day_list),name,5)
    
def check_comittee_sub(name,vars_list,include_long=False):
    #print(name,vars_list)
    day_end=100
    if name=='現任教育委員会' or name=='新任教育委員会':#10日までに開催委員会
        day_end=制約開始日+10
    day_list=[]
    big_cnt_day=0
    big_cnt=0
    for day in 今月稼働日:
        and_cnt=0
        for person in vars_list:
            if include_long:
                v=shift_solution[person][day]=='日勤' or shift_solution[person][day]=='ロング日勤' or shift_solution[person][day]=='ロング日勤単発'
            else:
                v=shift_solution[person][day]=='日勤' 
            if v:
                and_cnt+=1
        if and_cnt>big_cnt:
            big_cnt=and_cnt
            big_cnt_day=day
        if big_cnt==len(vars_list):
            day_list.append(day)
        if day>day_end:
            break
    success=True
    if len(day_list)>=1:
        if include_long:
            print("長日を含めると")
        print("successful ",name)
        for day in day_list:
            print(name,"委員会日は、",daydef[day],"参加者全員は",len(vars_list),"人です")
        print("")
    else:
        if include_long:
            print("長日を含めても")
        print("unsuccessful ",name,len(vars_list),"人に対して",big_cnt,"人しかアサインされていません。",daydef[day])
        success=False
        if include_long:
            print("")
    
    return success
def check_comittee():
    
    global_vars = globals()
    print("グローバル変数一覧:")
    for var_name, var_value in global_vars.items():
        if '委員会' in var_name and isinstance(var_value,list):#list list
            success=check_comittee_sub(var_name,var_value[0])# ":", var_value)
            if not success:
                check_comittee_sub(var_name,var_value[0],True)


    

def post_main():
    check_comittee()
    

委員会制約()

ポスト処理後は、以下の表示となりました。
コンパイルの準備中
ソルバを呼び出し中です。
	制約をコンパイル中です。
	Python プロパティファイルの生成が終わりました。
グローバル変数一覧:
現任教育委員会 [5, 22, 28, 33, 46, 51, 56] False
新任教育委員会 [2, 29, 32, 54, 58, 62] False
リスク委員会 [3, 25, 31, 57, 64] False
感染委員会 [4, 24, 37, 55, 59, 66] False
業務委員会 [2, 21, 39, 52, 62, 65] False
倫理委員会 [3, 34, 41, 42, 49, 61] False
ケア委員会 [3, 23, 43, 48, 50, 53] False
教育企画委員会 [5, 6, 19, 30, 35, 45] False
記録委員会 [4, 26, 27, 38, 47, 60] False
Aチームリーダ会議 [6, 8, 9, 10] [12, 13, 14, 15, 16, 17, 18] 2
Bチームリーダ会議 [7, 11, 12, 13] [12, 13, 14, 15, 16, 17, 18] 2
今月休日8人以上 8 [5, 11, 12, 13, 18, 19, 25, 26, 32, 33] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
今月平日副看護師長会議日以外9人以上 9 [6, 7, 8, 9, 10, 14, 15, 16, 17, 20, 21, 22, 23, 27, 28, 29, 30, 31, 34, 35] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
今月副看護師長会議日9人以上 9 [24] [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
	Algorithm 1 Solving Process Started..
			o 2887   16.728000(sec) 
			o 2738   16.861000(sec) 
			o 2677   17.144000(sec) 
			o 2593   17.609000(sec) 
			o 2534   17.730000(sec) 
			o 2509   17.818000(sec) 
			o 2440   17.914000(sec) 
			o 2418   18.003000(sec) 
			o 2363   18.090000(sec) 
			o 2318   18.174000(sec) 
			o 2282   18.281000(sec) 
			o 2265   18.373000(sec) 
			o 2219   18.473000(sec) 
			o 2150   18.576000(sec) 
			o 2022   18.726000(sec) 
			o 2003   18.808000(sec) 
			o 1948   18.896000(sec) 
			o 1890   18.983000(sec) 
			o 1883   19.061000(sec) 
			o 1843   19.139000(sec) 
			o 1789   19.299000(sec) 
			o 1733   19.433000(sec) 
			o 1670   19.525000(sec) 
			o 1642   19.630000(sec) 
			o 1587   19.798000(sec) 
			o 1573   19.878000(sec) 
			o 1497   20.035000(sec) 
			o 1432   20.116000(sec) 
			o 1340   20.400000(sec) 
			o 1332   20.482000(sec) 
			o 1315   20.592000(sec) 
			o 1278   20.767000(sec) 
			o 1194   20.913000(sec) 
			o 1172   20.993000(sec) 
			o 1112   21.085000(sec) 
			o 1104   21.164000(sec) 
			o 1094   21.243000(sec) 
			o 1073   21.326000(sec) 
			o 1024   21.616000(sec) 
			o 1006   21.699000(sec) 
			o 999   21.780000(sec) 
			o 972   21.869000(sec) 
			o 939   21.958000(sec) 
			o 927   22.037000(sec) 
			o 911   22.118000(sec) 
			o 897   22.208000(sec) 
			o 864   22.312000(sec) 
			o 857   22.393000(sec) 
			o 832   22.479000(sec) 
			o 825   22.575000(sec) 
			o 807   22.656000(sec) 
			o 784   22.761000(sec) 
			o 770   22.868000(sec) 
			o 764   22.948000(sec) 
			o 749   23.195000(sec) 
			o 708   23.274000(sec) 
			o 692   23.360000(sec) 
			o 684   23.445000(sec) 
			o 669   23.537000(sec) 
			o 646   23.637000(sec) 
			o 632   23.819000(sec) 
			o 611   23.956000(sec) 
			o 586   24.037000(sec) 
			o 571   24.119000(sec) 
			o 548   24.383000(sec) 
			o 521   24.496000(sec) 
			o 504   24.592000(sec) 
			o 497   24.870000(sec) 
			o 490   24.955000(sec) 
			o 468   25.050000(sec) 
			o 442   25.287000(sec) 
			o 438   25.372000(sec) 
			o 416   25.457000(sec) 
			o 407   25.539000(sec) 
			o 392   25.808000(sec) 
			o 376   25.903000(sec) 
			o 368   25.984000(sec) 
			o 353   26.120000(sec) 
			o 350   40.217000(sec) 
			o 338   40.329000(sec) 
			o 333   40.490000(sec) 
			o 329   40.598000(sec) 
			o 323   40.742000(sec) 
			o 308   40.834000(sec) 
			o 295   41.180000(sec) 
			o 291   41.284000(sec) 
			o 287   41.526000(sec) 
			o 280   41.625000(sec) 
			o 272   41.704000(sec) 
			o 267   55.882000(sec) 
			o 262   56.089000(sec) 
			o 257   56.176000(sec) 
			o 252   56.261000(sec) 
			o 247   56.582000(sec) 
			o 239   56.681000(sec) 
			o 231   56.787000(sec) 
			o 226   56.873000(sec) 
			o 221   56.964000(sec) 
			o 213   81.083000(sec) 
			o 212   105.596000(sec) 
			o 210   105.677000(sec) 
			o 206   105.769000(sec) 
			o 202   105.848000(sec) 
			o 198   106.304000(sec) 
			o 196   106.438000(sec) 
			o 194   106.518000(sec) 
			o 191   106.757000(sec) 
			o 190   106.837000(sec) 
			o 188   106.933000(sec) 
			o 186   107.012000(sec) 
			o 184   107.386000(sec) 
			o 183   107.742000(sec) 
			o 181   108.191000(sec) 
			o 178   108.484000(sec) 
			o 176   108.569000(sec) 
			o 174   109.120000(sec) 
			o 170   109.210000(sec) 
			o 168   109.290000(sec) 
			o 166   109.373000(sec) 
			o 164   109.656000(sec) 
			o 162   109.930000(sec) 
			o 160   110.008000(sec) 
			o 158   110.088000(sec) 
			o 156   110.167000(sec) 
			o 154   110.430000(sec) 
			o 149   110.526000(sec) 
			o 147   110.606000(sec) 
			o 145   110.687000(sec) 
			o 143   110.925000(sec) 
			o 141   111.321000(sec) 
			o 135   111.558000(sec) 
			o 134   111.643000(sec) 
			o 132   111.784000(sec) 
			o 130   111.864000(sec) 
			o 128   111.943000(sec) 
			o 126   112.346000(sec) 
			o 125   112.451000(sec) 
			o 123   112.530000(sec) 
			o 121   112.622000(sec) 
			o 120   137.179000(sec) 
			o 118   137.262000(sec) 
			o 115   137.376000(sec) 
			o 113   137.460000(sec) 
			o 112   137.970000(sec) 
			o 109   138.207000(sec) 
			o 108   138.288000(sec) 
			o 107   138.368000(sec) 
			o 106   138.965000(sec) 
			o 105   139.044000(sec) 
			o 104   139.125000(sec) 
			o 103   139.205000(sec) 
			o 101   139.556000(sec) 
			o 98   139.636000(sec) 
			o 97   140.223000(sec) 
			o 92   140.411000(sec) 
			o 91   140.494000(sec) 
			o 89   140.575000(sec) 
			o 88   140.654000(sec) 
			o 86   140.734000(sec) 
			o 85   140.819000(sec) 
			o 84   140.901000(sec) 
			o 82   141.306000(sec) 
			o 81   141.384000(sec) 
			o 80   141.465000(sec) 
			o 78   141.546000(sec) 
			o 77   141.707000(sec) 
			o 76   141.787000(sec) 
			o 74   141.900000(sec) 
			o 72   141.980000(sec) 
			o 70   142.111000(sec) 
			o 68   142.191000(sec) 
			o 67   142.270000(sec) 
			o 66   142.357000(sec) 
			o 65   142.514000(sec) 
			o 64   142.846000(sec) 
			o 62   142.926000(sec) 
			o 59   143.006000(sec) 
			o 58   143.085000(sec) 
			o 55   143.165000(sec) 
			o 54   143.245000(sec) 
			o 52   143.324000(sec) 
			o 50   143.405000(sec) 
			o 49   143.484000(sec) 
			o 48   143.896000(sec) 
			o 46   143.976000(sec) 
			o 43   144.054000(sec) 
			o 41   144.261000(sec) 
			o 40   144.341000(sec) 
			o 39   144.449000(sec) 
			o 37   144.586000(sec) 
			o 36   144.667000(sec) 
			o 35   144.748000(sec) 
			o 34   144.857000(sec) 
			o 33   147.963000(sec) 
			o 32   148.264000(sec) 
			o 31   148.850000(sec) 
			o 30   149.683000(sec) 
			o 29   152.470000(sec) 
			o 28   152.940000(sec) 
			o 27   155.131000(sec) 
			o 26   157.387000(sec) 
			o 25   157.683000(sec) 
			o 23   160.193000(sec) 
			o 22   160.365000(sec) 
			o 21   160.537000(sec) 
			o 20   160.705000(sec) 
			o 19   161.021000(sec) 
			o 18   163.325000(sec) 
			o 17   164.045000(sec) 
			o 16   170.757000(sec) 
			o 15   171.258000(sec) 
			o 14   173.438000(sec) 
			o 12   173.907000(sec) 
			o 10   175.485000(sec) 
			o 9   188.802000(sec) 
			o 8   191.120000(sec) 
			o 7   215.816000(sec) 
			o 6   220.261000(sec) 
			o 5   223.345000(sec) 
	Python プロパティファイルの生成が終わりました。
 _____________________________________
|           |           |             |
|   Weight  |   Errors  |    Cost     |
|___________|___________|_____________|
|           |           |             |
|         7 |         0 |           0 |
|         6 |         0 |           0 |
|         5 |         0 |           0 |
|         3 |         0 |           0 |
|         2 |         2 |           4 |
|         1 |         1 |           1 |
|___________|___________|_____________|
|                       |             |
|         Total         |           5 |
|_______________________|_____________|
	*********UB=5(0)  267.77(cpu sec)
o 5(0)
解探索が終了しました。 270 (秒)
解が得られました。
ポスト処理を実行します。ソルバを呼び出し中です。
グローバル変数一覧:
successful  現任教育委員会
現任教育委員会 委員会日は、 2023-10-11 参加者全員は 7 人です
現任教育委員会 委員会日は、 2023-10-12 参加者全員は 7 人です

successful  新任教育委員会
新任教育委員会 委員会日は、 2023-10-02 参加者全員は 6 人です
新任教育委員会 委員会日は、 2023-10-03 参加者全員は 6 人です
新任教育委員会 委員会日は、 2023-10-04 参加者全員は 6 人です
新任教育委員会 委員会日は、 2023-10-05 参加者全員は 6 人です
新任教育委員会 委員会日は、 2023-10-06 参加者全員は 6 人です
新任教育委員会 委員会日は、 2023-10-10 参加者全員は 6 人です
新任教育委員会 委員会日は、 2023-10-11 参加者全員は 6 人です
新任教育委員会 委員会日は、 2023-10-12 参加者全員は 6 人です

successful  リスク委員会
リスク委員会 委員会日は、 2023-10-30 参加者全員は 5 人です
リスク委員会 委員会日は、 2023-10-31 参加者全員は 5 人です

successful  感染委員会
感染委員会 委員会日は、 2023-10-02 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-03 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-04 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-05 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-06 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-10 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-11 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-12 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-13 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-16 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-17 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-18 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-19 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-20 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-23 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-24 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-25 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-26 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-27 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-30 参加者全員は 6 人です
感染委員会 委員会日は、 2023-10-31 参加者全員は 6 人です

successful  業務委員会
業務委員会 委員会日は、 2023-10-20 参加者全員は 6 人です
業務委員会 委員会日は、 2023-10-23 参加者全員は 6 人です
業務委員会 委員会日は、 2023-10-24 参加者全員は 6 人です
業務委員会 委員会日は、 2023-10-25 参加者全員は 6 人です
業務委員会 委員会日は、 2023-10-26 参加者全員は 6 人です
業務委員会 委員会日は、 2023-10-27 参加者全員は 6 人です
業務委員会 委員会日は、 2023-10-30 参加者全員は 6 人です
業務委員会 委員会日は、 2023-10-31 参加者全員は 6 人です

successful  倫理委員会
倫理委員会 委員会日は、 2023-10-31 参加者全員は 6 人です

successful  ケア委員会
ケア委員会 委員会日は、 2023-10-23 参加者全員は 6 人です
ケア委員会 委員会日は、 2023-10-24 参加者全員は 6 人です
ケア委員会 委員会日は、 2023-10-25 参加者全員は 6 人です
ケア委員会 委員会日は、 2023-10-26 参加者全員は 6 人です
ケア委員会 委員会日は、 2023-10-27 参加者全員は 6 人です
ケア委員会 委員会日は、 2023-10-30 参加者全員は 6 人です
ケア委員会 委員会日は、 2023-10-31 参加者全員は 6 人です

successful  教育企画委員会
教育企画委員会 委員会日は、 2023-10-26 参加者全員は 6 人です
教育企画委員会 委員会日は、 2023-10-27 参加者全員は 6 人です
教育企画委員会 委員会日は、 2023-10-30 参加者全員は 6 人です
教育企画委員会 委員会日は、 2023-10-31 参加者全員は 6 人です

successful  記録委員会
記録委員会 委員会日は、 2023-10-05 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-06 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-10 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-11 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-12 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-13 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-16 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-17 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-18 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-19 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-20 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-23 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-24 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-25 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-26 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-27 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-30 参加者全員は 6 人です
記録委員会 委員会日は、 2023-10-31 参加者全員は 6 人です

Aチームリーダ会議 [6, 8, 9, 10] [12, 13, 14, 15, 16, 17, 18] 2
Aチームリーダ会議は確保できました。必要人数 2 人に対して 2 人確保しました。 2023-10-12
Bチームリーダ会議 [7, 11, 12, 13] [12, 13, 14, 15, 16, 17, 18] 2
Bチームリーダ会議は確保できました。必要人数 2 人に対して 2 人確保しました。 2023-10-10
ポスト処理を終了しました。 1 (秒)

2023年11月18日土曜日

委員会の設計

現任教育委員会(現任者(2年目以降)の人が教育・研修計画を立案・計画・実施する)や新任教育委員会等、 委員会を動的に割り当てるには、シフトを分ける必要があり、これが多数あると面倒です。

シフトの種類としては、日勤なので、委員会用のシフトも日勤集合とする必要があります。

これが面倒な場合には、Pythonで記述します。



委員会と名のつく変数で、なおかつリストオブジェクトである変数が候補となります。それらのANDを取って、少なくとも一つ以上であることが必要となります。
委員会日は、日勤です。このようにすると、委員会の数や参加者が変化してもスタッフプロパティシート群のみを編集すればよいので、メンテナンス上好ましいです。

ただし、解を見ただけは、開催日がいつかは分かりにくくなるので、ポスト処理で、解をチェックし該当日を報告する設計としています。


2023年11月17日金曜日

”半人前”の設計


さて、「新人は、人数にカウントしない」、はよくある実装です。これは、新人グループという集合を作成して、それ以外の集合のみをカウントすれば事足ります。

次に、「あの人は、半人前だ」についての実装を考えてみます。「半人前集合」を定義して、0.5カウントすればよいのですが、制約系は、全て整数が基本なので、二人で一カウントすればよいことになります。問題は、二人で一カウントすることが現機能では出来ないことです。

簡単そうに見えますが、最高難易度の問題です。ソルバーは、AL1、AL2,AL4とテクノロジーバックグランドの異なる系を備えているので、各々のバックグランドに適した実装とする必要があります。

https://schedule-nurse.blogspot.com/2023/11/blog-post_21.html



2023年11月16日木曜日

ダイアログを前面に出すハンドル

 ダイアログが隠れていると気付かずに、ハングしたのでは?と不安になってしまいます。






そんなときに前に出してくれるのがハンドルHWNDです。MessageBoxの第一パラメータとなっています。

HWNDは、GUIのハンドルです。

ソース全体を見ると定義されています。

メッセージダイアログを出しているのは、pythonを解釈実行中のソルバーでありGUIとは別プロセスですが、このおかげで、少なくともGUIよりは前面にダイアログが出力されます。

Pythonの中身を看護師長がEditするのは難しいと思うので、こういうインタラクティブなIFで、パラメータを変更できるようにすると良いと思います。



2023年11月15日水曜日

予定縮小時の不具合いについて

  11月6日の週は、妻のお供で、東京に滞在している時間が多く、ほぼメールのみの対応とさせて頂きました。全ての関連行事は滞りなく終了しました。今週よりまた復帰します。


Q.12月の勤務表作成時から、予定入力しているシフトの文字サイズのみが

少し大きく表示される様になり、枠内におさまらない表示になりました。

設定等、対処方法がありましたら、教えてください。

現状では、枠サイズを大きめにしていますので、大きな支障はありません。

A.

「シフト数が百数十個あり画面からはみ出し表示されなくなる」というお客さま用に、修正したのが仇になってしまいました。

下記ツールストリップサイズで、調整することができます。


ただし、これだと拡大時にも同じサイズになってしまいます。この点について、次回11月ENDのリリースで改善するので、お待ちになっていただければ何もする必要はありません。


2023年11月8日水曜日

シフト勤務表で日勤者数を日毎に変えるには?

 

制約による 曜日や特別な日の設定ではなく、日毎に勤務者数を指定したい、という場合は、タスク予定の基数制約テーブルで指定します。しかし、自分の勤務表スタイルは、シフト勤務表だ、という方もいらっしゃるかと思います。そんな方のための処方箋です。




2023年11月7日火曜日

連続日勤3日まで

 グループ属性で、アイテムを記述します

スタッフプロパティシートで、設定します。
制約します。






連続日勤5日までの記述は、既に、連続勤務6日禁止であるので不要です。


2023年11月6日月曜日

NOV052023BUILD内容

■ soft error 解析改善

■ キーボード入力サポート

https://schedule-nurse.blogspot.com/2023/11/blog-post.html

■ Day集合Error解析改善

■ NoTaskVarのみ Export 改善

■ TaskSchedule基数 数値入力チェック 追加

2023年11月5日日曜日

一般化変則2交代記述スタイル変更

 応援先として救急外来があったとき、タスクを使って表しています。

このとき、

NoTaskVar:自職場

救急外来:応援先

を表現しています。

日勤者の列制約の変更前と変更後です。青部が該当箇所です。

上の記述では、
応援先もしくは、自職場の制約人数が変化したとき、どちらも影響がでてしまいます。
下の記述は、変化があったところだけをメンテすればよいことになります。煩雑な
曜日集合演算も必要ありません。

さらに、曜日により複雑に日勤者数が変化する場合には、


とすることもできます。これだと、ベクトル表現で一行で記述できますが、

毎月メンテする必要があるのが難点です。


制約の方法は、一つではなく

1)制約記述による方法

2)特別な日のカレンダを使う方法

3)予定基数制約を使う方法

があります。

■制約が、将来的にも、殆ど変化しなければ、1)がよいでしょうし、

■制約しない月もある場合は、2)がよいでしょう

■ランダムに日勤者数が変化する場合は、3)がよいでしょう。(毎月メンテしないと誤制約になってしまいます。)

それでは、シフト勤務表では、3)が使えないのでは? と思われるかもしれませんが、上と同様に使えます。(https://schedule-nurse.blogspot.com/2023/11/blog-post_8.html





2023年11月4日土曜日

キーボードバインディング

 以前からご要望のあったキーボードによる予定入力を実装しました。



深夜のツールバーのところマウスをホバリングさせると、深夜:3というのがツールチップされています。ツールバーは、内部で番号が割り当ててあり、その番号を出力しています。このようにして、任意のラベルの番号を調べることができます。

キーボードとのバインディング

ファンクションキーF1-F9、数値キー1-9、テンキー1-9まで、総計27個までキーボードとのバインディングを指定することができます。F1は、ファンクションキーのF1,D1は、数値キーの1、NumPad1は、テンキーの1を指します。

ウィンドゥズの設定のところで、キーボードとのマッピングを設定します。-2は初期値で

なにもしません。(初期はDisable状態です。)-1は、ブランク、1-199番までラベルを指定可能となります。この表は、レジストリに保存しています。シフトおよびタスクについて動作します。




加えて、キーボードのカーソルキーも動くようにしています。

11月6日の週にリリースするので、審査で落ちなければ、11月10日頃から配信が始まると思います。


2023年11月3日金曜日

6連勤務禁止バグ修正

 バグがありました。

正しくは、下です。制約最終日に、長日、または入りがくると、次の日は、また勤務が強制されるので、それを禁止します。最後のパターンは、それの1日前の長日で始まるパターンの禁止です。