From 5caedabfee96a4a559c9554cd396c17bffbfa344 Mon Sep 17 00:00:00 2001 From: Dimitri Alston <123396563+DimitriAlston@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:28:38 -0500 Subject: [PATCH] Add support for `MOI.Parameter` --- src/eago_optimizer/moi_wrapper.jl | 9 ++++++++ src/eago_optimizer/optimizer.jl | 2 ++ src/eago_optimizer/parse.jl | 1 + src/eago_optimizer/types/global_optimizer.jl | 4 ++++ src/eago_optimizer/types/variable_info.jl | 22 ++++++++++++++++++++ 5 files changed, 38 insertions(+) diff --git a/src/eago_optimizer/moi_wrapper.jl b/src/eago_optimizer/moi_wrapper.jl index a1c0dafe..aeac4232 100644 --- a/src/eago_optimizer/moi_wrapper.jl +++ b/src/eago_optimizer/moi_wrapper.jl @@ -39,6 +39,7 @@ end MOI.supports_constraint(::Optimizer, ::Type{VI}, ::Type{S}) where S <: VAR_SETS = true MOI.supports_constraint(::Optimizer,::Type{T},::Type{S}) where {T<:Union{SAF,SQF,MOI.ScalarNonlinearFunction},S<:INEQ_SETS} = true +MOI.supports_add_constrained_variable(::Optimizer, ::Type{MOI.Parameter{Float64}}) = true MOI.is_valid(m::Optimizer, v::VI) = (1 <= v.value <= m._input_problem._variable_count) MOI.is_valid(m::Optimizer, c::CI{VI,S}) where S <: VAR_SETS = (1 <= c.value <= m._input_problem._variable_count) @@ -62,6 +63,14 @@ function MOI.add_variable(m::Optimizer, name::String) return vi end +function MOI.add_constrained_variable(m::Optimizer, p::MOI.Parameter{Float64}) + vi = VI(m._input_problem._variable_count += 1) + m._input_problem._variable_names[vi] = "" + ci = CI{VI, MOI.Parameter{Float64}}(m._input_problem._constraint_count += 1) + _constraints(m, VI, MOI.Parameter{Float64})[ci] = (vi, p) + return vi, ci +end + function MOI.add_constraint(m::Optimizer, f::F, s::S) where {F<:Union{SAF,SQF,MOI.ScalarNonlinearFunction},S<:INEQ_SETS} check_inbounds!(m, f) ci = CI{F, S}(m._input_problem._constraint_count += 1) diff --git a/src/eago_optimizer/optimizer.jl b/src/eago_optimizer/optimizer.jl index e3f04118..c37f237c 100644 --- a/src/eago_optimizer/optimizer.jl +++ b/src/eago_optimizer/optimizer.jl @@ -115,6 +115,8 @@ _constraints(m::Optimizer, ::Type{VI}, ::Type{IT}) = m._input_problem._vi_it_con _constraints(m::Optimizer, ::Type{VI}, ::Type{ZO}) = m._input_problem._vi_zo_constraints _constraints(m::Optimizer, ::Type{VI}, ::Type{INT}) = m._input_problem._vi_int_constraints +_constraints(m::Optimizer, ::Type{VI}, ::Type{MOI.Parameter{Float64}}) = m._input_problem._parameter_constraints + _constraints(m::Optimizer, ::Type{SAF}, ::Type{LT}) = _constraints(m._input_problem, SAF, LT) _constraints(m::Optimizer, ::Type{SAF}, ::Type{GT}) = _constraints(m._input_problem, SAF, GT) _constraints(m::Optimizer, ::Type{SAF}, ::Type{ET}) = _constraints(m._input_problem, SAF, ET) diff --git a/src/eago_optimizer/parse.jl b/src/eago_optimizer/parse.jl index b7d4391e..cd6db7d3 100644 --- a/src/eago_optimizer/parse.jl +++ b/src/eago_optimizer/parse.jl @@ -433,6 +433,7 @@ function initial_parse!(m::Optimizer{R,S,T}) where {R,S,T} variable_load_parse!(m, VI, ET) variable_load_parse!(m, VI, ZO) variable_load_parse!(m, VI, INT) + variable_load_parse!(m, VI, MOI.Parameter{Float64}) wp._variable_count = ip._variable_count # Copy all constraint dictionaries from the input problem to the working problem diff --git a/src/eago_optimizer/types/global_optimizer.jl b/src/eago_optimizer/types/global_optimizer.jl index c5c4eb6e..f5189c39 100644 --- a/src/eago_optimizer/types/global_optimizer.jl +++ b/src/eago_optimizer/types/global_optimizer.jl @@ -278,6 +278,8 @@ Base.@kwdef mutable struct InputProblem _vi_zo_constraints::Dict{CI{VI,ZO}, Tuple{VI,ZO}} = Dict{CI{VI,ZO}, Tuple{VI,ZO}}() _vi_int_constraints::Dict{CI{VI,INT}, Tuple{VI,INT}} = Dict{CI{VI,INT}, Tuple{VI,INT}}() + _parameter_constraints::Dict{CI{VI,MOI.Parameter{Float64}}, Tuple{VI,MOI.Parameter{Float64}}} = Dict{CI{VI,MOI.Parameter{Float64}}, Tuple{VI,MOI.Parameter{Float64}}}() + _linear_leq_constraints::Dict{CI{SAF,LT}, Tuple{SAF,LT}} = Dict{CI{SAF,LT}, Tuple{SAF,LT}}() _linear_geq_constraints::Dict{CI{SAF,GT}, Tuple{SAF,GT}} = Dict{CI{SAF,GT}, Tuple{SAF,GT}}() _linear_eq_constraints::Dict{CI{SAF,ET}, Tuple{SAF,ET}} = Dict{CI{SAF,ET}, Tuple{SAF,ET}}() @@ -368,6 +370,8 @@ _constraints(m::InputProblem, ::Type{VI}, ::Type{IT}) = m._vi_it_constraints _constraints(m::InputProblem, ::Type{VI}, ::Type{ZO}) = m._vi_zo_constraints _constraints(m::InputProblem, ::Type{VI}, ::Type{INT}) = m._vi_int_constraints +_constraints(m::InputProblem, ::Type{VI}, ::Type{MOI.Parameter{Float64}}) = m._parameter_constraints + _constraints(m::InputProblem, ::Type{SAF}, ::Type{LT}) = m._linear_leq_constraints _constraints(m::InputProblem, ::Type{SAF}, ::Type{GT}) = m._linear_geq_constraints _constraints(m::InputProblem, ::Type{SAF}, ::Type{ET}) = m._linear_eq_constraints diff --git a/src/eago_optimizer/types/variable_info.jl b/src/eago_optimizer/types/variable_info.jl index 3fbf875d..ee9fb343 100644 --- a/src/eago_optimizer/types/variable_info.jl +++ b/src/eago_optimizer/types/variable_info.jl @@ -191,9 +191,31 @@ function VariableInfo(v::VariableInfo{T}, s::INT) where {T <: AbstractFloat} upper_bound = u) end +function VariableInfo(v::VariableInfo{T}, p::MOI.Parameter{T}) where {T <: AbstractFloat} + isempty(v) && return v + l = max(p.value, lower_bound(v)) + u = min(p.value, upper_bound(v)) + check_isempty(l, u, is_integer(v)) && return empty_variable_info(T) + out = VariableInfo(is_integer = is_integer(v), + has_lower_bound = !isinf(l), + has_upper_bound = !isinf(u), + has_constraints = !isinf(l) | !isinf(u), + is_fixed = true, + lower_bound = l, + upper_bound = u) + return VariableInfo(is_integer = is_integer(v), + has_lower_bound = !isinf(l), + has_upper_bound = !isinf(u), + has_constraints = !isinf(l) | !isinf(u), + is_fixed = true, + lower_bound = l, + upper_bound = u) +end + ZO(v::VariableInfo) = MOI.ZeroOne() ET(v::VariableInfo{T}) where {T <: AbstractFloat} = MOI.EqualTo{T}(v.lower_bound) IT(v::VariableInfo{T}) where {T <: AbstractFloat} = MOI.Interval{T}(v.lower_bound,v.upper_bound) GT(v::VariableInfo{T}) where {T <: AbstractFloat} = MOI.GreaterThan{T}(v.lower_bound) LT(v::VariableInfo{T}) where {T <: AbstractFloat} = MOI.LessThan{T}(v.upper_bound) INT(v::VariableInfo{T}) where {T <: AbstractFloat} = MOI.Semiinteger{T}(v.lower_bound, v.upper_bound) +MOI.Parameter{Float64}(v::VariableInfo{T}) where {T <: AbstractFloat} = MOI.Parameter{T}(v.lower_bound)