nAG数値計算ライブラリ
> 最適化アルゴリズムExample集
> 疎な非線形最適化問題の逐次二次計画法による解法
逐次二次計画法-SQP(疎)
このExampleは、スパースな非線形計画問題(NLP)を逐次二次計画法(SQP)で解いています。2次の目的関数、線形制約、2つの非線形制約を含む問題を扱っています。目的関数は、ユーザコールバックの使用方法を示すために非線形関数としてコード化されています。
目的関数:
タスク | 式 |
---|---|
minimize | \(f(x) = (x_0 + x_1 + x_2)^2 + 3x_2 + 5x_3 + \cos(0.01x_0) - 1\) |
決定変数:
変数 | 範囲 |
---|---|
\(x_0\) | \((-\infty, \infty)\) |
\(x_1\) | \((-\infty, \infty)\) |
\(x_2\) | \([0, \infty)\) |
\(x_3\) | \([0, \infty)\) |
制約条件:
制約 | 式 |
---|---|
線形制約 | \(2x_0 + 4x_1 \geq 0\) |
非線形制約1 | \(x_0^2 + x_1^2 + x_2 = 2\) |
非線形制約2 | \(x_1^4 + x_3 = 4\) |
目的関数は2次形式と非線形項の和で構成されています。\(x_0, x_1, x_2\) の2次形式に加えて、\(x_2, x_3\) の線形項、および \(x_0\) の非線形項 \(\cos(0.01x_0)\) が含まれています。
制約条件は1つの線形不等式制約と2つの非線形等式制約から成ります。線形制約は \(x_0, x_1\) に関する不等式で表現されています。非線形制約1は \(x_0, x_1, x_2\) に関する2次形式と定数項からなる等式です。非線形制約2は \(x_1\) の4次式と \(x_3\) の和が定数値と等しいことを表しています。
\(x_2, x_3\) の下限が0に設定されているのに対し、\(x_0, x_1\) は上下限が設定されていないことから、\(x_0, x_1\) は負の値も取り得ることがわかります。
Exampleの実行コマンド:
python -m naginterfaces.library.examples.opt.handle_solve_ssqp_ex
ソースコード表示コマンド:
python -c "import inspect; from naginterfaces.library.examples.opt import handle_solve_ssqp_ex; print(''.join(inspect.getsourcelines(handle_solve_ssqp_ex)[0]))"
出力結果例:
naginterfaces.library.opt.handle_solve_ssqp Python Example Results.
At the solution the objective function is 1.900124e+00.
マニュアル:
ソース:
#!/usr/bin/env python3
"``naginterfaces.library.opt.handle_solve_ssqp`` Python Example."
# nAG Copyright 2022.
# pylint: disable=invalid-name,too-many-arguments,too-many-locals,too-many-statements
import numpy as np
from naginterfaces.library import opt
def main():
"""
Example for :func:`naginterfaces.library.opt.handle_solve_ssqp`.
SQP solver for sparse NLP.
NLP example: Quadratic objective, linear constraint and two nonlinear
constraints.
For illustrative purposes, the quadratic objective is coded as a nonlinear
function to show the usage of objfun, objgrd user call-backs.
>>> main()
naginterfaces.library.opt.handle_solve_ssqp Python Example Results.
At the solution the objective function is 1.900124e+00.
"""
print(
'naginterfaces.library.opt.handle_solve_ssqp Python Example Results.'
)
# The nonlinear objective:
= lambda x, inform: (
cb_objfun
(0]+x[1]+x[2])*(x[0]+x[1]+x[2]) + 3.0*x[2] + 5.0*x[3] +
(x[0.01*x[0]) - 1.0
np.cos(
),0,
)
def cb_objgrd(x, fdx, inform):
"""The gradient of the objective."""
= 2.0*(x[0]+x[1]+x[2])
summ 0] = summ - 0.01*np.sin(0.01*x[0])
fdx[1] = summ
fdx[2] = summ + 3.0
fdx[3] = 5.0
fdx[return 0
# The nonlinear constraints function:
= lambda x, _ncnln, inform: (
cb_confun
[0]*x[0] + x[1]*x[1] + x[2], x[1]*x[1]*x[1]*x[1] + x[3],
x[
],0,
)
def cb_congrd(x, gdx, inform):
"""The Jacobian of the nonlinear constraints."""
= [
gdx[:] 2.0*x[0],
2.0*x[1],
1.0,
4.0*x[1]*x[1]*x[1],
1.0,
]return inform
# The initial guess:
= [1., 2., 3., 4.]
x = len(x)
nvar = 2*nvar
nnzu # Create a handle for the problem:
= opt.handle_init(nvar)
handle
# Define the bounds:
opt.handle_set_simplebounds(
handle,=[-1.e20, -1.e20, 0., 0.], bu=[1.e20]*nvar,
bl
)
# Define the non-linear objective:
opt.handle_set_nlnobj(
handle,=[1, 2, 3, 4],
idxfd
)
# Define the linear constraints:
opt.handle_set_linconstr(
handle,=[0.], bu=[1.e20],
bl=[1, 1],
irowb=[1, 2],
icolb=[2.0, 4.0],
b
)+= 2*1
nnzu
# Define the nonlinear constraints:
opt.handle_set_nlnconstr(
handle,=[2., 4.], bu=[2., 4.],
bl=[1, 1, 1, 2, 2], icolgd=[1, 2, 3, 2, 4],
irowgd
)+= 2*2
nnzu
opt.handle_opt_set('Verify Derivatives = Yes',
handle,
)
opt.handle_opt_set('Print Solution = No',
handle,
)
opt.handle_opt_set('Print Level = 0',
handle,
)
# Optionally, define variable x(4) to be linear
# Hinting which variables are linear in problems with many
# variables can speed up performance
"Linear", 4)
opt.handle_set_property(handle,
# Solve the problem:
= opt.handle_solve_ssqp(
sn_soln
handle, x,=cb_objfun, objgrd=cb_objgrd, confun=cb_confun, congrd=cb_congrd
objfun
)
print(
'At the solution the objective function is {:.6e}.'.format(
0]
sn_soln.rinfo[
)
)
# Destroy the handle:
opt.handle_free(handle)
if __name__ == '__main__':
import doctest
import sys
sys.exit(
doctest.testmod(None, verbose=True, report=False,
=doctest.ELLIPSIS | doctest.REPORT_NDIFF,
optionflags
).failed
)