数学モデリングの一連の記事:
以下は、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 ソリューション プロセス – プログラミング手順:
- scipy、numpy パッケージをインポートします。
- は目的関数 objf3(x) を定義し、入力変数 x はベクトルを表し、戻り値 fx は目的関数の計算結果です。 デフォルトは min です (最大値が必要な場合は、負符号 -min を追加します)
- 境界制約、つまり最適化変数の上限と下限を定義します。
- minimize() デフォルトでは境界制約はありません。つまり、各変数の値の範囲に制限はありません。あ>
- 境界制約を設定する場合は、独立変数(決定変数)ごとに上限値と下限値を定義する必要がありますので、境界制約の定義形式に注意してください。
- 引数に上限(下限)がない場合は、 None と表現されます。
x の初期値を定義します。- 最小化問題 resRosen を解きます。目的関数 objf3 と探索の初期値点 xIni が必要ですが、最適化方法と境界条件の指定はオプションです。 最適化問題が最大値 maxFx を見つけることである場合、minFx = - maxFx の変換によって達成できます 。
- 最適点 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个约束条件
参考文献: