Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.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
Fortran 求所有可能的半正定整数,其加权和等于某个整数_Fortran_Integer Arithmetic - Fatal编程技术网

Fortran 求所有可能的半正定整数,其加权和等于某个整数

Fortran 求所有可能的半正定整数,其加权和等于某个整数,fortran,integer-arithmetic,Fortran,Integer Arithmetic,我对fortran 90代码有问题。所以,我有n+1半正定整数k1,k2,k3千牛和千牛。现在,对于给定的n,我需要找到k1、k2、k3、千牛这样k1+2*k2+3*k3+…+n*kn=n。有人可能会考虑使用一个n级嵌套循环,每个循环从0运行到n,但实际上我将把这个代码放在一个子例程中,n(也就是说,k的数量)将作为这个子例程的输入。因此,如果我要使用嵌套循环,那么嵌套级别的数量应该是自动化的,我认为这在Fortran中很难做到(如果不是不可能的话)。有更好的方法解决这个问题吗?如果n非常小(比

我对fortran 90代码有问题。所以,我有
n+1
半正定整数
k1
k2
k3
<代码>千牛和<代码>千牛。现在,对于给定的
n
,我需要找到
k1
k2
k3
、<代码>千牛这样
k1+2*k2+3*k3+…+n*kn=n
。有人可能会考虑使用一个n级嵌套循环,每个循环从
0
运行到
n
,但实际上我将把这个代码放在一个子例程中,
n
(也就是说,
k
的数量)将作为这个子例程的输入。因此,如果我要使用嵌套循环,那么嵌套级别的数量应该是自动化的,我认为这在Fortran中很难做到(如果不是不可能的话)。有更好的方法解决这个问题吗?

如果
n
非常小(比如,5),我认为编写多维循环以获得满足k1+k2*2+…+的所需k向量(k1,k2,…,kn)更简单kn*n=n。否则,可以选择使用递归。示例代码可能如下所示(请注意,我们需要
recursive
关键字):

这里,我们可以看到,例如,对于n=4,kvec=[k1,k2,k3,k4]=[2,1,0,0]满足
k1+k2*2+k3*3+k4*4=2+1*2+0+0=4
。使用这些k向量,我们可以计算f(g(x))的n阶导数(如OP所述,如下所示)


为了了解递归是如何工作的,插入大量代码通常很有用 打印语句并监控变量的变化。例如,代码的“详细”版本可能如下所示(为了简单起见,我删除了早期拒绝的内容):

请注意,数组
kvec
kvelist
的值总是在递归调用进入和退出时保留。特别是,我们正在覆盖每个维度的
kvec
元素,以获得可能模式的完整列表(因此本质上相当于多维循环)。我们还注意到,
kvec
的值仅在最终递归级别(即,
ind=n
)有效


另一种方法是将递归调用重写为特定
n
的等效非递归调用。例如,
n=2的情况可以如下重写。这不依赖于递归,而是执行与上述代码相同的操作(对于
n=2
)。如果我们设想将
recur\u sub2
内联到
recur\u sub
,很明显这些例程相当于
k1
k2
上的二维循环

!! routine specific for n = 2
subroutine recur_sub( n, ind, kvec, kveclist, nvec )
    integer, intent(in)    :: n, ind
    integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
    integer  k1

    !! now ind == 1

    do k1 = 0, n
        kvec( ind ) = k1

        call recur_sub2( n, ind + 1, kvec, kveclist, nvec )  !! go to next index
    enddo

endsubroutine

!! routine specific for n = 2
subroutine recur_sub2( n, ind, kvec, kveclist, nvec )
    integer, intent(in)    :: n, ind
    integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
    integer  k2, ksum, t

    !! now ind == n == 2

    do k2 = 0, n
        kvec( ind ) = k2

        ksum = sum( [( kvec( t ) * t, t = 1, n )] )

        if ( ksum == 2 ) then
            nvec = nvec + 1
            if ( nvec > nvecmax ) stop "nvecmax too small"
            kveclist( :, nvec ) = kvec(:)    !! save k-vectors
        endif
    enddo

endsubroutine

附录

下面是f(g(x))的第n阶导数的“漂亮打印”例程(在Julia中)(只是为了好玩)。如有必要,请使用Fortran编写相应的例程(但请注意大n!)


如果
n
相当小(比如,5),我认为编写多维循环以获得满足k1+k2*2+…+的所需k向量(k1,k2,…,kn)更简单kn*n=n。否则,可以选择使用递归。示例代码可能如下所示(请注意,我们需要
recursive
关键字):

这里,我们可以看到,例如,对于n=4,kvec=[k1,k2,k3,k4]=[2,1,0,0]
满足
k1+k2*2+k3*3+k4*4=2+1*2+0+0=4
。使用这些k向量,我们可以计算f(g(x))的n阶导数(如OP所述,如下所示)


为了了解递归是如何工作的,插入大量代码通常很有用 打印语句并监控变量的变化。例如,代码的“详细”版本可能如下所示(为了简单起见,我删除了早期拒绝的内容):

请注意,数组
kvec
kvelist
的值总是在递归调用进入和退出时保留。特别是,我们正在覆盖每个维度的
kvec
元素,以获得可能模式的完整列表(因此本质上相当于多维循环)。我们还注意到,
kvec
的值仅在最终递归级别(即,
ind=n
)有效


另一种方法是将递归调用重写为特定
n
的等效非递归调用。例如,
n=2的情况可以如下重写。这不依赖于递归,而是执行与上述代码相同的操作(对于
n=2
)。如果我们设想将
recur\u sub2
内联到
recur\u sub
,很明显这些例程相当于
k1
k2
上的二维循环

!! routine specific for n = 2
subroutine recur_sub( n, ind, kvec, kveclist, nvec )
    integer, intent(in)    :: n, ind
    integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
    integer  k1

    !! now ind == 1

    do k1 = 0, n
        kvec( ind ) = k1

        call recur_sub2( n, ind + 1, kvec, kveclist, nvec )  !! go to next index
    enddo

endsubroutine

!! routine specific for n = 2
subroutine recur_sub2( n, ind, kvec, kveclist, nvec )
    integer, intent(in)    :: n, ind
    integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
    integer  k2, ksum, t

    !! now ind == n == 2

    do k2 = 0, n
        kvec( ind ) = k2

        ksum = sum( [( kvec( t ) * t, t = 1, n )] )

        if ( ksum == 2 ) then
            nvec = nvec + 1
            if ( nvec > nvecmax ) stop "nvecmax too small"
            kveclist( :, nvec ) = kvec(:)    !! save k-vectors
        endif
    enddo

endsubroutine

附录

下面是f(g(x))的第n阶导数的“漂亮打印”例程(在Julia中)(只是为了好玩)。如有必要,请使用Fortran编写相应的例程(但请注意大n!)


它也可以这样表述,但主要问题是让Fortran找到满足上述要求的所有可能的
ki
组合。这要么是拖拉,要么是作业。如果不是,你能解释一下你想做什么以及为什么吗?这既不是拖拉也不是家庭作业。我实际上在用所谓的Faa-di-Bruno公式计算函数f(g(x))对x的任意阶导数。如果你看一下表中的等式(1),你就会明白为什么我需要做我在帖子中解释的事情。但是为什么-不是什么?不管怎样,如果你是认真的,那就看看哪种方法可能是正确的。对于我的研究来说。它也可以这样表述,但主要的问题是让Fortran找到满足上述要求的所有可能的
ki
。这要么是trolling
recursive subroutine recur_sub( n, ind, kvec, kveclist, nvec )
    integer, intent(in)    :: n, ind
    integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
    integer  k, ksum, t, ind_next

    print *, "Top of recur_sub: ind = ", ind

    do k = 0, n

        kvec( ind ) = k
        print *, "ind = ", ind, " k = ", k, "kvec = ", kvec

        if ( ind < n ) then
            ind_next = ind + 1
            print *, "  > now going to the next level"
            call recur_sub( n, ind_next, kvec, kveclist, nvec )
            print *, "  > returned to the current level"
        endif
        if ( ind == n ) then
            ksum = sum( [( kvec( t ) * t, t = 1, n )] )

            if ( ksum == n ) then
                nvec = nvec + 1
                if ( nvec > nvecmax ) stop "nvecmax too small"
                kveclist( :, nvec ) = kvec(:)
            endif
        endif
    enddo

    print *, "Exiting recur_sub"
endsubroutine
 Top of recur_sub: ind =            1
 ind =            1  k =            0 kvec =            0           0
   > now going to the next level
 Top of recur_sub: ind =            2
 ind =            2  k =            0 kvec =            0           0
 ind =            2  k =            1 kvec =            0           1
 ind =            2  k =            2 kvec =            0           2
 Exiting recur_sub
   > returned to the current level
 ind =            1  k =            1 kvec =            1           2
   > now going to the next level
 Top of recur_sub: ind =            2
 ind =            2  k =            0 kvec =            1           0
 ind =            2  k =            1 kvec =            1           1
 ind =            2  k =            2 kvec =            1           2
 Exiting recur_sub
   > returned to the current level
 ind =            1  k =            2 kvec =            2           2
   > now going to the next level
 Top of recur_sub: ind =            2
 ind =            2  k =            0 kvec =            2           0
 ind =            2  k =            1 kvec =            2           1
 ind =            2  k =            2 kvec =            2           2
 Exiting recur_sub
   > returned to the current level
 Exiting recur_sub

 For n =            2
 kvec =            0           1
 kvec =            2           0
!! routine specific for n = 2
subroutine recur_sub( n, ind, kvec, kveclist, nvec )
    integer, intent(in)    :: n, ind
    integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
    integer  k1

    !! now ind == 1

    do k1 = 0, n
        kvec( ind ) = k1

        call recur_sub2( n, ind + 1, kvec, kveclist, nvec )  !! go to next index
    enddo

endsubroutine

!! routine specific for n = 2
subroutine recur_sub2( n, ind, kvec, kveclist, nvec )
    integer, intent(in)    :: n, ind
    integer, intent(inout) :: kvec(:), kveclist(:,:), nvec
    integer  k2, ksum, t

    !! now ind == n == 2

    do k2 = 0, n
        kvec( ind ) = k2

        ksum = sum( [( kvec( t ) * t, t = 1, n )] )

        if ( ksum == 2 ) then
            nvec = nvec + 1
            if ( nvec > nvecmax ) stop "nvecmax too small"
            kveclist( :, nvec ) = kvec(:)    !! save k-vectors
        endif
    enddo

endsubroutine
function recur_main( n )

    kvec = zeros( Int, n )       # [k1,k2,...,kn] (work vector)
    kveclist = Vector{Int}[]     # list of k-vectors (output)

    recur_sub( n, 1, kvec, kveclist )   # now entering recursion over {ki}...

    return kveclist
end

function recur_sub( n, i, kvec, kveclist )

    for ki = 0 : n
        kvec[ i ] = ki

        ksum = sum( kvec[ t ] * t for t = 1:i )  # k1 + k2*2 + ... + ki*i
        ksum > n && continue                     # early rejection

        if i < n
            recur_sub( n, i + 1, kvec, kveclist )   # go to the next index
        end
        if i == n && ksum == n
            push!( kveclist, copy( kvec ) )   # save k-vectors
        end
    end
end

function showderiv( n )

    kveclist = recur_main( n )

    println()
    println( "(f(g))_$(n) = " )

    fact( k ) = factorial( big(k) )

    for (term, kvec) in enumerate( kveclist )

        fac1 = div( fact( n ), prod( fact( kvec[ i ] ) for i = 1:n ) )
        fac2 = prod( fact( i )^kvec[ i ] for i = 1:n )
        coeff = div( fac1, fac2 )

        term  == 1 ? print( "   " )    : print( " + " )
        coeff == 1 ? print( " " ^ 15 ) : @printf( "%15i", coeff )  
        print( " (f$( sum( kvec ) ))" )

        for i = 1 : length( kvec )
            ki = kvec[ i ]
            if ki > 0
                print( "(g$( i ))" )
                ki > 1 && print( "^$( ki )" )
            end
        end
        println()
    end
end

#--- test ---
if false
for n = 1 : 4
    kveclist = recur_main( n )

    println( "\nFor n = ", n )
    for kvec in kveclist
        println( "kvec = ", kvec )
    end
end
end

showderiv( 1 )
showderiv( 2 )
showderiv( 3 )
showderiv( 4 )
showderiv( 5 )
showderiv( 8 )
showderiv( 10 )
(f(g))_1 = 
                   (f1)(g1)

(f(g))_2 = 
                   (f1)(g2)
 +                 (f2)(g1)^2

(f(g))_3 = 
                   (f1)(g3)
 +               3 (f2)(g1)(g2)
 +                 (f3)(g1)^3

(f(g))_4 = 
                   (f1)(g4)
 +               3 (f2)(g2)^2
 +               4 (f2)(g1)(g3)
 +               6 (f3)(g1)^2(g2)
 +                 (f4)(g1)^4

(f(g))_5 = 
                   (f1)(g5)
 +              10 (f2)(g2)(g3)
 +               5 (f2)(g1)(g4)
 +              15 (f3)(g1)(g2)^2
 +              10 (f3)(g1)^2(g3)
 +              10 (f4)(g1)^3(g2)
 +                 (f5)(g1)^5

(f(g))_8 = 
                   (f1)(g8)
 +              35 (f2)(g4)^2
 +              56 (f2)(g3)(g5)
 +              28 (f2)(g2)(g6)
 +             280 (f3)(g2)(g3)^2
 +             210 (f3)(g2)^2(g4)
 +             105 (f4)(g2)^4
 +               8 (f2)(g1)(g7)
 +             280 (f3)(g1)(g3)(g4)
 +             168 (f3)(g1)(g2)(g5)
 +             840 (f4)(g1)(g2)^2(g3)
 +              28 (f3)(g1)^2(g6)
 +             280 (f4)(g1)^2(g3)^2
 +             420 (f4)(g1)^2(g2)(g4)
 +             420 (f5)(g1)^2(g2)^3
 +              56 (f4)(g1)^3(g5)
 +             560 (f5)(g1)^3(g2)(g3)
 +              70 (f5)(g1)^4(g4)
 +             210 (f6)(g1)^4(g2)^2
 +              56 (f6)(g1)^5(g3)
 +              28 (f7)(g1)^6(g2)
 +                 (f8)(g1)^8

(f(g))_10 = 
                   (f1)(g10)
 +             126 (f2)(g5)^2
 +             210 (f2)(g4)(g6)
 +             120 (f2)(g3)(g7)
 +            2100 (f3)(g3)^2(g4)
 +              45 (f2)(g2)(g8)
 +            1575 (f3)(g2)(g4)^2
 +            2520 (f3)(g2)(g3)(g5)
 +             630 (f3)(g2)^2(g6)
 +            6300 (f4)(g2)^2(g3)^2
 +            3150 (f4)(g2)^3(g4)
 +             945 (f5)(g2)^5
 +              10 (f2)(g1)(g9)
 +            1260 (f3)(g1)(g4)(g5)
 +             840 (f3)(g1)(g3)(g6)
 +            2800 (f4)(g1)(g3)^3
 +             360 (f3)(g1)(g2)(g7)
 +           12600 (f4)(g1)(g2)(g3)(g4)
 +            3780 (f4)(g1)(g2)^2(g5)
 +           12600 (f5)(g1)(g2)^3(g3)
 +              45 (f3)(g1)^2(g8)
 +            1575 (f4)(g1)^2(g4)^2
 +            2520 (f4)(g1)^2(g3)(g5)
 +            1260 (f4)(g1)^2(g2)(g6)
 +           12600 (f5)(g1)^2(g2)(g3)^2
 +            9450 (f5)(g1)^2(g2)^2(g4)
 +            4725 (f6)(g1)^2(g2)^4
 +             120 (f4)(g1)^3(g7)
 +            4200 (f5)(g1)^3(g3)(g4)
 +            2520 (f5)(g1)^3(g2)(g5)
 +           12600 (f6)(g1)^3(g2)^2(g3)
 +             210 (f5)(g1)^4(g6)
 +            2100 (f6)(g1)^4(g3)^2
 +            3150 (f6)(g1)^4(g2)(g4)
 +            3150 (f7)(g1)^4(g2)^3
 +             252 (f6)(g1)^5(g5)
 +            2520 (f7)(g1)^5(g2)(g3)
 +             210 (f7)(g1)^6(g4)
 +             630 (f8)(g1)^6(g2)^2
 +             120 (f8)(g1)^7(g3)
 +              45 (f9)(g1)^8(g2)
 +                 (f10)(g1)^10