/
univariate_milp_relaxation.jl
90 lines (80 loc) · 2.62 KB
/
univariate_milp_relaxation.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""
_check_consistency(formulation_info, num_vars)
Checks consistency between provided variables and partition sizes
"""
function _check_consistency(formulation_info::FormulationInfo, num_vars)::Bool
var = formulation_info.variables
if haskey(var, :z)
(length(var[:z]) == num_vars) && (return true)
end
return false
end
"""
_build_univariate_milp_relaxation!(m,x,y,function_data,pre_base_name)
Return a MILPRelaxation object with constraint and RHS information of the MILP
formulation of the polyhedral relaxation.
"""
function _build_univariate_milp_relaxation!(
m::JuMP.Model,
x::JuMP.VariableRef,
y::JuMP.VariableRef,
univariate_function_data::UnivariateFunctionData,
variable_pre_base_name::AbstractString,
reuse::FormulationInfo,
)::FormulationInfo
sec_vs, tan_vs = _collect_vertices(univariate_function_data)
formulation_info = FormulationInfo()
# create variables
num_vars = length(univariate_function_data.partition) - 1
reuse_variables = reuse.variables
is_consistent = _check_consistency(reuse, num_vars)
delta_1 =
formulation_info.variables[:delta_1] = JuMP.@variable(
m,
[1:num_vars],
lower_bound = 0.0,
upper_bound = 1.0,
base_name = variable_pre_base_name * "delta_1"
)
delta_2 =
formulation_info.variables[:delta_2] = JuMP.@variable(
m,
[1:num_vars],
lower_bound = 0.0,
upper_bound = 1.0,
base_name = variable_pre_base_name * "delta_2"
)
z =
(is_consistent) ? reuse_variables[:bin] :
JuMP.@variable(
m,
[1:num_vars],
binary = true,
base_name = variable_pre_base_name * "_z"
)
formulation_info.variables[:bin] = z
# add x constraints
JuMP.@constraint(
m,
x ==
sec_vs[1][1] + sum(
delta_1[i] * (tan_vs[i][1] - sec_vs[i][1]) +
delta_2[i] * (sec_vs[i+1][1] - sec_vs[i][1]) for i in 1:num_vars
)
)
# add y constraints
JuMP.@constraint(
m,
y ==
sec_vs[1][2] + sum(
delta_1[i] * (tan_vs[i][2] - sec_vs[i][2]) +
delta_2[i] * (sec_vs[i+1][2] - sec_vs[i][2]) for i in 1:num_vars
)
)
# add first delta constraint
JuMP.@constraint(m, delta_1[1] + delta_2[1] <= 1)
# add linking constraints between delta_1, delta_2 and z
JuMP.@constraint(m, [i = 2:num_vars], delta_1[i] + delta_2[i] <= z[i-1])
JuMP.@constraint(m, [i = 2:num_vars], z[i-1] <= delta_2[i-1])
return formulation_info
end