HalfspaceIntersection#
- class scipy.spatial.HalfspaceIntersection(halfspaces, interior_point, incremental=False, qhull_options=None)#
N 维中的半空间交集。
Added in version 0.19.0.
- 参数:
- 半角空格浮点数的 ndarray,形状为 (nineq, ndim+1)
堆叠不等式形式 Ax + b <= 0 的格式为 [A; b]
- interior_point浮点数的 ndarray,形状为 (ndim,)
明确指向由半空间定义的区域内。也称为可行点,可以通过线性规划获得。
- 增量bool, 可选
允许逐步添加新半空间。这会占用一些额外资源。
- qhull_optionsstr, 可选
传递给 Qhull 的额外选项。详情请参阅 Qhull 手册。(默认值:ndim > 4 时为 “Qx”,否则为 “”)选项 “H” 始终启用。
- 属性:
- 半角空格双精度数组,形状为 (nineq, ndim+1)
输入半角空格。
- interior_point :ndarray of floats, shape (ndim,)
输入内部点。
- 交叉点双精度 ndarray,形状为 (ninter, ndim)
所有半空间的交集。
- 双点双精度数组,形状为 (nineq, ndim)
输入半空间的两个端点。
- 双面整数列表的列表
形成对偶凸包(不一定是单纯形)面的点的索引。
- dual_vertices整数 ndarray,形状为 (nvertices,)
形成对偶凸包顶点的半空间索引。对于2维凸包,顶点按逆时针顺序排列。对于其他维度,它们按输入顺序排列。
- 双变量方程双精度 ndarray,形状为 (nfacet, ndim+1)
[normal, offset] 形成对偶面的超平面方程(更多信息请参见 Qhull 文档)。
- 双区域浮动
对偶凸包的面积
- 双卷浮动
对偶凸包的体积
方法
add_halfspaces
(halfspaces[, restart])处理一组额外的新的半空间。
close
()完成增量处理。
- Raises:
- QhullError
当 Qhull 遇到错误条件时引发,例如在未启用解决选项时的几何退化。
- ValueError
如果输入的是一个不兼容的数组,则会引发此错误。
注释
交点的计算使用了 Qhull 库 。这重现了 Qhull 的 “qhalf” 功能。
参考文献
[Qhull][1]S. Boyd, L. Vandenberghe, Convex Optimization, available at http://stanford.edu/~boyd/cvxbook/
示例
形成某些多边形的平面半空间交集
>>> from scipy.spatial import HalfspaceIntersection >>> import numpy as np >>> halfspaces = np.array([[-1, 0., 0.], ... [0., -1., 0.], ... [2., 1., -4.], ... [-0.5, 1., -2.]]) >>> feasible_point = np.array([0.5, 0.5]) >>> hs = HalfspaceIntersection(halfspaces, feasible_point)
绘制半空间的填充区域和交点:
>>> import matplotlib.pyplot as plt >>> fig = plt.figure() >>> ax = fig.add_subplot(1, 1, 1, aspect='equal') >>> xlim, ylim = (-1, 3), (-1, 3) >>> ax.set_xlim(xlim) >>> ax.set_ylim(ylim) >>> x = np.linspace(-1, 3, 100) >>> symbols = ['-', '+', 'x', '*'] >>> signs = [0, 0, -1, -1] >>> fmt = {"color": None, "edgecolor": "b", "alpha": 0.5} >>> for h, sym, sign in zip(halfspaces, symbols, signs): ... hlist = h.tolist() ... fmt["hatch"] = sym ... if h[1]== 0: ... ax.axvline(-h[2]/h[0], label='{}x+{}y+{}=0'.format(*hlist)) ... xi = np.linspace(xlim[sign], -h[2]/h[0], 100) ... ax.fill_between(xi, ylim[0], ylim[1], **fmt) ... else: ... ax.plot(x, (-h[2]-h[0]*x)/h[1], label='{}x+{}y+{}=0'.format(*hlist)) ... ax.fill_between(x, (-h[2]-h[0]*x)/h[1], ylim[sign], **fmt) >>> x, y = zip(*hs.intersections) >>> ax.plot(x, y, 'o', markersize=8)
默认情况下,qhull 不提供计算内部点的方法。这可以通过线性规划轻松计算。考虑形式为 \(Ax + b \leq 0\) 的半空间,求解线性规划问题:
\[ \begin{align}\begin{aligned}最大值:y\\约束条件:Ax + y ||A_i|| ≤ -b\end{aligned}\end{align} \]其中 \(A_i\) 是 A 的行,即每个平面的法线。
将产生一个点 x,该点位于凸多面体内最深处。确切地说,它是半径为 y 的最大超球体的中心,该超球体内切于该多面体。这个点被称为多面体的切比雪夫中心(参见 [1] 4.3.1,第148-149页)。Qhull 输出的方程总是归一化的。
>>> from scipy.optimize import linprog >>> from matplotlib.patches import Circle >>> norm_vector = np.reshape(np.linalg.norm(halfspaces[:, :-1], axis=1), ... (halfspaces.shape[0], 1)) >>> c = np.zeros((halfspaces.shape[1],)) >>> c[-1] = -1 >>> A = np.hstack((halfspaces[:, :-1], norm_vector)) >>> b = - halfspaces[:, -1:] >>> res = linprog(c, A_ub=A, b_ub=b, bounds=(None, None)) >>> x = res.x[:-1] >>> y = res.x[-1] >>> circle = Circle(x, radius=y, alpha=0.3) >>> ax.add_patch(circle) >>> plt.legend(bbox_to_anchor=(1.6, 1.0)) >>> plt.show()