matlab 如何生成三维随机点,使每个点之间的距离最小?

9jyewag0  于 11个月前  发布在  Matlab
关注(0)|答案(3)|浏览(172)

我将在matlab中使用此特定字符生成10^6个随机点。这些点应该位于半径为25的球体内,是三维的,因此我们有x,y,z或r,theta,phi。每个点之间有一个最小距离。首先,我决定生成点,然后检查距离,然后忽略不具备这些条件的点。但是,它可能会省略很多点。另一种方法是使用RSA(随机序贯加法),表示以最小距离逐个生成点。例如生成第一个点,然后从点1的最小距离中随机生成第二个。继续下去,直到达到10^6分。但这需要很多时间,我无法达到10^6分6分,因为搜索新点的适当位置的速度将花费很长时间。
我现在正在使用这个程序:

Nmax=10000; 
R=25; 
P=rand(1,3); 
k=1; 
while k<Nmax 
theta=2*pi*rand(1); 
phi=pi*rand(1); 
r = R*sqrt(rand(1)); 
% convert to cartesian 
x=r.*sin(theta).*cos(phi); 
y=r.*sin(theta).*sin(phi); 
z=r.*cos(theta); 
P1=[x y z]; 
r=sqrt((x-0)^2+(y-0)^2+(z-0)^2); 
D = pdist2(P1,P,'euclidean'); 
% euclidean distance 

    if D>0.146*r^(2/3) 
        P=[P;P1]; 
        k=k+1;
    end 
    i=i+1; 
end 
x=P(:,1);y=P(:,2);z=P(:,3); plot3(x,y,z,'.');

字符串
我如何能有效地生成点,通过这些条件?

h9a6wy2h

h9a6wy2h1#

我仔细看了一下你的算法,得出的结论是它永远不会工作-至少如果你真的想在那个球体上得到一百万个点的话。有一个简单的图片可以解释为什么不-这是你需要测试的点的数量图(使用你的RSA技术)得到一个额外的“好”点。正如你所看到的,这在几千个点上是渐进的(我对20万个点运行了一个稍微快一点的算法来产生这个):
x1c 0d1x的数据
我不知道你是否曾经试图计算理论上的点的数量,当你把它们完美地排列在你的球体上时,但我开始怀疑这个数字比1 E6小得多。
我用来研究这个问题的完整代码,加上它生成的输出,可以在here中找到。我从来没有达到我在前面的回答中描述的技术......在你描述的设置中还有太多其他的东西。
编辑:我开始想,即使有“完美”的安排,也不可能达到100万点。我为自己做了一个简单的模型,如下所示:
假设你从“ shell ”(r=25)开始,试着拟合等距点,如果你用“ shell ”的面积除以一个“排除盘”(半径为r_sub_crit)的面积,你会得到该距离上的点的数量的(高)估计:

numpoints = 4*pi*r^2 / (pi*(0.146 * r^(2/3))^2) ~ 188 * r^(2/3)

字符串
下一个“shell”的半径应该小于0.146*r^(2/3)-但是如果你认为这些点是非常仔细排列的,你可能会得到一点接近。同样,让我们慷慨地说,这些shell可以比标准接近1/sqrt(3)。然后你可以从外部shell开始,使用一个简单的python脚本来工作:

import scipy as sc
r = 25
npts = 0
def rc(r):
  return 0.146*sc.power(r, 2./3.)
while (r > rc(r)):  
  morePts = sc.floor(4/(0.146*0.146)*sc.power(r, 2./3.))
  npts = npts + morePts
  print morePts, ' more points at r = ', r
  r = r - rc(r)/sc.sqrt(3)

print 'total number of points fitted in sphere: ', npts


其输出为:

1604.0  more points at r =  25
1573.0  more points at r =  24.2793037966
1542.0  more points at r =  23.5725257555
1512.0  more points at r =  22.8795314897
1482.0  more points at r =  22.2001865995
1452.0  more points at r =  21.5343566722
1422.0  more points at r =  20.8819072818
1393.0  more points at r =  20.2427039885
1364.0  more points at r =  19.6166123391
1336.0  more points at r =  19.0034978659
1308.0  more points at r =  18.4032260869
1280.0  more points at r =  17.8156625053
1252.0  more points at r =  17.2406726094
1224.0  more points at r =  16.6781218719
1197.0  more points at r =  16.1278757499
1171.0  more points at r =  15.5897996844
1144.0  more points at r =  15.0637590998
1118.0  more points at r =  14.549619404
1092.0  more points at r =  14.0472459873
1066.0  more points at r =  13.5565042228
1041.0  more points at r =  13.0772594652
1016.0  more points at r =  12.6093770509
991.0  more points at r =  12.1527222975
967.0  more points at r =  11.707160503
943.0  more points at r =  11.2725569457
919.0  more points at r =  10.8487768835
896.0  more points at r =  10.4356855535
872.0  more points at r =  10.0331481711
850.0  more points at r =  9.64102993012
827.0  more points at r =  9.25919600154
805.0  more points at r =  8.88751153329
783.0  more points at r =  8.52584164948
761.0  more points at r =  8.17405144976
740.0  more points at r =  7.83200600865
718.0  more points at r =  7.49957037478
698.0  more points at r =  7.17660957023
677.0  more points at r =  6.86298858965
657.0  more points at r =  6.55857239952
637.0  more points at r =  6.26322593726
618.0  more points at r =  5.97681411037
598.0  more points at r =  5.69920179546
579.0  more points at r =  5.43025383729
561.0  more points at r =  5.16983504778
542.0  more points at r =  4.91781020487
524.0  more points at r =  4.67404405146
506.0  more points at r =  4.43840129415
489.0  more points at r =  4.21074660206
472.0  more points at r =  3.9909446055
455.0  more points at r =  3.77885989456
438.0  more points at r =  3.57435701766
422.0  more points at r =  3.37730048004
406.0  more points at r =  3.1875547421
390.0  more points at r =  3.00498421767
375.0  more points at r =  2.82945327223
360.0  more points at r =  2.66082622092
345.0  more points at r =  2.49896732654
331.0  more points at r =  2.34374079733
316.0  more points at r =  2.19501078464
303.0  more points at r =  2.05264138052
289.0  more points at r =  1.91649661498
276.0  more points at r =  1.78644045325
263.0  more points at r =  1.66233679273
250.0  more points at r =  1.54404945973
238.0  more points at r =  1.43144220603
226.0  more points at r =  1.32437870508
214.0  more points at r =  1.22272254805
203.0  more points at r =  1.1263372394
192.0  more points at r =  1.03508619218
181.0  more points at r =  0.94883272297
170.0  more points at r =  0.867440046252
160.0  more points at r =  0.790771268402
150.0  more points at r =  0.718689381062
140.0  more points at r =  0.65105725389
131.0  more points at r =  0.587737626612
122.0  more points at r =  0.528593100237
113.0  more points at r =  0.473486127367
105.0  more points at r =  0.422279001431
97.0  more points at r =  0.374833844693
89.0  more points at r =  0.331012594847
82.0  more points at r =  0.290676989951
75.0  more points at r =  0.253688551418
68.0  more points at r =  0.219908564725
61.0  more points at r =  0.189198057381
55.0  more points at r =  0.161417773651
49.0  more points at r =  0.136428145311
44.0  more points at r =  0.114089257597
38.0  more points at r =  0.0942608092113
33.0  more points at r =  0.0768020649149
29.0  more points at r =  0.0615717987589
24.0  more points at r =  0.0484282253244
20.0  more points at r =  0.0372289153633
17.0  more points at r =  0.0278306908104
13.0  more points at r =  0.0200894920319
10.0  more points at r =  0.013860207063
8.0  more points at r =  0.00899644813842
5.0  more points at r =  0.00535025545232 

total number of points fitted in sphere:  55600.0


这似乎证实了你真的无法达到一百万,无论你如何尝试。

5ktev3wc

5ktev3wc2#

你可以做很多事情来改进你的程序--算法和代码。
在代码方面,真正使您的速度变慢的一个原因是,您不仅使用了for循环(这很慢),而且在行

P = [P;P1];

字符串
您将元素添加到数组中。每次发生这种情况时,Matlab都需要找到一个新的位置来放置数据,并在此过程中复制所有的点。这很快就会变得非常慢。

P = zeros(1000000, 3);


记录到目前为止已找到的点数N,并将距离计算改为

D = pdist2(P1, P(1:N, :), 'euclidean');


至少能解决这个问题。
另一个问题是,您需要对照以前找到的所有点来检查新点,因此,当您有100个点时,您需要检查大约100 x100个点,对于1000,它是1000 x1000。您可以看到,此算法至少是O(N^3)......不考虑随着密度的增加,您将获得更多“未命中”的事实。10 E6至少需要10 E18个周期;如果你有一台4GHz的机器,每次比较一个时钟周期,你需要2.5E9秒=大约80年。你可以尝试并行处理,但那只是蛮力--谁愿意呢?
我建议您考虑将问题分解为更小的部分(字面意思):举例来说,如果你把球体分成大小与你的最大距离相当的小方块,并记录每个方块中的点,那么你只需要检查“这个”方块中的点及其紧邻的点--总共27个方块。2如果你的方块有2.5毫米宽,您将有100 x100 x100 = 1 M个盒子。这看起来很多,但现在您的计算时间将大幅减少,因为(在算法结束时)每个盒子平均只有1个点......当然,根据您使用的距离标准,您将在中心附近有更多的点,但这只是一个细节。
您需要的数据结构是一个100 x100 x100的单元数组,每个单元包含“在该单元中”迄今为止找到的好点的索引。单元数组的问题在于它不适合矢量化。如果您有足够的内存,则可以将其指定为一个10 x100 x100 x100的4D数组。假设每个像元中的点不超过10个(如果超过10个,则必须单独处理;在此与我一起工作...)。对于尚未找到的点,使用-1索引
那么你的支票应该是这样的:

% initializing:
bigList = zeros(10,102,102,102)-1; % avoid hitting the edge...
NPlist = zeros(102, 102, 102); % track # valid points in each box
bottomcorner = [-25.5, -25.5, -25.5]; % boxes span from -25.5 to +25.5
cellSize = 0.5;


% in your loop:
P1= [x, y, z];
cellCoords = ceil(P1/cellSize);
goodFlag = true;
pointsSoFar = bigList(:, cellCoords(1)+(-1:1), cellCoords(2)+(-1:1), cellCoords(3)+(-1:1));
pointsToCheck = find(pointsSoFar>0); % this is where the big gains come...
r=sum(P1.^2);
D = pdist2(P1,P(pointsToCheck, :),'euclidean'); % euclidean distance 

if D>0.146*r^(2/3) 
    P(k,:) = P1;
    % check the syntax of this line...
    cci = ind2sub([102 102 102], cellCoords(1), cellCoords(2), cellCoords(3));
    NP(cci)=NP(cci)+1; % increasing number of points in this box
    % you want to handle the case where this > 10!!!
    bigList(NP(cci), cci) = k;
    k=k+1;
end
....


我不知道你能不能从这里开始,如果你不能,在笔记里说,我可能会在这个周末有时间来更详细地编码。有一些方法可以通过一些矢量化来加快速度,但是很快就变得很难管理了。
我认为在空间中随机放置大量的点,然后使用上面的方法进行巨大的矢量化剔除,可能是一种可行的方法。但我建议先采取一些小步骤......如果你能让上面的方法很好地工作,那么你可以进一步优化(数组大小等)。

xdnvmnnf

xdnvmnnf3#

我发现the reference -“Simulated Brain Tumor Growth Dynamics Using a Three-Dimensional Cellular Automaton”,Ansal et al(2000).
我同意这是令人费解的-直到你意识到一个重要的事情。他们报告他们的结果在mm,但你的代码是写在cm。虽然这似乎无关紧要,公式“临界半径”,rc = 0.146r^(2/3)包括一个常数,0.146,这是维数-维数是mm^(1/3),而不是cm^(1/3)
当我在我的python代码中进行修改以评估可能的晶格点的数量时,它跳了10倍。现在他们声称他们使用了0.38的“干扰限制”-你真的找不到更多的点。如果你包括这个限制,我预测不会超过20万个点-仍然低于他们的1.5M,但不那么疯狂。

相关问题