Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # version 0.3
- # 製品製造に使える装置を複数の中から選べる機能を追加
- set Day; # カレンダーの日付を読み込む
- set Holiday; # 休業日を読み込む
- set WorkingDay := Day diff Holiday; # 営業日
- set ManufacturingMachine dimen 2; # 製品と製造機械の対応を読み込む
- set ProductName:= setof{(p,m) in ManufacturingMachine}p; # 製品名
- set MachineName:= setof{(p,m) in ManufacturingMachine}m; # 製造機械名
- param maxProductTypeInDay integer, default card(MachineName); # 一日で製造できる製品の種類の最大数
- set ProductionVolume dimen 3; # 製品の製造日数と生産数量を読み込む
- set ManufacturingProduct := setof{(p,r,v) in ProductionVolume}(p); # 実際に製造する製品
- param manufacturingPeriod{p in ManufacturingProduct} integer := sum{(p,r,v) in ProductionVolume}(r); # 製品ごとの所要製造日数
- param outputPerDay{p in ManufacturingProduct} := sum{(p,r,v) in ProductionVolume}(v); # 一日あたりの製品別生産数量
- set RestrictPlan dimen 3 within {ManufacturingProduct, WorkingDay, WorkingDay}; # 生産期間が限定される条件読み込み
- set RestrictProduct := setof{(p,d1,d2) in RestrictPlan}(p); # 生産日が限定される製品
- set RestrictPeriod := setof{d in WorkingDay, (p,d1,d2) in RestrictPlan : d>=d1 and d<=d2}(d,p);
- set AvailableDayForProduct := {d in WorkingDay, (p,m) in ManufacturingMachine: (not p in RestrictProduct) or (d,p) in RestrictPeriod}; # 製品別の生産可能日
- param workerHourRatio{WorkingDay} default 1.0; # 目標工数比率の読み込み
- param targetOutput{d in WorkingDay} := (sum{p in ManufacturingProduct}manufacturingPeriod[p]*outputPerDay[p]/sum{d1 in WorkingDay}workerHourRatio[d1])*workerHourRatio[d]; # 目標製造数量
- set ContinuousWorkingDay{d in WorkingDay, i in 1..card({d0 in WorkingDay: d<=d0})} := # 連続した営業日
- (if i==1 then {} else ContinuousWorkingDay[d, i-1]) union setof{d1 in WorkingDay : sum{d2 in WorkingDay : d2<=d1 and d2>=d}1==i }d1;
- set ContinuousWorkingDayIndex := {d in WorkingDay, 1..card(setof{d1 in WorkingDay : d1>=d}d1)}; # 生産が開始できる日付と製造期間
- # 製品ごとに有効な連続した日付のインデックス
- set EffectiveContinuousWorkingDayIndex := {p in ManufacturingProduct, (p,m) in ManufacturingMachine, (d,w) in ContinuousWorkingDayIndex :
- w==manufacturingPeriod[p] and forall{d1 in ContinuousWorkingDay[d,w]}(d1,p,m) in AvailableDayForProduct};
- # 設定値の出力
- printf "期間中に使用される製造装置とそれで製造可能な製品\n";
- for{m in MachineName}{
- printf "%s ", m;
- printf{(p, m) in ManufacturingMachine : p in ManufacturingProduct} " %s", p;
- printf "\n";
- }
- printf "\n";
- printf "期間中の製造日数 一日あたりの製造数量 総製造数量\n";
- for{p in ManufacturingProduct}{
- printf "%s %8d %8.2f %8.2f\n", p, manufacturingPeriod[p], outputPerDay[p], manufacturingPeriod[p]*outputPerDay[p];
- }
- printf "合計 %8d %8.2f\n\n", sum{p1 in ManufacturingProduct}manufacturingPeriod[p1], sum{p1 in ManufacturingProduct}manufacturingPeriod[p1]*outputPerDay[p1];
- printf "日ごとの目標数量\n";
- for{d in Day}{
- printf "%s " & (if d in WorkingDay then "%8.2f" else " -") & "\n", d, targetOutput[d];
- }
- printf "\n";
- printf (if card(RestrictPlan) >0 then "生産可能日が限定される製品\n" else "");
- for{p in RestrictProduct}{
- printf "%s ", p;
- printf{(d,p) in RestrictPeriod} " %s", d;
- printf "\n";
- }
- printf (if card(RestrictPlan) >0 then "\n" else "");
- # 生産不可能な日程の表示
- set ImpossibleManufacturing := ManufacturingProduct diff setof{(p,m,d,w) in EffectiveContinuousWorkingDayIndex}p;
- for{p in ImpossibleManufacturing}{
- printf "%s は製造可能日が短すぎます\n", p;
- }
- var manufacturingDayByProduct{AvailableDayForProduct} binary; # 製品ごとの製造日
- var startDay{EffectiveContinuousWorkingDayIndex} binary; # 製造開始日
- var totalProductionInDay{WorkingDay} >=0; # 日ごとの製造数量の集計値
- var differenceFromTarget{WorkingDay} >=0; # 目標数量との差
- s.t. restrictPeriod{p in ManufacturingProduct}:
- sum{(d,p,m) in AvailableDayForProduct}manufacturingDayByProduct[d,p,m]==manufacturingPeriod[p]; # 製造日数を規定の日数に
- s.t. restrictMachine{d in WorkingDay, m in MachineName}:
- sum{(d,p,m) in AvailableDayForProduct}manufacturingDayByProduct[d,p,m]<=1; # 製造装置の使用が重ならない
- s.t. restrictProduct{d in WorkingDay, p in ManufacturingProduct}:
- sum{(d,p,m) in AvailableDayForProduct}manufacturingDayByProduct[d,p,m]<=1; # 同じ製品は1系列のみ
- s.t. restrictNProductPerDay{d in WorkingDay}:
- sum{(d,p,m) in AvailableDayForProduct}manufacturingDayByProduct[d,p,m]<=maxProductTypeInDay; # 一日の商品種類の上限
- s.t. startManufacturing{p in ManufacturingProduct}: sum{(p,m,d,w) in EffectiveContinuousWorkingDayIndex}startDay[p,m,d,w]==1; # 製造開始日
- s.t. restrictCont1{p in ManufacturingProduct, (p,m,d,w) in EffectiveContinuousWorkingDayIndex}:
- sum{d1 in ContinuousWorkingDay[d,w]}manufacturingDayByProduct[d1,p,m]-manufacturingPeriod[p]+1<=startDay[p,m,d,w]; # 連続した製造日を設定
- s.t. restrictCont2{(p,m,d,w) in EffectiveContinuousWorkingDayIndex, d1 in ContinuousWorkingDay[d,w]}:
- manufacturingDayByProduct[d1,p,m]>=startDay[p,m,d,w];
- s.t. calcGross{d in WorkingDay}:
- sum{p in ManufacturingProduct, (p,m) in ManufacturingMachine: (d,p,m) in AvailableDayForProduct}
- manufacturingDayByProduct[d,p,m]*outputPerDay[p]==totalProductionInDay[d]; # 日々の製造数量を集計
- s.t. diff1{d in WorkingDay}: totalProductionInDay[d]-targetOutput[d]<=differenceFromTarget[d]; # 目標数量と実際の数量との差の絶対値を計算
- s.t. diff2{d in WorkingDay}: totalProductionInDay[d]-targetOutput[d]>=-differenceFromTarget[d];
- minimize diffrence: sum{d in WorkingDay}differenceFromTarget[d];
- solve;
- set UseMachine := setof{(p,m,d,w) in EffectiveContinuousWorkingDayIndex : startDay[p,m,d,w]==1}(p,m); # 使用製造装置
- # 結果出力
- printf "製品ごとの製造装置\n";
- printf "製品名 製造装置\n";
- for{p in ManufacturingProduct}{
- printf "%-10s ", p;
- printf{(p,m) in UseMachine}" %s\n", m;
- }
- printf "\n";
- printf "製品ごとの製造日\n";
- printf "製品名 製造日\n";
- for{p in ManufacturingProduct}{
- printf "%-10s ", p;
- printf{d in WorkingDay, (p,m) in ManufacturingMachine: (d,p,m) in AvailableDayForProduct and manufacturingDayByProduct[d,p,m]==1} " %s", d;
- printf "\n";
- }
- printf "\n";
- printf "日ごとの生産数\n";
- for{d in WorkingDay}{
- printf "%s 合計 %8.1f", d, totalProductionInDay[d];
- printf{(p,m) in ManufacturingMachine: (d,p,m) in AvailableDayForProduct and manufacturingDayByProduct[d,p,m]==1} " %s %8.1f", p, outputPerDay[p];
- printf "\n";
- }
- printf "\n";
- # 表計算ソフトへのコピペ用
- printf "タブ区切り出力\n";
- printf "製品\t製造設備/日付";
- printf{d in Day} "\t%s", d;
- printf "\n";
- for{p in ManufacturingProduct}{
- printf "%s", p;
- printf{(p,m) in UseMachine}"\t%s", m;
- printf{d in Day}(if sum{(d,p,m) in AvailableDayForProduct}manufacturingDayByProduct[d,p,m]>=1 then "\t%8.1f" else "\t"), sum{(d,p,m) in AvailableDayForProduct}manufacturingDayByProduct[d,p,m]*outputPerDay[p];
- printf "\n";
- }
- printf "\n";
- data;
- # 製品に対する製造装置名 対象期間に製造しない製品が含まれていてもよい
- set ManufacturingMachine :=
- ("製品1", *) "装置a"
- ("製品2", *) "装置a"
- ("製品3", *) "装置b"
- ("製品4", *) "装置b"
- ("製品5", *) "装置c"
- ("製品6", *) "装置e"
- ("製品7", *) "装置d" "装置b"
- ("製品8", *) "装置d" "装置b"
- ("製品9", *) "装置d" "装置b"
- ("製品10", *) "装置d" "装置b"
- ;
- # 製造日数と一日あたりの生産数量
- set ProductionVolume :=
- "製品1" 5 1800
- "製品2" 2 3150
- "製品3" 5 2520
- "製品4" 1 1590
- "製品5" 3 1800
- "製品6" 6 950
- "製品7" 1 2900
- "製品8" 2 1440
- "製品9" 2 1260
- "製品10" 3 1800
- ;
- # カレンダーの日付 数値が小->大の順になるように
- set Day:= 1 2 3 4 5 6 7 8 9 10
- 11 12;
- # 休業日 出力はカレンダーの日付で行うが生産を割り当てない
- set Holiday := 3 4 9 10;
- # 一日で製造できる製品の種類の最大数
- param maxProductTypeInDay:=10;
- # 生産日が限定される製品名と開始、終了可能日
- set RestrictPlan :=
- "製品2" 1 2
- # "製品8" 1 5
- ;
- # 行事等で目標工数を変えたい場合 日付と比率
- param workerHourRatio :=
- # 7 0.9 # 先頭の#を外すと営業日の目標工数が変えられる、7日が9割に減少
- ;
- end;
Advertisement
Add Comment
Please, Sign In to add comment