主頁 > 後端開發 > Python小白的數學建模課-07 選址問題

Python小白的數學建模課-07 選址問題

2021-06-14 06:11:05 後端開發


選址問題是要選擇設施位置使目標達到最優,是數模競賽中的常見題型,

小白不一定要掌握所有的選址問題,但要能判斷是哪一類問題,用哪個模型,

進一步學習 PuLP工具包中處理復雜問題的字典格式快捷建模方法,

歡迎關注『Python小白的數學建模課 @ Youcans』系列,每周持續更新



1. 選址問題

選址問題是指在某個區域內選擇設施的位置使所需的目標達到最優,選址問題也是一種互斥的計劃問題,

例如投資場所的選址:企業要在 m 個候選位置選擇若干個建廠,已知建廠費用、運輸費及 n 個地區的產品需求量,應如何進行選址,

選址問題是運籌學中經典的問題之一,選址問題在生產生活、物流、甚至軍事中都有著非常廣泛的應用,如工廠、倉庫、急救中心、消防站、垃圾處理中心、物流中心、導彈倉庫的選址等,更重要的,選址問題也是數模競賽的熱點問題,

選址是重要的長期決策,選址的好壞直接影響到服務方式、服務質量、服務效率、服務成本等,從而影響到利潤和市場競爭力,選址問題的研究有著重大的經濟、社會和軍事意義,

選址問題有四個基本要素:設施、區域、距離和優化目標,

1.1 設施

選址問題中所說的設施,在具體題目中可以是工廠、倉庫、服務站等形式,

1.2 區域

選址問題中所說的區域,在具體題目中可以是工廠、車間的內部布局,也可以是給定的某個地區、甚至空間范圍,

按照規劃區域的特征,可以分為連續選址問題和離散選址問題,連續選址問題,設施可以布局在區域內的任意位置,就要求出最優選址的坐標;離散選址問題,只能從若干候選位置中進行選擇,運籌學中的選址問題通常是這類離散選址問題,

1.3 距離

選址問題中所說的距離,是指設施到服務物件之間的距離,在具體題目中也可以是某個選址位置的服務時間、成本、覆寫范圍,如果用圖論方法求解,通常就是連接頂點的邊的權值,

當問題所關注的是設施到服務物件之間的距離時,如果問題給出的不是頂點之間的距離,而是設施的位置坐標,要注意不是只有歐式距離,對于不同問題也可能是球面距離、曼哈頓距離、切比雪夫距離,

1.4 優化目標

選址問題要求選擇最好的選址位置,但選址位置只是決策變數,選擇的最終目的通常是實作加權距離最短、費用最小、利潤最大、時間最短,這才是優化問題的目標函式,

按照目標函式的特點,可以分為:中位問題,要求總成本最小;中心問題,服務于每個客戶的最大成本最小;反中心問題:服務于每個客戶的最小成本最大,




2. 常見選址問題及建模

2.1 P-中位問題(P-median problem)

P-中位問題,假設有 N 個候選服務站和 M 個需求點,要從 N 個候選服務站中選擇 P 個,使所有需求點到最近的服務站的加權距離 \(d_{ij}\) 的總和最小,需求點 i 的權值,通常是指該需求點的需求量,

這是一個 MinSum 問題,定義決策變數 \(x_j\) 為選中的服務站,\(y_{ij}\) 將各需求點匹配到最近的服務站:

\[x_j = \begin{cases} 1,& 服務站\ j\ 被選中\\ 0,& 服務站\ j\ 未被選中 \end{cases} \]

\[y_{ij} = \begin{cases} 1,& 需求點\ i\ 由服務站\ j\ 服務\\ 0,& 需求點\ i\ 不由服務站\ j\ 服務 \end{cases} \]

可以建立數學模型如下:

\[\begin{align*} & min\;\sum_{i \in M}\sum_{j \in N} w_i d_{ij}y_{ij}\\ & s.t.:\;\begin{cases} \sum_{j \in N} x_{j} = P\\ \sum_{j \in N} y_{ij} = 1,\forall i\\ y_{ij} - x_j \leq 0,\forall i,j\\ x_{j} \in \{0,1\}, \;y_{ij} \in \{0,1\} \end{cases} \end{align*} \]

其中:j 為服務站,i 為需求點,\(w_i\) 為需求點 i 的需求量, \(d_{ij}\) 為需求點 i 到服務站 j 的距離,


2.2 P-中心問題

P-中心問題,假設有 N 個候選服務站和 M 個需求點,要從 N個候選服務站中選擇 P個,使任一需求點到最近的服務站的最大距離最小,

這是一個 MinMax 問題,需要最小化任何需求點與其鄰近設施點的最大距離,P-中位問題追求總和最小,可以理解為發展經濟總量優先;P-中心問題關注最差個體的最好結果,可以理解為優先進行扶貧,

定義決策變數 \(x_j\) 為選中的服務站,\(y_{ij}\) 將各需求點匹配到最近的服務站:

\[x_j = \begin{cases} 1,& 服務站\ j\ 被選中\\ 0,& 服務站\ j\ 未被選中\end{cases} \]

\[y_{ij} = \begin{cases} 1,& 需求點\ i\ 由服務站\ j\ 服務\\ 0,& 需求點\ i\ 不由服務站\ j\ 服務\end{cases} \]

可以建立數學模型如下:

\[\begin{align*} & min\; D\\ & s.t.:\;\begin{cases} \sum_{j \in N} w_i d_{ij} y_{ij} \leq D, \forall i\\ \sum_{j \in N} x_{j} = P\\ \sum_{j \in N} y_{ij} = 1, \forall i\\ y_{ij} - x_j \leq 0, \forall i,j\\ x_{j} \in \{0,1\}, \;y_{ij} \in \{0,1\} \end{cases} \end{align*} \]

其中:j 為服務站,i 為需求點, \(d_{ij}\) 為需求點 i 到服務站 j 的距離,如果只求需求點到最近的服務站的最大距離,則 \(w_i = 1\) ;如果要求任一需求點到最近的服務站的最大運費,則 \(w_i\) 為需求點 i 的需求量,即加權最大距離,


2.3 集合覆寫問題

覆寫模型適用于一些特殊場景,例如消防中心、救護車、巡邏車等應急設施的區位選址問題,覆寫問題分為集合覆寫問題(Set covering problem)和最大覆寫問題(Maximal covering problem),

集合覆寫問題研究滿足覆寫所有需求點顧客的前提下,服務站的最少個數或建設費用最小的問題,假設有 N 個候選服務站和 M 個需求點,已知每個服務站的服務范圍(或服務容量),要從 N個候選服務站中選擇若干個,使所有需求點得到服務(到所屬服務站的距離或時間小于給定的臨界值),服務站的個數最少或成本最小,

定義引數 \(a_{ij}\) 為每個服務站的覆寫范圍:

\[a_{ij} = \begin{cases} 1,& 服務站\ j\ 可以覆寫需求點\ i\\ 0,& 服務站\ j\ 不能覆寫需求點\ i \end{cases} \]

定義決策變數 \(x_j\) 為選中的服務站:

\[x_j = \begin{cases} 1,& 服務站\ j\ 被選中\\ 0,& 服務站\ j\ 未被選中\end{cases} \]

可以建立數學模型如下:

\[\begin{align*} & min\; \sum_{j \in N} c_j x_{j}\\ & s.t.:\;\begin{cases} \sum_{j \in N_i} x_j \geq 1, \forall i \in M\\ x_{j} \in \{0,1\} \end{cases} \end{align*} \]

其中:j 為服務站,i 為需求點,\(c_j\) 為服務站 j 的建設費用(最少個數問題中不需要考慮),\(N_i=\{j:a_{ij}=1\}\) 是覆寫需求點 i 的候選服務站的集合,


2.4 最大覆寫問題

最大覆寫問題研究在已知服務站的數目和服務半徑的條件下,如何設立 P個服務站使得可接受的服務需求最大的問題,

定義決策變數 \(x_j\) 為選中的服務站:

\[x_j = \begin{cases} 1,& 服務站\ j\ 被選中\\ 0,& 服務站\ j\ 未被選中 \end{cases} \]

\[z_i = \begin{cases} 1,& 需求點\ i\ 被覆寫\\ 0,& 需求點\ i\ 未被覆寫\ \end{cases} \]

可以建立數學模型如下:

\[\begin{align*} & max\; \sum_{i \in N_i} w_i z_i\\ & s.t.:\; \begin{cases} z_i \leq \sum_{j \in N_i} x_j , \forall i \in M\\ \sum_{j \in M} x_j = p\\ x_{j} \in \{0,1\}, z_{i} \in \{0,1\} \end{cases} \end{align*} \]

其中:j 為服務站,i 為需求點,\(w_i\) 為需求點 i 的需求量,


2.5 其它選址問題

其它選址問題,在數學建模中應用相對較少,限于篇幅不能逐一介紹其數學模型,在此將各模型的特點簡要介紹,以便判斷問題的型別,

帶固定費用和容量限制的選址問題

服務站建站的固定費用和服務站的容量(能力)限制這兩個因素具有很強的實際意義,經常作為基本選址問題的深化研究課題,
無容量限制的固定費用下的選址問題,就是去掉服務站個數的約束,并將固定建站費用加到 P-中位問題的目標函式上,

選址分配問題

選址分配問題類似于 P-中位問題,有 m 個服務站需要選址,n 個已知位置的顧客分配給不同的設施,已知每個服務站的能力和每個顧客的需求,要求服務站的選址和顧客對服務站的分配,使顧客與所分配服務站的距離總和最小,

隨機選址問題
服務站的運行時間、建設成本、需求點位置、需求數量等全部或部分引數是不確定的,但服從某種隨機分布,

動態選址問題
研究未來若干時間段內服務站的最優選址問題,在不同時間段內動態選址模型的引數是變化的,但在某一時間段內模型引數是確定的,

競爭選址問題
研究考慮市場上存在兩個以上同類產品或服務的提供者,或服務站提供多個產品或服務,



2.6 選址問題的求解演算法與編程實作

設施選址問題通常是是 NP 問題,不存在多項式時間演算法,常用的近似解法有:

線性規劃舍入演算法,相當于整數規劃問題的求解演算法,首先給出原問題的整數規劃模型,然后求解相應的線性規劃松弛問題得到分數最優解,根據可行要求對分數最優解進行改造,構造原問題的整數可行解,

原始對偶演算法,首先找到對偶問題的一個可行解,再根據該對偶可行解構造原始問題的整數可行解,不斷調整對偶問題的可行解,直到找到最優解為止,

區域搜索演算法:給定初始可行解,定義適當的鄰域,通過引入恰當的調整策略,在鄰域中得到改進的可行解,依次迭代,直到調整策略不能改進為止

啟發式演算法或隨機優化演算法,

本節作為線性規劃問題系列的一篇,仍然選擇 PuLP工具包求解選址問題,很多選址問題適合用圖論方法描述和求解,這將在后續課程中進行介紹,



3. 案例 1:PuLP求解指派問題

說明:本案例是指派問題,不是選址問題,因指派問題未單獨成文,因此將該案例放在本文中,

另外,本案例給出了 PuLP 工具包使用字典方式快捷編程的使用方法,這在選址問題中是非常方便的,

3.1 游泳接力賽的指派問題

游泳隊中 A、B、C、D 四名運動員組成 4x100米混合泳接力隊,運動員各種泳姿的成績如下表所示:

隊員\專案 自由泳 蛙泳 蝶泳 仰泳
A 56 74 61 63
B 63 69 65 71
C 57 77 63 67
D 55 76 62 62

如何安排 A、B、C、D 四名運動員的泳姿,才最有可能取得好成績?


3.2 指派問題建模分析

引入 0-1 變數 \(x_{ij}\)

\[x_{i,j} = \begin{cases} 0,第\;i\;人不游第\;j\;種姿勢\\ 1,第\;i\;人游第\;j\;種姿勢,i,j=1,...4 \end{cases} \]

指派問題的數學模型就可以描述為:

\[\begin{align*} & min\;f(x) = \sum_{i=1} ^n \sum_{j=1} ^n (c_{ij} x_{ij})\\ & s.t.:\;\begin{cases} \sum_{j=1} ^n x_{ij} = 1,i=1,...,n\\ \sum_{i=1} ^n x_{ij} = 1,j=1,...,n\\ x_{ij} = 0,1,i,j=1,...,n \end{cases} \end{align*} \]

其中:

\[c_{i,j}=\left( \begin{matrix} 56 & 74 & 61 & 63 \\ 63 & 69 & 65 & 71 \\ 57 & 77 & 63 & 67 \\ 55 & 76 & 62 & 62 \end{matrix} \right) \]

3.3 指派問題模型求解的編程

模型求解,用標準模型的優化演算法對模型求解,得到優化結果,模型求解的編程步驟如下:

(0)匯入 PuLP庫函式

    import pulp

(1)定義一個規劃問題

    AssignLP = pulp.LpProblem("Assignment_problem_for_swimming_relay_race", sense=pulp.LpMinimize)

pulp.LpProblem 用來定義問題的建構式,引數 sense 指定問題求目標函式的最小值/最大值 ,

(2)定義決策變數

    rows = cols = range(0, 4)
    x = pulp.LpVariable.dicts("x", (rows, cols), cat="Binary")

pulp.LpVariable 用來定義決策變數的函式,引數 cat 設定變數型別,' Binary ' 表示 0/1 變數,

注意,指派問題、選址問題中都涉及 N*M 維矩陣變數,變數個數很多,如果逐一定義非常冗長,而且容易出錯、不便修改,本例使用 pulp.LpVariable.dicts 提供的字典格式定義了 4*4 個變數 \(x_{ij}\),使程式大為簡化,

(3)添加目標函式

    scoreM = [[56,74,61,63],[63,69,65,71],[57,77,63,67],[55,76,62,62]]
    AssignLP += pulp.lpSum([[x[row][col]*scoreM[row][col] for row in rows] for col in cols])

本例程在陳述句內使用兩重 for 回圈遍歷串列實作所有變數的線性組合 ,使程式大為簡化,

(4)添加約束條件

    for row in rows:
        AssignLP += pulp.lpSum([x[row][col] for col in cols]) == 1 # sum(x(i,j),j=1,4)=1, i=1,4
    for col in cols:
        AssignLP += pulp.lpSum([x[row][col] for row in rows]) == 1 # sum(x(i,j),i=1,4)=1, j=1,4

快捷方法對于約束條件的定義與對目標函式的定義相似,使用字典定義引數,使用回圈定義約束條件,使程式簡單、結構清楚,

(5)求解和結果輸出

    AssignLP.solve()  # youcans
    print(AssignLP.name)
    member = ["隊員A","隊員B","隊員C","隊員D"]
    style = ["自由泳","蛙泳","蝶泳","仰泳"]
    if pulp.LpStatus[AssignLP.status] == "Optimal":  # 獲得最優解
        xValue = https://www.cnblogs.com/youcans/archive/2021/06/13/[v.varValue for v in AssignLP.variables()]
        # [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
        xOpt = np.array(xValue).reshape((4, 4))  # 將 xValue 格式轉換為 4x4 矩陣
        print("最佳分配:" )
        for row in rows:
            print("{}\t{} 參加專案:{}".format(xOpt[row],member[row],style[np.argmax(xOpt[row])]))
        print("預測最好成績為:{}".format(pulp.value(AssignLP.objective)))

xValue 獲得的是串列變數,通過 numpy 的 reshape() 函式轉換為 4*4 矩陣,便于格式化輸出,


3.4 指派問題 Python 例程

# mathmodel08_v1.py
# Demo08 of mathematical modeling algorithm
# Solving assignment problem with PuLP.
# Copyright 2021 Youcans, XUPT
# Crated:2021-06-02
# Python小白的數學建模課 @ Youcans

import pulp      # 匯入 pulp 庫
import numpy as np

# 主程式
def main():
    # 問題建模:
    """
        決策變數:
            x(i,j) = 0, 第 i 個人不游第 j 種姿勢
            x(i,j) = 1, 第 i 個人游第 j 種姿勢
            i=1,4, j=1,4
        目標函式:
            min time = sum(sum(c(i,j)*x(i,j))), i=1,4, j=1,4
        約束條件:
            sum(x(i,j),j=1,4)=1, i=1,4
            sum(x(i,j),i=1,4)=1, j=1,4
        變數取值范圍:
            x(i,j) = 0,1 
    """

    # 游泳比賽的指派問題 (assignment problem)
    # 1.建立優化問題 AssignLP: 求最小值(LpMinimize)
    AssignLP = pulp.LpProblem("Assignment_problem_for_swimming_relay_race", sense=pulp.LpMinimize)  # 定義問題,求最小值
    # 2. 建立變數
    rows = cols = range(0, 4)
    x = pulp.LpVariable.dicts("x", (rows, cols), cat="Binary")
    # 3. 設定目標函式
    scoreM = [[56,74,61,63],[63,69,65,71],[57,77,63,67],[55,76,62,62]]
    AssignLP += pulp.lpSum([[x[row][col]*scoreM[row][col] for row in rows] for col in cols])
    # 4. 施加約束
    for row in rows:
        AssignLP += pulp.lpSum([x[row][col] for col in cols]) == 1 # sum(x(i,j),j=1,4)=1, i=1,4
    for col in cols:
        AssignLP += pulp.lpSum([x[row][col] for row in rows]) == 1 # sum(x(i,j),i=1,4)=1, j=1,4
    # 5. 求解
    AssignLP.solve()  # youcans
    # 6. 列印結果
    print(AssignLP.name)
    member = ["隊員A","隊員B","隊員C","隊員D"]
    style = ["自由泳","蛙泳","蝶泳","仰泳"]
    if pulp.LpStatus[AssignLP.status] == "Optimal":  # 獲得最優解
        xValue = https://www.cnblogs.com/youcans/archive/2021/06/13/[v.varValue for v in AssignLP.variables()]
        # [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
        xOpt = np.array(xValue).reshape((4, 4))  # 將 xValue 格式轉換為 4x4 矩陣
        print("最佳分配:" )
        for row in rows:
            print("{}\t{} 參加專案:{}".format(xOpt[row],member[row],style[np.argmax(xOpt[row])]))
        print("預測最好成績為:{}".format(pulp.value(AssignLP.objective)))

    return

if __name__ == '__main__':  # Copyright 2021 YouCans, XUPT
    main()  # Python小白的數學建模課 @ Youcans

3.5 Python 例程運行結果

Welcome to the CBC MILP Solver 
Version: 2.9.0 
Build Date: Feb 12 2015 

Result - Optimal solution found

Assignment_problem_for_swimming_relay_race
最佳分配:
[0. 0. 1. 0.]	隊員A 參加專案:蝶泳
[0. 1. 0. 0.]	隊員B 參加專案:蛙泳
[1. 0. 0. 0.]	隊員C 參加專案:自由泳
[0. 0. 0. 1.]	隊員D 參加專案:仰泳
預測最好成績為:249.0


4. 案例 2:PuLP求解選址問題

4.1 消防站的選址問題

例題 2:某城市有 8 個區,每個區最多建一個消防站,擬建設消防站到各區的最長時間如下表所示,現要求任何區域發生火警時,消防車能在 10分鐘內趕到,在此條件下盡量減少消防站數量,應該在哪幾個區建設消防站?

區域 1 2 3 4 5 6 7 8
1 7 12 18 20 24 26 25 28
2 14 5 8 15 16 18 18 18
3 19 9 4 14 10 22 16 13
4 14 15 15 10 18 15 14 18
5 20 18 12 20 9 25 14 12
6 18 21 20 16 20 6 10 15
7 22 18 20 15 16 15 5 9
8 30 22 15 20 14 18 8 6

4.2 選址問題建模分析

首先判斷這是一個集合覆寫問題,要求從 8 個候選消防站中選擇若干個,在所有需求點得到服務的時間都小于臨界值 10分鐘的條件下,選擇消防站的數量最少,本問題不考慮各候選站點建設費用的差異,即不帶權重,

定義引數 \(R_{ij}\) 為每個消防站的覆寫范圍:

\[R_{ij} = \begin{cases} 1,& 消防站\ j\ 可以覆寫區域\ i\\ 0,& 消防站\ j\ 不能覆寫區域\ i \end{cases} \]

由擬建消防站到各區的最長時間表可以得到引數 \(R_{ij}\) 如下表:

區域 1 2 3 4 5 6 7 8
1 1 0 0 0 0 0 0 0
2 0 1 1 0 0 0 0 0
3 0 1 1 0 1 0 0 0
4 0 0 0 1 0 0 0 0
5 0 0 0 0 1 0 0 0
6 0 0 0 0 0 1 1 0
7 0 0 0 0 0 0 1 1
8 0 0 0 0 0 0 1 1

定義決策變數 \(x_j\) 為選中的服務站:

\[x_j = \begin{cases} 1,& 消防站\ j\ 被選中\\ 0,& 消防站\ j\ 未被選中\end{cases} \]

可以建立數學模型如下:

\[\begin{align*} & min\; f(x) = \sum_{j=1}^8 x_{j}\\ & s.t.:\;\begin{cases} \sum_{j=1}^8 x_j R_{ij} \geq 1, &i=1,..8\\ x_{j} \in \{0,1\}, &j=1,..8 \end{cases} \end{align*} \]

選址問題的模型求解,用標準模型的優化演算法對模型求解,得到優化結果,

模型求解的編程步驟與指派問題是一致的,且在例程中給出了詳細的注釋,就不再進行逐項解釋了,

需要注意的是,選址問題的決策變數、引數、約束條件的數量較大(N*M),如果對變數、約束條件逐個進行定義,編程程序將是非常冗長和痛苦的,因此需要使用串列、字典等快捷方式進行定義,對于更大規模的問題,模型中的資料要通過讀取資料檔案獲得,就更需要采用這種方式來編程,


4.3 選址問題 Python 例程

# mathmodel09_v1.py
# Demo08 of mathematical modeling algorithm
# Solving set covering problem with PuLP.
# Copyright 2021 Youcans, XUPT
# Crated:2021-06-06
# Python小白的數學建模課 @ Youcans

import pulp      # 匯入 pulp 庫

# 主程式
def main():

    # 問題建模:
    """
        決策變數:
            x(j) = 0, 不選擇第 j 個消防站
            x(j) = 1, 選擇第 j 個消防站, j=1,8
        目標函式:
            min fx = sum(x(j)), j=1,8
        約束條件:
            sum(x(j)*R(i,j),j=1,8) >=1, i=1,8
        變數取值范圍:
            x(j) = 0,1
    """

    # 消防站的選址問題 (set covering problem, site selection of fire station)
    # 1.建立優化問題 SetCoverLP: 求最小值(LpMinimize)
    SetCoverLP = pulp.LpProblem("SetCover_problem_for_fire_station", sense=pulp.LpMinimize)  # 定義問題,求最小值
    # 2. 建立變數
    zones = list(range(8))  #  定義各區域 youcans
    x = pulp.LpVariable.dicts("zone", zones, cat="Binary")  # 定義 0/1 變數,是否在該區域設消防站
    # 3. 設定目標函式
    SetCoverLP += pulp.lpSum([x[j] for j in range(8)])  # 設定消防站的個數
    # 4. 施加約束
    reachable = [[1, 0, 0, 0, 0, 0, 0, 0],
                 [0, 1, 1, 0, 0, 0, 0, 0],
                 [0, 1, 1, 0, 1, 0, 0, 0],
                 [0, 0, 0, 1, 0, 0, 0, 0],
                 [0, 0, 0, 0, 1, 0, 0, 0],
                 [0, 0, 0, 0, 0, 1, 1, 0],
                 [0, 0, 0, 0, 0, 0, 1, 1],
                 [0, 0, 0, 0, 0, 0, 1, 1]]  # 引數矩陣,第 i 消防站能否在 10分鐘內到達第 j 區域
    for i in range(8):
        SetCoverLP += pulp.lpSum([x[j]*reachable[j][i] for j in range(8)]) >= 1

    # 5. 求解
    SetCoverLP.solve()
    # 6. 列印結果
    print(SetCoverLP.name)
    temple = "區域 %(zone)d 的決策是:%(status)s"  # 格式化輸出
    if pulp.LpStatus[SetCoverLP.status] == "Optimal":  # 獲得最優解
        for i in range(8):
            output = {'zone': i+1,  # 與問題中區域 1~8 一致
                      'status': '建站' if x[i].varValue else '--'}
            print(temple % output)
        print("需要建立 {} 個消防站,".format(pulp.value(SetCoverLP.objective)))

    return

if __name__ == '__main__':  # Copyright 2021 YouCans, XUPT
    main()  # Python小白的數學建模課 @ Youcans


4.4 Python 例程運行結果

Welcome to the CBC MILP Solver 
Version: 2.9.0 
Build Date: Feb 12 2015 

Result - Optimal solution found

SetCover_problem_for_fire_station
區域 1 的決策是:建站
區域 2 的決策是:--
區域 3 的決策是:建站
區域 4 的決策是:建站
區域 5 的決策是:--
區域 6 的決策是:建站
區域 7 的決策是:建站
區域 8 的決策是:--
需要建立 5.0 個消防站


5. 小結

  1. 關于規劃問題,我們從線性規劃、整數規劃、0-1規劃到一些特殊型別問題,用 5節課進行了介紹,到這里就暫告一段落了,后面根據需要,可能還會講非線性規劃,實際上主要是非線性優化問題了,
  2. 雖然各種規劃問題的求解演算法差別很大,但我們所用的編程實作方法都是基于 PuLP工具包,編程步驟都是一致的,
  3. 本系列集中體現了與其它課程的區別,沒有展開講演算法的實作步驟,而是重點講編程方法的選擇、建立模型方程的程序和編程實作的步驟,這主要是為了便于小白學習和掌握,

【本節完】


著作權宣告:

歡迎關注『Python小白的數學建模課 @ Youcans』 原創作品

原創作品,轉載必須標注原文鏈接,

Copyright 2021 Youcans, XUPT

Crated:2021-06-06


歡迎關注 『Python小白的數學建模課 @ Youcans』,每周更新數模筆記
Python小白的數學建模課-01.新手必讀
Python小白的數學建模課-02.資料匯入
Python小白的數學建模課-03.線性規劃
Python小白的數學建模課-04.整數規劃
Python小白的數學建模課-05.0-1規劃
Python小白的數學建模課-A1.國賽賽題型別分析
Python小白的數學建模課-A2.2021年數維杯C題探討
Python小白的數學建模課-A3.12個新冠疫情數模競賽賽題及短評
Python數模筆記-PuLP庫
Python數模筆記-StatsModels統計回歸
Python數模筆記-Sklearn
Python數模筆記-NetworkX
Python數模筆記-模擬退火演算法


轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/287055.html

標籤:其他

上一篇:python基礎——time模塊和datetime模塊

下一篇:python檔案操作

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more