使用Python Scipy Minimize进行运输成本流优化

时间:2018-02-20 23:15:27

标签: python numpy optimization scipy solver

我遇到运输成本流问题,目的是最大限度地降低5个运输公司和3000多条运输车道(例如纽约到MIA)的整体运输成本 我将从我的数据集中模拟一些示例数据,以帮助您更好地理解该问题。请在此处查看我的数据图片

Transportation Optimization

我尝试过Lonprog,但它只能用于车道而非矩阵决策变量

请告知正确的解决问题的方法,无需商业解算器(标准excel解算器有200个变量限制)

由于

1 个答案:

答案 0 :(得分:1)

您的问题是一个结构良好的运输问题。它可以通过各种方式解决。

如果您想通过线性编程解决它,可以使用scipy.optimize.linprog。使用多维决策变量对变量进行编码会稍微困难一些。

使用scipy.optimize.linprog,您可以建模并解决您的问题:

import random
import numpy as np
import scipy.optimize

LANES = 30
CARRIERS = 6

cost = np.random.rand(LANES, CARRIERS) # c
demand = np.random.rand(LANES) # b_eq
capacity = [250, 300, 500, 750, 100, 200] # b_ub

A_eq = np.zeros(LANES*CARRIERS*LANES).reshape(LANES, LANES*CARRIERS)
# Constraint for each lane, sum over the available carriers
for l in range(LANES):
    for var in range(l*CARRIERS, l*CARRIERS+CARRIERS):
        A_eq[l, var] = 1

A_ub = np.zeros(CARRIERS*LANES*CARRIERS).reshape(CARRIERS, LANES*CARRIERS)
# Constraint for each carrier, sum over the lanes
for c in range(CARRIERS):
    for var in range(c, LANES*CARRIERS, CARRIERS):
        A_ub[c, var] = 1

print(scipy.optimize.linprog(cost.flatten(), A_eq=A_eq, b_eq=demand, 
    A_ub=A_ub, b_ub=capacity, options={"maxiter": 10000}))

我们需要总共LANES*CARRIERS个变量,这些变量可以用一维数组表示。表示在具有载体l的车道c上运输多少的变量具有索引l*LANES + c。在这种假设下,可以添加约束。 由于完整问题矩阵具有LANES*CARRIERS*(LANES+CARRIERS)个元素,linprog函数可能不适合问题大小。您可以增加maxiter参数,但是您可能遇到其他问题,例如数值问题,但我没有阅读源代码。

更快,更强大的免费解算器与PuLP捆绑在一起。您可以使用PuLP安装easy_install pulp。问题也可以用更自然的方式表达,因为PuLP具有用于声明变量字典的便利功能。虽然商业解算器比PuLP捆绑的快,但你的问题是一个纯粹的线性程序,并且相对容易"即使有3000个车道和6个航空公司。

PuLP中,它可以更自然的方式实现:

from pulp import *
import numpy as np
from itertools import product

LANES = 30
CARRIERS = 6

cost = 100 * np.random.rand(LANES, CARRIERS) # c
demand = 10 * np.random.rand(LANES) # b_eq
capacity = [250, 300, 500, 750, 100, 200] # b_ub

prob = LpProblem("Transportation",LpMinimize)
x = LpVariable.dicts("Route", product(range(LANES), range(CARRIERS)), 0, None)

prob += lpSum(cost[l, c] * x[l, c] for l in range(LANES) for c in range(CARRIERS))

for l in range(LANES):
    prob += lpSum(cost[l, c] * x[l, c] for c in range(CARRIERS)) == demand[l]

for c in range(CARRIERS):
    prob += lpSum(cost[l, c] * x[l, c] for l in range(LANES)) <= capacity[c]

prob.solve()

# Get optimal solution
if LpStatus[prob.status] == "Optimal":
    x = {(l, c): value(x[l, c]) for l in range(LANES) for c in range(CARRIERS)}
else:
    print("Optimization failed.")