Math 如何在高维超球面上均匀分布点?

Math 如何在高维超球面上均匀分布点?,math,geometry,pseudocode,n-dimensional,Math,Geometry,Pseudocode,N Dimensional,我感兴趣的是在3维或更高维的球体表面上均匀分布N个点 更具体地说: 给定点数N和维数D(其中D>1,N>1) 每个点到原点的距离必须为1 任意两点之间的最小距离应尽可能大 每个点到最近邻点的距离不一定必须对每个点都相同(事实上,它不可能是相同的,除非点的数量形成柏拉图式实体的顶点,或者如果N作为部分答案,你可以用来计算f的逆。在牛顿迭代中使用x作为初始点是一个不错的选择,因为f(x)与x的距离永远不会超过1个单位。下面是一个Python实现: import math def f(x):

我感兴趣的是在3维或更高维的球体表面上均匀分布N个点

更具体地说:

  • 给定点数N和维数D(其中D>1,N>1)
  • 每个点到原点的距离必须为1
  • 任意两点之间的最小距离应尽可能大

  • 每个点到最近邻点的距离不一定必须对每个点都相同(事实上,它不可能是相同的,除非点的数量形成柏拉图式实体的顶点,或者如果N作为部分答案,你可以用来计算f的逆。在牛顿迭代中使用
    x
    作为初始点是一个不错的选择,因为
    f(x)
    x
    的距离永远不会超过1个单位。下面是一个Python实现:

    import math
    
    def f(x):
        return x + 0.5*math.sin(2*x)
    
    def f_inv(x,tol = 1e-8):
        xn = x
        y = f(xn)
        while abs(y-x) > tol:
            xn -= (y-x)/(1+math.cos(2*xn))
            y = f(xn)
        return xn
    

    关于牛顿方法的这个应用,一个很好的事实是,每当
    cos(2*x)=-1
    (如果你要除以0),你就会自动得到
    sin(2*x)=0
    ,因此
    f(x)=x
    。在这种情况下,不会输入while循环,并且
    f_inv
    只返回原始的x。

    我们有n个点,它们是P1,…,Pn。我们有一个维度号d。每个(i=1,n)点可以表示为:

    π=(π(x1),…,π(xd))

    我们知道

    D(Pi,0)=1

    sqrt((pi(x1)-pj(x1))^2+…+(pi(xd)-pj(xd))^2)=1

    任意点之间的最小距离,MD是

    无限大
  • 每边的长度相似
因此,一个有n个角的多边形,其中n是一个有限的数,大于2,并且,每边的长度相似,每次我们增加n时,它更接近一个圆。注意,d=2中的第一个多边形是三角形。我们有一个角,最小角度单位是360度/n

现在,如果我们有一个正方形,并且在其上均匀分布点,那么将正方形转换成圆通孔应该是精确解,或者非常接近它。如果它是精确解,那么对于d=2的情况,这是一个简单的解。如果它非常接近,那么通过近似的方法,我们可以确定溶胶是什么计算精度在您选择的给定精度范围内

我会在d=3的情况下使用这个想法。我会解决立方体的问题,这个问题要简单得多,使用基变换将立方体点转换为球体点。我会在d>3的情况下使用这个方法,解决超立方体的问题并将其转换为超球体。当你y将点分布在d维的超立方体上

请注意,我不知道转化为超球体的超立方体的解是精确解还是接近精确解,但是如果它不是精确解,那么我们可以通过近似提高精度

因此,这种方法是问题的解决方案,就时间复杂度而言,它不一定是最好的方法,因此,如果一个人深入研究了斐波那契晶格区域,并且知道如何将其推广到更多维度,那么他/她的答案可能比我的答案更好


如果定义f(x)的倒数,可以确定f(x)=x的倒数-0.5sin2x。你会得到x的多项式序列。

非常有趣的问题。我想把它实现为,因为我很好奇它看起来会是什么样子,但我太懒了,不能从数学方面处理ND超越的问题

相反,我对这个问题提出了不同的解决方案。它不是一个斐波那契关系!!!相反,我将a的参数方程展开为超螺旋,然后只拟合螺旋参数,使点的距离大致相等

我知道这听起来很可怕,但它并没有那么难,在解决了一些愚蠢的打字错误(复制/粘贴错误)后,结果对我来说是正确的(最后:)

其主要思想是使用超球体的n维参数方程从角度和半径计算其表面点。此处实现:

import math

def f(x):
    return x + 0.5*math.sin(2*x)

def f_inv(x,tol = 1e-8):
    xn = x
    y = f(xn)
    while abs(y-x) > tol:
        xn -= (y-x)/(1+math.cos(2*xn))
        y = f(xn)
    return xn
请参阅[edit2]。现在问题归结为两个主要问题:

  • 计算螺钉数量

    因此,如果我们希望我们的点是等距的,那么它们必须等距离地位于螺旋路径上(见bullet#2),而且螺钉本身之间的距离应该相同。为此,我们可以利用超球体的几何特性。让我们从2D开始:

    因此,只需
    screws=r/d
    。点数也可以推断为
    points=area/d^2=PI*r^2/d^2

    因此,我们可以简单地将2D螺旋线写成:

    t = <0.0,1.0>
    a = 2.0*M_PI*screws*t;
    x = r*t*cos(a);
    y = r*t*sin(a);
    
    3D:

    screws=1.0/d;          // radius/d
    points=M_PI/(d*d);     // surface_area/d^2
    a = 2.0*M_PI*t*screws;
    x = t*cos(a);
    y = t*sin(a);
    
    screws=M_PI/d;         // half_circumference/d
    points=4.0*M_PI/(d*d); // surface_area/d^2
    a=    M_PI*t;
    b=2.0*M_PI*t*screws;
    x=cos(a)       ;
    y=sin(a)*cos(b);
    z=sin(a)*sin(b);
    
    screws = M_PI/d;
    points = 3.0*M_PI*M_PI*M_PI/(4.0*d*d*d);
    a=    M_PI*t;
    b=    M_PI*t*screws;
    c=2.0*M_PI*t*screws*screws;
    x=cos(a)              ;
    y=sin(a)*cos(b)       ;
    z=sin(a)*sin(b)*cos(c);
    w=sin(a)*sin(b)*sin(c);
    
    4D:

    screws=1.0/d;          // radius/d
    points=M_PI/(d*d);     // surface_area/d^2
    a = 2.0*M_PI*t*screws;
    x = t*cos(a);
    y = t*sin(a);
    
    screws=M_PI/d;         // half_circumference/d
    points=4.0*M_PI/(d*d); // surface_area/d^2
    a=    M_PI*t;
    b=2.0*M_PI*t*screws;
    x=cos(a)       ;
    y=sin(a)*cos(b);
    z=sin(a)*sin(b);
    
    screws = M_PI/d;
    points = 3.0*M_PI*M_PI*M_PI/(4.0*d*d*d);
    a=    M_PI*t;
    b=    M_PI*t*screws;
    c=2.0*M_PI*t*screws*screws;
    x=cos(a)              ;
    y=sin(a)*cos(b)       ;
    z=sin(a)*sin(b)*cos(c);
    w=sin(a)*sin(b)*sin(c);
    
    现在注意4D的点只是我的假设。我根据经验发现它们与
    常量/d^3
    有关,但并不完全相同。每个角度的螺钉都不同。我的假设是除了
    螺钉^I
    之外没有其他比例,但它可能需要一些常量调整(未对生成的点云进行分析,因为我认为结果正常)

    现在我们可以从单个参数
    t=
    生成螺旋上的任意点

    请注意,如果您颠倒方程式,那么
    d=f(点)
    您可以将点作为输入值,但请注意,它只是近似的点数,并不精确

  • 在螺旋上生成阶跃,使点等距

    这是我跳过代数混乱而使用拟合的部分。我只需对delta
    t
    进行二元搜索,结果点距离上一点
    d
    较远。只需生成点
    t=0
    ,然后在估计位置附近进行二元搜索,直到距离起点
    d
    较远。然后重复直到