実は、訓練期間が、下のようにブランクだと、右ペインに示されるようにエラーになってしまいます。
原因は、行制約で訓練期間では、2回夜勤を行うという制約をハード制約として記述したからです。
単純にソフト制約とすれば回避できますが、ソフトエラーとしてカウントされるのが面白くない、という方もおられでしょう。それが今日のテーマです。
訓練期間が定義されていないときは、制約そのものをDisableしてしまえばよい、という発想が浮かびます。下の最後の方、 夜勤新人Disable()が制約をDisableする記述です。僅か3行で済みます。
スタッフプロパティで夜勤新人を設定、上で期間設定を行う、ということをマニュアルに書いておけば、来年もまた使えます。
import sc3
def 夜勤回数設定sub(person):
st=staffdef[person]+'夜勤回数を制約'
sc3.print(st+'します。\n')
max=-1
min=0
if person in 夜勤回数最大属性:
max=夜勤回数最大属性[person]
if person in 夜勤回数最小属性:
min=夜勤回数最小属性[person]
sc3.print(str(max)+str(min)+'\n')
vlist=[]
for day in 今月:
v=sc3.GetShiftVar(person,day,'入り')
vlist.append(v)
sc3.AddSoft(sc3.SeqError(min,max,3,vlist),st,5)
def 夜勤回数設定():
for person in 夜勤あり:
夜勤回数設定sub(person)
def 公休数設定():
for person in 全スタッフ:
max=-1
min=0
if person not in 公休数属性最大:
continue
st=staffdef[person]+'公休数を制約'
sc3.print(st+'します。\n')
if person in 公休数属性最大:
max=公休数属性最大[person]#float
if person in 公休数属性最小:
min=公休数属性最小[person]
max *=2
min *=2
if isinstance(max, float) and not max.is_integer():
sc3.print('公休数設定で、maxが整数型ではありません。')
continue
if isinstance(min, float) and not min.is_integer():
sc3.print('公休数設定で、minが整数型ではありません。')
continue
max =int(max) #float to int
min =int(min) #float to int
sc3.print(str(max)+str(min)+'\n')
vlist=[]
for day in 今月:
v=sc3.GetShiftVar(person,day,'公休')#公休は2回分カウント
vlist.append(v)
vlist.append(v)
v=sc3.GetShiftVar(person,day,'早半休')#早半休は1回
vlist.append(v)
v=sc3.GetShiftVar(person,day,'半休')#半休は1回
vlist.append(v)
sc3.AddSoft(sc3.SeqError(min,max,4,vlist),st,6)
def 土曜以外の半休抑制():
for person in 全スタッフ:
for day in 土曜でない今月:
ts=shift_schedules[person][day][0]
if ts !='半休':
v=sc3.GetShiftVar(person,day,'半休')
st=staffdef[person]+'土曜以外の半休抑制'
sc3.AddSoft(~v,st,1)
def 夜勤新人Disable():
if len(夜勤新人訓練期間)==0:
sc3.ConstraintEnable('夜勤新人.夜勤新人は、夜勤訓練期間に2回訓練を行う',False)
夜勤回数設定()
公休数設定()
土曜以外の半休抑制()
夜勤新人Disable()
夜勤新人訓練期間がなくても意図通り動作しました。
期間を日月火水木にした例です。
0 件のコメント:
コメントを投稿