2020年12月29日火曜日
2020年12月28日月曜日
2020年12月27日日曜日
GPOST Nurse Scheduling Benchmark
Cplex 206秒、Gurobi 30秒、スケジュールナース7秒でした。この例も、夜勤の4回連続を禁止した結果、2回から3回の連続となっています。欧米の殆どのベンチマークがほぼこのような形態となっています。
2020年12月24日木曜日
2020年12月23日水曜日
Azaiez Nurse Scheduling Benchmark
SC3で6秒、Cplex9秒、Gurobi3秒でした。
下記の勤務パターンをみてお気づきかと思いますが、欧米の勤務パターンは、日本と全く異なります。基本的に、夜勤は12時間で、それが、2-3日続くパターンが一般的になっています。
クラッシックなベンチマークは、欧米の論文に由来しています。結果、殆どが下記のパターンと似通ったものになります。INRC1のパターンもそのようなパターンとなっています。
ベンチマークとしての問題は、欧米パターンに偏っていることです。もっと難しい問題は、色々ある、という風に力説したいと思います。
2020年12月18日金曜日
LLR Nurse Scheduling Benchmark
Gurobi /Cplex共5秒程度、ScheduleNurse AL1では、19secでOptimum値(301)に達しますが、厳密解ではありません。AL4では、4secで厳密解となります。ちなみにGoogleORToolsで使われているCBCでは、Optimum値に到達するのが275秒、28000秒かけても、Optimum証明が出来ていません。一般的に、MIPソルバの世界では、商用ソルバとOpensource ソルバでは、相当な性能比となることは、よく知られており、100倍となることは、珍しくないというか普通に起こります。(それ故に商用ソルバの存在価値があるわけです。)
2020年12月14日月曜日
2020年12月13日日曜日
2020年12月12日土曜日
Musa Nurse Scheduling Benchmark
これも古いです。シフトが2、2週間で小規模、パターンがほぼありません。ほぼ全体が基数制約です。こういったベンチは、MIPソルバが圧倒します。CPLEXで0.01secでOptimum証明完了です。
スケジュールナースⅢでは、Optimum値が出現するまで10sec,証明完了まで23secかかりました。
2020年12月11日金曜日
Ozkarahan nurse scheduling benchmark
1989年ということですので、最も古いNSP問題ということになりそうです。
現在では、0secで解ける問題です。
ptpmcrender.fcgi (europepmc.org)
驚くべきは、すでにこの時代から、個人毎のスタッフ契約体系になっていることで、土日働けない人の考慮がなされています。
import sc3 for person in [2]: clist=[] for day in AllDays: vlist=[] if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if len(vlist) >= 1: clist.append(sc3.Or(vlist)) sc3.AddSoft(sc3.SeqError(0,0,3, clist),'3_1',1) for person in [3]: clist=[] for day in AllDays: vlist=[] if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if len(vlist) >= 1: clist.append(sc3.Or(vlist)) sc3.AddSoft(sc3.SeqError(0,0,3, clist),'4_1',1) for person in [6]: clist=[] for day in AllDays: vlist=[] if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if len(vlist) >= 1: clist.append(sc3.Or(vlist)) sc3.AddSoft(sc3.SeqError(0,0,3, clist),'7_1',1) for person in [7]: clist=[] for day in AllDays: vlist=[] if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if len(vlist) >= 1: clist.append(sc3.Or(vlist)) sc3.AddSoft(sc3.SeqError(0,0,3, clist),'8_1',1) for person in [8]: clist=[] for day in AllDays: vlist=[] if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if len(vlist) >= 1: clist.append(sc3.Or(vlist)) sc3.AddSoft(sc3.SeqError(0,0,3, clist),'9_1',1) for person in [12]: clist=[] for day in AllDays: vlist=[] if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if day in Sat : if day +1 in AllDays : v=sc3.And(~sc3.GetShiftVar(person ,day+0,'Y'),~sc3.GetShiftVar(person ,day+1,'Y')) vlist.append(v) if len(vlist) >= 1: clist.append(sc3.Or(vlist)) sc3.AddSoft(sc3.SeqError(0,0,3, clist),'13_1',1)
2020年12月10日木曜日
Real Nurse Scheduling Benchmarksの構想
ベンチマーキングは、SchedulingBenchmarksとNurseSchedulingCompetitionⅡが現存しており、既に、結果についてはレポート済みです。
Benchmarks|What is Schedule NurseⅢ (nurse-scheduling-software.com)
後は、過去のOR関係の論文で言及があるものを集めたセットのみが残っています。これらをスケジュールナースで解いてみたいと思います。これらのプロジェクトとMPSファイルをGithubに集めてOneStopのベンチマーク集としたいと思います。MPSファイルを添付することで、MIPソルバー同士、あるいは、MIPソルバー対メタヒューリスティクスも論じ易くなるのではないかと思います。
また、日本の実際的なベンチもいくつか提供したいと思います。たとえば、シフト数が25を超えるものや、プリセプタ・プリセプテイ、等、これまでにない、しかし現場での実際的な問題を提供したいと思っています。
これらにより、Realなベンチマーキング集としたいと思います。(Githubなので、どなたでもForkしてPull Request出来ます。)
GitHub - sugawara-system/Schedule_Nurse3_Gallery
2020年12月9日水曜日
2020年12月8日火曜日
Date Aggregate Rep2/3/4/7/14とは?
https://nurse-scheduling-software.com/knowledge_base/
に書きました。カレンダを見て頂いた方が早いです。私も使ったことはないのですが、例えば「特定の日基準の隔週」という集合を定義したいときに使うことを設計時意図していたと思います。GUIカレンダとSolver側に認識は、一致しているはずですが、確認したいときは、python で、
import sc3
だけ記述して、言語制約をオンして求めると、
とR2,R3,R4,R7,R14 Day集合を確認できます。Repは、132Dからのサポートになります。
2020年12月6日日曜日
SDK2のAWS ACOUNT ID Checkを廃止
SDK2(Scheduling Solver Engine on Lambda function in AWS Development Kit 2)では、これまで、お客様固有のアカントしか動作できませんでしたが、この条件を緩和し、どのアカウントでも動作できるようにしました。ただし、期限は変わらず残ります。期限内に量産への移行をできればお願いいたします。
2020年12月5日土曜日
新しいシフトスケジューリング論文
保育士や、パートタイムについて論じています。
http://repository.nihon-u.ac.jp/xmlui/handle/11263/1659
未だあまり読み込んでいないのですが、具体データもあるので、スケジュールナースでモデル化したらどういう感じになるか、興味深いです。
2020年12月4日金曜日
ikegami benchmarkの評価
日本語サイトは、
に移動しました。
プロモーション用に最新のデータを採取しました。
Fast|What is Schedule NurseⅢ (nurse-scheduling-software.com)
GurobiとCplexのデータは、Optimumの値証明が完了するまでの時間です。GurobiとCplexは、結構差がついてしまいましたが、Gurobiの進歩が著しいということでしょう。
誤解のないようにお願いしたいのですが、このデータは、これらインスタンスに限ってのお話です。平均的な比較ではありません。
MIPソルバーの性能向上が著しくて、メタヒューリスティクスは、肩身が狭くなりつつはありますが、上記データが示すように全てMIPで済むという話には未だならないと思います。それぞれに得意不得意の領域があり、実務的・典型的ナーススケジューリング問題には、ScheduleNurseⅢ Algorithm1がMIPソルバーより良い結果を示すということであります。
それから、StateOfArtRosteringSolverとは、AutoRosterの4.34でこれは、多分昔とったデータと変わらないと思います。
2020年12月2日水曜日
SC3 AWS LAMBDA ENGINE ブローシャ
日本語サイトは、
に移動しました。
ブローシャは、以下です。
https://www.nurse-scheduling-software.com/publications/SC3_AWS_LAMBDA_ENGINE_EN.pdf
英語Videoは、こちら。