From 0d1866f97632cc640d3e5466b85552755bba8de5 Mon Sep 17 00:00:00 2001 From: Hector Perez Date: Tue, 11 Jul 2023 22:25:46 -0400 Subject: [PATCH] close #64; add epsilon value for Hull --- examples/ex1.jl | 15 ++++++++++++++- src/datatypes.jl | 17 ++++++++++++++++- src/reformulate.jl | 46 ++++++++++++++++++++++++++++++++-------------- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/examples/ex1.jl b/examples/ex1.jl index 98368dc..ce66452 100644 --- a/examples/ex1.jl +++ b/examples/ex1.jl @@ -71,4 +71,17 @@ print(m) # x_Y[1] <= 10.0 # x_Y[2] <= 10.0 # Y[1] binary -# Y[2] binary \ No newline at end of file +# Y[2] binary + +## +DisjunctiveProgramming._reformulate(m, Indicator()) +print(m) +# Feasibility +# Subject to +# Y[2] => {x ≤ 9} +# x ≥ -5 +# x ≤ 10 +# Y[1] binary +# Y[2] binary +# Y[1] => {x ∈ [0, 3]} +# Y[2] => {x ≥ 5} \ No newline at end of file diff --git a/src/datatypes.jl b/src/datatypes.jl index fbaf39e..6951e3d 100644 --- a/src/datatypes.jl +++ b/src/datatypes.jl @@ -242,8 +242,23 @@ end # TODO add fields if needed A type for using the convex hull reformulation approach for disjunctive constraints. + +**Fields** +- `ϵ::Float64`: epsilon value for nonlinear hull reformulations. +""" +struct Hull <: AbstractReformulationMethod # TODO add fields if needed + ϵ::Float64 + function Hull(ϵ = 1e-6) + new(ϵ) + end +end + +""" + Indicator <: AbstractReformulationMethod + +A type for using indicator constraint approach for linear disjunctive constraints. """ -struct Hull <: AbstractReformulationMethod end # TODO add fields if needed +struct Indicator <: AbstractReformulationMethod end """ GDPData diff --git a/src/reformulate.jl b/src/reformulate.jl index ae8eed0..d6a8244 100644 --- a/src/reformulate.jl +++ b/src/reformulate.jl @@ -10,7 +10,7 @@ end """ """ -function _reformulate(model::JuMP.Model, method::BigM, disj::DisjunctiveConstraintData) +function _reformulate(model::JuMP.Model, method::Union{BigM,Indicator}, disj::DisjunctiveConstraintData) ind_var_dict = gdp_data(model).indicator_variables for d in disj.constraint.disjuncts #create binary variable for logic variable (indicator) @@ -86,7 +86,7 @@ function _reformulate( method::BigM, con::JuMP.ScalarConstraint{T, S}, bvar::JuMP.VariableRef - ) where {T, S <: _MOI.LessThan} +) where {T, S <: _MOI.LessThan} #TODO: need to pass _error to build_constraint M = _calculate_tight_M(con) if isinf(M) @@ -104,7 +104,7 @@ function _reformulate( method::BigM, con::JuMP.ScalarConstraint{T, S}, bvar::JuMP.VariableRef - ) where {T, S <: _MOI.GreaterThan} +) where {T, S <: _MOI.GreaterThan} #TODO: need to pass _error to build_constraint M = _calculate_tight_M(con) if isinf(M) @@ -122,7 +122,7 @@ function _reformulate( method::BigM, con::JuMP.ScalarConstraint{T, S}, bvar::JuMP.VariableRef - ) where {T, S <: _MOI.Interval} +) where {T, S <: _MOI.Interval} #TODO: need to pass _error to build_constraint M = _calculate_tight_M(con) if isinf(first(M)) @@ -149,7 +149,7 @@ function _reformulate( method::BigM, con::JuMP.ScalarConstraint{T, S}, bvar::JuMP.VariableRef - ) where {T, S <: _MOI.EqualTo} +) where {T, S <: _MOI.EqualTo} #TODO: need to pass _error to build_constraint M = _calculate_tight_M(con) if isinf(first(M)) @@ -177,10 +177,10 @@ end """ function _reformulate( model::JuMP.Model, - method::Hull, + ::Hull, con::JuMP.ScalarConstraint{JuMP.AffExpr, S}, bvar::JuMP.VariableRef - ) where {S <: _MOI.LessThan} +) where {S <: _MOI.LessThan} #TODO: need to pass _error to build_constraint con_func = _disaggregated_constraint(model, con, bvar) con_func.terms[bvar] = -con.set.upper @@ -194,10 +194,10 @@ function _reformulate( end function _reformulate( model::JuMP.Model, - method::Hull, + ::Hull, con::JuMP.ScalarConstraint{JuMP.AffExpr, S}, bvar::JuMP.VariableRef - ) where {S <: _MOI.GreaterThan} +) where {S <: _MOI.GreaterThan} #TODO: need to pass _error to build_constraint con_func = _disaggregated_constraint(model, con, bvar) con_func.terms[bvar] = -con.set.lower @@ -211,10 +211,10 @@ function _reformulate( end function _reformulate( model::JuMP.Model, - method::Hull, + ::Hull, con::JuMP.ScalarConstraint{JuMP.AffExpr, S}, bvar::JuMP.VariableRef - ) where {S <: _MOI.Interval} +) where {S <: _MOI.Interval} #TODO: need to pass _error to build_constraint con_func_GreaterThan = _disaggregated_constraint(model, con, bvar) con_func_LessThan = copy(con_func_GreaterThan) @@ -236,7 +236,7 @@ function _reformulate( end function _reformulate( model::JuMP.Model, - method::Hull, + ::Hull, con::JuMP.ScalarConstraint{JuMP.AffExpr, S}, bvar::JuMP.VariableRef ) where {S <: _MOI.EqualTo} @@ -251,12 +251,30 @@ function _reformulate( ) ) end + +""" + +""" +function _reformulate( + model::JuMP.Model, + ::Indicator, + con::JuMP.ScalarConstraint{JuMP.AffExpr, S}, + bvar::JuMP.VariableRef +) where {S} + JuMP.add_constraint(model, + JuMP.build_constraint(error, + [bvar, con.func], + _MOI.Indicator{_MOI.ACTIVATE_ON_ONE}(con.set) + ) + ) +end + # define fallbacks for other constraint types function _reformulate( - model::JuMP.Model, + ::JuMP.Model, method::AbstractReformulationMethod, con::JuMP.AbstractConstraint, - lvar::LogicalVariableRef + ::JuMP.VariableRef ) error("$method reformulation for constraint $con is not supported yet.") end \ No newline at end of file