Python 具有两个约束的数组优化
Python array optimization with two constraints
我有一个优化问题,我试图找到一个需要同时优化两个函数的数组。
在下面的最小示例中,我有两个已知数组 w
和 x
以及一个 unknown 数组 y
。我将数组 y
初始化为仅包含 1s.
然后我指定函数 np.sqrt(np.sum((x-np.array)**2)
并想找到数组 y
where
np.sqrt(np.sum((x-y)**2)
接近 5
np.sqrt(np.sum((w-y)**2)
接近 8
下面的代码可用于针对单个数组成功优化 y
,但我想找到针对两个 x
优化 y
的解决方案] 和 y
同时,但我不确定如何指定这两个约束。
y
应该只包含大于 0 的值。
关于如何解决这个问题的任何想法?
w = np.array([6, 3, 1, 0, 2])
x = np.array([3, 4, 5, 6, 7])
y = np.array([1, 1, 1, 1, 1])
def func(x, y):
z = np.sqrt(np.sum((x-y)**2)) - 5
return np.zeros(x.shape[0],) + z
r = opt.root(func, x0=y, method='hybr')
print(r.x)
# array([1.97522498 3.47287981 5.1943792 2.10120135 4.09593969])
print(np.sqrt(np.sum((x-r.x)**2)))
# 5.0
一个选项是使用 scipy.optimize.minimize
而不是 root
,这里有多个求解器选项,其中一些(即 SLSQP
)允许您指定多个约束。请注意,我更改了变量名称,以便 x
是您要优化的数组,y
和 z
定义约束。
from scipy.optimize import minimize
import numpy as np
x0 = np.array([1, 1, 1, 1, 1])
y = np.array([6, 3, 1, 0, 2])
z = np.array([3, 4, 5, 6, 7])
constraint_x = dict(type='ineq',
fun=lambda x: x) # fulfilled if > 0
constraint_y = dict(type='eq',
fun=lambda x: np.linalg.norm(x-y) - 5) # fulfilled if == 0
constraint_z = dict(type='eq',
fun=lambda x: np.linalg.norm(x-z) - 8) # fulfilled if == 0
res = minimize(fun=lambda x: np.linalg.norm(x), constraints=[constraint_y, constraint_z], x0=x0,
method='SLSQP', options=dict(ftol=1e-8)) # default 1e-6
print(res.x) # [1.55517124 1.44981672 1.46921122 1.61335466 2.13174483]
print(np.linalg.norm(res.x-y)) # 5.00000000137866
print(np.linalg.norm(res.x-z)) # 8.000000000930026
这是一个最小化器,所以除了约束之外,它还需要一个函数来最小化,我只选择了 y
的范数,但是将函数设置为常量(即 lambda x: 1)也会工作了。
另请注意,约束并未 完全 满足,您可以通过将可选参数 ftol
设置为较小的值来提高准确性,即 1e-10
。
有关详细信息,另请参阅 documentation 和每个求解器的相应部分。
我有一个优化问题,我试图找到一个需要同时优化两个函数的数组。
在下面的最小示例中,我有两个已知数组 w
和 x
以及一个 unknown 数组 y
。我将数组 y
初始化为仅包含 1s.
然后我指定函数 np.sqrt(np.sum((x-np.array)**2)
并想找到数组 y
where
np.sqrt(np.sum((x-y)**2)
接近 5
np.sqrt(np.sum((w-y)**2)
接近 8
下面的代码可用于针对单个数组成功优化 y
,但我想找到针对两个 x
优化 y
的解决方案] 和 y
同时,但我不确定如何指定这两个约束。
y
应该只包含大于 0 的值。
关于如何解决这个问题的任何想法?
w = np.array([6, 3, 1, 0, 2])
x = np.array([3, 4, 5, 6, 7])
y = np.array([1, 1, 1, 1, 1])
def func(x, y):
z = np.sqrt(np.sum((x-y)**2)) - 5
return np.zeros(x.shape[0],) + z
r = opt.root(func, x0=y, method='hybr')
print(r.x)
# array([1.97522498 3.47287981 5.1943792 2.10120135 4.09593969])
print(np.sqrt(np.sum((x-r.x)**2)))
# 5.0
一个选项是使用 scipy.optimize.minimize
而不是 root
,这里有多个求解器选项,其中一些(即 SLSQP
)允许您指定多个约束。请注意,我更改了变量名称,以便 x
是您要优化的数组,y
和 z
定义约束。
from scipy.optimize import minimize
import numpy as np
x0 = np.array([1, 1, 1, 1, 1])
y = np.array([6, 3, 1, 0, 2])
z = np.array([3, 4, 5, 6, 7])
constraint_x = dict(type='ineq',
fun=lambda x: x) # fulfilled if > 0
constraint_y = dict(type='eq',
fun=lambda x: np.linalg.norm(x-y) - 5) # fulfilled if == 0
constraint_z = dict(type='eq',
fun=lambda x: np.linalg.norm(x-z) - 8) # fulfilled if == 0
res = minimize(fun=lambda x: np.linalg.norm(x), constraints=[constraint_y, constraint_z], x0=x0,
method='SLSQP', options=dict(ftol=1e-8)) # default 1e-6
print(res.x) # [1.55517124 1.44981672 1.46921122 1.61335466 2.13174483]
print(np.linalg.norm(res.x-y)) # 5.00000000137866
print(np.linalg.norm(res.x-z)) # 8.000000000930026
这是一个最小化器,所以除了约束之外,它还需要一个函数来最小化,我只选择了 y
的范数,但是将函数设置为常量(即 lambda x: 1)也会工作了。
另请注意,约束并未 完全 满足,您可以通过将可选参数 ftol
设置为较小的值来提高准确性,即 1e-10
。
有关详细信息,另请参阅 documentation 和每个求解器的相应部分。