手动展开 3 个嵌套循环 (Julia)

Manually unrolling 3 nested loops (Julia)

这是 使用 for 循环将文字插入数组中的每个表达式的后续问题 。在那个问题中,我想在一个循环中插入一个一维表达式数组(向量)。使用已接受的答案:

julia> array_of_expr = Any[:(A * 5), :(B * 6 * T)]

julia> arglist = [:A; :B; :T]
julia> test_input = [1e5, 1e1, 100]

julia> @eval begin
        function interpolate_1by1($(arglist...))
            result_array = similar($array_of_expr)
            $((quote
                result_array[$i] = $(array_of_expr[i])
            end for i in 1:length(array_of_expr))...)
            return result_array
        end
    end

julia> interpolate_all(test_input...)
2-element Array{Float64,1}:
 500000.0
 6000.0

根据 ,假设我现在有一个表达式向量数组:

args = [:A, :B, :C]
args_typed = [:($s::Float64) for s in args]
    
big_expr_array = Array{Vector{Expr}}(undef, 3, 4)
    
big_expr_array[1, :] = [[:(A+B), :(C/A)], [:(B+1), :(A+C)], [:(B%5)], [:(C+7)]]
big_expr_array[2, :] = [[:(A*B+C), :(B*C+A)], [:(C/6), :(C+C)], [:(3*C)], [:(A%2)]]
big_expr_array[3, :] = [[:(A*C), :(A*B)], [:(A-6), :(B+C/A)], [:(B+2)], [:(C%3)]]

并且想要在给定一些参数的情况下计算所有表达式,而不丢失数组的整体结构。在我看来,我必须遍历数组中的 i 行、j 列和 k 元素(表达式向量)。

我尝试通过两种方式修改上一个问题的已接受答案,这两种方式都会产生错误:

@eval begin
    function looped_eval1($(args_typed...))

        result = similar($big_expr_array)
        $( (quote 
            $( (quote 
                $( (quote
                        # i = row, j = vector, k = specific expression
                        result[$i, $j][$k] = $(big_expr_array[i, j][k])
                    end for k in 1:length(big_expr_array[i, j]))...
                 ) 
                end for j in 1:size(big_expr_array)[2])...
             )
            end for i in 1:size(big_expr_array)[1])...
         )
    end
end

这会引发 UndefRefError: access to undefined reference.

第二个:

@eval begin
    function looped_eval2($(args_typed...))
        
        result = similar($big_expr_array)
        $( (quote (quote (quote
                              # i = row, j = vector, k = specific expression
                              result[$i, $j][$k] = $(big_expr_array[i, j][k])
                          end for k in 1:length(big_expr_array[i, j]))... 
                   end for j in 1:size(big_expr_array)[2])...
            end for i in 1:size(big_expr_array)[1])...
         )
    
    end
end

这会引发 syntax: "..." expression outside call around In[130]:5.

参数 A = 10、B = 20、C = 30 的期望结果示例:

big_expr_array[1, :] = [[30, 3], [21, 40], [0], [37]]
big_expr_array[2, :] = [[230, 610], [5, 60], [90], [0]]
big_expr_array[3, :] = [[300, 200], [4, 23], [22], [0]]

我应该如何编写手动循环展开以容纳这些嵌套数组?或者,是否有更优雅的方式来实现对所有这些表达式的求值并保持相同的数组结构?

(代码也可能正确地分配给 result——因为我卡在循环展开中,我不确定。)

这是有效的:

@eval begin                                                                                                                                                      
    function looped_eval2($(args_typed...))                                                                                                                                                                                                                                                                                       
        result = similar($big_expr_array, Vector{Float64})                                                                                                           
        result .= [[]]                                                                                                                                               
        $( (quote                                                                                                                                                                          
                # i = row, j = vector, k = specific expression                                                                                                 
                push!(result[$i, $j], $(expr))                                                                                                                           
            end                                                                                                                                                                                                                                                                                                                       
            for i in 1:size(big_expr_array, 1)                                                                                                                           
            for j in 1:size(big_expr_array, 2)                                                                                                                           
            for expr in big_expr_array[i, j]                                                                                                                                  
            )...                                                                                                                                                                                    
        )                                                                                                                                                           
        result                                                                                                                                                   
    end                                                                                                                                                      
end

需要对您之前的工作进行一些修改:

  • 您必须键入注释并初始化结果,否则当您尝试访问 result;
  • 的任何元素时会出现 UndefRefError
  • 展开循环时,只需要一个引号,所有 3 个循环都在引号之外,然后计算生成的整个表达式列表;
  • 因为你的 big_expr_array 里面的所有向量的大小都不一样,结果的类型有点复杂 (Matrix{Vector{Float}}) 并且你必须在里面使用 push!引用而不是直接定义值。

结果如你所愿:

julia> looped_eval2(10., 20., 30.)                                                                                                                           
3×4 Matrix{Vector{Float64}}:                                                                                                                                  
    [30.0, 3.0]     [21.0, 40.0]  [0.0]   [37.0]                                                                                                                 
    [230.0, 610.0]  [5.0, 60.0]   [90.0]  [0.0]                                                                                                                  
    [300.0, 200.0]  [4.0, 23.0]   [22.0]  [0.0]

相同代码的更好的 Julia 版本(根据 BenchmarkTools 稍好)是:

@eval begin                                                                                                                                                      
    function looped_eval3($(args_typed...))                                                                                                                                                                                                                                                                                       
        result = map(_ -> Float64[], $big_expr_array)                                                                                                                
        $( (quote                                                                                                                                                            
                # i = row, j = vector, k = specific expression                                                                                                               
                push!(result[$i], $(expr))                                                                                                                               
            end                                                                                                                                                          
            for (i, expr_l) in enumerate(big_expr_array)                                                                                                                 
            for expr in expr_l                                                                                                                                           
            )...                                                                                                                                                      
        )                                                                                                                                                           
        result                                                                                                                                                   
    end                                                                                                                                                      
end