ki0073

GLPK

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