More Related Content Similar to Operations research yonezawa_no2
Similar to Operations research yonezawa_no2 (20) Operations research yonezawa_no21. 整数計画問題
⚫ 決定変数に整数制約が付いた線形計画問題
⚫ 整数計画問題 (Integer Programming, IP)
⚫ 決定変数が整数に限定され、4.5といった小数を許さない
⚫ 整数の組合せの探索が必要になり膨大な探索が必要
⚫ シンプレックス法の様な万能の手法は存在しない
⚫ 整数計画問題のバリエーション
⚫ 混合整数計画問題 (Mixed Integer Programming, MIP)
▪ 決定変数に実数と整数の両方がある問題
⚫ 0-1問題
▪ 整数計画問題のうち決定変数が0, 1に限定されている問題
整数計画問題
4. 制約条件と実行可能領域
⚫0 ⚫5 ⚫10 ⚫15 ⚫20 ⚫25
⚫ポテトサラダ(100g)
⚫2
⚫4
⚫6
⚫8
⚫10
⚫グリーンサラダ(100g)
x2
x1
⚫食物繊維
⚫カルシウム
⚫ビタミンC
実行可能領域
整数計画問題 > サラダパック問題
目的関数
5. lp_solveによる定式化
⚫ lp_solveの入力ファイルに整数制約を追加指定
⚫ 実行結果
min: 100 x1 + 80 x2; /* カロリー */
c1: 5 x1 + 2.5 x2 >= 25; /* ビタミンC */
c2: 20 x1 + 50 x2 >= 300; /* カルシウム */
c3: 0.5 x1 + 4 x2 >= 12; /* 食物繊維 */
int x1, x2; /* 整数制約 */
Value of objective function: 680
Actual values of the variables:
x1 2
x2 6
整数計画問題 > サラダパック問題
7. ナップサック問題の定式化
⚫ ナップサック問題の
⚫ 決定変数
⚫ xi = {0,1} iに投資する(1)か否(0)か
⚫ 定数
⚫ L 手持ち資金
⚫ li iに必要な投資金額
⚫ wi iに投資して得られる利益
⚫ 制約条件
⚫ ∑lixi ≦ L 投資総額が資金を以下
⚫ 目的関数
⚫ z = ∑ wixi 得られる利益を最大化
w1, x1
w2, x2
w3, x3
w4, x4
w5, x5
w6, x6
w7, x7
l1
l2
l3
l4
l5
l6
l7
L
w7, x7
w6, x6
w4, x4
w2, x2
w1, x1
整数計画問題 > ナップサック問題
9. lp_solveによる最適化の実行
⚫ lp_solveによる定式化
/* 目的関数 */
max: 20x1 + 32x2 + 16x3 + 12x4
+ 5x5 + 20x6 + 3x7 + 4x8;
/* 合計重量制約 */
4x1 + 6x2 + 3x3 + 2x4
+ 1x5 + 5x6 + 2x7 + 3x8 <= 10;
/* 0,1 制約 */
x1 <= 1; x2 <= 1; x3 <= 1; x4 <= 1;
x5 <= 1; x6 <= 1; x7 <= 1; x8 <= 1;
/* 整数制約 */
int x1, x2, x3, x4, x5, x6, x7, x8;
非常食 選択 重量 カロリー
1 1 4 20
2 0 6 32
3 1 3 16
4 1 2 12
5 1 1 5
6 0 5 20
7 0 2 3
8 0 3 4
合計 10 53
⚫ 最適化結果
整数計画問題 > ナップサック問題
10. 貪欲法による解法
⚫ 組合せ問題の近似解法
⚫ 効率の良い順に選択
⚫ 目先の利益を追求
⚫ 手戻りや後先を考えない
⚫ 最も単純な近似解法
⚫ ナップサック問題に適用
⚫ カロリー/重量で並べ替え
⚫ 重量制約の範囲で選択
整数計画問題 > ナップサック問題
非常食 重量
カロ
リー
効率 重量
カロ
リー
4 2 12 6.00 2 12
2 6 32 5.33 8 44
3 3 16 5.33 X11 -
1 4 20 5.00 X12 -
5 1 5 5.00 9 49
6 5 20 4.00 X14 -
7 2 3 1.50 X11 -
8 3 4 1.33 X12 -
合計 10 9 49
12. 列挙法による解法
⚫ 全ての組合せを列挙する
⚫ 制約を満たす範囲で探索
⚫ 制約を満たせなければ終了
⚫ 計算量は膨大
⚫ 例題では最大28=256通り
⚫ 組合せが指数関数的に爆発
1 1
2 2 2 2
3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
整数計画問題 > 列挙法
n
n
選択、レベルn
非選択
L W
2 12 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 32 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 16 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 20 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 5 1 0 0 1 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 1 1 1 0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
5 20 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
2 3 0 1 0 0 0 1 0 0 0 1 1 0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 0 1 1 0 0 1 0 1 1 0 0 0 1 1 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
3 4 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 0 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
L 9 10 8 10 9 8 9 6 10 10 7 8 5 9 10 7 8 9 6 10 8 8 5 6 3 9 10 7 7 4 5 2 10 9 10 9 10 7 8 9 6 10 8 9 10 7 9 9 6 7 4 10 8 8 5 6 3 10 10 7 8 5 9 9 6 7 4 8 9 6 6 3 4 1 10 7 8 5 5 2 3 0
W 49 47 44 53 48 36 37 33 48 35 31 32 28 40 41 37 35 36 32 40 37 24 20 21 17 35 36 32 19 15 16 12 53 48 52 40 41 37 35 36 32 44 41 39 40 36 41 28 24 25 21 39 36 23 19 20 16 45 32 28 29 25 40 27 23 24 20 28 29 25 12 8 9 5 27 23 24 20 7 3 4 0
13. 列挙法のプログラム
1. #define L_MAX (10.0)
2. #define NUM (8)
3.
4. double W_max = 0;
5. double l[NUM] = { 2, 6, 3, 4, 1, 5, 2, 3};
6. double w[NUM] = {12,32,16,20, 5,20, 3, 4};
7. // レベル 0 1 2 3 4 5 6 7
8. void enumulate(int i, double L, double W);
9.
10. int main(int argc, char* argv[]){
11. enumulate(0, 0, 0);
12. return 0;
13. }
効率順に
ソート済み
レベル0より
探索の開始
整数計画問題 > 列挙法
14. 列挙法のプログラム(続き)
1. void enumulate(int i, double L, double W) {
2. if (W > W_max)
3. W_max = W;
4. if (i < NUM) { // 最終レベルに到達していなければ
5. if (L + l[i] <= L_MAX) // 容量制約以内であれば
6. enumulate(i+1, L + l[i], W + w[i]);//選択
7. enumulate(i+1, L, W); //非選択
8. }
9. } 2 0
8 2 6 0
X 8 5 2 9 6 3 0
X 8 9 5 6 2 X 9 10 6 7 3 4 0
⚫ 再帰呼出による実装
⚫ 選択・非選択を再帰呼出
⚫ 最終レベルまで繰り返す
整数計画問題 > 列挙法
次のレベル
15. 分枝限定法
⚫ 分枝限定法の考え方
⚫ 基本的には列挙法
⚫ 全ての組合せを列挙する
⚫ 無駄な列挙を省く
⚫ 緩和問題により上限値を計算
⚫ ある分枝方向の上限値が既存の解
以下なら探索を省略
⚫ 緩和問題
⚫ 元の問題の制約を取り除いた問題
⚫ 整数制約を取り除き簡単にする
⚫ 元問題の最適値の上限を与える
整数計画問題 > 分枝限定法
重量
カロ
リー
重量
カロ
リー
2 12 2 12
6 32 8 44
3 16 10 54.7
4 20 - -
1 5 - -
5 20 - -
2 3 - -
3 4 - -
10 54.7
緩和問題
2/3個を選択
16. 分枝限定法
⚫ 深さ優先
⚫ 左(選択)優先
レ
ベ
ル
l w
1 2 12
2 6 32
3 3 16
4 4 20
5 1 5
6 5 20
7 2 3
8 3 4
212/53
528/53X 844/54
X 844/53
949/50.3
948/53
949/50.5
X
X
844/52 948/52
528/49
212/49
00/53
1053/53949/53
949/49X
n
n
選択、容量n
容量超過
非選択、容量n
X
解の更新
分枝限定
212/54.7
844/54.7
目的関数値/上限値
整数計画問題 > 分枝限定法
844/47
17. 分枝限定法のプログラム
1. void enumulate(int i, double L, double W) {
2. if (W_max < W)
3. W_max = W;
4. if (i < NUM) {
5. double UB = upper_bound(i+1, L, W); //上限値
6. if (L+l[i] <= L_MAX)
7. enumulate(i+1, L + l[i], W + w[i]);//選択
8. if (UB > W_max) // 改善が見込めるならば
9. enumulate(i+1, L, W); //非選択
10. }
11. }
整数計画問題 > 分枝限定法
18. 分枝限定法のプログラム(続き)
1. /* 緩和問題を計算し目的関数の上限値を決める関数 */
2. double upper_bound(int i, double L, double W) {
3. for (; i < NUM && L + l[i] <= L_MAX; i++) {
4. L += l[i]; // 入る範囲で充填
5. W += w[i];
6. }
7. if (i < NUM && L < L_MAX) { // まだ満たない場合
8. W += w[i] * (L_MAX - L)/l[i]; // 残りを充填
9. L = L_MAX;
10. }
11. return W;
12. }
整数計画問題 > 分枝限定法
w7, x7
w6, x6
w4, x4
w2, x2
w1, x1
L_MAXL
この部分のみを充填
20. 輸送コスト表と輸送量
コ
ス
ト
倉庫\店舗 S1 S2 S3 S4 固定費
D1 2 3 4 6 50
D2 7 4 3 1 50
D3 4 5 6 2 50
輸
送
量
倉庫\店舗 S1 S2 S3 S4 供給量
D1 x11 x12 x13 x14 15
D2 x21 x22 x23 x24 15
D3 x31 x32 x33 x34 20
需要量 3 16 9 6 34
線形計画問題 > 倉庫選択問題
21. 倉庫選択問題の定式化
⚫ 倉庫の存続を0-1整数変数で表現
⚫ 決定変数
⚫ xij 倉庫iから店舗jへの輸送量
⚫ yi = 0 ならば倉庫を廃止
⚫ yi = 1 ならば倉庫を存続
⚫ 制約条件(荷量の制約以外)
⚫
⚫ 目的関数
⚫
整数計画問題 > 倉庫選択問題
}{
4
1
に対して全ての拠点iyMx
j
iiij
=
}{
4
1
3
1
==
+=
j
ijijii
i
xcyDz
⚫ その他の定数記号
⚫ Mi: 倉庫iの供給可能量
⚫ cij : ij間の輸送コスト
⚫ Di : 倉庫iの固定費
xijが全て = 0 ⇒ yi = 0
xijが1つでも > 0 ⇒ yi = 1
(yiにコストが設定)
22. lp_solveで解を求める
⚫ lp_solveの入力ファイルの作成
⚫ lp_solveの実行結果
min: 2 x11 + 3 x12 + 4 x13 + 6 x14 + 50 y1 +
7 x21 + 4 x22 + 3 x23 + 1 x24 + 50 y2 +
4 x31 + 5 x32 + 6 x33 + 2 x34 + 50 y3;
/* 需要量の制約、供給量の上限、省略 */
/* 倉庫の存続、廃止の条件を表現する制約 */
x11 + x12 + x13 + x14 <= 15 y1;
x21 + x22 + x23 + x24 <= 15 y2;
x31 + x32 + x33 + x34 <= 30 y3;
int y1, y2, y3; /* 倉庫の存続、廃止を表す整数変数 */
整数計画問題 > 倉庫選択問題
z = 225
x21 = 0, x22 = 6, x23 = 9, x24 = 0, y2 = 1
x31 = 3, x32 =10, x33 = 0, x34 = 6, y3 = 1
24. トラックの輸送パターン
パターン A AA AAA B BB C AB AC BC
時間(h) 3 6 9 4 8 5 7 8 9
費用(万円) 13 16 19 14 18 15 17 18 19
車両数 xa xaa xaaa xb xbb xc xab xac xbc
A輸送回数 1 2 3 1 1 = 42
B輸送回数 1 2 1 1 = 25
C輸送回数 1 1 1 = 10
整数計画問題 > 輸送スケジュール問題
25. 輸送スケジュール問題の定式化
⚫ 集合分割問題として定式化
⚫ 決定変数
⚫ 各輸送パターンの車両数
⚫ xa , xaa , xaaa , xb , xbb , xc , xab , xac , xbc
⚫ 制約条件
⚫ xa + 2 xaa + 3 xaaa + xab + xac = 42 倉庫Aへの輸送回数
⚫ xb + 2 xbb + xab + xbc = 25 倉庫Bへの輸送回数
⚫ xc + xac + xbc = 10 倉庫Cへの輸送回数
⚫ 目的関数
⚫ z = caxa + caaxaa + caaaxaaa + cbxb + cbbxbb + ccxc +
cabxab + cacxac + cbcxbc
整数計画問題 > 輸送スケジュール問題
26. lp_solveで解を求める
⚫ lp_solveの入力ファイルの作成
⚫ lp_solveの実行結果
/* 目的関数 */
min: 13 xa + 16 xaa + 19 xaaa + 14 xb + 18 xbb
+ 15 xc + 17 xab + 18 xac + 19 xbc;
/* 輸送量制約 */
xa + 2 xaa + 3 xaaa + xab + xac = 42;
xb + 2 xbb + xab + xbc = 25;
xc + xac + xbc = 10;
/* 整数制約 */
int xa, xaa, xaaa, xb, xbb, xc, xab, xac, xbc;
決定変数 xa xaa xaaa xb xbb xc xab xac xbc
車両数 0 1 13 0 7 0 1 0 10
整数計画問題 > 輸送スケジュール問題
27. 整数計画法の典型的な定式化
⚫ 固定費
⚫ xi ≦ Byi yiは0-1変数、Bは大数
⚫ 最小値(0かm以上)
⚫ 0 ≦ –xi + Byi ≦ B – m yiは0-1変数、Bは大数、mは最小値
⚫ 依存関係(iを選択するにはjが前提)
⚫ xi ≦ xj xiは0-1変数
⚫ 排他関係(同時に選択されない)
⚫ xi + xj ≦ 1 xiは0-1変数
⚫ 排他選択(いずれか1つを選択)
⚫ x1 + x2 + ... + xi = 1 xiは0-1変数
整数計画問題
28. 整数計画法の典型的な定式化
⚫ 集合分割問題
⚫ 行の成分を分割するように
複数の列を選択
⚫ 重複した選択を許さない
⚫ 集合被覆問題
⚫ 行の成分を覆うように複数
の列を選択
⚫ 行の成分が条件を超える
のは問題ない
整数計画問題
最小化でc2>c4ならば
( )
( )
=
1
1
1
1
0
1
1
0
1
0
0
0
0
1
0
0
0
0
1
1
4321
4321
cccc
xxxx ( )
( )
1
1
1
1
0
1
1
0
1
0
0
0
0
1
0
0
0
0
1
1
4321
4321
cccc
xxxx
30. 経済発注量モデル
⚫ 経済発注量モデル
⚫ 最も基本的な在庫管理問題
⚫ 次の仮定の下でコスト最小化
⚫ 製品をQ発注し倉庫に在庫
⚫ 一定量dで倉庫から出荷
⚫ 期間T後に次の発注
⚫ 発注には発注費用c1
⚫ 在庫には在庫費用c2
⚫ 総費用を最小化する発注量Qを
決定する
在庫管理問題 >経済発注量モデル
発
注
量
Q
発注間隔T
在庫レベル
時間
需要量d(傾き)
Q:発注量
T:発注間隔
d:需要量(d=Q/T)
c1:発注費用
c2:在庫費用
32. 経済発注量モデルの最適化
⚫ 微分法による求解
⚫ 目的関数のQによる微分
⚫
⚫ z’(Q*) = 0 を解くと
⚫
⚫ d=Q/Tより
⚫
⚫ z(Q) にQ*を代入して
⚫
0
2
4
6
8
10
0 2 4 6 8 10
発注費用 在庫費用 総費用
発注量Q (千個)
費
用
(
万
円
)
20
200000
200
2
1
=
=
=
c
c
d
40000*
2000*
=
=
z
Q
2
)( 2
2
1 c
Q
dc
Qz +−=
2
12
*
c
dc
Q =
dccz 212* =
在庫管理問題 >経済発注量モデル
dc
c
T
2
12
* =
33. 2のべき乗方策
⚫ 現実世界の制約を反映した方策
⚫ 基準期間×2n を発注間隔とする
⚫ 1, 2, 4, 8, 16, 32, …週 (週を基本単位として)
⚫ 問題の定式化
⚫ 目的関数を発注間隔Tの関数とすると
▪
⚫ 発注間隔をT = B2k とし、次の条件を満たすkを求める
▪ z(B2k–1) ≧ z(B2k) ≦ z(B2k+1)
⚫ 目的関数を展開すると
▪
在庫管理問題 >経済発注量モデル
2
)( 21 dTc
T
c
Tz +=
d
Bc
B
c
d
Bc
B
c
d
Bc
B
c k
k
k
k
k
k
2
2
22
2
22
2
2
1
2
1
121
1
2
1
1
+
+
−
−
+++
34. 2のべき乗方策(続き)
⚫ 目的値最小とするT#=B2k*を考える
⚫ 先の条件式を変形すると
▪
⚫ を用いると
▪
⚫ この両端での目的関数値を計算すると
▪
( ) dc
c
BT
dc
c k
2
1*#
2
1 4
2 =
*2
2
* #
TT
T
( ) *06.1*
22
3
2
22
3
*2
2
*
21 zzdccTz
T
z ===
dc
c
T
2
12
* =
在庫管理問題 >経済発注量モデル
高々6%の増加で抑えられることがわかる
0
2
4
6
8
10
0 2 4 6 8 10
発注費用 在庫費用 総費用
発注間隔T
費
用
(
万
円
)
T*2
*T
*2T
35. 生産時間の考慮
⚫ 経済発注量モデルの拡張
⚫ 製品を生産し在庫とする
⚫ 製品生産速度:p (> d=Q/T)
⚫ 発注量Qに達すると生産終了
⚫ 平均在庫量 :
⚫ 在庫費用 :
⚫ 平均費用 :
⚫ 目的関数は
⚫
発
注
量
Q
発注間隔T
在庫レベル
平均在庫量
生産量:傾きp
( )
2
12 TQpdc −
( )
2
1 Qpd−
( )
2
121 Qpdc
T
c −
+
( )
2
1
)( 21 Qpdc
Q
dc
Qz
−
+=
最大在庫量Qm
( )
( )Qpd
pQdQ
dQ
Q
Qm
−=
−=
−=
−=
1
生産完了時間
生産完了時の出庫量
最大在庫量
在庫管理問題 >経済発注量モデル
36. 生産時間を考慮した場合の最適化
⚫ 微分法による求解
⚫ 目的関数のQによる微分
⚫
⚫ z’(Q*) = 0 を解くと
⚫
⚫ d=Q/Tより
⚫
⚫ z(Q) にQ*を代入して
⚫
⚫ 最適解の性質
⚫ p → ∞ の極限を考える
⚫
⚫
⚫
⚫ p → d の極限を考える
⚫
⚫
⚫
( )
2
1
)( 2
2
1 pdc
Q
dc
Qz
−
+−=
( )pdc
dc
Q
−
=
1
2
*
2
1
( )dpdccz −= 12* 21
( )dpdc
c
T
−
=
1
2
*
2
1
2
12
*
c
dc
Q →
dccz 212*→
dc
c
T
2
12
* →
→*Q
0*→z
→*T
在庫管理問題 >経済発注量モデル
37. c3
不足損失の考慮
⚫ 経済発注量モデルの拡張
⚫ 受注残を許し次回納品時に出庫
⚫ 不足量に違反金を設定
⚫ 不足量×不足時間に比例
⚫
⚫
⚫
⚫
在庫管理問題 >経済発注量モデル
発
注
量
Q
発注間隔T
在庫レベル
平均在庫量c2
需要量d(傾き)
平均不足量
( )
( )
Q
SQTc
SQ
Q
SQT
c
2
2
2
3
3
−
−
−
損失費用:
平均不足量:
不足時間:
不足損失:
Q
TSc
S
Q
TS
c
2
2
2
2
2
在庫費用:
平均在庫量:
在庫時間:
在庫費用:
在
庫
量
S
c1
在庫時間
TS/Q
不足時間
T(Q – S)/Q
38. 不足損失の考慮した場合の最適化
⚫ 微分法による求解
⚫ SとQによる目的関数
⚫
⚫ Sに対する偏導関数
⚫
⚫ Qに対する偏導関数
⚫
( )
Q
SQc
Q
Sc
Q
dc
QSz
22
),(
2
3
2
21 −
++=
( ) ( )
2
2
33
2
2
2
2
1
22
),(
Q
SQc
Q
SQc
Q
Sc
Q
dc
Q
QSz −
−
−
+−−=
( )
Q
SQc
Q
Sc
S
QSz −
−=
32),(
目的関数
0
200
400
600
800
1000
1200
1400
1600
1800
2000
2200
2400
2600
2800
3000
3200
3400
3600
3800
4000
200
2200
0
20000
40000
60000
80000
100000
120000
140000
160000
180000
200000
在庫管理問題 >経済発注量モデル
d = 200
c1 = 200000
c2 = 20
c3 = 200
S* = 1907
Q* = 2098
Q* – S* = 191
×
39. 32
3
2
1* 2
cc
c
c
dc
S
+
=
( ) ( ) 022
2**
3
***
3
2*
21 =−−−+−− SQcSQQcScdc
( ) ( ) *
3
2***
3
32*
*
**
3
*
*
2
,0 S
c
c
SQS
c
cc
Q
Q
SQc
Q
Sc
=−
+
=→=
−
−
不足損失の考慮した場合の最適化
⚫ S、Qの偏導関数が0の時が最適解
⚫ Sによる偏導関数=0より、
⚫
⚫ Qによる偏導関数=0に代入すると
⚫
⚫
⚫ →
( ) 0
2
2 2*
3
2
22*
3
3222*
21 =−
+
+−− S
c
c
S
c
ccc
Scdc
3
32
2
1* 2
c
cc
c
dc
Q
+
=
2
1**
3
2
c
dc
QS
c
==
→ ならば
在庫管理問題 >経済発注量モデル
40. 不足損失の考慮した場合の最適化
⚫ 最適解の目的関数値の計算
( )
( )
( )
32
3
21
32
3
2
1
2
2
3
2
2322
3
32
2
3
22
2
3
2
32
2
2
2
*
2**
3
*
2*
2
*
1**
2
2
22222
222
22
),(
cc
c
dcc
cc
c
c
dc
c
abc
c
bccabcabc
c
abcabcabc
a
bab
c
c
c
a
babc
a
bac
Q
SQc
Q
Sc
Q
dc
QSz
+
=
+
=
=
+
+=++=
++=
−
++=
ab
c
c
SQ
b
a
QabS
cc
c
b
c
dc
a
3
2**
**
32
3
2
1
,
,
2
=−
==
+
==
と置くと、
在庫管理問題 >経済発注量モデル
dccz
c
21
*
3
2=
→ ならば
43. 新聞売り子問題
⚫ 不確定需要に対して在庫を決定する問題
⚫ 需要予測に基づき新聞の最適発注量を決定
⚫ 新聞を前日に発注
⚫ 売残りは全て損失
⚫ 具体的な問題設定
⚫ 仕入価格30円、販売価格120円、利益90円
⚫ 仕入部数をb、販売可能部数をsとする
⚫ 利益を表す目的関数z
▪
⚫ 仕入部数b = 販売可能部数s で目的関数z最大
在庫管理問題 > 新聞売り子問題
( )
( )
−
−
=
bsbb
bsbs
z
30120
30120 仕入れが過剰の場合
仕入れが不足の場合
46. 新聞売り子問題の最適化
⚫ 目的関数を微分法で最適化
⚫ 目的関数を微分すると
⚫
⚫ 導関数=0となるのは
⚫ 90 – 30b = 0 より b = 75
⚫ – 30 より解無し
⚫ 最適解は
⚫ 仕入部数は75部
⚫ 目的関数値は3375円
在庫管理問題 > 新聞売り子問題
( )
( )
−
−
=
10030
1002.190
)(
b
bb
bz
0 20 40 60 80 100 120
販売可能部数 / 仕入れ部数
0
500
1000
1500
2000
2500
3000
3500
4000
4500
5000
利益
0.0%
1.0%
2.0%
3.0%
4.0%
5.0%
確率 利益確率
販売可能部数の確率分布と
仕入部数に対する利益の期待値
48. モンテカルロ法の例
在庫管理問題 > 新聞売り子問題 > シミュレーション
1│#include <stdlib.h>
2│
5│int main(int argc, char* argv[]) {
7│ int n = atoi(argv[1]); /* 試行回数の取得 */
9│
10│ srand(time(NULL)); /* 乱数の種を時刻で設定 */
11│
12│ for (i = 0 ; i < n ; i++) {
13│ x = rand01(); /* x座標の取得 */
14│ y = rand01(); /* y座標の取得 */
15│ if (x * x + y * y <= 1.0) /* 半径1以内の点を選択 */
16│ m++;
17│ }
18│ printf(“pi = %g¥n”, 4.0 * m / n); /* 結果の出力 */
19│}
20│
21│double rand01(void) { /* 0-1の乱数を発生 */
22│ return (double) rand() / (RAND_MAX + 1.0);
23│}
49. 新聞売り子問題への適用
⚫ 販売可能部数が正規分布を成す場合
⚫ 関数が複雑で解析的に積分は不可
⚫ モンテカルロ法で求解
⚫ 正規分布を発生する関数を使用
▪ 平均50、標準偏差10
⚫ シミュレーションの結果
⚫ 仕入部数は約56
⚫ 利益は4072円
0.0%
1.0%
2.0%
3.0%
4.0%
5.0%
0 20 40 60 80 100 120
販売可能部数 / 仕入れ部数
確率
0
500
1000
1500
2000
2500
3000
3500
4000
4500
5000
利益利益確率
販売可能部数の確率分布の平
均値は同じ50でも一様分布の場
合と比べて利益は増加
在庫管理問題 > 新聞売り子問題 > シミュレーション
50. プログラムの例
在庫管理問題 > 新聞売り子問題 > シミュレーション
4│int main(int argc, char* argv[]) {
8│ for (buy = 0 ; buy <= 120 ; buy++) { /* 仕入部数のループ */
9│ profit = simulate(buy, n); /* シミュレーションの実行 */
10│ printf("buy %3d : profit %5d¥n", buy, profit);
11│ }
12│}
13│int simulate(int buy, int n) { /* シミュレーションを実行する */
17│ for (i = 0 ; i < n ; i++) { /* n回の試行のループ */
18│ sell = randn() * 10 + 50; /* 販売可能部数の生成 */
19│ sum += profit(buy, sell); /* 利益の計算と足しこみ */
20│ }
21│ return (int) (sum / n); /* 平均値を戻す */
22│}
23│int profit(int buy, int sell) { /* 利益を計算する関数 */
24│ if (sell <= buy) /* 販売可能部数が仕入以下 */
25│ return 120 * sell - 30 * buy;
26│ else /* 販売可能部数が仕入より多 */
27│ return 120 * buy - 30 * buy;
28│}
randn()は平均0、標
準偏差1の乱数を
発生させる関数
52. 計算オーダー
⚫ アルゴリズムの計算量を表す方法
⚫ 問題を大規模にする場合の計算量で表現
⚫ 計算量がan2+bn+cの場合→O(n2)
▪ nが大きくなるとbn+cの項は影響が相対的に小さくなる
⚫ n語載っている辞書から単語を探す場合
⚫ 逐次探索法 O(n)
⚫ 二分探索法 O(logn) ←高速なアルゴリズム
⚫ ソート(並べ替え)のアルゴリズム
⚫ バブルソート O(n2)
⚫ クイックソート O(nlogn) ←高速なアルゴリズム
⚫ 巡回セールスマン問題
⚫ 列挙法 O(n!)
組合せ最適化問題
53. NP困難
⚫ クラスP (Polynomial, 多項式)
⚫ 計算量が多項式時間O(nk)の解法が存在する問題
⚫ クラスNP (Non-deterministic Polynomial, 非決定性多項式)
⚫ 非決定性アルゴリズムで計算量が多項式時間となる問題
⚫ 非決定性:選択肢を1つに決めずに同時に探索する方法
⚫ 現実のコンピューターでは実現不可能な方法
⚫ NP困難
⚫ クラスNPに属する問題かそれ以上に困難であること
⚫ NP困難な問題は多項式時間では解けないと“予測”されている
1
2
3 4
・・・
全ての枝分れを
同時に探索を行
う方法
組合せ最適化問題
57. プログラムの例
⚫ プログラムの概要
⚫ 標準入力より荷物のサイズを読み込む
⚫ 容器のサイズを100とする
⚫ ファースト・フィット・ディクリージング法を適用
⚫ プログラムの構成
⚫ ヘッダーファイル
⚫ bp.h
⚫ メイン関数
⚫ bp.c
⚫ サブ関数
⚫ get_data.c, print_bin.c, sol_const.c, sort_item.c
⚫ プログラムの生成
⚫ gcc bp.c get_data.c print_bin.c sol_const.c sort_item.c -o bp.exe
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
58. bp.h:共通ヘッダーファイル
1|#include <stdlib.h>
2|#include <math.h>
3|
4|#ifdef MAIN
5|#define DEF
6|#else
7|#define DEF extern
8|#endif
9|
10|void get_data(void);
11|void sort_item(void);
12|void print_bin(void);
13|void sol_const(void);
14|
15|#define BIN_SIZE 100.0
16|#define BIN_NUM_MAX 100000
17|#define ITEM_NUM_MAX 100000
18|
19|DEF int bin_n; /* 容器の数 */
20|DEF int bin_item_n[BIN_NUM_MAX]; /* 容器の荷物の数 */
21|DEF double bin_size[BIN_NUM_MAX]; /* 容器に詰められた大きさ */
22|
23|DEF int item_n; /* 荷物の数 */
24|DEF int item_bin[ITEM_NUM_MAX]; /* 荷物を入れた容器 */
25|DEF double item_size[ITEM_NUM_MAX]; /* 荷物の大きさ */
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
59. bp.c:メイン関数
1|#define MAIN
2|
3|#include "bp.h"
4|
5|int main(int argc, char* argv[]) {
6| get_data(); /* データの読み込み */
7| sort_item(); /* 荷物のソート */
8| sol_const(); /* 解の生成 */
9| print_bin(); /* 解の印刷 */
10|
11| return 0;
12|}
1|#include "bp.h"
2|
3|void get_data(void) {
4| double size;
5|
6| while (scanf("%lf", &size) > 0) {
7| item_bin[item_n] = -1; /* まだ容器には入れない */
8| item_size[item_n] = size; /* 荷物のサイズの設定 */
9| item_n++; /* 荷物の数 */
10| }
11|}
get_data.c:データの読込み関数
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
60. sort_item.c:荷物のソート関数
1|#include "bp.h"
2|
3|void sort_item(void) {
4| int i1, i2;
5| double size;
6|
7| for (i1 = 0 ; i1 < item_n - 1 ; i1++) {
8| for (i2 = item_n - 1; i2 > i1 ; i2--) {
9| if (item_size[i2] < item_size[i2+1]) {
10| size = item_size[i2];
11| item_size[i2] = item_size[i2+1];
12| item_size[i2+1] = size;
13| }
14| }
15| }
16|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
61. sol_const.c:解の生成関数
1|#include "bp.h"
2|
3|void sol_const(void) {
4| int b, i;
5| int b_max = 0;
6|
7| for (i = 0 ; i < item_n ; i++) { /* 荷物の処理 */
8| for (b = 0 ; b < BIN_NUM_MAX ; b++) { /* 各容器を順に処理 */
9| /* 空き容量の検査 */
10| if (bin_size[b] + item_size[i] <= BIN_SIZE) {
11| bin_item_n[b]++; /* 容器内の数 */
12| bin_size[b] += item_size[i]; /* 容器の容量 */
13| item_bin[i] = b; /* 容器の割当て */
14|
15| if (b_max < b) /* 使用した容器の数 */
16| b_max = b;
17|
18| break;
19| }
20| }
21| }
22|
23| bin_n = b_max+1;
24|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
62. print_bin.c:解の表示関数
1|#include "bp.h"
2|
3|void print_bin(void) {
4| int b, i, avg_n = 0;
5| double avg = 0.0;
6|
7| for (b = 0 ; b < bin_n ; b++) {
8| if (bin_item_n[b] <= 0)
9| continue;
10|
11| avg_n++;
12| avg += bin_size[b]/BIN_SIZE;
13|
14| printf("[%4d] %.3f", b, bin_size[b]/BIN_SIZE);
15| for (i = 0 ; i < item_n ; i++) {
16| if (item_bin[i] == b)
17| printf(" %3d", i);
18| }
19| printf("¥n");
20| }
21| printf("[ avg] %.3f", avg/avg_n);
22|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
63. プログラムの実行例
> bp_nosort < input.txt
[ 0] 0.940 23 1 27 28 3 12
[ 1] 0.990 37 22 40
[ 2] 0.960 46 30 20
[ 3] 0.930 36 33 24
[ 4] 0.820 44 38
[ 5] 0.590 38 21
[ 6] 0.480 48
[ avg] 0.816
> bp < input.txt
[ 0] 0.980 48 46 3 1
[ 1] 0.960 44 40 12
[ 2] 1.000 38 38 24
[ 3] 1.000 37 36 27
[ 4] 0.910 33 30 28
[ 5] 0.860 23 22 21 20
[ avg] 0.952
23 1 27 28 37 22 40 3 46 30 36 33 20 24 44 12 38 38 21 48
ソートしない場合の例
容器が一つ余分に
必要になっている
非常に高い充填率
になっている
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
入力ファイル
input.txt
64. 改善法による解法
⚫ 近傍探索法による改善
⚫ 貪欲方で高速に初期解を生成
⚫ 小規模な改善(近傍操作)を繰り返し適用
⚫ 改善可能な近傍操作がなくなるまで継続
組合せ最適化問題 > 改善法
局所最適解
(近傍内に良い解が無い)
初期解
近傍操作
その近傍
改善された解
その近傍
初期解作成
近傍操作有
近傍操作適用
解が改善?
近傍操作復元
近傍探索終了
Yes
Yes
No
No
近傍探索処理の
フローチャート
67. ビンパッキング問題への適用
⚫ 近傍操作の定義
⚫ 移動近傍
⚫ 荷物を他の容器へ移動
⚫ 交換近傍
⚫ 荷物を容器間で交換
⚫ その他の近傍
⚫ 3個の荷物の回転交換
⚫ 移動と交換の組合せ
⚫ 近傍が広くなると⇒
良い解に早く到達 or
探索時間が長くなる
移動
交換
i1
i1
i2
i1
i2
i1
b1 b2 b1 b2
b1 b2 b1 b2
組合せ最適化問題 > ビンパッキング問題 > 改善法
68. プログラムの例
⚫ プログラムの概要
⚫ 移動と交換の近傍操作を適用
⚫ 変更のあった容器を管理し効率よく探索を行う
⚫ プログラムの構成
⚫ ヘッダーファイル
⚫ bp.h
⚫ メイン関数
⚫ bp.c
⚫ サブ関数
⚫ get_data.c, print_bin.c, sol_const.c, sort_item.c,
⚫ 近傍探索処理関数
⚫ local_search_queue.c, local_search.c,
try_local_operation.c, local_opearation.c,
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
69. bp.h:共通ヘッダーファイル
1|#include <stdio.h>
2|#include <stdlib.h>
3|#include <math.h>
4|
5|#ifdef MAIN
6|#define DEF
7|#else
8|#define DEF extern
9|#endif
10|
11|#define bool int
12|#define true 1
13|#define false 0
14|
15|#define BIN_SIZE 100.0
16|#define BIN_NUM_MAX 100000
17|#define ITEM_NUM_MAX 100000
18|
19|void get_data(void);
20|void sort_item(void);
21|void print_bin(void);
22|void sol_const(void);
23|/* 一つの容器の目的関数値の計算式 */
24|#define calc_z(b) (sqrt(bin_size[b]/BIN_SIZE))
25|
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
70. 26|void local_search(void);
27|void try_operation(int i);
28|int q_n(void);
29|void enq_all(void);
30|void enq_bin(int b);
31|void enq(int i);
32|int deq(void);
33|bool move(int i, int b);
34|bool swap(int i1, int i2);
35|
36|DEF int bin_item_n[BIN_NUM_MAX];
37|DEF int bin_n;
38|DEF double bin_size[BIN_NUM_MAX];
39|DEF int item_n;
40|DEF double item_size[ITEM_NUM_MAX];
41|DEF int item_bin[ITEM_NUM_MAX];
42|DEF double z;
43|DEF int n;
44|DEF double z_bin[BIN_NUM_MAX];
45|DEF int ls_item_q[ITEM_NUM_MAX];
46|DEF int ls_item_f[ITEM_NUM_MAX];
47|DEF int ls_item_n;
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
71. bp.c:メイン関数
1|#define MAIN
2|#include "bp.h"
3|int main() {
4| get_data(); /* データの読みこみ */
5| sort_item(); /* 降順のソート */
6| sol_const(); /* ファースト・フィット法による初期解作成 */
7| print_bin(); /* 初期解の出力 */
8| local_search(); /* 近傍探索の実行 */
9| print_bin(); /* 結果の出力 */
10| return 0;
11|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
get_data.c:データの読込み関数
sort_item.c:荷物のソート関数
print_bin.c:解の表示関数
貪欲法のプログラムと同一
貪欲法のプログラムと同一
貪欲法のプログラムと同一
72. sol_const.c:初期解作成関数
1|#include "bp.h"
2|
3|void sol_const(void) {
4| int b, i;
5| int b_max = 0;
6|
7| for (i = 0 ; i < item_n ; i++) {
8| for (b = 0 ; b < bin_n ; b++) {
9| if (bin_size[b] + item_size[i] <= BIN_SIZE) {
10| bin_item_n[b]++;
11| bin_size[b] += item_size[i];
12| item_bin[i] = b;
13| if (b_max < b)
14| b_max = b;
15| break;
16| }
17| }
18| }
19|
20| n = bin_n = b_max + 1;
21|
22| /* 目的関数値の計算 */
23| for (b = 0 ; b < bin_n ; b++)
24| z += z_bin[b] = calc_z(b);
25|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
73. local_search_queue.c:待ち行列処理関数
1|#include "bp.h"
2|
3|int q_n(void) { /* que内の荷物の数 */
4| return ls_item_n;
5|}
6|
7|void enq_all(void) { /* 全荷物のqueへの追加 */
8| int i;
9| for (i = 0 ; i < item_n ; i++)
10| enq(i);
11|}
12|
13|void enq_bin(int b) { /* 容器b内の全荷物の追加 */
14| int i;
15| for (i = 0 ; i < item_n ; i++)
16| if (item_bin[i] == b)
17| enq(i);
18|}
19|
20|void enq(int i) { /* 荷物iの追加 */
21| if (ls_item_f[i]) return; /* すでにque内ならば */
22|
23| ls_item_f[i] = 1; /* que内にある目印 */
24| ls_item_q[ls_item_n++] = i; /* queの最後に追加 */
25|}
26|
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
74. local_search.c:近傍探索メイン関数
1|#include "bp.h"
2|
3|void local_search(void) {
4| int i;
5|
6| enq_all(); /* 全ての荷物をqueへ追加 */
7|
8| while (q_n() > 0) { /* queが空になるまで */
9| i = deq(); /* 近傍操作対象の取得 */
10| try_operation(i); /* 近傍操作の試行 */
11| }
12|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
27|int deq(void) { /* 荷物をランダムに除去 */
28| int i, r;
29|
30| i = ls_item_q[r = rand() % ls_item_n];
31| ls_item_q[r] = ls_item_q[--ls_item_n];
32| ls_item_f[i] = 0; /* queから除去された印 */
33|
34| return i;
35|}
75. try_operation.c:近傍操作試行関数
1|#include "bp.h"
2|
3|void try_operation(int i1) {
4| int i2;
5| int b1, b2;
6| double z_old;
7|
8| /* 移動近傍操作の試行 */
9| for (b2 = 0; b2 < bin_n ; b2++) {
10| b1 = item_bin[i1];
11|
12| z_old = z; /* 試行前の目的関数値の保管 */
13|
14| if (move(i1, b2) == false) /* 操作の実行 */
15| continue;
16|
17| if (z < z_old) { /* 解が改善されたならば */
18| printf("OK move(%4d,%4d) z=%4d, %.8f¥n", i1, b2, n, z);
19| enq_bin(b1); /* 関連する容器の荷物をenq */
20| enq_bin(b2); /* 関連する容器の荷物をenq */
21| continue;
22| }
23|
24| move(i1, b1); /* 解を元に復元する */
25| }
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
76. 26|
27| /* 交換近傍操作の試行 */
28| for (i2 = 0; i2 < item_n ; i2++) {
29| b1 = item_bin[i1];
30| b2 = item_bin[i2];
31|
32| z_old = z; /* 試行前の目的関数値の保管 */
33|
34| if (swap(i1, i2) == false) /* 操作の実行 */
35| continue;
36|
37| if (z < z_old) { /* 解が改善されたならば */
38| printf("OK swap(%4d,%4d) z=%4d, %.8f¥n", i1, i2, n, z);
39| enq_bin(b1); /* 関連する容器の荷物をenq */
40| enq_bin(b2); /* 関連する容器の荷物をenq */
41| continue;
42| }
43|
44| swap (i1, i2); /* 解を元に復元する */
45| }
46|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
77. local_operation.c:近傍操作処理関数
3|/* 移動近傍操作関数 */
4|bool move(int i, int b2) { /* 荷物iを容器b2へ移動 */
5| int b1 = item_bin[i];
6|
7| if (b1 == b2 /* 無効な操作の検査 */
8| || bin_size[b2] + item_size[i] > BIN_SIZE
9| || bin_item_n[b2] == 0) return false;
10|
11| item_bin[i] = b2;
12|
13| bin_size[b1] -= item_size[i];
14| bin_size[b2] += item_size[i];
15|
16| bin_item_n[b1] -= 1;
17| bin_item_n[b2] += 1;
18|
19| if (bin_item_n[b1] == 0) bin_size[b1] = 0.0;
20|
21| if (bin_item_n[b1] == 0) n--;
22| if (bin_item_n[b2] == 1) n++;
23|
24| /* 目的関数値の更新 */
25| z -= z_bin[b1]; /* 古い値を引く */
26| z -= z_bin[b2]; /* 古い値を引く */
27| z += z_bin[b1] = calc_z(b1); /* 新しい値を足す */
28| z += z_bin[b2] = calc_z(b2); /* 新しい値を足す */
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
78. 29|
30| return true;
31|}
32|
33|/* 交換近傍操作関数 */
34|bool swap(int i1, int i2) { /* 荷物i1とi2の交換 */
35| int b1 = item_bin[i1];
36| int b2 = item_bin[i2];
37|
38| if (b1 == b2 /* 無効な操作の検査 */
39| || bin_size[b1] - item_size[i1] + item_size[i2] > BIN_SIZE
40| || bin_size[b2] - item_size[i2] + item_size[i1] > BIN_SIZE)
41| return false;
42|
43| item_bin[i1] = b2;
44| item_bin[i2] = b1;
45|
46| bin_size[b1] += item_size[i2] - item_size[i1];
47| bin_size[b2] += item_size[i1] - item_size[i2];
48|
49| /* 目的関数値の更新 */
50| z -= z_bin[b1]; /* 古い値を引く */
51| z -= z_bin[b2]; /* 古い値を引く */
52| z += z_bin[b1] = calc_z(b1); /* 新しい値を足す */
53| z += z_bin[b2] = calc_z(b2); /* 新しい値を足す */
54|
55| return true;
56|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
79. プログラムの実行例
23 23 23 23 23 23 23 23 23 1 1 1 27 27 27 27 27 27 27 28
28 28 28 37 37 37 22 22 22 22 22 22 22 22 22 22 40 40 3 3
3 3 3 46 46 46 46 46 30 30 30 30 30 36 36 36 36 36 36 36
36 33 33 33 20 20 20 20 20 20 20 24 24 24 24 24 24 24 44 44
12 12 12 12 38 38 38 38 21 21 21 21 21 48 48 48 48 48 23 23
> bp < input.txt
[ 0] 1.000 48 48 3 1
[ 1] 1.000 48 48 3 1
[ 2] 1.000 48 46 3 3
[ 3] 0.960 46 46 3 1
[ 4] 0.920 46 46
[ 5] 1.000 44 44 12
[ 6] 1.000 40 40 20
[ 7] 1.000 38 38 24
[ 8] 1.000 38 38 24
[ 9] 0.980 37 37 24
[ 10] 1.000 37 36 27
[ 11] 1.000 36 36 28
[ 12] 1.000 36 36 28
[ 13] 1.000 36 36 28
[ 14] 0.990 36 33 30
[ 15] 0.960 33 33 30
[ 16] 0.900 30 30 30
[ 17] 0.940 28 27 27 12
[ 18] 0.930 27 27 27 12
[ 19] 0.990 27 24 24 24
[ 20] 0.930 24 23 23 23
[ 21] 0.920 23 23 23 23
[ 22] 0.920 23 23 23 23
[ 23] 1.000 22 22 22 22 12
[ 24] 0.880 22 22 22 22
[ 25] 0.860 22 22 21 21
[ 26] 0.830 21 21 21 20
[ 27] 1.000 20 20 20 20 20
OK swap( 65, 33) z= 28, 27.43987621
OK swap( 65, 34) z= 28, 27.43863405
OK swap( 65, 70) z= 28, 27.43844417
OK swap( 54, 34) z= 28, 27.43795393
OK swap( 54, 35) z= 28, 27.43530780
OK swap( 54, 55) z= 28, 27.43456598
OK swap( 29, 42) z= 28, 27.43440765
OK swap( 7, 55) z= 28, 27.43293622
OK move( 65, 3) z= 28, 27.42733747
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
初期解
80. OK swap( 65, 42) z= 28, 27.42657461
OK swap( 65, 70) z= 28, 27.42629759
OK swap( 8, 7) z= 28, 27.42629759
OK swap( 8, 9) z= 28, 27.42629759
OK swap( 8, 28) z= 28, 27.42453614
OK swap( 65, 50) z= 28, 27.42448499
OK swap( 65, 70) z= 28, 27.42443305
OK swap( 63, 51) z= 28, 27.42440767
OK swap( 59, 35) z= 28, 27.42383102
OK swap( 59, 70) z= 28, 27.42360594
OK move( 74, 24) z= 28, 27.42192340
OK swap( 74, 30) z= 28, 27.41824097
OK swap( 74, 78) z= 28, 27.41799610
OK move( 59, 15) z= 28, 27.41655050
OK swap( 59, 52) z= 28, 27.41649935
OK swap( 59, 71) z= 28, 27.41642203
OK move( 76, 9) z= 28, 27.38661279
OK swap( 76, 53) z= 28, 27.38645203
OK swap( 76, 74) z= 28, 27.38615114
OK swap( 76, 75) z= 28, 27.38395314
OK swap( 76, 82) z= 28, 27.38163080
OK swap( 44, 63) z= 28, 27.38107736
OK swap( 60, 53) z= 28, 27.38102621
OK swap( 60, 71) z= 28, 27.38097427
OK swap( 60, 90) z= 28, 27.38067187
OK swap( 44, 18) z= 28, 27.38010416
OK swap( 44, 28) z= 28, 27.37628361
OK swap( 44, 71) z= 28, 27.37182493
OK move( 75, 4) z= 28, 27.36765805
OK move( 82, 26) z= 28, 27.30292116
OK swap( 82, 18) z= 28, 27.30192830
OK swap( 82, 77) z= 28, 27.29642284
OK swap( 82, 90) z= 28, 27.23876419
OK swap( 32, 82) z= 28, 27.23849157
OK swap( 75, 65) z= 28, 27.23843251
OK swap( 5, 7) z= 28, 27.23843251
OK move( 90, 14) z= 27, 26.95393920
[ 0] 1.000 48 48 3 1
[ 1] 1.000 48 48 3 1
[ 2] 1.000 48 46 3 3
[ 3] 1.000 46 27 23 3 1
[ 4] 0.910 46 23 22
[ 5] 1.000 44 44 12
[ 6] 1.000 40 40 20
[ 7] 1.000 38 38 24
[ 8] 1.000 38 38 24
[ 9] 1.000 37 36 27
[ 10] 1.000 37 36 27
[ 11] 1.000 36 36 28
[ 12] 1.000 36 36 28
[ 13] 1.000 36 36 28
[ 14] 1.000 46 22 20 12
[ 15] 1.000 33 24 22 21
[ 16] 1.000 46 30 24
[ 17] 1.000 33 28 27 12
[ 18] 1.000 27 27 23 23
[ 19] 1.000 30 27 22 21
[ 20] 1.000 30 24 23 23
[ 21] 1.000 30 24 23 23
[ 22] 1.000 30 24 23 23
[ 23] 1.000 22 22 22 22 12
[ 24] 1.000 33 23 22 22
[ 26] 1.000 37 21 21 21
[ 27] 1.000 20 20 20 20 20
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
局所最適解
容器25が
不要になっ
ている