@@ -23,3 +23,221 @@ function MOI.set(o::Optimizer, attr::MOI.NLPBlock, data::MOI.NLPBlockData)
23
23
end
24
24
return nothing
25
25
end
26
+
27
+ # MOI.ScalarNonlinearFunction
28
+
29
+ function MOI. get (:: Optimizer , :: MOI.ListOfSupportedNonlinearOperators )
30
+ return Symbol[:+ , :- , :* , :/ , :^ , :abs , :exp , :log , :sin , :cos , :sqrt ]
31
+ end
32
+
33
+ function MOI. supports_constraint (
34
+ :: Optimizer ,
35
+ :: Type{MOI.ScalarNonlinearFunction} ,
36
+ :: Type{S} ,
37
+ ) where {S<: BOUNDS }
38
+ return true
39
+ end
40
+
41
+ function MOI. add_constraint (
42
+ model:: Optimizer ,
43
+ f:: MOI.ScalarNonlinearFunction ,
44
+ s:: BOUNDS ,
45
+ )
46
+ allow_modification (model)
47
+ expr = NonlinExpr ()
48
+ root = _SCIPcreateExpr (model, f, expr)
49
+ l, u = bounds (model, s)
50
+ cons__ = Ref {Ptr{SCIP_CONS}} (C_NULL )
51
+ @SCIP_CALL SCIPcreateConsBasicNonlinear (model, cons__, " " , root[], l, u)
52
+ @SCIP_CALL SCIPaddCons (model, cons__[])
53
+ push! (model. inner. nonlinear_storage, expr)
54
+ cr = store_cons! (model. inner, cons__)
55
+ ci = MOI. ConstraintIndex {MOI.ScalarNonlinearFunction,typeof(s)} (cr. val)
56
+ register! (model, ci)
57
+ register! (model, cons (model, ci), cr)
58
+ return ci
59
+ end
60
+
61
+ function _SCIPcreateExpr (model:: Optimizer , f:: Real , expr:: NonlinExpr )
62
+ ret = Ref {Ptr{SCIP_EXPR}} (C_NULL )
63
+ @SCIP_CALL SCIPcreateExprValue (model, ret, f, C_NULL , C_NULL )
64
+ push! (expr. exprs, ret)
65
+ return ret
66
+ end
67
+
68
+ function _SCIPcreateExpr (
69
+ model:: Optimizer ,
70
+ f:: MOI.VariableIndex ,
71
+ expr:: NonlinExpr ,
72
+ )
73
+ ret = Ref {Ptr{SCIP_EXPR}} (C_NULL )
74
+ v = var (model, f)
75
+ @SCIP_CALL SCIPcreateExprVar (model, ret, v, C_NULL , C_NULL )
76
+ push! (expr. exprs, ret)
77
+ return ret
78
+ end
79
+
80
+ function _SCIPcreateExpr (
81
+ model:: Optimizer ,
82
+ f:: MOI.ScalarNonlinearFunction ,
83
+ expr:: NonlinExpr ,
84
+ )
85
+ ret = Ref {Ptr{SCIP_EXPR}} (C_NULL )
86
+ if f. head == :+
87
+ children = map (arg -> _SCIPcreateExpr (model, arg, expr)[], f. args)
88
+ @SCIP_CALL SCIPcreateExprSum (
89
+ model,
90
+ ret,
91
+ length (f. args), # int nchildren
92
+ children, # SCIP_EXPR **children,
93
+ ones (Float64, length (f. args)), # SCIP_REAL *coefficients
94
+ 0.0 , # SCIP_Real constant
95
+ C_NULL ,
96
+ C_NULL ,
97
+ )
98
+ elseif f. head == :*
99
+ x = map (arg -> _SCIPcreateExpr (model, arg, expr)[], f. args)
100
+ n = length (f. args)
101
+ @SCIP_CALL SCIPcreateExprProduct (model, ret, n, x, 1.0 , C_NULL , C_NULL )
102
+ elseif f. head == :/
103
+ # Convert x / y --> x * y^-1
104
+ @assert length (f. args) == 2
105
+ x = _SCIPcreateExpr (model, f. args[1 ], expr)[]
106
+ y = _SCIPcreateExpr (model, f. args[2 ], expr)[]
107
+ ret_y = Ref {Ptr{SCIP_EXPR}} (C_NULL )
108
+ @SCIP_CALL SCIPcreateExprPow (model, ret_y, y, - 1.0 , C_NULL , C_NULL )
109
+ push! (expr. exprs, ret_y)
110
+ xy = [x, ret_y[]]
111
+ @SCIP_CALL SCIPcreateExprProduct (model, ret, 2 , xy, 1.0 , C_NULL , C_NULL )
112
+ elseif f. head == :-
113
+ @assert 1 <= length (f. args) <= 2
114
+ children = map (arg -> _SCIPcreateExpr (model, arg, expr)[], f. args)
115
+ n = length (f. args)
116
+ coefficients = ones (Float64, n)
117
+ coefficients[end ] = - 1.0
118
+ @SCIP_CALL SCIPcreateExprSum (
119
+ model,
120
+ ret,
121
+ n,
122
+ children,
123
+ coefficients,
124
+ 0.0 ,
125
+ C_NULL ,
126
+ C_NULL ,
127
+ )
128
+ elseif f. head == :^
129
+ @assert length (f. args) == 2
130
+ if ! (f. args[2 ] isa Real)
131
+ throw (MOI. UnsupportedNonlinearOperator (f. head))
132
+ end
133
+ child = _SCIPcreateExpr (model, first (f. args), expr)
134
+ expon = convert (Float64, f. args[2 ])
135
+ @SCIP_CALL SCIPcreateExprPow (model, ret, child[], expon, C_NULL , C_NULL )
136
+ elseif f. head == :abs
137
+ child = _SCIPcreateExpr (model, only (f. args), expr)
138
+ @SCIP_CALL SCIPcreateExprAbs (model, ret, child[], C_NULL , C_NULL )
139
+ elseif f. head == :exp
140
+ child = _SCIPcreateExpr (model, only (f. args), expr)
141
+ @SCIP_CALL SCIPcreateExprExp (model, ret, child[], C_NULL , C_NULL )
142
+ elseif f. head == :log
143
+ child = _SCIPcreateExpr (model, only (f. args), expr)
144
+ @SCIP_CALL SCIPcreateExprLog (model, ret, child[], C_NULL , C_NULL )
145
+ elseif f. head == :sin
146
+ child = _SCIPcreateExpr (model, only (f. args), expr)
147
+ @SCIP_CALL SCIPcreateExprSin (model, ret, child[], C_NULL , C_NULL )
148
+ elseif f. head == :cos
149
+ child = _SCIPcreateExpr (model, only (f. args), expr)
150
+ @SCIP_CALL SCIPcreateExprCos (model, ret, child[], C_NULL , C_NULL )
151
+ elseif f. head == :sqrt
152
+ child = _SCIPcreateExpr (model, only (f. args), expr)
153
+ @SCIP_CALL SCIPcreateExprPow (model, ret, child[], 0.5 , C_NULL , C_NULL )
154
+ else
155
+ throw (MOI. UnsupportedNonlinearOperator (f. head))
156
+ end
157
+ push! (expr. exprs, ret)
158
+ return ret
159
+ end
160
+
161
+ function _SCIPcreateExpr (
162
+ model:: Optimizer ,
163
+ f:: MOI.ScalarAffineFunction ,
164
+ expr:: NonlinExpr ,
165
+ )
166
+ ret = Ref {Ptr{SCIP_EXPR}} (C_NULL )
167
+ n = length (f. terms)
168
+ children = map (f. terms) do term
169
+ return _SCIPcreateExpr (model, term. variable, expr)[]
170
+ end
171
+ coefficients = map (f. terms) do term
172
+ return convert (Float64, term. coefficient)
173
+ end
174
+ @SCIP_CALL SCIPcreateExprSum (
175
+ model,
176
+ ret,
177
+ n,
178
+ children,
179
+ coefficients,
180
+ f. constant,
181
+ C_NULL ,
182
+ C_NULL ,
183
+ )
184
+ push! (expr. exprs, ret)
185
+ return ret
186
+ end
187
+
188
+ function _SCIPcreateExpr (
189
+ model:: Optimizer ,
190
+ f:: MOI.ScalarQuadraticFunction ,
191
+ expr:: NonlinExpr ,
192
+ )
193
+ ret = Ref {Ptr{SCIP_EXPR}} (C_NULL )
194
+ children = map (f. affine_terms) do term
195
+ return _SCIPcreateExpr (model, term. variable, expr)[]
196
+ end
197
+ coefficients = map (f. affine_terms) do term
198
+ return convert (Float64, term. coefficient)
199
+ end
200
+ for term in f. quadratic_terms
201
+ ret_xy = Ref {Ptr{SCIP_EXPR}} (C_NULL )
202
+ x = _SCIPcreateExpr (model, term. variable_1, expr)
203
+ y = _SCIPcreateExpr (model, term. variable_2, expr)
204
+ scale = ifelse (term. variable_1 == term. variable_2, 0.5 , 1.0 )
205
+ @SCIP_CALL SCIPcreateExprProduct (
206
+ model,
207
+ ret_xy,
208
+ 2 ,
209
+ [x[], y[]],
210
+ 1.0 ,
211
+ C_NULL ,
212
+ C_NULL ,
213
+ )
214
+ push! (children, ret_xy[])
215
+ push! (coefficients, scale * term. coefficient)
216
+ push! (expr. exprs, ret_xy)
217
+ end
218
+ @SCIP_CALL SCIPcreateExprSum (
219
+ model,
220
+ ret,
221
+ length (children),
222
+ children,
223
+ coefficients,
224
+ f. constant,
225
+ C_NULL ,
226
+ C_NULL ,
227
+ )
228
+ push! (expr. exprs, ret)
229
+ return ret
230
+ end
231
+
232
+ function MOI. get (
233
+ o:: Optimizer ,
234
+ :: MOI.ConstraintPrimal ,
235
+ ci:: MOI.ConstraintIndex{MOI.ScalarNonlinearFunction} ,
236
+ )
237
+ _throw_if_invalid (o, ci)
238
+ c = cons (o, ci)
239
+ expr_ref = SCIPgetExprNonlinear (c)
240
+ sol = SCIPgetBestSol (o)
241
+ @SCIP_CALL SCIPevalExpr (o, expr_ref, sol, Clonglong (0 ))
242
+ return SCIPexprGetEvalValue (expr_ref)
243
+ end
0 commit comments