Skip to content

Commit d074ecf

Browse files
committed
split nonlinearconstraint without parsing to Expr
1 parent 7ebd400 commit d074ecf

File tree

2 files changed

+35
-52
lines changed

2 files changed

+35
-52
lines changed

src/constraint.jl

Lines changed: 35 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function check_constraint!(m::Model, constr_j::ConstraintRef, constr_list::Vecto
3737
end
3838
function check_constraint!(m::Model, constr::ConstraintRef)
3939
@assert all(is_valid(m, constr)) "$constr is not a valid constraint."
40-
new_constr = split_constraint(m, constr)
40+
new_constr = split_constraint(constr)
4141
if isnothing(new_constr)
4242
new_constr = constr
4343
else
@@ -53,7 +53,7 @@ function check_constraint!(m::Model, constr::AbstractArray{<:ConstraintRef})
5353
idxs = get_indices(constr)
5454
constr_dict = Dict(union(
5555
[
56-
split_constraint(m, constr[idx...]) |>
56+
split_constraint(constr[idx...]) |>
5757
i -> isnothing(i) ?
5858
(idx...,"") => constr[idx...] :
5959
[(idx...,"lb") => i[1], (idx...,"ub") => i[2]]
@@ -68,75 +68,59 @@ end
6868
check_constraint!(m::Model, constr::Nothing) = nothing
6969

7070
"""
71-
split_constraint(m::Model, constr::NonlinearConstraintRef)
71+
split_constraint(constr::ConstraintRef)
7272
73-
Split a nonlinear constraint that is an Interval or EqualTo constraint.
74-
75-
split_constraint(m::Model, constr::ConstraintRef, constr_name::String = name(constr))
76-
77-
Split a linear or quadratic constraint.
78-
79-
split_constraint(m::Model, constr_obj::ScalarConstraint, lb_name::String, ub_name::String)
80-
81-
Split a constraint that is a MOI.EqualTo or MOI.Interval.
82-
83-
split_constraint(m::Model, func::Union{AffExpr,QuadExpr}, lb::Float64, ub::Float64, lb_name::String, ub_name::String)
84-
85-
Create split constraint for linear or quadratic constraint.
86-
87-
split_constraint(m::Model, constr::ConstraintRef, constr_func_expr::Expr, lb::Float64, ub::Float64)
88-
89-
Split a nonlinear constraint.
73+
Split a constraint that is an Interval or EqualTo constraint.
9074
9175
split_constraint(args...)
9276
9377
Return nothing for an empty disjunct.
9478
"""
95-
function split_constraint(m::Model, constr::NonlinearConstraintRef)
96-
constr_expr = Meta.parse(string(constr))
97-
if is_equalto(constr) #replace == for lb <= expr <= ub and split
98-
lb, ub = 0, 0#rhs is always 0, but could get obtained from: constr_expr.args[3]
99-
constr_func_expr = copy(constr_expr.args[2])
100-
return split_constraint(m, constr_func_expr, lb, ub)
101-
elseif is_interval(constr) #split lb <= expr <= ub
102-
lb = constr_expr.args[1]
103-
ub = constr_expr.args[5]
104-
constr_func_expr = copy(constr_expr.args[3]) #get func part of constraint
105-
return split_constraint(m, constr_func_expr, lb, ub)
79+
function split_constraint(constr::ConstraintRef)
80+
constr_set = constraint_set(constr)
81+
if is_equalto(constr)
82+
lb = ub = constr_set.value
83+
return _split_constraint(constr.model, constr, lb, ub)
84+
elseif is_interval(constr)
85+
lb = constr_set.lower
86+
ub = constr_set.upper
87+
return _split_constraint(constr.model, constr, lb, ub)
10688
else
10789
return nothing
10890
end
10991
end
110-
function split_constraint(m::Model, constr::ConstraintRef, constr_name::String = name(constr))
92+
function _split_constraint(m::Model, constr::NonlinearConstraintRef, lb::Float64, ub::Float64)
93+
nlp = nonlinear_model(m)
94+
nlconstr = nlp[index(constr)]
95+
#add lb constraint
96+
nlp.last_constraint_index += 1
97+
index1 = MOI.Nonlinear.ConstraintIndex(nlp.last_constraint_index)
98+
nlp.constraints[index1] =
99+
MOI.Nonlinear.Constraint(nlconstr.expression, MOI.LessThan(ub))
100+
#add ub constraint
101+
nlp.last_constraint_index += 1
102+
index2 = MOI.Nonlinear.ConstraintIndex(nlp.last_constraint_index)
103+
nlp.constraints[index2] =
104+
MOI.Nonlinear.Constraint(nlconstr.expression, MOI.GreaterThan(lb))
105+
106+
return [
107+
ConstraintRef(m, index1, constr.shape),
108+
ConstraintRef(m, index2, constr.shape)
109+
]
110+
end
111+
function _split_constraint(m::Model, constr::ConstraintRef, lb::Float64, ub::Float64)
112+
constr_name = name(constr)
111113
if isempty(constr_name)
112114
constr_name = "[$constr]"
113115
end
114116
lb_name = name_split_constraint(constr_name, :lb)
115117
ub_name = name_split_constraint(constr_name, :ub)
116-
constr_obj = constraint_object(constr)
117-
new_constraints = split_constraint(m, constr_obj, lb_name, ub_name)
118-
119-
return new_constraints
120-
end
121-
function split_constraint(m::Model, func::Union{AffExpr,QuadExpr}, lb::Float64, ub::Float64, lb_name::String, ub_name::String)
118+
func = constraint_object(constr).func
122119
return [
123120
@constraint(m, lb <= func, base_name = lb_name),
124121
@constraint(m, func <= ub, base_name = ub_name)
125122
]
126123
end
127-
function split_constraint(m::Model, constr_obj::ScalarConstraint{T,<:MOI.EqualTo}, lb_name::String, ub_name::String) where T
128-
split_constraint(m, constr_obj.func, constr_obj.set.value, constr_obj.set.value, lb_name, ub_name)
129-
end
130-
function split_constraint(m::Model, constr_obj::ScalarConstraint{T,<:MOI.Interval}, lb_name::String, ub_name::String) where T
131-
split_constraint(m, constr_obj.func, constr_obj.set.lower, constr_obj.set.upper, lb_name, ub_name)
132-
end
133-
function split_constraint(m::Model, constr_func_expr::Expr, lb::Real, ub::Real)
134-
replace_JuMPvars!(constr_func_expr, m) #replace Expr with JuMP vars
135-
return [
136-
add_nonlinear_constraint(m, :($lb <= $constr_func_expr)),
137-
add_nonlinear_constraint(m, :($constr_func_expr <= $ub))
138-
]
139-
end
140124
split_constraint(args...) = nothing
141125

142126
"""

src/utils.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ function name_split_constraint(con_name, side)
172172
else
173173
con_name = "$(con_name)[$side]"
174174
end
175-
176175
return con_name
177176
end
178177

0 commit comments

Comments
 (0)