ki0073

GLPK

Aug 10th, 2016
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.78 KB | None | 0 0
  1. # version 0.2
  2. set Day; # カレンダーの日付を読み込む
  3. set Holiday; # 休業日を読み込む
  4. set WorkingDay := Day diff Holiday; # 営業日
  5.  
  6. set ManufacturingMachine dimen 2; # 製品と製造機械の対応を読み込む
  7. set ProductName:= setof{(p,m) in ManufacturingMachine}p; # 製品名
  8. set MachineName:= setof{(p,m) in ManufacturingMachine}m; # 製造機械名
  9. param maxProductTypeInDay integer; # 一日で製造できる製品の種類の最大数
  10.  
  11. set ProductionVolume dimen 3; # 製品の製造日数と生産数量を読み込む
  12. set ManufacturingProduct := setof{(p,r,v) in ProductionVolume}(p); # 実際に製造する製品
  13. param manufacturingPeriod{p in ManufacturingProduct} integer := sum{(p,r,v) in ProductionVolume}(r); # 製品ごとの所要製造日数
  14. param outputPerDay{p in ManufacturingProduct} := sum{(p,r,v) in ProductionVolume}(v); # 一日あたりの製品別生産数量
  15.  
  16. set RestrictPlan dimen 3 within {ManufacturingProduct, WorkingDay, WorkingDay}; # 生産期間が限定される条件読み込み
  17. set RestrictProduct := setof{(p,d1,d2) in RestrictPlan}(p); # 生産日が限定される製品
  18. set RestrictPeriod := setof{d in WorkingDay, (p,d1,d2) in RestrictPlan : d>=d1 and d<=d2}(d,p);
  19. set AvailableDayForProduct := {WorkingDay, ManufacturingProduct diff RestrictProduct} union RestrictPeriod; # 製品別の生産可能日
  20.  
  21. param workerHourRatio{WorkingDay} default 1.0; # 目標工数比率の読み込み
  22. param targetOutput{d in WorkingDay} := (sum{p in ManufacturingProduct}manufacturingPeriod[p]*outputPerDay[p]/sum{d1 in WorkingDay}workerHourRatio[d1])*workerHourRatio[d]; # 目標製造数量
  23.  
  24. set ContinuousWorkingDay{d in WorkingDay, i in 1..card({d0 in WorkingDay: d<=d0})} := # 連続した営業日
  25. (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;
  26. set ContinuousWorkingDayIndex := {d in WorkingDay, 1..card(setof{d1 in WorkingDay : d1>=d}d1)}; # 生産が開始できる日付と製造期間
  27. # 製品ごとに有効な連続した日付のインデックス
  28. set EffectiveContinuousWorkingDayIndex := {p in ManufacturingProduct, (d, w) in ContinuousWorkingDayIndex :
  29. w==manufacturingPeriod[p] and forall{d1 in ContinuousWorkingDay[d,w]}(d1,p) in AvailableDayForProduct};
  30.  
  31. # 設定値の出力
  32. printf "期間中に使用される製造装置とそれで製造する製品\n";
  33. for{m in MachineName}{
  34. printf "%s ", m;
  35. printf{(p, m) in ManufacturingMachine : p in ManufacturingProduct} " %s", p;
  36. printf "\n";
  37. }
  38.  
  39. printf "\n";
  40. printf "期間中の製造日数 一日あたりの製造数量 総製造数量\n";
  41. for{p in ManufacturingProduct}{
  42. printf "%s %8d %8.2f %8.2f\n", p, manufacturingPeriod[p], outputPerDay[p], manufacturingPeriod[p]*outputPerDay[p];
  43. }
  44. printf "合計 %8d %8.2f\n\n", sum{p1 in ManufacturingProduct}manufacturingPeriod[p1], sum{p1 in ManufacturingProduct}manufacturingPeriod[p1]*outputPerDay[p1];
  45.  
  46. printf "日ごとの目標数量\n";
  47. for{d in Day}{
  48. printf "%s " & (if d in WorkingDay then "%8.2f" else " -") & "\n", d, targetOutput[d];
  49. }
  50. printf "\n";
  51. printf (if card(RestrictPlan) >0 then "生産可能日が限定される製品\n" else "");
  52. for{p in RestrictProduct}{
  53. printf "%s ", p;
  54. printf{(d,p) in RestrictPeriod} " %s", d;
  55. printf "\n";
  56. }
  57. printf (if card(RestrictPlan) >0 then "\n" else "");
  58. # 生産不可能な日程の表示
  59. set ImpossibleManufacturing := ManufacturingProduct diff setof{(p,d,w) in EffectiveContinuousWorkingDayIndex}p;
  60. for{p in ImpossibleManufacturing}{
  61. printf "%s は製造可能日が短すぎます\n", p;
  62. }
  63.  
  64. var manufacturingDayByProduct{AvailableDayForProduct} binary; # 製品ごとの製造日設定
  65. var startDay{EffectiveContinuousWorkingDayIndex} binary; # 製造開始日を設定
  66. var totalProductionInDay{WorkingDay} >=0; # 日ごとの製造数量の集計値
  67. var differenceFromTarget{WorkingDay} >=0; # 目標数量との差
  68.  
  69. s.t. restrictPeriod{p in ManufacturingProduct}: sum{(d,p) in AvailableDayForProduct}manufacturingDayByProduct[d,p]==manufacturingPeriod[p]; # 製品ごとの製造日数を合わす
  70. s.t. restrictNProductPerDay{d in WorkingDay}: sum{(d,p) in AvailableDayForProduct}manufacturingDayByProduct[d,p]<=maxProductTypeInDay; # 一日の商品種数の上限
  71. s.t. restrictMachine{d in WorkingDay, m in MachineName}: sum{(p,m) in ManufacturingMachine: (d,p) in AvailableDayForProduct}manufacturingDayByProduct[d,p]<=1;
  72. s.t. startManufacturing{p in ManufacturingProduct}: sum{(p,d,w) in EffectiveContinuousWorkingDayIndex}startDay[p,d,w]==1; # 製造開始日
  73. s.t. restrictCont1{p in ManufacturingProduct, (p,d,w) in EffectiveContinuousWorkingDayIndex}: sum{d1 in ContinuousWorkingDay[d,w]}manufacturingDayByProduct[d1,p]-manufacturingPeriod[p]+1<=startDay[p,d,w]; # 連続した製造日を設定
  74. s.t. restrictCont2{(p,d,w) in EffectiveContinuousWorkingDayIndex, d1 in ContinuousWorkingDay[d,w]}: manufacturingDayByProduct[d1,p]>=startDay[p,d,w];
  75. s.t. calcGross{d in WorkingDay}: sum{p in ManufacturingProduct:(d,p) in AvailableDayForProduct}manufacturingDayByProduct[d,p]*outputPerDay[p]==totalProductionInDay[d]; # 日々の製造数量を集計
  76. s.t. diff1{d in WorkingDay}: totalProductionInDay[d]-targetOutput[d]<=differenceFromTarget[d]; # 目標数量と実際の数量との差の絶対値を求める
  77. s.t. diff2{d in WorkingDay}: totalProductionInDay[d]-targetOutput[d]>=-differenceFromTarget[d];
  78. minimize diffrence: sum{d in WorkingDay}differenceFromTarget[d];
  79. # 装置の共用
  80.  
  81. solve;
  82.  
  83. # 結果出力
  84. printf "製品ごとの製造日\n";
  85. printf "製品名 製造日\n";
  86. for{p in ManufacturingProduct}{
  87. printf "%-10s ", p;
  88. printf{d in WorkingDay: (d,p) in AvailableDayForProduct and manufacturingDayByProduct[d,p]==1} " %s", d;
  89. printf "\n";
  90. }
  91. printf "\n";
  92.  
  93. printf "日ごとの生産数\n";
  94. for{d in WorkingDay}{
  95. printf "%s 合計 %8.1f", d, totalProductionInDay[d];
  96. printf{p in ManufacturingProduct: (d,p) in AvailableDayForProduct and manufacturingDayByProduct[d,p]==1} " %s %8.1f", p, outputPerDay[p];
  97. printf "\n";
  98. }
  99. printf "\n";
  100. # 表計算ソフトへのコピペ用
  101. printf "タブ区切り出力\n";
  102. printf "製品名/日付";
  103. printf{d in Day} "\t%s", d;
  104. printf "\n";
  105. for{p in ManufacturingProduct}{
  106. printf "%-10s ", p;
  107. printf{d in Day}(if (d,p) in AvailableDayForProduct and manufacturingDayByProduct[d,p]==1 then "\t%8.1f" else "\t"), outputPerDay[p];
  108. printf "\n";
  109. }
  110. printf "\n";
  111.  
  112. data;
  113. # 製品に対する製造装置名 対象期間に製造しない製品が含まれていてもよい
  114. set ManufacturingMachine :=
  115. "製品1" "装置1"
  116. "製品2" "装置2"
  117. "製品3" "装置3"
  118. "製品4" "装置4"
  119. "製品5" "装置5"
  120. "製品6" "装置6"
  121. "製品7" "装置7"
  122. "製品8" "装置8"
  123. "製品9" "装置9"
  124. "製品10" "装置10"
  125. "製品11" "装置11"
  126. ;
  127. # 製造日数と一日あたりの生産数量
  128. set ProductionVolume :=
  129. "製品1" 5 1800
  130. "製品2" 2 3150
  131. "製品3" 5 2520
  132. "製品4" 1 1590
  133. "製品5" 3 1800
  134. "製品6" 6 950
  135. "製品7" 1 2900
  136. "製品8" 2 1440
  137. "製品9" 2 1260
  138. "製品10" 3 1800
  139. ;
  140. # カレンダーの日付 数値が小->大の順になるように
  141. set Day:= 1 2 3 4 5 6 7 8 9 10
  142. 11 12;
  143. # 休業日 出力はカレンダーの日付で行うが生産を割り当てない
  144. set Holiday := 3 4 9 10;
  145.  
  146. # 一日で製造できる製品の種類の最大数
  147. param maxProductTypeInDay:=5;
  148.  
  149. # 生産日が限定される製品名と開始、終了可能日
  150. set RestrictPlan :=
  151. # "製品2" 1 2
  152. # "製品8" 1 5
  153. ;
  154. # 行事等で目標工数を変えたい場合 日付と比率
  155. param workerHourRatio :=
  156. # 7 0.9 # 先頭の#を外すと営業日の目標工数が変えられる、7日が9割に減少
  157. ;
  158. end;
Advertisement
Add Comment
Please, Sign In to add comment