Skip to content

Commit 4124e18

Browse files
committed
cleanup and add docstrings
1 parent 761adbd commit 4124e18

File tree

9 files changed

+464
-661
lines changed

9 files changed

+464
-661
lines changed

src/DisjunctiveProgramming.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export @disjunction, @proposition
77

88
include("constraint.jl")
99
include("logic.jl")
10+
include("bounds.jl")
1011
include("utils.jl")
1112
include("bigm.jl")
1213
include("hull.jl")

src/bigm.jl

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,40 @@
1-
# function big_m_reformulation!(constr, bin_var, i, k, M)
2-
# if ismissing(k)
3-
# ref = constr
4-
# elseif k isa CartesianIndex
5-
# ref = constr[k]
6-
# else
7-
# ref = constr[k...]
8-
# end
9-
# if ismissing(M)
10-
# M = apply_interval_arithmetic(ref)
11-
# # @warn "No M value passed for $ref. M = $M was inferred from the variable bounds."
12-
# elseif !ismissing(k) && !isa(M,Real)
13-
# M = M[k]
14-
# end
15-
# if ref isa NonlinearConstraintRef
16-
# nonlinear_bigM(ref, bin_var, M, i)
17-
# elseif ref isa ConstraintRef
18-
# linear_bigM(ref, bin_var, M, i)
19-
# end
20-
# end
1+
"""
2+
big_m_reformulation!(constr::ConstraintRef, bin_var, M, i, j, k)
213
4+
Perform Big-M reformulation on a linear or quadratic constraint at index k of constraint j in disjunct i.
5+
6+
big_m_reformulation!(constr::NonlinearConstraintRef, bin_var, M, i, j, k)
7+
8+
Perform Big-M reformulaiton on a nonlinear constraint at index k of constraint j in disjunct i.
9+
10+
big_m_reformulation!(constr::AbstractArray, bin_var, M, i, j, k)
11+
12+
Perform Big-M reformulation on a constraint at index k of constraint j in disjunct i.
13+
"""
2214
function big_m_reformulation!(constr::ConstraintRef, bin_var, M, i, j, k)
2315
M = get_reform_param(M, i, j, k; constr)
24-
linear_bigM(constr, bin_var, M, i)
16+
bin_var_ref = constr.model[bin_var][i]
17+
add_to_function_constant(constr, -M)
18+
set_normalized_coefficient(constr, bin_var_ref , M)
2519
end
2620
function big_m_reformulation!(constr::NonlinearConstraintRef, bin_var, M, i, j, k)
2721
M = get_reform_param(M, i, j, k; constr)
28-
nonlinear_bigM(constr, bin_var, M, i)
29-
end
30-
big_m_reformulation!(constr::AbstractArray, bin_var, M, i, j, k) =
31-
big_m_reformulation(constr[k], bin_var, M, i, j, k)
32-
33-
function linear_bigM(ref, bin_var, M, i)
34-
bin_var_ref = ref.model[bin_var][i]
35-
add_to_function_constant(ref, -M)
36-
set_normalized_coefficient(ref, bin_var_ref , M)
37-
end
38-
39-
function nonlinear_bigM(ref, bin_var, M, i)
4022
#create symbolic variables (using Symbolics.jl)
41-
for var_ref in ref.model[:gdp_variable_refs]
23+
for var_ref in constr.model[:gdp_variable_refs]
4224
var_sym = Symbol(var_ref)
4325
eval(:(Symbolics.@variables($var_sym)[1]))
4426
end
4527
bin_var_sym = Symbol("$bin_var[$i]")
4628
λ = Num(Symbolics.Sym{Float64}(bin_var_sym))
4729

48-
#parse ref
49-
op, lhs, rhs = parse_NLconstraint(ref)
50-
replace_Symvars!(lhs, ref.model) #convert JuMP variables into Symbolic variables
30+
#parse constr
31+
op, lhs, rhs = parse_constraint(constr)
32+
replace_Symvars!(lhs, constr.model) #convert JuMP variables into Symbolic variables
5133
gx = eval(lhs) #convert the LHS of the constraint into a Symbolic expression
5234
gx = gx - M*(1-λ) #add bigM
5335

5436
#update constraint
55-
replace_NLconstraint(ref, gx, op, rhs)
56-
end
37+
replace_constraint(constr, gx, op, rhs)
38+
end
39+
big_m_reformulation!(constr::AbstractArray, bin_var, M, i, j, k) =
40+
big_m_reformulation(constr[k], bin_var, M, i, j, k)

src/bounds.jl

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"""
2+
apply_interval_arithmetic(constr)
3+
4+
Apply interval arithmetic on a constraint to find the bounds on the constraint.
5+
"""
6+
function apply_interval_arithmetic(constr)
7+
#convert constraints into Expr to replace variables with interval sets and determine bounds
8+
constr_type, constr_func_expr, constr_rhs = parse_constraint(constr)
9+
#create a map of variables to their bounds
10+
interval_map = Dict()
11+
vars = all_variables(constr.model)#constr.model[:gdp_variable_constrs]
12+
obj_dict = object_dictionary(constr.model)
13+
bounds_dict = :variable_bounds_dict in keys(obj_dict) ? obj_dict[:variable_bounds_dict] : Dict() #NOTE: should pass as an keyword argument
14+
for var in vars
15+
LB, UB = get_bounds(var, bounds_dict)
16+
interval_map[string(var)] = LB..UB
17+
end
18+
constr_func_expr = replace_intevals!(constr_func_expr, interval_map)
19+
#get bounds on the entire expression
20+
func_bounds = eval(constr_func_expr)
21+
Mlo = func_bounds.lo - constr_rhs
22+
Mhi = func_bounds.hi - constr_rhs
23+
M = constr_type == :(<=) ? Mhi : Mlo
24+
isinf(M) && error("M parameter for $constr cannot be infered due to lack of variable bounds.")
25+
return M
26+
end
27+
28+
"""
29+
get_bounds(var::VariableRef)
30+
31+
Get bounds on a variable.
32+
33+
get_bounds(var::VariableRef, bounds_dict::Dict)
34+
35+
Get bounds on a variable. Check if a bounds dictionary has ben provided with bounds for that value.
36+
37+
get_bounds(var::AbstractArray, bounds_dict::Dict, LB, UB)
38+
39+
Update lower bound `LB` and upper bound `UB` on a variable container.
40+
41+
get_bounds(var::Array{VariableRef}, bounds_dict::Dict)
42+
43+
Get lower and upper bounds on a variable array.
44+
45+
get_bounds(var::Containers.DenseAxisArray, bounds_dict::Dict)
46+
47+
Get lower and upper bounds on a variable DenseAxisArray.
48+
49+
get_gounds(var::Containers.SparseAxisArray, bounds_dict::Dict)
50+
51+
Get lower and upper bounds on a variable SparseAxisArray.
52+
"""
53+
function get_bounds(var::VariableRef)
54+
LB = has_lower_bound(var) ? lower_bound(var) : (is_binary(var) ? 0 : -Inf)
55+
UB = has_upper_bound(var) ? upper_bound(var) : (is_binary(var) ? 1 : Inf)
56+
return LB, UB
57+
end
58+
function get_bounds(var::VariableRef, bounds_dict::Dict)
59+
if string(var) in keys(bounds_dict)
60+
return bounds_dict[string(var)]
61+
else
62+
return get_bounds(var)
63+
end
64+
end
65+
function get_bounds(var::AbstractArray, bounds_dict::Dict, LB, UB)
66+
#populate UB and LB
67+
for idx in eachindex(var)
68+
LB[idx], UB[idx] = get_bounds(var[idx], bounds_dict)
69+
end
70+
return LB, UB
71+
end
72+
function get_bounds(var::Array{VariableRef}, bounds_dict::Dict)
73+
#initialize
74+
LB, UB = zeros(size(var)), zeros(size(var))
75+
return get_bounds(var, bounds_dict, LB, UB)
76+
end
77+
function get_bounds(var::Containers.DenseAxisArray, bounds_dict::Dict)
78+
#initialize
79+
LB = Containers.DenseAxisArray(zeros(size(var)), axes(var)...)
80+
UB = Containers.DenseAxisArray(zeros(size(var)), axes(var)...)
81+
return get_bounds(var, bounds_dict, LB, UB)
82+
end
83+
function get_gounds(var::Containers.SparseAxisArray, bounds_dict::Dict)
84+
#initialize
85+
idxs = keys(var.data)
86+
LB = Containers.SparseAxisArray(Dict(idx => 0. for idx in idxs))
87+
UB = Containers.SparseAxisArray(Dict(idx => 0. for idx in idxs))
88+
return get_bounds(var, bounds_dict, LB, UB)
89+
end

0 commit comments

Comments
 (0)