From fef88eb33123364c01cbea241ee097644ce31da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 10 Nov 2023 10:03:41 +0100 Subject: [PATCH] Add support for starting values --- src/MOI_wrapper.jl | 127 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 110 insertions(+), 17 deletions(-) diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index 1b0a763..14ed747 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -319,9 +319,57 @@ function _get_at_index( return _get(optimizer, attr, ci_primal, ci_dual)[idx] end +_minus(::Nothing) = nothing +_minus(x) = -x + +function _dual_attribute(attr::MOI.VariablePrimal) + return MOI.ConstraintDual(attr.result_index) +end + +function _dual_attribute(attr::MOI.VariablePrimalStart) + return MOI.ConstraintDualStart() +end + +function _dual_attribute(attr::MOI.ConstraintDual) + return MOI.ConstraintPrimal(attr.result_index) +end + +function _dual_attribute(attr::MOI.ConstraintDualStart) + return MOI.ConstraintPrimalStart() +end + +function _variable_dual_attribute(attr::MOI.ConstraintDual) + return MOI.VariablePrimal(attr.result_index) +end + +function _variable_dual_attribute(attr::MOI.ConstraintDualStart) + return MOI.VariablePrimalStart() +end + + +function MOI.set( + optimizer::DualOptimizer, + ::MOI.VariablePrimalStart, + vi::MOI.VariableIndex, + value, +) + primal_dual_map = optimizer.dual_problem.primal_dual_map + if vi in keys(primal_dual_map.constrained_var_idx) + error("Setting starting value for variables constrained at creation is not supported yet") + else + MOI.set( + optimizer.dual_problem.dual_model, + _dual_attribute(attr), + get_ci_dual_problem(optimizer, vi), + _minus(value), + ) + end + return +end + function MOI.get( optimizer::DualOptimizer, - ::MOI.VariablePrimal, + ::Union{MOI.VariablePrimal,MOI.VariablePrimalStart}, vi::MOI.VariableIndex, ) primal_dual_map = optimizer.dual_problem.primal_dual_map @@ -330,7 +378,7 @@ function MOI.get( ci_dual = primal_dual_map.constrained_var_dual[ci_primal] return _get_at_index( optimizer, - MOI.ConstraintDual(), + _dual_attribute(attr), ci_primal, ci_dual, idx, @@ -338,15 +386,35 @@ function MOI.get( else return -MOI.get( optimizer.dual_problem.dual_model, - MOI.ConstraintDual(), + _dual_attribute(attr), get_ci_dual_problem(optimizer, vi), ) end end +function MOI.set( + optimizer::DualOptimizer, + attr::MOI.ConstraintDualStart, + ci::MOI.ConstraintIndex, + value, +) + primal_dual_map = optimizer.dual_problem.primal_dual_map + if ci in keys(primal_dual_map.constrained_var_dual) + error("Setting starting value for variables constrained at creation is not supported yet") + else + MOI.set( + optimizer.dual_problem.dual_model, + _variable_dual_attribute(attr), + get_vi_dual_problem(optimizer, ci), + value, + ) + end + return +end + function MOI.get( optimizer::DualOptimizer, - attr::MOI.ConstraintDual, + attr::Union{MOI.ConstraintDual,MOI.ConstraintDualStart}, ci::MOI.ConstraintIndex{F,S}, ) where {F<:MOI.AbstractScalarFunction,S<:MOI.AbstractScalarSet} primal_dual_map = optimizer.dual_problem.primal_dual_map @@ -358,7 +426,7 @@ function MOI.get( ) do vi return MOI.get( optimizer.dual_problem.dual_model, - MOI.VariablePrimal(), + _variable_dual_attribute(attr), vi, ) end @@ -370,13 +438,13 @@ function MOI.get( ) return MOI.get( optimizer.dual_problem.dual_model, - MOI.ConstraintPrimal(), + _dual_attribute(attr), ci_dual, ) - MOI.constant(set) else return MOI.get( optimizer.dual_problem.dual_model, - MOI.VariablePrimal(), + _variable_dual_attribute(attr), get_vi_dual_problem(optimizer, ci), ) end @@ -384,7 +452,7 @@ end function MOI.get( optimizer::DualOptimizer, - ::MOI.ConstraintDual, + attr::Union{MOI.ConstraintDual,MOI.ConstraintDualStart}, ci::MOI.ConstraintIndex{F,S}, ) where {F<:MOI.AbstractVectorFunction,S<:MOI.AbstractVectorSet} primal_dual_map = optimizer.dual_problem.primal_dual_map @@ -396,35 +464,60 @@ function MOI.get( ) do vi return MOI.get( optimizer.dual_problem.dual_model, - MOI.VariablePrimal(), + _variable_dual_attribute(attr), vi, ) end end return MOI.get( optimizer.dual_problem.dual_model, - MOI.ConstraintPrimal(), + _dual_attribute(attr), primal_dual_map.constrained_var_dual[ci], ) else return MOI.get.( optimizer.dual_problem.dual_model, - MOI.VariablePrimal(), + _variable_dual_attribute(attr), get_vis_dual_problem(optimizer, ci), ) end end +function MOI.set( + optimizer::DualOptimizer, + attr::MOI.ConstraintPrimalStart, + ci::MOI.ConstraintIndex{F}, + value, +) where {F<:MOI.AbstractScalarFunction} + primal_dual_map = optimizer.dual_problem.primal_dual_map + if ci in keys(primal_dual_map.constrained_var_dual) + error("Setting starting value for variables constrained at creation is not supported yet") + elseif haskey(primal_dual_map.primal_con_dual_con, ci) + # If it has no key then there is no dual constraint + ci_dual_problem = get_ci_dual_problem(optimizer, ci) + if !isnothing(value) && (F <: MOI.AbstractScalarFunction) + value -= get_primal_ci_constant(optimizer, ci) + end + MOI.set( + optimizer.dual_problem.dual_model, + _dual_attribute(attr), + ci_dual_problem, + value, + ) + end + return +end + function MOI.get( optimizer::DualOptimizer, - ::MOI.ConstraintPrimal, + attr::Union{MOI.ConstraintPrimal,MOI.ConstraintPrimalStart}, ci::MOI.ConstraintIndex{F,S}, ) where {F<:MOI.AbstractScalarFunction,S<:MOI.AbstractScalarSet} primal_dual_map = optimizer.dual_problem.primal_dual_map if ci in keys(primal_dual_map.constrained_var_dual) return _get( optimizer, - MOI.ConstraintDual(), + _dual_attribute(attr), ci, primal_dual_map.constrained_var_dual[ci], ) @@ -437,7 +530,7 @@ function MOI.get( ci_dual_problem = get_ci_dual_problem(optimizer, ci) return MOI.get( optimizer.dual_problem.dual_model, - MOI.ConstraintDual(), + _dual_attribute(attr), ci_dual_problem, ) - primal_ci_constant end @@ -445,14 +538,14 @@ end function MOI.get( optimizer::DualOptimizer{T}, - ::MOI.ConstraintPrimal, + attr::Union{MOI.ConstraintPrimal,MOI.ConstraintPrimalStart}, ci::MOI.ConstraintIndex{F,S}, ) where {T,F<:MOI.AbstractVectorFunction,S<:MOI.AbstractVectorSet} primal_dual_map = optimizer.dual_problem.primal_dual_map if ci in keys(primal_dual_map.constrained_var_dual) return _get( optimizer, - MOI.ConstraintDual(), + _dual_attribute(attr), ci, primal_dual_map.constrained_var_dual[ci], ) @@ -466,7 +559,7 @@ function MOI.get( ci_dual_problem = get_ci_dual_problem(optimizer, ci) return MOI.get( optimizer.dual_problem.dual_model, - MOI.ConstraintDual(), + _dual_attribute(attr), ci_dual_problem, ) end