オリジナル問題で、LBが上がらない原因の一つは、カバー制約(スケジュールナース用語では、列制約)で、緩和解が満足してしまうことです。通常、簡単な資源であれば、LPソルバは、資源が足りない、人が居ない、(←スラックが0でない)を理解してくれますが、制約が複雑だと、理解するところまで行ってくれません。(←スラックが0になってしまう。人が足りていないはずなのに、足りているという結論になってしまう)
次の制約は、インスタンス記述のAutoRosterのrosファイルの記述になります。
ここで、青部に、パターン記述があります。この記述は、スケジュールナース上では、Python制約に自動変換され、
となります。(rosファイル読み込み時)これらの形式は、SchedulingBenchmarks instance1-instance24で、同じです。制約の意味は、
土日に一回でも勤務したなら、1カウントとして、総計MAX以内に収める(ハード制約)
というものです。
ここでパターンを見て頂きたいのですが、3つのパターン
~YY
Y~Y
~Y~Y
のORを取って、総計制約(SEQLE)しています。Yは、やすみ(休み)のYシフトです。~Yは、休みの否定で、勤務を表します。
つまり、
土日 |
------------------------------
~YY :土勤務 日曜休み
Y~Y :土休み 日曜勤務
~Y~Y:土日共勤務
のいずれかだったらを1カウントとして総計カウントして制約、が上になります。この演算では、3AND項と1OR 項が演算として使われています。Y~Yの2種類が2つあるので、全部で4パターンが存在します。4パターンのうち、3パターンを使いました。
しかし、それだったら、
土 | 日
~Y | ~Y :土曜日勤務もしくは、日曜日勤務
をカウントした方が、OR項が1項だけで済みます。これは、残りの1パターンYYを否定したもの(=既述3パターン)です。~(YY) → ~Y |~Y (ドモルガンの法則)
これをPython制約にしたのが、次です。
プログラムでそのようにしたのではなく、エディタで置き換えたました。(プログラム化するのは難しい)
このように問題のモデル化(モデリング)を分かり易くすると、LPソルバも余計な演算をしなくてよいので、LBが上がる(スラックが0でなくなる)可能性があります。
上の制約は、各スタッフ毎に決まるMAX値になります。各Dayでは、各スタッフの各Shiftを累計して、[Max,Min]に制約しますが、上のような書き方をすることで、LPソルバに資源の制限をより分かり易く伝えることが出来ます。資源の供給側である各スタッフは、Max回までしか土日勤務はできないんだよ。とLPソルバに分かり易く伝えることができます。
一方カバー制約側では、各スタッフ累計[Max,Min]要るんだよ、と言う要求を満たすように各スタッフに勤務を割り当てます。ここで、LPソルバは、緩和という技を持っているので、Fractinalな値(0.5とか)を使って、表面上取り繕う([Max,Min]を満たす)動きをしてきます。
このような人的資源に関わる制約に絡んできます。今回の場合、追加ではありませんが、明示的な資源制約追加を一般に、キャパシティカットと呼んでいます。
出来る限りFractionalな値を持ち出されないようにする、というのがその真意です。
モデル作成時(問題作成時)にそこまでやってくれれば、苦労が減るのですが、一般の実務問題でも、上のような簡単化(ユーザヒアリング→モデル化)をすると、問題が簡単になるのは、良く遭遇します。
0 件のコメント:
コメントを投稿