數學建模 1 線性規劃

原文鏈接:https://www.jianshu.com/p/9be417cbfebb

可以解決 線性規劃 中的

 

一. 線性規劃

參考《數學建模算法與應用-司守奎》第一章線性規劃 

求解最普通的線性規劃問題:

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]

如果存在類似x_1+2x_2+4x_3=101這種情況,可以

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元素的位置

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章