A simple tutorial for cvxopt

针对官方cvxopt文档中的nonlinear optimization进行一些记录
https://cvxopt.org/userguide/solvers.html#problems-with-nonlinear-objectives

首先着眼于该示例’Example: equality constrained analytic centering’

1
2
3
4
5
6
7
8
9
10
11
12
13
from cvxopt import solvers, matrix, spdiag, log

def acent(A, b):
m, n = A.size
def F(x=None, z=None):
if x is None: return 0, matrix(1.0, (n,1))
if min(x) <= 0.0: return None
f = -sum(log(x))
Df = -(x**-1).T
if z is None: return f, Df
H = spdiag(z[0] * x**-2)
return f, Df, H
return solvers.cp(F, A=A, b=b)['x']

对上述代码中,这里详细描述其中关于x的判断的代码作用.

1
if x is None: return 0, matrix(1.0, (n,1))

这一段非常重要,因为当第一次cvxopt调用F函数的时候,会传入x=None(具体原因没有深究,我理解为初始化吧…),这个时候,就需要我们手动去对x进行初始化赋值,根据目标函数的形式,将其初始化一个符合约束的合理的值,例子中的x在分母位置,所以这里的代码是将其全部赋值为1.文档中别的示例也将其赋值为0, 只要是一个合理的值就可以,当然初值的赋值可能会影响到收敛的时间和最终解,这里需要一些技巧提前对目标函数进行分析,然后设置一个合理的初始值.

1
if min(x) <= 0.0: return None

这一段代码是同样是保证x在一个合理的定义域范围内,不能违反objective function的定义,但是具体为什么不放在G,h中,目前还没有深究.

spdiag是组装一个hessian矩阵用的,目的是将输入中的向量或矩阵按照规则放置在对角线上
log,div等方法都是针对matrix变量操作的,算子是对矩阵中的每一个元素分别进行操作的
G,h是不等式约束
A,b是等式约束
Dff的梯度,需要对objective function事先求解出其derivative funciton后放置在F方法内,确保最终是行向量的形式
H是Hessian矩阵,需要对objective function事先求解出Hessian矩阵,然后放置在F方法内,确保最终是matrix形式的变量

cvxopt将Nonlinear Convex Optimization中的不等式约束分为了三种:

  • nonnegative orthant,
  • second-order cones,
  • positive semidefinite cones.
    这三种约束分别需要写入G,h中去,如果原问题含有非线性的不等式约束,那么需要在Df[k,:]中写入该约束的梯度信息,其中k>0,k=0为原问题的梯度. z[0]表示原文题的梯度前面的系数,在调试中发现,cvxopt将其赋值为1,但是有时候也会赋值为None所以就需要判断其值,有如下代码进行判断
1
if z is None: return f, Df

z0的时候,H就不需要计算,略过H的更新,那么这里的逻辑可能是因为H变化不大了,亦或者是结束迭代的标志了,具体也需要去看源码深究.