-
Notifications
You must be signed in to change notification settings - Fork 4
Support Multiple Big-M reformulation. #120
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
base: master
Are you sure you want to change the base?
Conversation
…eplace_variables_in_constraint() testcase hack.
deleting prior to merge to main branch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall pretty good, please generalize to work with the InfiniteOpt extension and add this to the docs.
src/mbm.jl
Outdated
method::MBM | ||
) where {T,S <: Union{_MOI.LessThan, _MOI.GreaterThan}} | ||
sub_model = JuMP.Model() | ||
new_vars = Dict{JuMP.VariableRef, JuMP.VariableRef}() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JuMP.Variable_ref_type ->get the type -> use that type
function _copy_variable( | ||
target_model::JuMP.AbstractModel, | ||
original_var::JuMP.AbstractVariableRef, | ||
) | ||
# Create new variable | ||
new_var = JuMP.@variable(target_model, base_name = JuMP.name(original_var)) | ||
|
||
# Copy all properties from original variable | ||
JuMP.has_lower_bound(original_var) && JuMP.set_lower_bound(new_var, JuMP.lower_bound(original_var)) | ||
JuMP.has_upper_bound(original_var) && JuMP.set_upper_bound(new_var, JuMP.upper_bound(original_var)) | ||
JuMP.has_start_value(original_var) && JuMP.set_start_value(new_var, JuMP.start_value(original_var)) | ||
JuMP.is_integer(original_var) && JuMP.set_integer(new_var) | ||
JuMP.is_binary(original_var) && JuMP.set_binary(new_var) | ||
|
||
# Handle fixed values with force=true (as in original MBM code) | ||
if JuMP.is_fixed(original_var) | ||
JuMP.fix(new_var, JuMP.fix_value(original_var); force=true) | ||
end | ||
|
||
return new_var | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new function differs from make_disaggregated_variable()
. The main difference is that instead of passing the variable attributes, I instead pass the variable itself and check for the attributes within this new function.
Why?
The alternative to this would be to have all attributes as possible inputs and default them to nothing
, but then the function would still need to check if the value is 'nothing'.
For example:
function _copy_variable(
target_model::JuMP.AbstractModel,
original_var::JuMP.AbstractVariableRef;
base_name::Union{String, Nothing} = nothing,
lower_bound::Union{Float64, Nothing} = nothing,
upper_bound::Union{Float64, Nothing} = nothing,
start_value::Union{Float64, Nothing} = nothing,
is_integer::Union{Bool, Nothing} = nothing,
is_binary::Union{Bool, Nothing} = nothing,
fixed_value::Union{Float64, Nothing} = nothing
)
# Create new variable with base name
var_name = base_name !== nothing ? base_name : JuMP.name(original_var)
new_var = JuMP.@variable(target_model, base_name = var_name)
# Set attributes if provided
lower_bound !== nothing && JuMP.set_lower_bound(new_var, lower_bound)
upper_bound !== nothing && JuMP.set_upper_bound(new_var, upper_bound)
start_value !== nothing && JuMP.set_start_value(new_var, start_value)
is_integer !== nothing && is_integer && JuMP.set_integer(new_var)
is_binary !== nothing && is_binary && JuMP.set_binary(new_var)
# Handle fixed value with force=true
if fixed_value !== nothing
JuMP.fix(new_var, fixed_value; force=true)
end
return new_var
end
This involved two checks, once before passing to the function, then one inside the function. So I thought just passing the variable to limit it to one check was better.
Let me know if there is a better way to do this, especially if I can make more akin to make_disaggregated_variable
.
VariableRef changed to AbstractVariableRef.
This PR adds the Multiple Big-M reformation technique. The technique can be called similar to BigM and Hull:
optimize!(model, gdp_method = MBM(Gurobi.Optimizer))
In
src/mbm.jl
are extensions forreformulate_disjunction
,_reformulate_disjunct
, andreformulate_disjunct_constraint
functions that dispatch over the new MBM datatype.Documentation to follow in another PR.