2026年6月13日土曜日

MDD TREEの枝刈り

Scheduling Benchmarksでは、すべて、

RMPの重みは、Understaffing=100、Overstaffing=1

スタッフ側(Pricer)は、希望休み・シフトに対する違反重み種類が3種類(1,2,3)

と非常にシンプルです。


前提の整理

  • 最小化問題とします。

  • 目的関数は、重み付き個数の和:

z=100x100+1x1+1y1+2y2+3y3

のような形(RMP に 100,1、Pricer に 1,2,3 の重み)。

  • 線形緩和の最適値を LB、現在の整数実行可能解の値を UB とし、

GAP=UBLB

とする。

基本アイデア

ある重み w を持つ変数(列)を、LP 解から整数解に向かうときに「どれだけ増やせるか」は、

wΔnwGAP

を満たさないと UB を超えてしまう、という制約から来ます。 したがって、

ΔnwGAPw

が、その重みクラスについて許される“増分の最大数”になります。

各重みごとの限定

  • 重み 100 の列:

Δn100GAP100
  • 重み 3 の列:

Δn3GAP3
  • 重み 2 の列:

Δn2GAP2
  • 重み 1 の列(RMP, Pricer 両方含めて):

Δn1GAP

ここでの Δnw は「LP 解から整数化の過程で、その重みクラスについて増やせる“余分な個数”」という意味です。 他の重みクラスの変数をすでにある程度固定しているなら、その分のコストを差し引いた残りの余裕に対して同じ式を適用できます。

直感的なまとめ

  • GAP が小さいほど、重い列(重み 100 や 3)の「取りすぎ」はすぐに UB を超えるので、 それぞれ GAP/w 個までしか“余分には”許されない。

  • これを使うと、整数化フェーズで「重み 100 の列は LP 解から多くても GAP/100 本まで」「重み 3 は GAP/3 本まで」などと、探索空間をかなり素直にカットできます。

もし「RMP 側の 100 と 1」「Pricer 側の 1,2,3」を別々に扱いたい(例えば RMP の 1 と Pricer の 1 を区別したい)なら、そのクラスごとに同じ形で上限を入れていく形になります。

この方向性で、実際に使っている目的関数の形(係数と変数の対応)をもう少し具体的に書いてくれたら、 「絶対個数の上限」まで踏み込んだ式に落とし込むこともできますが、まずはこの GAP/w ルールがコアになります。

Q.GAPが1.5のときどうなりますか?

結論だけ先に言うと、GAP = 1.5 のとき、重み 2・3・100 の列は “追加ゼロ” しか許されません。 追加できるのは重み 1 の列だけで、最大 1 本まで です。

◆ なぜそうなるか(核心)

整数化で LP 解から増やせる本数 Δn は

wΔnGAP

なので

ΔnGAPw

を満たす必要があります。

GAP = 1.5 を代入すると:

◆ 重みごとの上限(GAP = 1.5)

  • 重み 100

Δn1001.5/100=0
  • 重み 3

Δn31.5/3=0
  • 重み 2

Δn21.5/2=0
  • 重み 1(RMP・Pricer 共通)

Δn11.5=1

◆ つまりどうなるか

  • 重い列(100, 3, 2)は一切増やせない → 追加した瞬間に UB を超えるため。

  • 重み 1 の列だけが最大 1 本まで許される → GAP 1.5 の範囲で収まる唯一のクラス。

0 件のコメント:

コメントを投稿