#!/usr/bin/env python3
"``naginterface.library.glopt.nlp_multistart_sqp_lsq`` Python Example."
# NAG Copyright 2017-2019.
# pylint: disable=invalid-name,no-member,too-many-arguments,too-many-locals
from math import exp
import warnings
import numpy as np
from naginterfaces.base import utils
from naginterfaces.library import glopt
[docs]def main():
"""
Example for :func:`naginterfaces.library.glopt.nlp_multistart_sqp_lsq`.
Global optimization of a sum of squares problem using multi-start.
Demonstrates catching a ``NagAlgorithmicWarning`` and accessing its
``return_data`` attribute.
>>> main()
naginterfaces.library.glopt.nlp_multistart_sqp_lsq Python Example Results.
Minimizes the sum of squares function
based on Problem 57 in Hock and Schittkowski (1981).
Solution number 1.
Final objective value = 0.0142298.
"""
print(
'naginterfaces.library.glopt.nlp_multistart_sqp_lsq '
'Python Example Results.'
)
print('Minimizes the sum of squares function')
print('based on Problem 57 in Hock and Schittkowski (1981).')
# Input data for the optimizer:
# The number of solutions required:
nb = 1
# The number of nonlinear constraints:
ncnln = 1
# The number of starting points:
npts = 3
# Matrix of general linear constraints:
a = np.array([[1.0, 1.0]])
# The bounds for the problem:
bl = [0.4, -4., 1., 0.]
bu = [1.e25]*len(bl)
# Coefficients of the constant vector y of the objective function:
y = [
0.49, 0.49, 0.48, 0.47, 0.48, 0.47, 0.46, 0.46, 0.45, 0.43, 0.45,
0.43, 0.43, 0.44, 0.43, 0.43, 0.46, 0.45, 0.42, 0.42, 0.43, 0.41,
0.41, 0.40, 0.42, 0.40, 0.40, 0.41, 0.40, 0.41, 0.41, 0.40, 0.40,
0.40, 0.38, 0.41, 0.40, 0.40, 0.41, 0.38, 0.40, 0.40, 0.39, 0.39
]
def cb_confun(mode, needc, x, cjsl, nstate):
"""
Function to evaluate the nonlinear constraint and
its first derivatives.
"""
if needc[0] <= 0 or mode == 1:
c = [0.]*len(needc)
elif mode in [0, 2]:
c = [0.49*x[1] - x[0]*x[1] - 0.09]
if needc[0] <= 0:
return c
if mode in [1, 2]:
cjsl[0, 0] = -x[1]
cjsl[0, 1] = -x[0] + 0.49
return c
def cb_objfun(mode, needfi, x, fjsl, nstate):
"This is a two-dimensional objective function."
# The set of 44 'a' data values:
a = [
8., 8., 10., 10., 10., 10., 12., 12., 12.,
12., 14., 14., 14., 16., 16., 16., 18., 18.,
20., 20., 20., 22.,
22., 22., 24., 24., 24., 26., 26., 26., 28.,
28., 30., 30., 30., 32., 32., 34., 36., 36.,
38., 38., 40., 42.,
]
m = fjsl.shape[0]
f = np.empty(m)
for fi in range(m):
exp_term = exp(-x[1]*(a[fi] - 8.))
if needfi == fi + 1 or mode in [0, 2]:
f[fi] = x[0] + (0.49 - x[0])*exp_term
if needfi == fi + 1:
return f
if mode in [1, 2]:
fjsl[fi, 0] = 1. - exp_term
fjsl[fi, 1] = -(0.49 - x[0])*(a[fi] - 8.)*exp_term
return f
def cb_start(quas, repeat1, bl, bu):
"Function to set up the starting points for the optimization."
quas[:, :] = [
[0.4, 0., 0.],
[0., 1., 0.],
]
# Initialize the communication structure for the solver:
comm = {}
glopt.optset('Initialize = nlp_multistart_sqp_lsq', comm)
# nlp_multistart_sqp_lsq may trigger a 'Warning' when a
# start-point failed to produce a convergent solution.
# By promoting this warning to an error and catching the specific
# exit case (errno 8) we can determine the number of
# converged solutions if this happens, from the 'info'
# return data.
warnings.simplefilter('error', utils.NagAlgorithmicWarning)
try:
objf = glopt.nlp_multistart_sqp_lsq(
ncnln, bl, bu, y, cb_objfun, npts, nb, comm,
a=a, confun=cb_confun,
start=cb_start, repeat1=True,
).objf
n_sol = nb
except utils.NagAlgorithmicWarning as exc:
if exc.errno == 8:
objf = exc.return_data.objf
n_sol = exc.return_data.info[nb-1]
else:
raise exc
for sol_i in range(n_sol):
print('Solution number {:d}.'.format(sol_i + 1))
print('Final objective value = {:15.7f}.'.format(objf[sol_i]))
if __name__ == '__main__':
import doctest
import sys
sys.exit(
doctest.testmod(
None, verbose=True, report=False,
optionflags=doctest.REPORT_NDIFF,
).failed
)