Skip to content

Commit ee34be8

Browse files
committed
track nested perspective functions to avoid issues
1 parent 7c1bf50 commit ee34be8

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

src/hull.jl

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ function hull_reformulation!(constr::ConstraintRef{<:AbstractModel, MOI.Constrai
1616
m = constr.model
1717
i = args[2] #get disjunct index
1818
bin_var_ref = m[bin_var][i]
19-
#replace each variable with its disaggregated version (skip disaggregated vars)
20-
for var_ref in filter!(!in(values(m.ext[:disaggregated_variables])), get_constraint_variables(constr))#setdiff(get_constraint_variables(constr), values(m.ext[:disaggregated_variables]))
21-
is_binary(var_ref) && continue #NOTE: binaries from nested disjunctions are not disaggregated and don't need to be swapped out
19+
#replace each variable with its disaggregated version (skip disaggregated vars and binaries)
20+
for var_ref in filter!(v -> !in(v, values(m.ext[:disaggregated_variables])) && !is_binary(v), get_constraint_variables(constr))#setdiff(get_constraint_variables(constr), values(m.ext[:disaggregated_variables]))
2221
# var_ref in values(m.ext[:disaggregated_variables]) && continue #disaggregated variables are not touched
2322
#get disaggregated variable reference
2423
var_name_i = name_disaggregated_variable(var_ref, bin_var, i)
@@ -36,11 +35,17 @@ function hull_reformulation!(constr::ConstraintRef{<:AbstractModel, MOI.Constrai
3635
set_normalized_coefficient(constr, bin_var_ref, -rhs) #add binary variable (same as multiplying rhs constant by binary variable)
3736
end
3837
function hull_reformulation!(constr::ConstraintRef, bin_var, eps, i, j, k)
38+
m = constr.model #get model
39+
if constr in values(m.ext[:perspective_functions]) #if constraint nested and was already reformulated, doesn't need to be reformulated again
40+
push!(m.ext[bin_var], constr)
41+
return
42+
end
3943
eps = get_reform_param(eps, i, j, k)
4044
#create symbolic variables (using Symbolics.jl)
4145
sym_vars = Dict(
42-
symbolic_variable(var_ref) => symbolic_variable(name_disaggregated_variable(var_ref, bin_var, i))
43-
for var_ref in get_constraint_variables(constr)
46+
symbolic_variable(var_ref) =>
47+
symbolic_variable(m.ext[:disaggregated_variables][name_disaggregated_variable(var_ref, bin_var, i)])
48+
for var_ref in filter!(v -> !in(v, values(m.ext[:disaggregated_variables])) && !is_binary(v), get_constraint_variables(constr))
4449
)
4550
ϵ = eps #epsilon parameter for perspective function (See Furman, Sawaya, Grossmann [2020] perspecive function)
4651
bin_var_sym = Symbol("$bin_var[$i]")
@@ -66,7 +71,8 @@ function hull_reformulation!(constr::ConstraintRef, bin_var, eps, i, j, k)
6671
pers_func = substitute(pers_func, Dict(FSG1 => (1-ϵ)*λ+ϵ,
6772
FSG2 => ϵ*(1-λ)))
6873
pers_func = simplify(pers_func)
69-
add_reformulated_constraint(constr, bin_var, pers_func, op, rhs)
74+
constr_str = string(constr)
75+
m.ext[:perspective_functions][constr_str] = add_reformulated_constraint(constr, bin_var, pers_func, op, rhs)
7076
end
7177
hull_reformulation!(constr::AbstractArray{<:ConstraintRef}, bin_var, eps, i, j, k) =
7278
hull_reformulation!(constr[k], bin_var, eps, i, j, k)

src/reformulate.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ function reformulate_disjunction(m::Model, disj...; bin_var, reformulation, para
1818
if !in(:disaggregated_variables, keys(m.ext))
1919
m.ext[:disaggregated_variables] = Dict{String,VariableRef}() #record disaggregated variables to avoid duplicating disaggregation (nested disjunctions)
2020
end
21+
if !in(:perspective_functions, keys(m.ext))
22+
m.ext[:perspective_functions] = Dict() #record previously added nonlinear perspective functions
23+
end
2124
disaggregate_variables(m, disj, bin_var)
2225
end
2326
reformulate_disjunction(m, disj, bin_var, reformulation, param)

0 commit comments

Comments
 (0)