Scipy ConvexHull 和 QHull:等级/维度不是最大的

Posted

技术标签:

【中文标题】Scipy ConvexHull 和 QHull:等级/维度不是最大的【英文标题】:Scipy ConvexHull and QHull: rank/dimension is not maximal 【发布时间】:2015-07-19 20:37:20 【问题描述】:

我正在尝试使用库 Scipy 和 ConvexHull 创建一个 Convex Hull。据我所知,它叫QHull。

当我要添加的点没有“全维度”时,就会出现问题。示例:

from scipy.spatial import ConvexHull
import numpy as np
points = np.append([[0,2]],[[2,0]],axis=0)
hull = ConvexHull(points)

有输出:

Traceback (most recent call last):
  File "C:/folder/vertices_scipy2.py", line 5, in <module>
hull = ConvexHull(points)
  File "scipy\spatial\qhull.pyx", line 2230, in scipy.spatial.qhull.ConvexHull.__init__ (scipy\spatial\qhull.c:20317)
  File "scipy\spatial\qhull.pyx", line 328, in scipy.spatial.qhull._Qhull.__init__ (scipy\spatial\qhull.c:3639)
QhullError: Qhull error

但是,如果我添加一个额外的点,使凸包具有完整的维度:

from scipy.spatial import ConvexHull
import numpy as np
points = np.append([[0,0],[0,2]],[[2,0]],axis=0)
hull = ConvexHull(points)

然后一切正常。一个例子和另一个例子之间的区别(我已经做了很多其他例子,所以我确定)是第一种情况下的凸包在二维空间中是一维的,而在第二种情况下,是 2-二维空间中的维度(即全维度)。

有什么想法吗?自docs 指示以来,我想通过一些 qhull_options,正如答案中提到的那样:

QHullError 在 Qhull 遇到错误条件时引发,例如在未启用解决选项时出现几何退化。

但是,我已经阅读了许多options in QHull,但似乎都没有解决这个问题。我随机尝试了其中一些,但收效甚微。

任何帮助都会有所帮助。我正在开发一个程序来创建数百个这样的船体,其中一些不是全尺寸的。

【问题讨论】:

【参考方案1】:

ConvexHull 似乎不支持退化凸包。

点数必须至少是维数加一才能具有非退化凸包。

例如在平面中,您需要 3 个点才能获得非退化包:3 个点的凸包将是一个三角形,而退化包将是 2 个点之间的线段。

事实上docs 提到:

引发:QhullError 当 Qhull 遇到错误情况时引发, 例如几何退化时解决的选项不是 已启用。

【讨论】:

所以你确定吗?它不承认“退化”凸包?我从更多的点开始,但在某些情况下,组合是“线性相关的”,这很烦人。这就是为什么我问解决“几何退化”的选项是什么。我会在问题中更清楚地写出来。谢谢! 只是为了让它更精确,即使我有很多点(这是真正的问题,而不是我构建的 MWE),这仍然会发生,例如点 (1,1)(2,2) (3,3)...等 实际上,先生,您已经给了我解决问题的关键:退化这个词(作为一名数学家,我从未见过它适用于这种情况,但适用于无穷大的点)。如果我用一行替换最后一行:hull = ConvexHull(points, qhull_options="QJn") 它就像一个魅力。谢谢! 实际上,再三考虑这不是一个好的选择。 QJn 所做的基本上是将所有点随机移动到两侧,直到达到最大尺寸。出于我正在研究的目的(确定一个点是否在凸包的边界内),这不是一个好的解决方案。 @endolith 哦,我明白了。恐怕我不知道。我一直在反复试验,如果我没记错的话,最后我采用了不同的解决方案(在低维子空间中投影,以使图像最大化)。【参考方案2】:

我无法发表评论,所以这不是真正的答案,但您可以通过以下方式获得更好的错误描述:

>>> points2 = np.append([[0,0],[1,1]],[[2,2]],axis=0)
>>> hull = ConvexHull(points2)
QH6154 qhull precision error: initial facet 1 is coplanar with the interior point
ERRONEOUS FACET:
- f1
    - flags: bottom simplicial flipped
    - normal:   -0.7071   0.7071
    - offset:         -0
    - vertices: p2(v1) p0(v0)
    - neighboring facets: f2 f3

While executing:  | qhull i Qt
Options selected for Qhull 2012.1 2012/02/18:
  run-id 972186139  incidence  Qtriangulate  _pre-merge  _zero-centrum
  _max-width  2  Error-roundoff 1.7e-15  _one-merge 8.6e-15
  _near-inside 4.3e-14  Visible-distance 3.4e-15  U-coplanar-distance 3.4e-15
  Width-outside 6.9e-15  _wide-facet 2.1e-14

The input to qhull appears to be less than 2 dimensional, or a
computation has overflowed.

Qhull could not construct a clearly convex simplex from points:
- p1(v2):     1     1
- p2(v1):     2     2
- p0(v0):     0     0

The center point is coplanar with a facet, or a vertex is coplanar
with a neighboring facet.  The maximum round off error for
computing distances is 1.7e-15.  The center point, facets and distances
to the center point are as follows:

center point        1        1

facet p2 p0 distance=    0
facet p1 p0 distance=    0
facet p1 p2 distance=    0

These points either have a maximum or minimum x-coordinate, or
they maximize the determinant for k coordinates.  Trial points
are first selected from points that maximize a coordinate.

The min and max coordinates for each dimension are:
  0:         0         2  difference=    2
  1:         0         2  difference=    2

If the input should be full dimensional, you have several options that
may determine an initial simplex:
  - use 'QJ'  to joggle the input and make it full dimensional
  - use 'QbB' to scale the points to the unit cube
  - use 'QR0' to randomly rotate the input for different maximum points
  - use 'Qs'  to search all points for the initial simplex
  - use 'En'  to specify a maximum roundoff error less than 1.7e-15.
  - trace execution with 'T3' to see the determinant for each point.

If the input is lower dimensional:
  - use 'QJ' to joggle the input and make it full dimensional
  - use 'Qbk:0Bk:0' to delete coordinate k from the input.  You should
    pick the coordinate with the least range.  The hull will have the
    correct topology.
  - determine the flat containing the points, rotate the points
    into a coordinate plane, and delete the other coordinates.
  - add one or more points to make the input full dimensional.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "qhull.pyx", line 2230, in scipy.spatial.qhull.ConvexHull.__init__ (scipy/spatial/qhull.c:19173)
  File "qhull.pyx", line 328, in scipy.spatial.qhull._Qhull.__init__ (scipy/spatial/qhull.c:3670)
scipy.spatial.qhull.QhullError: Qhull error
>>> 

【讨论】:

这不是一个答案,但它非常有用。你是怎么得到它来打印这些信息的?你用的是 Python 吗? 我的 scipy 版本可能比你(0.14.1)更新,因为总体上我得到了更详细的错误描述(对于你的例子,这只是 2 点还不够,然后列出调用 Qhull 的选项)。

以上是关于Scipy ConvexHull 和 QHull:等级/维度不是最大的的主要内容,如果未能解决你的问题,请参考以下文章

C ++ ConvexHull点算法(及其索引)

from scipy import spatial 出现 from .qhull import * ImportError: DLL load failed: The specified mod

检查点是不是位于凸包内

获取创建 ConvexHull 的点的索引

在 C++ 代码中提供 qconvex 的输入

scipy.spatial 中的凸壳例程给了我原来的一组点