-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathlinear_constraints.jl
106 lines (90 loc) · 2.86 KB
/
linear_constraints.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# Copyright (c) 2018 Felipe Serrano, Miles Lubin, Robert Schwarz, and contributors
#
# Use of this source code is governed by an MIT-style license that can be found
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
# linear constraints
function MOI.supports_constraint(
o::Optimizer,
::Type{MOI.ScalarAffineFunction{Float64}},
::Type{<:BOUNDS},
)
true
end
function MOI.add_constraint(
o::Optimizer,
func::F,
set::S,
) where {F<:MOI.ScalarAffineFunction{Float64},S<:BOUNDS}
if func.constant != 0.0
throw(MOI.ScalarFunctionConstantNotZero{Float64,F,S}(func.constant))
end
allow_modification(o)
varrefs = [VarRef(t.variable.value) for t in func.terms]
coefs = [t.coefficient for t in func.terms]
lhs, rhs = bounds(set)
lhs = lhs === nothing ? -SCIPinfinity(o) : lhs
rhs = rhs === nothing ? SCIPinfinity(o) : rhs
cr = add_linear_constraint(o.inner, varrefs, coefs, lhs, rhs)
ci = MOI.ConstraintIndex{F,S}(cr.val)
register!(o, ci)
register!(o, cons(o, ci), cr)
return ci
end
function MOI.set(
o::SCIP.Optimizer,
::MOI.ConstraintSet,
ci::MOI.ConstraintIndex{<:MOI.ScalarAffineFunction{Float64},S},
set::S,
) where {S<:BOUNDS}
allow_modification(o)
lhs, rhs = bounds(set)
lhs = lhs === nothing ? -SCIPinfinity(o) : lhs
rhs = rhs === nothing ? SCIPinfinity(o) : rhs
@SCIP_CALL SCIPchgLhsLinear(o, cons(o, ci), lhs)
@SCIP_CALL SCIPchgRhsLinear(o, cons(o, ci), rhs)
return nothing
end
function MOI.get(
o::Optimizer,
::MOI.ConstraintFunction,
ci::MOI.ConstraintIndex{<:MOI.ScalarAffineFunction{Float64},S},
) where {S<:BOUNDS}
_throw_if_invalid(o, ci)
c = cons(o, ci)
nvars::Int = SCIPgetNVarsLinear(o, c)
vars = unsafe_wrap(Array{Ptr{SCIP_VAR}}, SCIPgetVarsLinear(o, c), nvars)
vals = unsafe_wrap(Array{Float64}, SCIPgetValsLinear(o, c), nvars)
orig_vars = get_original_variables(vars, nvars)
terms = [
MOI.ScalarAffineTerm{Float64}(
vals[i],
MOI.VariableIndex(ref(o, orig_vars[i]).val),
) for i in 1:nvars
]
# can not identify constant anymore (is merged with lhs,rhs)
return MOI.ScalarAffineFunction{Float64}(terms, 0.0)
end
function MOI.get(
o::Optimizer,
::MOI.ConstraintSet,
ci::MOI.ConstraintIndex{<:MOI.ScalarAffineFunction{Float64},S},
) where {S<:BOUNDS}
_throw_if_invalid(o, ci)
lhs = SCIPgetLhsLinear(o, cons(o, ci))
rhs = SCIPgetRhsLinear(o, cons(o, ci))
return from_bounds(S, lhs, rhs)
end
function MOI.modify(
o::Optimizer,
ci::MOI.ConstraintIndex{<:MOI.ScalarAffineFunction{Float64},<:BOUNDS},
change::MOI.ScalarCoefficientChange{Float64},
)
allow_modification(o)
@SCIP_CALL SCIPchgCoefLinear(
o,
cons(o, ci),
var(o, change.variable),
change.new_coefficient,
)
return nothing
end