-
Notifications
You must be signed in to change notification settings - Fork 94
Closed
Description
The following returns a StackOverflowError
due to deep recursion:
x = [i + i*MOI.VariableIndex(i) for i in 1:1000]
MOI.Utilities.operate(+, Int, x...)
operate
is used in SolverAPI.jl to convert from SNF to SAF or SQF when possible.
The proposed fix is to rewrite the following
MathOptInterface.jl/src/Utilities/operate.jl
Lines 323 to 327 in 53ec269
### 1c: operate(+, T, args...) | |
function operate(::typeof(+), ::Type{T}, f, g, h, args...) where {T<:Number} | |
return operate!(+, T, operate(+, T, f, g), h, args...) | |
end |
as (credit to @bachdavi for this solution):
function operate(::typeof(+), ::Type{T}, args...) where {T<:Number}
operate_plus(accum, x) = MOI.Utilities.operate!(+, T, accum, x)
return reduce(operate_plus, args)
end
Some tests shown below (Note: operate2
is the new form of operate
above):
# 100 ScalarAffineFunction args
julia> x = [i + i*MOI.VariableIndex(i) for i in 1:100];
julia> @time MOIU.operate(+, Int, x...);
0.000200 seconds (199 allocations: 46.078 KiB)
julia> @time MOIU.operate2(+, Int, x...);
0.000030 seconds (7 allocations: 6.797 KiB)
#--------------------------------------------------
# 1000 ScalarAffineFunction{Int} args
julia> x = [i + i*MOI.VariableIndex(i) for i in 1:1000];
julia> @time MOIU.operate(+, Int, x...);
ERROR: StackOverflowError:
julia> @time MOIU.operate2(+, Int, x...);
0.000093 seconds (9 allocations: 74.734 KiB)
#--------------------------------------------------
# 1000 ScalarAffineFunction{Float64} args
julia> x = [i + i*MOI.VariableIndex(i) for i in 1.0:1000.0];
julia> @time MOIU.operate2(+, Float64, x...);
0.000116 seconds (9 allocations: 74.734 KiB)
#--------------------------------------------------
# 1000 ScalarQuadraticFunction args
julia> x = [i + i*MOI.VariableIndex(i)*MOI.VariableIndex(i) for i in 1:1000];
julia> @time MOIU.operate(+, Int, x...);
ERROR: StackOverflowError:
julia> @time MOIU.operate2(+, Int, x...);
0.000105 seconds (5 allocations: 127.562 KiB)
#--------------------------------------------------
# 1000 mixed aff and quad args
julia> x = [i + i*MOI.VariableIndex(i)*MOI.VariableIndex(i) for i in 1:500];
julia> y = [i + i*MOI.VariableIndex(i) for i in 1:500];
julia> z = vcat(x,y);
julia> @time MOIU.operate(+, Int, z...);
ERROR: StackOverflowError:
julia> @time MOIU.operate2(+, Int, z...);
0.000126 seconds (6 allocations: 102.750 KiB)
Moving to higher number of affine function args:
Happy to submit a PR to MOI if desired.
chriscoey
Metadata
Metadata
Assignees
Labels
No labels