Ans.
誰もその人とはペアになりたくない、という方はいらっしゃるかもしれません。大体どの病棟・施設でも、そういう方はいらっしゃいます。しかし、だからと言って誰ともペアを組ませないと、夜勤の人数は、常にその方、一人となってしまい、列制約を満足できなくなってしまいます。題意は、恐らく、そのようなスタッフと組む回数を平等にする、ということなので、その人とのペア回数を平準化することです。
例えば、その方とのペア回数を全員1回以下とする、可能ならば。ということではないかと思います。
残念ながら、この制約は、Pythonでしか記述できません。この職場の場合、男同士の夜勤は禁止、なおかつ看護師と介護各々1名ということなので、その方が介護・男である場合、あり得る組み合わせ対象は、女性・看護師に限定されることに注意します。そうなると、意外に組み合わせ範囲は、限定され、例えば、夜勤を6回、女性看護師が4人しかいない場合、
6回=1回2人 2回2人
6回=2回 3人
6回= 3回 2人
6回=3回1人 1回1人 2回1人
つまり、ペア1回の人が2人、ペア2回の人が2人という解しか、全員が負担する、という解は存在しないことになります。他の全てのでケースにおいて、負担0の方が存在し不平等がありえます。「私2回だ、不平等だ」は、4人のうちの50%、2人に発生するのは必然となることは理解しておいた方が良いと思います。別な見方をするなら、3回ペア夜勤を禁止することで、2回以下となる解が得られるようになる、ということです。また、ペア1回以下をハード制約とすると解は存在しない、ということになります。
この辺が組み合わせ最適化の難しいところです。単純なリニア制約では表現できないところが、人間的であるところだと思います。
次の求解パラーメータ、許容エラー1に注目してください。
一番下で、オーバライドにチェックが入っています。
これは、次のPythonソースで、最大ペア回数を1回に制限している部分に作用します。
Pythonソース上は、許容エラー数が3(sc3.SeqError(min,max,許容エラー数)になっていますが、上記のようにオーバライドのチェックされているので、1が適用されて、実際は、
0±1≦ペア回数≦1 ±1
のように許容エラー部±1として作用します。たとえば、
6回=3回1人 1回1人 2回1人
のように一人の人にエラーが集中しても、目的関数値が小さければそちらが最適値になります。しかし、題意は、一人の人に負担を集中させないことにあるので、±1で2回まではOKだが、3回は絶対ダメよ、とハード制約にしている訳です。この辺の設定をPythonソースを弄ることがなく出来るようなオプションがオーバライド設定になります。
ちなみに、許容0とすれば、ハード制約となり、解が存在しない、もしくは、強制的に夜勤4回以下となるでしょう。→やってみました。解がありません。つまり、全員を1回以下にする解は物理的に存在しません、ということです。
Pythonソースは、以下です。上で説明した内容そのものですので、理解し易いと思います。下から見ていくと良いと思います。今回は、かなり高度な設定の仕方でした。
import sc3
def ペア回数制限Sub(person1,person2):
list=[]
for day in 今月:
v1=sc3.GetShiftVar(person1,day,'入り')
v2=sc3.GetShiftVar(person2,day,'入り')
list.append(v1&v2)
s=staffdef[person1]+"と"+staffdef[person2]+"の組み合わせ回数"
print(s)
sc3.AddSoft(sc3.SeqError(0,1,3,list),s,5)#min max allowable errors 最大1回に制限
def ペア回数制限(person1):
if person1 in 男:
if person1 in 看護師 or person in 准看護師:
#ペア対象 女性 かつ 看護師または准看護師 ではない
for person2 in 入り:
if person2 in 女 and person2 not in 看護師 and person2 not in 准看護師:
ペア回数制限Sub(person1,person2)
else:
#ペア対象 女性 かつ 看護師または准看護師
for person2 in 入り:
if person2 in 女 and (person2 in 看護師 or person2 in 准看護師):
ペア回数制限Sub(person1,person2)
else:
if person1 in 看護師 or person in 准看護師:
#ペア対象 看護師または准看護師 ではない
for person2 in 入り:
if person2 not in 看護師 and person2 not in 准看護師:
ペア回数制限Sub(person1,person2)
else:
#ペア対象 看護師または准看護師
for person2 in 入り:
if person2 in 看護師 or person2 in 准看護師:
ペア回数制限Sub(person1,person2)
for person in 特別ペア回数制限:
ペア回数制限(person)