Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
286 views
in Technique[技术] by (71.8m points)

Julia - How to cat UnitRanges and prevent bad type performance

For a variable i I have two UnitRanges 1:i-1 and i+1:n and I want only one UnitRange that would be their concatenation. My current workaround is doing vcat(1:i-1, i+1:n) but it will result an Array{Int} instead of a UnitRange{Int}.

This will finally gives red performance type with @code_warntype in the next minimal example:

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() 

Type performance result:

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

I have search Julia's document page on UnitRanges but couldn't find where it is told how should I cat them.

I tried other ways such as

  • @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)

without success.

question from:https://stackoverflow.com/questions/66066136/julia-how-to-cat-unitranges-and-prevent-bad-type-performance

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I guess this should work (no more red in @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

you should really test different options and see what's best in YOUR case


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...