nAG数値計算ライブラリ
> 最適化アルゴリズムExample集
> Hock and Schittkowski Problem 74の疎な非線形計画法による解法
非線形計画法-NLP(疎)
このExampleでは、Hock and Schittkowski Problem
74という非線形最適化問題を疎行列を用いて定式化し、nAGライブラリの関数
nlp1_sparse_solve
を使って解いています。
目的関数:
タスク | 式 |
---|---|
minimize | \(f(x) = 10^{-6} x_2^3 + \frac{2}{3} \cdot 10^{-6} x_3^3\) |
決定変数:
変数 | 範囲 |
---|---|
\(x_0\) | \([-0.55, 0.55]\) |
\(x_1\) | \([-0.55, 0.55]\) |
\(x_2\) | \([0, 1200]\) |
\(x_3\) | \([0, 1200]\) |
制約条件:
制約 | 式 |
---|---|
非線形制約1 | \(g_1(x) = 1000 \sin(-x_0-0.25) + 1000 \sin(-x_1-0.25) = -894.8\) |
非線形制約2 | \(g_2(x) = 1000 \sin(x_0-0.25) + 1000 \sin(x_0-x_1-0.25) = -894.8\) |
非線形制約3 | \(g_3(x) = 1000 \sin(x_1-0.25) + 1000 \sin(x_1-x_0-0.25) = -1294.8\) |
線形制約1 | \(-x_0 + x_1 \leq 0\) |
線形制約2 | \(x_0 - x_1 \leq 0\) |
目的関数は3次の非線形関数で、\(x_2\) と \(x_3\) のみに依存しています。
非線形の等式制約が3つあり、正弦関数を使った複雑な形をしています。 線形不等式制約が2つあり、\(x_0\) と \(x_1\) の関係を規定しています。
コードでは疎行列の形式で制約条件の係数行列を定義しています。
目的関数と非線形制約の関数は、コールバック関数 cb_objfun
と
cb_confun
で別途定義されています。
Exampleの実行コマンド:
python -m naginterfaces.library.examples.opt.nlp1_sparse_solve_ex
ソースコード表示コマンド:
python -c "import inspect; from naginterfaces.library.examples.opt import nlp1_sparse_solve_ex; print(''.join(inspect.getsourcelines(nlp1_sparse_solve_ex)[0]))"
出力結果例:
naginterfaces.library.opt.nlp1_sparse_solve Python Example Results.
Solve Hock and Schittkowski Problem 74.
Final objective value is 5.1264981e+03
マニュアル:
ソース:
#!/usr/bin/env python3
"``naginterfaces.library.opt.nlp1_sparse_solve`` Python Example."
# nAG Copyright 2017-2022.
# pylint: disable=invalid-name,too-many-locals
from math import cos, sin
import warnings
import numpy as np
from naginterfaces.base import utils
from naginterfaces.library import opt
def main():
"""
Example for :func:`naginterfaces.library.opt.nlp1_sparse_solve`.
Sparse NLP.
>>> main()
naginterfaces.library.opt.nlp1_sparse_solve Python Example Results.
Solve Hock and Schittkowski Problem 74.
Final objective value is 5.1264981e+03
"""
print(
'naginterfaces.library.opt.nlp1_sparse_solve Python Example Results.'
)print('Solve Hock and Schittkowski Problem 74.')
def cb_confun(mode, ncnln, x, fjac, _nstate):
"""The nonlinear constraints."""
if mode in [0, 2]:
= [
f 1000.*sin(-x[0]-0.25) + 1000.*sin(-x[1]-0.25),
1000.*sin(x[0]-0.25) + 1000.*sin(x[0]-x[1]-0.25),
1000.*sin(x[1]-0.25) + 1000.*sin(x[1]-x[0]-0.25),
]else:
= np.empty(ncnln)
f if mode in [1, 2]:
= [
fjac[:] -1000.*cos(-x[0]-0.25),
1000.*cos(x[0]-0.25) + 1000.*cos(x[0]-x[1]-0.25),
-1000.*cos(x[1]-x[0]-0.25),
-1000.*cos(-x[1]-0.25),
-1000.*cos(x[0]-x[1]-0.25),
1000.*cos(x[1]-x[0]-0.25) + 1000.*cos(x[1]-0.25),
]return 0, f, fjac
def cb_objfun(mode, x, objgrd, _nstate):
"""The objective function."""
if mode in [0, 2]:
= 1.e-6*x[2]**3 + 2.e-6*x[3]**3/3.
objf else:
= 0.
objf if mode in [1, 2]:
= [
objgrd[:] 0.,
0.,
3.e-6*x[2]**2,
2.e-6*x[3]**2,
]return 0, objf, objgrd
# Silence deprecation warning:
'ignore', utils.NagDeprecatedWarning)
warnings.simplefilter(
# Initialize the solver:
= opt.nlp1_init('nlp1_sparse_solve')
comm # There are three nonlinear constraints defined by cb_confun:
= 3
ncnln # There are six general constraints:
= 6
m # The numbers of nonlinear variables:
= 4
nonln = 2
njnln # The Jacobian A stored by columns:
= [
a 1e+25, 1e+25, 1e+25, -1.0, 1.0,
1e+25, 1e+25, 1e+25, 1.0, -1.0,
-1.0, 3.0, -1.0, 2.0,
]# The packing information for A:
= [
ha 1, 2, 3, 4, 5,
1, 2, 3, 4, 5,
1, 6,
2, 6,
]= [1, 6, 11, 13, 15]
ka = len(ka) - 1
n # Denote a free row in A:
= 6
iobj # The bounds:
= [
bl -0.55, -0.55, 0., 0.,
-894.8, -894.8, -1294.8,
-0.55, -0.55,
-1e+25,
]= [
bu 0.55, 0.55, 1200., 1200.,
-894.8, -894.8, -1294.8,
1e+25, 1.e+25,
1e+25,
]# Initial guess:
= [0.]*(n+m)
xs # Cold start:
= 'Cold'
start # Row and column names:
= [
names 'Varble 1', 'Varble 2', 'Varble 3', 'Varble 4',
'NlnCon 1', 'NlnCon 2', 'NlnCon 3',
'LinCon 1', 'LinCon 2',
'Free Row',
]# No superbasics to specify:
= 0
ns
= np.zeros(n + m, dtype=int)
istate = np.zeros(n + m)
clamda
# Form the main argument list for the routine.
# We perform a query call first using the routine's defaults
# for leniz and lenz to determine their minimum required values.
# For the basis factors in this problem, twice the minimum is
# sufficient.
= [
nlp_args
m, ncnln, nonln, njnln, iobj,
a, ha, ka, bl, bu, start,
names, ns, xs, istate, clamda, comm,
]# Silence warnings from the query call:
'ignore', utils.NagAlgorithmicWarning)
warnings.simplefilter(= opt.nlp1_sparse_solve(
soln_q *nlp_args, confun=cb_confun, objfun=cb_objfun
)# Restore warnings verbosity:
'always', utils.NagAlgorithmicWarning)
warnings.simplefilter(= opt.nlp1_sparse_solve(
obj *nlp_args, confun=cb_confun, objfun=cb_objfun,
=2*soln_q.miniz, lenz=2*soln_q.minz
leniz
).obj
print('Final objective value is {:.7e}'.format(obj))
if __name__ == '__main__':
import doctest
import sys
sys.exit(
doctest.testmod(None, verbose=True, report=False,
=doctest.REPORT_NDIFF,
optionflags
).failed )