Python Forum
Nelder-Mead gives wrong result
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Nelder-Mead gives wrong result
#1
Hello. I want to solve some optimization problem with Nelder-Mead algorithm. After that I want to port it into VBA.
So I use this code
class Vector(object):
    def __init__(self, x, y):
        """ Create a vector, example: v = Vector(1,2) """
        self.x = x
        self.y = y

    def __repr__(self):
        return "({0}, {1})".format(self.x, self.y)

    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)

    def __sub__(self, other):
        x = self.x - other.x
        y = self.y - other.y
        return Vector(x, y)

    def __rmul__(self, other):
        x = self.x * other
        y = self.y * other
        return Vector(x, y)

    def __truediv__(self, other):
        x = self.x / other
        y = self.y / other
        return Vector(x, y)

    def c(self):
        return (self.x, self.y)
        
# objective function
def f(point):
    p0, p1 = point
    n=56
    d1=10
    d2=15
    bb=1/0.05
    return 1/(2*bb*n*(p0+(n-1)*p1))*p0**-n*(-2*(-100+d2)*p0**2+2*bb*(d2+100*(-1+n))*p0**(2+n)-bb*(-1+n)*n*p0**n*p1* \
                    (200+(-100+2*d1-d2)*p1)+2*bb*n*p0**(1+n)*(-100+(-d1+d2+100*(-1+n))*p1)) 
def nelder_mead(alpha=1, beta=0.5, gamma=2, maxiter=50):
    
    # initialization
    v1 = Vector(0.5, 0.5)
    v2 = Vector(0.99999, 0.00001)
    v3 = Vector(0.00001, 0.99999)

    for i in range(maxiter):
        adict = {v1:f(v1.c()), v2:f(v2.c()), v3:f(v3.c())}
        points = sorted(adict.items(), key=lambda x: x[1])
        
        b = points[0][0]
        g = points[1][0]
        w = points[2][0]
        
        
        mid = (g + b)/2

        # reflection
        xr = mid + alpha * (mid - w)
        if f(xr.c()) < f(g.c()):
            w = xr
        else:
            if f(xr.c()) < f(w.c()):
                w = xr
            c = (w + mid)/2
            if f(c.c()) < f(w.c()):
                w = c
        if f(xr.c()) < f(b.c()):

            # expansion
            xe = mid + gamma * (xr - mid)
            if f(xe.c()) < f(xr.c()):
                w = xe
            else:
                w = xr
        if f(xr.c()) > f(g.c()):
            
            # contraction
            xc = mid + beta * (w - mid)
            if f(xc.c()) < f(w.c()):
                w = xc

        # update points
        v1 = w
        v2 = g
        v3 = b
    return b

print("Result of Nelder-Mead algorithm: ")
xk = nelder_mead()
print("Best poits is: %s"%(xk))
and see no mistakes here. but it gives wrong result as (0.9242635409630066, 0.07573645903699333)
The right result should be {-5.27607, {Subscript[p, 0] -> 0.937948,
Subscript[p, 1] -> 0.00888233}}

I also used some python chackup which gives right result but with a warning.
import scipy.optimize as optimize
def f2(point):
    p0, p1 = point
    n=56
    d1=10
    d2=15
    bb=1/0.05
    return 1/(2*bb*n*(p0+(n-1)*p1))*p0**-n*(-2*(-100+d2)*p0**2+2*bb*(d2+100*(-1+n))*p0**(2+n)-bb*(-1+n)*n*p0**n*p1* \
                    (200+(-100+2*d1-d2)*p1)+2*bb*n*p0**(1+n)*(-100+(-d1+d2+100*(-1+n))*p1)) 
print(f2((1,1)))
initial_guess = [1, 1]
bounds = [(0,1),(0,1)]
result = optimize.minimize(f2, initial_guess, method='SLSQP', bounds=bounds)
if result.success:
    fitted_params = result.x
    print(fitted_params)
else:
    raise ValueError(result.message)
--------------------------------------------------------------------
Warning (from warnings module):
  File "C:/Users/Alex/Downloads/1.py", line 8
    return 1/(2*bb*n*(p0+(n-1)*p1))*p0**-n*(-2*(-100+d2)*p0**2+2*bb*(d2+100*(-1+n))*p0**(2+n)-bb*(-1+n)*n*p0**n*p1* \
RuntimeWarning: overflow encountered in double_scalars
[0.93794678 0.0088846 ]
What's wrong with Nelder-Mead code?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Wrong result of polyroots Thomas 1 1,885 May-15-2019, 03:04 AM
Last Post: scidam

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020