0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GLPKによる勤務シフト表の作成1(3)

Last updated at Posted at 2017-03-25

###目次
GLPKによる勤務シフト表の作成1(1)(基礎編) (2) (3) ←ここ (4)
GLPKによる勤務シフト表の作成2 (2日連続して勤務する場合の勤務シフト)

デバッグ

モデル記述の中に
display 変数名;
を挿入することで変数の値が表示されます。
varだけではなくsetやparamで指定した名称も可能です。

さらなる改良版

スタッフが従事する時間帯や休みを確保するために、制約条件を追加してきましたが、varを宣言する時に変数の取り得る範囲を制限してしまって、従事する時は>=1に、休む時は<=0にすると、実現できます。

var assignShiftSchedule{(d,t) in BusinessHour, s in Staff} binary;

var assignShiftSchedule{(d,t) in BusinessHour, s in Staff} binary, >= if (d,t,s) in FixOnDuty then 1 else 0, <= if (d,t,s) in FixOffDuty then 0 else 1;
に変更して範囲指定、
不要になった
s.t. fix1{(d,t,s) in FixOnDuty}: assignShiftSchedule[d,t,s]=1;
s.t. fix2{(d,t,s) in FixOffDuty}: assignShiftSchedule[d,t,s]=0;
を取り除きます。

全体としては次のようになります。

shift3.model
# version 0.13
# シフト表作成
param firstDate; # 期間の最初の日付
param endDate;   # 最後の日付
set Date := firstDate..endDate; # 期間内の日付
set TimeSlot := {"朝", "夕", "夜"}; # シフト時間枠
set Staff; # スタッフ名
param maxWorkingDays{Staff}; # 各スタッフの最大勤務日数
set BusinessHour dimen 2; # 営業時間帯
set FixOnDuty dimen 3;    # 勤務時間帯
set FixOffDuty dimen 3;   # 非番時間帯
# 日付,シフト時間枠,スタッフの配列を確保、出勤の割り当てで1が入る
var assignShiftSchedule{(d,t) in BusinessHour, s in Staff} binary, >= if (d,t,s) in FixOnDuty then 1 else 0, <= if (d,t,s) in FixOffDuty then 0 else 1;

# シフト時間枠に必ず1人従事
s.t. keepStaffInTimeSlot{(d,t) in BusinessHour}: sum{s in Staff}assignShiftSchedule[d,t,s]==1;
# 出勤は1日1回以下
s.t. avoidShiftPatten1{s in Staff, d in Date}: sum{(d,t) in BusinessHour}
    assignShiftSchedule[d,t,s]<=1;
# 各スタッフの最大勤務日数で制限
s.t. restrictMaxWorkDays{s in Staff}: sum{(d,t) in BusinessHour}
    assignShiftSchedule[d,t,s]<=maxWorkingDays[s];
# 連続勤務は3日以下
s.t. keepOffDay{s in Staff, d in firstDate..endDate-3}: sum{t in TimeSlot, d4 in d..d+3 : (d4,t) in BusinessHour}
    assignShiftSchedule[d4,t,s]<=3;
# 翌日の勤務時間帯を制限
s.t. avoidShiftPatten2{s in Staff, d in firstDate..endDate-1}: sum{(d1, t) in {(d, "夕"), (d, "夜"), (d+1, "朝")} :(d1,t) in BusinessHour}
    assignShiftSchedule[d1,t,s]<=1;
s.t. avoidShiftPatten3{s in Staff, d in firstDate..endDate-1}: sum{(d1, t) in {(d, "夜"), (d+1, "朝"), (d+1, "夕")} :(d1,t) in BusinessHour}assignShiftSchedule[d1,t,s]<=1;

solve;
# 出力
for{d in Date}{
    printf "%2d ", d;
    for{t in TimeSlot : (d,t) in BusinessHour}{
        printf{s in Staff : assignShiftSchedule[d,t,s]==1}" %s", s;
    }
    printf "\n";
}

data;
# 期間の最初の日付と最後の日付
param firstDate:=1; 
param endDate  :=13;
# スタッフ名と最大勤務日数
param : Staff : maxWorkingDays :=
"A"  9
"B"  9
"C"  9
"D"  9
;
# 営業時間帯
set BusinessHour :=
(1, *) "朝" "夕" "夜"
(2, *) "朝" "夕" "夜"
(3, *) "朝" "夕" "夜"
(4, *) "朝" "夕" "夜"
(5, *) "朝" "夕" "夜"
(6, *) "朝" "夕"
# 7日は休業
(8, *) "朝" "夕" "夜"
(9, *) "朝" "夕" "夜"
(10, *) "朝" "夕" "夜"
(11, *) "朝" "夕" "夜"
(12, *) "朝" "夕" "夜"
(13, *) "朝" "夕"
;
# スタッフが従事する時間帯を指定
set FixOnDuty :=
(1, "朝", "A")
(1, "夕", "B")
(1, "夜", "C")
;
# スタッフが出勤できない時間帯を指定
set FixOffDuty :=
(2, *, "A") "朝" "夕" "夜"
(3, *, "B") "朝" "夕" "夜"
;

GLPKによる勤務シフト表の作成1(4)->

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?