最適化モデル(2) 非線形計画法の詳しい解説と例題、Scipy.optimizeで非線形計画法を解く

数学モデリングの一連の記事:

以下は、National Digital Analog Competition の準備中に私がコンパイルしたモデル アルゴリズムとコードの一部です。時間があるときに内容を更新します:
評価モデル (1) 分析階層プロセス (AHP) 、エントロピー重み法、TOPSIS 分析とそれに対応する PYTHON 実装コードと例の説明
評価モデル (2) 主成分分析、因子分析、両者の比較PYTHON の実装コードと例の説明
最適化モデル (ゼロ) さまざまな最適化モデルの概要、分類、分析と普遍的な問題解決手順
最適化モデル (1)線形計画法の詳しい説明と例題、Python の Pulp ライブラリ関数を使って線形計画法を解く
最適化モデル (2) 非線形計画法の詳しい解説と例題、Scipy.optimize で非線形計画法を解く >

3.3 Scipy.optimize は非線形計画法を解決します

非線形計画法の概要:

目的関数f(x)または制約条件のいずれかが決定変数Xの非線形表現である場合、このときの数理計画問題は非線形計画問題に属する。非線形計画法を解くことは、線形計画法よりもはるかに困難です。現在、普遍的なアルゴリズムはありません。ほとんどのアルゴリズムは、決定変数の初期値を選択した後、特定の検索アルゴリズムを通じて最適な決定変数を探します。この記事で使用されている方法は、Scipy ライブラリのいくつかの機能に基づいています。

scipy ソリューション プロセス – プログラミング手順:

  1. scipy、numpy パッケージをインポートします。
  2. は目的関数 objf3(x) を定義し、入力変数 x はベクトルを表し、戻り値 fx は目的関数の計算結果です。 デフォルトは min です (最大値が必要な場合は、負符号 -min を追加します)
  3. 境界制約、つまり最適化変数の上限と下限を定義します。
    • minimize() デフォルトでは境界制約はありません。つまり、各変数の値の範囲に制限はありません。あ>
    • 境界制約を設定する場合は、独立変数(決定変数)ごとに上限値と下限値を定義する必要がありますので、境界制約の定義形式に注意してください。
  4. 引数に上限(下限)がない場合は、 None と表現されます。
    x の初期値を定義します。
  5. 最小化問題 resRosen を解きます。目的関数 objf3 と探索の初期値点 xIni が必要ですが、最適化方法と境界条件の指定はオプションです。 最適化問題が最大値 maxFx を見つけることである場合、minFx = - maxFx の変換によって達成できます
  6. 最適点 xOpt は、最小化問題からの resRosen.x の戻り値を呼び出すことによって取得されます。

Scipy.optimizeパラメータの説明:

minimize(fun,x0,method,bounds,constraints)最小化関数を解く

fun: 最初のステップで定義した目的関数。

x0: リストまたはタプルの形式での推測解または初期解、通常は N 次元配列オブジェクト ndarray;;

method: 通常は「SLSQP」(逐次最小二乗プログラミング) を入力します。

bounds: 変数境界/値範囲; b0 = (0.0, None) # 0.0 <= x[0] <= Inf None == 無限大

constraints: (制約) 以前に定義され、ここで呼び出されます。

jac: オプション**、** 目的関数のヤコビ行列 (目的関数の一次偏導関数)。これらのメソッドでは、CG、BFGS、Newton-CG、L-BfFGS-B、TNC、SLSQP、dogleg、trust-ncg が使用されます。

cons: 制限関数 cons = ({‘type’: ‘eq’, ‘fun’: lambda x:f(x)})

cons = ({‘type’:‘eq’,‘fun’: ラムダ x: x[0]*x[1]*x[2]-12})

type: 制約のタイプ eq は方程式です ineq は不等式です。

lambda: これは制約関数式です。デフォルトでは、変数を左側に抽出します。記号は >= の不等式です。たとえば、 lambda x: x[0]*x[1]*x[2]-12 x*y*z>=12 を意味します。 <= が必要な場合は、負符号を抽出するだけです。たとえば、この -(x*y*z)>=-12 は を意味します。 (x*y*z) <= 12, if 待ちたくない場合は、1e-20 などの非常に小さな数値を追加してください。たとえば、ラムダ x: x[0]*x[1]*x[2]-12-1e-20 は とほぼ同じになります。x*y*z>12

コードの説明 1:

from scipy.optimize import brent, fmin, minimize
import numpy as np

# 多变量边界约束优化问题(Scipy.optimize.minimize)
# 定义目标函数
def objf3(x):  # Rosenbrock 测试函数
    fx = x[0]+2*x[1]+3*x[2]+1
    return fx

cons = ({
    
    'type':'eq','fun': lambda x: x[0]*x[1]*x[2]-12})

# 定义没一个变量边界约束(优化变量的上下限)
b0 = (0.0, None)  # 0.0 <= x[0] <= Inf
b1 = (0.0, None)  # 0.0 <= x[1] <= Inf
b2 = (0.0, None)  # 0.0 <= x[2] <= Inf
bnds = (b0, b1, b2)  # 边界约束

# 优化计算
xIni = np.array([1., 2., 3.]) # 定义初始值
resRosen = minimize(objf3, xIni, method='SLSQP',constraints = cons ,bounds=bnds)
xOpt = resRosen.x

print("xOpt = {:.4f}, {:.4f}, {:.4f}".format(xOpt[0],xOpt[1],xOpt[2]))
print("min f(x) = {:.4f}".format(objf3(xOpt)))

コードの説明 2:

次の最適化関数を解きます。
ここに画像の説明を挿入します

from scipy.optimize import brent, fmin, minimize
import numpy as np

# 约束非线性规划问题(Scipy.optimize.minimize)
def objF6(args):  # 定义目标函数
    a,b,c,d = args
    fx = lambda x: a*x[0]**2 + b*x[1]**2 + c*x[2]**2 + d
    return fx

def constraint2(args):
    xmin0, xmin1, xmin2 = args
    cons = ({
    
    'type': 'ineq', 'fun': lambda x: (x[0]**2 - x[1] + x[2]**2)},  # 不等式约束 f(x)>=0
            {
    
    'type': 'ineq', 'fun': lambda x: -(x[0] + x[1]**2 + x[2]**3 - 20)},  # 不等式约束 转换为标准形式
            {
    
    'type': 'eq', 'fun': lambda x: (-x[0] - x[1]**2 + 2)},  # 等式约束
            {
    
    'type': 'eq', 'fun': lambda x: (x[1] + 2*x[2]**2 - 3)},  # 等式约束
            {
    
    'type': 'ineq', 'fun': lambda x: (x[0] - xmin0)},  # x0 >= xmin0
            {
    
    'type': 'ineq', 'fun': lambda x: (x[1] - xmin1)},  # x1 >= xmin1
            {
    
    'type': 'ineq', 'fun': lambda x: (x[2] - xmin2)})  # x2 >= xmin2
    return cons

# 求解优化问题
args1 = (1,2,3,8)  # 定义目标函数中的参数
args2 = (0.0, 0.0, 0.0)  # xmin0, xmin1, xmin2
cons2 = constraint2(args2)

x0 = np.array([1., 2., 3.])  # 定义搜索的初值
res2 = minimize(objF6(args1), x0, method='SLSQP', constraints=cons2)

print("Optimization problem (res2):\t{}".format(res2.message))  # 优化是否成功
print("xOpt = {}".format(res2.x))  # 自变量的优化值
print("min f(x) = {:.4f}".format(res2.fun))  # 目标函数的优化值

制約は次のように定義することもできます。

# 定义约束条件函数
def constraint1(x):  # 不等式约束 f(x)>=0
    return x[0]** 2 - x[1] + x[2]**2
def constraint2(x):  # 不等式约束 转换为标准形式
    return -(x[0] + x[1]**2 + x[2]**3 - 20)
def constraint3(x):  # 等式约束
    return -x[0] - x[1]**2 + 2
def constraint4(x):  # 等式约束
    return x[1] + 2*x[2]**2 -3

# 定义边界约束
b = (0.0, None)
bnds = (b, b, b)

# 定义约束条件
con1 = {
    
    'type': 'ineq', 'fun': constraint1}
con2 = {
    
    'type': 'ineq', 'fun': constraint2}
con3 = {
    
    'type': 'eq', 'fun': constraint3}
con4 = {
    
    'type': 'eq', 'fun': constraint4}
cons = ([con1, con2, con3,con4])  # 3个约束条件

参考文献:

Python初心者のための数理モデリング講座-12.非線形プログラミング

おすすめ

転載: blog.csdn.net/m0_63669388/article/details/132703640