最適化アルゴリズムExample集: Hock and Schittkowski Problem 74の疎な非線形計画法による解法
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_objfuncb_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

マニュアル:

nlp1_sparse_solveのマニュアル

ソース:

#!/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:
            f = np.empty(ncnln)
        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]:
            objf = 1.e-6*x[2]**3 + 2.e-6*x[3]**3/3.
        else:
            objf = 0.
        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:
    warnings.simplefilter('ignore', utils.NagDeprecatedWarning)

    # Initialize the solver:
    comm = opt.nlp1_init('nlp1_sparse_solve')
    # There are three nonlinear constraints defined by cb_confun:
    ncnln = 3
    # There are six general constraints:
    m = 6
    # The numbers of nonlinear variables:
    nonln = 4
    njnln = 2
    # 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,
    ]
    ka = [1, 6, 11, 13, 15]
    n = len(ka) - 1
    # Denote a free row in A:
    iobj = 6
    # 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:
    xs = [0.]*(n+m)
    # Cold start:
    start = 'Cold'
    # 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:
    ns = 0

    istate = np.zeros(n + m, dtype=int)
    clamda = np.zeros(n + m)

    # 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:
    warnings.simplefilter('ignore', utils.NagAlgorithmicWarning)
    soln_q = opt.nlp1_sparse_solve(
        *nlp_args, confun=cb_confun, objfun=cb_objfun
    )
    # Restore warnings verbosity:
    warnings.simplefilter('always', utils.NagAlgorithmicWarning)
    obj = opt.nlp1_sparse_solve(
        *nlp_args, confun=cb_confun, objfun=cb_objfun,
        leniz=2*soln_q.miniz, lenz=2*soln_q.minz
    ).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,
            optionflags=doctest.REPORT_NDIFF,
        ).failed
    )

関連情報
Privacy Policy  /  Trademarks