Skip to content

Commit

Permalink
improve error message
Browse files Browse the repository at this point in the history
  • Loading branch information
hdavid16 committed Jan 18, 2024
1 parent 9ab25ae commit 47e9400
Showing 1 changed file with 45 additions and 40 deletions.
85 changes: 45 additions & 40 deletions src/bigm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,20 @@ end
function _get_tight_M(func::JuMP.AbstractJuMPScalar, set::_MOI.AbstractSet, method::BigM)
M = min.(method.value, _calculate_tight_M(func, set, method)) #broadcast for when S <: MOI.Interval or MOI.EqualTo or MOI.Zeros
if any(isinf.(M))
error("A finite Big-M value must be used. The value obtained was $M.")
error(
"A finite Big-M value could not be inferred from the variable bounds. " *
"If the model is linear, please check that all variables are bounded, or " *
"provide a finite Big-M value with `gdp_method = BigM(<value>). " *
"Note: inferring tight M values for nonlinear models is not currently supported."
)
end
return M
end

# Get user-specified Big-M value
function _get_M(
::JuMP.AbstractJuMPScalar,
::Union{_MOI.LessThan, _MOI.GreaterThan, _MOI.Nonnegatives, _MOI.Nonpositives},
::JuMP.AbstractJuMPScalar,
::Union{_MOI.LessThan, _MOI.GreaterThan, _MOI.Nonnegatives, _MOI.Nonpositives},
method::BigM
)
M = method.value
Expand All @@ -33,8 +38,8 @@ function _get_M(
return M
end
function _get_M(
::JuMP.AbstractJuMPScalar,
::Union{_MOI.Interval, _MOI.EqualTo, _MOI.Zeros},
::JuMP.AbstractJuMPScalar,
::Union{_MOI.Interval, _MOI.EqualTo, _MOI.Zeros},
method::BigM
)
M = method.value
Expand All @@ -46,36 +51,36 @@ end

# Apply interval arithmetic on a linear constraint to infer the tightest Big-M value from the bounds on the constraint.
function _calculate_tight_M(
func::JuMP.GenericAffExpr,
set::_MOI.LessThan,
func::JuMP.GenericAffExpr,
set::_MOI.LessThan,
method::BigM
)
return _interval_arithmetic_LessThan(func, -set.upper, method)
end
function _calculate_tight_M(
func::JuMP.GenericAffExpr,
set::_MOI.GreaterThan,
func::JuMP.GenericAffExpr,
set::_MOI.GreaterThan,
method::BigM
)
return _interval_arithmetic_GreaterThan(func, -set.lower, method)
end
function _calculate_tight_M(
func::JuMP.GenericAffExpr{C, V},
::_MOI.Nonpositives,
func::JuMP.GenericAffExpr{C, V},
::_MOI.Nonpositives,
method::BigM
) where {C, V}
return _interval_arithmetic_LessThan(func, zero(C), method)
end
function _calculate_tight_M(
func::JuMP.GenericAffExpr{C, V},
::_MOI.Nonnegatives,
func::JuMP.GenericAffExpr{C, V},
::_MOI.Nonnegatives,
method::BigM
) where {C, V}
return _interval_arithmetic_GreaterThan(func, zero(C), method)
end
function _calculate_tight_M(
func::JuMP.GenericAffExpr,
set::_MOI.Interval,
func::JuMP.GenericAffExpr,
set::_MOI.Interval,
method::BigM
)
return (
Expand All @@ -84,8 +89,8 @@ function _calculate_tight_M(
)
end
function _calculate_tight_M(
func::JuMP.GenericAffExpr,
set::_MOI.EqualTo,
func::JuMP.GenericAffExpr,
set::_MOI.EqualTo,
method::BigM
)
return (
Expand All @@ -94,8 +99,8 @@ function _calculate_tight_M(
)
end
function _calculate_tight_M(
func::JuMP.GenericAffExpr{C, V},
::_MOI.Zeros,
func::JuMP.GenericAffExpr{C, V},
::_MOI.Zeros,
method::BigM
) where {C, V}
return (
Expand All @@ -105,17 +110,17 @@ function _calculate_tight_M(
end
# fallbacks for other scalar constraints
function _calculate_tight_M(
func::Union{JuMP.GenericQuadExpr, JuMP.GenericNonlinearExpr},
set::Union{_MOI.Interval, _MOI.EqualTo, _MOI.Zeros},
func::Union{JuMP.GenericQuadExpr, JuMP.GenericNonlinearExpr},
set::Union{_MOI.Interval, _MOI.EqualTo, _MOI.Zeros},
method::BigM
)
return (Inf, Inf)
end
function _calculate_tight_M(
func::Union{JuMP.GenericQuadExpr, JuMP.GenericNonlinearExpr},
set::Union{_MOI.LessThan, _MOI.GreaterThan, _MOI.Nonnegatives, _MOI.Nonpositives},
func::Union{JuMP.GenericQuadExpr, JuMP.GenericNonlinearExpr},
set::Union{_MOI.LessThan, _MOI.GreaterThan, _MOI.Nonnegatives, _MOI.Nonpositives},
method::BigM
)
)
return Inf
end
function _calculate_tight_M(::F, ::S, ::BigM) where {F, S}
Expand Down Expand Up @@ -168,31 +173,31 @@ end

function reformulate_disjunct_constraint(
model::JuMP.AbstractModel,
con::JuMP.ScalarConstraint{T, S},
con::JuMP.ScalarConstraint{T, S},
bvref::JuMP.AbstractVariableRef,
method::BigM
) where {T, S <: _MOI.LessThan}
M = _get_M_value(con.func, con.set, method)
new_func = JuMP.@expression(model, con.func - M*(1-bvref))
reform_con = JuMP.build_constraint(error, new_func, con.set)
reform_con = JuMP.build_constraint(error, new_func, con.set)
return [reform_con]
end
function reformulate_disjunct_constraint(
model::JuMP.AbstractModel,
con::JuMP.VectorConstraint{T, S, R},
con::JuMP.VectorConstraint{T, S, R},
bvref::JuMP.AbstractVariableRef,
method::BigM
) where {T, S <: _MOI.Nonpositives, R}
M = [_get_M_value(func, con.set, method) for func in con.func]
new_func = JuMP.@expression(model, [i=1:con.set.dimension],
new_func = JuMP.@expression(model, [i=1:con.set.dimension],
con.func[i] - M[i]*(1-bvref)
)
reform_con = JuMP.build_constraint(error, new_func, con.set)
reform_con = JuMP.build_constraint(error, new_func, con.set)
return [reform_con]
end
function reformulate_disjunct_constraint(
model::JuMP.AbstractModel,
con::JuMP.ScalarConstraint{T, S},
model::JuMP.AbstractModel,
con::JuMP.ScalarConstraint{T, S},
bvref::JuMP.AbstractVariableRef,
method::BigM
) where {T, S <: _MOI.GreaterThan}
Expand All @@ -202,21 +207,21 @@ function reformulate_disjunct_constraint(
return [reform_con]
end
function reformulate_disjunct_constraint(
model::JuMP.AbstractModel,
con::JuMP.VectorConstraint{T, S, R},
model::JuMP.AbstractModel,
con::JuMP.VectorConstraint{T, S, R},
bvref::JuMP.AbstractVariableRef,
method::BigM
) where {T, S <: _MOI.Nonnegatives, R}
M = [_get_M_value(func, con.set, method) for func in con.func]
new_func = JuMP.@expression(model, [i=1:con.set.dimension],
new_func = JuMP.@expression(model, [i=1:con.set.dimension],
con.func[i] + M[i]*(1-bvref)
)
reform_con = build_constraint(error, new_func, con.set)
return [reform_con]
end
function reformulate_disjunct_constraint(
model::JuMP.AbstractModel,
con::JuMP.ScalarConstraint{T, S},
model::JuMP.AbstractModel,
con::JuMP.ScalarConstraint{T, S},
bvref::JuMP.AbstractVariableRef,
method::BigM
) where {T, S <: Union{_MOI.Interval, _MOI.EqualTo}}
Expand All @@ -229,16 +234,16 @@ function reformulate_disjunct_constraint(
return [reform_con_gt, reform_con_lt]
end
function reformulate_disjunct_constraint(
model::JuMP.AbstractModel,
con::JuMP.VectorConstraint{T, S, R},
model::JuMP.AbstractModel,
con::JuMP.VectorConstraint{T, S, R},
bvref::JuMP.AbstractVariableRef,
method::BigM
) where {T, S <: _MOI.Zeros, R}
M = [_get_M_value(func, con.set, method) for func in con.func]
new_func_nn = JuMP.@expression(model, [i=1:con.set.dimension],
new_func_nn = JuMP.@expression(model, [i=1:con.set.dimension],
con.func[i] + M[i][1]*(1-bvref)
)
new_func_np = JuMP.@expression(model, [i=1:con.set.dimension],
new_func_np = JuMP.@expression(model, [i=1:con.set.dimension],
con.func[i] - M[i][2]*(1-bvref)
)
reform_con_nn = JuMP.build_constraint(error, new_func_nn, _MOI.Nonnegatives(con.set.dimension))
Expand Down

0 comments on commit 47e9400

Please sign in to comment.