方向是牛顿方向 G k d k = − g k G_kd_{k}=-g_k Gkdk=−gk
稳定牛顿法
步长为1
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
def Newton(f,g,h,X,N):
eps = 1e-8
for i in range(N):
X_old = X
d,lu = torch.solve(-g(X_old).t(),h(X_old))
X = X_old + d.t()
if i%5 == 0:
print('the iteration:%d,grad_2:%.3e'%(i,(g(X)**2).sum()))
tmp = abs(f(X_old) - f(X))
if max(tmp) < eps:
break
print('the end iteration:%d,grad_2:%.3e'%(i + 1,(g(X)**2).sum()))
return X
#Wood函数
def FF(X):
out = 100*(X[:,1] - X[:,0])**2 + (1 - X[:,0])**2 + 90*(X[:,3] - X[:,2])**2 + (1 - X[:,2])**2 + 10*(X[:,1] + X[:,3] - 2)**2 + ((X[:,1] - X[:,3])**2)/10
return out
def GG(X):
n = X.shape[1]
vec = torch.zeros_like(X)
vec[:,0] = -400*X[:,0]*(X[:,1] - X[:,0]**2) - 2*(1 - X[:,0])
vec[:,1] = 200*(X[:,1] - X[:,0]**2) + 20*(X[:,1] + X[:,3]- 2) + (X[:,1] - X[:,3])/5
vec[:,2] = -360*X[:,2]*(X[:,3] - X[:,2]**2) - 2*(1 - X[:,2])
vec[:,3] = 180*(X[:,3] - X[:,2]**2) + 20*(X[:,1] + X[:,3] - 2) - (X[:,1] - X[:,3])/5
return vec
def HH(X):
n = X.shape[1]
mat = torch.zeros(n,n)
mat[0,0] = -400*(X[:,1] - X[:,0]**2) + 800*X[:,0]**2 + 2
mat[0,1] = -400*X[:,0];mat[0,2] = 0;mat[0,3] = 0
#----------------
mat[1,0] = -400*X[:,0]
mat[1,1] = 220.5
mat[1,2] = 0;mat[1,3] = 19.5
#-----------------
mat[2,0] = 0;mat[2,1] = 0
mat[2,2] = 720*X[:,2]**2 - 360*(X[:,3] - X[:,2]**2) + 2
mat[2,3] = -360*X[:,2]
#---------------------
mat[3,0] = 0
mat[3,1] = 19.5
mat[3,2] = -360*X[:,2]
mat[3,3] = 200.5
return mat
X = torch.tensor([[-3.0,-1,-3,-1]])
N = 200
x_new = Newton(FF,GG,HH,X,N)
print(x_new)
print(FF(x_new))
#!/usr/bin/env python
# coding: utf-8
# In[2]:
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
import random
# In[3]:
def Newton(f,g,h,X,N):
eps = 1e-8
for i in range(N):
X_old = X
d,lu = torch.solve(-g(X_old).t(),h(X_old))
X = X_old + d.t()
if i%5 == 0:
print('the iteration:%d,grad_2:%.3e'%(i,(g(X)**2).sum()))
tmp = abs(f(X_old) - f(X))
if max(tmp) < eps:
break
print('the end iteration:%d,grad_2:%.3e'%(i + 1,(g(X)**2).sum()))
return X
# In[6]:
#Trigonometric 函数
def F(X,i):
n = X.shape[1]
temp = 0
for j in range(n):
temp -= torch.cos(X[:,j])
temp += n + (i + 1)*(1 - torch.cos(X[:,i])) - torch.sin(X[:,i])
return temp
def FF(X):
n = X.shape[1]
temp = 0
for j in range(n):
temp += F(X,j)**2
return temp
def GG(X):
n = X.shape[1]
vec = torch.zeros_like(X)
temp = 0
for j in range(n):
temp += F(X,j)
for i in range(n):
vec[:,i] = 2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*F(X,i) + 2*torch.sin(X[:,i])*temp
return vec
def HH(X):
n = X.shape[1]
mat = torch.zeros(n,n)
temp = 0
for j in range(n):
temp += F(X,j)
for i in range(n):
for j in range(n):
if i == j:
mat[i,j] = 2*((i + 1)*torch.cos(X[:,i]) + torch.sin(X[:,i]))*F(X,i) + 2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*((i + 2)*torch.sin(X[:,i]) - torch.cos(X[:,i])) + 2*torch.cos(X[:,i])*temp + 2*torch.sin(X[:,i])*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))
else:
mat[i,j] = 2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*torch.sin(X[:,j]) + 2*torch.sin(X[:,i])*((j + 1)*torch.sin(X[:,j]) - torch.cos(X[:,j]))
return mat
n = 20;X = torch.ones(1,n)/n
alpham = 1.0
rho = 0.4
t = 1
N = 800
x_new = Newton(FF,GG,HH,X,N)
print(x_new)
print(FF(x_new))
#!/usr/bin/env python
# coding: utf-8
# In[4]:
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
# In[5]:
def Newton(f,g,h,X,N):
eps = 1e-8
for i in range(N):
X_old = X
d,lu = torch.solve(-g(X_old).t(),h(X_old))
X = X_old + d.t()
if i%5 == 0:
print('the iteration:%d,grad_2:%.3e'%(i,(g(X)**2).sum()))
tmp = abs(f(X_old) - f(X))
if max(tmp) < eps:
break
print('the end iteration:%d,grad_2:%.3e'%(i + 1,(g(X)**2).sum()))
return X
#eps函数
# Extended Powell singular function
def F(X,rank,i):
if i == 0:
return X[:,4*rank] + 10*X[:,4*rank + 1]
if i == 1:
return (X[:,4*rank + 2] - X[:,4*rank + 3])*5**(0.5)
if i == 2:
return (X[:,4*rank + 1] - 2*X[:,4*rank + 2])**2
if i == 3:
return (10**(0.5))*(X[:,4*i] - X[:,4*i + 3])**2
def FF(X):#i >= 0
n = X.shape[1];rank = int(n/4)
temp = 0
for i in range(rank):
temp += (X[:,4*i] + 10*X[:,4*i + 1])**2
temp += 5*(X[:,4*i + 2] - X[:,4*i + 3])**2
temp += (X[:,4*i + 1] - 2*X[:,4*i + 2])**4
temp += 10*(X[:,4*i] - X[:,4*i + 3])**4
return temp
def GG(X):
n = X.shape[1];rank = int(n/4)
vec = torch.zeros_like(X)
for i in range(rank):
vec[:,4*i] = 2*(X[:,4*i] + 10*X[:,4*i + 1]) + 40*(X[:,4*i] - X[:,4*i + 3])**3
vec[:,4*i + 1] = 20*(X[:,4*i] + 10*X[:,4*i + 1]) + 4*(X[:,4*i + 1] - 2*X[:,4*i + 2])**3
vec[:,4*i + 2] = 10*(X[:,4*i + 2] - X[:,4*i + 3]) - 8*(X[:,4*i + 1] - 2*X[:,4*i + 2])**3
vec[:,4*i + 3] = -10*(X[:,4*i + 2] - X[:,4*i + 3]) - 40*(X[:,4*i] - X[:,4*i + 3])**3
return vec
def HH(X):
n = X.shape[1];rank = int(n/4)
mat = torch.zeros(n,n)
for j in range(rank):
mat[4*j,4*j] = 2 + 120*(X[:,4*j] - X[:,4*j + 3])**2
mat[4*j,4*j + 1] = 20
mat[4*j,4*j + 2] = 0
mat[4*j,4*j + 3] = - 120*(X[:,4*j] - X[:,4*j + 3])**2
#------------------
mat[4*j + 1,4*j] = 20
mat[4*j + 1,4*j + 1] = 200 + 12*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 1,4*j + 2] = -24*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 1,4*j + 3] = 0
#-------------------
mat[4*j + 2,4*j] = 0
mat[4*j + 2,4*j + 1] = -24*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 2,4*j + 2] = 10 + 48*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 2,4*j + 3] = -10
#----------------
mat[4*j + 3,4*j] = - 120*(X[:,4*j] - X[:,4*j + 3])**2
mat[4*j + 3,4*j + 1] = 0
mat[4*j + 3,4*j + 2] = -10
mat[4*j + 3,4*j + 3] = 10 + 120*(X[:,4*j] - X[:,4*j + 3])**2
return mat
n = 20
X = torch.zeros(1,n)
for i in range(int(n/4)):
X[:,4*i] = 3.0
X[:,4*i + 1] = -1
X[:,4*i + 3] = 1
N = 200
x_new = Newton(FF,GG,HH,X,N)
print(x_new)
print(FF(x_new))
GLL+牛顿方向
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
#eps函数
# Extended Powell singular function
def F(X,rank,i):
if i == 0:
return X[:,4*rank] + 10*X[:,4*rank + 1]
if i == 1:
return (X[:,4*rank + 2] - X[:,4*rank + 3])*5**(0.5)
if i == 2:
return (X[:,4*rank + 1] - 2*X[:,4*rank + 2])**2
if i == 3:
return (10**(0.5))*(X[:,4*i] - X[:,4*i + 3])**2
def FF(X):#i >= 0
n = X.shape[1];rank = int(n/4)
temp = 0
for i in range(rank):
temp += (X[:,4*i] + 10*X[:,4*i + 1])**2
temp += 5*(X[:,4*i + 2] - X[:,4*i + 3])**2
temp += (X[:,4*i + 1] - 2*X[:,4*i + 2])**4
temp += 10*(X[:,4*i] - X[:,4*i + 3])**4
return temp
def GG(X):
n = X.shape[1];rank = int(n/4)
vec = torch.zeros_like(X)
for i in range(rank):
vec[:,4*i] = 2*(X[:,4*i] + 10*X[:,4*i + 1]) + 40*(X[:,4*i] - X[:,4*i + 3])**3
vec[:,4*i + 1] = 20*(X[:,4*i] + 10*X[:,4*i + 1]) + 4*(X[:,4*i + 1] - 2*X[:,4*i + 2])**3
vec[:,4*i + 2] = 10*(X[:,4*i + 2] - X[:,4*i + 3]) - 8*(X[:,4*i + 1] - 2*X[:,4*i + 2])**3
vec[:,4*i + 3] = -10*(X[:,4*i + 2] - X[:,4*i + 3]) - 40*(X[:,4*i] - X[:,4*i + 3])**3
return vec
def HH(X):
n = X.shape[1];rank = int(n/4)
mat = torch.zeros(n,n)
for j in range(rank):
mat[4*j,4*j] = 2 + 120*(X[:,4*j] - X[:,4*j + 3])**2
mat[4*j,4*j + 1] = 20
mat[4*j,4*j + 2] = 0
mat[4*j,4*j + 3] = - 120*(X[:,4*j] - X[:,4*j + 3])**2
#------------------
mat[4*j + 1,4*j] = 20
mat[4*j + 1,4*j + 1] = 200 + 12*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 1,4*j + 2] = -24*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 1,4*j + 3] = 0
#-------------------
mat[4*j + 2,4*j] = 0
mat[4*j + 2,4*j + 1] = -24*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 2,4*j + 2] = 10 + 48*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 2,4*j + 3] = -10
#----------------
mat[4*j + 3,4*j] = - 120*(X[:,4*j] - X[:,4*j + 3])**2
mat[4*j + 3,4*j + 1] = 0
mat[4*j + 3,4*j + 2] = -10
mat[4*j + 3,4*j + 3] = 10 + 120*(X[:,4*j] - X[:,4*j + 3])**2
return mat
def gll(f,df,d,x,rho,lis,M = 4):
if (df(x)**2).sum() > 1e2:
al_old = 16.0
else:
al_old = 1.0
for i in range(10):
mi = min(i + 1,M)
al_new = al_old*0.5**i
#print(max(lis[-mi:]))
if f(x + al_new*d.t()) <= max(lis[-mi:]) + rho*al_new*df(x)@d:
break
return al_new
def gllsolve(f,df,h,x,rho,M,N):
lis = []
eps = 1e-8
for i in range(N):
x_old = x
lis.append(f(x_old))
d,lu = torch.solve(-df(x_old).t(),h(x_old))
al_new = gll(f,df,d,x_old,rho,lis,M)
x = x_old + al_new*d.t()
if i%20 == 0:
print('the iteration is %d,the grad_2 is %.3e'%(i,(df(x)**2).sum()))
tmp = abs(f(x_old) - f(x))
if max(tmp) < eps:
break
print('the end iteration is %d,the grad_2 is %.3e,tmp = %.3e'%(i + 1,(df(x)**2).sum(),tmp))
return x
n = 20
X = torch.zeros(1,n)
for i in range(int(n/4)):
X[:,4*i] = 3.0
X[:,4*i + 1] = -1
X[:,4*i + 3] = 1
N = 200
rho = 0.4
M = 4
x = gllsolve(FF,GG,HH,X,rho,M,N)
print(FF(x))
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
#Trigonometric 函数
def F(X,i):
n = X.shape[1]
temp = 0
for j in range(n):
temp -= torch.cos(X[:,j])
temp += n + (i + 1)*(1 - torch.cos(X[:,i])) - torch.sin(X[:,i])
return temp
def FF(X):
n = X.shape[1]
temp = 0
for j in range(n):
temp += F(X,j)**2
return temp
def GG(X):
n = X.shape[1]
vec = torch.zeros_like(X)
temp = 0
for j in range(n):
temp += F(X,j)
for i in range(n):
vec[:,i] = 2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*F(X,i) + 2*torch.sin(X[:,i])*temp
return vec
def HH(X):
n = X.shape[1]
mat = torch.zeros(n,n)
temp = 0
for j in range(n):
temp += F(X,j)
for i in range(n):
for j in range(n):
if i == j:
mat[i,j] = 2*((i + 1)*torch.cos(X[:,i]) + torch.sin(X[:,i]))*F(X,i) + 2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*((i + 2)*torch.sin(X[:,i]) - torch.cos(X[:,i])) + 2*torch.cos(X[:,i])*temp + 2*torch.sin(X[:,i])*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))
else:
mat[i,j] = 2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*torch.sin(X[:,j]) + 2*torch.sin(X[:,i])*((j + 1)*torch.sin(X[:,j]) - torch.cos(X[:,j]))
return mat
def gll(f,df,d,x,rho,lis,M = 4):
if (df(x)**2).sum() > 1e2:
al_old = 16.0
else:
al_old = 1.0
for i in range(10):
mi = min(i + 1,M)
al_new = al_old*0.5**i
#print(max(lis[-mi:]))
if f(x + al_new*d.t()) <= max(lis[-mi:]) + rho*al_new*df(x)@d:
break
return al_new
def gllsolve(f,df,h,x,rho,M,N):
lis = []
eps = 1e-8
for i in range(N):
x_old = x
lis.append(f(x_old))
d,lu = torch.solve(-df(x_old).t(),h(x_old))
al_new = gll(f,df,d,x_old,rho,lis,M)
x = x_old + al_new*d.t()
if i%20 == 0:
print('the iteration is %d,the grad_2 is %.3e'%(i,(df(x)**2).sum()))
tmp = abs(f(x_old) - f(x))
if max(tmp) < eps:
break
print('the end iteration is %d,the grad_2 is %.3e,tmp = %.3e'%(i + 1,(df(x)**2).sum(),tmp))
return x
n = 20;X = torch.ones(1,n)/n
rho = 0.4
M = 4
N = 100
x = gllsolve(FF,GG,HH,X,rho,M,N)
print(FF(x))
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
#Wood函数
def FF(X):
out = 100*(X[:,1] - X[:,0])**2 + (1 - X[:,0])**2 + 90*(X[:,3] - X[:,2])**2 + \
(1 - X[:,2])**2 + 10*(X[:,1] + X[:,3] - 2)**2 + ((X[:,1] - X[:,3])**2)/10
return out
def GG(X):
n = X.shape[1]
vec = torch.zeros_like(X)
vec[:,0] = -400*X[:,0]*(X[:,1] - X[:,0]**2) - 2*(1 - X[:,0])
vec[:,1] = 200*(X[:,1] - X[:,0]**2) + 20*(X[:,1] + X[:,3]- 2) + (X[:,1] - X[:,3])/5
vec[:,2] = -360*X[:,2]*(X[:,3] - X[:,2]**2) - 2*(1 - X[:,2])
vec[:,3] = 180*(X[:,3] - X[:,2]**2) + 20*(X[:,1] + X[:,3] - 2) - (X[:,1] - X[:,3])/5
return vec
def HH(X):
n = X.shape[1]
mat = torch.zeros(n,n)
mat[0,0] = -400*(X[:,1] - X[:,0]**2) + 800*X[:,0]**2 + 2
mat[0,1] = -400*X[:,0];mat[0,2] = 0;mat[0,3] = 0
#----------------
mat[1,0] = -400*X[:,0]
mat[1,1] = 220.5
mat[1,2] = 0;mat[1,3] = 19.5
#-----------------
mat[2,0] = 0;mat[2,1] = 0
mat[2,2] = 720*X[:,2]**2 - 360*(X[:,3] - X[:,2]**2) + 2
mat[2,3] = -360*X[:,2]
#---------------------
mat[3,0] = 0
mat[3,1] = 19.5
mat[3,2] = -360*X[:,2]
mat[3,3] = 200.5
return mat
def gll(f,df,d,x,rho,lis,M = 4):
if (df(x)**2).sum() > 1e2:
al_old = 16.0
else:
al_old = 1.0
for i in range(10):
mi = min(i + 1,M)
al_new = al_old*0.5**i
#print(max(lis[-mi:]))
if f(x + al_new*d.t()) <= max(lis[-mi:]) + rho*al_new*df(x)@d:
break
return al_new
def gllsolve(f,df,h,x,rho,M,N):
lis = []
eps = 1e-8
for i in range(N):
x_old = x
lis.append(f(x_old))
d,lu = torch.solve(-df(x_old).t(),h(x_old))
al_new = gll(f,df,d,x_old,rho,lis,M)
x = x_old + al_new*d.t()
if i%20 == 0:
print('the iteration is %d,the grad_2 is %.3e'%(i,(df(x)**2).sum()))
tmp = abs(f(x_old) - f(x))
if max(tmp) < eps:
break
print('the end iteration is %d,the grad_2 is %.3e,tmp = %.3e'%(i + 1,(df(x)**2).sum(),tmp))
return x
X = torch.tensor([[-3.0,-1,-3,-1]])
d,lu = torch.solve(-GG(X).t(),HH(X))
rho = 0.4
M = 4
N = 300
x = gllsolve(FF,GG,HH,X,rho,M,N)
print(FF(x))
gold+牛顿方向
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 22 23:08:02 2020
@author: 2001213226
"""
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
def goldsteinsearch(f,df,d,x,alpham,rho,t):#利用goldstein原则求解步长
flag = 0
a = 0
b = alpham
fk = f(x)
gk = df(x)
phi0 = fk
dphi0 = gk@d.t()#梯度和方向的内积
# print(dphi0)
#alpha=b*random.uniform(0,1)
alpha = 1e-1
for i in range(10):#类似于二分的过程,最多进行10次
newfk = f(x + alpha * d)
phi = newfk
if (phi - phi0 )<= (rho * alpha * dphi0):
if (phi - phi0) >= ((1 - rho) * alpha * dphi0):
break#如果满足goldstein的两个准则,直接跳出循环
else:
a = alpha
b = b
if (b < alpham):
alpha = (a + b) / 2
else:
alpha = t * alpha
else:
a = a
b = alpha
alpha = (a + b) / 2
return alpha
def Goldsolve(x,f,df,h,alpham,rho,t,N):
eps = 1e-8
for i in range(N):
X_old = x
d,lu = torch.solve(-df(X_old).t(),h(X_old))
x = X_old + goldsteinsearch(f,df,d.t(),x,alpham,rho,t)*d.t()
if i%20 == 0:
print('the iteration is %d,the grad_2 is %.3f'%(i,(df(x)**2).sum()))
tmp = abs(f(X_old) - f(x))
if max(tmp) < eps:
break
print('the end iteration is %d,the grad_2 is %.3f,tmp = %.3f'%(i + 1,(df(x)**2).sum(),tmp))
return x
#Wood函数
def FF(X):
out = 100*(X[:,1] - X[:,0])**2 + (1 - X[:,0])**2 + 90*(X[:,3] - X[:,2])**2 + \
(1 - X[:,2])**2 + 10*(X[:,1] + X[:,3] - 2)**2 + ((X[:,1] - X[:,3])**2)/10
return out
def GG(X):
n = X.shape[1]
vec = torch.zeros_like(X)
vec[:,0] = -400*X[:,0]*(X[:,1] - X[:,0]**2) - 2*(1 - X[:,0])
vec[:,1] = 200*(X[:,1] - X[:,0]**2) + 20*(X[:,1] + X[:,3]- 2) + (X[:,1] - X[:,3])/5
vec[:,2] = -360*X[:,2]*(X[:,3] - X[:,2]**2) - 2*(1 - X[:,2])
vec[:,3] = 180*(X[:,3] - X[:,2]**2) + 20*(X[:,1] + X[:,3] - 2) - (X[:,1] - X[:,3])/5
return vec
def HH(X):
n = X.shape[1]
mat = torch.zeros(n,n)
mat[0,0] = -400*(X[:,1] - X[:,0]**2) + 800*X[:,0]**2 + 2
mat[0,1] = -400*X[:,0];mat[0,2] = 0;mat[0,3] = 0
#----------------
mat[1,0] = -400*X[:,0]
mat[1,1] = 220.5
mat[1,2] = 0;mat[1,3] = 19.5
#-----------------
mat[2,0] = 0;mat[2,1] = 0
mat[2,2] = 720*X[:,2]**2 - 360*(X[:,3] - X[:,2]**2) + 2
mat[2,3] = -360*X[:,2]
#---------------------
mat[3,0] = 0
mat[3,1] = 19.5
mat[3,2] = -360*X[:,2]
mat[3,3] = 200.5
return mat
X = torch.tensor([[-3.0,-1,-3,-1]])
alpham = 1.0
rho = 0.4
t = 1
N =100
x_new = Goldsolve(X,FF,GG,HH,alpham,rho,t,N)
print(FF(x_new))
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
def goldsteinsearch(f,df,d,x,alpham,rho,t):#利用goldstein原则求解步长
flag = 0
a = 0
b = alpham
fk = f(x)
gk = df(x)
phi0 = fk
dphi0 = gk@d.t()#梯度和方向的内积
# print(dphi0)
#alpha=b*random.uniform(0,1)
alpha = 1e-1
for i in range(10):#类似于二分的过程,最多进行10次
newfk = f(x + alpha * d)
phi = newfk
if (phi - phi0 )<= (rho * alpha * dphi0):
if (phi - phi0) >= ((1 - rho) * alpha * dphi0):
break#如果满足goldstein的两个准则,直接跳出循环
else:
a = alpha
b = b
if (b < alpham):
alpha = (a + b) / 2
else:
alpha = t * alpha
else:
a = a
b = alpha
alpha = (a + b) / 2
return alpha
def Goldsolve(x,f,df,h,alpham,rho,t,N):
eps = 1e-8
for i in range(N):
X_old = x
d,lu = torch.solve(-df(X_old).t(),h(X_old))
x = X_old + goldsteinsearch(f,df,d.t(),x,alpham,rho,t)*d.t()
if i%20 == 0:
print('the iteration is %d,the grad_2 is %.3f'%(i,(df(x)**2).sum()))
tmp = abs(f(X_old) - f(x))
if max(tmp) < eps:
break
print('the end iteration is %d,the grad_2 is %.3f,tmp = %.3f'%(i + 1,(df(x)**2).sum(),tmp))
return x
#Trigonometric 函数
def F(X,i):
n = X.shape[1]
temp = 0
for j in range(n):
temp -= torch.cos(X[:,j])
temp += n + (i + 1)*(1 - torch.cos(X[:,i])) - torch.sin(X[:,i])
return temp
def FF(X):
n = X.shape[1]
temp = 0
for j in range(n):
temp += F(X,j)**2
return temp
def GG(X):
n = X.shape[1]
vec = torch.zeros_like(X)
temp = 0
for j in range(n):
temp += F(X,j)
for i in range(n):
vec[:,i] = 2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*F(X,i) + 2*torch.sin(X[:,i])*temp
return vec
def HH(X):
n = X.shape[1]
mat = torch.zeros(n,n)
temp = 0
for j in range(n):
temp += F(X,j)
for i in range(n):
for j in range(n):
if i == j:
mat[i,j] = 2*((i + 1)*torch.cos(X[:,i]) + torch.sin(X[:,i]))*F(X,i) + \
2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*((i + 2)*torch.sin(X[:,i]) - torch.cos(X[:,i])) +\
2*torch.cos(X[:,i])*temp + 2*torch.sin(X[:,i])*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))
else:
mat[i,j] = 2*((i + 1)*torch.sin(X[:,i]) - torch.cos(X[:,i]))*torch.sin(X[:,j]) + \
2*torch.sin(X[:,i])*((j + 1)*torch.sin(X[:,j]) - torch.cos(X[:,j]))
return mat
n = 20;X = torch.ones(1,n)/n
alpham = 1.0
rho = 0.4
t = 1
N = 200
x_new = Goldsolve(X,FF,GG,HH,alpham,rho,t,N)
print(FF(x_new))
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 22 23:06:47 2020
@author: 2001213226
"""
import numpy as np
import matplotlib.pyplot as plt
import torch
import time
import torch.nn as nn
import torch.nn.functional as F
def goldsteinsearch(f,df,d,x,alpham,rho,t):#利用goldstein原则求解步长
flag = 0
a = 0
b = alpham
fk = f(x)
gk = df(x)
phi0 = fk
dphi0 = gk@d.t()#梯度和方向的内积
# print(dphi0)
#alpha=b*random.uniform(0,1)
alpha = 1e-1
for i in range(10):#类似于二分的过程,最多进行10次
newfk = f(x + alpha * d)
phi = newfk
if (phi - phi0 )<= (rho * alpha * dphi0):
if (phi - phi0) >= ((1 - rho) * alpha * dphi0):
break#如果满足goldstein的两个准则,直接跳出循环
else:
a = alpha
b = b
if (b < alpham):
alpha = (a + b) / 2
else:
alpha = t * alpha
else:
a = a
b = alpha
alpha = (a + b) / 2
return alpha
def Goldsolve(x,f,df,h,alpham,rho,t,N):
eps = 1e-8
for i in range(N):
X_old = x
d,lu = torch.solve(-df(X_old).t(),h(X_old))
x = X_old + goldsteinsearch(f,df,d.t(),x,alpham,rho,t)*d.t()
if i%20 == 0:
print('the iteration is %d,the grad_2 is %.3f'%(i,(df(x)**2).sum()))
tmp = abs(f(X_old) - f(x))
if max(tmp) < eps:
break
print('the end iteration is %d,the grad_2 is %.3f,tmp = %.3f'%(i + 1,(df(x)**2).sum(),tmp))
return x
#eps函数
# Extended Powell singular function
def F(X,rank,i):
if i == 0:
return X[:,4*rank] + 10*X[:,4*rank + 1]
if i == 1:
return (X[:,4*rank + 2] - X[:,4*rank + 3])*5**(0.5)
if i == 2:
return (X[:,4*rank + 1] - 2*X[:,4*rank + 2])**2
if i == 3:
return (10**(0.5))*(X[:,4*i] - X[:,4*i + 3])**2
def FF(X):#i >= 0
n = X.shape[1];rank = int(n/4)
temp = 0
for i in range(rank):
temp += (X[:,4*i] + 10*X[:,4*i + 1])**2
temp += 5*(X[:,4*i + 2] - X[:,4*i + 3])**2
temp += (X[:,4*i + 1] - 2*X[:,4*i + 2])**4
temp += 10*(X[:,4*i] - X[:,4*i + 3])**4
return temp
def GG(X):
n = X.shape[1];rank = int(n/4)
vec = torch.zeros_like(X)
for i in range(rank):
vec[:,4*i] = 2*(X[:,4*i] + 10*X[:,4*i + 1]) + 40*(X[:,4*i] - X[:,4*i + 3])**3
vec[:,4*i + 1] = 20*(X[:,4*i] + 10*X[:,4*i + 1]) + 4*(X[:,4*i + 1] - 2*X[:,4*i + 2])**3
vec[:,4*i + 2] = 10*(X[:,4*i + 2] - X[:,4*i + 3]) - 8*(X[:,4*i + 1] - 2*X[:,4*i + 2])**3
vec[:,4*i + 3] = -10*(X[:,4*i + 2] - X[:,4*i + 3]) - 40*(X[:,4*i] - X[:,4*i + 3])**3
return vec
def HH(X):
n = X.shape[1];rank = int(n/4)
mat = torch.zeros(n,n)
for j in range(rank):
mat[4*j,4*j] = 2 + 120*(X[:,4*j] - X[:,4*j + 3])**2
mat[4*j,4*j + 1] = 20
mat[4*j,4*j + 2] = 0
mat[4*j,4*j + 3] = - 120*(X[:,4*j] - X[:,4*j + 3])**2
#------------------
mat[4*j + 1,4*j] = 20
mat[4*j + 1,4*j + 1] = 200 + 12*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 1,4*j + 2] = -24*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 1,4*j + 3] = 0
#-------------------
mat[4*j + 2,4*j] = 0
mat[4*j + 2,4*j + 1] = -24*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 2,4*j + 2] = 10 + 48*(X[:,4*j + 1] - 2*X[:,4*j + 2])**2
mat[4*j + 2,4*j + 3] = -10
#----------------
mat[4*j + 3,4*j] = - 120*(X[:,4*j] - X[:,4*j + 3])**2
mat[4*j + 3,4*j + 1] = 0
mat[4*j + 3,4*j + 2] = -10
mat[4*j + 3,4*j + 3] = 10 + 120*(X[:,4*j] - X[:,4*j + 3])**2
return mat
n = 20
X = torch.zeros(1,n)
for i in range(int(n/4)):
X[:,4*i] = 3.0
X[:,4*i + 1] = -1
X[:,4*i + 3] = 1
alpham = 1.0
rho = 0.4
t = 1
N = 800
x_new = Goldsolve(X,FF,GG,HH,alpham,rho,t,N)
print(FF(x_new))
运行结果