Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add POI.Parameters #40

Closed
wants to merge 1 commit into from
Closed

Add POI.Parameters #40

wants to merge 1 commit into from

Conversation

guilhermebodin
Copy link
Collaborator

This is a step towards solving #20
Now this works

optimizer = POI.ParametricOptimizer(GLPK.Optimizer())

model = direct_model(optimizer)

@variable(model, x[i=1:2] >= 0)

@variable(model, y[i=1:3] in POI.Parameters(zeros(3)))

@constraint(model, 2*x[1] + x[2] + y[1] <= 4)
@constraint(model, 1*x[1] + 2*x[2] + y[3] <= 4)

@objective(model, Max, 4*x[1] + 3*x[2] + y[2])

optimize!(model)

but this does not

model = Model(() -> POI.ParametricOptimizer(GLPK.Optimizer()));

@variable(model, x[i=1:2] >= 0);
@variable(model, y[i=1:3] in POI.Parameters(zeros(3)))

@constraint(model, 2*x[1] + x[2] + y[1] <= 4)
@constraint(model, 1*x[1] + 2*x[2] + y[3] <= 4)

@objective(model, Max, 4*x[1] + 3*x[2] + y[2])

optimize!(model)

The model gives the following error:

ERROR: MathOptInterface.UnsupportedConstraint{MathOptInterface.VectorOfVariables, ParametricOptInterface.Parameters}: `MathOptInterface.VectorOfVariables`-in-`ParametricOptInterface.Parameters` constraint is not supported by the model.
Stacktrace:
  [1] bridge_type(b::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ParametricOptInterface.ParametricOptimizer{Float64, GLPK.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}}}, S::Type{ParametricOptInterface.Parameters})
    @ MathOptInterface.Bridges C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Bridges\lazy_bridge_optimizer.jl:423
  [2] concrete_bridge_type
    @ C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Bridges\Variable\bridge.jl:248 [inlined]
  [3] add_constrained_variables(b::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ParametricOptInterface.ParametricOptimizer{Float64, GLPK.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}}}, set::ParametricOptInterface.Parameters)
    @ MathOptInterface.Bridges C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Bridges\bridge_optimizer.jl:1646
  [4] copy_vector_of_variables(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ParametricOptInterface.ParametricOptimizer{Float64, GLPK.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}}}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}, idxmap::MathOptInterface.Utilities.IndexMap, S::Type{ParametricOptInterface.Parameters}, copy_constrained_variables::typeof(MathOptInterface.add_constrained_variables))
    @ MathOptInterface.Utilities C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:335
  [5] try_constrain_variables_on_creation(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ParametricOptInterface.ParametricOptimizer{Float64, GLPK.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}}}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}, idxmap::MathOptInterface.Utilities.IndexMap, copy_constrained_variables::typeof(MathOptInterface.add_constrained_variables), copy_constrained_variable::typeof(MathOptInterface.add_constrained_variable))
    @ MathOptInterface.Utilities C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:619
  [6] default_copy_to(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.CachingOptimizer{ParametricOptInterface.ParametricOptimizer{Float64, GLPK.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}}}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}, copy_names::Bool, filter_constraints::Nothing)
    @ MathOptInterface.Utilities C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:691
  [7] #automatic_copy_to#127
    @ C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Utilities\copy.jl:24 [inlined]
  [8] #copy_to#4
    @ C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Bridges\bridge_optimizer.jl:401 [inlined]
  [9] attach_optimizer(model::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}})
    @ MathOptInterface.Utilities C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Utilities\cachingoptimizer.jl:185
 [10] optimize!(m::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}})
    @ MathOptInterface.Utilities C:\Users\guilhermebodin\.julia\packages\MathOptInterface\YDdD3\src\Utilities\cachingoptimizer.jl:248
 [11] optimize!(model::Model, optimizer_factory::Nothing; bridge_constraints::Bool, ignore_optimize_hook::Bool, kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ JuMP C:\Users\guilhermebodin\.julia\packages\JuMP\Xrr7O\src\optimizer_interface.jl:185
 [12] optimize! (repeats 2 times)
    @ C:\Users\guilhermebodin\.julia\packages\JuMP\Xrr7O\src\optimizer_interface.jl:157 [inlined]
 [13] top-level scope
    @ REPL[43]:1

@codecov
Copy link

codecov bot commented Jul 21, 2021

Codecov Report

Merging #40 (bf2489f) into master (be9bf86) will increase coverage by 0.22%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #40      +/-   ##
==========================================
+ Coverage   90.71%   90.94%   +0.22%     
==========================================
  Files           4        4              
  Lines         528      541      +13     
==========================================
+ Hits          479      492      +13     
  Misses         49       49              
Impacted Files Coverage Δ
src/ParametricOptInterface.jl 87.50% <100.00%> (+0.77%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update be9bf86...bf2489f. Read the comment docs.

@joaquimg
Copy link
Member

Not sure we should create another set for this.
Currently, we are able to create multiple variables in LessThan in jump which is a scalar set.

Maybe @odow has a suggestion for this...

If JuMP is doing something really different we should re-think the way forward and not add much complexity here.

@guilhermebodin
Copy link
Collaborator Author

@joaquimg indeed there is this version. It works on MOI but it does not work in JuMP, at least the way I tried.

using JuMP, ParametricOptInterface, MathOptInterface, GLPK

const POI = ParametricOptInterface
const MOI = MathOptInterface
n = 100

model = Model(() -> POI.ParametricOptimizer(GLPK.Optimizer()))

@variable(model, x[i=1:2] >= 0)
@variable(model, y[i=1:3] in POI.Parameter.(zeros(3)))

leads to

ERROR: MethodError: no method matching build_variable(::JuMP.var"#_error#108"{LineNumberNode}, ::Vector{ScalarVariable{Float64, Float64, Float64, Float64}}, ::Vector{ParametricOptInterface.Parameter})
Closest candidates are:
  build_variable(::Function, ::Vector{var"#s142"} where var"#s142"<:ScalarVariable, ::AbstractVectorSet) at C:\Users\guilhermebodin\.julia\packages\JuMP\Xrr7O\src\sets.jl:14
  build_variable(::Function, ::VariableInfo, ::Any...; kwargs...) at C:\Users\guilhermebodin\.julia\packages\JuMP\Xrr7O\src\macros.jl:1340
  build_variable(::Function, ::Vector{var"#s142"} where var"#s142"<:ScalarVariable, ::MathOptInterface.AbstractVectorSet) at C:\Users\guilhermebodin\.julia\packages\JuMP\Xrr7O\src\macros.jl:1356
  ...
Stacktrace:
 [1] macro expansion
   @ C:\Users\guilhermebodin\.julia\packages\JuMP\Xrr7O\src\macros.jl:142 [inlined]
 [2] top-level scope
   @ REPL[25]:1

@guilhermebodin
Copy link
Collaborator Author

@joaquimg Alternatively we can also make this work by adding these two methods

using JuMP, ParametricOptInterface, MathOptInterface, GLPK

const POI = ParametricOptInterface
const MOI = MathOptInterface
n = 100

function JuMP.build_variable(
    _error::Function,
    variables::Vector{<:ScalarVariable},
    sets::Vector{<:MOI.AbstractScalarSet},
)
    v = Vector{VariableConstrainedOnCreation}(undef, length(sets))
    for i in eachindex(variables)
        v[i] = VariableConstrainedOnCreation(variables[i], sets[i])
    end
    return v
end

function JuMP.add_variable(
    model::Model,
    variables::Vector{VariableConstrainedOnCreation},
    names,
)
    var_indices = Vector{MOI.VariableIndex}(undef, length(variables))
    for (i, variable) in enumerate(variables)
        var_indices[i] = JuMP._moi_add_constrained_variable(
            JuMP.backend(model),
            variable.scalar_variable,
            variable.set,
            names[i],
        )
    end
    return [JuMP.VariableRef(model, var_index) for var_index in var_indices]
end

model = Model(() -> POI.ParametricOptimizer(GLPK.Optimizer()))

@variable(model, x[i=1:2] >= 0)
@variable(model, y[i=1:3] in POI.Parameter.(zeros(3)))

@constraint(model, 2*x[1] + x[2] + y[1] <= 4)
@constraint(model, 1*x[1] + 2*x[2] + y[3] <= 4)

@objective(model, Max, 4*x[1] + 3*x[2] + y[2])

optimize!(model)

And this would also be possible

@variable(model, z[i=1:3] in MOI.LessThan.(zeros(3)))

@guilhermebodin guilhermebodin requested a review from odow July 21, 2021 17:28
@joaquimg
Copy link
Member

It might be that JuMP is missing those functions. I just don't know if they are not there on purpose.

@joaquimg
Copy link
Member

strongly related discussion: jump-dev/JuMP.jl#2148

@guilhermebodin
Copy link
Collaborator Author

guilhermebodin commented Aug 8, 2021

@joaquimg it works on your branch of JuMP

(ParametricOptInterface) pkg> st
     Project ParametricOptInterface v0.1.1
      Status `C:\Users\guilhermebodin\Documents\Github\ParametricOptInterface.jl\Project.toml`
  [4076af6c] JuMP v0.21.9 `https://github.com/jump-dev/JuMP.jl.git#jg/at_var`
  [b8f27783] MathOptInterface v0.9.22

julia> 

julia> model = Model(() -> POI.ParametricOptimizer(GLPK.Optimizer()));

julia> 

julia> @variable(model, x[i=1:2] >= 0)
2-element Vector{VariableRef}:
 x[1]
 x[2]

julia> @variable(model, y[i=1:3] in POI.Parameter.([1.0, 2.0, 3.0]))
3-element Vector{VariableRef}:
 y[1]
 y[2]
 y[3]

julia> 

julia> @constraint(model, 2*x[1] + x[2] + y[1] <= 4)
2 x[1] + x[2] + y[1] <= 4.0

julia> @constraint(model, 1*x[1] + 2*x[2] + y[3] <= 4)
x[1] + 2 x[2] + y[3] <= 4.0

julia> 

julia> @objective(model, Max, 4*x[1] + 3*x[2] + y[2])
4 x[1] + 3 x[2] + y[2]

julia> 

julia> optimize!(model)

@guilhermebodin
Copy link
Collaborator Author

Closing this because either we go on with jump-dev/JuMP.jl#2657 or define it outside the package for now.

@guilhermebodin guilhermebodin deleted the poi_parameters branch April 5, 2022 22:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants