Search

OR Tools 이용해서 Transshipment 풀어보기

Transshipment 문제는 물류 최적화 문제 중 하나로, 공급지에서 수요지로 물품을 직접 운송하는 것이 아니라,
중간 경유지(Transshipment point)를 통해 물품을 전달하는 문제를 다룹니다.
즉, 물품이 한 번에 최종 목적지로 가는 것이 아니라, 경유지를 거쳐 최종 목적지에 도착하는 구조입니다.
구성
Transshipment 문제는 크게 세 가지 요소로 구성됩니다.
1. 공급지(Supply nodes): 물품을 제공하는 출발지입니다. 예를 들어 공장이나 창고가 될 수 있습니다. 2. 수요지(Demand nodes): 물품을 필요로 하는 목적지입니다. 매장이나 고객지일 수 있습니다. 3. 경유지(Transshipment nodes): 물품이 중간에 머무르거나 분배되는 장소입니다. 이 경유지에서는 물품이 도착한 후 다른 목적지로 다시 이동할 수 있습니다.
Transshipment 문제의 목표는 물품을 공급지에서 수요지로 이동시키는 총 운송 비용을 최소화하는 것입니다.
다만, 물품이 경유지를 거쳐서 이동한다는 것이 Transportation 문제와 다른 부분입니다.
수리적 모델
Transshipment 문제는 선형 계획법(Linear Programming)으로 모델링할 수 있습니다.
이를 위해 다음과 같은 변수와 제약 조건을 정의합니다.
설명을 위해서 아래와 같은 Transshipment 문제가 있다고 가정해 보겠습니다.
목적함수
목적은 운송비용을 최소화 하는 것입니다.
여기에서:
제약식
각 공급지에서 경유지로 운송되는 물품의 총량은 그 공급지의 최대 공급량을 초과할 수 없습니다.
각 수요지로 경유지에서 운송되는 물품의 총량은 해당 수요지의 요구량과 정확히 일치해야 합니다. (Balanced)
각 경유지로 들어온 물품의 양은 그 경유지에서 나가는 물품의 양과 동일해야 합니다.
즉, 경유지는 물품을 보관하는 것이 아니라, 들어온 물품을 다른 경로로 내보내는 역할을 합니다.
전체소스
from ortools.linear_solver import pywraplp def create_data_model(): """Stores the data for the problem.""" data = {} # Supply at each source data['supply'] = [300, 300] # Demand at each destination data['demand'] = [200, 200, 200] # Transshipment nodes capacities data['transshipment'] = [300, 300] # Transportation costs between each node (source, transshipment, and destination) data['costs'] = [ # From sources to transshipment nodes [8, 6], # Source 1 to transshipment 1 and 2 [7, 5], # Source 2 to transshipment 1 and 2 # From transshipment nodes to destinations [4, 2, 7], # Transshipment 1 to destinations 1, 2, 3 [3, 8, 6], # Transshipment 2 to destinations 1, 2, 3 ] # Number of nodes data['num_sources'] = len(data['supply']) data['num_destinations'] = len(data['demand']) data['num_transshipment'] = len(data['transshipment']) return data def main(): # Create the data data = create_data_model() # Create the linear solver using the GLOP backend solver = pywraplp.Solver.CreateSolver('GLOP') if not solver: return # Create variables for each transportation route x = {} # From sources to transshipment nodes for i in range(data['num_sources']): for j in range(data['num_transshipment']): x[(i, j)] = solver.NumVar(0, solver.infinity(), f'x_source{i}_trans{j}') # From transshipment nodes to destinations for i in range(data['num_transshipment']): for j in range(data['num_destinations']): x[(data['num_sources'] + i, j)] = solver.NumVar(0, solver.infinity(), f'x_trans{i}_dest{j}') # Objective function: Minimize transportation costs objective = solver.Objective() # Costs from sources to transshipment nodes for i in range(data['num_sources']): for j in range(data['num_transshipment']): objective.SetCoefficient(x[(i, j)], data['costs'][i][j]) # Costs from transshipment nodes to destinations for i in range(data['num_transshipment']): for j in range(data['num_destinations']): objective.SetCoefficient(x[(data['num_sources'] + i, j)], data['costs'][data['num_sources'] + i][j]) objective.SetMinimization() # Constraints: Supply from each source for i in range(data['num_sources']): solver.Add(sum(x[(i, j)] for j in range(data['num_transshipment'])) <= data['supply'][i]) # Constraints: Demand at each destination for j in range(data['num_destinations']): solver.Add(sum(x[(data['num_sources'] + i, j)] for i in range(data['num_transshipment'])) == data['demand'][j]) # Flow conservation at transshipment nodes for i in range(data['num_transshipment']): solver.Add(sum(x[(data['num_sources'] + i, j)] for j in range(data['num_destinations'])) == sum(x[(j, i)] for j in range(data['num_sources']))) # Capacity constraints for transshipment nodes for i in range(data['num_transshipment']): # Ensure the total goods entering and leaving each transshipment node do not exceed its capacity solver.Add(sum(x[(j, i)] for j in range(data['num_sources'])) <= data['transshipment'][i]) solver.Add(sum(x[(data['num_sources'] + i, j)] for j in range(data['num_destinations'])) <= data['transshipment'][i]) # Solve the problem status = solver.Solve() # Output results if status == pywraplp.Solver.OPTIMAL: print('Solution:') print(f'Total transportation cost = {solver.Objective().Value()}\n') for i in range(data['num_sources']): for j in range(data['num_transshipment']): print(f'Source {i} to Transshipment {j}: {x[(i, j)].solution_value()} units') for i in range(data['num_transshipment']): for j in range(data['num_destinations']): print(f'Transshipment {i} to Destination {j}: {x[(data['num_sources'] + i, j)].solution_value()} units') else: print('The problem does not have an optimal solution.') if __name__ == '__main__': main()
Python
복사
위의 코드를 수행하면 아래와 같은 결과를 얻을 수 있습니다.
Solution: Total transportation cost = 6200.0 Source 0 to Transshipment 0: 0.0 units Source 0 to Transshipment 1: 300.0 units Source 1 to Transshipment 0: 300.0 units Source 1 to Transshipment 1: 0.0 units Transshipment 0 to Destination 0: 100.0 units Transshipment 0 to Destination 1: 200.0 units Transshipment 0 to Destination 2: 0.0 units Transshipment 1 to Destination 0: 100.0 units Transshipment 1 to Destination 1: 0.0 units Transshipment 1 to Destination 2: 200.0 units
JavaScript
복사
Keyword: Logistics Optimization, 물류 최적화, 파이썬, Python, 선형계획법, Linear Programming, Google OR Tools
Reference: