You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python的Plotly等库绘制3D Permutohedron(排列多面体)的问题求助

我正尝试使用Python的plotly、numpy和pandas库绘制Permutohedron(排列多面体)。

这是我目前编写的代码:

import plotly.express as px
import numpy as np
import itertools
import pandas as pd

order = 4
items = range(1, order+1)
permuted_items = np.array([*itertools.permutations(items)])

def closest_nodes(node, nodes):
      # 返回nodes中与node距离最近的实例
      nodes = np.asarray(nodes)
      dist_2 = np.sum((nodes - node)**2, axis=1)**.5
      indices = np.where(dist_2 == dist_2.min())[0]

      return nodes[indices]

xyzs = []
colors = []

for i, point in enumerate(permuted_items[:-1]):
      closest_points = closest_nodes(point, permuted_items[i+1:])
      for c_point in closest_points:
            xyzs.extend([point[:3], c_point[:3]])

            # 生成唯一字符串作为颜色标识,用于绘图时对边进行分组
            c = str(point) + str(c_point[:3])
            colors.extend([c, c])

lines = np.array(xyzs)
x, y, z = lines.T
plotting_data = pd.DataFrame({
      "X": x,
      "Y": y,
      "Z": z,
      "color": colors
})

fig = px.line_3d(plotting_data, x='X', y='Y', z='Z', color="color")
fig.show()

但输出的图形严重变形:
变形的绘制结果

也就是我通过删除最后一维将形状投影到3D的方法改变了每条边的长度,导致所有边的长度都不等于√2。

我期望得到的正确形状如下:
正确的3D排列多面体形状

请问应该如何修改代码才能得到正确的绘制结果?


问题原因

4阶排列多面体的所有顶点都位于4维空间的超平面x₁+x₂+x₃+x₄ = 10上,直接丢弃最后一维的投影方式不是等距投影,会破坏原有顶点间的距离关系,导致图形变形。

解决方案

你需要先将4维顶点等距投影到3维空间,再进行绘制。核心是先对4维顶点做中心化,再投影到超平面x₁+x₂+x₃+x₄=0的正交单位基上,即可保留原始距离关系。

修改后完整代码

import plotly.express as px
import numpy as np
import itertools
import pandas as pd

order = 4
items = range(1, order+1)
permuted_items = np.array([*itertools.permutations(items)])

# 构造4维到3维的等距投影矩阵
# 超平面x1+x2+x3+x4=0的正交基
basis = np.array([
    [1, -1, 0, 0],
    [1, 1, -2, 0],
    [1, 1, 1, -3]
])
# 基向量单位化
basis = basis / np.linalg.norm(basis, axis=1, keepdims=True)
# 顶点中心化(去掉均值,平移到超平面x1+x2+x3+x4=0上)
centered_points = permuted_items - permuted_items.mean(axis=1, keepdims=True)
# 投影得到3维坐标
projected_3d = centered_points @ basis.T

def closest_nodes(node, nodes):
      nodes = np.asarray(nodes)
      dist_2 = np.sum((nodes - node)**2, axis=1)**.5
      indices = np.where(dist_2 == dist_2.min())[0]
      return nodes[indices]

xyzs = []
colors = []

for i, point in enumerate(permuted_items[:-1]):
      closest_points = closest_nodes(point, permuted_items[i+1:])
      for c_point in closest_points:
            # 使用投影后的3维坐标,而非原始前3维
            c_idx = np.where((permuted_items == c_point).all(axis=1))[0][0]
            xyzs.extend([projected_3d[i], projected_3d[c_idx]])
            c = str(point) + str(c_point)
            colors.extend([c, c])

lines = np.array(xyzs)
x, y, z = lines.T
plotting_data = pd.DataFrame({
      "X": x,
      "Y": y,
      "Z": z,
      "color": colors
})

fig = px.line_3d(plotting_data, x='X', y='Y', z='Z', color="color")
# 设置等轴比例避免plotly自动拉伸
fig.update_layout(scene=dict(aspectmode='data'))
fig.show()

运行后即可得到边长一致、形状正确的3D排列多面体。


内容的提问来源于stack exchange,提问作者Zoom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:36:03