-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathnelder_mead.py
95 lines (73 loc) · 2.06 KB
/
nelder_mead.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# !/usr/bin/python
# -*- coding: utf-8 -*-
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):
x, y = point
return x ** 2 + x * y + y ** 2 - 6 * x - 9 * y
def nelder_mead(alpha=1, beta=0.5, gamma=2, maxiter=10):
# initialization
v1 = Vector(0, 0)
v2 = Vector(1.0, 0)
v3 = Vector(0, 1)
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
xk = nelder_mead()
print("Result of Nelder-Mead algorithm:")
print("Best point is: {}".format(xk))