我有一个在n维空间中给出的点集。我想要找到其中构成凸包的顶点(角落)。
我希望使用Python来解决这个问题(但也可以调用其他程序)。
编辑:所有坐标都是自然数。输出应该是顶点的索引。
通常通过搜索引擎查找出来的答案只能解决2D情况,或者要求列出面,这在计算上更加困难。
我目前的尝试:
scipy.spatial.ConvexHull()
: Throws error for my current example. And I think, I have read, it does not work for dimension above 10. Also my supervisor advised against it.Normaliz
(as part of polymake): works, but too slow. But maybe I did something wrong.import PyNormaliz def find_column_indices(A,B): return [i for i in range(A.shape[1]) if list(A[:,i]) in B.T.tolist()] def convex_hull(A): poly = PyNormaliz.Cone(polytope = A.T.tolist()) hull_cone = poly.IntegerHull() hull_vertices = np.array([entry[:-1] for entry in hull_cone.VerticesOfPolyhedron()]).T hull_indices = find_column_indices(A, hull_vertices) return hull_indices
Solve with linear programmes: works, but completely not optimised, so I think there must be a better solution.
import subprocess from multiprocessing import Pool, cpu_count from scipy.optimize import linprog import numpy as np def is_in_convex_hull(arg): A,v = arg m = A.shape[1] A_ub = -np.eye(m,dtype = np.int) b_ub = np.zeros(m) res = linprog([1 for _ in range(m)],A_ub,b_ub,A,v) return res['success'] def convex_hull2(A): pool = Pool(processes = cpu_count()) res = pool.map(is_in_convex_hull,[(np.delete(A,i,axis=1),A[:,i]) for i in range(A.shape[1])]) return [i for i in range(A.shape[1]) if not res[i]]
例子:
A = array([[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
...: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 4, 6, 6, 6, 8, 1, 2, 2, 2, 2, 3, 2, 1, 2, 1, 2, 1, 1, 1, 1, 2, 2, 2, 3, 1, 2, 2, 1, 2, 1, 1, 1, 2, 1, 2],
...: [ 0, 0, 0, 0, 0, 2, 2, 4, 6, 0, 0, 2, 4, 0, 0, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 1, 0, 1],
...: [ 0, 0, 2, 4, 4, 2, 2, 0, 0, 0, 6, 2, 0, 4, 0, 2, 4, 0, 1, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1],
...: [ 0, 6, 0, 2, 4, 0, 6, 4, 2, 2, 0, 0, 8, 4, 8, 4, 0, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 4, 2, 2, 1, 1, 1, 2, 3, 2, 2, 2, 2, 1, 2],
...: [ 0, 2, 14, 0, 4, 6, 0, 0, 4, 0, 2, 0, 4, 4, 4, 0, 0, 2, 2, 2, 2, 2, 2, 1, 2, 4, 1, 3, 2, 1, 1, 1, 1, 2, 1, 4, 1, 1, 0, 1, 1, 1, 2, 3, 1, 1, 1, 1],
...: [ 0, 0, 0, 2, 6, 0, 4, 6, 0, 0, 6, 2, 2, 0, 0, 2, 2, 0, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1],
...: [ 0, 2, 2, 12, 2, 0, 0, 2, 0, 8, 2, 4, 0, 4, 0, 4, 0, 0, 2, 1, 2, 1, 1, 2, 1, 1, 4, 2, 1, 2, 3, 1, 3, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 3, 1, 1, 2],
...: [ 0, 8, 2, 0, 0, 2, 2, 4, 4, 4, 2, 4, 0, 0, 2, 0, 0, 6, 2, 2, 1, 1, 1, 3, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 3, 1, 2, 1, 1, 1, 1, 3, 1, 3, 2, 2, 0, 1]])
产出运行时间
In [44]: %timeit convex_hull(A)
1.79 s ± 16.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [45]: %timeit convex_hull2(A)
337 ms ± 3.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
对于稍微大一些的例子,比率更糟糕,因此也不能通过并行化来解释。
非常感谢任何帮助和改进。
3
更多的维度,这是一个CG程序吗?您希望有多精确? - user1767754