LoginSignup
0
0

More than 5 years have passed since last update.

整数計画ソルバーの使い方1

Posted at

はじめに

整数計画ソルバーの基本的な使い方を紹介します。
OS別のインストール方法などは
GLPKによる勤務シフト表の作成1
からたどってください。

例1

以下に示す重量のジャガイモがあります。1kg入り(1kg以上)を10袋作りたいのですが、どのように詰めれば良いのでしょうか?

46g 17個
47g 20個
48g 22個
49g 16個
50g 21個
51g 22個
52g 25個
53g 21個
54g 16個
55g 21個

GLPKで動くプログラムを書いてみました。今回はモデルとデータを分けてあります。別々のファイルにして
glpsol -m packing1.mod -d data1.txt
で実行できます。またそのままつなげて1つのファイルにしても構いません。

packing1.mod
set Package; # 袋の番号
set Weight; # 重量
param n{Weight}; # 重量ごとの個数
var assign{Package, Weight} integer, >=0; # 詰める個数

s.t. limit{w in Weight}: sum{p in Package}assign[p,w]<=n[w]; # それぞの重量の個数の上限
s.t. packing{p in Package}: sum{w in Weight}w*assign[p, w]>=1000; # 袋の中身が1000g以上

solve;

# 出力
printf "Package ";
printf{w in Weight}"%4d", w;
printf "\n";
for{p in Package}{
    printf "  %3d   ", p;
    printf{w in Weight}"%4d", assign[p, w];
    printf "\n";
}
printf "Sum     ";
printf{w in Weight}"%4d", sum{p in Package}assign[p, w];
printf "\n";
data1.txt
data;
# 袋の番号
set Package := 1 2 3 4 5 6 7 8 9 10;
# 1個あたりの重量と個数
param : Weight :  n :=
46  17
47  20
48  22
49  16
50  21
51  22
52  25
53  21
54  16
55  21
;

しばらくすると、答えが出力されます。私の環境では以下のようになりました。条件を満たす答えが多種類ありますので、同じ結果になるとは限りません。

result
Package   46  47  48  49  50  51  52  53  54  55
    1      0   0   0   0   0   0   0   0   0  19
    2      0   0   0   0   0   0   1   0  16   2
    3      0   0   0   0   0   0   0  19   0   0
    4      0   0   1   0   0   1  17   1   0   0
    5      0   0   1   0   0  13   6   0   0   0
    6      0  13   7   0   0   0   0   1   0   0
    7      0   0   0   3  14   3   0   0   0   0
    8      2   0  13   6   0   0   0   0   0   0
    9      0   0   0   7   7   5   1   0   0   0
   10     15   7   0   0   0   0   0   0   0   0
Sum       17  20  22  16  21  22  25  21  16  21

1kg以上になる条件にしましたので、全部を詰めた太っ腹な結果になりました。(多分たまたま)

solve;より上に
minimize tatal_packing_weight: sum{p in Package, w in Weight}w*assign[p, w];
この1行を追加すると袋詰めする総重量が最小化されます。

+ 87727: mip =   1.011300000e+04 >=   1.000000000e+04   1.1% (43194; 4913)
+ 94668: mip =   1.011300000e+04 >=   1.000000000e+04   1.1% (46780; 5378)
+100669: mip =   1.011300000e+04 >=   1.000000000e+04   1.1% (49826; 5818)
+106053: mip =   1.011300000e+04 >=   1.000000000e+04   1.1% (52275; 6280)
+111379: mip =   1.011300000e+04 >=   1.000000000e+04   1.1% (55292; 6672)
+116711: mip =   1.011300000e+04 >=   1.000000000e+04   1.1% (58408; 7048)

こんなメッセージが延々と出てきますが、私の非力なパソコンではしばらく待っても答えを返しくれませんでした。

mip =の後に、2つの数値が表示されている時には、最適解は見つかっていないけれど、条件を満たしてい許容解は見つかってます。

待てない人は、コマンドに
--tmlim 60
を追加すると、指定時間後に制約条件を満たした答が出力されます。(この場合は60秒)

また、一番重い袋の重量を最小化する方法もあります。

var max_package_weight integer;
s.t. max_paking_weigth{p in Package}: sum{w in Weight}w*assign[p, w]<=max_package_weight;
minimize pack_weight: max_package_weight;

max_package_weightに一番重い袋の重量が入ります。

「整数計画ソルバーの使い方2」に続く予定

0
0
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
0