评估凸组合的权重

问题描述

我正在使用 scipy.spatial.ConvexHull API 来评估一组点的凸包,并且效果很好。鉴于以下代码

p1 = points[11]
hull = ConvexHull(points)
vertices = [points[i] for i in hull.vertices] 

如何计算等于 verticesp1 的凸组合的系数(权重)?

非常感谢, 摩西

解决方法

注意:如果顶点数大于 d+1,其中 d 是维度,那么组合将是唯一的。在答案的其余部分,我假设 d=2 为简单起见。

输入:

  • 顶点 v0 = (x0,y0),v1 = (x1,y1),...,vn = (xn,yn);
  • p1 = (x,y);

输出:

  • 组合a0,a1,an;

使得:

  • x = a0 * x0 + a1 * x1 + ... + an * xn;
  • y = a0 * y0 + a1 * y1 + ... + an * yn;
  • 1 = a0 + a1 + ... + an;
  • 对于我来说,ai >= 0

这是一个由未知 (a0,an) 中的三个线性方程以及 n+1 个线性不等式组成的系统。我们可以使用 scipy's linear programming module scipy.optimize.linprog

解决这个系统

示例解决方案:

import random                      # generate points
import scipy.spatial as scispa     # ConvexHull
import scipy.optimize as sciopt    # linprog
from scipy.sparse import identity  # identity matrix

points = [(random.randrange(0,100),random.randrange(0,100)) for _ in range(20)]
p1 = points[11]
hull = scispa.ConvexHull(points)
vertices = [points[i] for i in hull.vertices]

c = [1 for _ in vertices]
A = [[x for x,y in vertices],[y for x,[1 for _ in vertices]]
b = [p1[0],p1[1],1]
s = sciopt.linprog(c,A_eq = A,b_eq = b)

>>> s.x
array([0.13393774,0.06470577,0.07367599,0.09523271,0.18924727,0.26909487,0.17410566])
>>> p1
(36,57)
>>> [sum(a*xi for a,(xi,_) in zip(s.x,vertices)),sum(a*yi for a,(_,yi) in zip(s.x,vertices))]
[36.00000000719907,57.00000000671608]

重要提示:我在回答这个问题时警告说,如果平面中有 3 个以上的顶点,或者维度 d 中有 d+1 个以上的顶点,那么将有 1 个以上的解到我们的方程组。上面的代码只返回一个解决方案,这意味着做出了任意选择。您可以控制这个任意选择:scipy.optimize.linprog 是一个优化工具;这里它最小化了我们作为参数给出的向量 c 和解向量 s.x 的点积。这里我将 c 的所有系数都设置为 1,这意味着 linprog 会找到一个使解中系数之和最小的解;尝试提供不同的向量 c,您会得到不同的解决方案。