2024年1月31日水曜日

Grammerly Generative AIが凄い

 Would you please be so kind as to explain me what the purpose of the 'weight' in the Solve tab ? (nurse-scheduling-software.com)

は、GenerativeAIをほぼそのまま張り付けた文章。

こちらは、使わないでいつものアシストで修正した文章。

https://schedule-nurse.blogspot.com/2024/01/relationship-between-level-and-weight.html

違いは歴然です。CHATGPI3ベースらしいですが、内容を理解して分かりやすくしている点が素晴らしいです。

2024年1月30日火曜日

マクロの浮動小数サポート

 マクロは、整数だけを置換するものでしたが、浮動小数もサポートすることにしました。

具体的には、時間制約の値に対して作用します。


列の時間に対しては、列浮動小数にします。

行の時間に関しては、
行浮動小数を使います。

内部用アサートに関しては、浮動小数も同様に動作します。

適用は、2月第2週です。

2024年1月29日月曜日

JAN282024BUILD 内容

ソフトシフト集合仕様変更

https://schedule-nurse.blogspot.com/2024/01/blog-post_28.html

シフト集合要素のSanityチェック追加

マクロTextBox WordWrap禁止・最大容量1MB→10MB

2024年1月28日日曜日

ソフトシフト集合の仕様変更

 ソフトシフト集合の仕様をシンプルにし、オペレータに関係なく、基本的に全集合としました。唯一、スタッフ毎のシフト設定は、ハード制約なので、チェックを外すと除外されますが、それ以外は、全集合となります。



2024年1月27日土曜日

Highs Interior Solver Development

 https://mcusercontent.com/4e6b25e3b608de7e4aa9e7706/files/64698e34-bfd9-bcbb-9492-c6f7a0058c69/HiGHS_Newsletter_24_0.pdf

がアナウンスされました。現在のHighsの内点法ソルバは、マルチスレッド化されていなくて、仕方なく、自作していましたが、これで、拙作ソルバは、お箱入りになると思います。楽しみです。

またEUのOR学会での最後にエジンバラ大学で、初のワークショップが開催される模様です。PhDは、無料とのこと。オンライン聴講は、(案内はないので)多分ないと思います。

2024年1月25日木曜日

サブスクリプションのイントール方法を変更しました

 サブスクリプション購入 (nurse-scheduling-software.com)

ストアにマイクロソフトアカウントにサインインしてから、操作するように変更しました。

また、ストアへの直接リンクを無くしました。



2024年1月23日火曜日

intel uhd graphics 予定ラベルが黒くなる

 特定のGPUで、特定のRGBを持つラベルが黒くなる現象が報告されています。

NVIDIA系GPUでは、起こりません。IntelCPUが内蔵するGPUでのみ起きる模様です。具体的には、高画質のノートPCです。顧客の情報では、新しいPCでのみ発生するとのことです。私のNoteもIntel 系ですが、低解像度のためか、発生しません。これは、描画の問題であり見た目だけの問題です。内部の制約に影響はしません。

ある顧客から、指摘を頂き、当該機種系統のPCを新たに購入したところ、再現することができました。

改善後は、



原因解析:

ビットマップをライブラリ(syncfusion)に渡すところまでは、問題ありませんでした。(アプリ上では問題を発見できませんでした。)ライブラリ内部となるために、解析できませんでした。可能性としては、

以下の指摘です。

.net - WriteableBitmap.WritePixels not refreshing on some PCs - Stack Overflow

原因推定:

特定RGB範囲でのみ、観測されるので、恐らくは、intel uhd graphicsのバグだと思います。

対策:

ドライバーのupdateで回復する可能性が強いと思います。しかし、ドライバーのアップデートは、難しいでしょうから、対策することにしました。特定RGB範囲でのみ、不具合が観測されるので、特定RGB範囲は、近くの問題ない領域に避難することにしました。

リリース:

JAN242024






2024年1月22日月曜日

定例会議は、月初め、月終わりを避ける

 通常に比べ多くの日勤者を要する会議では、月初め・月終わりの数日間は避けた方がよいです。理由は、先月・次月の影響が出るからです。会議を意識して、例えば、先月から夜勤が入らないようにすれば、影響を最小にすることは出来ますが、中々そこまで気が廻らないのではないでしょうか?

2024年1月21日日曜日

Relationships between Level and Weight

Q.

Would you please be so kind as to explain me what the purpose of the

"weight" in the Solve tab ?

Is there any impact changing the integer value of it ?

I understand the "soft level" principle but the weight...


I may have missed this part somewhere in the documentation, sorry if it is

the case.

Kind regards,


Ans.


For more information on the relationship between levels and weights,
Please read the following section.



You should see ******UB=... in the right pane in the fig.

The objective function value (UB) of a linear system is,
The following equation.

UB = ΣWeigts[i]*Errors[i].

The solver's task is then to find the shift assignment that minimizes the value of UB.
Optimization in linear systems is to minimize UB.

So, the magnitude of the weights corresponds to the priority. The larger the weight, the higher the priority.

In contrast, a level is like an index that summaries the weights.
By convention, level 7 is marked as a serious error, with red and others marked yellow, but there is no relationship between that and the weights. It is also fine if level 7 is weighted 1 and level 1 is weighted 10. It is only the weights that are passed to the solver.


However, the advantage of such a system for Scheduling Nurse is that the weights of the desired constraints can be changed immediately at hand when seeking solutions. As is well known, the nurse scheduling problem is not known what the error looks like at the time until it is solved. Depending on the state of the error at the time, the priority can be changed immediately at hand.

2024年1月20日土曜日

5連勤の後2連休の解説


 

制約では、次のようになっています。

まずは、チェックマーク(✔)休集の意味です。

休集は、あらゆる休みの集合体です。チェックマークは、それに対して反対を取ることを意味します。集合で言うと補集合です。



あらゆる休みの補集合は、あらゆる勤務となります。

つまり

✔休集=勤務

となります。勤務は、日勤かもしれないし、長日、入り、明け、研修..あらゆる休み以外のシフト全ての集合です。

上のパターンを解説します。7日のパターンですが、実は、これに包含される

制約があります。6連禁禁止です。



なので、上の6日目のパターンは、通常休みになります。その後7日目での勤務が、7日のパターン全体での勤務パターンになります。つまり、5連勤務の後休み、その後勤務というパターンです。制約は、パターン禁止ですから、

「5連勤務の後休み、その後勤務」というパターンの禁止

になります。ここで、既に6連勤務は、規制されていることに注意してください。7日パターンのみでは、6連勤務禁止にならないことに注意してください。

制約パターンの検証方法

弱いソフト予定で考え付くパターンの全てを書いてみて、目論見どおり動くかを見るとよいです。制約パターンの方が強ければ、弱い予定は、全て制約パターンに規制されます。目論みの「5連勤の後2連休」に当てはまらないパターンが解にあれば、制約設計のバグ、ということになります。なお、目的外の制約をオフにすると(求解時のチェックを外す)スピーディにデバッグすることが出来ます。





2024年1月19日金曜日

4連続休み禁止

 4連続公休禁止は、前にやりました。


今度は、一般的な休みの禁止です。シフト集合を使います。

「休集」は、休みの総称です。週休もあれば、年休、有給、非番、半休もあります。全ての休みの集合体です。



2024年1月18日木曜日

Python記述されていない変数に対する参照対策

 下記で、CCは、クリニカルコーチのリストですが、CCが存在しない場合は、エラーとなって、止まってしまいます。


import sc3

for person in a_1年目:
    list=[]
    for day in 今月:
        v=sc3.GetShiftVar(person,day,'ロング日勤')
        vc=sc3.GetShiftVar(CC[0],day,'ロング日勤')
        list.append(v&vc)
        
    s='1年目CCと長日_'+staffdef[person]
    sc3.AddSoft(sc3.SeqError(1,1,3,list),s,4)

プログラムは、CCの存在を暗黙のうちに仮定していましたが、堅牢なプログラムならば、それをものともせず動き続けるはずです。次のように修正しました。CCが存在しない場合は、警告を出力します。

import sc3

for person in a_1年目:
    list=[]
    for day in 今月:
        v=sc3.GetShiftVar(person,day,'ロング日勤')
        try :
            vc=sc3.GetShiftVar(CC[0],day,'ロング日勤')
            list.append(v&vc)
        except:
            print("警告 CCがいません")
    s='1年目CCと長日_'+staffdef[person]
    if len(list)>=1:
        sc3.AddSoft(sc3.SeqError(1,1,3,list),s,4)

    

2024年1月17日水曜日

看護師長がいない休日に、副看護師長の誰かはいて欲しい

休日に、副看護師長が、日勤または長日>夜勤の順の優先度で、少なくとも一人は居て欲しい

 これが実現できるところは、限られているかもしれませんが、

一応書いてみました

休日勤務は、休日にありえる勤務の全てです。こちらの制約の優先度は高くして、最悪、夜勤でもよいから居てほしいという、意味にします。
日ロングは、日勤または長日勤です。こちらの優先度は低くします。

こうすることによって、上手くいけば、日勤または長日が割り当てられ、最悪でも、夜勤が割り当てられます。

2024年1月16日火曜日

JAN142024の内容

 ソルバ―、フェーズモード、不等式制約で、Day集合が空集合だとクラッシュする問題のFix


2024年1月14日日曜日

リニアペアフェーズの拡張

 リニアペアフェーズ制約において、シフトA/シフトBをオプションとして追加しました。

オプションなので、なくても動作します。さらにAについては、タスクAもしくは、シフトAのどちらかが、Bについても、タスクBかシフトBのどちらかがあれば、よくなりました。

例えば、下のAタスクは、記載されていませんが、Aシフトは記述されています。Bについては、BタスクとBシフトの両方が記載されています。


記載されているということは、条件であり、ANDで結ばれることになります。これに対し、記載されてないことはDon't Careということであり、何であってもよい、ということになります。

この問題は、かなり高度な部類です。これ以上複雑なDay条件のときは、タスク予定上の予定テーブルによる記述の方がよいでしょう。

上の記述について解説します。上二つは、会議時に日勤者数最小を規制する制約です。副看護師長会議時の日勤者数を増やす記述です。具体的には、最小値を底上げする記述になります。

<最小値に条件を追加する>

A*Coff<=B*1+0

今、Aは、副看護師長会議時1、その他は、0とします。その他のときは、0ですから、0<=B 常に成立します。会議時は、

    Coff<=B 

となり、会議時は、Bシフト=日勤は、Coff人以上居ることを要求する記述になります。言い換えると、会議時以外は、何もせず、会議時は、日勤者数を規制する制約となります。この要領で、同じDay集合上に、いくつもの制約をオーバライドすることができます。これがMinに対する整数計画的記法となります。

最大値に条件を追加する>

問題は、最大値です。

CoffA*A Operator ΣCoffB[i]*B[i]+offset

において、アクティブ0で条件が働くようにします。

通常時、Aは、1としてCoffA+Offset>=ΣCoffB[i]*B[i]

アクティブ時は、0としてOffset>=ΣCoffB[i]*B[i]

と作用させます。つまりOffsetは、Active時の最大値とすればよい訳です。ここで、

offset=-Offset

CoffAは、整数プログラミングの世界では、bigMという呼称が一般的です。

CoffA+Offsetがあり得る最大値以上すればにすれよく、CoffA=bigMがそのための定数です。数理ソルバー的には、一定以上であれば、問題ないのですが、2値ソルバー上では、大きすぎると問題ですので、必要以上に大きくしないようにします。

よって、次のようなマクロ記述になります。


BigMの計算方法


2024年1月13日土曜日

画像付き使用法説明用htmlの作成

 マークダウン言語(md)からhtmlを生成しています。病棟のPCは、ネットワークから遮断された状態が多いので、画像にしても外部参照ではなく、ローカルに持つのがよいでしょう。その際、複数のファイルをコピーするのが面倒という場合もあるのでhtml自身に画像を持たせています。こうすると、プロジェクトファイルがあれば、他は何もいりません。(プロジェクトファイルのコピーだけで済みます)

具体方法です。mdからhtmlを生成するのは、Typoraを使用していますが、何でもよいと思います。


画像のファイルは、Base64で変換したものを下記mdソース上の"..."

にコピペすればよいです。

<img src="data:image/png;base64,xxxxx”>

コンバータは、"md base64"で検索すると沢山でてきます。 

下記は、Typora上の表示例です。


画像記述部のソースを表示しています。

スケジュールナース上の表示です。黒塗り部をブランクにしておくと、
プロジェクトをロードしたフォルダ上にプロジェクト名.htmlが生成され、
そのパスが黒塗り部に入ります。以降そのパスでの表示となります。

手順
    1)黒塗り部をブランクにする
    2)設定ボタンを押す
    3)プロジェクトを保存する
    4)プロジェクトを再ロードする





マクロがどこで参照されているか?を調べる

 チェックを外して、設定をしてみると分かります。


<マクロのExport>




<マクロのImport>

<Pythonへの出力>



2024年1月12日金曜日

マクロ式の関数

 スケジュールナースで独自に実装している関数は、C(Day集合アドレス)、=C(グループ集合アドレス)だけです。それ以外の関数は、以下を参照してください。

Formula Support in Windows Forms Grid Control | Syncfusion

Cは、Countを指し、当該集合の要素をカウントします。

「今月土日」の数を数えて、それを公休数としています。


「夜勤可能者」の数を数えています。

「今月」の日数を数えています。

一人あたりの夜勤回数を切り捨て、それを夜勤回数最小値としています。

最小値+1を最大値としています。

<内部用アサートの機能>
アサートは、プログラミング言語でのアサートに近い動きをします。本来の動作をチェックするための機構になります。アサート条件は、>=0です。下の場合、深夜夜勤回数の最大ー最小>=0をアサートしています。
しかし、設定者が間違って、最大・最小を逆に設定しているために、-1となりアサートエラーが生じています。この結果、設定することが出来ません。エラー時、アサートエラーのダイアログは、コメントをそのまま出す仕様です。



2024年1月11日木曜日

スプレッドシートの機能

 マクロは、単に数値の置き換えだけではなく、当該計算で必要な数を提供する機能を有しています。黄色の部分が、スプレッドシート機能を有する部分です。Excelライクな記法ですが、Excel互換ではなく独自のものです。詳細は、以下のAPIを参照ください。

Formula Support in Windows Forms Grid Control | Syncfusion

例えば、通常時平日最大日勤者数は、8です。この値は使用者が設定する値です。



しかし、制約上では、使いたい値は、マイナスした-8として記述したいという状況があります。ユーザ側では、-8にする理由が分からないし、細かい制約の事は気にしたくないので、単に8として値として設定したい訳です。そういう場合は、「式の値を適用」にチェックを入れて、「式の値」のところに式=-D4 としてやります。ユーザが8と設定したセルは、D4セルであり、そのマイナスの値をマクロの値として使う、という意味になります。

式の値を編集モードにすると、式編集になります。


他の黄色のセルは、補助式として機能します。
ユーザにとって関心は、単に値(D)の部分だけです。通常、黄色の部分は、制約設計者が記述するものですので、ユーザは関わらなくてもよいです。









2024年1月10日水曜日

マクロの進化

 マクロ機能を充実させます。設計意図は、

1)なるべく制約を見ないで設定できるようにする(メンテナンスの容易化)

2)意図しない、誤制約を防止する

3)設定の説明画面により、使い方の理解の容易化

です。外観は、以下のようになります。


説明画面

マークダウンで書いたものをTyporaでhtmlにしたものを左上のTextBoxに貼り付けています。再ロードすると当該プロジェクトフォルダーにプロジェクト名.htmlがファイル生成されます。それをC#webbrowserで右上に表示させています。WebView2も試したのですが、DLLがデバッグモードで作成されているために、審査キットで不合格となり断念しました。

ともあれ、プロジェクト作成者が、使用者に使用法を説明をするのは、ここを使えばよいと思います。

なお、説明用htmlファイルが既に作成済みの場合にはそれを「htmlファイル」で、ファイル指定します。Textボックスの中身は、全部クリアして設定ボタンを押すと、指定htmlファイルを指すようになります。




2024年1月9日火曜日

シフト・タスク Excel Import改善

 プロジェクトの全日数と同じである必要がありましたが、この制限がなくなり、制約表示開始日から、制約開始日の間のスタートであれば問題なく読めるようになります。1月15日の週のリリースになります。

次の予定で、プロジェクトの表示開始日は、26日です。Excelデータは、25日からありますが、25日のデータは無視されて26日より取り込まれます。





2024年1月7日日曜日

マウスMiddleボタンで表示確認

 機能改良し、以下のツールチップが出来るようにします。適用は、1月12日頃です。

1)シフト集合



2)マクロ


3)タスク集合



2024年1月6日土曜日

人員不足は、何人でしょうか?に対する回答

 ある病棟での質問です。これについては、特定の月の特定の予定については、求解すれば、分かります。が、それ以外の、一般月の一般のシフト希望予定に対しては、答えをだせません、というのが回答になります。例えば、休み希望何個まで、という条件があれば、未だ検討の余地がありますが、無制限のシフト希望に対しては、無制限の組み合わせがあるので、これをハード予定とした場合、答えを出すことは出来ません。

一方、ブランク予定については、正確に必要人員を割り出すことは出来ます。ブランク予定とは、予定が全く入力されていない状態を指します。

全てのスタッフが一律に同じ夜勤回数でないのですが、要は、個々のスタッフが最大夜勤回数をこなしたときに供給できるコマ数は決まっています。具体的には、スタッフプロパティシートの最大夜勤回数をExcelで総計し、供給コマ数を求めます。(全てのスタッフが同じ最大夜勤数ではないし、夜勤しない人もいる)





一方必要な夜勤コマ数は、10人/Dayとすると、最大必要なコマ数は、10x31=310コマとなります。必要なコマ数310コマに対して上記コマ数が下回れば、絶対的な人数が不足していることになります。

310コマが物理限界なので、人員を削っていって、この値にどこまで肉薄できるか?がソルバの実力ということになります。実際は、綺麗に310コマに配置できる訳ではないことに注意してください。ブランク解の場合、ほぼ数コマ分以下となるのがスケジュールナースの実力です。通常、4~6コマ/人なので、言い換えれば、物理限界+1人分の人員と、無制限のソフト予定化が許されれば、必ず配置できることになります。なぜならば、無制限のソフト予定化が許されれば、究極的にはブランク予定とすることできるからです。

ここまでのまとめ

(1)物理必要コマ数に対し供給コマ数が下回れば、物理的に配置不能

(2)一般シフト予定にたいして、必要人員は見積もることができない

(3)ブランク予定については、見積もりが可能

実際は、無制限のソフト予定化ができないので、何がしかのプラスα人員が必要ということになります。それは、その職場の希望休み状況と不足事態に対するマージンの取り方によるので、実績を積み重ねて推定するのが現実的、ということではないでしょうか? 

一般的には、物理コマ数に対して、5~7%程度を見るのがよくある人員設定です。3%以下だと、かなり無理がある状態、つまり人力で行うと、最大設定夜勤数に対してそれを超えるスタッフが散見される状態であると思います。