<jupyter_start><jupyter_text>Global OptimizationFinding the absolute maximum or minimum value of a function can be hard. For problems with a few tens of variables and only bound constraints the NAG solver [`glopt.bnd_mcs_solve`](https://www.nag.com/numeric/py/nagdoc_latest/naginterfaces.library.glopt.bnd_mcs_solve.html) for multi-level coordinate search (from Huyer and Neumaier) is an effective routine.For a quick demonstration of `glopt.bnd_mcs_solve` we find the global minimum of the two-dimensional 'peaks' function, which (in a suitable form for the solver's `objfun` argument) is<jupyter_code>from math import exp
objfun = lambda x, _nstate: (
    3.*(1. - x[0])**2*exp(-x[0]**2 - (x[1] + 1.)**2)
    - (10.*(x[0]/5. - x[0]**3 - x[1]**5)*exp(-x[0]**2 - x[1]**2))
    - 1./3.0*exp(-(x[0] + 1.)**2 - x[1]**2)
)<jupyter_output><empty_output><jupyter_text>The optimization is over the box $[-3, -3]\times[3, 3]$<jupyter_code>n = 2
bl = [-3.]*n
bu = [3.]*n<jupyter_output><empty_output><jupyter_text>The `ibound` argument tells the solver that we are supplying the bounds explicitly ourselves<jupyter_code>ibound = 0<jupyter_output><empty_output><jupyter_text>The plot for this example is going to show the search boxes that the optimizer considers as it iterates. We can use the function's monitoring callback to store the boxes that it visits<jupyter_code>from matplotlib.patches import Rectangle

boxes = []

def monit(
    _ncall, _xbest, _icount, _inlist, _numpts,
    _initpt, _xbaskt, boxl, boxu, _nstate,
):
    boxes.append(Rectangle(boxl, *(boxu - boxl)))<jupyter_output><empty_output><jupyter_text>Before calling the optimizer we need to initialize its communication state<jupyter_code>from naginterfaces.library import glopt
comm = glopt.bnd_mcs_init()<jupyter_output><empty_output><jupyter_text>Now do the optimization. The monitoring function is an optional keyword argument. In this example we don't need to access any of the return data<jupyter_code>_ = glopt.bnd_mcs_solve(objfun, ibound, bl, bu, comm, monit=monit)<jupyter_output><empty_output><jupyter_text>Grid the objective function for plotting<jupyter_code>import numpy as np
delta = 0.025
x = np.arange(bl[0], bu[0], delta)
y = np.arange(bl[1], bu[1], delta)
X, Y = np.meshgrid(x, y)
Z = np.empty((len(X), len(Y)))
for i, x_i in enumerate(x):
    for j, y_j in enumerate(y):
        Z[j, i] = objfun([x_i, y_j], None)<jupyter_output><empty_output><jupyter_text>Store the optimization start and end points for inclusion in the plot. For the routine's default 'simple' initialization method (`iinit = 0`) the start point (`initpt`) was at the origin<jupyter_code>start_x = [0.]*n<jupyter_output><empty_output><jupyter_text>Here is the known global minimum for the problem<jupyter_code>min_x = [0.23, -1.63]<jupyter_output><empty_output><jupyter_text>Aggregate the search boxes to include in the subsequent plot<jupyter_code>from matplotlib.collections import PatchCollection
boxes_col = PatchCollection(
    boxes,
    edgecolor='b', facecolor='none', linewidth=0.2,
)
# Select the display backend for Jupyter:
%matplotlib inline<jupyter_output><empty_output><jupyter_text>Now assemble the plot<jupyter_code>from matplotlib import cm
import matplotlib.pyplot as plt
ax = plt.axes()
ax.contour(
    X, Y, Z,
    levels=[-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 6, 8],
    cmap=cm.jet,
)
ax.plot(start_x[0], start_x[1], 'rx')
ax.plot(min_x[0], min_x[1], 'go')
ax.legend(('Start', 'Glob. min.'), loc='upper right')
ax.add_collection(boxes_col)
ax.axis(xmin=bl[0], ymin=bl[1], xmax=bu[0], ymax=bu[1])
ax.set_title(r'The Peaks Function and MCS Search Boxes')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1338239302262197, 'fraction_numerical': 0.020714091032979012, 'mean_word_length': 5.697080291970803, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '573046', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 1396, 'n_tokens_neox': 1355, 'n_words': 369, 'path': 'global_optimization/bnd_mcs_solve.ipynb', 'repo_name': 'Brunochris13/NAGPythonExamples', 'size': '3669'}