使用fortran生成可能组合的矩阵

时间:2013-01-28 23:10:39

标签: fortran

我有一个数组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 个答案:

答案 0 :(得分: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

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

答案 1 :(得分: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 

答案 2 :(得分:0)

确实有更好的方法。例如,请参阅Martin Broadhurst's combinatorial algorithms - 特别是笛卡尔积产品示例和文件n-tuple.c。尽管在C中,代码始终使用数组和引用参数,因此可以毫无困难地将其转换为Fortran,而不是将索引更改为从1开始而不是0.他使用的方法是使用索引数组向上计数。 / p>

答案 3 :(得分: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