Skip to content

Instantly share code, notes, and snippets.

@endolith
Last active September 8, 2017 04:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save endolith/6f89b1cb0baa98688a5bc49e590ce196 to your computer and use it in GitHub Desktop.
Save endolith/6f89b1cb0baa98688a5bc49e590ce196 to your computer and use it in GitHub Desktop.
import numpy as np
from numpy import exp, sqrt, pi, cos, sin, e
import matplotlib.pyplot as plt
from scipy import optimize
import warnings
warnings.filterwarnings("ignore",".*GUI is implemented.*")
from scipy._lib._util import check_random_state
from scipy.optimize._basinhopping import AdaptiveStepsize, RandomDisplacement
def mishra_bird(x, y):
"""
This is a constrained problem with two continuous design variables. There
is one global optimum and a few local optima.
Minimize:
f = sin(x1)*exp((1-cos(x2))^2) + cos(x2)*exp((1-sin(x1))^2) + (x1-x2)^2
The function has two global minima at f(x) = −106.764537 located at
x = ( 4.70104, 3.15294)
x = (−1.58214,−3.13024)
"""
return (sin(x) * exp((1-cos(y))**2) +
cos(y) * exp((1-sin(x))**2) +
(x - y)**2)
def inside_curve(xy):
"""
Subject to:
g1 = (x1+5)^2 + (x2+5)^2 >= 25
equivalent to
(x+5)^2 + (y+5)^2 - 25 >= 0
The optimal points are:
f* = -106.764537 at x* = (4.7, 3.15)
"""
x, y = xy
return (x + 5)**2 + (y + 5)**2 - 25
cons = ({'type': 'ineq', 'fun': inside_curve})
"""
With a search space:
-6 <= x1, x2 <= 6
"""
bnds = ((-6, None), (None, 6))
N = 800
func = mishra_bird
X, Y = np.mgrid[-15:15:complex(0, N), -15:15:complex(0, N)]
stepsize = 13
niter = 2000
x0 = 9, -9
x0 = 0, 0
def func_array(xy):
return func(xy[0], xy[1])
Z = func(X, Y)
plt.imshow(Z.T, cmap='gray', origin='lower', interpolation='bilinear',
extent=[X.min(), X.max(), Y.min(), Y.max()],)
plt.axis('image')
plt.plot(x0[0], x0[1], '.')
plt.tight_layout()
def test_plotter(f_new, x_new, f_old, x_old):
print(f' AT step ({x_old[0]:.2f}, {x_old[1]:.2f}) -> '
f'({x_new[0]:.2f}, {x_new[1]:.2f})')
plt.plot(x_new[0], x_new[1], 'y.')
return False # Random sampling around first minimum found
rng = check_random_state(None)
interval = 50
def step_taking(x):
displace = RandomDisplacement(stepsize=stepsize, random_state=rng)
stepper = AdaptiveStepsize(displace, interval=interval, verbose=True)
x_old = np.copy(x)
x_new = stepper(x)
print(f' ST step ({x_old[0]:.2f}, {x_old[1]:.2f}) -> '
f'({x_new[0]:.2f}, {x_new[1]:.2f})')
# if inside_curve(x_new) >= 0:
# plt.plot(x_new[0], x_new[1], '.', color='limegreen')
# else:
# plt.plot(x_new[0], x_new[1], '.', color='purple')
return x_new
bnds_x = [X.min(), X.min(), X.max(), X.max(), bnds[0][0], bnds[0][0]]
bnds_y = [Y.min(), Y.max(), Y.max(), bnds[1][1], bnds[1][1], Y.min()]
plt.fill(bnds_x, bnds_y, color='red', alpha=0.2, linewidth=0)
con_circle = plt.Circle((-5, -5), 5, color='blue', alpha=0.3)
ax = plt.gca()
ax.add_artist(con_circle)
minres = optimize.basinhopping(func_array, x0, stepsize=stepsize, disp=True,
minimizer_kwargs={
'constraints': cons,
'bounds': bnds,
},
niter=niter,
interval=interval,
take_step=step_taking,
accept_test=test_plotter,
)
plt.plot(minres.x[0], minres.x[1], 'r.', markersize=3.5)
print('----minres-----\n', minres)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment