凸优化学习笔记:Inner-point methods 内点法
参考书目 convex optimization
minimize subject to f0(x)fi(x)≤0Ax=b
其中fi:Rn→R是凸的且二次可微,A∈Rp×n,rand A=p<n,假设问题可解,最优点为x∗,最优值p∗=f0(x∗)。
内点法通过将牛顿法应用在一系列等式约束上来解最优化问题
首先应将不等式约束化为等式约束
minimize subject to f0(x)+Σi=1mI−(fi(x))Ax=b
I−(u)={0,u≤0∞,u>0
当不等式不被满足时,目标函数会变的无穷大,因此当解该最优化问题时自然会满足不等式约束。此时虽然化为了等式约束,但是目标函数不可微。
牛顿法
牛顿步
二阶泰勒展开
f(x+Δx)≈f(x)+∇f(x)TΔx+21ΔxT∇2f(x)Δx
是关于Δx的凸二次函数(默认∇f(x)是正定的)。为了找到极小值点,应使该函数对Δx的导数为0,可得当Δx=−∇2f(x)−1∇f(x)T时该式取极小值,是下降的方向。
我们将其称为牛顿步
Δxnt=−∇2f(x)−1∇f(x)
此处详细解释一下,我们每次走一步牛顿步,都是将当前的二阶泰勒展开公式最小化,这是一个近似,但是每次都会使函数的数值变得越来越小。
参考书目 convex optimization
minimize subject to f0(x)fi(x)≤0Ax=b
其中fi:Rn→R是凸的且二次可微,A∈Rp×n,rand A=p<n,假设问题可解,最优点为x∗,最优值p∗=f0(x∗)。
内点法通过将牛顿法应用在一系列等式约束上来解最优化问题
首先应将不等式约束化为等式约束
minimize subject to f0(x)+Σi=1mI−(fi(x))Ax=b
I−(u)={0,u≤0∞,u>0
当不等式不被满足时,目标函数会变的无穷大,因此当解该最优化问题时自然会满足不等式约束。此时虽然化为了等式约束,但是目标函数不可微。
牛顿法
牛顿步
二阶泰勒展开
f(x+Δx)≈f(x)+∇f(x)TΔx+21ΔxT∇2f(x)Δx
是关于Δx的凸二次函数(默认∇f(x)是正定的)。为了找到极小值点,应使该函数对Δx的导数为0,可得当Δx=−∇2f(x)−1∇f(x)T时该式取极小值,是下降的方向。
我们将其称为牛顿步
Δxnt=−∇2f(x)−1∇f(x)
此处详细解释一下,我们每次走一步牛顿步,都是将当前的二阶泰勒展开公式最小化,这是一个近似,但是每次都会使函数的数值变得越来越小。

牛顿下降量
λ(x)=(∇f(x)T∇2f(x)−1∇f(x))1/2
被称为牛顿下降量。
假设f^为f在x处的二阶近似
f(x)−yinf f^(y)=f(x)−f^(x+Δxnt)=21∇f(x)T∇2f(x)−1∇f(x)=21λ(x)2
也就是说,每次牛顿迭代后,二阶估计和目标函数的差值是21λ(x)2
将牛顿步代入
λ=(∇xntT∇2f(x)Δxnt)1/2
换言之,λ是Δxnt的Hessian范数
下降法搜索还需要确定步长,来实现x=x+tΔx的迭代,有以下方式实现步长的确定。
Exact line search
精确线搜索(Exact Line Search),在这种方法中,选择 tt 来最小化沿着射线x+tΔx∣t≥0的函数 f 的值:
t=argminss≥0f(x+sΔx)
换言之,Δx决定了搜索的方向,而t则是寻找在这条射线上使函数值最小的自变量的数值。
精确线搜索通常用于牛顿法(Newton’s Method)中,特别是在计算搜索方向 Δx的成本较高时。在这种情况下,精确线搜索可以提供比直接计算搜索方向更低的成本。
backtracking line search
大多数的搜索都是不精确的。已经提出了许多不精确线搜索方法。其中一个非常简单且相当有效的方法被称为回溯线搜索(Backtracking Line Search)。它依赖于两个常数 α 和 β,其中 0<α<0.5 和 0<β<1。
其算法流程为
given a descent direction ∆x for f at x ∈ dom f, α ∈ (0,0.5), β ∈ (0,1).t := 1.
while f(x+t∆x)>f(x)+αt∇f(x)T∆x, t := βt.
也就是说,给定下降方向以及α,β后,设置t的初始值为1。
每次遍历时判断f(x+t∆x)>f(x)+αt∇f(x)T∆x是否成立,成立就更新 t := βt
牛顿法

给出起点x∈dom f,ϵ>0
每次迭代牛顿步和牛顿下降量
Δxnt=−∇2f(x)−1∇f(x);λ2=∇f(x)T∇2f(x)−1∇f(x)
判断λ2/2≤ϵ,决定是否停止
根据backtracking line search选择step size t
更新x=x+tΔxnt。
Logarithmic barriers
为了解决不可微的问题,可以将分段函数转化为对数函数
I^−(u)=−(1/t)log(−u),dom I^−=−R++,t>0
该函数为凸增函数,可微,调节t的值可以调整曲线形状。

此时目标函数可以化为
f0(x)+Σi=1m−(1/t)log(−fi(x))
其中ϕ(x)=−Σi=1mlog(−fi(x))即为Logarithmic barrier。
越大的t会使的函数模拟的质量更好,但是使用牛顿法求解f0+(1/t)ϕ的难度也会增大(Hessian阵在可行域边界处快速变化)。在目标函数处乘正数t,目标函数可化为
tf0(x)+ϕ(x)
logarithmic barrier函数的Hessian为:
∇ϕ(x)=Σi=1m−fi(x)1∇fi(x)∇2ϕ(x)=Σi=1mfi(x)21∇fi(x)∇fi(x)T+Σi=1m−fi(x)1∇2fi(x)
central points
对于不同的t取值,能找到不同的点x∗(t),即为中心点,其集合为中心线。
其满足条件
Ax∗(t)=b,fi(x∗(t))<0,i=1,...,m
且存在v^∈Rp
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
其中v^为拉格朗日乘子向量,这一项 ATv 的存在是为了满足等式约束 Ax=b 在优化过程中的KKT(Karush-Kuhn-Tucker)条件。
例1:
将log barrier应用到LP问题中
minimize subject to cTxAx⪯b
ϕ(x)=−Σi=1mlog(bi−aiTx),dom ϕ={x∣Ax≺b}
其中aiT为A的行。可得对应梯度和的Hessian为
∇ϕ(x)=Σi=1mbi−aiTx1ai=ATd,∇2ϕ(x)=Σi=1m(bi−aiTx)21aiaiT=ATdiag(d)2A
d=1/(bi−aiTx)
中心点条件为
tc+ATd=0

Dual points from central path
每个中心点都有一个dual feasible point(相关知识见dual部分内容),因此可一确定最优值p∗的下界。
定义
λi∗(t)=−tfi(x∗(t))1,ν∗(t)=ν^/t
λi∗(t)的值与目标函数 fi(x) 在当前迭代点 x∗(t)处的负倒数成正比。随着迭代进行,λi∗(t) 的值会逐渐减小,直到满足互补松弛性条件。ν∗ 是问题的界限,而 t 是迭代参数,通常初始值设为 1。随着迭代进行,t 的值会逐渐减小,以引导算法逐渐逼近问题的最优解。
这些参数的定义是内点法能够有效解决线性规划问题的关键。通过迭代更新这些参数,内点法能够确保算法在每一步都满足KKT条件,从而确保算法能够找到问题的最优解。
此时,将其带入到之前所述的
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
,可以得到KKT条件中的
∇f0(x∗(t))+Σi=1mλi∗(t)∇fi(x∗(t))+ATv∗(t)=0
对偶函数是有界的,有
g(λ∗(t),ν∗(t))=f0(x∗(t))+Σi=1mλi∗(t)fi(x∗(t))+νT(Ax−b)=f0(x∗(t))−m/t
可以得到duality gap是m/t,有
f0(x∗(t))−p∗≤m/t
例2:
求例1的对偶问题
L(x,λ,ν)=cTx+λT(Ax−b)
因此其下界为
g(λ,ν)={−bλ,ATλ+c=0−∞,ATλ+c=0
因此该对偶问题为
maximize subject to −bTλATλ+c=0
定义
λi∗(t)ν∗(t)=−tfi(x∗(t))1,=−t(aiTx−bi)1=ν^/t
dual目标值为
−bTλ∗=cTx∗(t)+1/tΣi=1m1+(Ax∗(t)−b)Tλ∗(t)=cTx∗(t)−m/t
这是因为目标x*应该满足(Ax∗(t)−b)=0,而前一项因为是倒数相乘变成了1,再求和就是m/t
所以应有
f0(x∗(t))−p∗≤m/t
再次说明的是,p∗是f(x∗)的下界,因此不等式左侧大于0,如果我们的算法迭代时能够不断缩小m/t直到小于允许误差ϵ时,就可以近似认为两数值相等。
barrier method 障碍法
设精度为ϵ,我们使t=m/ϵ,然后使用牛顿法求解问题
minimize subject to tf0(x)+ϕ(x)Ax=b
即为[Logarithmic barriers](## Logarithmic barriers)部分所转化出的问题。
这种方法可以称为无约束最小化方法,因为它允许我们通过解决无约束或线性约束的问题来以保证的准确性解决不等式约束问题。虽然这种方法适用于小问题、良好的起点和中等精度(即ε不太小),但在其他情况下效果不佳。因此,它很少被使用。
实际算法不会直接使t满足精度要求,而是从一个值开始逐步增大。
其算法流程为
given strictly feasible x, t := t(0) > 0, μ > 1, tolerance ε > 0.
repeat
- Centering step.
Compute x∗(t) by minimizing tf(0) + φ, subject to Ax = b, starting at x.
- Update. x := x⋆(t).
- Stopping criterion. quit if m/t < ε. 4. Increase t. t := μt.
即在每次迭代时,我们计算新的x∗,然后以因子μ>0放大t,直到满足精度要求。
在这种求解方式中,我们有两重迭代,外部的centering step迭代和内部的牛顿求解迭代。
μ的选择
当 μ 较小(即接近 1)时,每次外迭代 t 只增加一个小的因子,这意味着初始点(即前一个迭代点 x)对于牛顿过程来说是一个非常良好的起点,因此计算下一个迭代点所需的牛顿步数较少。因此,对于较小的 μ,我们期望每个外迭代只需要少量的牛顿步,但相应地需要大量的外迭代,因为每次外迭代只减少了少量的间隙。在这种情况下,迭代点(实际上,内迭代的迭代点也是)紧密跟随中心路径,这也解释了另一个名称“路径跟随法”。μ 值较大时,外层迭代次数少,内层迭代次数多,迭代点在中心路径上相隔较远;内迭代点会远离中心路径。大约从 3 到 100 左右,两种效果几乎相互抵消,因此牛顿步的总数保持大致恒定。这意味着 μ 的选择并不是特别关键。
t(0)的选择
最好能使m/t和f0(x(0))−p∗的量级差不多。

示例
minimize subject to cTxAx⪯b
A∈R100×50,可以用一个随机矩阵来进行实验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/SparseCholesky>
#include <iostream>
using namespace Eigen;
using namespace std;
int main() {
SparseMatrix<double> A(3, 3);
VectorXd b(3);
VectorXd c(3);
A.resize(3, 3);
A.coeffRef(0, 0) = 1;
A.coeffRef(0, 1) = 2;
A.coeffRef(0, 2) = 3;
A.coeffRef(1, 0) = 4;
A.coeffRef(1, 1) = 5;
A.coeffRef(1, 2) = 6;
A.coeffRef(2, 0) = 7;
A.coeffRef(2, 1) = 8;
A.coeffRef(2, 2) = 9;
b << 10, 25, 30;
c << 1, 3, 7;
SimplicialLDLT<SparseMatrix<double>> solver(A);
VectorXd x = solver.solve(c);
cout << "Optimal solution: " << x.transpose() << endl;
return 0;
}
|
牛顿下降量
λ(x)=(∇f(x)T∇2f(x)−1∇f(x))1/2
被称为牛顿下降量。
假设f^为f在x处的二阶近似
f(x)−yinf f^(y)=f(x)−f^(x+Δxnt)=21∇f(x)T∇2f(x)−1∇f(x)=21λ(x)2
也就是说,每次牛顿迭代后,二阶估计和目标函数的差值是21λ(x)2
将牛顿步代入
λ=(∇xntT∇2f(x)Δxnt)1/2
换言之,λ是Δxnt的Hessian范数
下降法搜索还需要确定步长,来实现x=x+tΔx的迭代,有以下方式实现步长的确定。
Exact line search
精确线搜索(Exact Line Search),在这种方法中,选择 tt 来最小化沿着射线x+tΔx∣t≥0的函数 f 的值:
t=argminss≥0f(x+sΔx)
换言之,Δx决定了搜索的方向,而t则是寻找在这条射线上使函数值最小的自变量的数值。
精确线搜索通常用于牛顿法(Newton’s Method)中,特别是在计算搜索方向 Δx的成本较高时。在这种情况下,精确线搜索可以提供比直接计算搜索方向更低的成本。
backtracking line search
大多数的搜索都是不精确的。已经提出了许多不精确线搜索方法。其中一个非常简单且相当有效的方法被称为回溯线搜索(Backtracking Line Search)。它依赖于两个常数 α 和 β,其中 0<α<0.5 和 0<β<1。
其算法流程为
given a descent direction ∆x for f at x ∈ dom f, α ∈ (0,0.5), β ∈ (0,1).t := 1.
while f(x+t∆x)>f(x)+αt∇f(x)T∆x, t := βt.
也就是说,给定下降方向以及α,β后,设置t的初始值为1。
每次遍历时判断f(x+t∆x)>f(x)+αt∇f(x)T∆x是否成立,成立就更新 t := βt
牛顿法
参考书目 convex optimization
minimize subject to f0(x)fi(x)≤0Ax=b
其中fi:Rn→R是凸的且二次可微,A∈Rp×n,rand A=p<n,假设问题可解,最优点为x∗,最优值p∗=f0(x∗)。
内点法通过将牛顿法应用在一系列等式约束上来解最优化问题
首先应将不等式约束化为等式约束
minimize subject to f0(x)+Σi=1mI−(fi(x))Ax=b
I−(u)={0,u≤0∞,u>0
当不等式不被满足时,目标函数会变的无穷大,因此当解该最优化问题时自然会满足不等式约束。此时虽然化为了等式约束,但是目标函数不可微。
牛顿法
牛顿步
二阶泰勒展开
f(x+Δx)≈f(x)+∇f(x)TΔx+21ΔxT∇2f(x)Δx
是关于Δx的凸二次函数(默认∇f(x)是正定的)。为了找到极小值点,应使该函数对Δx的导数为0,可得当Δx=−∇2f(x)−1∇f(x)T时该式取极小值,是下降的方向。
我们将其称为牛顿步
Δxnt=−∇2f(x)−1∇f(x)
此处详细解释一下,我们每次走一步牛顿步,都是将当前的二阶泰勒展开公式最小化,这是一个近似,但是每次都会使函数的数值变得越来越小。

牛顿下降量
λ(x)=(∇f(x)T∇2f(x)−1∇f(x))1/2
被称为牛顿下降量。
假设f^为f在x处的二阶近似
f(x)−yinf f^(y)=f(x)−f^(x+Δxnt)=21∇f(x)T∇2f(x)−1∇f(x)=21λ(x)2
也就是说,每次牛顿迭代后,二阶估计和目标函数的差值是21λ(x)2
将牛顿步代入
λ=(∇xntT∇2f(x)Δxnt)1/2
换言之,λ是Δxnt的Hessian范数
下降法搜索还需要确定步长,来实现x=x+tΔx的迭代,有以下方式实现步长的确定。
Exact line search
精确线搜索(Exact Line Search),在这种方法中,选择 tt 来最小化沿着射线x+tΔx∣t≥0的函数 f 的值:
t=argminss≥0f(x+sΔx)
换言之,Δx决定了搜索的方向,而t则是寻找在这条射线上使函数值最小的自变量的数值。
精确线搜索通常用于牛顿法(Newton’s Method)中,特别是在计算搜索方向 Δx的成本较高时。在这种情况下,精确线搜索可以提供比直接计算搜索方向更低的成本。
backtracking line search
大多数的搜索都是不精确的。已经提出了许多不精确线搜索方法。其中一个非常简单且相当有效的方法被称为回溯线搜索(Backtracking Line Search)。它依赖于两个常数 α 和 β,其中 0<α<0.5 和 0<β<1。
其算法流程为
given a descent direction ∆x for f at x ∈ dom f, α ∈ (0,0.5), β ∈ (0,1).t := 1.
while f(x+t∆x)>f(x)+αt∇f(x)T∆x, t := βt.
也就是说,给定下降方向以及α,β后,设置t的初始值为1。
每次遍历时判断f(x+t∆x)>f(x)+αt∇f(x)T∆x是否成立,成立就更新 t := βt
牛顿法

给出起点x∈dom f,ϵ>0
每次迭代牛顿步和牛顿下降量
Δxnt=−∇2f(x)−1∇f(x);λ2=∇f(x)T∇2f(x)−1∇f(x)
判断λ2/2≤ϵ,决定是否停止
根据backtracking line search选择step size t
更新x=x+tΔxnt。
Logarithmic barriers
为了解决不可微的问题,可以将分段函数转化为对数函数
I^−(u)=−(1/t)log(−u),dom I^−=−R++,t>0
该函数为凸增函数,可微,调节t的值可以调整曲线形状。

此时目标函数可以化为
f0(x)+Σi=1m−(1/t)log(−fi(x))
其中ϕ(x)=−Σi=1mlog(−fi(x))即为Logarithmic barrier。
越大的t会使的函数模拟的质量更好,但是使用牛顿法求解f0+(1/t)ϕ的难度也会增大(Hessian阵在可行域边界处快速变化)。在目标函数处乘正数t,目标函数可化为
tf0(x)+ϕ(x)
logarithmic barrier函数的Hessian为:
∇ϕ(x)=Σi=1m−fi(x)1∇fi(x)∇2ϕ(x)=Σi=1mfi(x)21∇fi(x)∇fi(x)T+Σi=1m−fi(x)1∇2fi(x)
central points
对于不同的t取值,能找到不同的点x∗(t),即为中心点,其集合为中心线。
其满足条件
Ax∗(t)=b,fi(x∗(t))<0,i=1,...,m
且存在v^∈Rp
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
其中v^为拉格朗日乘子向量,这一项 ATv 的存在是为了满足等式约束 Ax=b 在优化过程中的KKT(Karush-Kuhn-Tucker)条件。
例1:
将log barrier应用到LP问题中
minimize subject to cTxAx⪯b
ϕ(x)=−Σi=1mlog(bi−aiTx),dom ϕ={x∣Ax≺b}
其中aiT为A的行。可得对应梯度和的Hessian为
∇ϕ(x)=Σi=1mbi−aiTx1ai=ATd,∇2ϕ(x)=Σi=1m(bi−aiTx)21aiaiT=ATdiag(d)2A
d=1/(bi−aiTx)
中心点条件为
tc+ATd=0

Dual points from central path
每个中心点都有一个dual feasible point(相关知识见dual部分内容),因此可一确定最优值p∗的下界。
定义
λi∗(t)=−tfi(x∗(t))1,ν∗(t)=ν^/t
λi∗(t)的值与目标函数 fi(x) 在当前迭代点 x∗(t)处的负倒数成正比。随着迭代进行,λi∗(t) 的值会逐渐减小,直到满足互补松弛性条件。ν∗ 是问题的界限,而 t 是迭代参数,通常初始值设为 1。随着迭代进行,t 的值会逐渐减小,以引导算法逐渐逼近问题的最优解。
这些参数的定义是内点法能够有效解决线性规划问题的关键。通过迭代更新这些参数,内点法能够确保算法在每一步都满足KKT条件,从而确保算法能够找到问题的最优解。
此时,将其带入到之前所述的
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
,可以得到KKT条件中的
∇f0(x∗(t))+Σi=1mλi∗(t)∇fi(x∗(t))+ATv∗(t)=0
对偶函数是有界的,有
g(λ∗(t),ν∗(t))=f0(x∗(t))+Σi=1mλi∗(t)fi(x∗(t))+νT(Ax−b)=f0(x∗(t))−m/t
可以得到duality gap是m/t,有
f0(x∗(t))−p∗≤m/t
例2:
求例1的对偶问题
L(x,λ,ν)=cTx+λT(Ax−b)
因此其下界为
g(λ,ν)={−bλ,ATλ+c=0−∞,ATλ+c=0
因此该对偶问题为
maximize subject to −bTλATλ+c=0
定义
λi∗(t)ν∗(t)=−tfi(x∗(t))1,=−t(aiTx−bi)1=ν^/t
dual目标值为
−bTλ∗=cTx∗(t)+1/tΣi=1m1+(Ax∗(t)−b)Tλ∗(t)=cTx∗(t)−m/t
这是因为目标x*应该满足(Ax∗(t)−b)=0,而前一项因为是倒数相乘变成了1,再求和就是m/t
所以应有
f0(x∗(t))−p∗≤m/t
再次说明的是,p∗是f(x∗)的下界,因此不等式左侧大于0,如果我们的算法迭代时能够不断缩小m/t直到小于允许误差ϵ时,就可以近似认为两数值相等。
barrier method 障碍法
设精度为ϵ,我们使t=m/ϵ,然后使用牛顿法求解问题
minimize subject to tf0(x)+ϕ(x)Ax=b
即为[Logarithmic barriers](## Logarithmic barriers)部分所转化出的问题。
这种方法可以称为无约束最小化方法,因为它允许我们通过解决无约束或线性约束的问题来以保证的准确性解决不等式约束问题。虽然这种方法适用于小问题、良好的起点和中等精度(即ε不太小),但在其他情况下效果不佳。因此,它很少被使用。
实际算法不会直接使t满足精度要求,而是从一个值开始逐步增大。
其算法流程为
given strictly feasible x, t := t(0) > 0, μ > 1, tolerance ε > 0.
repeat
- Centering step.
Compute x∗(t) by minimizing tf(0) + φ, subject to Ax = b, starting at x.
- Update. x := x⋆(t).
- Stopping criterion. quit if m/t < ε. 4. Increase t. t := μt.
即在每次迭代时,我们计算新的x∗,然后以因子μ>0放大t,直到满足精度要求。
在这种求解方式中,我们有两重迭代,外部的centering step迭代和内部的牛顿求解迭代。
μ的选择
当 μ 较小(即接近 1)时,每次外迭代 t 只增加一个小的因子,这意味着初始点(即前一个迭代点 x)对于牛顿过程来说是一个非常良好的起点,因此计算下一个迭代点所需的牛顿步数较少。因此,对于较小的 μ,我们期望每个外迭代只需要少量的牛顿步,但相应地需要大量的外迭代,因为每次外迭代只减少了少量的间隙。在这种情况下,迭代点(实际上,内迭代的迭代点也是)紧密跟随中心路径,这也解释了另一个名称“路径跟随法”。μ 值较大时,外层迭代次数少,内层迭代次数多,迭代点在中心路径上相隔较远;内迭代点会远离中心路径。大约从 3 到 100 左右,两种效果几乎相互抵消,因此牛顿步的总数保持大致恒定。这意味着 μ 的选择并不是特别关键。
t(0)的选择
最好能使m/t和f0(x(0))−p∗的量级差不多。

示例
minimize subject to cTxAx⪯b
A∈R100×50,可以用一个随机矩阵来进行实验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/SparseCholesky>
#include <iostream>
using namespace Eigen;
using namespace std;
int main() {
SparseMatrix<double> A(3, 3);
VectorXd b(3);
VectorXd c(3);
A.resize(3, 3);
A.coeffRef(0, 0) = 1;
A.coeffRef(0, 1) = 2;
A.coeffRef(0, 2) = 3;
A.coeffRef(1, 0) = 4;
A.coeffRef(1, 1) = 5;
A.coeffRef(1, 2) = 6;
A.coeffRef(2, 0) = 7;
A.coeffRef(2, 1) = 8;
A.coeffRef(2, 2) = 9;
b << 10, 25, 30;
c << 1, 3, 7;
SimplicialLDLT<SparseMatrix<double>> solver(A);
VectorXd x = solver.solve(c);
cout << "Optimal solution: " << x.transpose() << endl;
return 0;
}
|
给出起点x∈dom f,ϵ>0
每次迭代牛顿步和牛顿下降量
Δxnt=−∇2f(x)−1∇f(x);λ2=∇f(x)T∇2f(x)−1∇f(x)
判断λ2/2≤ϵ,决定是否停止
根据backtracking line search选择step size t
更新x=x+tΔxnt。
Logarithmic barriers
为了解决不可微的问题,可以将分段函数转化为对数函数
I^−(u)=−(1/t)log(−u),dom I^−=−R++,t>0
该函数为凸增函数,可微,调节t的值可以调整曲线形状。
参考书目 convex optimization
minimize subject to f0(x)fi(x)≤0Ax=b
其中fi:Rn→R是凸的且二次可微,A∈Rp×n,rand A=p<n,假设问题可解,最优点为x∗,最优值p∗=f0(x∗)。
内点法通过将牛顿法应用在一系列等式约束上来解最优化问题
首先应将不等式约束化为等式约束
minimize subject to f0(x)+Σi=1mI−(fi(x))Ax=b
I−(u)={0,u≤0∞,u>0
当不等式不被满足时,目标函数会变的无穷大,因此当解该最优化问题时自然会满足不等式约束。此时虽然化为了等式约束,但是目标函数不可微。
牛顿法
牛顿步
二阶泰勒展开
f(x+Δx)≈f(x)+∇f(x)TΔx+21ΔxT∇2f(x)Δx
是关于Δx的凸二次函数(默认∇f(x)是正定的)。为了找到极小值点,应使该函数对Δx的导数为0,可得当Δx=−∇2f(x)−1∇f(x)T时该式取极小值,是下降的方向。
我们将其称为牛顿步
Δxnt=−∇2f(x)−1∇f(x)
此处详细解释一下,我们每次走一步牛顿步,都是将当前的二阶泰勒展开公式最小化,这是一个近似,但是每次都会使函数的数值变得越来越小。

牛顿下降量
λ(x)=(∇f(x)T∇2f(x)−1∇f(x))1/2
被称为牛顿下降量。
假设f^为f在x处的二阶近似
f(x)−yinf f^(y)=f(x)−f^(x+Δxnt)=21∇f(x)T∇2f(x)−1∇f(x)=21λ(x)2
也就是说,每次牛顿迭代后,二阶估计和目标函数的差值是21λ(x)2
将牛顿步代入
λ=(∇xntT∇2f(x)Δxnt)1/2
换言之,λ是Δxnt的Hessian范数
下降法搜索还需要确定步长,来实现x=x+tΔx的迭代,有以下方式实现步长的确定。
Exact line search
精确线搜索(Exact Line Search),在这种方法中,选择 tt 来最小化沿着射线x+tΔx∣t≥0的函数 f 的值:
t=argminss≥0f(x+sΔx)
换言之,Δx决定了搜索的方向,而t则是寻找在这条射线上使函数值最小的自变量的数值。
精确线搜索通常用于牛顿法(Newton’s Method)中,特别是在计算搜索方向 Δx的成本较高时。在这种情况下,精确线搜索可以提供比直接计算搜索方向更低的成本。
backtracking line search
大多数的搜索都是不精确的。已经提出了许多不精确线搜索方法。其中一个非常简单且相当有效的方法被称为回溯线搜索(Backtracking Line Search)。它依赖于两个常数 α 和 β,其中 0<α<0.5 和 0<β<1。
其算法流程为
given a descent direction ∆x for f at x ∈ dom f, α ∈ (0,0.5), β ∈ (0,1).t := 1.
while f(x+t∆x)>f(x)+αt∇f(x)T∆x, t := βt.
也就是说,给定下降方向以及α,β后,设置t的初始值为1。
每次遍历时判断f(x+t∆x)>f(x)+αt∇f(x)T∆x是否成立,成立就更新 t := βt
牛顿法

给出起点x∈dom f,ϵ>0
每次迭代牛顿步和牛顿下降量
Δxnt=−∇2f(x)−1∇f(x);λ2=∇f(x)T∇2f(x)−1∇f(x)
判断λ2/2≤ϵ,决定是否停止
根据backtracking line search选择step size t
更新x=x+tΔxnt。
Logarithmic barriers
为了解决不可微的问题,可以将分段函数转化为对数函数
I^−(u)=−(1/t)log(−u),dom I^−=−R++,t>0
该函数为凸增函数,可微,调节t的值可以调整曲线形状。

此时目标函数可以化为
f0(x)+Σi=1m−(1/t)log(−fi(x))
其中ϕ(x)=−Σi=1mlog(−fi(x))即为Logarithmic barrier。
越大的t会使的函数模拟的质量更好,但是使用牛顿法求解f0+(1/t)ϕ的难度也会增大(Hessian阵在可行域边界处快速变化)。在目标函数处乘正数t,目标函数可化为
tf0(x)+ϕ(x)
logarithmic barrier函数的Hessian为:
∇ϕ(x)=Σi=1m−fi(x)1∇fi(x)∇2ϕ(x)=Σi=1mfi(x)21∇fi(x)∇fi(x)T+Σi=1m−fi(x)1∇2fi(x)
central points
对于不同的t取值,能找到不同的点x∗(t),即为中心点,其集合为中心线。
其满足条件
Ax∗(t)=b,fi(x∗(t))<0,i=1,...,m
且存在v^∈Rp
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
其中v^为拉格朗日乘子向量,这一项 ATv 的存在是为了满足等式约束 Ax=b 在优化过程中的KKT(Karush-Kuhn-Tucker)条件。
例1:
将log barrier应用到LP问题中
minimize subject to cTxAx⪯b
ϕ(x)=−Σi=1mlog(bi−aiTx),dom ϕ={x∣Ax≺b}
其中aiT为A的行。可得对应梯度和的Hessian为
∇ϕ(x)=Σi=1mbi−aiTx1ai=ATd,∇2ϕ(x)=Σi=1m(bi−aiTx)21aiaiT=ATdiag(d)2A
d=1/(bi−aiTx)
中心点条件为
tc+ATd=0

Dual points from central path
每个中心点都有一个dual feasible point(相关知识见dual部分内容),因此可一确定最优值p∗的下界。
定义
λi∗(t)=−tfi(x∗(t))1,ν∗(t)=ν^/t
λi∗(t)的值与目标函数 fi(x) 在当前迭代点 x∗(t)处的负倒数成正比。随着迭代进行,λi∗(t) 的值会逐渐减小,直到满足互补松弛性条件。ν∗ 是问题的界限,而 t 是迭代参数,通常初始值设为 1。随着迭代进行,t 的值会逐渐减小,以引导算法逐渐逼近问题的最优解。
这些参数的定义是内点法能够有效解决线性规划问题的关键。通过迭代更新这些参数,内点法能够确保算法在每一步都满足KKT条件,从而确保算法能够找到问题的最优解。
此时,将其带入到之前所述的
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
,可以得到KKT条件中的
∇f0(x∗(t))+Σi=1mλi∗(t)∇fi(x∗(t))+ATv∗(t)=0
对偶函数是有界的,有
g(λ∗(t),ν∗(t))=f0(x∗(t))+Σi=1mλi∗(t)fi(x∗(t))+νT(Ax−b)=f0(x∗(t))−m/t
可以得到duality gap是m/t,有
f0(x∗(t))−p∗≤m/t
例2:
求例1的对偶问题
L(x,λ,ν)=cTx+λT(Ax−b)
因此其下界为
g(λ,ν)={−bλ,ATλ+c=0−∞,ATλ+c=0
因此该对偶问题为
maximize subject to −bTλATλ+c=0
定义
λi∗(t)ν∗(t)=−tfi(x∗(t))1,=−t(aiTx−bi)1=ν^/t
dual目标值为
−bTλ∗=cTx∗(t)+1/tΣi=1m1+(Ax∗(t)−b)Tλ∗(t)=cTx∗(t)−m/t
这是因为目标x*应该满足(Ax∗(t)−b)=0,而前一项因为是倒数相乘变成了1,再求和就是m/t
所以应有
f0(x∗(t))−p∗≤m/t
再次说明的是,p∗是f(x∗)的下界,因此不等式左侧大于0,如果我们的算法迭代时能够不断缩小m/t直到小于允许误差ϵ时,就可以近似认为两数值相等。
barrier method 障碍法
设精度为ϵ,我们使t=m/ϵ,然后使用牛顿法求解问题
minimize subject to tf0(x)+ϕ(x)Ax=b
即为[Logarithmic barriers](## Logarithmic barriers)部分所转化出的问题。
这种方法可以称为无约束最小化方法,因为它允许我们通过解决无约束或线性约束的问题来以保证的准确性解决不等式约束问题。虽然这种方法适用于小问题、良好的起点和中等精度(即ε不太小),但在其他情况下效果不佳。因此,它很少被使用。
实际算法不会直接使t满足精度要求,而是从一个值开始逐步增大。
其算法流程为
given strictly feasible x, t := t(0) > 0, μ > 1, tolerance ε > 0.
repeat
- Centering step.
Compute x∗(t) by minimizing tf(0) + φ, subject to Ax = b, starting at x.
- Update. x := x⋆(t).
- Stopping criterion. quit if m/t < ε. 4. Increase t. t := μt.
即在每次迭代时,我们计算新的x∗,然后以因子μ>0放大t,直到满足精度要求。
在这种求解方式中,我们有两重迭代,外部的centering step迭代和内部的牛顿求解迭代。
μ的选择
当 μ 较小(即接近 1)时,每次外迭代 t 只增加一个小的因子,这意味着初始点(即前一个迭代点 x)对于牛顿过程来说是一个非常良好的起点,因此计算下一个迭代点所需的牛顿步数较少。因此,对于较小的 μ,我们期望每个外迭代只需要少量的牛顿步,但相应地需要大量的外迭代,因为每次外迭代只减少了少量的间隙。在这种情况下,迭代点(实际上,内迭代的迭代点也是)紧密跟随中心路径,这也解释了另一个名称“路径跟随法”。μ 值较大时,外层迭代次数少,内层迭代次数多,迭代点在中心路径上相隔较远;内迭代点会远离中心路径。大约从 3 到 100 左右,两种效果几乎相互抵消,因此牛顿步的总数保持大致恒定。这意味着 μ 的选择并不是特别关键。
t(0)的选择
最好能使m/t和f0(x(0))−p∗的量级差不多。

示例
minimize subject to cTxAx⪯b
A∈R100×50,可以用一个随机矩阵来进行实验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/SparseCholesky>
#include <iostream>
using namespace Eigen;
using namespace std;
int main() {
SparseMatrix<double> A(3, 3);
VectorXd b(3);
VectorXd c(3);
A.resize(3, 3);
A.coeffRef(0, 0) = 1;
A.coeffRef(0, 1) = 2;
A.coeffRef(0, 2) = 3;
A.coeffRef(1, 0) = 4;
A.coeffRef(1, 1) = 5;
A.coeffRef(1, 2) = 6;
A.coeffRef(2, 0) = 7;
A.coeffRef(2, 1) = 8;
A.coeffRef(2, 2) = 9;
b << 10, 25, 30;
c << 1, 3, 7;
SimplicialLDLT<SparseMatrix<double>> solver(A);
VectorXd x = solver.solve(c);
cout << "Optimal solution: " << x.transpose() << endl;
return 0;
}
|
此时目标函数可以化为
f0(x)+Σi=1m−(1/t)log(−fi(x))
其中ϕ(x)=−Σi=1mlog(−fi(x))即为Logarithmic barrier。
越大的t会使的函数模拟的质量更好,但是使用牛顿法求解f0+(1/t)ϕ的难度也会增大(Hessian阵在可行域边界处快速变化)。在目标函数处乘正数t,目标函数可化为
tf0(x)+ϕ(x)
logarithmic barrier函数的Hessian为:
∇ϕ(x)=Σi=1m−fi(x)1∇fi(x)∇2ϕ(x)=Σi=1mfi(x)21∇fi(x)∇fi(x)T+Σi=1m−fi(x)1∇2fi(x)
central points
对于不同的t取值,能找到不同的点x∗(t),即为中心点,其集合为中心线。
其满足条件
Ax∗(t)=b,fi(x∗(t))<0,i=1,...,m
且存在v^∈Rp
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
其中v^为拉格朗日乘子向量,这一项 ATv 的存在是为了满足等式约束 Ax=b 在优化过程中的KKT(Karush-Kuhn-Tucker)条件。
例1:
将log barrier应用到LP问题中
minimize subject to cTxAx⪯b
ϕ(x)=−Σi=1mlog(bi−aiTx),dom ϕ={x∣Ax≺b}
其中aiT为A的行。可得对应梯度和的Hessian为
∇ϕ(x)=Σi=1mbi−aiTx1ai=ATd,∇2ϕ(x)=Σi=1m(bi−aiTx)21aiaiT=ATdiag(d)2A
d=1/(bi−aiTx)
中心点条件为
tc+ATd=0
参考书目 convex optimization
minimize subject to f0(x)fi(x)≤0Ax=b
其中fi:Rn→R是凸的且二次可微,A∈Rp×n,rand A=p<n,假设问题可解,最优点为x∗,最优值p∗=f0(x∗)。
内点法通过将牛顿法应用在一系列等式约束上来解最优化问题
首先应将不等式约束化为等式约束
minimize subject to f0(x)+Σi=1mI−(fi(x))Ax=b
I−(u)={0,u≤0∞,u>0
当不等式不被满足时,目标函数会变的无穷大,因此当解该最优化问题时自然会满足不等式约束。此时虽然化为了等式约束,但是目标函数不可微。
牛顿法
牛顿步
二阶泰勒展开
f(x+Δx)≈f(x)+∇f(x)TΔx+21ΔxT∇2f(x)Δx
是关于Δx的凸二次函数(默认∇f(x)是正定的)。为了找到极小值点,应使该函数对Δx的导数为0,可得当Δx=−∇2f(x)−1∇f(x)T时该式取极小值,是下降的方向。
我们将其称为牛顿步
Δxnt=−∇2f(x)−1∇f(x)
此处详细解释一下,我们每次走一步牛顿步,都是将当前的二阶泰勒展开公式最小化,这是一个近似,但是每次都会使函数的数值变得越来越小。

牛顿下降量
λ(x)=(∇f(x)T∇2f(x)−1∇f(x))1/2
被称为牛顿下降量。
假设f^为f在x处的二阶近似
f(x)−yinf f^(y)=f(x)−f^(x+Δxnt)=21∇f(x)T∇2f(x)−1∇f(x)=21λ(x)2
也就是说,每次牛顿迭代后,二阶估计和目标函数的差值是21λ(x)2
将牛顿步代入
λ=(∇xntT∇2f(x)Δxnt)1/2
换言之,λ是Δxnt的Hessian范数
下降法搜索还需要确定步长,来实现x=x+tΔx的迭代,有以下方式实现步长的确定。
Exact line search
精确线搜索(Exact Line Search),在这种方法中,选择 tt 来最小化沿着射线x+tΔx∣t≥0的函数 f 的值:
t=argminss≥0f(x+sΔx)
换言之,Δx决定了搜索的方向,而t则是寻找在这条射线上使函数值最小的自变量的数值。
精确线搜索通常用于牛顿法(Newton’s Method)中,特别是在计算搜索方向 Δx的成本较高时。在这种情况下,精确线搜索可以提供比直接计算搜索方向更低的成本。
backtracking line search
大多数的搜索都是不精确的。已经提出了许多不精确线搜索方法。其中一个非常简单且相当有效的方法被称为回溯线搜索(Backtracking Line Search)。它依赖于两个常数 α 和 β,其中 0<α<0.5 和 0<β<1。
其算法流程为
given a descent direction ∆x for f at x ∈ dom f, α ∈ (0,0.5), β ∈ (0,1).t := 1.
while f(x+t∆x)>f(x)+αt∇f(x)T∆x, t := βt.
也就是说,给定下降方向以及α,β后,设置t的初始值为1。
每次遍历时判断f(x+t∆x)>f(x)+αt∇f(x)T∆x是否成立,成立就更新 t := βt
牛顿法

给出起点x∈dom f,ϵ>0
每次迭代牛顿步和牛顿下降量
Δxnt=−∇2f(x)−1∇f(x);λ2=∇f(x)T∇2f(x)−1∇f(x)
判断λ2/2≤ϵ,决定是否停止
根据backtracking line search选择step size t
更新x=x+tΔxnt。
Logarithmic barriers
为了解决不可微的问题,可以将分段函数转化为对数函数
I^−(u)=−(1/t)log(−u),dom I^−=−R++,t>0
该函数为凸增函数,可微,调节t的值可以调整曲线形状。

此时目标函数可以化为
f0(x)+Σi=1m−(1/t)log(−fi(x))
其中ϕ(x)=−Σi=1mlog(−fi(x))即为Logarithmic barrier。
越大的t会使的函数模拟的质量更好,但是使用牛顿法求解f0+(1/t)ϕ的难度也会增大(Hessian阵在可行域边界处快速变化)。在目标函数处乘正数t,目标函数可化为
tf0(x)+ϕ(x)
logarithmic barrier函数的Hessian为:
∇ϕ(x)=Σi=1m−fi(x)1∇fi(x)∇2ϕ(x)=Σi=1mfi(x)21∇fi(x)∇fi(x)T+Σi=1m−fi(x)1∇2fi(x)
central points
对于不同的t取值,能找到不同的点x∗(t),即为中心点,其集合为中心线。
其满足条件
Ax∗(t)=b,fi(x∗(t))<0,i=1,...,m
且存在v^∈Rp
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
其中v^为拉格朗日乘子向量,这一项 ATv 的存在是为了满足等式约束 Ax=b 在优化过程中的KKT(Karush-Kuhn-Tucker)条件。
例1:
将log barrier应用到LP问题中
minimize subject to cTxAx⪯b
ϕ(x)=−Σi=1mlog(bi−aiTx),dom ϕ={x∣Ax≺b}
其中aiT为A的行。可得对应梯度和的Hessian为
∇ϕ(x)=Σi=1mbi−aiTx1ai=ATd,∇2ϕ(x)=Σi=1m(bi−aiTx)21aiaiT=ATdiag(d)2A
d=1/(bi−aiTx)
中心点条件为
tc+ATd=0

Dual points from central path
每个中心点都有一个dual feasible point(相关知识见dual部分内容),因此可一确定最优值p∗的下界。
定义
λi∗(t)=−tfi(x∗(t))1,ν∗(t)=ν^/t
λi∗(t)的值与目标函数 fi(x) 在当前迭代点 x∗(t)处的负倒数成正比。随着迭代进行,λi∗(t) 的值会逐渐减小,直到满足互补松弛性条件。ν∗ 是问题的界限,而 t 是迭代参数,通常初始值设为 1。随着迭代进行,t 的值会逐渐减小,以引导算法逐渐逼近问题的最优解。
这些参数的定义是内点法能够有效解决线性规划问题的关键。通过迭代更新这些参数,内点法能够确保算法在每一步都满足KKT条件,从而确保算法能够找到问题的最优解。
此时,将其带入到之前所述的
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
,可以得到KKT条件中的
∇f0(x∗(t))+Σi=1mλi∗(t)∇fi(x∗(t))+ATv∗(t)=0
对偶函数是有界的,有
g(λ∗(t),ν∗(t))=f0(x∗(t))+Σi=1mλi∗(t)fi(x∗(t))+νT(Ax−b)=f0(x∗(t))−m/t
可以得到duality gap是m/t,有
f0(x∗(t))−p∗≤m/t
例2:
求例1的对偶问题
L(x,λ,ν)=cTx+λT(Ax−b)
因此其下界为
g(λ,ν)={−bλ,ATλ+c=0−∞,ATλ+c=0
因此该对偶问题为
maximize subject to −bTλATλ+c=0
定义
λi∗(t)ν∗(t)=−tfi(x∗(t))1,=−t(aiTx−bi)1=ν^/t
dual目标值为
−bTλ∗=cTx∗(t)+1/tΣi=1m1+(Ax∗(t)−b)Tλ∗(t)=cTx∗(t)−m/t
这是因为目标x*应该满足(Ax∗(t)−b)=0,而前一项因为是倒数相乘变成了1,再求和就是m/t
所以应有
f0(x∗(t))−p∗≤m/t
再次说明的是,p∗是f(x∗)的下界,因此不等式左侧大于0,如果我们的算法迭代时能够不断缩小m/t直到小于允许误差ϵ时,就可以近似认为两数值相等。
barrier method 障碍法
设精度为ϵ,我们使t=m/ϵ,然后使用牛顿法求解问题
minimize subject to tf0(x)+ϕ(x)Ax=b
即为[Logarithmic barriers](## Logarithmic barriers)部分所转化出的问题。
这种方法可以称为无约束最小化方法,因为它允许我们通过解决无约束或线性约束的问题来以保证的准确性解决不等式约束问题。虽然这种方法适用于小问题、良好的起点和中等精度(即ε不太小),但在其他情况下效果不佳。因此,它很少被使用。
实际算法不会直接使t满足精度要求,而是从一个值开始逐步增大。
其算法流程为
given strictly feasible x, t := t(0) > 0, μ > 1, tolerance ε > 0.
repeat
- Centering step.
Compute x∗(t) by minimizing tf(0) + φ, subject to Ax = b, starting at x.
- Update. x := x⋆(t).
- Stopping criterion. quit if m/t < ε. 4. Increase t. t := μt.
即在每次迭代时,我们计算新的x∗,然后以因子μ>0放大t,直到满足精度要求。
在这种求解方式中,我们有两重迭代,外部的centering step迭代和内部的牛顿求解迭代。
μ的选择
当 μ 较小(即接近 1)时,每次外迭代 t 只增加一个小的因子,这意味着初始点(即前一个迭代点 x)对于牛顿过程来说是一个非常良好的起点,因此计算下一个迭代点所需的牛顿步数较少。因此,对于较小的 μ,我们期望每个外迭代只需要少量的牛顿步,但相应地需要大量的外迭代,因为每次外迭代只减少了少量的间隙。在这种情况下,迭代点(实际上,内迭代的迭代点也是)紧密跟随中心路径,这也解释了另一个名称“路径跟随法”。μ 值较大时,外层迭代次数少,内层迭代次数多,迭代点在中心路径上相隔较远;内迭代点会远离中心路径。大约从 3 到 100 左右,两种效果几乎相互抵消,因此牛顿步的总数保持大致恒定。这意味着 μ 的选择并不是特别关键。
t(0)的选择
最好能使m/t和f0(x(0))−p∗的量级差不多。

示例
minimize subject to cTxAx⪯b
A∈R100×50,可以用一个随机矩阵来进行实验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/SparseCholesky>
#include <iostream>
using namespace Eigen;
using namespace std;
int main() {
SparseMatrix<double> A(3, 3);
VectorXd b(3);
VectorXd c(3);
A.resize(3, 3);
A.coeffRef(0, 0) = 1;
A.coeffRef(0, 1) = 2;
A.coeffRef(0, 2) = 3;
A.coeffRef(1, 0) = 4;
A.coeffRef(1, 1) = 5;
A.coeffRef(1, 2) = 6;
A.coeffRef(2, 0) = 7;
A.coeffRef(2, 1) = 8;
A.coeffRef(2, 2) = 9;
b << 10, 25, 30;
c << 1, 3, 7;
SimplicialLDLT<SparseMatrix<double>> solver(A);
VectorXd x = solver.solve(c);
cout << "Optimal solution: " << x.transpose() << endl;
return 0;
}
|
Dual points from central path
每个中心点都有一个dual feasible point(相关知识见dual部分内容),因此可一确定最优值p∗的下界。
定义
λi∗(t)=−tfi(x∗(t))1,ν∗(t)=ν^/t
λi∗(t)的值与目标函数 fi(x) 在当前迭代点 x∗(t)处的负倒数成正比。随着迭代进行,λi∗(t) 的值会逐渐减小,直到满足互补松弛性条件。ν∗ 是问题的界限,而 t 是迭代参数,通常初始值设为 1。随着迭代进行,t 的值会逐渐减小,以引导算法逐渐逼近问题的最优解。
这些参数的定义是内点法能够有效解决线性规划问题的关键。通过迭代更新这些参数,内点法能够确保算法在每一步都满足KKT条件,从而确保算法能够找到问题的最优解。
此时,将其带入到之前所述的
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
,可以得到KKT条件中的
∇f0(x∗(t))+Σi=1mλi∗(t)∇fi(x∗(t))+ATv∗(t)=0
对偶函数是有界的,有
g(λ∗(t),ν∗(t))=f0(x∗(t))+Σi=1mλi∗(t)fi(x∗(t))+νT(Ax−b)=f0(x∗(t))−m/t
可以得到duality gap是m/t,有
f0(x∗(t))−p∗≤m/t
例2:
求例1的对偶问题
L(x,λ,ν)=cTx+λT(Ax−b)
因此其下界为
g(λ,ν)={−bλ,ATλ+c=0−∞,ATλ+c=0
因此该对偶问题为
maximize subject to −bTλATλ+c=0
定义
λi∗(t)ν∗(t)=−tfi(x∗(t))1,=−t(aiTx−bi)1=ν^/t
dual目标值为
−bTλ∗=cTx∗(t)+1/tΣi=1m1+(Ax∗(t)−b)Tλ∗(t)=cTx∗(t)−m/t
这是因为目标x*应该满足(Ax∗(t)−b)=0,而前一项因为是倒数相乘变成了1,再求和就是m/t
所以应有
f0(x∗(t))−p∗≤m/t
再次说明的是,p∗是f(x∗)的下界,因此不等式左侧大于0,如果我们的算法迭代时能够不断缩小m/t直到小于允许误差ϵ时,就可以近似认为两数值相等。
barrier method 障碍法
设精度为ϵ,我们使t=m/ϵ,然后使用牛顿法求解问题
minimize subject to tf0(x)+ϕ(x)Ax=b
即为[Logarithmic barriers](## Logarithmic barriers)部分所转化出的问题。
这种方法可以称为无约束最小化方法,因为它允许我们通过解决无约束或线性约束的问题来以保证的准确性解决不等式约束问题。虽然这种方法适用于小问题、良好的起点和中等精度(即ε不太小),但在其他情况下效果不佳。因此,它很少被使用。
实际算法不会直接使t满足精度要求,而是从一个值开始逐步增大。
其算法流程为
given strictly feasible x, t := t(0) > 0, μ > 1, tolerance ε > 0.
repeat
- Centering step.
Compute x∗(t) by minimizing tf(0) + φ, subject to Ax = b, starting at x.
- Update. x := x⋆(t).
- Stopping criterion. quit if m/t < ε. 4. Increase t. t := μt.
即在每次迭代时,我们计算新的x∗,然后以因子μ>0放大t,直到满足精度要求。
在这种求解方式中,我们有两重迭代,外部的centering step迭代和内部的牛顿求解迭代。
μ的选择
当 μ 较小(即接近 1)时,每次外迭代 t 只增加一个小的因子,这意味着初始点(即前一个迭代点 x)对于牛顿过程来说是一个非常良好的起点,因此计算下一个迭代点所需的牛顿步数较少。因此,对于较小的 μ,我们期望每个外迭代只需要少量的牛顿步,但相应地需要大量的外迭代,因为每次外迭代只减少了少量的间隙。在这种情况下,迭代点(实际上,内迭代的迭代点也是)紧密跟随中心路径,这也解释了另一个名称“路径跟随法”。μ 值较大时,外层迭代次数少,内层迭代次数多,迭代点在中心路径上相隔较远;内迭代点会远离中心路径。大约从 3 到 100 左右,两种效果几乎相互抵消,因此牛顿步的总数保持大致恒定。这意味着 μ 的选择并不是特别关键。
t(0)的选择
最好能使m/t和f0(x(0))−p∗的量级差不多。
参考书目 convex optimization
minimize subject to f0(x)fi(x)≤0Ax=b
其中fi:Rn→R是凸的且二次可微,A∈Rp×n,rand A=p<n,假设问题可解,最优点为x∗,最优值p∗=f0(x∗)。
内点法通过将牛顿法应用在一系列等式约束上来解最优化问题
首先应将不等式约束化为等式约束
minimize subject to f0(x)+Σi=1mI−(fi(x))Ax=b
I−(u)={0,u≤0∞,u>0
当不等式不被满足时,目标函数会变的无穷大,因此当解该最优化问题时自然会满足不等式约束。此时虽然化为了等式约束,但是目标函数不可微。
牛顿法
牛顿步
二阶泰勒展开
f(x+Δx)≈f(x)+∇f(x)TΔx+21ΔxT∇2f(x)Δx
是关于Δx的凸二次函数(默认∇f(x)是正定的)。为了找到极小值点,应使该函数对Δx的导数为0,可得当Δx=−∇2f(x)−1∇f(x)T时该式取极小值,是下降的方向。
我们将其称为牛顿步
Δxnt=−∇2f(x)−1∇f(x)
此处详细解释一下,我们每次走一步牛顿步,都是将当前的二阶泰勒展开公式最小化,这是一个近似,但是每次都会使函数的数值变得越来越小。

牛顿下降量
λ(x)=(∇f(x)T∇2f(x)−1∇f(x))1/2
被称为牛顿下降量。
假设f^为f在x处的二阶近似
f(x)−yinf f^(y)=f(x)−f^(x+Δxnt)=21∇f(x)T∇2f(x)−1∇f(x)=21λ(x)2
也就是说,每次牛顿迭代后,二阶估计和目标函数的差值是21λ(x)2
将牛顿步代入
λ=(∇xntT∇2f(x)Δxnt)1/2
换言之,λ是Δxnt的Hessian范数
下降法搜索还需要确定步长,来实现x=x+tΔx的迭代,有以下方式实现步长的确定。
Exact line search
精确线搜索(Exact Line Search),在这种方法中,选择 tt 来最小化沿着射线x+tΔx∣t≥0的函数 f 的值:
t=argminss≥0f(x+sΔx)
换言之,Δx决定了搜索的方向,而t则是寻找在这条射线上使函数值最小的自变量的数值。
精确线搜索通常用于牛顿法(Newton’s Method)中,特别是在计算搜索方向 Δx的成本较高时。在这种情况下,精确线搜索可以提供比直接计算搜索方向更低的成本。
backtracking line search
大多数的搜索都是不精确的。已经提出了许多不精确线搜索方法。其中一个非常简单且相当有效的方法被称为回溯线搜索(Backtracking Line Search)。它依赖于两个常数 α 和 β,其中 0<α<0.5 和 0<β<1。
其算法流程为
given a descent direction ∆x for f at x ∈ dom f, α ∈ (0,0.5), β ∈ (0,1).t := 1.
while f(x+t∆x)>f(x)+αt∇f(x)T∆x, t := βt.
也就是说,给定下降方向以及α,β后,设置t的初始值为1。
每次遍历时判断f(x+t∆x)>f(x)+αt∇f(x)T∆x是否成立,成立就更新 t := βt
牛顿法

给出起点x∈dom f,ϵ>0
每次迭代牛顿步和牛顿下降量
Δxnt=−∇2f(x)−1∇f(x);λ2=∇f(x)T∇2f(x)−1∇f(x)
判断λ2/2≤ϵ,决定是否停止
根据backtracking line search选择step size t
更新x=x+tΔxnt。
Logarithmic barriers
为了解决不可微的问题,可以将分段函数转化为对数函数
I^−(u)=−(1/t)log(−u),dom I^−=−R++,t>0
该函数为凸增函数,可微,调节t的值可以调整曲线形状。

此时目标函数可以化为
f0(x)+Σi=1m−(1/t)log(−fi(x))
其中ϕ(x)=−Σi=1mlog(−fi(x))即为Logarithmic barrier。
越大的t会使的函数模拟的质量更好,但是使用牛顿法求解f0+(1/t)ϕ的难度也会增大(Hessian阵在可行域边界处快速变化)。在目标函数处乘正数t,目标函数可化为
tf0(x)+ϕ(x)
logarithmic barrier函数的Hessian为:
∇ϕ(x)=Σi=1m−fi(x)1∇fi(x)∇2ϕ(x)=Σi=1mfi(x)21∇fi(x)∇fi(x)T+Σi=1m−fi(x)1∇2fi(x)
central points
对于不同的t取值,能找到不同的点x∗(t),即为中心点,其集合为中心线。
其满足条件
Ax∗(t)=b,fi(x∗(t))<0,i=1,...,m
且存在v^∈Rp
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
其中v^为拉格朗日乘子向量,这一项 ATv 的存在是为了满足等式约束 Ax=b 在优化过程中的KKT(Karush-Kuhn-Tucker)条件。
例1:
将log barrier应用到LP问题中
minimize subject to cTxAx⪯b
ϕ(x)=−Σi=1mlog(bi−aiTx),dom ϕ={x∣Ax≺b}
其中aiT为A的行。可得对应梯度和的Hessian为
∇ϕ(x)=Σi=1mbi−aiTx1ai=ATd,∇2ϕ(x)=Σi=1m(bi−aiTx)21aiaiT=ATdiag(d)2A
d=1/(bi−aiTx)
中心点条件为
tc+ATd=0

Dual points from central path
每个中心点都有一个dual feasible point(相关知识见dual部分内容),因此可一确定最优值p∗的下界。
定义
λi∗(t)=−tfi(x∗(t))1,ν∗(t)=ν^/t
λi∗(t)的值与目标函数 fi(x) 在当前迭代点 x∗(t)处的负倒数成正比。随着迭代进行,λi∗(t) 的值会逐渐减小,直到满足互补松弛性条件。ν∗ 是问题的界限,而 t 是迭代参数,通常初始值设为 1。随着迭代进行,t 的值会逐渐减小,以引导算法逐渐逼近问题的最优解。
这些参数的定义是内点法能够有效解决线性规划问题的关键。通过迭代更新这些参数,内点法能够确保算法在每一步都满足KKT条件,从而确保算法能够找到问题的最优解。
此时,将其带入到之前所述的
0=t∇f0(x∗(t))+∇ϕ(x∗(t))+ATv^
,可以得到KKT条件中的
∇f0(x∗(t))+Σi=1mλi∗(t)∇fi(x∗(t))+ATv∗(t)=0
对偶函数是有界的,有
g(λ∗(t),ν∗(t))=f0(x∗(t))+Σi=1mλi∗(t)fi(x∗(t))+νT(Ax−b)=f0(x∗(t))−m/t
可以得到duality gap是m/t,有
f0(x∗(t))−p∗≤m/t
例2:
求例1的对偶问题
L(x,λ,ν)=cTx+λT(Ax−b)
因此其下界为
g(λ,ν)={−bλ,ATλ+c=0−∞,ATλ+c=0
因此该对偶问题为
maximize subject to −bTλATλ+c=0
定义
λi∗(t)ν∗(t)=−tfi(x∗(t))1,=−t(aiTx−bi)1=ν^/t
dual目标值为
−bTλ∗=cTx∗(t)+1/tΣi=1m1+(Ax∗(t)−b)Tλ∗(t)=cTx∗(t)−m/t
这是因为目标x*应该满足(Ax∗(t)−b)=0,而前一项因为是倒数相乘变成了1,再求和就是m/t
所以应有
f0(x∗(t))−p∗≤m/t
再次说明的是,p∗是f(x∗)的下界,因此不等式左侧大于0,如果我们的算法迭代时能够不断缩小m/t直到小于允许误差ϵ时,就可以近似认为两数值相等。
barrier method 障碍法
设精度为ϵ,我们使t=m/ϵ,然后使用牛顿法求解问题
minimize subject to tf0(x)+ϕ(x)Ax=b
即为[Logarithmic barriers](## Logarithmic barriers)部分所转化出的问题。
这种方法可以称为无约束最小化方法,因为它允许我们通过解决无约束或线性约束的问题来以保证的准确性解决不等式约束问题。虽然这种方法适用于小问题、良好的起点和中等精度(即ε不太小),但在其他情况下效果不佳。因此,它很少被使用。
实际算法不会直接使t满足精度要求,而是从一个值开始逐步增大。
其算法流程为
given strictly feasible x, t := t(0) > 0, μ > 1, tolerance ε > 0.
repeat
- Centering step.
Compute x∗(t) by minimizing tf(0) + φ, subject to Ax = b, starting at x.
- Update. x := x⋆(t).
- Stopping criterion. quit if m/t < ε. 4. Increase t. t := μt.
即在每次迭代时,我们计算新的x∗,然后以因子μ>0放大t,直到满足精度要求。
在这种求解方式中,我们有两重迭代,外部的centering step迭代和内部的牛顿求解迭代。
μ的选择
当 μ 较小(即接近 1)时,每次外迭代 t 只增加一个小的因子,这意味着初始点(即前一个迭代点 x)对于牛顿过程来说是一个非常良好的起点,因此计算下一个迭代点所需的牛顿步数较少。因此,对于较小的 μ,我们期望每个外迭代只需要少量的牛顿步,但相应地需要大量的外迭代,因为每次外迭代只减少了少量的间隙。在这种情况下,迭代点(实际上,内迭代的迭代点也是)紧密跟随中心路径,这也解释了另一个名称“路径跟随法”。μ 值较大时,外层迭代次数少,内层迭代次数多,迭代点在中心路径上相隔较远;内迭代点会远离中心路径。大约从 3 到 100 左右,两种效果几乎相互抵消,因此牛顿步的总数保持大致恒定。这意味着 μ 的选择并不是特别关键。
t(0)的选择
最好能使m/t和f0(x(0))−p∗的量级差不多。

示例
minimize subject to cTxAx⪯b
A∈R100×50,可以用一个随机矩阵来进行实验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/SparseCholesky>
#include <iostream>
using namespace Eigen;
using namespace std;
int main() {
SparseMatrix<double> A(3, 3);
VectorXd b(3);
VectorXd c(3);
A.resize(3, 3);
A.coeffRef(0, 0) = 1;
A.coeffRef(0, 1) = 2;
A.coeffRef(0, 2) = 3;
A.coeffRef(1, 0) = 4;
A.coeffRef(1, 1) = 5;
A.coeffRef(1, 2) = 6;
A.coeffRef(2, 0) = 7;
A.coeffRef(2, 1) = 8;
A.coeffRef(2, 2) = 9;
b << 10, 25, 30;
c << 1, 3, 7;
SimplicialLDLT<SparseMatrix<double>> solver(A);
VectorXd x = solver.solve(c);
cout << "Optimal solution: " << x.transpose() << endl;
return 0;
}
|
示例
minimize subject to cTxAx⪯b
A∈R100×50,可以用一个随机矩阵来进行实验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/SparseCholesky>
#include <iostream>
using namespace Eigen;
using namespace std;
int main() {
SparseMatrix<double> A(3, 3);
VectorXd b(3);
VectorXd c(3);
A.resize(3, 3);
A.coeffRef(0, 0) = 1;
A.coeffRef(0, 1) = 2;
A.coeffRef(0, 2) = 3;
A.coeffRef(1, 0) = 4;
A.coeffRef(1, 1) = 5;
A.coeffRef(1, 2) = 6;
A.coeffRef(2, 0) = 7;
A.coeffRef(2, 1) = 8;
A.coeffRef(2, 2) = 9;
b << 10, 25, 30;
c << 1, 3, 7;
SimplicialLDLT<SparseMatrix<double>> solver(A);
VectorXd x = solver.solve(c);
cout << "Optimal solution: " << x.transpose() << endl;
return 0;
}
|