Created
January 18, 2015 13:27
-
-
Save wbaek/36bd2039336bb11e14f1 to your computer and use it in GitHub Desktop.
NumericalOptimization/multivariate/melder_mead.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#-*- coding: utf-8 -*- | |
def _verbose(i, params, scores): | |
params_str = ', '.join(['(%s)'%(','.join(['%.2f'%p for p in param])) for param in params]) | |
scores_str = ', '.join(['%.2f'%s for s in scores]) | |
print 'iter=%03d, params=[%s], scores=[%s]'%(i, params_str, scores_str) | |
def minimize(function, initial, alpha=1.0, beta=2.0, gamma=0.5, epsilon=1e-5, repeat=int(1e6), verbose=False): | |
import numpy | |
def center_of_params(params): | |
return tuple(numpy.average(numpy.array(params[:-1]).transpose(), 1)) | |
def reflection(params, scores): | |
c = center_of_params(params) | |
reflection_param = tuple(numpy.array(c) + alpha * numpy.subtract(c, params[-1])) | |
return reflection_param, function(reflection_param) | |
def expansion(params, scores, reflection_param, reflection_score): | |
c = center_of_params(params) | |
expansion_param = tuple(numpy.array(c) + beta * numpy.subtract(reflection_param, c)) | |
return expansion_param, function(expansion_param) | |
def contraction(params, scores, reflection_param, reflection_score): | |
c = center_of_params(params) | |
if reflection_score < scores[-1]: p = reflection_param | |
else: p = params[-1] | |
contraction_param = tuple(numpy.array(c) + gamma * numpy.subtract(p, c)) | |
contraction_score = function(contraction_param) | |
if contraction_score < min(reflection_score, scores[-1]): | |
params[-1] = contraction_param | |
else: | |
params = [tuple(numpy.add(params[0], p)/2.0) for p in params] | |
return params, [function(p) for p in params] | |
last_index = len(initial) | |
scores = [function(p) for p in initial] | |
sort_index = [i[0] for i in sorted(enumerate(scores), key=lambda x:x[1])] | |
params = [initial[i] for i in sort_index] | |
scores = [scores[i] for i in sort_index] | |
for i in range(repeat): | |
if verbose: _verbose(i, params, scores) | |
xr, fr = reflection(params, scores) | |
if fr <= scores[0]: | |
xe, fe = expansion(params, scores, xr, fr) | |
if fe <= fr: | |
params[-1] = xe | |
scores[-1] = fe | |
else: | |
params[-1] = xr | |
scores[-1] = fr | |
elif fr >= scores[-2]: | |
params, scores = contraction(params, scores, xr, fr) | |
else: | |
params[-1] = xr | |
scores[-1] = fr | |
sort_index = [i[0] for i in sorted(enumerate(scores), key=lambda x:x[1])] | |
params = [params[i] for i in sort_index] | |
scores = [scores[i] for i in sort_index] | |
if epsilon > sum([numpy.linalg.norm(numpy.subtract(params[k], params[k+1]), 2) for k in range(len(params)-1)]): | |
break | |
return params[0] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
>>> minimize( lambda x: (x[0]-0.3)**2 + (x[1]-1.3)**2 + 3.0 ,\ | |
[(0.0,0.0), (1.0,1.0), (0.0,1.0)] ) | |
(0.30000068443533018, 1.3000025269138833) | |
>>> minimize( lambda x: abs(x[0]-0.3) + abs(x[1]-1.3) + abs(x[2]+0.7) ,\ | |
[(0.0,0.0,0.0), (1.0,1.0,1.0), (0.0,1.5,0.0), (1.5,2.5,0.0)] ) | |
(0.30000098578208223, 1.3000002242389832, -0.70000285189454658) | |
>>> minimize( lambda x: (x[0]-0.3)**2 + (x[1]-1.3)**2 + 3.0 ,\ | |
[(0.3,0.0), (1.0,1.0), (0.0,1.3)], repeat=10, verbose=True ) | |
iter=000, params=[(0.00,1.30), (1.00,1.00), (0.30,0.00)], scores=[3.09, 3.58, 4.69] | |
iter=001, params=[(0.00,1.30), (0.60,1.72), (1.00,1.00)], scores=[3.09, 3.27, 3.58] | |
iter=002, params=[(0.00,1.30), (0.65,1.26), (0.60,1.72)], scores=[3.09, 3.12, 3.27] | |
iter=003, params=[(0.46,1.50), (0.00,1.30), (0.65,1.26)], scores=[3.07, 3.09, 3.12] | |
iter=004, params=[(0.44,1.33), (0.46,1.50), (0.00,1.30)], scores=[3.02, 3.07, 3.09] | |
iter=005, params=[(0.23,1.36), (0.44,1.33), (0.46,1.50)], scores=[3.01, 3.02, 3.07] | |
iter=006, params=[(0.27,1.26), (0.23,1.36), (0.44,1.33)], scores=[3.00, 3.01, 3.02] | |
iter=007, params=[(0.27,1.26), (0.34,1.32), (0.23,1.36)], scores=[3.00, 3.00, 3.01] | |
iter=008, params=[(0.27,1.32), (0.27,1.26), (0.34,1.32)], scores=[3.00, 3.00, 3.00] | |
iter=009, params=[(0.31,1.31), (0.27,1.32), (0.27,1.26)], scores=[3.00, 3.00, 3.00] | |
(0.30558776855468739, 1.3068706512451174) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment