可以解決 線性規劃 中的
一. 線性規劃
參考《數學建模算法與應用-司守奎》第一章線性規劃
求解最普通的線性規劃問題:
PULP調用包
import pulp
#目標函數的係數
z = [2, 3, 1]
#約束
a = [[1, 4, 2], [3, 2, 0]]
b = [8, 6]
#確定最大化最小化問題,最大化只要把Min改成Max即可
m = pulp.LpProblem(sense=pulp.LpMinimize)
#定義三個變量放到列表中
x = [pulp.LpVariable(f'x{i}', lowBound=0) for i in [1,2,3]]
#定義目標函數,lpDot可以將兩個列表的對應位相乘再加和
#相當於z[0]*x[0]+z[1]*x[0]+z[2]*x[2]
m += pulp.lpDot(z, x)
#設置約束條件
for i in range(len(a)):
m += (pulp.lpDot(a[i], x) >= b[i])
#求解
m.solve()
#輸出結果
print(f'優化結果:{pulp.value(m.objective)}')
print(f'參數取值:{[pulp.value(var) for var in x]}')
#output:
#優化結果:7.0
#參數取值:[2.0, 0.0, 3.0]
如果存在類似這種情況,可以
A_eq = [1,2,4]
b_eq = 101
m += (pulp.lpDot(A_eq, x) == b_eq)
二、運輸問題
pulp調包代碼
import pulp
import numpy as np
from pprint import pprint
def transportation_problem(costs, x_max, y_max):
row = len(costs)
col = len(costs[0])
prob = pulp.LpProblem('Transportation Problem', sense=pulp.LpMaximize)
var = [[pulp.LpVariable(f'x{i}{j}', lowBound=0, cat=pulp.LpInteger) for j in range(col)] for i in range(row)]
flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
prob += pulp.lpDot(flatten(var), costs.flatten())
for i in range(row):
prob += (pulp.lpSum(var[i]) <= x_max[i])
for j in range(col):
prob += (pulp.lpSum([var[i][j] for i in range(row)]) <= y_max[j])
prob.solve()
return {'objective':pulp.value(prob.objective), 'var': [[pulp.value(var[i][j]) for j in range(col)] for i in range(row)]}
if __name__ == '__main__':
costs = np.array([[500, 550, 630, 1000, 800, 700],
[800, 700, 600, 950, 900, 930],
[1000, 960, 840, 650, 600, 700],
[1200, 1040, 980, 860, 880, 780]])
max_plant = [76, 88, 96, 40]
max_cultivation = [42, 56, 44, 39, 60, 59]
res = transportation_problem(costs, max_plant, max_cultivation)
print(f'最大值爲{res["objective"]}')
print('各變量的取值爲:')
pprint(res['var'])
#output:
#最大值爲284230.0
#各變量的取值爲:
#[[0.0, 0.0, 6.0, 39.0, 31.0, 0.0],
# [0.0, 0.0, 0.0, 0.0, 29.0, 59.0],
# [2.0, 56.0, 38.0, 0.0, 0.0, 0.0],
# [40.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
三、指派問題
https://www.jianshu.com/p/9be417cbfebb
https://blog.csdn.net/your_answer/article/details/79160045
指派問題概述:
實際中,會遇到這樣的問題,有n項不同的任務,需要n個人分別完成其中的1項,每個人完成任務的時間不一樣。於是就有一個問題,如何分配任務使得花費時間最少。
通俗來講,就是n*n矩陣中,選取n個元素,每行每列各有1個元素,使得和最小。
如下圖:
指派問題性質:
指派問題的最優解有這樣一個性質,若從矩陣的一行(列)各元素中分別減去該行(列)的最小元素,得到歸約矩陣,其最優解和原矩陣的最優解相同.
匈牙利法:
(3)暫時不看被線覆蓋的元素,重複(1)(2)直到沒有線可以畫。
(4)根據(2)找到的0元素個數判斷,找到n個獨立0元素則Success,小於n個則Fail.(本例子中,n=5,可以看到,第一次試指派之後,獨立0元素有4個,不符合)
4.畫蓋0線:
目標:做最少的直線數覆蓋所有0元素,直線數就是獨立0元素的個數。
注意:這跟3的線不同;不能用貪心法去畫線,比如
1 0 0
1 1 0
1 0 1
若先畫橫的,則得畫3條線,實際只需2條;若先畫豎的,將矩陣轉置後同理。
步驟3得出的獨立0元素的位置