nAG数値計算ライブラリ
> 最適化アルゴリズムExample集
> Hock and Schittkowski Problem 74の疎な非線形計画法による解法
(nlp2_sparse_solve)
非線形計画法-NLP(疎)
このExampleではHockとSchittkowskiの問題74を非線形計画法(NLP)で解いています。問題は4つの決定変数を持ち、6つの制約条件(3つの非線形制約、2つの線形制約、1つの変数の範囲制約)のもとで目的関数を最小化します。
目的関数:
| タスク | 式 |
|---|---|
| Minimize | \(f(x) = 10^{-6} x_3^3 + \frac{2}{3} \cdot 10^{-6} x_4^3\) |
目的関数は3次の項のみを含み、\(x_3\)と\(x_4\)の変数のみに依存しています。係数は非常に小さい値(\(10^{-6}\)のオーダー)です。
決定変数:
| 変数 | 範囲 |
|---|---|
| \(x_1\) | \(-0.55 \leq x_1 \leq 0.55\) |
| \(x_2\) | \(-0.55 \leq x_2 \leq 0.55\) |
| \(x_3\) | \(0 \leq x_3 \leq 1200\) |
| \(x_4\) | \(0 \leq x_4 \leq 1200\) |
制約条件:
| 制約 | 式 |
|---|---|
| 非線形制約1 | \(1000 \sin(-x_1-0.25) + 1000 \sin(-x_2-0.25) \geq -894.8\) |
| 非線形制約2 | \(1000 \sin(x_1-0.25) + 1000 \sin(x_1-x_2-0.25) \geq -894.8\) |
| 非線形制約3 | \(1000 \sin(x_2-0.25) + 1000 \sin(x_2-x_1-0.25) \geq -1294.8\) |
| 線形制約1 | \(-x_1 - x_2 - x_3 + x_4 \geq -0.55\) |
| 線形制約2 | \(x_1 - x_2 + x_3 - x_4 \geq -0.55\) |
| 変数の範囲制約 | \(-0.55 \leq x_1, x_2 \leq 0.55, \quad 0 \leq x_3, x_4 \leq 1200\) |
非線形制約は三角関数の項を含み、線形制約は決定変数の1次式で表現されています。非線形制約の右辺は定数で、線形制約の右辺も定数になっています。変数の範囲制約は各変数の上限と下限を定義しています。
Exampleの実行コマンド:
python -m naginterfaces.library.examples.opt.nlp2_sparse_solve_ex
ソースコード表示コマンド:
python -c "import inspect; from naginterfaces.library.examples.opt import nlp2_sparse_solve_ex; print(''.join(inspect.getsourcelines(nlp2_sparse_solve_ex)[0]))"
出力結果例:
naginterfaces.library.opt.nlp2_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.nlp2_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.nlp2_sparse_solve`.
Sparse NLP.
>>> main()
naginterfaces.library.opt.nlp2_sparse_solve Python Example Results.
Solve Hock and Schittkowski Problem 74.
Final objective value is 5.1264981e+03
"""
print(
'naginterfaces.library.opt.nlp2_sparse_solve Python Example Results.'
)
print('Solve Hock and Schittkowski Problem 74.')
def cb_usrfun(_status, x, needf, f, needg, g):
"""The nonlinear constraints."""
if needf > 0:
f[:3] = [
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),
]
# There is no need to define the wholly linear
# components f_3(x) and f_4(x)...
f[5] = 1.e-6*x[2]**3 + 2.e-6*x[3]**3/3.
if needg > 0:
g = [
-1000.*cos(-x[0]-0.25),
-1000.*cos(-x[1]-0.25),
1000.*cos(x[0]-0.25) + 1000.*cos(x[0]-x[1]-0.25),
-1000.*cos(x[0]-x[1]-0.25),
-1000.*cos(x[1]-x[0]-0.25),
1000.*cos(x[1]-x[0]-0.25) + 1000.*cos(x[1]-0.25),
3.e-6*x[2]**2,
2.e-6*x[3]**2,
]
return 0, f, g
# Silence deprecation warning:
warnings.simplefilter('ignore', utils.NagDeprecatedWarning)
# Initialize the solver:
comm = opt.nlp2_sparse_init()
# Initial guess:
x = [0., 0., 0., 0.]
n = len(x)
# There are six problem functions:
nf = 6
# The linear part of F and its packing information:
a = [
-1., -1., -1., 1., 1., -1., 3., 2.,
]
nea = 8
iafun = [1, 2, 4, 4, 5, 5, 6, 6]
javar = [3, 4, 1, 2, 1, 2, 3, 4]
# The coordinates of the nonzero elements of G:
neg = 8
igfun = [1, 1, 2, 2, 3, 3, 6, 6]
jgvar = [1, 2, 1, 2, 1, 2, 3, 4]
# Variable names:
xnames = ['X1', 'X2', 'X3', 'X4']
# Function names:
fnames = [
'NlnCon 1', 'NlnCon 2', 'NlnCon 3', 'LinCon 1', 'LinCon 2', 'Objectiv',
]
# No constant objective term:
objadd = 0.
# Use row six of F as the objective:
objrow = 6
# Blank problem name:
prob = ''
# The bounds:
xlow = [
-0.55, -0.55, 0., 0.,
]
flow = [
-894.8, -894.8, -1294.8,
-0.55, -0.55,
-1.e+25,
]
xupp = [
0.55, 0.55, 1200., 1200.,
]
fupp = [
-894.8, -894.8, -1294.8,
1.e+25, 1.e+25,
1.e+25,
]
# Cold start:
start = 0
# Initial state:
xstate = np.zeros(n, dtype=int)
f = np.zeros(nf)
fstate = np.zeros(nf, dtype=int)
fmul = np.zeros(nf)
# No superbasics to specify:
ns = 0
nlp_soln = opt.nlp2_sparse_solve(
start, objadd, objrow, prob,
cb_usrfun, iafun, javar, nea, a, igfun, jgvar, neg,
xlow, xupp, xnames, flow, fupp, fnames, x, xstate, f, fstate,
fmul, ns, comm,
)
print('Final objective value is {:.7e}'.format(nlp_soln.f[objrow-1]))
if __name__ == '__main__':
import doctest
import sys
sys.exit(
doctest.testmod(
None, verbose=True, report=False,
optionflags=doctest.REPORT_NDIFF,
).failed
)