最適化アルゴリズムExample集: 非線形計画問題におけるコールバック関数の早期終了
nAG数値計算ライブラリ > 最適化アルゴリズムExample集 > 非線形計画問題におけるコールバック関数の早期終了

非線形計画法-NLP(導関数無し最適化のコールバック関数の早期終了)

このExampleは、境界制約付き非線形最適化問題を導関数を用いないで解く方法を示しています。また、コールバック関数内で最適化計算を早期に終了させ、その際に発生するNagCallbackTerminateWarningを抑止する方法も説明しています。

目的関数:

タスク
Minimize \(f(x) = (x_1 + 10x_2)^2 + 5(x_3 - x_4)^2 + (x_2 - 2x_3)^4 + 10(x_1 - x_4)^4\)

目的関数は4変数の非線形関数で、最小化問題として定式化されています。

決定変数:

変数 範囲
\(x_1\) \(1 \leq x_1 \leq 3\)
\(x_2\) \(-2 \leq x_2 \leq 0\)
\(x_3\) \(-\infty < x_3 < \infty\)
\(x_4\) \(1 \leq x_4 \leq 3\)

制約条件:

制約
単純な境界制約 \(1 \leq x_1 \leq 3\)
\(-2 \leq x_2 \leq 0\)
\(1 \leq x_4 \leq 3\)

決定変数\(x_1, x_2, x_4\)には明示的な境界制約が課されています。\(x_3\)は実数全体を取り得ます。その他の制約条件は課されていません。

Exampleの実行コマンド:

python -m naginterfaces.library.examples.opt.handle_solve_dfno_ex

ソースコード表示コマンド:

python -c "import inspect; from naginterfaces.library.examples.opt import handle_solve_dfno_ex; print(''.join(inspect.getsourcelines(handle_solve_dfno_ex)[0]))"

出力結果例:

naginterfaces.library.opt.handle_solve_dfno Python Example Results.
Minimizing a bound-constrained nonlinear problem.
Terminating early because rho is small enough.
Function value at lowest point found is 2.43383.
The corresponding x is (1.0000, -0.0858, 0.4097, 1.0000).

マニュアル:

handle_solve_dfnoのマニュアル

ソース:

#!/usr/bin/env python3
"``naginterfaces.library.opt.handle_solve_dfno`` Python Example."

# nAG Copyright 2018-2019.

# pylint: disable=invalid-name

import warnings

from naginterfaces.base import utils
from naginterfaces.library import opt

def main():
    """
    Example for :func:`naginterfaces.library.opt.handle_solve_dfno`.

    Derivative-free solver for nonlinear problems.

    Demonstrates terminating early in a callback function and
    how to silence the subsequent ``NagCallbackTerminateWarning``.

    >>> main()
    naginterfaces.library.opt.handle_solve_dfno Python Example Results.
    Minimizing a bound-constrained nonlinear problem.
    ...
    Terminating early because rho is small enough.
    Function value at lowest point found is 2.43383.
    The corresponding x is (1.0000, -0.0858, 0.4097, 1.0000).
    """

    print(
        'naginterfaces.library.opt.handle_solve_dfno Python Example Results.'
    )
    print('Minimizing a bound-constrained nonlinear problem.')

    # warnings.simplefilter can be used to silence warning messages
    # because of user-requested termination in callback function:
    warnings.simplefilter('ignore', utils.NagCallbackTerminateWarning)

    def cb_monit(x, rinfo, stats):
        """The monitoring function."""
        rho = rinfo[1]
        if rho < 1e-3:
            print('Terminating early because rho is small enough.')
            raise utils.UserCallbackTerminate()

    # The initial guess:
    x = [3., -1., 0., 1.]

    # The objective function:
    objfun = lambda x, _inform: (
        (
            (x[0] + 10.*x[1])**2 +
            5.*(x[2] - x[3])**2 +
            (x[1] - 2.*x[2])**4 +
            10.*(x[0] - x[3])**4
        ),
        0,
    )

    # Create a handle for the problem:
    handle = opt.handle_init(nvar=len(x))

    # Define the bounds:
    opt.handle_set_simplebounds(
        handle,
        bl=[1., -2., -1.e20, 1.],
        bu=[3., 0., 1.e20, 3.],
    )

    # Define the objective for the problem as being nonlinear:
    opt.handle_set_nlnobj(
        handle,
        idxfd=list(range(1, len(x)+1)),
    )

    # Set some algorithmic options.
    for option in [
            'DFO Trust Region Tolerance = 5.0e-6',
            'Print Options = NO',
            'DFO Starting trust Region = 0.2',
            'DFO Monitor Frequency = 1',
    ]:
        opt.handle_opt_set(handle, option)

    # Use an explicit I/O manager for abbreviated iteration output:
    iom = utils.FileObjManager(locus_in_output=False)

    # Solve the problem:
    soln = opt.handle_solve_dfno(
        handle, x, objfun=objfun, monit=cb_monit, io_manager=iom,
    )

    print(
        'Function value at lowest point found is {:.5f}.'.format(
            soln.rinfo[0]
        )
    )
    print(
        'The corresponding x is (' +
        ', '.join(['{:.4f}']*len(soln.x)).format(*soln.x) +
        ').'
    )

    # Destroy the handle:
    opt.handle_free(handle)

if __name__ == '__main__':
    import doctest
    import sys
    sys.exit(
        doctest.testmod(
            None, verbose=True, report=False,
            optionflags=doctest.ELLIPSIS | doctest.REPORT_NDIFF,
        ).failed
    )

関連情報
Privacy Policy  /  Trademarks