1

我有一个数组 X(9,2),我想用所有可能的组合生成另一个数组 B(512,9)。

我想过做 9 个循环,但我希望有一种更有效的方法。

这就是我所拥有的

    do i1=1, 2
    do i2=1, 2
        do i3=1,2
            do i4=1,2
                do i5=1,2
                    do i6=1,2
                        do i7=1,2
                            do i8=i,2
                                do i9=1,2
                                    B(row, col) = X(1,i1)
                                    col = col + 1
                                    B(row, col) = X(2,i2)
                                    col = col + 1
                                    B(row, col) = X(3,i3)
                                    col = col + 1
                                    B(row, col) = X(4,i4)
                                    col = col + 1
                                    B(row, col) = X(5,i5)
                                    col = col + 1
                                    B(row, col) = X(6,i6)
                                    col = col + 1
                                    B(row, col) = X(7,i7)
                                    col = col + 1
                                    B(row, col) = X(8,i8)
                                    col = col + 1
                                    B(row, col) = X(9,i9)
                                    col = 1
                                    row = row + 1
                                end do
                            end do
                        end do
                    end do
                end do
            end do
        end do
    end do
end do

这种方式有问题吗?有没有更好的方法来做到这一点?

谢谢!

4

4 回答 4

1

您应该通过循环 B 的元素来使循环反过来(我有一个 print 语句而不是赋值...):

 program test
  implicit none

  integer, parameter :: nn = 9, imax = 2
  integer :: row, col, ii
  integer :: indices(nn)

  indices(:) = 1
  do row = 1, imax**nn
    do col = 1, nn
      print "(A,I0,A,I0,A,I0,A,I0,A)", "B(", row, ",", col, ") = X(",&
          & col, ",", indices(col), ")"
      !B(row, col) = X(col, indices(col))
    end do
    indices(nn) = indices(nn) + 1
    ii = nn
    do while (ii > 1 .and. indices(ii) > imax)
      indices(ii) = 1
      indices(ii-1) = indices(ii-1) + 1
      ii = ii - 1
    end do
  end do

end program test

据我所知,这给出了与原始代码相同的结果,但更紧凑,适用于任何元组大小和索引范围。

于 2013-01-29T08:44:02.827 回答
1

我认为这也可以解决问题

ncol = 9
B = 0
tot = 2**ncol
do n = 1, ncol
   div = 2**n
   step = tot/div
   do m = 0, div-1
      fr = 1 + m*step
      to = fr + step
      B(fr:to,n) = X(n, 1+mod(m,2))
   end do
end do

do n = 1, tot
     write(*,*) (B(n,i), i=1,ncol)
end do 
于 2013-01-29T12:35:28.093 回答
0

确实有更好的方法。例如,参见Martin Broadhurst 的组合算法——特别是笛卡尔积示例和文件n-tuple.c。尽管在 C 中,代码始终使用数组和引用参数,因此除了将索引更改为从 1 开始而不是 0 之外,可以毫无困难地将其转换为 Fortran。他使用的方法是使用索引数组向上计数。

于 2013-01-29T00:08:45.443 回答
0
  character *70 ofil
  ofil='allcomb.txt'
  write(*,*)'feed n and m (Note: n or m larger than 20 takes time)'
  read(*,*) n,m
  write(*,*)'feed file name to store results'
  read(*,*) ofil
  call combin(n,m,ofil)
  write(*,*)'Over'
  end
  !---------------------------------------------------------------
  subroutine combin(n,m,ofil)
  ! Generates all ncm combinatins
  parameter (mx=20)! mx is maximum dimension
  Integer a(mx),b(mx),c
  double precision ncm,ic
  character *70 ofil
  open(15,file=ofil)
  ncm=1
    do i=1,m
    a(i)=i ! a is least indexed combination
    b(i)=n-m+i ! b is maximum indexed combination
    ncm=ncm*b(i)/i ! total possible combinations
    enddo
  write (15,*) (a(i),i=1,m)! Initial (least indexed) combination
  incmpl=1
  ic=1
  ! --------------------------------------------------------------
  do while (incmpl.ne.0 .and.int(ic).lt.ncm)
  incm=0
    do i=1,m
    incm=incm+(b(i)-a(i))
    enddo
  incmpl=incm
  a(m)=a(m)+1
    do i=1,m
    ii=m-i+1
      if(a(ii).gt.b(ii)) then
      a(ii-1)=a(ii-1)+1
         do j=ii,m
         a(j)=a(j-1)+1
         enddo
      endif
    enddo
  ic=ic+1
  write(15,*)(a(k),k=1,m)
  enddo ! end do while loop
  ! --------------------------------------------------------------
  close(15)
  return
  end
于 2017-03-29T07:55:18.423 回答