근사해 탐색 방법

Download Report

Transcript 근사해 탐색 방법

최적화 문제 해결
생산 계획 및 통제
부산대학교 산업공학과
2012년 2학기
하병현
목차
 서론
 공정별 배치: 물량 거리 모형
 근사해 탐색 방법
 발견적 기법
 최적해 방법
 모든 대안 검토
 상용 소프트웨어 사용
 근사해 탐색 방법
 상용 소프트웨어 사용
 메타 휴리스틱
 방법 간 비교 실험
 상용 소프트웨어 자동화
1
서론
 최적화 문제
 주어진 대안들 중 목적을 고려하여 가장 나은 것 선택
 예제
 공정별 배치 문제 -- 물량-거리 모형
• 입력: 부서 간 물량 및 단위 이송 비용
• 대안 집합: 모든 가능한 배치 형태
• 목적: 총 이송 비용 최소화
 배정 문제
• 입력: 각 작업자 별 과업 처리 비용
• 대안 집합: 모든 가능한 작업자-과업 배정 방법
• 목적: 총 비용의 최소화
 문제의 난이도
 쉬운 문제
• e.g., 배정 문제, 표준 수송 계획
 어려운 문제(NP-hard problems)
• e.g., 물량-거리 모형, traveling salesman problems
2
서론
 해결 방안(일부만 나열)
 최적화 방법
• 모든 대안 검토
• 문제에 특화된 최적화 알고리즘
• e.g., 배정 문제: Hungarian method, 최단거리 문제: Dijkstra algorithm
• 범용 최적화 알고리즘
• e.g., simplex, transportation simplex, network simplex
• e.g., branch and cut
 상용 최적화 소프트웨어(CPLEX, LINDO, Xpress 등)
• (범용) 최적화 방법론
• e.g., branch and bound, dynamic programming, A* algorithm
 근사해 탐색 방법
• 발견적 기법(heuristic algorithms)
• e.g., 물량-거리 모형의 최대 비용 부서 인접화
• 메타 휴리스틱(meta-heuristics)
• e.g., simulated annealing, tabu search, genetic algorithms
 상용 근사해 탐색 소프트웨어(Excel solver, OptQuest 등)
3
공정별 배치: 물량 거리 모형
 예제 문제
 부서 간 이동 물량
 부서 간 단위 물량 당 이동 비용(DijCij)
• 물량 한 단위 당, 인접 부서의 경우 1원, 한 부서를 건너뛸 때마다 1원이 추가
• 대각선의 경우 인접 부서로 봄
 배치 가능 형태
 Quadratic assignment problem
 NP-hard
4
근사해 탐색 방법: 발견적 기법
 Gradient-descent 또는 greedy approach
1. 최초 배치 도출
• e.g., 순서대로 배치, 임의로 배치
2. 총비용을 감소시킬 수 있는 새로운 배치 도출
• 모든 인접 부서를 서로 교환해본 후 총비용을 가장 감소시키는 배치 선택
3. 비용이 개선되었다면 단계 2 반복, 아니면 종료
2
3
5
7
1
4
6
8
1
3
5
7
3
1
5
7
3
1
5
7
2
4
6
8
2
4
6
8
2
4
8
6
4
3
5
7
2
1
6
8
5
근사해 탐색 방법: 발견적 기법
 구현(Python)
 z = 2,778, X = [1, 1, 3, 2, 3, 2, 4, 4]
 X[i]: 부서 i가 위치한 열
1
4
3
7
2
6
5
8
L = [[0, 175, 50,
0, 30, 200, 20, 25],
[0,
0, 0, 100, 75, 90, 80, 90],
[0,
0, 0, 17, 88, 125, 99, 180],
[0,
0, 0,
0, 20,
5,
0, 25],
[0,
0, 0,
0, 0,
0, 180, 187],
[0,
0, 0,
0, 0,
0, 80, 70],
[0,
0, 0,
0, 0,
0,
0,
7],
[0,
0, 0,
0, 0,
0,
0,
0]]
def C(x1, x2):
return max(1, abs(x1 - x2))
def total_cost(X):
return sum(L[i][j] * C(X[i], X[j]) for i in xrange(7)
for j in xrange(i + 1, 8))
(뒤에서 계속)
6
근사해 탐색 방법: 발견적 기법
 구현(Python) (계속)
(앞에서 계속)
X0 = X = [1,1,2,2,3,3,4,4]
z0 = total_cost(X)
while True:
updated = False
for i in xrange(7):
for j in xrange(i + 1, 8):
X1 = X[:]
X1[i], X1[j] = X1[j], X1[i]
z1 = total_cost(X1)
if z1 < z0:
z0, X0 = z1, X1
updated = True
if not updated:
break
print "z = %d, X = %s" % (z0, X0)
 결과인 2,778원이 최적?
7
최적해 방법: 모든 대안 검토
 모든 대안
 [1,1,2,2,3,3,4,4], [1,1,2,2,3,4,3,4], [1,1,2,2,4,4,3,3], ...
 모두 몇 개? 대략 87654321 = 8! = 40320
 구현(Python)
 z* = 2,510, X* = [1, 2, 3, 1, 4, 2, 4, 3]
1
2
3
5
4
6
8
7
...
from itertools import permutations
z0 = 10**10
for X in permutations([1,1,2,2,3,3,4,4]):
z = total_cost(X)
if z < z0:
z0, X0 = z, X
print "z* = %d, X* = %s" % (z0, X0)
 문제?
 12! = 479,001,600
 30! = 265,252,859,812,191,058,636,308,480,000,000
8
최적해 방법: 상용 소프트웨어 사용
 최적화 수리 모형(문제를 기술하는 한 가지 방법)
 정수 계획 모형
 입력 변수
• Lij : 부서 i에서 j로의 이동 물량
 결정 변수
• yik : 부서 i가 k 번째 열에 있으면 1, 아니면 0
 부서 i가 위치한 열: k=1..4 kyik
 부서 i와 j가 떨어진 정도: max(1, |k=1..4 kyik – k=1..4 kyjk|)
 Objective
• min. i=1..7 j=(i+1)..8 Lij max(1, |k=1..4 kyik – k=1..4 kyjk|)
 Constraints
• k=1..4 yik = 1 for i=1,...,8
• i=1..8 yik = 2 for k=1,...,4
9
최적해 방법: 상용 소프트웨어 사용
 구현(CPLEX)
 z* = 2,510, y*14 = y*23 = y*32 = y*44 = y*51 = y*63 = y*71 = y*82 = 1
float L[1..8][1..8] = [
[0, 175, 50,
0, 30, 200,
[0,
0, 0, 100, 75, 90,
...
[0,
0, 0,
0, 0,
0,
];
20,
80,
0,
25],
90],
0]
dvar int y[1..8][1..4] in 0..1;
minimize sum (i in 1..7) sum (j in (i + 1)..8)
L[i][j] * maxl(1, abs(sum (k in 1..4) k * y[i][k] sum (k in 1..4) k * y[j][k]));
subject to {
forall (i in 1..8) sum (k in 1..4) y[i][k] == 1;
forall (k in 1..4) sum (i in 1..8) y[i][k] == 2;
}
10
근사해 탐색 방법: 상용 소프트웨어 사용
 구현(MS Excel)
 z = 3,147
 엑셀은 이 문제는 제대로 해결
하지 못하는 것으로 보임
참고: Google에서 “엑셀 해찾기,” “excel solver”
등으로 검색
11
근사해 탐색 방법: 상용 소프트웨어 사용
 구현(Open Solver for Excel)
 http://opensolver.org/
 z = 3,107
12
근사해 탐색 방법: 메타 휴리스틱
 Simulated annealing
 구현(Python)
• z = 2,510 / 2,510 / 2,510 / 2,510 / 2,510 / 2,510 / 2,510 / 2,510 / 2,510 / 2,510
...
from random import shuffle, randrange, random
from math import exp
for _ in xrange(10):
X = [1, 1, 2, 2, 3, 3, 4, 4]
shuffle(X)
X0 = X[:]
z = z0 = total_cost(X)
t, pi, EPSILON = 100, 0.999, 0.001
while t > EPSILON:
X1 = list(X)
i, j = randrange(8), randrange(8)
X1[i], X1[j] = X1[j], X1[i]
z1 = total_cost(X1)
if z1 <= z or random() < exp((z - z1) / t):
X, z = X1, z1
if z < z0:
X0, z0 = X[:], z
t *= pi
print "z = %d, X = %s" % (z0, X0)
13
방법 간 비교 실험
 Medium-size problem (16개의 부서)
 실험 결과
 Gap = (z – z*) / z*  100%
해결 방법
최적화 방법
상용 소프트웨어
총비용
Gap
계산시간
31,338
–
14586.5 초
34,486
10%
< 0.1 초
OpenSolver
36,712
17%
< 0.1 초
초기해보다 나쁨
Simulated annealing
31,338
0%
9.2 초
10회 수행 중 5회
CPLEX
발견적 기법
근사해 도출
방법
상용 소프트웨어
메타 휴리스틱
L = [[0, 166, 147, 72, 37, 92, 69, 153, 47,
[0,
0, 35, 181, 197, 159, 179, 48, 141,
[0,
0,
0, 193, 85, 171, 37, 157, 101,
[0,
0,
0,
0, 171, 33, 51, 172, 22,
[0,
0,
0,
0,
0, 92, 186,
4, 101,
[0,
0,
0,
0,
0,
0, 78, 111, 65,
[0,
0,
0,
0,
0,
0,
0,
0, 147,
[0,
0,
0,
0,
0,
0,
0,
0, 135,
[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,
0,
0,
0,
0,
[0,
0,
0,
0,
0,
0,
0,
0,
0,
[0,
0,
0,
0,
0,
0,
0,
0,
0,
85,
178,
0,
105,
136,
107,
173,
40,
79,
0,
0,
0,
0,
0,
0,
0,
108,
131,
139,
32,
100,
44,
184,
159,
125,
87,
0,
0,
0,
0,
0,
0,
180,
84,
68,
193,
159,
21,
166,
167,
200,
119,
28,
0,
0,
0,
0,
0,
91,
2,
162,
157,
99,
21,
178,
177,
182,
166,
155,
12,
0,
0,
0,
0,
42,
75,
127,
79,
193,
115,
184,
110,
155,
33,
53,
134,
181,
0,
0,
0,
비고
최적해
147,
115,
0,
0,
113,
125,
99,
189,
0,
141,
160,
0,
98,
0,
0,
0,
116],
181],
89],
50],
109],
85],
66],
108],
115],
5],
2],
106],
130],
120],
114],
0]] 14
상용 소프트웨어 자동화
 Excel automation
L = [[0, 175, 50,
0, 30, 200, 20, 25],
[0,
0, 0, 100, 75, 90, 80, 90],
[0,
0, 0, 17, 88, 125, 99, 180],
[0,
0, 0,
0, 20,
5,
0, 25],
[0,
0, 0,
0, 0,
0, 180, 187],
[0,
0, 0,
0, 0,
0, 80, 70],
[0,
0, 0,
0, 0,
0,
0,
7],
[0,
0, 0,
0, 0,
0,
0,
0]]
import win32com.client as win32
xl = win32.gencache.EnsureDispatch('Excel.Application')
xl.Visible = True
ss = xl.Workbooks.Add()
sh = ss.ActiveSheet
n = len(L)
for i in xrange(n):
for j in xrange(n):
sh.Cells(i + 1,j + 1).Value = L[i][j]
15
상용 소프트웨어 자동화
 CPLEX interfacing
...
model = cplex.Cplex()
model.objective.set_sense(model.objective.sense.minimize)
model.variables.add(names = sources)
model.variables.set_upper_bounds("Ingots", 100000)
model.objective.set_linear(zip(sources, costs))
model.variables.add(names = ["Element1", "Element2", "Element3"],
lb = [min * alloy for min in min_spec],
ub = [max * alloy for max in max_spec])
model.linear_constraints.add(lin_expr =
[cplex.SparsePair(ind = ["Element1",
"Element2",
"Element3"],
val = [1.0] * 3)],
senses = ["E"], rhs = [alloy])
mixed_sources = sources[3:]
for i in range(1, 4):
lhs = cplex.SparsePair(["Element" + str(i), "Pure" + str(i)] + mixed_sources,
[-1.0, 1.0] + composition["Element" + str(i)])
model.linear_constraints.add(lin_expr = [lhs], senses = ["E"],
rhs = [0.0])
model.solve()
16