@@ -9,6 +9,7 @@ mutable struct MathOptNLSModel <: AbstractNLSModel{Float64, Vector{Float64}}
99 linequ:: LinearEquations
1010 nlequ:: NonLinearStructure
1111 lincon:: LinearConstraints
12+ quadcon:: QuadraticConstraints
1213 nlcon:: NonLinearStructure
1314 counters:: NLSCounters
1415end
@@ -39,11 +40,11 @@ function MathOptNLSModel(cmodel::JuMP.Model, F; hessian::Bool = true, name::Stri
3940 Fnnzj = linequ. nnzj + nlequ. nnzj
4041 Fnnzh = nlequ. nnzh
4142
42- ncon = nlin + nnln
43- lcon = vcat (lin_lcon, nl_lcon)
44- ucon = vcat (lin_ucon, nl_ucon)
45- cnnzj = lincon. nnzj + nlcon. nnzj
46- cnnzh = lls. nnzh + nlcon. nnzh
43+ ncon = nlin + quadcon . nquad + nnln
44+ lcon = vcat (lin_lcon, quad_lcon, nl_lcon)
45+ ucon = vcat (lin_ucon, quad_ucon, nl_ucon)
46+ cnnzj = lincon. nnzj + quadcon . nnzj + nlcon. nnzj
47+ cnnzh = lls. nnzh + quadcon . nnzh + nlcon. nnzh
4748
4849 meta = NLPModelMeta (
4950 nvar,
@@ -58,7 +59,7 @@ function MathOptNLSModel(cmodel::JuMP.Model, F; hessian::Bool = true, name::Stri
5859 nnzh = cnnzh,
5960 lin = collect (1 : nlin),
6061 lin_nnzj = lincon. nnzj,
61- nln_nnzj = nlcon. nnzj,
62+ nln_nnzj = quadcon . nnzj + nlcon. nnzj,
6263 minimize = objective_sense (cmodel) == MOI. MIN_SENSE,
6364 islp = false ,
6465 name = name,
@@ -73,6 +74,7 @@ function MathOptNLSModel(cmodel::JuMP.Model, F; hessian::Bool = true, name::Stri
7374 linequ,
7475 nlequ,
7576 lincon,
77+ quadcon,
7678 nlcon,
7779 NLSCounters (),
7880 )
253255
254256function NLPModels. cons_nln! (nls:: MathOptNLSModel , x:: AbstractVector , c:: AbstractVector )
255257 increment! (nls, :neval_cons_nln )
256- MOI. eval_constraint (nls. ceval, c, x)
258+ for i = 1 : (nls. quadcon. nquad)
259+ qcon = nls. quadcon. constraints[i]
260+ c[i] = 0.5 * coo_sym_dot (qcon. A. rows, qcon. A. cols, qcon. A. vals, x, x) + dot (qcon. b, x)
261+ end
262+ if nls. meta. nnln > nls. quadcon. nquad
263+ MOI. eval_constraint (nls. ceval, view (c, (nls. quadcon. nquad + 1 ): (nls. meta. nnln)), x)
264+ end
257265 return c
258266end
259267
@@ -272,8 +280,20 @@ function NLPModels.jac_nln_structure!(
272280 rows:: AbstractVector{<:Integer} ,
273281 cols:: AbstractVector{<:Integer} ,
274282)
275- view (rows, 1 : (nls. nlcon. nnzj)) .= nls. nlcon. jac_rows
276- view (cols, 1 : (nls. nlcon. nnzj)) .= nls. nlcon. jac_cols
283+ if nls. quadcon. nquad > 0
284+ index = 0
285+ for i = 1 : (nls. quadcon. nquad)
286+ qcon = nls. quadcon. constraints[i]
287+ view (rows, index+ 1 : index+ qcon. nnzg) .= i
288+ view (cols, index+ 1 : index+ qcon. nnzg) .= qcon. g
289+ index += qcon. nnzg
290+ end
291+ end
292+ if nls. meta. nnln > nls. quadcon. nquad
293+ ind_nnln = (nls. quadcon. nnzj + 1 ): (nls. quadcon. nnzj + nls. nlcon. nnzj)
294+ view (rows, ind_nnln) .= nls. nlcon. jac_rows
295+ view (cols, ind_nnln) .= nls. nlcon. jac_cols
296+ end
277297 return rows, cols
278298end
279299
285305
286306function NLPModels. jac_nln_coord! (nls:: MathOptNLSModel , x:: AbstractVector , vals:: AbstractVector )
287307 increment! (nls, :neval_jac_nln )
288- MOI. eval_constraint_jacobian (nls. ceval, view (vals, 1 : (nls. nlcon. nnzj)), x)
308+ if nls. quadcon. nquad > 0
309+ index = 0
310+ view (vals, 1 : nls. quadcon. nnzj) .= 0.0
311+ for i = 1 : (nls. quadcon. nquad)
312+ qcon = nls. quadcon. constraints[i]
313+ for (j, ind) in enumerate (qcon. b. nzind)
314+ k = qcon. dg[ind]
315+ vals[index+ k] += qcon. b. nzval[j]
316+ end
317+ for j = 1 : qcon. nnzh
318+ row = qcon. A. rows[j]
319+ col = qcon. A. cols[j]
320+ val = qcon. A. vals[j]
321+ k1 = qcon. dg[row]
322+ vals[index+ k1] += val * x[col]
323+ if row != col
324+ k2 = qcon. dg[col]
325+ vals[index+ k2] += val * x[row]
326+ end
327+ end
328+ index += qcon. nnzg
329+ end
330+ end
331+ if nls. meta. nnln > nls. quadcon. nquad
332+ ind_nnln = (nls. quadcon. nnzj + 1 ): (nls. quadcon. nnzj + nls. nlcon. nnzj)
333+ MOI. eval_constraint_jacobian (nls. ceval, view (vals, ind_nnln), x)
334+ end
289335 return vals
290336end
291337
@@ -313,7 +359,18 @@ function NLPModels.jprod_nln!(
313359 Jv:: AbstractVector ,
314360)
315361 increment! (nls, :neval_jprod_nln )
316- MOI. eval_constraint_jacobian_product (nls. ceval, Jv, x, v)
362+ if nls. meta. nnln > nls. quadcon. nquad
363+ ind_nnln = (nls. quadcon. nquad + 1 ): (nls. meta. nnln)
364+ MOI. eval_constraint_jacobian_product (nls. ceval, view (Jv, ind_nnln), x, v)
365+ end
366+ (nls. meta. nnln == nls. quadcon. nquad) && (Jv .= 0.0 )
367+ if nls. quadcon. nquad > 0
368+ for i = 1 : (nls. quadcon. nquad)
369+ # Jv[i] = (Aᵢ * x + bᵢ)ᵀ * v
370+ qcon = nls. quadcon. constraints[i]
371+ v[i] += coo_sym_dot (qcon. A. rows, qcon. A. cols, qcon. A. vals, x, v) + dot (qcon. b, v)
372+ end
373+ end
317374 return Jv
318375end
319376
@@ -341,7 +398,19 @@ function NLPModels.jtprod_nln!(
341398 Jtv:: AbstractVector ,
342399)
343400 increment! (nls, :neval_jtprod_nln )
344- MOI. eval_constraint_jacobian_transpose_product (nls. ceval, Jtv, x, v)
401+ if nls. meta. nnln > nls. quadcon. nquad
402+ ind_nnln = (nls. quadcon. nquad + 1 ): (nls. meta. nnln)
403+ MOI. eval_constraint_jacobian_transpose_product (nls. ceval, Jtv, x, view (v, ind_nnln))
404+ end
405+ (nls. meta. nnln == nls. quadcon. nquad) && (Jtv .= 0.0 )
406+ if nls. quadcon. nquad > 0
407+ for i = 1 : (nls. quadcon. nquad)
408+ # Jtv += v[i] * (Aᵢ * x + bᵢ)
409+ qcon = nls. quadcon. constraints[i]
410+ coo_sym_add_mul! (rows, cols, vals, x, Jtv, v[i])
411+ Jtv .+ = v[i] .* qcon. b
412+ end
413+ end
345414 return Jtv
346415end
347416
@@ -354,9 +423,18 @@ function NLPModels.hess_structure!(
354423 view (rows, 1 : (nls. lls. nnzh)) .= nls. lls. hessian. rows
355424 view (cols, 1 : (nls. lls. nnzh)) .= nls. lls. hessian. cols
356425 end
357- if nls. nls_meta. nnln > 0
358- view (rows, (nls. lls. nnzh + 1 ): (nls. meta. nnzh)) .= nls. nlcon. hess_rows
359- view (cols, (nls. lls. nnzh + 1 ): (nls. meta. nnzh)) .= nls. nlcon. hess_cols
426+ if (nls. nls_meta. nnln > 0 ) || (nlp. meta. nnln > nlp. quadcon. nquad)
427+ view (rows, (nls. lls. nnzh + nlp. quadcon. nnzh + 1 ): (nls. meta. nnzh)) .= nls. nlcon. hess_rows
428+ view (cols, (nls. lls. nnzh + nlp. quadcon. nnzh + 1 ): (nls. meta. nnzh)) .= nls. nlcon. hess_cols
429+ end
430+ if nls. quadcon. nquad > 0
431+ index = nls. lls. nnzh
432+ for i = 1 : (nls. quadcon. nquad)
433+ qcon = nls. quadcon. constraints[i]
434+ view (rows, (index + 1 ): (index + qcon. nnzh)) .= qcon. A. rows
435+ view (cols, (index + 1 ): (index + qcon. nnzh)) .= qcon. A. cols
436+ index += qcon. nnzh
437+ end
360438 end
361439 return rows, cols
362440end
@@ -372,15 +450,24 @@ function NLPModels.hess_coord!(
372450 if nls. nls_meta. nlin > 0
373451 view (vals, 1 : (nls. lls. nnzh)) .= obj_weight .* nls. lls. hessian. vals
374452 end
375- if (nls. nls_meta. nnln > 0 ) || (nls. meta. nnln > 0 )
453+ if (nls. nls_meta. nnln > 0 ) || (nls. meta. nnln > nls. quadcon. nquad)
454+ λ = view (y, (nls. meta. nlin + nls. quadcon. nquad + 1 ): (nls. meta. ncon))
376455 MOI. eval_hessian_lagrangian (
377456 nls. ceval,
378- view (vals, (nls. lls. nnzh + 1 ): (nls. meta. nnzh)),
457+ view (vals, (nls. lls. nnzh + nls . quadcon . nnzh + 1 ): (nls. meta. nnzh)),
379458 x,
380459 obj_weight,
381- view (y, nls . meta . nln),
460+ λ
382461 )
383462 end
463+ if nls. quadcon. nquad > 0
464+ index = nls. lls. nnzh
465+ for i = 1 : (nls. quadcon. nquad)
466+ qcon = nls. quadcon. constraints[i]
467+ view (vals, (index + 1 ): (index + qcon. nnzh)) .= y[i] .* qcon. A. vals
468+ index += qcon. nnzh
469+ end
470+ end
384471 return vals
385472end
386473
@@ -394,16 +481,18 @@ function NLPModels.hess_coord!(
394481 if nls. nls_meta. nlin > 0
395482 view (vals, 1 : (nls. lls. nnzh)) .= obj_weight .* nls. lls. hessian. vals
396483 end
484+ view (vals, (nls. lls. nnzh + 1 ): (nls. lls. nnzh + nls. quadcon. nnzh)) .= 0.0
397485 if nls. nls_meta. nnln > 0
486+ λ = zeros (nlp. meta. nnln - nlp. quadcon. nquad) # Should be stored in the structure MathOptNLSModel
398487 MOI. eval_hessian_lagrangian (
399488 nls. ceval,
400- view (vals, (nls. lls. nnzh + 1 ): (nls. meta. nnzh)),
489+ view (vals, (nls. lls. nnzh + nls . quadcon . nnzh + 1 ): (nls. meta. nnzh)),
401490 x,
402491 obj_weight,
403- zeros (nls . meta . nnln) ,
492+ λ ,
404493 )
405494 else
406- view (vals, (nls. lls. nnzh + 1 ): (nls. meta. nnzh)) .= 0.0
495+ view (vals, (nls. lls. nnzh + nls . quadcon . nnzh + 1 ): (nls. meta. nnzh)) .= 0.0
407496 end
408497 return vals
409498end
@@ -417,11 +506,12 @@ function NLPModels.hprod!(
417506 obj_weight:: Float64 = 1.0 ,
418507)
419508 increment! (nls, :neval_hprod )
420- if (nls. nls_meta. nnln > 0 ) || (nls. meta. nnln > 0 )
421- MOI. eval_hessian_lagrangian_product (nls. ceval, hv, x, v, obj_weight, view (y, nls. meta. nln))
509+ if (nls. nls_meta. nnln > 0 ) || (nls. meta. nnln > nls. quadcon. nquad)
510+ λ = view (y, (nls. meta. nlin + nls. quadcon. nquad + 1 ): (nls. meta. ncon))
511+ MOI. eval_hessian_lagrangian_product (nls. ceval, hv, x, v, obj_weight, λ)
422512 end
513+ (nls. nls_meta. nnln == 0 ) && (nls. meta. nnln == nls. quadcon. nquad) && (hv .= 0.0 )
423514 if nls. nls_meta. nlin > 0
424- (nls. nls_meta. nnln == 0 ) && (nls. meta. nnln == 0 ) && (hv .= 0.0 )
425515 coo_sym_add_mul! (
426516 nls. lls. hessian. rows,
427517 nls. lls. hessian. cols,
@@ -431,6 +521,12 @@ function NLPModels.hprod!(
431521 obj_weight,
432522 )
433523 end
524+ if nls. quadcon. nquad > 0
525+ for i = 1 : (nls. quadcon. nquad)
526+ qcon = nls. quadcon. constraints[i]
527+ coo_sym_add_mul! (qcon. A. rows, qcon. A. cols, qcon. A. vals, v, hv, y[nls. meta. nlin + i])
528+ end
529+ end
434530 return hv
435531end
436532
@@ -443,7 +539,8 @@ function NLPModels.hprod!(
443539)
444540 increment! (nls, :neval_hprod )
445541 if nls. nls_meta. nnln > 0
446- MOI. eval_hessian_lagrangian_product (nls. ceval, hv, x, v, obj_weight, zeros (nls. meta. nnln))
542+ λ = zeros (nls. meta. nnln - nls. quadcon. nquad) # Should be stored in the structure MathOptNLSModel
543+ MOI. eval_hessian_lagrangian_product (nls. ceval, hv, x, v, obj_weight, λ)
447544 end
448545 if nls. nls_meta. nlin > 0
449546 (nls. nls_meta. nnln == 0 ) && (hv .= 0.0 )
0 commit comments