欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    angchain-ChatChat是現(xiàn)在用的很廣的一個(gè)大模型應(yīng)用框架,基于 ChatGLM 等大語言模型與 Langchain 等應(yīng)用框架實(shí)現(xiàn),開源、可離線部署的檢索增強(qiáng)生成(RAG)大模型知識(shí)庫項(xiàng)目。前一段時(shí)間用過幾次,哪個(gè)時(shí)候還叫Langchain-ChatGLM,感覺很不錯(cuò)。最近正好要做一個(gè)RAG系統(tǒng),就又裝了一次。這次因?yàn)槭窃赪indows上裝的,踩了點(diǎn)坑,記錄了一下。

    GitHub: https://github.com/chatchat-space/Langchain-Chatchat


    添加圖片注釋,不超過 140 字(可選)

    線性規(guī)劃說明

    什么是線性規(guī)劃?

    想象一下,您有一個(gè)線性方程組和不等式系統(tǒng)。這樣的系統(tǒng)通常有許多可能的解決方案。線性規(guī)劃是一組數(shù)學(xué)和計(jì)算工具,可讓您找到該系統(tǒng)的特定解,該解對(duì)應(yīng)于某些其他線性函數(shù)的最大值或最小值。

    什么是混合整數(shù)線性規(guī)劃?

    混合整數(shù)線性規(guī)劃是 線性規(guī)劃 的擴(kuò)展。它處理至少一個(gè)變量采用離散整數(shù)而不是連續(xù)值的問題。盡管乍一看混合整數(shù)問題與連續(xù)變量問題相似,但它們?cè)陟`活性和精度方面具有顯著優(yōu)勢。

    整數(shù)變量對(duì)于正確表示自然用整數(shù)表示的數(shù)量很重要,例如生產(chǎn)的飛機(jī)數(shù)量或服務(wù)的客戶數(shù)量。

    一種特別重要的整數(shù)變量是 二進(jìn)制變量 。它只能取 的值,在做出是或否的決定時(shí)很有用,例如是否應(yīng)該建造工廠或者是否應(yīng)該打開或關(guān)閉機(jī)器。您還可以使用它們來模擬邏輯約束。

    為什么線性規(guī)劃很重要?

    線性規(guī)劃是一種基本的優(yōu)化技術(shù),已在科學(xué)和數(shù)學(xué)密集型領(lǐng)域使用了數(shù)十年。它精確、相對(duì)快速,適用于一系列實(shí)際應(yīng)用。

    混合整數(shù)線性規(guī)劃允許您克服線性規(guī)劃的許多限制。您可以使用分段線性函數(shù)近似非線性函數(shù)、使用半連續(xù)變量、模型邏輯約束等。它是一種計(jì)算密集型工具,但計(jì)算機(jī)硬件和軟件的進(jìn)步使其每天都更加適用。

    通常,當(dāng)人們?cè)噲D制定和解決優(yōu)化問題時(shí),第一個(gè)問題是他們是否可以應(yīng)用線性規(guī)劃或混合整數(shù)線性規(guī)劃。

    以下文章說明了線性規(guī)劃和混合整數(shù)線性規(guī)劃的一些用例:

    • Gurobi 優(yōu)化案例研究
    • 線性規(guī)劃技術(shù)的五個(gè)應(yīng)用領(lǐng)域

    隨著計(jì)算機(jī)能力的增強(qiáng)、算法的改進(jìn)以及更多用戶友好的軟件解決方案的出現(xiàn),線性規(guī)劃,尤其是混合整數(shù)線性規(guī)劃的重要性隨著時(shí)間的推移而增加。

    使用 Python 進(jìn)行線性規(guī)劃

    解決線性規(guī)劃問題的基本方法稱為,它有多種變體。另一種流行的方法是。

    混合整數(shù)線性規(guī)劃問題可以通過更復(fù)雜且計(jì)算量更大的方法來解決,例如,它在幕后使用線性規(guī)劃。這種方法的一些變體是,它涉及使用 切割平面 ,以及。

    有幾種適用于線性規(guī)劃和混合整數(shù)線性規(guī)劃的合適且眾所周知的 Python 工具。其中一些是開源的,而另一些是專有的。您是否需要免費(fèi)或付費(fèi)工具取決于問題的規(guī)模和復(fù)雜性,以及對(duì)速度和靈活性的需求。

    值得一提的是,幾乎所有廣泛使用的線性規(guī)劃和混合整數(shù)線性規(guī)劃庫都是以 Fortran 或 C 或 C++ 原生和編寫的。這是因?yàn)榫€性規(guī)劃需要對(duì)(通常很大)矩陣進(jìn)行計(jì)算密集型工作。此類庫稱為求解器。Python 工具只是求解器的包裝器。

    Python 適合圍繞本機(jī)庫構(gòu)建包裝器,因?yàn)樗梢院芎玫嘏c C/C++ 配合使用。對(duì)于本教程,您不需要任何 C/C++(或 Fortran),但如果您想了解有關(guān)此酷功能的更多信息,請(qǐng)查看以下資源:

    • 構(gòu)建 Python C 擴(kuò)展模塊
    • CPython 內(nèi)部
    • 用 C 或 C++ 擴(kuò)展 Python

    基本上,當(dāng)您定義和求解模型時(shí),您使用 Python 函數(shù)或方法調(diào)用低級(jí)庫,該庫執(zhí)行實(shí)際優(yōu)化工作并將解決方案返回給您的 Python 對(duì)象。

    幾個(gè)免費(fèi)的 Python 庫專門用于與線性或混合整數(shù)線性規(guī)劃求解器交互:

    • SciPy Optimization and Root Finding
    • PuLP
    • Pyomo
    • CVXOPT

    在本教程中,您將使用SciPy和PuLP來定義和解決線性規(guī)劃問題。

    線性規(guī)劃示例

    在本節(jié)中,您將看到線性規(guī)劃問題的兩個(gè)示例:

    1. 一個(gè)說明什么是線性規(guī)劃的小問題
    2. 一個(gè)與資源分配相關(guān)的實(shí)際問題,它說明了現(xiàn)實(shí)世界場景中的線性規(guī)劃概念

    您將在下一節(jié)中使用 Python 來解決這兩個(gè)問題。

    小型線性規(guī)劃問題

    考慮以下線性規(guī)劃問題:

    你需要找到X和?使得紅色,藍(lán)色和黃色的不平等,以及不平等X ≥0和? ≥0,是滿意的。同時(shí),您的解決方案必須對(duì)應(yīng)于z的最大可能值。

    您需要找到的自變量(在本例中為 xy )稱為 決策變量 。要最大化或最小化的決策變量的函數(shù)(在本例中為 z) 稱為 目標(biāo)函數(shù)成本函數(shù) 或僅稱為 目標(biāo) 。您需要滿足的 不等式 稱為 不等式約束 。您還可以在稱為 等式約束 的約束中使用方程。

    這是您如何可視化問題的方法:

    紅線代表的功能2 X + Y=20,和它上面的紅色區(qū)域示出了紅色不等式不滿足。同樣,藍(lán)線是函數(shù)?4 x + 5 y=10,藍(lán)色區(qū)域被禁止,因?yàn)樗`反了藍(lán)色不等式。黃線是 ? x + 2 y=?2,其下方的黃色區(qū)域是黃色不等式無效的地方。

    如果您忽略紅色、藍(lán)色和黃色區(qū)域,則僅保留灰色區(qū)域。灰色區(qū)域的每個(gè)點(diǎn)都滿足所有約束,是問題的潛在解決方案。該區(qū)域稱為 可行域 ,其點(diǎn)為 可行解 。在這種情況下,有無數(shù)可行的解決方案。

    您想最大化z。對(duì)應(yīng)于最大z的可行解是 最優(yōu)解 。如果您嘗試最小化目標(biāo)函數(shù),那么最佳解決方案將對(duì)應(yīng)于其可行的最小值。

    請(qǐng)注意,z是線性的。你可以把它想象成一個(gè)三維空間中的平面。這就是為什么最優(yōu)解必須在可行區(qū)域的 頂點(diǎn) 或角上的原因。在這種情況下,最佳解決方案是紅線和藍(lán)線相交的點(diǎn),稍后您將看到。

    有時(shí),可行區(qū)域的整個(gè)邊緣,甚至整個(gè)區(qū)域,都可以對(duì)應(yīng)相同的z值。在這種情況下,您有許多最佳解決方案。

    您現(xiàn)在已準(zhǔn)備好使用綠色顯示的附加等式約束來擴(kuò)展問題:

    方程式 ? x + 5 y=15,以綠色書寫,是新的。這是一個(gè)等式約束。您可以通過向上一張圖像添加相應(yīng)的綠線來將其可視化:

    現(xiàn)在的解決方案必須滿足綠色等式,因此可行區(qū)域不再是整個(gè)灰色區(qū)域。它是綠線從與藍(lán)線的交點(diǎn)到與紅線的交點(diǎn)穿過灰色區(qū)域的部分。后一點(diǎn)是解決方案。

    如果插入x的所有值都必須是整數(shù)的要求,那么就會(huì)得到一個(gè)混合整數(shù)線性規(guī)劃問題,可行解的集合又會(huì)發(fā)生變化:

    您不再有綠線,只有沿線的x值為整數(shù)的點(diǎn)。可行解是灰色背景上的綠點(diǎn),此時(shí)最優(yōu)解離紅線最近。

    這三個(gè)例子說明了 可行的線性規(guī)劃問題 ,因?yàn)樗鼈兙哂杏薪缈尚袇^(qū)域和有限解。

    不可行的線性規(guī)劃問題

    如果沒有解,線性規(guī)劃問題是 不可行的 。當(dāng)沒有解決方案可以同時(shí)滿足所有約束時(shí),通常會(huì)發(fā)生這種情況。

    例如,考慮如果添加約束x + y ≤ ?1會(huì)發(fā)生什么。那么至少有一個(gè)決策變量(x或y)必須是負(fù)數(shù)。這與給定的約束x ≥ 0 和y ≥ 0相沖突。這樣的系統(tǒng)沒有可行的解決方案,因此稱為不可行的。

    另一個(gè)示例是添加與綠線平行的第二個(gè)等式約束。這兩行沒有共同點(diǎn),因此不會(huì)有滿足這兩個(gè)約束的解決方案。

    無界線性規(guī)劃問題

    一個(gè)線性規(guī)劃問題是 無界的 ,如果它的可行區(qū)域是無界,將溶液不是有限。這意味著您的變量中至少有一個(gè)不受約束,可以達(dá)到正無窮大或負(fù)無窮大,從而使目標(biāo)也無限大。

    例如,假設(shè)您采用上面的初始問題并刪除紅色和黃色約束。從問題中刪除約束稱為 放松 問題。在這種情況下,x和y不會(huì)在正側(cè)有界。您可以將它們?cè)黾拥秸裏o窮大,從而產(chǎn)生無限大的z值。

    資源分配問題

    在前面的部分中,您研究了一個(gè)與任何實(shí)際應(yīng)用程序無關(guān)的抽象線性規(guī)劃問題。在本小節(jié)中,您將找到與制造業(yè)資源分配相關(guān)的更具體和實(shí)用的優(yōu)化問題。

    假設(shè)一家工廠生產(chǎn)四種不同的產(chǎn)品,第一種產(chǎn)品的日產(chǎn)量為x ?,第二種產(chǎn)品的產(chǎn)量為x 2,依此類推。目標(biāo)是確定每種產(chǎn)品的利潤最大化日產(chǎn)量,同時(shí)牢記以下條件:

    1. 第一種、第二種、第三種和第四種產(chǎn)品的每單位產(chǎn)品利潤分別為 20 美元、12 美元、40 美元和 25 美元。
    2. 由于人力限制,每天生產(chǎn)的總數(shù)量不能超過五十臺(tái)。
    3. 對(duì)于每單位第一個(gè)產(chǎn)品,消耗三個(gè)單位的原材料 A。每單位第二產(chǎn)品需要兩單位原料 A 和一單位原料 B。每單位第三產(chǎn)品需要一單位 A 和兩單位 B。最后,每單位第四產(chǎn)品需要三B 的單位
    4. 由于運(yùn)輸和儲(chǔ)存的限制,工廠每天最多可以消耗一百單位的原材料 A 和九十單位的 B。

    數(shù)學(xué)模型可以這樣定義:

    目標(biāo)函數(shù)(利潤)在條件 1 中定義。人力約束遵循條件 2。對(duì)原材料 A 和 B 的約束可以從條件 3 和條件 4 中通過對(duì)每種產(chǎn)品的原材料需求求和得出。

    最后,產(chǎn)品數(shù)量不能為負(fù),因此所有決策變量必須大于或等于零。

    與前面的示例不同,您無法方便地將其可視化,因?yàn)樗兴膫€(gè)決策變量。但是,無論問題的維度如何,原理都是相同的。

    線性規(guī)劃 Python 實(shí)現(xiàn)

    在本教程中,您將使用兩個(gè)Python 包來解決上述線性規(guī)劃問題:

    1. SciPy 是一個(gè)用于使用 Python 進(jìn)行科學(xué)計(jì)算的通用包。
    2. PuLP 是一個(gè) Python 線性編程 API,用于定義問題和調(diào)用外部求解器。

    SciPy 設(shè)置起來很簡單。安裝后,您將擁有開始所需的一切。它的子包 scipy.optimize 可用于線性和非線性優(yōu)化。

    PuLP 允許您選擇求解器并以更自然的方式表述問題。PuLP 使用的默認(rèn)求解器是COIN-OR Branch and Cut Solver (CBC)。它連接到用于線性松弛的COIN-OR 線性規(guī)劃求解器 (CLP)和用于切割生成的COIN-OR 切割生成器庫 (CGL)。

    另一個(gè)偉大的開源求解器是GNU 線性規(guī)劃工具包 (GLPK)。一些著名且非常強(qiáng)大的商業(yè)和專有解決方案是Gurobi、CPLEX和XPRESS。

    除了在定義問題時(shí)提供靈活性和運(yùn)行各種求解器的能力外,PuLP 使用起來不如 Pyomo 或 CVXOPT 等替代方案復(fù)雜,后者需要更多的時(shí)間和精力來掌握。

    安裝 SciPy 和 PuLP

    要學(xué)習(xí)本教程,您需要安裝 SciPy 和 PuLP。下面的示例使用 SciPy 1.4.1 版和 PuLP 2.1 版。

    您可以使用pip以下方法安裝兩者:

    $ python -m pip install -U "scipy==1.4.*" "pulp==2.1"
    

    您可能需要運(yùn)行pulptest或sudo pulptest啟用 PuLP 的默認(rèn)求解器,尤其是在您使用 Linux 或 Mac 時(shí):

    $ pulptest
    

    或者,您可以下載、安裝和使用 GLPK。它是免費(fèi)和開源的,適用于 Windows、MacOS 和 Linux。在本教程的后面部分,您將看到如何將 GLPK(除了 CBC)與 PuLP 一起使用。

    在 Windows 上,您可以下載檔案并運(yùn)行安裝文件。

    在 MacOS 上,您可以使用 Homebrew:

    $ brew install glpk
    

    在 Debian 和 Ubuntu 上,使用apt來安裝glpk和glpk-utils:

    $ sudo apt install glpk glpk-utils
    

    在Fedora,使用dnf具有g(shù)lpk-utils:

    $ sudo dnf install glpk-utils
    

    您可能還會(huì)發(fā)現(xiàn)conda對(duì)安裝 GLPK 很有用:

    $ conda install -c conda-forge glpk
    

    安裝完成后,可以查看GLPK的版本:

    $ glpsol --version
    

    有關(guān)詳細(xì)信息,請(qǐng)參閱 GLPK 關(guān)于使用Windows 可執(zhí)行文件和Linux 軟件包進(jìn)行安裝的教程。

    使用 SciPy

    在本節(jié)中,您將學(xué)習(xí)如何使用 SciPy優(yōu)化和求根庫進(jìn)行線性規(guī)劃。

    要使用 SciPy 定義和解決優(yōu)化問題,您需要導(dǎo)入scipy.optimize.linprog():

    >>>
    >>> from scipy.optimize import linprog
    

    現(xiàn)在您已經(jīng)linprog()導(dǎo)入,您可以開始優(yōu)化。

    示例 1

    讓我們首先解決上面的線性規(guī)劃問題:

    linprog()僅解決最小化(而非最大化)問題,并且不允許具有大于或等于符號(hào) (≥) 的不等式約束。要解決這些問題,您需要在開始優(yōu)化之前修改您的問題:

    • 不是最大化z=x + 2 y,你可以最小化它的負(fù)值(? z=? x ? 2 y)。
    • 代替大于或等于符號(hào),您可以將黃色不等式乘以 -1 并得到小于或等于符號(hào) (≤) 的相反數(shù)。

    引入這些更改后,您將獲得一個(gè)新系統(tǒng):

    該系統(tǒng)與原始系統(tǒng)等效,并且將具有相同的解決方案。應(yīng)用這些更改的唯一原因是克服 SciPy 與問題表述相關(guān)的局限性。

    下一步是定義輸入值:

    >>>
    >>> obj=[-1, -2]
    >>> #      ─┬  ─┬
    >>> #       │   └┤ Coefficient for y
    >>> #       └────┤ Coefficient for x
    
    >>> lhs_ineq=[[ 2,  1],  # Red constraint left side
    ...             [-4,  5],  # Blue constraint left side
    ...             [ 1, -2]]  # Yellow constraint left side
    
    >>> rhs_ineq=[20,  # Red constraint right side
    ...             10,  # Blue constraint right side
    ...              2]  # Yellow constraint right side
    
    >>> lhs_eq=[[-1, 5]]  # Green constraint left side
    >>> rhs_eq=[15]       # Green constraint right side
    

    您將上述系統(tǒng)中的值放入適當(dāng)?shù)牧斜怼⒃M或NumPy 數(shù)組中:

    • obj 保存目標(biāo)函數(shù)的系數(shù)。
    • lhs_ineq 保存不等式(紅色、藍(lán)色和黃色)約束的左側(cè)系數(shù)。
    • rhs_ineq 保存不等式(紅色、藍(lán)色和黃色)約束的右側(cè)系數(shù)。
    • lhs_eq 保存來自等式(綠色)約束的左側(cè)系數(shù)。
    • rhs_eq 保存來自等式(綠色)約束的右側(cè)系數(shù)。

    注意:請(qǐng)注意行和列的順序!

    約束左側(cè)和右側(cè)的行順序必須相同。每一行代表一個(gè)約束。

    來自目標(biāo)函數(shù)和約束左側(cè)的系數(shù)的順序必須匹配。每列對(duì)應(yīng)一個(gè)決策變量。

    下一步是以與系數(shù)相同的順序定義每個(gè)變量的界限。在這種情況下,它們都在零和正無窮大之間:

    >>>
    >>> bnd=[(0, float("inf")),  # Bounds of x
    ...        (0, float("inf"))]  # Bounds of y
    

    此語句是多余的,因?yàn)閘inprog()默認(rèn)情況下采用這些邊界(零到正無窮大)。

    注:相反的float("inf"),你可以使用math.inf,numpy.inf或scipy.inf。

    最后,是時(shí)候優(yōu)化和解決您感興趣的問題了。你可以這樣做linprog():

    >>>
    >>> opt=linprog(c=obj, A_ub=lhs_ineq, b_ub=rhs_ineq,
    ...               A_eq=lhs_eq, b_eq=rhs_eq, bounds=bnd,
    ...               method="revised simplex")
    >>> opt
         con: array([0.])
         fun: -16.818181818181817
     message: 'Optimization terminated successfully.'
         nit: 3
       slack: array([ 0.        , 18.18181818,  3.36363636])
      status: 0
     success: True
           x: array([7.72727273, 4.54545455])
    

    參數(shù)c是指來自目標(biāo)函數(shù)的系數(shù)。A_ub和b_ub分別與不等式約束左邊和右邊的系數(shù)有關(guān)。同樣,A_eq并b_eq參考等式約束。您可以使用bounds提供決策變量的下限和上限。

    您可以使用該參數(shù)method來定義要使用的線性規(guī)劃方法。有以下三種選擇:

    1. method="interior-point" 選擇內(nèi)點(diǎn)法。默認(rèn)情況下設(shè)置此選項(xiàng)。
    2. method="revised simplex" 選擇修正的兩相單純形法。
    3. method="simplex" 選擇傳統(tǒng)的兩相單純形方法。

    linprog() 返回具有以下屬性的數(shù)據(jù)結(jié)構(gòu):

    • .con 是等式約束殘差。
    • .fun 是最優(yōu)的目標(biāo)函數(shù)值(如果找到)。
    • .message 是解決方案的狀態(tài)。
    • .nit 是完成計(jì)算所需的迭代次數(shù)。
    • .slack 是松弛變量的值,或約束左右兩側(cè)的值之間的差異。
    • .status 是一個(gè)介于0和之間的整數(shù)4,表示解決方案的狀態(tài),例如0找到最佳解決方案的時(shí)間。
    • .success 是一個(gè)布爾值,顯示是否已找到最佳解決方案。
    • .x 是一個(gè)保存決策變量最優(yōu)值的 NumPy 數(shù)組。

    您可以分別訪問這些值:

    >>>
    >>> opt.fun
    -16.818181818181817
    
    >>> opt.success
    True
    
    >>> opt.x
    array([7.72727273, 4.54545455])
    

    這就是您獲得優(yōu)化結(jié)果的方式。您還可以以圖形方式顯示它們:

    如前所述,線性規(guī)劃問題的最優(yōu)解位于可行區(qū)域的頂點(diǎn)。在這種情況下,可行區(qū)域只是藍(lán)線和紅線之間的綠線部分。最優(yōu)解是代表綠線和紅線交點(diǎn)的綠色方塊。

    如果要排除相等(綠色)約束,只需刪除參數(shù)A_eq并b_eq從linprog()調(diào)用中刪除:

    >>>
    >>> opt=linprog(c=obj, A_ub=lhs_ineq, b_ub=rhs_ineq, bounds=bnd,
    ...               method="revised simplex")
    >>> opt
         con: array([], dtype=float64)
         fun: -20.714285714285715
     message: 'Optimization terminated successfully.'
         nit: 2
       slack: array([0.        , 0.        , 9.85714286])
      status: 0
     success: True
           x: array([6.42857143, 7.14285714]))
    

    解決方案與前一種情況不同。你可以在圖表上看到:

    在這個(gè)例子中,最優(yōu)解是紅色和藍(lán)色約束相交的可行(灰色)區(qū)域的紫色頂點(diǎn)。其他頂點(diǎn),如黃色頂點(diǎn),具有更高的目標(biāo)函數(shù)值。

    示例 2

    您可以使用 SciPy 來解決前面部分所述的資源分配問題:

    和前面的例子一樣,你需要從上面的問題中提取必要的向量和矩陣,將它們作為參數(shù)傳遞給.linprog(),然后得到結(jié)果:

    >>>
    >>> obj=[-20, -12, -40, -25]
    
    >>> lhs_ineq=[[1, 1, 1, 1],  # Manpower
    ...             [3, 2, 1, 0],  # Material A
    ...             [0, 1, 2, 3]]  # Material B
    
    >>> rhs_ineq=[ 50,  # Manpower
    ...             100,  # Material A
    ...              90]  # Material B
    
    >>> opt=linprog(c=obj, A_ub=lhs_ineq, b_ub=rhs_ineq,
    ...               method="revised simplex")
    >>> opt
         con: array([], dtype=float64)
         fun: -1900.0
     message: 'Optimization terminated successfully.'
         nit: 2
       slack: array([ 0., 40.,  0.])
      status: 0
     success: True
           x: array([ 5.,  0., 45.,  0.])
    

    結(jié)果告訴您最大利潤是1900并且對(duì)應(yīng)于x ?=5 和x ?=45。在給定條件下生產(chǎn)第二和第四個(gè)產(chǎn)品是沒有利潤的。您可以在這里得出幾個(gè)有趣的結(jié)論:

    1. 第三個(gè)產(chǎn)品帶來的單位利潤最大,因此工廠將生產(chǎn)最多。
    2. 第一個(gè)slack是0,表示人力(第一)約束左右兩邊的值是一樣的。工廠每天50生產(chǎn)單位,這是它的全部產(chǎn)能。
    3. 第二個(gè)松弛是40因?yàn)楣S消耗了 60 單位的原材料 A(第一種產(chǎn)品為 15 單位,第三種產(chǎn)品為 45100單位)。
    4. 第三個(gè)裕量是0,這意味著工廠消耗了所有90單位的原材料 B。這全部量都用于第三個(gè)產(chǎn)品。這就是為什么工廠根本不能生產(chǎn)第二或第四種產(chǎn)品,也不能生產(chǎn)超過45單位的第三種產(chǎn)品。缺乏原材料 B.

    opt.statusis0和opt.successis True,說明優(yōu)化問題成功求解,最優(yōu)可行解。

    SciPy 的線性規(guī)劃功能主要用于較小的問題。對(duì)于更大和更復(fù)雜的問題,您可能會(huì)發(fā)現(xiàn)其他庫更適合,原因如下:

    • SciPy 無法運(yùn)行各種外部求解器。
    • SciPy 不能使用整數(shù)決策變量。
    • SciPy 不提供促進(jìn)模型構(gòu)建的類或函數(shù)。您必須定義數(shù)組和矩陣,這對(duì)于大型問題來說可能是一項(xiàng)乏味且容易出錯(cuò)的任務(wù)。
    • SciPy 不允許您直接定義最大化問題。您必須將它們轉(zhuǎn)換為最小化問題。
    • SciPy 不允許您直接使用大于或等于符號(hào)來定義約束。您必須改用小于或等于。

    幸運(yùn)的是,Python 生態(tài)系統(tǒng)為線性編程提供了幾種替代解決方案,這些解決方案對(duì)于更大的問題非常有用。其中之一是 PuLP,您將在下一節(jié)中看到它的實(shí)際應(yīng)用。

    Using PuLP

    PuLP 具有比 SciPy 更方便的線性編程 API。您不必在數(shù)學(xué)上修改您的問題或使用向量和矩陣。一切都更干凈,更不容易出錯(cuò)。

    像往常一樣,您首先導(dǎo)入您需要的內(nèi)容:

    from pulp import LpMaximize, LpProblem, LpStatus, lpSum, LpVariable
    

    現(xiàn)在您已經(jīng)導(dǎo)入了 PuLP,您可以解決您的問題。

    示例 1

    您現(xiàn)在將使用 PuLP 解決此系統(tǒng):

    第一步是初始化一個(gè)實(shí)例LpProblem來表示你的模型:

    # Create the model
    model=LpProblem(name="small-problem", sense=LpMaximize)
    

    您可以使用該sense參數(shù)來選擇是執(zhí)行最小化(LpMinimize或1,這是默認(rèn)值)還是最大化(LpMaximize或-1)。這個(gè)選擇會(huì)影響你的問題的結(jié)果。

    一旦有了模型,就可以將決策變量定義為LpVariable類的實(shí)例:

    # Initialize the decision variables
    x=LpVariable(name="x", lowBound=0)
    y=LpVariable(name="y", lowBound=0)
    

    您需要提供下限,lowBound=0因?yàn)槟J(rèn)值為負(fù)無窮大。該參數(shù)upBound定義了上限,但您可以在此處省略它,因?yàn)樗J(rèn)為正無窮大。

    可選參數(shù)cat定義決策變量的類別。如果您使用的是連續(xù)變量,則可以使用默認(rèn)值"Continuous"。

    您可以使用變量x和y創(chuàng)建表示線性表達(dá)式和約束的其他 PuLP 對(duì)象:

    >>>
    >>> expression=2 * x + 4 * y
    >>> type(expression)
    <class 'pulp.pulp.LpAffineExpression'>
    
    >>> constraint=2 * x + 4 * y >=8
    >>> type(constraint)
    <class 'pulp.pulp.LpConstraint'>
    

    當(dāng)您將決策變量與標(biāo)量相乘或構(gòu)建多個(gè)決策變量的線性組合時(shí),您會(huì)得到一個(gè)pulp.LpAffineExpression代表線性表達(dá)式的實(shí)例。

    注意:您可以增加或減少變量或表達(dá)式,你可以乘他們常數(shù),因?yàn)榧垵{類實(shí)現(xiàn)一些Python的特殊方法,即模擬數(shù)字類型一樣__add__(),__sub__()和__mul__()。這些方法用于像定制運(yùn)營商的行為+,-和*。

    類似地,您可以將線性表達(dá)式、變量和標(biāo)量與運(yùn)算符==、<=、 或>=以獲取表示模型線性約束的紙漿.LpConstraint實(shí)例。

    注:也有可能與豐富的比較方法來構(gòu)建的約束.__eq__(),.__le__()以及.__ge__()定義了運(yùn)營商的行為==,<=和>=。

    考慮到這一點(diǎn),下一步是創(chuàng)建約束和目標(biāo)函數(shù)并將它們分配給您的模型。您不需要?jiǎng)?chuàng)建列表或矩陣。只需編寫 Python 表達(dá)式并使用+=運(yùn)算符將它們附加到模型中:

    # Add the constraints to the model
    model +=(2 * x + y <=20, "red_constraint")
    model +=(4 * x - 5 * y >=-10, "blue_constraint")
    model +=(-x + 2 * y >=-2, "yellow_constraint")
    model +=(-x + 5 * y==15, "green_constraint")
    

    在上面的代碼中,您定義了包含約束及其名稱的元組。LpProblem允許您通過將約束指定為元組來向模型添加約束。第一個(gè)元素是一個(gè)LpConstraint實(shí)例。第二個(gè)元素是該約束的可讀名稱。

    設(shè)置目標(biāo)函數(shù)非常相似:

    # Add the objective function to the model
    obj_func=x + 2 * y
    model +=obj_func
    

    或者,您可以使用更短的符號(hào):

    # Add the objective function to the model
    model +=x + 2 * y
    

    現(xiàn)在您已經(jīng)添加了目標(biāo)函數(shù)并定義了模型。

    注意:您可以使用運(yùn)算符將?約束或目標(biāo)附加到模型中,+=因?yàn)樗念怢pProblem實(shí)現(xiàn)了特殊方法.__iadd__(),該方法用于指定 的行為+=。

    對(duì)于較大的問題,lpSum()與列表或其他序列一起使用通常比重復(fù)+運(yùn)算符更方便。例如,您可以使用以下語句將目標(biāo)函數(shù)添加到模型中:

    # Add the objective function to the model
    model +=lpSum([x, 2 * y])
    

    它產(chǎn)生與前一條語句相同的結(jié)果。

    您現(xiàn)在可以看到此模型的完整定義:

    >>>
    >>> model
    small-problem:
    MAXIMIZE
    1*x + 2*y + 0
    SUBJECT TO
    red_constraint: 2 x + y <=20
    
    blue_constraint: 4 x - 5 y >=-10
    
    yellow_constraint: - x + 2 y >=-2
    
    green_constraint: - x + 5 y=15
    
    VARIABLES
    x Continuous
    y Continuous
    

    模型的字符串表示包含所有相關(guān)數(shù)據(jù):變量、約束、目標(biāo)及其名稱。

    注意:字符串表示是通過定義特殊方法構(gòu)建的.__repr__()。有關(guān) 的更多詳細(xì)信息.__repr__(),請(qǐng)查看Pythonic OOP 字符串轉(zhuǎn)換:__repr__vs__str__ .

    最后,您已準(zhǔn)備好解決問題。你可以通過調(diào)用.solve()你的模型對(duì)象來做到這一點(diǎn)。如果要使用默認(rèn)求解器 (CBC),則不需要傳遞任何參數(shù):

    # Solve the problem
    status=model.solve()
    

    .solve()調(diào)用底層求解器,修改model對(duì)象,并返回解決方案的整數(shù)狀態(tài),1如果找到了最優(yōu)解。有關(guān)其余狀態(tài)代碼,請(qǐng)參閱LpStatus[]。

    你可以得到優(yōu)化結(jié)果作為 的屬性model。該函數(shù)value()和相應(yīng)的方法.value()返回屬性的實(shí)際值:

    >>>
    >>> print(f"status: {model.status}, {LpStatus[model.status]}")
    status: 1, Optimal
    
    >>> print(f"objective: {model.objective.value()}")
    objective: 16.8181817
    
    >>> for var in model.variables():
    ...     print(f"{var.name}: {var.value()}")
    ...
    x: 7.7272727
    y: 4.5454545
    
    >>> for name, constraint in model.constraints.items():
    ...     print(f"{name}: {constraint.value()}")
    ...
    red_constraint: -9.99999993922529e-08
    blue_constraint: 18.181818300000003
    yellow_constraint: 3.3636362999999996
    green_constraint: -2.0000000233721948e-07)
    

    model.objective持有目標(biāo)函數(shù)model.constraints的值,包含松弛變量的值,以及對(duì)象x和y具有決策變量的最優(yōu)值。model.variables()返回一個(gè)包含決策變量的列表:

    >>>
    >>> model.variables()
    [x, y]
    >>> model.variables()[0] is x
    True
    >>> model.variables()[1] is y
    True
    

    如您所見,此列表包含使用 的構(gòu)造函數(shù)創(chuàng)建的確切對(duì)象LpVariable。

    結(jié)果與您使用 SciPy 獲得的結(jié)果大致相同。

    注意:注意這個(gè)方法.solve()——它會(huì)改變對(duì)象的狀態(tài),x并且y!

    您可以通過調(diào)用查看使用了哪個(gè)求解器.solver:

    >>>
    >>> model.solver
    <pulp.apis.coin_api.PULP_CBC_CMD object at 0x7f60aea19e50>
    

    輸出通知您求解器是 CBC。您沒有指定求解器,因此 PuLP 調(diào)用了默認(rèn)求解器。

    如果要運(yùn)行不同的求解器,則可以將其指定為 的參數(shù).solve()。例如,如果您想使用 GLPK 并且已經(jīng)安裝了它,那么您可以solver=GLPK(msg=False)在最后一行使用。請(qǐng)記住,您還需要導(dǎo)入它:

    from pulp import GLPK
    

    現(xiàn)在你已經(jīng)導(dǎo)入了 GLPK,你可以在里面使用它.solve():

    # Create the model
    model=LpProblem(name="small-problem", sense=LpMaximize)
    
    # Initialize the decision variables
    x=LpVariable(name="x", lowBound=0)
    y=LpVariable(name="y", lowBound=0)
    
    # Add the constraints to the model
    model +=(2 * x + y <=20, "red_constraint")
    model +=(4 * x - 5 * y >=-10, "blue_constraint")
    model +=(-x + 2 * y >=-2, "yellow_constraint")
    model +=(-x + 5 * y==15, "green_constraint")
    
    # Add the objective function to the model
    model +=lpSum([x, 2 * y])
    
    # Solve the problem
    status=model.solve(solver=GLPK(msg=False))
    

    該msg參數(shù)用于顯示來自求解器的信息。msg=False禁用顯示此信息。如果要包含信息,則只需省略msg或設(shè)置msg=True。

    您的模型已定義并求解,因此您可以按照與前一種情況相同的方式檢查結(jié)果:

    >>>
    >>> print(f"status: {model.status}, {LpStatus[model.status]}")
    status: 1, Optimal
    
    >>> print(f"objective: {model.objective.value()}")
    objective: 16.81817
    
    >>> for var in model.variables():
    ...     print(f"{var.name}: {var.value()}")
    ...
    x: 7.72727
    y: 4.54545
    
    >>> for name, constraint in model.constraints.items():
    ...     print(f"{name}: {constraint.value()}")
    ...
    red_constraint: -1.0000000000509601e-05
    blue_constraint: 18.181830000000005
    yellow_constraint: 3.3636299999999997
    green_constraint: -2.000000000279556e-05
    

    使用 GLPK 得到的結(jié)果與使用 SciPy 和 CBC 得到的結(jié)果幾乎相同。

    一起來看看這次用的是哪個(gè)求解器:

    >>>
    >>> model.solver
    <pulp.apis.glpk_api.GLPK_CMD object at 0x7f60aeb04d50>
    

    正如您在上面用突出顯示的語句定義的那樣model.solve(solver=GLPK(msg=False)),求解器是 GLPK。

    您還可以使用 PuLP 來解決混合整數(shù)線性規(guī)劃問題。要定義整數(shù)或二進(jìn)制變量,只需傳遞cat="Integer"或cat="Binary"到LpVariable。其他一切都保持不變:

    # Create the model
    model=LpProblem(name="small-problem", sense=LpMaximize)
    
    # Initialize the decision variables: x is integer, y is continuous
    x=LpVariable(name="x", lowBound=0, cat="Integer")
    y=LpVariable(name="y", lowBound=0)
    
    # Add the constraints to the model
    model +=(2 * x + y <=20, "red_constraint")
    model +=(4 * x - 5 * y >=-10, "blue_constraint")
    model +=(-x + 2 * y >=-2, "yellow_constraint")
    model +=(-x + 5 * y==15, "green_constraint")
    
    # Add the objective function to the model
    model +=lpSum([x, 2 * y])
    
    # Solve the problem
    status=model.solve()
    

    在本例中,您有一個(gè)整數(shù)變量并獲得與之前不同的結(jié)果:

    >>>
    >>> print(f"status: {model.status}, {LpStatus[model.status]}")
    status: 1, Optimal
    
    >>> print(f"objective: {model.objective.value()}")
    objective: 15.8
    
    >>> for var in model.variables():
    ...     print(f"{var.name}: {var.value()}")
    ...
    x: 7.0
    y: 4.4
    
    >>> for name, constraint in model.constraints.items():
    ...     print(f"{name}: {constraint.value()}")
    ...
    red_constraint: -1.5999999999999996
    blue_constraint: 16.0
    yellow_constraint: 3.8000000000000007
    green_constraint: 0.0)
    
    >>> model.solver
    <pulp.apis.coin_api.PULP_CBC_CMD at 0x7f0f005c6210>
    

    Nowx是一個(gè)整數(shù),如模型中所指定。(從技術(shù)上講,它保存一個(gè)小數(shù)點(diǎn)后為零的浮點(diǎn)值。)這一事實(shí)改變了整個(gè)解決方案。讓我們?cè)趫D表上展示這一點(diǎn):

    如您所見,最佳解決方案是灰色背景上最右邊的綠點(diǎn)。這是兩者的最大價(jià)值的可行的解決方案x和y,給它的最大目標(biāo)函數(shù)值。

    GLPK 也能夠解決此類問題。

    示例 2

    現(xiàn)在你可以使用 PuLP 來解決上面的資源分配問題:

    定義和解決問題的方法與前面的示例相同:

    # Define the model
    model=LpProblem(name="resource-allocation", sense=LpMaximize)
    
    # Define the decision variables
    x={i: LpVariable(name=f"x{i}", lowBound=0) for i in range(1, 5)}
    
    # Add constraints
    model +=(lpSum(x.values()) <=50, "manpower")
    model +=(3 * x[1] + 2 * x[2] + x[3] <=100, "material_a")
    model +=(x[2] + 2 * x[3] + 3 * x[4] <=90, "material_b")
    
    # Set the objective
    model +=20 * x[1] + 12 * x[2] + 40 * x[3] + 25 * x[4]
    
    # Solve the optimization problem
    status=model.solve()
    
    # Get the results
    print(f"status: {model.status}, {LpStatus[model.status]}")
    print(f"objective: {model.objective.value()}")
    
    for var in x.values():
        print(f"{var.name}: {var.value()}")
    
    for name, constraint in model.constraints.items():
        print(f"{name}: {constraint.value()}")
    

    在這種情況下,您使用字典 x來存儲(chǔ)所有決策變量。這種方法很方便,因?yàn)樽值淇梢詫Q策變量的名稱或索引存儲(chǔ)為鍵,將相應(yīng)的LpVariable對(duì)象存儲(chǔ)為值。列表或元組的LpVariable實(shí)例可以是有用的。

    上面的代碼產(chǎn)生以下結(jié)果:

    status: 1, Optimal
    objective: 1900.0
    x1: 5.0
    x2: 0.0
    x3: 45.0
    x4: 0.0
    manpower: 0.0
    material_a: -40.0
    material_b: 0.0
    

    如您所見,該解決方案與使用 SciPy 獲得的解決方案一致。最有利可圖的解決方案是每天生產(chǎn)5.0第一件產(chǎn)品和45.0第三件產(chǎn)品。

    讓我們把這個(gè)問題變得更復(fù)雜和有趣。假設(shè)由于機(jī)器問題,工廠無法同時(shí)生產(chǎn)第一種和第三種產(chǎn)品。在這種情況下,最有利可圖的解決方案是什么?

    現(xiàn)在您有另一個(gè)邏輯約束:如果x ? 為正數(shù),則x ? 必須為零,反之亦然。這是二元決策變量非常有用的地方。您將使用兩個(gè)二元決策變量y ? 和y ?,它們將表示是否生成了第一個(gè)或第三個(gè)產(chǎn)品:

     1model=LpProblem(name="resource-allocation", sense=LpMaximize)
     2
     3# Define the decision variables
     4x={i: LpVariable(name=f"x{i}", lowBound=0) for i in range(1, 5)}
     5y={i: LpVariable(name=f"y{i}", cat="Binary") for i in (1, 3)}
     6
     7# Add constraints
     8model +=(lpSum(x.values()) <=50, "manpower")
     9model +=(3 * x[1] + 2 * x[2] + x[3] <=100, "material_a")
    10model +=(x[2] + 2 * x[3] + 3 * x[4] <=90, "material_b")
    11
    12M=100
    13model +=(x[1] <=y[1] * M, "x1_constraint")
    14model +=(x[3] <=y[3] * M, "x3_constraint")
    15model +=(y[1] + y[3] <=1, "y_constraint")
    16
    17# Set objective
    18model +=20 * x[1] + 12 * x[2] + 40 * x[3] + 25 * x[4]
    19
    20# Solve the optimization problem
    21status=model.solve()
    22
    23print(f"status: {model.status}, {LpStatus[model.status]}")
    24print(f"objective: {model.objective.value()}")
    25
    26for var in model.variables():
    27    print(f"{var.name}: {var.value()}")
    28
    29for name, constraint in model.constraints.items():
    30    print(f"{name}: {constraint.value()}")
    

    除了突出顯示的行之外,代碼與前面的示例非常相似。以下是差異:

    • 第 5 行 定義了二元決策變量y[1]并y[3]保存在字典中y。
    • 第 12 行 定義了一個(gè)任意大的數(shù)M。100在這種情況下,該值足夠大,因?yàn)槟?00每天的數(shù)量不能超過單位。
    • 第 13 行 說如果y[1]為零,則x[1]必須為零,否則它可以是任何非負(fù)數(shù)。
    • 第 14 行 說如果y[3]為零,則x[3]必須為零,否則它可以是任何非負(fù)數(shù)。
    • 第 15 行 說要么y[1]ory[3]為零(或兩者都是),所以要么x[1]or 也x[3]必須為零。

    這是解決方案:

    status: 1, Optimal
    objective: 1800.0
    x1: 0.0
    x2: 0.0
    x3: 45.0
    x4: 0.0
    y1: 0.0
    y3: 1.0
    manpower: -5.0
    material_a: -55.0
    material_b: 0.0
    x1_constraint: 0.0
    x3_constraint: -55.0
    y_constraint: 0.0
    

    事實(shí)證明,最佳方法是排除第一種產(chǎn)品而只生產(chǎn)第三種產(chǎn)品。

    線性規(guī)劃求解器

    就像有許多資源可以幫助您學(xué)習(xí)線性規(guī)劃和混合整數(shù)線性規(guī)劃一樣,還有許多具有 Python 包裝器的求解器可用。這是部分列表:

    • GLPK
    • LP Solve
    • CLP
    • CBC
    • CVXOPT
    • SciPy
    • SCIP with PySCIPOpt
    • Gurobi Optimizer
    • CPLEX
    • XPRESS
    • MOSEK

    其中一些庫,如 Gurobi,包括他們自己的 Python 包裝器。其他人使用外部包裝器。例如,您看到可以使用 PuLP 訪問 CBC 和 GLPK。

    結(jié)論

    您現(xiàn)在知道什么是線性規(guī)劃以及如何使用 Python 解決線性規(guī)劃問題。您還了解到 Python 線性編程庫只是本機(jī)求解器的包裝器。當(dāng)求解器完成其工作時(shí),包裝器返回解決方案狀態(tài)、決策變量值、松弛變量、目標(biāo)函數(shù)等。

網(wǎng)站首頁   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號(hào):冀ICP備2024067069號(hào)-3 北京科技有限公司版權(quán)所有