【问题标题】:Quadratic programming in MathematicaMathematica 中的二次规划
【发布时间】:2011-03-01 06:20:37
【问题描述】:

我正在研究最大独立集问题的二次松弛 (p.22 here),发现 FindMaximum 对于我尝试的每个图都失败了,除非我以最优解作为起点。这些二次程序有 10-20 个变量,所以我希望它们是可解的。

  1. 有没有办法让 Mathematica 解决这样的二次规划?
  2. 是否有一些易于从 Mathematica 中调用的二次编程包?

这是一个失败的示例 FindMaximum,然后是在解决方案中初始化的 FindMaximum 工作

setupQuadratic[g_Graph] := (
   Ag = AdjacencyMatrix[g];
   A = IdentityMatrix[Length@VertexList@g] - Ag;
   cons = And @@ Table[0 <= x[v] <= 1, {v, VertexList@g}];
   vars = x /@ VertexList[g];
   indSet = FindIndependentVertexSet@g;
   xOpt = Array[Boole[MemberQ[indSet, #]] &, {Length@VertexList@g}];
   );

g = GraphData[{"Cubic", {10, 11}}];
setupQuadratic[g];
FindMaximum[{vars.A.vars, cons}, vars]
FindMaximum[{vars.A.vars, cons}, Thread[{vars, xOpt}]]

这是我尝试过的其他图表

{"DodecahedralGraph", "FruchtGraph", "TruncatedPrismGraph", \
"TruncatedTetrahedralGraph", {"Cubic", {10, 2}}, {"Cubic", {10, 
   3}}, {"Cubic", {10, 4}}, {"Cubic", {10, 6}}, {"Cubic", {10, 
   7}}, {"Cubic", {10, 11}}, {"Cubic", {10, 12}}, {"Cubic", {12, 
   5}}, {"Cubic", {12, 6}}, {"Cubic", {12, 7}}, {"Cubic", {12, 
   9}}, {"Cubic", {12, 10}}}

【问题讨论】:

  • 您链接的论文非常好。谢谢!

标签: wolfram-mathematica graph-theory mathematical-optimization


【解决方案1】:

可能会尝试位于here 的包中显示的方法。见问题 8

丹尼尔·利希特布劳 Wolfram 研究

【讨论】:

【解决方案2】:

看来Maximize 会更好地为您服务。这是您的函数的修改版本,它返回一个包含 2 个结果的列表 - “手动”一个和由 Maximize 获得的一个:

Clear[findIVSet];
findIVSet[g_Graph] :=
Module[{Ag, A, cons, vars, indSet, indSetFromMaximize, xOpt},
  Ag = AdjacencyMatrix[g];
  A = IdentityMatrix[Length@VertexList@g] - Ag;
  cons = And @@ Table[0 <= x[v] <= 1, {v, VertexList@g}];
  vars = x /@ VertexList[g];
  indSet = FindIndependentVertexSet@g;
  xOpt = Array[Boole[MemberQ[indSet, #]] &, {Length@VertexList@g}];
  {indSet, DeleteCases[vars /. (Last@
    Maximize[{vars.A.vars, cons}, vars,Integers] /. (x[i_] -> 1) :> (x[i] -> i)), 0]}];

结果如下:

In[32]:= graphs = GraphData /@ {"DodecahedralGraph", "FruchtGraph", 
"TruncatedPrismGraph", "TruncatedTetrahedralGraph", {"Cubic", {10, 2}}, {"Cubic", {10, 
  3}}, {"Cubic", {10, 4}}, {"Cubic", {10, 6}}, {"Cubic", {10, 
  7}}, {"Cubic", {10, 11}}, {"Cubic", {10, 12}}, {"Cubic", {12, 
  5}}, {"Cubic", {12, 6}}, {"Cubic", {12, 7}}, {"Cubic", {12, 
  9}}, {"Cubic", {12, 10}}};


In[33]:= sets = findIVSet /@ graphs

Out[33]= {{{1, 2, 3, 8, 10, 11, 17, 20}, {5, 6, 7, 8, 14, 15, 17, 18}},
{{2, 4, 6, 11, 12}, {2, 4, 6, 11, 12}}, {{2, 7, 10, 12, 16, 18}, {8, 11, 13, 16, 17, 18}}, 
{{1, 4, 7, 12}, {4, 7, 9, 12}}, {{2,3, 8, 9}, {2, 3, 8, 9}}, {{1, 4, 7, 10}, {2, 5, 8, 9}}, 
{{1, 4, 7, 10}, {2, 4, 7, 9}}, {{2, 4, 5, 8}, {3, 6, 7, 9}}, {{2, 5, 8, 9}, {2, 5, 8, 9}}, 
{{1, 3, 7, 10}, {4, 5, 8, 9}}, {{1, 6, 8, 9}, {2, 3, 6, 10}}, {{1, 6, 7, 12}, {4, 5, 9, 10}}, 
{{3, 4, 7, 8, 12}, {3, 4, 7, 8, 12}}, {{1, 5, 8, 9}, {4, 5, 10, 11}}, 
{{1, 5, 6, 9, 10}, {3, 4, 7, 8, 12}}, {{3, 4, 7, 9, 10}, {3, 4, 7, 9, 10}}}

“手动”和Maximize 的那些并不总是相同的,但是还有更多 独立集合的一种解决方案。 Maximize的结果都是独立的集合,很容易验证:

In[34]:= MapThread[IndependentVertexSetQ, {graphs, sets[[All, 2]]}]

Out[34]= {True, True, True, True, True, True, True, True, True, True, True, True, True, 
True, True,True}

【讨论】:

  • 好吧,我已经有来自 FindIndependentVertexSet 的独立集,它可能在内部使用类似你建议的东西,我实际上有兴趣找到原始二次实域的最大值
  • @Yaroslav 为什么你对真实域名感兴趣?据我所知,在您链接的论文中明确指出,所有变量只能具有值 0 或 1(即整数域)。而且,就此而言,是什么让您认为真实域的结果与最大独立集问题有任何关系?很明显,我们不是在这里搜索局部极值,因此约束很重要。具有连续约束的极值可能与具有离散约束的极值完全不同。还是我完全没有抓住重点?
  • 因为在整数域中求解它是 NP 完全的,而实值 QP 编程是易于处理的。丢弃整数约束被称为“松弛”,它对某些类别的图效果出奇的好——cstheory.stackexchange.com/questions/5170/…
  • @Yaroslav 这很容易处理,但最大化是非凸的(在这种情况下最小化是凸的)。所以不能保证全球性。
  • 有趣,我猜这个QP并不像我想象的那么容易。显然,这种非凸 QP 问题被称为“Box-QP”
【解决方案3】:

IMO,FindMaximum 在这里不起作用的原因是你的函数的野性。我尝试了一个在可变空间中包含 1,048,576 个样本的网格,但没有一个样本的值高于零。您的最佳起始值为 -20。

In[10]:= (x[1]^2 + x[2]^2 + x[3]^2 - 2 x[3] x[4] + x[4]^2 - 
  2 x[2] (x[3] + x[4]) + x[5]^2 - 2 x[3] x[6] - 2 x[5] x[6] + 
  x[6]^2 - 2 x[5] x[7] + x[7]^2 - 2 x[6] x[8] - 2 x[7] x[8] + 
  x[8]^2 - 2 x[7] x[9] + x[9]^2 - 2 x[1] (x[2] + x[5] + x[9]) - 
  2 x[4] x[10] - 2 x[8] x[10] - 2 x[9] x[10] + x[10]^2 /. 
 Thread[vars -> #]) & @@@ Tuples[{0.0, 0.333, 0.667, 1.0}, 10] // Max

Out[10]= 0.

In[11]:= (x[1]^2 + x[2]^2 + x[3]^2 - 2 x[3] x[4] + x[4]^2 - 
 2 x[2] (x[3] + x[4]) + x[5]^2 - 2 x[3] x[6] - 2 x[5] x[6] + 
 x[6]^2 - 2 x[5] x[7] + x[7]^2 - 2 x[6] x[8] - 2 x[7] x[8] + 
 x[8]^2 - 2 x[7] x[9] + x[9]^2 - 2 x[1] (x[2] + x[5] + x[9]) - 
 2 x[4] x[10] - 2 x[8] x[10] - 2 x[9] x[10] + x[10]^2 /. 
Thread[vars -> #]) & @@@ {xOpt}

Out[11]= {-20}

【讨论】:

  • 上述目标在ReplaceAll之后简化为Times[-20,Power[Slot[1],2]]。评估原始目标的一种方法是vars.A.vars /. Thread[vars -&gt; xOpt]
  • 顺便说一句,如果您将 @@@ 替换为 /@ 或将 # 替换为 {##}(但不能同时使用两者!),则可以修复上述问题!
  • 我扩展了 vars.A.vars,因为它在我的机器上节省了 2.3 倍的时间。我知道第二部分的写法可能不同。我只是这样做是为了保持代码的结构相同。
  • 我的意思是有一个错误,目标应该是4xOpt,而不是-20
猜你喜欢
  • 2012-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多