• 内点法(interior point method)求解二次规划,附python代码


     内点法介绍这篇博文写的很好https://blog.csdn.net/dymodi/article/details/46441783,在这篇文章的基础上,本文给出障碍函数法代码和一个算例。

    障碍函数内点法的主要思想是:把不等式约束放进目标函数里。以下面的问题为例

     不等式约束放进目标函数,变成如下形式:

    f_{i}(x)>0 时,函数I_{-}(u)特别大,我们希望I_{-}(u)这个函数像下图红虚线的样子,

    但那样不可导,所以我们用如下形式的函数去近似。

    图中,u=-3时由下往上的的3根蓝线,对应的t值是依次增大。障碍函数内点法在迭代的时候,t初值给一个小值,t逐渐增大,使可行域越来越接近红虚线。

    在 t 的每一步迭代中,原问题转化为如下子问题:

     

    求解子问题,得到一个最优解x^{*},这个x^{*}是 t 下一步迭代的x初值。

    子问题的求解可以用拉格朗日乘子法

     

    拉格朗日乘子法中,F(x, \lambda)=0通过牛顿迭代法(Newton-Raphson method)求解。

    牛顿迭代法解非线性方程组

    x_{n+1}=x_{n} - \alpha * (H(f))^{-1}\bigtriangledown f

    H(f)是Hessian矩阵。

    得到子问题的最优解x^{*},然后继续迭代 t

     障碍函数内点法的算法步骤如下:(节选自Stephen Boyd的《Convex Optimization》)

     迭代终止条件中的m就是不等式约束的个数那个m,为什么以这个条件为终止的原因,参见文章开头提到的博客,Boyd的书里也有详细的证明,是通过原问题的对偶问题证明得到的。\mu是一个大于0的参数,使t每次迭代增大。

     算例:

    求解如下二次规划问题(解为 x1=0.5,x2=2.25):

     转化为如下子问题:

    t(x_{1}^{2}-x_{1}x_{2}+2x_{2}^{2}-x_{1}-10x^{2})-log(6-3x_{1}-2x_{2})-log(x_{1})-log(x_{2})

     完整python代码如下:

    1. import numpy as np
    2. import time
    3. def grad_f(t, x1, x2):
    4. return np.array([[t * (2 * x1 - x2 - 1) + 3 / (6 - 3 * x1 - 2 * x2) - 1 / x1],
    5. [t * (-1 * x1 + 4 * x2 - 10) + 2 / (6 - 3 * x1 - 2 * x2) - 1 / x2]])
    6. def Hessian_f(t, x1, x2):
    7. return np.array([[2*t - 9 / pow((6-3*x1-2*x2), 2) + 1 / pow(x1, 2), -t - 6 / pow((6-3*x1-2*x2), 2)],
    8. [-t - 6 / pow((6-3*x1-2*x2), 2), 4*t - 4 / pow((6-3*x1-2*x2), 2) + 1 / pow(x2, 2)]])
    9. def NewtonRaphson(t, x1, x2):
    10. gf = grad_f(t, x1, x2)
    11. Hf = Hessian_f(t, x1, x2)
    12. Hf_inv = np.linalg.inv(Hf)
    13. deltaX = 0.1 * np.matmul(Hf_inv, gf)
    14. res = np.linalg.norm(deltaX, 2)
    15. return x1 - deltaX[0, 0], x2 - deltaX[1, 0], res
    16. if __name__ == "__main__":
    17. time_start = time.time()
    18. t = 2
    19. x1 = 1
    20. x2 = 2
    21. while True:
    22. while True:
    23. x1, x2, res = NewtonRaphson(t, x1, x2)
    24. if res < 0.0001:
    25. break
    26. # print(x1, x2, res)
    27. # print("------")
    28. if 3.0 / t < 0.0001:
    29. time_end = time.time()
    30. print('consume time:', time_end - time_start)
    31. print("t:{}, x1:{}, x2:{}".format(t, x1, x2))
    32. break
    33. t = 2 * t

  • 相关阅读:
    只知道sort?C++序列操作函数最全总结
    Java序列化与反序列化
    面试官:你说你用过Dubbo,那你说说看Dubbo的SPI
    【图像识别】基于hog特征的机器学习交通标识识别附matlab代码
    使用D435i+Avia跑Fast-LIVO
    包管理工具--》发布一个自己的npm包
    Go错误处理方式真的不好吗?
    六大排序算法(Java版):从插入排序到快速排序(含图解)
    质数的判定和质因数分解
    GOM跟GEE登陆器列表文件加密教程
  • 原文地址:https://blog.csdn.net/qq_41816368/article/details/125888172