-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpowell.py
83 lines (78 loc) · 2.97 KB
/
powell.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
from problems import *
from linear_optimization import *
import numpy as np
class PowellMethod:
"""
Class of implementation of Powell's conjugate direction method, which realize
initialization of method's parameters and minimization of function
"""
def __init__(self, ls: LinearOptimizationMethod, restarts: int = None,
eps: float = None, iterations: int = None, always_change_basis: bool = False):
self.ls = ls
if restarts is None:
restarts = 1
self.restarts = restarts
if eps is None:
eps = 1e-6
self.eps = eps
if iterations is None:
iterations = 100
self.iterations = iterations
self.always_change_basis = always_change_basis
def minimize(self, problem: Problem, x0: np.ndarray) -> (np.ndarray, float):
"""
Powell's conjugate direction method
:param problem: Problem object represents function to minimize
:param x0: starting point of minimization
:return: point of minimum, minimal value
"""
f = problem.f
ls = self.ls
if x0 is None:
x0 = np.zeros(problem.size)
elif x0.dtype != np.float64:
x0 = x0.astype(np.float64)
restart = 0
k = problem.size
xi = np.copy(x0)
fi = f(xi)
while restart < self.restarts:
d = np.array([np.array([1.0 if i == j else 0.0 for i in range(k)]) for j in range(k)])
xi = np.copy(x0)
fi = f(xi)
iteration = 0
while iteration < self.iterations:
x0i = np.copy(xi)
f0i = fi
delta_k = 0
ind = 0
for i, di in enumerate(d):
diff = fi
alpha, fi = ls.optimize(problem, xi, fi, di)
diff -= fi
if diff > delta_k:
delta_k = diff
ind = i
xi += alpha * di
dn = xi - x0i
if np.all(np.abs(d) < self.eps) or np.linalg.norm(dn) < 0.1 * self.eps:
break
if not self.always_change_basis:
f1, f2, f3 = f0i, fi, f(2 * xi - x0i)
if f3 >= f1 or (f1 - 2 * f2 + f3) * (f1 - f2 - delta_k) ** 2 >= 0.5 * delta_k * (f1 - f3) ** 2:
if f3 < f2:
xi = 2 * xi - x0i
fi = f3
iteration += 1
continue
alpha, fi = ls.optimize(problem, xi, fi, dn)
xi += alpha * dn
d = np.append(np.delete(d, ind, axis=0), np.array([dn]), axis=0)
if np.all(np.abs(d) < self.eps) or np.linalg.norm(xi - x0i) < 0.1 * self.eps:
break
iteration += 1
x0 = np.copy(xi)
restart += 1
return fi, xi
if __name__ == '__main__':
pass