Julia - 如何分类 UnitRanges 并防止不良类型性能
Julia - How to cat UnitRanges and prevent bad type performance
对于一个变量 i
我有两个 UnitRanges 1:i-1
和 i+1:n
我只想要一个 UnitRange 来连接它们。我目前的解决方法是 vcat(1:i-1, i+1:n)
但它会导致 Array{Int}
而不是 UnitRange{Int}
.
这最终将在下一个最小示例中使用@code_warntype 给出红色性能类型:
using Gurobi, JuMP
function minimal_example()
milp = Model(() -> Gurobi.Optimizer())
@variable(milp, x[i=1:n, j=vcat(1:i-1, i+1:n)], Bin)
end
@code_warntype minimal_example()
键入性能结果:
Variables
#self#::Core.Compiler.Const(minimal_example, false)
#9::var"#9#13"
#10::var"#10#14"{Model}
#11::var"#11#15"
#12::var"#12#16"
milp::Model
##1226::JuMP.Containers.SparseAxisArray
x::JuMP.Containers.SparseAxisArray
Body::JuMP.Containers.SparseAxisArray
1 ─ (#9 = %new(Main.:(var"#9#13")))
│ %2 = #9::Core.Compiler.Const(var"#9#13"(), false)
│ (milp = Main.Model(%2))
│ JuMP._valid_model(milp, :milp)
│ JuMP._error_if_cannot_register(milp, :x)
│ %6 = JuMP.Containers.container::Core.Compiler.Const(JuMP.Containers.container, false)
│ %7 = Main.:(var"#10#14")::Core.Compiler.Const(var"#10#14", false)
│ %8 = Core.typeof(milp)::Core.Compiler.Const(Model, false)
│ %9 = Core.apply_type(%7, %8)::Core.Compiler.Const(var"#10#14"{Model}, false)
│ (#10 = %new(%9, milp))
│ %11 = #10::var"#10#14"{Model}
│ %12 = JuMP.Containers.nested::Core.Compiler.Const(JuMP.Containers.nested, false)
│ (#11 = %new(Main.:(var"#11#15")))
│ %14 = #11::Core.Compiler.Const(var"#11#15"(), false)
│ (#12 = %new(Main.:(var"#12#16")))
│ %16 = #12::Core.Compiler.Const(var"#12#16"(), false)
│ %17 = (%12)(%14, %16)::Core.Compiler.Const(JuMP.Containers.NestedIterator{Tuple{var"#11#15",var"#12#16"},JuMP.Containers.var"#20#22"}((var"#11#15"(), var"#12#16"()), JuMP.Containers.var"#20#22"()), false)
│ (##1226 = (%6)(%11, %17))
│ %19 = JuMP.object_dictionary(milp)::Dict{Symbol,Any}
│ %20 = ##1226::JuMP.Containers.SparseAxisArray
│ Base.setindex!(%19, %20, :x)
│ (x = ##1226)
│ %23 = ##1226::JuMP.Containers.SparseAxisArray
└── return %23
我在 UnitRanges 上搜索了 Julia 的文档页面,但找不到告诉我应该如何分类它们的位置。
我尝试了其他方法,例如
@variable(milp, x[i=1:n, j=[j for j in 1:n if i!=j]], Bin)
@variable(milp, x[i=1:n, j=UnitRange(vcat(1:i-1, i+1:n))], Bin)
没有成功。
A UnitRange
仅由其起点和终点定义。您提议的范围将跳过范围内的数字之一。所以,很明显,结果不能是 UnitRange
,甚至不能是 StepRange
.
我不知道有任何标准库范围执行此操作,因此您可能必须创建自己的自定义 SkipRange
(或其他一些适当的名称。)
我想这应该可行(@code_warntype
中不再是红色)
function minimal_example(n)
milp = Model()
x = Array{VariableRef}(undef, n, n)
for i in 1:n
x[i, 1:i-1] = @variable(milp, [1:i-1], Bin)
x[i, i+1:n] = @variable(milp, [i+1:n], Bin)
end
x
end
你真的应该测试不同的选项,看看什么最适合你的情况
对于一个变量 i
我有两个 UnitRanges 1:i-1
和 i+1:n
我只想要一个 UnitRange 来连接它们。我目前的解决方法是 vcat(1:i-1, i+1:n)
但它会导致 Array{Int}
而不是 UnitRange{Int}
.
这最终将在下一个最小示例中使用@code_warntype 给出红色性能类型:
using Gurobi, JuMP
function minimal_example()
milp = Model(() -> Gurobi.Optimizer())
@variable(milp, x[i=1:n, j=vcat(1:i-1, i+1:n)], Bin)
end
@code_warntype minimal_example()
键入性能结果:
Variables
#self#::Core.Compiler.Const(minimal_example, false)
#9::var"#9#13"
#10::var"#10#14"{Model}
#11::var"#11#15"
#12::var"#12#16"
milp::Model
##1226::JuMP.Containers.SparseAxisArray
x::JuMP.Containers.SparseAxisArray
Body::JuMP.Containers.SparseAxisArray
1 ─ (#9 = %new(Main.:(var"#9#13")))
│ %2 = #9::Core.Compiler.Const(var"#9#13"(), false)
│ (milp = Main.Model(%2))
│ JuMP._valid_model(milp, :milp)
│ JuMP._error_if_cannot_register(milp, :x)
│ %6 = JuMP.Containers.container::Core.Compiler.Const(JuMP.Containers.container, false)
│ %7 = Main.:(var"#10#14")::Core.Compiler.Const(var"#10#14", false)
│ %8 = Core.typeof(milp)::Core.Compiler.Const(Model, false)
│ %9 = Core.apply_type(%7, %8)::Core.Compiler.Const(var"#10#14"{Model}, false)
│ (#10 = %new(%9, milp))
│ %11 = #10::var"#10#14"{Model}
│ %12 = JuMP.Containers.nested::Core.Compiler.Const(JuMP.Containers.nested, false)
│ (#11 = %new(Main.:(var"#11#15")))
│ %14 = #11::Core.Compiler.Const(var"#11#15"(), false)
│ (#12 = %new(Main.:(var"#12#16")))
│ %16 = #12::Core.Compiler.Const(var"#12#16"(), false)
│ %17 = (%12)(%14, %16)::Core.Compiler.Const(JuMP.Containers.NestedIterator{Tuple{var"#11#15",var"#12#16"},JuMP.Containers.var"#20#22"}((var"#11#15"(), var"#12#16"()), JuMP.Containers.var"#20#22"()), false)
│ (##1226 = (%6)(%11, %17))
│ %19 = JuMP.object_dictionary(milp)::Dict{Symbol,Any}
│ %20 = ##1226::JuMP.Containers.SparseAxisArray
│ Base.setindex!(%19, %20, :x)
│ (x = ##1226)
│ %23 = ##1226::JuMP.Containers.SparseAxisArray
└── return %23
我在 UnitRanges 上搜索了 Julia 的文档页面,但找不到告诉我应该如何分类它们的位置。
我尝试了其他方法,例如
@variable(milp, x[i=1:n, j=[j for j in 1:n if i!=j]], Bin)
@variable(milp, x[i=1:n, j=UnitRange(vcat(1:i-1, i+1:n))], Bin)
没有成功。
A UnitRange
仅由其起点和终点定义。您提议的范围将跳过范围内的数字之一。所以,很明显,结果不能是 UnitRange
,甚至不能是 StepRange
.
我不知道有任何标准库范围执行此操作,因此您可能必须创建自己的自定义 SkipRange
(或其他一些适当的名称。)
我想这应该可行(@code_warntype
中不再是红色)
function minimal_example(n)
milp = Model()
x = Array{VariableRef}(undef, n, n)
for i in 1:n
x[i, 1:i-1] = @variable(milp, [1:i-1], Bin)
x[i, i+1:n] = @variable(milp, [i+1:n], Bin)
end
x
end
你真的应该测试不同的选项,看看什么最适合你的情况