-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
464 additions
and
661 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,40 @@ | ||
# function big_m_reformulation!(constr, bin_var, i, k, M) | ||
# if ismissing(k) | ||
# ref = constr | ||
# elseif k isa CartesianIndex | ||
# ref = constr[k] | ||
# else | ||
# ref = constr[k...] | ||
# end | ||
# if ismissing(M) | ||
# M = apply_interval_arithmetic(ref) | ||
# # @warn "No M value passed for $ref. M = $M was inferred from the variable bounds." | ||
# elseif !ismissing(k) && !isa(M,Real) | ||
# M = M[k] | ||
# end | ||
# if ref isa NonlinearConstraintRef | ||
# nonlinear_bigM(ref, bin_var, M, i) | ||
# elseif ref isa ConstraintRef | ||
# linear_bigM(ref, bin_var, M, i) | ||
# end | ||
# end | ||
""" | ||
big_m_reformulation!(constr::ConstraintRef, bin_var, M, i, j, k) | ||
Perform Big-M reformulation on a linear or quadratic constraint at index k of constraint j in disjunct i. | ||
big_m_reformulation!(constr::NonlinearConstraintRef, bin_var, M, i, j, k) | ||
Perform Big-M reformulaiton on a nonlinear constraint at index k of constraint j in disjunct i. | ||
big_m_reformulation!(constr::AbstractArray, bin_var, M, i, j, k) | ||
Perform Big-M reformulation on a constraint at index k of constraint j in disjunct i. | ||
""" | ||
function big_m_reformulation!(constr::ConstraintRef, bin_var, M, i, j, k) | ||
M = get_reform_param(M, i, j, k; constr) | ||
linear_bigM(constr, bin_var, M, i) | ||
bin_var_ref = constr.model[bin_var][i] | ||
add_to_function_constant(constr, -M) | ||
set_normalized_coefficient(constr, bin_var_ref , M) | ||
end | ||
function big_m_reformulation!(constr::NonlinearConstraintRef, bin_var, M, i, j, k) | ||
M = get_reform_param(M, i, j, k; constr) | ||
nonlinear_bigM(constr, bin_var, M, i) | ||
end | ||
big_m_reformulation!(constr::AbstractArray, bin_var, M, i, j, k) = | ||
big_m_reformulation(constr[k], bin_var, M, i, j, k) | ||
|
||
function linear_bigM(ref, bin_var, M, i) | ||
bin_var_ref = ref.model[bin_var][i] | ||
add_to_function_constant(ref, -M) | ||
set_normalized_coefficient(ref, bin_var_ref , M) | ||
end | ||
|
||
function nonlinear_bigM(ref, bin_var, M, i) | ||
#create symbolic variables (using Symbolics.jl) | ||
for var_ref in ref.model[:gdp_variable_refs] | ||
for var_ref in constr.model[:gdp_variable_refs] | ||
var_sym = Symbol(var_ref) | ||
eval(:(Symbolics.@variables($var_sym)[1])) | ||
end | ||
bin_var_sym = Symbol("$bin_var[$i]") | ||
λ = Num(Symbolics.Sym{Float64}(bin_var_sym)) | ||
|
||
#parse ref | ||
op, lhs, rhs = parse_NLconstraint(ref) | ||
replace_Symvars!(lhs, ref.model) #convert JuMP variables into Symbolic variables | ||
#parse constr | ||
op, lhs, rhs = parse_constraint(constr) | ||
replace_Symvars!(lhs, constr.model) #convert JuMP variables into Symbolic variables | ||
gx = eval(lhs) #convert the LHS of the constraint into a Symbolic expression | ||
gx = gx - M*(1-λ) #add bigM | ||
|
||
#update constraint | ||
replace_NLconstraint(ref, gx, op, rhs) | ||
end | ||
replace_constraint(constr, gx, op, rhs) | ||
end | ||
big_m_reformulation!(constr::AbstractArray, bin_var, M, i, j, k) = | ||
big_m_reformulation(constr[k], bin_var, M, i, j, k) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
""" | ||
apply_interval_arithmetic(constr) | ||
Apply interval arithmetic on a constraint to find the bounds on the constraint. | ||
""" | ||
function apply_interval_arithmetic(constr) | ||
#convert constraints into Expr to replace variables with interval sets and determine bounds | ||
constr_type, constr_func_expr, constr_rhs = parse_constraint(constr) | ||
#create a map of variables to their bounds | ||
interval_map = Dict() | ||
vars = all_variables(constr.model)#constr.model[:gdp_variable_constrs] | ||
obj_dict = object_dictionary(constr.model) | ||
bounds_dict = :variable_bounds_dict in keys(obj_dict) ? obj_dict[:variable_bounds_dict] : Dict() #NOTE: should pass as an keyword argument | ||
for var in vars | ||
LB, UB = get_bounds(var, bounds_dict) | ||
interval_map[string(var)] = LB..UB | ||
end | ||
constr_func_expr = replace_intevals!(constr_func_expr, interval_map) | ||
#get bounds on the entire expression | ||
func_bounds = eval(constr_func_expr) | ||
Mlo = func_bounds.lo - constr_rhs | ||
Mhi = func_bounds.hi - constr_rhs | ||
M = constr_type == :(<=) ? Mhi : Mlo | ||
isinf(M) && error("M parameter for $constr cannot be infered due to lack of variable bounds.") | ||
return M | ||
end | ||
|
||
""" | ||
get_bounds(var::VariableRef) | ||
Get bounds on a variable. | ||
get_bounds(var::VariableRef, bounds_dict::Dict) | ||
Get bounds on a variable. Check if a bounds dictionary has ben provided with bounds for that value. | ||
get_bounds(var::AbstractArray, bounds_dict::Dict, LB, UB) | ||
Update lower bound `LB` and upper bound `UB` on a variable container. | ||
get_bounds(var::Array{VariableRef}, bounds_dict::Dict) | ||
Get lower and upper bounds on a variable array. | ||
get_bounds(var::Containers.DenseAxisArray, bounds_dict::Dict) | ||
Get lower and upper bounds on a variable DenseAxisArray. | ||
get_gounds(var::Containers.SparseAxisArray, bounds_dict::Dict) | ||
Get lower and upper bounds on a variable SparseAxisArray. | ||
""" | ||
function get_bounds(var::VariableRef) | ||
LB = has_lower_bound(var) ? lower_bound(var) : (is_binary(var) ? 0 : -Inf) | ||
UB = has_upper_bound(var) ? upper_bound(var) : (is_binary(var) ? 1 : Inf) | ||
return LB, UB | ||
end | ||
function get_bounds(var::VariableRef, bounds_dict::Dict) | ||
if string(var) in keys(bounds_dict) | ||
return bounds_dict[string(var)] | ||
else | ||
return get_bounds(var) | ||
end | ||
end | ||
function get_bounds(var::AbstractArray, bounds_dict::Dict, LB, UB) | ||
#populate UB and LB | ||
for idx in eachindex(var) | ||
LB[idx], UB[idx] = get_bounds(var[idx], bounds_dict) | ||
end | ||
return LB, UB | ||
end | ||
function get_bounds(var::Array{VariableRef}, bounds_dict::Dict) | ||
#initialize | ||
LB, UB = zeros(size(var)), zeros(size(var)) | ||
return get_bounds(var, bounds_dict, LB, UB) | ||
end | ||
function get_bounds(var::Containers.DenseAxisArray, bounds_dict::Dict) | ||
#initialize | ||
LB = Containers.DenseAxisArray(zeros(size(var)), axes(var)...) | ||
UB = Containers.DenseAxisArray(zeros(size(var)), axes(var)...) | ||
return get_bounds(var, bounds_dict, LB, UB) | ||
end | ||
function get_gounds(var::Containers.SparseAxisArray, bounds_dict::Dict) | ||
#initialize | ||
idxs = keys(var.data) | ||
LB = Containers.SparseAxisArray(Dict(idx => 0. for idx in idxs)) | ||
UB = Containers.SparseAxisArray(Dict(idx => 0. for idx in idxs)) | ||
return get_bounds(var, bounds_dict, LB, UB) | ||
end |
Oops, something went wrong.
4124e18
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.
@JuliaRegistrator register
4124e18
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.
Registration pull request created: JuliaRegistries/General/60023
After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.
This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via: