Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm matlab中计算大量位置成对距离的有效算法_Algorithm_Matlab - Fatal编程技术网

Algorithm matlab中计算大量位置成对距离的有效算法

Algorithm matlab中计算大量位置成对距离的有效算法,algorithm,matlab,Algorithm,Matlab,我最近在matlab中计算具有大量位置的球面距离时遇到了一个问题。问题是: 1.位置是纬度和经度,存储在尺寸为nx2的矢量LOC中,其中n=10^5 2.我想计算矢量LOC中任意两个位置之间的球面距离。请注意,生成的距离矩阵可能稀疏,也可能不稀疏,因为如果没有距离,我无法检查它。让我们假设它是稀疏的,因为我们可以用一个数字来截断距离,比如说1000。(单位为km),生成的距离矩阵足以供我使用 3.我试过两种方法来计算,但每种方法都有缺点 PS:我用Matlab2014学生版在Mac OS上运行代

我最近在matlab中计算具有大量位置的球面距离时遇到了一个问题。问题是:

1.位置是纬度和经度,存储在尺寸为nx2的矢量LOC中,其中n=10^5

2.我想计算矢量LOC中任意两个位置之间的球面距离。请注意,生成的距离矩阵可能稀疏,也可能不稀疏,因为如果没有距离,我无法检查它。让我们假设它是稀疏的,因为我们可以用一个数字来截断距离,比如说1000。(单位为km),生成的距离矩阵足以供我使用

3.我试过两种方法来计算,但每种方法都有缺点

PS:我用Matlab2014学生版在Mac OS上运行代码。函数great_circle_distance()非常类似于Matlab内置函数,该函数使用地理空间坐标计算任意两个位置之间的大圆距离。这里的问题与此函数的使用无关

提前感谢您的各种建议

--圆盘

方法1: 这种方法的缺点是在计算代码中的d时消耗了太多内存(超过15G)。

1)方法#1 在构建中间变量(数组改变大小等)的方式上效率非常低。考虑这种改进的实现:

% given some data (longitude/latitude)
locs = rand(N,2);    % N = 10^5 in your case

% pick an appropriate size (guesstimate the number of nonzeros in the sparse mat)
nzmx = ...;

% compute pairwise-distance matrix (only those satisfying some condition)
D = spalloc(N, N, nzmx);
for i=1:N
    d = great_circle_distance(locs(i,:), locs);
    idx = find(100<d & d<400);   % distances in the range [100,400] km
    D(idx,i) = d(idx);
end

2) 方法#2
显然,由于您使用的是
pdist
,因此它将计算整个矩阵(很好,只计算其中的一半)。因此,您必须确保有足够的内存来存储它(根据我的计算,大约
((N*(N-1)/2)*8)/2^30=37.25 GB
)。

一个解决方案。通过重叠边界框覆盖整个球体,这些边界框的边都至少有600英里长。将每个点放在它所属的所有边界框中。计算并过滤每个边界框内的成对距离。收集并消除找到的所有点对(给定的点对可以位于两个边界框中,因此可能出现两次)。感谢您的建议。我尝试了你对方法1的建议,它持续运行了一整夜,但比上一个快了一点。我想我需要并行运行for循环。顺便说一句,大圆距离函数只是从地理空间坐标到地球表面大圆距离的转换(假设它是一个球体),没有任何循环和索引。@Disc:nzmx你选择了什么?如果该值太小,则矩阵每次需要更多空间时都会增长,从而导致其不断重复,这是非常昂贵的..我设置了nzmx=floor(1e-4*n^2)=42949935,但我不知道距离矩阵的稀疏性应该有多大,因为我想使用距离创建协方差矩阵。如果我将nzmx设置为一个非常小的整数,它可能对我的使用没有帮助。如果我正确理解spalloc(),当我在spalloc中设置nzmx时,矩阵D的内存将不会重新分配。顺便说一句,我有一个想法,从I=N:-1:1运行for循环,只计算距离矩阵的下三角部分。@Disc:实际上,稀疏矩阵(与MATLAB中的所有其他数组类型一样)会在需要更多空间时动态扩展容量(因此,底层的
pr
ir
jc
阵列将被重新分配)。当然,如果重复执行此操作,则会带来性能成本(和内存碎片)这就是为什么为
nzmax
选择一个合适的值非常重要,该值足够大,以减少重新分配的次数,但不能太大,以至于超出并保留实际需要的更多内存(如我们所说,在这种情况下,完整矩阵可能大于总可用RAM)现在你是对的,我们可以通过只填充距离矩阵的一半(下半部分或上半部分)来进一步改进第一个代码,实现起来应该不会太难。注意:我认为如果你对I=1:N使用
,或者对I=N:-1:1使用
,那么矩阵在一开始就已经预先分配好了。。
d = pdist(locs, @great_circle_distance);
[i, j] = find(tril(true(n), -1)); % extract index below main diagonal
d = d';
a = [i, j, d];
con = d == 0;   % specify condition. 
a(con, :) = [];   % delete rows satisfying condition con.
clear i j d;
i = a(:, 1);
j = a(:, 2);
d = a(:, 3);
dist_mat = sparse(i, j, d);
% given some data (longitude/latitude)
locs = rand(N,2);    % N = 10^5 in your case

% pick an appropriate size (guesstimate the number of nonzeros in the sparse mat)
nzmx = ...;

% compute pairwise-distance matrix (only those satisfying some condition)
D = spalloc(N, N, nzmx);
for i=1:N
    d = great_circle_distance(locs(i,:), locs);
    idx = find(100<d & d<400);   % distances in the range [100,400] km
    D(idx,i) = d(idx);
end
D = spalloc(N, N, nzmx);
for i=1:N-1
    d = great_circle_distance(locs(i,:), locs(i+1:end,:));
    idx = find(100<d & d<400);
    if isempty(idx), continue; end
    D(idx+i,i) = d(idx);
end