使用 scipy.optimize.minimize() 进行约束优化的问题
Problems with constrained optimization using scipy.optimize.minimize()
我正在尝试使用 scipy.optimize.minimize()
进行约束优化。如果我们调用最小化问题的解决方案 s
,我试图实现的约束集合 s[0] = 0
和 s[-1] = 1
。这是重现我得到的错误的最小脚本:
import numpy as np
from scipy.optimize import minimize
def potential( x, y ):
x2 = x * x
x4 = x2 * x2
y2 = y * y
y5 = ( y - 5./3. ) * ( y - 5./3. )
y3 = ( y - 1./3. ) * ( y - 1./3. )
y34 = y3 * y3
x_1 = ( x - 1. ) * ( x - 1. )
x1 = ( x + 1. ) * ( x + 1. )
pot = 5. * np.exp( -x2 - y2 ) - 3. * np.exp( - x2 - y5 ) - 5. * np.exp( - x_1 - y2 ) - 5. * np.exp( - x1 - y2 ) + 0.2 * x4 + 0.2 * y34
return pot
def functional( q, x_new, y_new ):
I = 0
beta = 1./6.67
dl = 0.2
dl2 = dl**2
for k in range(1, len(q) - 1):
ngradU = ( potential(x_new[k+1], y_new[k+1]) - potential(x_new[k], y_new[k]) ) / dl
I += ( beta/dl2 * ( q[k+1] + q[k-1] - 2. * q[k] ) + beta/2. * (q[k+1] - q[k]) * ngradU )**2
return I
def delta(i, k):
if( i == k ):
return 1.
else:
return 0.
def derivative( q, x_new, y_new ):
beta = 1./6.67
dl = 0.2
dl2 = dl**2
der = np.zeros_like(q)
for j in range(len(q)):
for k in range(1, len(q) - 1):
ngradU = ( potential(x_new[k+1], y_new[k+1]) - potential(x_new[k], y_new[k]) ) / dl
deltas = beta/dl2 * ( delta(k+1, j) + delta(k-1,j) - 2. * delta(k,j) ) - beta/dl * ngradU * ( delta(k+1, j) - delta(k,j) )
der[j] += ( beta/dl2 * ( q[k+1] + q[k-1] - 2. * q[k] ) + beta/2. * (q[k+1] - q[k]) * ngradU ) * deltas
return der
### MAIN
x_new = [-0.75956243, -0.63528643, -0.49338262, -0.35764855, -0.23954228, -0.12408018, 0.02134918, 0.20379693, 0.32454737, 0.43119557, 0.54225072, 0.66211977, 0.78198882]
y_new = [0.55944712, 0.70475988, 0.83125047, 0.96420533, 1.11378898, 1.26572396, 1.38819039, 1.33494757, 1.18824942, 1.03070726, 0.87501396, 0.7275383, 0.57900219]
s = [ 0.07453653, 0.14188005, 0.21413291, 0.28632847, 0.35839168, 0.43770331, 0.51499522, 0.58833728, 0.66737105, 0.73637078, 0.80085735, 0.86481271, 0.92374577]
cons = ({'type': 'eq',
'fun' : lambda x: x[0],
'jac' : lambda x: x[0]},
{'type': 'eq',
'fun' : lambda x: x[-1],
'jac' : lambda x: x[-1]})
res = minimize(functional, s, method='SLSQP', jac=derivative, constraints=cons, options={'disp': True}, args=(x_new, y_new))
错误如下:
ValueError: all the input array dimensions except for the concatenation axis must match exactly
x_new
、y_new
和 s
的长度完全匹配,所以我猜我在约束方面做错了什么。事实上,当我使用 method='CG'
和完全相同的参数时 - 不包括约束 - 计算运行完美。
感谢您的帮助!
错误是您在 cons
中的 jac
。
'jac' : lambda x: x[0]
你的x
是一个数组,数组的jac
应该产生一个数组。您可以通过删除此 jac
或通过正确的维度来修复它。
'CG' 方法无法处理约束,因此您的 cons
被简单地忽略了,这就是为什么您没有在 'CG'.
中发现此错误的原因
我正在尝试使用 scipy.optimize.minimize()
进行约束优化。如果我们调用最小化问题的解决方案 s
,我试图实现的约束集合 s[0] = 0
和 s[-1] = 1
。这是重现我得到的错误的最小脚本:
import numpy as np
from scipy.optimize import minimize
def potential( x, y ):
x2 = x * x
x4 = x2 * x2
y2 = y * y
y5 = ( y - 5./3. ) * ( y - 5./3. )
y3 = ( y - 1./3. ) * ( y - 1./3. )
y34 = y3 * y3
x_1 = ( x - 1. ) * ( x - 1. )
x1 = ( x + 1. ) * ( x + 1. )
pot = 5. * np.exp( -x2 - y2 ) - 3. * np.exp( - x2 - y5 ) - 5. * np.exp( - x_1 - y2 ) - 5. * np.exp( - x1 - y2 ) + 0.2 * x4 + 0.2 * y34
return pot
def functional( q, x_new, y_new ):
I = 0
beta = 1./6.67
dl = 0.2
dl2 = dl**2
for k in range(1, len(q) - 1):
ngradU = ( potential(x_new[k+1], y_new[k+1]) - potential(x_new[k], y_new[k]) ) / dl
I += ( beta/dl2 * ( q[k+1] + q[k-1] - 2. * q[k] ) + beta/2. * (q[k+1] - q[k]) * ngradU )**2
return I
def delta(i, k):
if( i == k ):
return 1.
else:
return 0.
def derivative( q, x_new, y_new ):
beta = 1./6.67
dl = 0.2
dl2 = dl**2
der = np.zeros_like(q)
for j in range(len(q)):
for k in range(1, len(q) - 1):
ngradU = ( potential(x_new[k+1], y_new[k+1]) - potential(x_new[k], y_new[k]) ) / dl
deltas = beta/dl2 * ( delta(k+1, j) + delta(k-1,j) - 2. * delta(k,j) ) - beta/dl * ngradU * ( delta(k+1, j) - delta(k,j) )
der[j] += ( beta/dl2 * ( q[k+1] + q[k-1] - 2. * q[k] ) + beta/2. * (q[k+1] - q[k]) * ngradU ) * deltas
return der
### MAIN
x_new = [-0.75956243, -0.63528643, -0.49338262, -0.35764855, -0.23954228, -0.12408018, 0.02134918, 0.20379693, 0.32454737, 0.43119557, 0.54225072, 0.66211977, 0.78198882]
y_new = [0.55944712, 0.70475988, 0.83125047, 0.96420533, 1.11378898, 1.26572396, 1.38819039, 1.33494757, 1.18824942, 1.03070726, 0.87501396, 0.7275383, 0.57900219]
s = [ 0.07453653, 0.14188005, 0.21413291, 0.28632847, 0.35839168, 0.43770331, 0.51499522, 0.58833728, 0.66737105, 0.73637078, 0.80085735, 0.86481271, 0.92374577]
cons = ({'type': 'eq',
'fun' : lambda x: x[0],
'jac' : lambda x: x[0]},
{'type': 'eq',
'fun' : lambda x: x[-1],
'jac' : lambda x: x[-1]})
res = minimize(functional, s, method='SLSQP', jac=derivative, constraints=cons, options={'disp': True}, args=(x_new, y_new))
错误如下:
ValueError: all the input array dimensions except for the concatenation axis must match exactly
x_new
、y_new
和 s
的长度完全匹配,所以我猜我在约束方面做错了什么。事实上,当我使用 method='CG'
和完全相同的参数时 - 不包括约束 - 计算运行完美。
感谢您的帮助!
错误是您在 cons
中的 jac
。
'jac' : lambda x: x[0]
你的x
是一个数组,数组的jac
应该产生一个数组。您可以通过删除此 jac
或通过正确的维度来修复它。
'CG' 方法无法处理约束,因此您的 cons
被简单地忽略了,这就是为什么您没有在 'CG'.