SlideShare a Scribd company logo
整数計画問題
⚫ 決定変数に整数制約が付いた線形計画問題
⚫ 整数計画問題 (Integer Programming, IP)
⚫ 決定変数が整数に限定され、4.5といった小数を許さない
⚫ 整数の組合せの探索が必要になり膨大な探索が必要
⚫ シンプレックス法の様な万能の手法は存在しない
⚫ 整数計画問題のバリエーション
⚫ 混合整数計画問題 (Mixed Integer Programming, MIP)
▪ 決定変数に実数と整数の両方がある問題
⚫ 0-1問題
▪ 整数計画問題のうち決定変数が0, 1に限定されている問題
整数計画問題
線形計画問題との比較
⚫ 線形計画問題と根本的に異なる問題
⚫ 最適解を整数化するのでは
不可
⚫ 実数時の最適解s1
⚫ (3.7, 3.3)
⚫ 小数部を切り捨てたs2
⚫ (3, 3)
⚫ 真の最適解はs3
⚫ (1, 4)
整数計画問題
0 1 2 3 4 5
1
2
3
4
5
s1
s3
s2
サラダパック問題
⚫ 栄養素を摂取しつつカロリーを最小化
⚫ ポテトサラダ、グリーンサラダの摂取量を決定
⚫ ただし、サラダは1パック100g単位でのみ摂取可能
⚫ 各栄養素は摂取目標以上
⚫ 総カロリーを最小化する
ポテトサラダ(100g) グリーンサラダ(100g) 摂取目標
ビタミンC(mg) 5 2.5 25
カルシウム(mg) 20 50 300
食物繊維(g) 0.5 4 12
カロリー(kcal) 100 80 最小化
整数計画問題 > サラダパック問題
制約条件と実行可能領域
⚫0 ⚫5 ⚫10 ⚫15 ⚫20 ⚫25
⚫ポテトサラダ(100g)
⚫2
⚫4
⚫6
⚫8
⚫10
⚫グリーンサラダ(100g)
x2
x1
⚫食物繊維
⚫カルシウム
⚫ビタミンC
実行可能領域
整数計画問題 > サラダパック問題
目的関数
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
整数計画問題 > サラダパック問題
ナップサック問題
⚫ 限られた投資で最大の利益を得る組合せを求め
る
⚫ 典型的な組合せ最適化問題
⚫ 決定変数
⚫ 多数の投資対象のどれを選択するかを決定
⚫ 制約条件
⚫ 必要な投資と得られる利益が定められている
⚫ 投資金額の合計は総資金以下
⚫ 目的関数
⚫ 利益が最大となる投資対象を選択
整数計画問題 > ナップサック問題
ナップサック問題の定式化
⚫ ナップサック問題の
⚫ 決定変数
⚫ 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
整数計画問題 > ナップサック問題
ナップサック問題の具体例
⚫ ナップサックに非常食を詰める
⚫ 重量制限の範囲内でなるべく高カ
ロリーに詰める
⚫ 決定変数:詰めるか否か
⚫ xi = {0,1} iは1から8
⚫ 定数
⚫ li 重量
⚫ wi カロリー
⚫ 制約条件:総重量は10kg以下
⚫ ∑lixi ≦ 10
⚫ 目的関数:総カロリー最大化
⚫ z = ∑ wixi 総カロリー
非常食 重量 カロリー
1 4 20
2 6 32
3 3 16
4 2 12
5 1 5
6 5 20
7 2 3
8 3 4
合計 10 最大化
整数計画問題 > ナップサック問題
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
⚫ 最適化結果
整数計画問題 > ナップサック問題
貪欲法による解法
⚫ 組合せ問題の近似解法
⚫ 効率の良い順に選択
⚫ 目先の利益を追求
⚫ 手戻りや後先を考えない
⚫ 最も単純な近似解法
⚫ ナップサック問題に適用
⚫ カロリー/重量で並べ替え
⚫ 重量制約の範囲で選択
整数計画問題 > ナップサック問題
非常食 重量
カロ
リー
効率 重量
カロ
リー
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
整数計画問題に対する手法
⚫ 整数により問題の組合せが発生
⚫ 万能で高速な手法は存在しない
⚫ それぞれの問題に応じた手法が有効
⚫ 一般的な手法としては以下が挙げられる
⚫ 近似解法
▪ 貪欲法や、発見的手法と呼ばれる様々な手法がある
⚫ 厳密解法
▪ 列挙法
▪ 原則的に全ての組合せを列挙
▪ 分枝限定法
▪ 列挙法の無駄な探索を種々の工夫で削減
整数計画問題
列挙法による解法
⚫ 全ての組合せを列挙する
⚫ 制約を満たす範囲で探索
⚫ 制約を満たせなければ終了
⚫ 計算量は膨大
⚫ 例題では最大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
列挙法のプログラム
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より
探索の開始
整数計画問題 > 列挙法
列挙法のプログラム(続き)
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
⚫ 再帰呼出による実装
⚫ 選択・非選択を再帰呼出
⚫ 最終レベルまで繰り返す
整数計画問題 > 列挙法
次のレベル
分枝限定法
⚫ 分枝限定法の考え方
⚫ 基本的には列挙法
⚫ 全ての組合せを列挙する
⚫ 無駄な列挙を省く
⚫ 緩和問題により上限値を計算
⚫ ある分枝方向の上限値が既存の解
以下なら探索を省略
⚫ 緩和問題
⚫ 元の問題の制約を取り除いた問題
⚫ 整数制約を取り除き簡単にする
⚫ 元問題の最適値の上限を与える
整数計画問題 > 分枝限定法
重量
カロ
リー
重量
カロ
リー
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個を選択
分枝限定法
⚫ 深さ優先
⚫ 左(選択)優先
レ
ベ
ル
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
分枝限定法のプログラム
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. }
整数計画問題 > 分枝限定法
分枝限定法のプログラム(続き)
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
この部分のみを充填
倉庫選択問題
⚫ 倉庫を取捨選択しコストを最小化
⚫ 倉庫の選択と輸送量を決定する
⚫ 倉庫の供給能力に余裕がある
⚫ 輸送コストと倉庫の固定費を勘案
⚫ 決定変数
⚫ 倉庫の選択と各輸送量
⚫ 制約条件
⚫ 倉庫が使用される場合に固定費
⚫ 目的関数
⚫ 輸送コスト+倉庫の固定費
整数計画問題 > 倉庫選択問題
D1
D2
D3
S1
S2
S3
S4
倉庫 店舗
x11
x12
輸送コスト表と輸送量
コ
ス
ト
倉庫\店舗 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
線形計画問題 > 倉庫選択問題
倉庫選択問題の定式化
⚫ 倉庫の存続を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にコストが設定)
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
輸送スケジュール問題
⚫ 工場から倉庫への輸送スケジュールを最適化
⚫ 倉庫A, B, Cへ製品を輸送
⚫ 輸送量はトラックで42, 25, 10回分
⚫ トラックはピストン輸送をする
⚫ 移動時間
⚫ 往復時間が右図で与えられる
⚫ トラックは最大9時間稼働
⚫ トラックのコスト
⚫ 10万円+1万円×稼働時間(h)
整数計画問題 > 輸送スケジュール問題
3h
C
4h
A
B
5h
トラックの輸送パターン
パターン 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
整数計画問題 > 輸送スケジュール問題
輸送スケジュール問題の定式化
⚫ 集合分割問題として定式化
⚫ 決定変数
⚫ 各輸送パターンの車両数
⚫ 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
整数計画問題 > 輸送スケジュール問題
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
整数計画問題 > 輸送スケジュール問題
整数計画法の典型的な定式化
⚫ 固定費
⚫ 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変数
整数計画問題
整数計画法の典型的な定式化
⚫ 集合分割問題
⚫ 行の成分を分割するように
複数の列を選択
⚫ 重複した選択を許さない
⚫ 集合被覆問題
⚫ 行の成分を覆うように複数
の列を選択
⚫ 行の成分が条件を超える
のは問題ない
整数計画問題
最小化で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
在庫管理問題
⚫ 製品や部品の在庫量、発注間隔などを最適化
⚫ 需要と供給の緩衝材として在庫が必要
⚫ 製品需要は不確定要素が高い
⚫ 製品はまとめて生産した方が効率が良い
⚫ 在庫は現金を寝かせておくのと同じ
⚫ その現金を他に投資すれば得られたはずの機会損失
⚫ 投資なるべく早く回収(キャッシュフロー最大化)
⚫ 経済発注量モデルを基本に多くのバリエーション
⚫ 確定型モデル
⚫ 確率型モデル
在庫管理問題
経済発注量モデル
⚫ 経済発注量モデル
⚫ 最も基本的な在庫管理問題
⚫ 次の仮定の下でコスト最小化
⚫ 製品をQ発注し倉庫に在庫
⚫ 一定量dで倉庫から出荷
⚫ 期間T後に次の発注
⚫ 発注には発注費用c1
⚫ 在庫には在庫費用c2
⚫ 総費用を最小化する発注量Qを
決定する
在庫管理問題 >経済発注量モデル
発
注
量
Q
発注間隔T
在庫レベル
時間
需要量d(傾き)
Q:発注量
T:発注間隔
d:需要量(d=Q/T)
c1:発注費用
c2:在庫費用
経済発注量モデルの定式化
⚫ 発注間隔での平均費用を最小化
⚫ 期間Tの費用から平均費用を求める
⚫ 平均在庫量 :
⚫ 在庫費用 :
⚫ 発注費用 :
⚫ 合計費用 :
⚫ 平均費用 :
⚫ 目的関数
⚫ d = Q/T を利用してQの関数として表すと
⚫
2
2TQc
2
21 Qc
T
c
+
発
注
量
Q
発注間隔T
在庫レベル
平均在庫量
2
Q
2
2
1
TQc
c +
2
)( 21 Qc
Q
dc
Qz +=
1c
在庫管理問題 >経済発注量モデル
経済発注量モデルの最適化
⚫ 微分法による求解
⚫ 目的関数の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
* =
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
+
+
−
−
+++
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
生産時間の考慮
⚫ 経済発注量モデルの拡張
⚫ 製品を生産し在庫とする
⚫ 製品生産速度: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
生産完了時間
生産完了時の出庫量
 最大在庫量
在庫管理問題 >経済発注量モデル
生産時間を考慮した場合の最適化
⚫ 微分法による求解
⚫ 目的関数の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
在庫管理問題 >経済発注量モデル
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
不足損失の考慮した場合の最適化
⚫ 微分法による求解
⚫ 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
×
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
==
→ ならば
在庫管理問題 >経済発注量モデル
不足損失の考慮した場合の最適化
⚫ 最適解の目的関数値の計算
( )
( )
( )
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=
→ ならば
不確定需要に対する方策
⚫ 定量発注方式
⚫ 在庫量がある値以下になると発注
⚫ 納入までの必要量を残すように管理
⚫ 発注間隔は出庫量に左右され不定
⚫ 発注量は経済発注量モデルを参考
⚫ 例えて言うと...
⚫ 一般ユーザーの給油法
▪ 燃料計のランプが点いたら給油
▪ 給油は常に満タン
▪ 車重が重くなるのは気にしない
在庫管理問題 >定量発注方式
定量発注方式
発注水準
不確定需要に対する方策
⚫ 定期発注方式
⚫ 一定期間が来れば出庫分を補充
⚫ 間隔は経済発注量モデルを参考
⚫ 発注作業の管理が容易
⚫ 比較的高額の製品に適用
⚫ 例えて言うと...
⚫ F1での給油法
▪ 定期的に必要最小限を給油
▪ 発注費用・在庫コスト共に高価
▪ 給油回数・車重をきめ細かく管理
在庫管理問題 >定期発注方式
定期発注方式
発注間隔
新聞売り子問題
⚫ 不確定需要に対して在庫を決定する問題
⚫ 需要予測に基づき新聞の最適発注量を決定
⚫ 新聞を前日に発注
⚫ 売残りは全て損失
⚫ 具体的な問題設定
⚫ 仕入価格30円、販売価格120円、利益90円
⚫ 仕入部数をb、販売可能部数をsとする
⚫ 利益を表す目的関数z
▪
⚫ 仕入部数b = 販売可能部数s で目的関数z最大
在庫管理問題 > 新聞売り子問題
( )
( )





−
−
=
bsbb
bsbs
z
30120
30120 仕入れが過剰の場合
仕入れが不足の場合
仕入れ部数/販売可能部数/利益
在庫管理問題 > 新聞売り子問題
0
10
20
30
40
50
60
70
80
90
100
0 10 20 30 40 50 60 70 80 90 100
-3000
-2000
-1000
0
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
利益
0
10
20
30
40
50
60
70
80
90
100
仕入れ部数 / 販売可能部数
0
20
40
60
80
新聞売り子問題の最適化
⚫ 販売可能が確率分布関数で与えられる
⚫ 需要予測が以下の式で与えられるとする
⚫
⚫ P(s)は となる確率分布関数
⚫ 仕入れ部数bの場合の利益の期待値を計算
⚫
( )
( )







=
1000
10001.0
)(
s
s
sP
( )
( )





−
−
=
= 

100306000
1006.090
)(),()(
2
0
bb
bbb
dssPsbzbz
1)(0
=

sP
在庫管理問題 > 新聞売り子問題
新聞売り子問題の最適化
⚫ 目的関数を微分法で最適化
⚫ 目的関数を微分すると
⚫
⚫ 導関数=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%
確率 利益確率
販売可能部数の確率分布と
仕入部数に対する利益の期待値
シミュレーションによる最適化
⚫ モンテカルロ法によるシミュレーション
⚫ 確率分布が複雑な形状で積分不可能な場合
⚫ シミュレーションにより目的関数値を推定
⚫ 決定変数を変えながら最適な値を探索
⚫ モンテカルロ法
⚫ 乱数を用いて確率的事象を再現
⚫ 四角形内にランダムにn個の点を決定
⚫ 半径1以内の点の数mをカウント
⚫ nを増やすとm/nは面積比に近づく
▪ m/n → π/4
(x, y)
22
yxr +=
1
1
在庫管理問題 > 新聞売り子問題 > シミュレーション
モンテカルロ法の例
在庫管理問題 > 新聞売り子問題 > シミュレーション
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│}
新聞売り子問題への適用
⚫ 販売可能部数が正規分布を成す場合
⚫ 関数が複雑で解析的に積分は不可
⚫ モンテカルロ法で求解
⚫ 正規分布を発生する関数を使用
▪ 平均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でも一様分布の場
合と比べて利益は増加
在庫管理問題 > 新聞売り子問題 > シミュレーション
プログラムの例
在庫管理問題 > 新聞売り子問題 > シミュレーション
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の乱数を
発生させる関数
組合せ最適化問題
⚫ 決定変数の組合せで目的関数が決まる問題
⚫ 個々の決定変数単独で良し悪しが決まらない
⚫ 「あちらを立てれば、こちらが立たず。こちらを立てれば、
あちらが立たず。」
⚫ 最短経路問題
⚫ 2点間を結ぶ最短の道順を決定する問題
⚫ 前半の順路は後半の順路に依存しない
▪ 厳密な意味で組合せ最適化問題ではない
⚫ 巡回セールスマン問題
⚫ 複数の訪問先を最短で回る訪問順を決定する問題
⚫ 典型的な組合せ最適化問題
組合せ最適化問題
計算オーダー
⚫ アルゴリズムの計算量を表す方法
⚫ 問題を大規模にする場合の計算量で表現
⚫ 計算量がan2+bn+cの場合→O(n2)
▪ nが大きくなるとbn+cの項は影響が相対的に小さくなる
⚫ n語載っている辞書から単語を探す場合
⚫ 逐次探索法 O(n)
⚫ 二分探索法 O(logn) ←高速なアルゴリズム
⚫ ソート(並べ替え)のアルゴリズム
⚫ バブルソート O(n2)
⚫ クイックソート O(nlogn) ←高速なアルゴリズム
⚫ 巡回セールスマン問題
⚫ 列挙法 O(n!)
組合せ最適化問題
NP困難
⚫ クラスP (Polynomial, 多項式)
⚫ 計算量が多項式時間O(nk)の解法が存在する問題
⚫ クラスNP (Non-deterministic Polynomial, 非決定性多項式)
⚫ 非決定性アルゴリズムで計算量が多項式時間となる問題
⚫ 非決定性:選択肢を1つに決めずに同時に探索する方法
⚫ 現実のコンピューターでは実現不可能な方法
⚫ NP困難
⚫ クラスNPに属する問題かそれ以上に困難であること
⚫ NP困難な問題は多項式時間では解けないと“予測”されている
1
2
3 4
・・・
全ての枝分れを
同時に探索を行
う方法
組合せ最適化問題
発見的手法
⚫ 発見的手法(ヒューリスティック手法)
⚫ 経験とアイデアに基づいた近似解法
⚫ 現実的な時間内に現実的な近似解を求める
⚫ 問題に応じてそれぞれ工夫が必要
⚫ 貪欲法
⚫ 1つの選択肢に対して現状で最善の選択肢を選ぶ
⚫ 後からの手戻りは考えない
⚫ 改善法
⚫ 貪欲法等を用いて初期解を作成
⚫ 解を部分的に修正し改善を繰り返す方法
組合せ最適化問題
ビンパッキング問題
⚫ 複数の容器(ビン)に荷物を最適に詰める問題
⚫ 問題の設定
⚫ 荷物にはそれぞれのサイズが設定
⚫ 容器には最大容量が設定
⚫ 典型的な組合せ最適化問題
⚫ 部分問題に分割できない
⚫ 現実問題への適用
⚫ トラックへ荷物の割当て
⚫ コンテナへの荷物の詰め込み
⚫ 人への仕事の分配
組合せ最適化問題 > ビンパッキング問題
貪欲法による解法
⚫ ファースト・フィット・ディクリージング法
⚫ 大→小の順に整列
⚫ 容器の先頭から調べて最初に入る容器に割当
○
○
××
×
○
×
× ×
○
×
× ×
○
×
× ×
×
○
×
○
× ×
○
× × × ×
○
組合せ最適化問題 > ビンパッキング問題 > 貪欲法
プログラムの例
⚫ プログラムの概要
⚫ 標準入力より荷物のサイズを読み込む
⚫ 容器のサイズを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
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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]; /* 荷物の大きさ */
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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:データの読込み関数
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
プログラムの実行例
> 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
改善法による解法
⚫ 近傍探索法による改善
⚫ 貪欲方で高速に初期解を生成
⚫ 小規模な改善(近傍操作)を繰り返し適用
⚫ 改善可能な近傍操作がなくなるまで継続
組合せ最適化問題 > 改善法
局所最適解
(近傍内に良い解が無い)
初期解
近傍操作
その近傍
改善された解
その近傍
初期解作成
近傍操作有
近傍操作適用
解が改善?
近傍操作復元
近傍探索終了
Yes
Yes
No
No
近傍探索処理の
フローチャート
最適解と局所最適解
⚫ 最適解
⚫ 全ての範囲内で最も良い解
⚫ 局所最適解
⚫ “近傍”内で最も良い解
⚫ “近傍”とは“近傍操作”で移行可能な範囲
局所最適解真の最適解
組合せ最適化問題 > 改善法
広い近傍 ⇒ 少数の局所最適解
狭い近傍 ⇒ 多数の局所最適解
ビンパッキング問題への適用
⚫ 目的関数の定義
⚫ 個々の容器の目的関数を定義しその合計とする
⚫
⚫
▪ Si:荷物iの大きさ
▪ B:容器の大きさ
⚫ 偏った解を良い解
と評価する
⚫ 同じ容器数でも差を
付けて評価するため
組合せ最適化問題 > ビンパッキング問題 > 改善法
b1 b2 b1 b2
比較
71.0
5.01

=z
87.0
75.02

=z
5.0
25.01
=
=z
1
12
=
=z
57.1 5.1=
= bzz


=
bi
ib BSz
容器
良い解
ビンパッキング問題への適用
⚫ 近傍操作の定義
⚫ 移動近傍
⚫ 荷物を他の容器へ移動
⚫ 交換近傍
⚫ 荷物を容器間で交換
⚫ その他の近傍
⚫ 3個の荷物の回転交換
⚫ 移動と交換の組合せ
⚫ 近傍が広くなると⇒
良い解に早く到達 or
探索時間が長くなる
移動
交換
i1
i1
i2
i1
i2
i1
b1 b2 b1 b2
b1 b2 b1 b2
組合せ最適化問題 > ビンパッキング問題 > 改善法
プログラムの例
⚫ プログラムの概要
⚫ 移動と交換の近傍操作を適用
⚫ 変更のあった容器を管理し効率よく探索を行う
⚫ プログラムの構成
⚫ ヘッダーファイル
⚫ 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,
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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|
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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;
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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:解の表示関数
貪欲法のプログラムと同一
貪欲法のプログラムと同一
貪欲法のプログラムと同一
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|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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|
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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|}
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| }
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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); /* 新しい値を足す */
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
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|}
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
プログラムの実行例
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
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
初期解
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が
不要になっ
ている
目的関数値の推移
組合せ最適化問題 > ビンパッキング問題 > プログラムの例
26.8
26.9
27
27.1
27.2
27.3
27.4
27.5
27.6
容器減少
MOVE

More Related Content

What's hot

深層学習による製造業のスマート化と産業応用の将来展望(クオリティフォーラム2020講演資料)
深層学習による製造業のスマート化と産業応用の将来展望(クオリティフォーラム2020講演資料)深層学習による製造業のスマート化と産業応用の将来展望(クオリティフォーラム2020講演資料)
深層学習による製造業のスマート化と産業応用の将来展望(クオリティフォーラム2020講演資料)
Preferred Networks
 
強化学習の基礎と深層強化学習(東京大学 松尾研究室 深層強化学習サマースクール講義資料)
強化学習の基礎と深層強化学習(東京大学 松尾研究室 深層強化学習サマースクール講義資料)強化学習の基礎と深層強化学習(東京大学 松尾研究室 深層強化学習サマースクール講義資料)
強化学習の基礎と深層強化学習(東京大学 松尾研究室 深層強化学習サマースクール講義資料)
Shota Imai
 
灯油配送計画の最適化に向けた ヒューリスティクスの開発に関する研究
灯油配送計画の最適化に向けた ヒューリスティクスの開発に関する研究灯油配送計画の最適化に向けた ヒューリスティクスの開発に関する研究
灯油配送計画の最適化に向けた ヒューリスティクスの開発に関する研究
harmonylab
 
【慶應大学講演】なぜ、博士課程に進学したか?
【慶應大学講演】なぜ、博士課程に進学したか?【慶應大学講演】なぜ、博士課程に進学したか?
【慶應大学講演】なぜ、博士課程に進学したか?
Hirokatsu Kataoka
 
[DL輪読会]Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Ima...
[DL輪読会]Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Ima...[DL輪読会]Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Ima...
[DL輪読会]Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Ima...
Deep Learning JP
 
Word Tour: One-dimensional Word Embeddings via the Traveling Salesman Problem...
Word Tour: One-dimensional Word Embeddings via the Traveling Salesman Problem...Word Tour: One-dimensional Word Embeddings via the Traveling Salesman Problem...
Word Tour: One-dimensional Word Embeddings via the Traveling Salesman Problem...
joisino
 
情報検索の基礎 #9適合フィードバックとクエリ拡張
情報検索の基礎 #9適合フィードバックとクエリ拡張情報検索の基礎 #9適合フィードバックとクエリ拡張
情報検索の基礎 #9適合フィードバックとクエリ拡張
nishioka1
 
アンサンブル木モデル解釈のためのモデル簡略化法
アンサンブル木モデル解釈のためのモデル簡略化法アンサンブル木モデル解釈のためのモデル簡略化法
アンサンブル木モデル解釈のためのモデル簡略化法
Satoshi Hara
 
自動運転におけるCNNの信頼性
自動運転におけるCNNの信頼性自動運転におけるCNNの信頼性
自動運転におけるCNNの信頼性
Fixstars Corporation
 
近年のHierarchical Vision Transformer
近年のHierarchical Vision Transformer近年のHierarchical Vision Transformer
近年のHierarchical Vision Transformer
Yusuke Uchida
 
Deeplearning輪読会
Deeplearning輪読会Deeplearning輪読会
Deeplearning輪読会
正志 坪坂
 
Curriculum Learning (関東CV勉強会)
Curriculum Learning (関東CV勉強会)Curriculum Learning (関東CV勉強会)
Curriculum Learning (関東CV勉強会)
Yoshitaka Ushiku
 
Teslaにおけるコンピュータビジョン技術の調査 (2)
Teslaにおけるコンピュータビジョン技術の調査 (2)Teslaにおけるコンピュータビジョン技術の調査 (2)
Teslaにおけるコンピュータビジョン技術の調査 (2)
Kazuyuki Miyazawa
 
[DL Hacks]Semantic Instance Segmentation with a Discriminative Loss Function
[DL Hacks]Semantic Instance Segmentation with a Discriminative Loss Function[DL Hacks]Semantic Instance Segmentation with a Discriminative Loss Function
[DL Hacks]Semantic Instance Segmentation with a Discriminative Loss Function
Deep Learning JP
 
スペクトラルグラフ理論入門
スペクトラルグラフ理論入門スペクトラルグラフ理論入門
スペクトラルグラフ理論入門irrrrr
 
Attentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門までAttentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門まで
AGIRobots
 
動画認識における代表的なモデル・データセット(メタサーベイ)
動画認識における代表的なモデル・データセット(メタサーベイ)動画認識における代表的なモデル・データセット(メタサーベイ)
動画認識における代表的なモデル・データセット(メタサーベイ)
cvpaper. challenge
 
Deep Learningを用いた経路予測の研究動向
Deep Learningを用いた経路予測の研究動向Deep Learningを用いた経路予測の研究動向
Deep Learningを用いた経路予測の研究動向
HiroakiMinoura
 
論文紹介-Multi-Objective Deep Reinforcement Learning
論文紹介-Multi-Objective Deep Reinforcement Learning論文紹介-Multi-Objective Deep Reinforcement Learning
論文紹介-Multi-Objective Deep Reinforcement Learning
Shunta Nomura
 
[DL輪読会]Live-Streaming Fraud Detection: A Heterogeneous Graph Neural Network A...
[DL輪読会]Live-Streaming Fraud Detection: A Heterogeneous Graph Neural Network A...[DL輪読会]Live-Streaming Fraud Detection: A Heterogeneous Graph Neural Network A...
[DL輪読会]Live-Streaming Fraud Detection: A Heterogeneous Graph Neural Network A...
Deep Learning JP
 

What's hot (20)

深層学習による製造業のスマート化と産業応用の将来展望(クオリティフォーラム2020講演資料)
深層学習による製造業のスマート化と産業応用の将来展望(クオリティフォーラム2020講演資料)深層学習による製造業のスマート化と産業応用の将来展望(クオリティフォーラム2020講演資料)
深層学習による製造業のスマート化と産業応用の将来展望(クオリティフォーラム2020講演資料)
 
強化学習の基礎と深層強化学習(東京大学 松尾研究室 深層強化学習サマースクール講義資料)
強化学習の基礎と深層強化学習(東京大学 松尾研究室 深層強化学習サマースクール講義資料)強化学習の基礎と深層強化学習(東京大学 松尾研究室 深層強化学習サマースクール講義資料)
強化学習の基礎と深層強化学習(東京大学 松尾研究室 深層強化学習サマースクール講義資料)
 
灯油配送計画の最適化に向けた ヒューリスティクスの開発に関する研究
灯油配送計画の最適化に向けた ヒューリスティクスの開発に関する研究灯油配送計画の最適化に向けた ヒューリスティクスの開発に関する研究
灯油配送計画の最適化に向けた ヒューリスティクスの開発に関する研究
 
【慶應大学講演】なぜ、博士課程に進学したか?
【慶應大学講演】なぜ、博士課程に進学したか?【慶應大学講演】なぜ、博士課程に進学したか?
【慶應大学講演】なぜ、博士課程に進学したか?
 
[DL輪読会]Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Ima...
[DL輪読会]Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Ima...[DL輪読会]Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Ima...
[DL輪読会]Auto-DeepLab: Hierarchical Neural Architecture Search for Semantic Ima...
 
Word Tour: One-dimensional Word Embeddings via the Traveling Salesman Problem...
Word Tour: One-dimensional Word Embeddings via the Traveling Salesman Problem...Word Tour: One-dimensional Word Embeddings via the Traveling Salesman Problem...
Word Tour: One-dimensional Word Embeddings via the Traveling Salesman Problem...
 
情報検索の基礎 #9適合フィードバックとクエリ拡張
情報検索の基礎 #9適合フィードバックとクエリ拡張情報検索の基礎 #9適合フィードバックとクエリ拡張
情報検索の基礎 #9適合フィードバックとクエリ拡張
 
アンサンブル木モデル解釈のためのモデル簡略化法
アンサンブル木モデル解釈のためのモデル簡略化法アンサンブル木モデル解釈のためのモデル簡略化法
アンサンブル木モデル解釈のためのモデル簡略化法
 
自動運転におけるCNNの信頼性
自動運転におけるCNNの信頼性自動運転におけるCNNの信頼性
自動運転におけるCNNの信頼性
 
近年のHierarchical Vision Transformer
近年のHierarchical Vision Transformer近年のHierarchical Vision Transformer
近年のHierarchical Vision Transformer
 
Deeplearning輪読会
Deeplearning輪読会Deeplearning輪読会
Deeplearning輪読会
 
Curriculum Learning (関東CV勉強会)
Curriculum Learning (関東CV勉強会)Curriculum Learning (関東CV勉強会)
Curriculum Learning (関東CV勉強会)
 
Teslaにおけるコンピュータビジョン技術の調査 (2)
Teslaにおけるコンピュータビジョン技術の調査 (2)Teslaにおけるコンピュータビジョン技術の調査 (2)
Teslaにおけるコンピュータビジョン技術の調査 (2)
 
[DL Hacks]Semantic Instance Segmentation with a Discriminative Loss Function
[DL Hacks]Semantic Instance Segmentation with a Discriminative Loss Function[DL Hacks]Semantic Instance Segmentation with a Discriminative Loss Function
[DL Hacks]Semantic Instance Segmentation with a Discriminative Loss Function
 
スペクトラルグラフ理論入門
スペクトラルグラフ理論入門スペクトラルグラフ理論入門
スペクトラルグラフ理論入門
 
Attentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門までAttentionの基礎からTransformerの入門まで
Attentionの基礎からTransformerの入門まで
 
動画認識における代表的なモデル・データセット(メタサーベイ)
動画認識における代表的なモデル・データセット(メタサーベイ)動画認識における代表的なモデル・データセット(メタサーベイ)
動画認識における代表的なモデル・データセット(メタサーベイ)
 
Deep Learningを用いた経路予測の研究動向
Deep Learningを用いた経路予測の研究動向Deep Learningを用いた経路予測の研究動向
Deep Learningを用いた経路予測の研究動向
 
論文紹介-Multi-Objective Deep Reinforcement Learning
論文紹介-Multi-Objective Deep Reinforcement Learning論文紹介-Multi-Objective Deep Reinforcement Learning
論文紹介-Multi-Objective Deep Reinforcement Learning
 
[DL輪読会]Live-Streaming Fraud Detection: A Heterogeneous Graph Neural Network A...
[DL輪読会]Live-Streaming Fraud Detection: A Heterogeneous Graph Neural Network A...[DL輪読会]Live-Streaming Fraud Detection: A Heterogeneous Graph Neural Network A...
[DL輪読会]Live-Streaming Fraud Detection: A Heterogeneous Graph Neural Network A...
 

Similar to Operations research yonezawa_no2

Operations research yonezawa_no1
Operations research yonezawa_no1Operations research yonezawa_no1
Operations research yonezawa_no1
ssuser0bebd2
 
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
Taketo Sano
 
拡張ライブラリ作成による高速化
拡張ライブラリ作成による高速化拡張ライブラリ作成による高速化
拡張ライブラリ作成による高速化
Kazunori Jo
 
【Unity道場】ゲーム制作に使う数学を学習しよう
【Unity道場】ゲーム制作に使う数学を学習しよう【Unity道場】ゲーム制作に使う数学を学習しよう
【Unity道場】ゲーム制作に使う数学を学習しよう
Unity Technologies Japan K.K.
 
バシク行列システムの解説 2版
バシク行列システムの解説 2版バシク行列システムの解説 2版
バシク行列システムの解説 2版
Bashicu Hyudora
 
自然言語処理のための機械学習入門1章
自然言語処理のための機械学習入門1章自然言語処理のための機械学習入門1章
自然言語処理のための機械学習入門1章
Hiroki Mizukami
 
or-11. 線形計画法を Excel で解く
or-11. 線形計画法を Excel で解くor-11. 線形計画法を Excel で解く
or-11. 線形計画法を Excel で解く
kunihikokaneko1
 
HistoPyramid Stream Compaction
HistoPyramid Stream CompactionHistoPyramid Stream Compaction
HistoPyramid Stream Compaction
dasyprocta
 
or-10. 線形計画法を Excel で解く
or-10. 線形計画法を Excel で解くor-10. 線形計画法を Excel で解く
or-10. 線形計画法を Excel で解く
kunihikokaneko1
 
トーナメントは運か実力か
トーナメントは運か実力かトーナメントは運か実力か
トーナメントは運か実力か
Kazuro Fukuhara
 
論文紹介:The wavelet matrix
論文紹介:The wavelet matrix論文紹介:The wavelet matrix
論文紹介:The wavelet matrix
Yuki Igarashi
 
2分木の演習問題[アルゴリズムとデータ構造]
2分木の演習問題[アルゴリズムとデータ構造]2分木の演習問題[アルゴリズムとデータ構造]
2分木の演習問題[アルゴリズムとデータ構造]
Hagihara Ryosuke
 
プログラマのための線形代数再入門
プログラマのための線形代数再入門プログラマのための線形代数再入門
プログラマのための線形代数再入門
Taketo Sano
 
SMO徹底入門 - SVMをちゃんと実装する
SMO徹底入門 - SVMをちゃんと実装するSMO徹底入門 - SVMをちゃんと実装する
SMO徹底入門 - SVMをちゃんと実装する
sleepy_yoshi
 
KLab勉強会#6 発表資料
KLab勉強会#6 発表資料KLab勉強会#6 発表資料
KLab勉強会#6 発表資料
Suguru Oho
 
CRC-32
CRC-32CRC-32
CRC-32
7shi
 
暗号技術の実装と数学
暗号技術の実装と数学暗号技術の実装と数学
暗号技術の実装と数学
MITSUNARI Shigeo
 
平方剰余
平方剰余平方剰余
平方剰余
Arisa Niitsuma
 
これならわかる最適化数学8章_動的計画法
これならわかる最適化数学8章_動的計画法これならわかる最適化数学8章_動的計画法
これならわかる最適化数学8章_動的計画法
kenyanonaka
 

Similar to Operations research yonezawa_no2 (20)

Operations research yonezawa_no1
Operations research yonezawa_no1Operations research yonezawa_no1
Operations research yonezawa_no1
 
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
 
拡張ライブラリ作成による高速化
拡張ライブラリ作成による高速化拡張ライブラリ作成による高速化
拡張ライブラリ作成による高速化
 
【Unity道場】ゲーム制作に使う数学を学習しよう
【Unity道場】ゲーム制作に使う数学を学習しよう【Unity道場】ゲーム制作に使う数学を学習しよう
【Unity道場】ゲーム制作に使う数学を学習しよう
 
バシク行列システムの解説 2版
バシク行列システムの解説 2版バシク行列システムの解説 2版
バシク行列システムの解説 2版
 
自然言語処理のための機械学習入門1章
自然言語処理のための機械学習入門1章自然言語処理のための機械学習入門1章
自然言語処理のための機械学習入門1章
 
or-11. 線形計画法を Excel で解く
or-11. 線形計画法を Excel で解くor-11. 線形計画法を Excel で解く
or-11. 線形計画法を Excel で解く
 
Listを串刺し
Listを串刺しListを串刺し
Listを串刺し
 
HistoPyramid Stream Compaction
HistoPyramid Stream CompactionHistoPyramid Stream Compaction
HistoPyramid Stream Compaction
 
or-10. 線形計画法を Excel で解く
or-10. 線形計画法を Excel で解くor-10. 線形計画法を Excel で解く
or-10. 線形計画法を Excel で解く
 
トーナメントは運か実力か
トーナメントは運か実力かトーナメントは運か実力か
トーナメントは運か実力か
 
論文紹介:The wavelet matrix
論文紹介:The wavelet matrix論文紹介:The wavelet matrix
論文紹介:The wavelet matrix
 
2分木の演習問題[アルゴリズムとデータ構造]
2分木の演習問題[アルゴリズムとデータ構造]2分木の演習問題[アルゴリズムとデータ構造]
2分木の演習問題[アルゴリズムとデータ構造]
 
プログラマのための線形代数再入門
プログラマのための線形代数再入門プログラマのための線形代数再入門
プログラマのための線形代数再入門
 
SMO徹底入門 - SVMをちゃんと実装する
SMO徹底入門 - SVMをちゃんと実装するSMO徹底入門 - SVMをちゃんと実装する
SMO徹底入門 - SVMをちゃんと実装する
 
KLab勉強会#6 発表資料
KLab勉強会#6 発表資料KLab勉強会#6 発表資料
KLab勉強会#6 発表資料
 
CRC-32
CRC-32CRC-32
CRC-32
 
暗号技術の実装と数学
暗号技術の実装と数学暗号技術の実装と数学
暗号技術の実装と数学
 
平方剰余
平方剰余平方剰余
平方剰余
 
これならわかる最適化数学8章_動的計画法
これならわかる最適化数学8章_動的計画法これならわかる最適化数学8章_動的計画法
これならわかる最適化数学8章_動的計画法
 

Operations research yonezawa_no2

  • 1. 整数計画問題 ⚫ 決定変数に整数制約が付いた線形計画問題 ⚫ 整数計画問題 (Integer Programming, IP) ⚫ 決定変数が整数に限定され、4.5といった小数を許さない ⚫ 整数の組合せの探索が必要になり膨大な探索が必要 ⚫ シンプレックス法の様な万能の手法は存在しない ⚫ 整数計画問題のバリエーション ⚫ 混合整数計画問題 (Mixed Integer Programming, MIP) ▪ 決定変数に実数と整数の両方がある問題 ⚫ 0-1問題 ▪ 整数計画問題のうち決定変数が0, 1に限定されている問題 整数計画問題
  • 2. 線形計画問題との比較 ⚫ 線形計画問題と根本的に異なる問題 ⚫ 最適解を整数化するのでは 不可 ⚫ 実数時の最適解s1 ⚫ (3.7, 3.3) ⚫ 小数部を切り捨てたs2 ⚫ (3, 3) ⚫ 真の最適解はs3 ⚫ (1, 4) 整数計画問題 0 1 2 3 4 5 1 2 3 4 5 s1 s3 s2
  • 3. サラダパック問題 ⚫ 栄養素を摂取しつつカロリーを最小化 ⚫ ポテトサラダ、グリーンサラダの摂取量を決定 ⚫ ただし、サラダは1パック100g単位でのみ摂取可能 ⚫ 各栄養素は摂取目標以上 ⚫ 総カロリーを最小化する ポテトサラダ(100g) グリーンサラダ(100g) 摂取目標 ビタミンC(mg) 5 2.5 25 カルシウム(mg) 20 50 300 食物繊維(g) 0.5 4 12 カロリー(kcal) 100 80 最小化 整数計画問題 > サラダパック問題
  • 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 整数計画問題 > サラダパック問題
  • 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 整数計画問題 > ナップサック問題
  • 8. ナップサック問題の具体例 ⚫ ナップサックに非常食を詰める ⚫ 重量制限の範囲内でなるべく高カ ロリーに詰める ⚫ 決定変数:詰めるか否か ⚫ xi = {0,1} iは1から8 ⚫ 定数 ⚫ li 重量 ⚫ wi カロリー ⚫ 制約条件:総重量は10kg以下 ⚫ ∑lixi ≦ 10 ⚫ 目的関数:総カロリー最大化 ⚫ z = ∑ wixi 総カロリー 非常食 重量 カロリー 1 4 20 2 6 32 3 3 16 4 2 12 5 1 5 6 5 20 7 2 3 8 3 4 合計 10 最大化 整数計画問題 > ナップサック問題
  • 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
  • 11. 整数計画問題に対する手法 ⚫ 整数により問題の組合せが発生 ⚫ 万能で高速な手法は存在しない ⚫ それぞれの問題に応じた手法が有効 ⚫ 一般的な手法としては以下が挙げられる ⚫ 近似解法 ▪ 貪欲法や、発見的手法と呼ばれる様々な手法がある ⚫ 厳密解法 ▪ 列挙法 ▪ 原則的に全ての組合せを列挙 ▪ 分枝限定法 ▪ 列挙法の無駄な探索を種々の工夫で削減 整数計画問題
  • 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 この部分のみを充填
  • 19. 倉庫選択問題 ⚫ 倉庫を取捨選択しコストを最小化 ⚫ 倉庫の選択と輸送量を決定する ⚫ 倉庫の供給能力に余裕がある ⚫ 輸送コストと倉庫の固定費を勘案 ⚫ 決定変数 ⚫ 倉庫の選択と各輸送量 ⚫ 制約条件 ⚫ 倉庫が使用される場合に固定費 ⚫ 目的関数 ⚫ 輸送コスト+倉庫の固定費 整数計画問題 > 倉庫選択問題 D1 D2 D3 S1 S2 S3 S4 倉庫 店舗 x11 x12
  • 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
  • 23. 輸送スケジュール問題 ⚫ 工場から倉庫への輸送スケジュールを最適化 ⚫ 倉庫A, B, Cへ製品を輸送 ⚫ 輸送量はトラックで42, 25, 10回分 ⚫ トラックはピストン輸送をする ⚫ 移動時間 ⚫ 往復時間が右図で与えられる ⚫ トラックは最大9時間稼働 ⚫ トラックのコスト ⚫ 10万円+1万円×稼働時間(h) 整数計画問題 > 輸送スケジュール問題 3h C 4h A B 5h
  • 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
  • 29. 在庫管理問題 ⚫ 製品や部品の在庫量、発注間隔などを最適化 ⚫ 需要と供給の緩衝材として在庫が必要 ⚫ 製品需要は不確定要素が高い ⚫ 製品はまとめて生産した方が効率が良い ⚫ 在庫は現金を寝かせておくのと同じ ⚫ その現金を他に投資すれば得られたはずの機会損失 ⚫ 投資なるべく早く回収(キャッシュフロー最大化) ⚫ 経済発注量モデルを基本に多くのバリエーション ⚫ 確定型モデル ⚫ 確率型モデル 在庫管理問題
  • 30. 経済発注量モデル ⚫ 経済発注量モデル ⚫ 最も基本的な在庫管理問題 ⚫ 次の仮定の下でコスト最小化 ⚫ 製品をQ発注し倉庫に在庫 ⚫ 一定量dで倉庫から出荷 ⚫ 期間T後に次の発注 ⚫ 発注には発注費用c1 ⚫ 在庫には在庫費用c2 ⚫ 総費用を最小化する発注量Qを 決定する 在庫管理問題 >経済発注量モデル 発 注 量 Q 発注間隔T 在庫レベル 時間 需要量d(傾き) Q:発注量 T:発注間隔 d:需要量(d=Q/T) c1:発注費用 c2:在庫費用
  • 31. 経済発注量モデルの定式化 ⚫ 発注間隔での平均費用を最小化 ⚫ 期間Tの費用から平均費用を求める ⚫ 平均在庫量 : ⚫ 在庫費用 : ⚫ 発注費用 : ⚫ 合計費用 : ⚫ 平均費用 : ⚫ 目的関数 ⚫ d = Q/T を利用してQの関数として表すと ⚫ 2 2TQc 2 21 Qc T c + 発 注 量 Q 発注間隔T 在庫レベル 平均在庫量 2 Q 2 2 1 TQc c + 2 )( 21 Qc Q dc Qz += 1c 在庫管理問題 >経済発注量モデル
  • 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= → ならば
  • 41. 不確定需要に対する方策 ⚫ 定量発注方式 ⚫ 在庫量がある値以下になると発注 ⚫ 納入までの必要量を残すように管理 ⚫ 発注間隔は出庫量に左右され不定 ⚫ 発注量は経済発注量モデルを参考 ⚫ 例えて言うと... ⚫ 一般ユーザーの給油法 ▪ 燃料計のランプが点いたら給油 ▪ 給油は常に満タン ▪ 車重が重くなるのは気にしない 在庫管理問題 >定量発注方式 定量発注方式 発注水準
  • 42. 不確定需要に対する方策 ⚫ 定期発注方式 ⚫ 一定期間が来れば出庫分を補充 ⚫ 間隔は経済発注量モデルを参考 ⚫ 発注作業の管理が容易 ⚫ 比較的高額の製品に適用 ⚫ 例えて言うと... ⚫ F1での給油法 ▪ 定期的に必要最小限を給油 ▪ 発注費用・在庫コスト共に高価 ▪ 給油回数・車重をきめ細かく管理 在庫管理問題 >定期発注方式 定期発注方式 発注間隔
  • 43. 新聞売り子問題 ⚫ 不確定需要に対して在庫を決定する問題 ⚫ 需要予測に基づき新聞の最適発注量を決定 ⚫ 新聞を前日に発注 ⚫ 売残りは全て損失 ⚫ 具体的な問題設定 ⚫ 仕入価格30円、販売価格120円、利益90円 ⚫ 仕入部数をb、販売可能部数をsとする ⚫ 利益を表す目的関数z ▪ ⚫ 仕入部数b = 販売可能部数s で目的関数z最大 在庫管理問題 > 新聞売り子問題 ( ) ( )      − − = bsbb bsbs z 30120 30120 仕入れが過剰の場合 仕入れが不足の場合
  • 44. 仕入れ部数/販売可能部数/利益 在庫管理問題 > 新聞売り子問題 0 10 20 30 40 50 60 70 80 90 100 0 10 20 30 40 50 60 70 80 90 100 -3000 -2000 -1000 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 利益 0 10 20 30 40 50 60 70 80 90 100 仕入れ部数 / 販売可能部数 0 20 40 60 80
  • 45. 新聞売り子問題の最適化 ⚫ 販売可能が確率分布関数で与えられる ⚫ 需要予測が以下の式で与えられるとする ⚫ ⚫ P(s)は となる確率分布関数 ⚫ 仕入れ部数bの場合の利益の期待値を計算 ⚫ ( ) ( )        = 1000 10001.0 )( s s sP ( ) ( )      − − = =   100306000 1006.090 )(),()( 2 0 bb bbb dssPsbzbz 1)(0 =  sP 在庫管理問題 > 新聞売り子問題
  • 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% 確率 利益確率 販売可能部数の確率分布と 仕入部数に対する利益の期待値
  • 47. シミュレーションによる最適化 ⚫ モンテカルロ法によるシミュレーション ⚫ 確率分布が複雑な形状で積分不可能な場合 ⚫ シミュレーションにより目的関数値を推定 ⚫ 決定変数を変えながら最適な値を探索 ⚫ モンテカルロ法 ⚫ 乱数を用いて確率的事象を再現 ⚫ 四角形内にランダムにn個の点を決定 ⚫ 半径1以内の点の数mをカウント ⚫ nを増やすとm/nは面積比に近づく ▪ m/n → π/4 (x, y) 22 yxr += 1 1 在庫管理問題 > 新聞売り子問題 > シミュレーション
  • 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の乱数を 発生させる関数
  • 51. 組合せ最適化問題 ⚫ 決定変数の組合せで目的関数が決まる問題 ⚫ 個々の決定変数単独で良し悪しが決まらない ⚫ 「あちらを立てれば、こちらが立たず。こちらを立てれば、 あちらが立たず。」 ⚫ 最短経路問題 ⚫ 2点間を結ぶ最短の道順を決定する問題 ⚫ 前半の順路は後半の順路に依存しない ▪ 厳密な意味で組合せ最適化問題ではない ⚫ 巡回セールスマン問題 ⚫ 複数の訪問先を最短で回る訪問順を決定する問題 ⚫ 典型的な組合せ最適化問題 組合せ最適化問題
  • 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 ・・・ 全ての枝分れを 同時に探索を行 う方法 組合せ最適化問題
  • 54. 発見的手法 ⚫ 発見的手法(ヒューリスティック手法) ⚫ 経験とアイデアに基づいた近似解法 ⚫ 現実的な時間内に現実的な近似解を求める ⚫ 問題に応じてそれぞれ工夫が必要 ⚫ 貪欲法 ⚫ 1つの選択肢に対して現状で最善の選択肢を選ぶ ⚫ 後からの手戻りは考えない ⚫ 改善法 ⚫ 貪欲法等を用いて初期解を作成 ⚫ 解を部分的に修正し改善を繰り返す方法 組合せ最適化問題
  • 55. ビンパッキング問題 ⚫ 複数の容器(ビン)に荷物を最適に詰める問題 ⚫ 問題の設定 ⚫ 荷物にはそれぞれのサイズが設定 ⚫ 容器には最大容量が設定 ⚫ 典型的な組合せ最適化問題 ⚫ 部分問題に分割できない ⚫ 現実問題への適用 ⚫ トラックへ荷物の割当て ⚫ コンテナへの荷物の詰め込み ⚫ 人への仕事の分配 組合せ最適化問題 > ビンパッキング問題
  • 56. 貪欲法による解法 ⚫ ファースト・フィット・ディクリージング法 ⚫ 大→小の順に整列 ⚫ 容器の先頭から調べて最初に入る容器に割当 ○ ○ ×× × ○ × × × ○ × × × ○ × × × × ○ × ○ × × ○ × × × × ○ 組合せ最適化問題 > ビンパッキング問題 > 貪欲法
  • 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 近傍探索処理の フローチャート
  • 65. 最適解と局所最適解 ⚫ 最適解 ⚫ 全ての範囲内で最も良い解 ⚫ 局所最適解 ⚫ “近傍”内で最も良い解 ⚫ “近傍”とは“近傍操作”で移行可能な範囲 局所最適解真の最適解 組合せ最適化問題 > 改善法 広い近傍 ⇒ 少数の局所最適解 狭い近傍 ⇒ 多数の局所最適解
  • 66. ビンパッキング問題への適用 ⚫ 目的関数の定義 ⚫ 個々の容器の目的関数を定義しその合計とする ⚫ ⚫ ▪ Si:荷物iの大きさ ▪ B:容器の大きさ ⚫ 偏った解を良い解 と評価する ⚫ 同じ容器数でも差を 付けて評価するため 組合せ最適化問題 > ビンパッキング問題 > 改善法 b1 b2 b1 b2 比較 71.0 5.01  =z 87.0 75.02  =z 5.0 25.01 = =z 1 12 = =z 57.1 5.1= = bzz   = bi ib BSz 容器 良い解
  • 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が 不要になっ ている
  • 81. 目的関数値の推移 組合せ最適化問題 > ビンパッキング問題 > プログラムの例 26.8 26.9 27 27.1 27.2 27.3 27.4 27.5 27.6 容器減少 MOVE