scipy.optimize.minimize如何传入多个向量(矩阵)

记一次困扰了一周的问题

向量

一般情况下,对于一个多维函数的优化,往往是把$x_0, x_1, … ,x_n$放进一个$1 \times n$的数组中,然后把这个数组作为minimize的参数x0。但现在碰到了一个这样的问题,优化函数为:$$min||x-z||_2$$

约束为$Ax-b\leq0$并且$z\geq0$,其中A是一个$m \times n$的矩阵,b是$m \times 1$的矩阵。也就是说,x和z均为一个n维的向量。

起初我的思路是将x和z强行放在一个数组x0里,x作为x0[0],z作为x0[1]。但这样在添加约束的时候会发生错误,大概是因为在约束函数里x0[0]被当作了一个1x1的元素,无法点乘也无法与b进行相减。

这个思路没有错,但是把x和z压成一个向量的话,需要用到numpy里的hstack函数,这样等于是把x和z拼接成一个1x2n的向量而非一个2xn的矩阵。这样的话在优化函数中需要重新将这个1x2n的向量拆成两个1xn的向量:

1
2
3
4
5
6
7
8
9
10
11
12
x = np.zeros(A.shape[1])
z = np.zeros(A.shape[1])
x0 = np.hstack([x, z])

def to_x_z(x0):
x = x0[:A.shape[1]]
z = x0[A.shape[1]:]
return x, z

def f(x0):
x, z = to_x_z(x0)
return np.linalg.norm([x-z], ord=2)

在约束中也是一样,需要对x0进行拆分。再返回结果的时候也是同样。

1
2
3
4
cons = [{'type': 'ineq', 'fun': lambda x: b-np.dot(A, to_x_z(x)[0])}, {'type': 'ineq', 'fun': lambda x: to_x_z(x)[1] - 1e-10}]
res = scipy.optimize.minimize(f, x0, method='SLSQP', constraints=cons)
res.x = to_x_z(res.x)
return res.x

矩阵

若传入的是矩阵而非向量,思路也是一样,但是需要利用numpy里的flatten来先对每个矩阵进行压缩:

1
np.hstack([w.flatten(), z.flatten()])

在拆分的时候,需要reshape一下让其恢复成矩阵:

1
2
3
4
def to_x_z(x0):
x = x0[:A.shape[1]].reshape(m, n)
z = x0[A.shape[1]:].reshape(m, n)
return x, z

参考

How Do I put 2 matrix into scipy.optimize.minimize?

scipy.optimize.minimize如何传入多个向量(矩阵)

http://xnsi.github.io/2020/11/19/scipy-minimize-with-vectors/

Author

s.x.

Posted on

2020-11-19

Updated on

2021-05-01

Licensed under

Comments