C ++中是否有二次编程库?

时间:2011-11-06 07:10:10

标签: c++ math quadratic

我找到的唯一Google搜索结果是QuadProg ++,但它无法解决二次编程问题,其矩阵不适用于Cholesky分解。

那么有人可以给我一些关于其他图书馆的建议吗?感谢。

5 个答案:

答案 0 :(得分:6)

有几个库包含QP求解器。有开源和商业选择。现有答案列出了其中的一些。我想澄清矩阵的问题。

我假设你指的是目标矩阵。约束矩阵仅需要导致非空可行集。你提到矩阵不适合Cholesky分解。由于Cholesky分解可以形成任何正定矩阵,这意味着你的矩阵不是正定的。

如果矩阵是半正定的(即它具有一个或多个零特征值),则问题是凸QP并且可以有效地求解。然而,许多解算者需要一个肯定的目标。由于正半正定QP的目标具有非平凡的零空间,因此可能存在许多解。事实上,这套解决方案甚至可以无限制。数值算法无论如何都只会给出近似解,因此矩阵的特征值恰好为零并不是很重要。您可以通过在对角线上添加一个小正值的对角矩阵来使矩阵为正。这将基本上选择具有最小2范数的解决方案。实际上,即使矩阵是正定的,这也是一个好主意,因为具有接近于零的特征值的矩阵通常会导致数值求解器出现问题。添加多少对角线是稳定性和准确性之间的权衡。

如果矩阵是不确定的(即它甚至有一个负的特征值),则问题是NP难的。这意味着任何基于当前可用算法的代码都会有不合理的最坏情况运行时间,即使对于中等大小的问题也是如此。如果您的问题有一些特殊结构,或者您不需要全局最优解决方案,那么您可能没问题。典型的方法是寻找凸松弛。

答案 1 :(得分:4)

LAPACK有许多Cholesky分解程序(他们称之为Cholesky分解)。有可用于LAPACK的C ++包装器(请参阅此SO question获取列表)。

Anycom在该帖子中的答案有点神秘,但他的意思是有LAPACK绑定可以与Boost的线性代数库uBLAS一起使用。


我找到了这个库:OOQP(面向对象的二次编程软件)。如果向下滚动该页面,您将找到研究论文和用户指南。该库似乎有一个C ++ API。希望这会有所帮助。

答案 2 :(得分:4)

CGAL看起来很适合二次规划。甚至有a manual

  // by default, we have a nonnegative QP with Ax <= b
  Program qp (CGAL::SMALLER, true, 0, false, 0); 

  // now set the non-default entries: 
  const int X = 0; 
  const int Y = 1;
  qp.set_a(X, 0,  1); qp.set_a(Y, 0, 1); qp.set_b(0, 7);  //  x + y  <= 7
  qp.set_a(X, 1, -1); qp.set_a(Y, 1, 2); qp.set_b(1, 4);  // -x + 2y <= 4
  qp.set_u(Y, true, 4);                                   //       y <= 4
  qp.set_d(X, X, 2); qp.set_d (Y, Y, 8); // !!specify 2D!!    x^2 + 4 y^2
  qp.set_c(Y, -32);                                       // -32y
  qp.set_c0(64);                                          // +64

  // solve the program, using ET as the exact type
  Solution s = CGAL::solve_quadratic_program(qp, ET());
  assert (s.solves_quadratic_program(qp));

来自the first example的代码。

答案 3 :(得分:2)

上述许多答案缺失的微妙之处在于矩阵是仅为正半定(PSD)还是实际上是不确定的。我没有使用过quadprog,但是如果它在PSD目标矩阵上失败,那就是软件缺乏鲁棒性的标志(凸QP通常是PSD,其中只有严格凸 QP是正定的)。根据Golub的书“Matrix Computations”,Cholesky分解可以应用于PSD矩阵,但数值稳定性往往会受到影响。

对于一般非线性编程软件 - 凸面和非凸面,COIN-OR项目维护免费和非自由软件列表。他们列出的解决方案之一是IPOPT,它当然能够解决您的问题。 IPOPT使用内点算法,对于小问题,通常比活动集方法(如quadprog使用)慢。作为替代方案,您可以将QP表示为线性互补问题(LCP),然后使用LCP求解器求解它。我发现Fackler和Miranda的Matlab代码LEMKE很容易移植到C ++。

答案 4 :(得分:1)

如果您愿意付款,可以使用Mosek。但是,有30天的免费试用期。它通常被认为是最快的解算器(没有引用,抱歉)界面是C风格,但显然完全来自C ++的callalbe。 Mosek实际上更像是一个圆锥曲线编程求解器,但是如果你不想把你的问题重新设计成一个圆锥形问题(Mosek有很多关于如何做这个的文档),你仍然可以使用它的随机梯度下降求解器解决你的二次公式。