我正在编写备用网格代码,需要将N个1维网格点(以矢量形式编写)组合成所有可能点的数组。例如,可以将两个向量(a,b)与(c,d,e)混合,给出以下几点:
(a,c)(a,d)(a,e) (b,c)(b,d)(b,e)
Matlab有一个名为combvec的函数:
http://www.mathworks.co.uk/help/nnet/ref/combvec.html
我在FORTRAN中编写此代码但是我无法找到基础算法。该代码需要采用N(N> 1)个向量(即2,3 ... N),并且每个可以是不同的长度。有谁知道算法?
答案 0 :(得分:1)
我不知道Fortran,但是因为你说你找不到底层算法我假设一旦你知道算法就可以自己编写。实际上这很容易。伪代码将是这样的(假设没有重复):
index = 0 ! or 1
for each element in first vector
for each element in second vector
matrix(index,1) = current element of first vector
matrix(index,2) = current element of second vector
index = index + 1
end for
end for
这应该为您提供类似于使用combvec
获得的矩阵。
可能有更有效的方法来做到这一点,但由于我不知道Fortran的细节我不能帮助你。在Matlab中,你当然会对此进行矢量化。
祝你好运=)
答案 1 :(得分:0)
我认为以下功能可以做你想要的。它尽可能简单,将包含数据集的基数的秩1数组作为输入,并返回第2列数组,每组包含一列,包含该集合的索引。表达式1 + mod((i-1)/rep, N)
表示整数序列i
的{{1}}元素,每个元素重复1,2,...,N
次。
rep
假设您已经如下定义了动态长度向量,您可以直接获得组合矩阵:
! (requires explicit interface)
pure function cartprod(v) result(cp)
integer, intent(in) :: v(1:)
integer :: cp(product(v), size(v,1))
integer :: i, j, p, rep
p = product(v)
do j = 1, size(v,1)
rep = p / product(v(1:j))
do i = 1, p
cp(i,j) = 1 + mod((i-1)/rep, v(j))
enddo
enddo
end function
简短的测试程序:
module dynamic_vector
implicit none
type :: d_vector
integer, allocatable :: val(:)
end type
contains
pure function combvec(v) result(cv)
type(d_vector), intent(in) :: v(1:)
integer, allocatable :: cv(:,:)
integer :: i, j, prod, rep, len, sizes(size(v,1))
len = size(v,1)
! Determine sizes of the vectors, loop is necessary because we may not
! reference v%val if v is an array and val is allocatable.
do i = 1, len
sizes(i) = size(v(i)%val,1)
enddo
prod = product(sizes)
! Allocate and fill the output matrix
allocate(cv(prod, len))
do j = 1, len
rep = prod / product(sizes(1:j))
do i = 1, prod
cv(i,j) = v(j)%val(1 + mod((i-1)/rep, sizes(j)))
enddo
enddo
end function
end module
结果:
program test
use dynamic_vector
implicit none
type(d_vector) :: foo(2)
integer :: i, bar(:,:)
allocatable :: bar
allocate(foo(1)%val, source = [1,2])
allocate(foo(2)%val, source = [3,4,5])
bar = combvec(foo)
write(*,'(2(I0,X))') (bar(i,:), i = 1, 6)
end program