【问题标题】:generate a matrix of possible combinations using fortran使用 fortran 生成可能组合的矩阵
【发布时间】:2017-03-29 15:55:18
【问题描述】:

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

这种方式有问题吗?有更好的方法吗?

谢谢!

【问题讨论】:

    标签: fortran


    【解决方案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
    

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

    【讨论】:

      【解决方案2】:

      我认为这也可以解决问题

      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 
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 谢谢西蒙!我不知道c,获取一些fortran代码有什么变化吗?
        • 我在 Fortran 中没有遇到任何合适的代码。不过,从 C 语言翻译一点也不难。您需要将for 循环更改为while 循环,并将++ 运算符从x++ 更改为x=x+1 等,否则Fortran 子例程看起来非常像C。你几乎可以这样做它通过尝试使用 Fortran 编译器编译 C 并仅修复编译器一一报告的语法错误。您可以为 Fortran 程序员找到一个很好的 C 入门(和快速)指南here
        【解决方案4】:
          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
        

        【讨论】:

        • 欢迎。解释你的代码总是好的。仅代码的答案是不受欢迎的,特别是如果它们超过几行。我知道这里还有其他答案没有过多解释,但它们很旧并且没有太多支持。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-28
        • 2011-06-20
        • 1970-01-01
        相关资源
        最近更新 更多