@@ -103,6 +103,9 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
103103 }
104104 # Constraint mappings.
105105 constraint_mapping:: Dict{MOI.ConstraintIndex,Union{Cint,Vector{Cint}}}
106+ vector_nonlinear_oracle_constraints:: Vector {
107+ Tuple{MOI. VectorOfVariables,MOI. VectorNonlinearOracle{Float64}},
108+ }
106109 license_manager:: Union{KNITRO.LMcontext,Nothing}
107110 options:: Dict{String,Any}
108111 # Cache for the solution
@@ -129,6 +132,7 @@ function Optimizer(; license_manager::Union{KNITRO.LMcontext,Nothing}=nothing, k
129132 MOI. FEASIBILITY_SENSE,
130133 nothing ,
131134 Dict {MOI.ConstraintIndex,Union{Cint,Vector{Cint}}} (),
135+ Tuple{MOI. VectorOfVariables,MOI. VectorNonlinearOracle{Float64}}[],
132136 license_manager,
133137 Dict {String,Any} (),
134138 Float64[],
@@ -167,6 +171,7 @@ function MOI.empty!(model::Optimizer)
167171 model. sense = MOI. FEASIBILITY_SENSE
168172 model. objective = nothing
169173 model. constraint_mapping = Dict ()
174+ empty! (model. vector_nonlinear_oracle_constraints)
170175 model. license_manager = model. license_manager
171176 for (name, value) in model. options
172177 MOI. set (model, MOI. RawOptimizerAttribute (name), value)
@@ -184,6 +189,7 @@ function MOI.is_empty(model::Optimizer)
184189 model. sense == MOI. FEASIBILITY_SENSE &&
185190 model. number_solved == 0 &&
186191 model. objective === nothing &&
192+ isempty (model. vector_nonlinear_oracle_constraints) &&
187193 ! model. nlp_loaded
188194end
189195
@@ -1012,6 +1018,105 @@ function MOI.add_constraint(
10121018 return ci
10131019end
10141020
1021+ # MOI.VectorOfVariables-in-MOI.VectorNonlinearOracle
1022+
1023+ function MOI. supports_constraint (
1024+ :: Optimizer ,
1025+ :: Type{MOI.VectorOfVariables} ,
1026+ :: Type{MOI.VectorNonlinearOracle{Float64}} ,
1027+ )
1028+ return true
1029+ end
1030+
1031+ function MOI. add_constraint (
1032+ model:: Optimizer ,
1033+ f:: MOI.VectorOfVariables ,
1034+ s:: MOI.VectorNonlinearOracle{Float64} ,
1035+ )
1036+ _throw_if_solved (model, f, s)
1037+ p = Ref {Cint} (0 )
1038+ KNITRO. @_checked KNITRO. KN_get_number_cons (model, p)
1039+ offset = p[]
1040+ rows = zeros (Cint, s. output_dimension)
1041+ KNITRO. @_checked KNITRO. KN_add_cons (model, s. output_dimension, rows)
1042+ for (r, l, u) in zip (rows, s. l, s. u)
1043+ KNITRO. @_checked KNITRO. KN_set_con_upbnd (model, r, _clamp_inf (l))
1044+ KNITRO. @_checked KNITRO. KN_set_con_lobnd (model, r, _clamp_inf (u))
1045+ end
1046+ KNITRO. @_checked KNITRO. KN_get_number_cons (model, p)
1047+ num_cons = p[]
1048+ tmp_x = zeros (Cdouble, s. input_dimension)
1049+ function eval_f_cb (:: Any , :: Any , evalRequest, evalResult, :: Any )
1050+ for i in 1 : s. input_dimension
1051+ tmp_x[i] = evalRequest. x[f. variables[i]. value]
1052+ end
1053+ s. eval_f (evalResult. c, tmp_x)
1054+ return 0
1055+ end
1056+ function eval_grad_cb (:: Any , :: Any , evalRequest, evalResult, :: Any )
1057+ for i in 1 : s. input_dimension
1058+ tmp_x[i] = evalRequest. x[f. variables[i]. value]
1059+ end
1060+ s. eval_jacobian (evalResult. jac, tmp_x)
1061+ return 0
1062+ end
1063+ cb = KNITRO. KN_add_eval_callback (model. inner, false , rows, eval_f_cb)
1064+ KNITRO. @_checked KNITRO. KN_set_cb_grad (
1065+ model. inner,
1066+ cb,
1067+ eval_grad_cb;
1068+ nV= Cint (0 ),
1069+ jacIndexCons= Cint[i - 1 + offset for (i, _) in s. jacobian_structure],
1070+ jacIndexVars= Cint[f. variables[j]. value - 1 for (_, j) in s. jacobian_structure],
1071+ )
1072+ if s. eval_hessian_lagrangian != = nothing
1073+ function eval_h_cb (:: Any , :: Any , evalRequest, evalResult, :: Any )
1074+ for i in 1 : s. input_dimension
1075+ tmp_x[i] = evalRequest. x[f. variables[i]. value]
1076+ end
1077+ @show evalRequest. lambda
1078+ lambda = view (evalRequest. lambda, (offset+ 1 ): num_cons)
1079+ s. eval_hessian_lagrangian (evalResult. hess, tmp_x, lambda)
1080+ return 0
1081+ end
1082+ I = Cint[f. variables[i]. value - 1 for (i, _) in s. hessian_lagrangian_structure]
1083+ J = Cint[f. variables[j]. value - 1 for (_, j) in s. hessian_lagrangian_structure]
1084+ KNITRO. @_checked KNITRO. KN_set_cb_hess (
1085+ model. inner,
1086+ cb,
1087+ length (s. hessian_lagrangian_structure),
1088+ eval_h_cb;
1089+ hessIndexVars1= I,
1090+ hessIndexVars2= J,
1091+ )
1092+ end
1093+ push! (model. vector_nonlinear_oracle_constraints, (f, s))
1094+ ci = MOI. ConstraintIndex {typeof(f),typeof(s)} (
1095+ length (model. vector_nonlinear_oracle_constraints),
1096+ )
1097+ model. constraint_mapping[ci] = rows
1098+ return ci
1099+ end
1100+
1101+ function MOI. get (
1102+ model:: Optimizer ,
1103+ attr:: MOI.ConstraintDual ,
1104+ ci:: MOI.ConstraintIndex{MOI.VectorOfVariables,MOI.VectorNonlinearOracle{Float64}} ,
1105+ )
1106+ MOI. check_result_index_bounds (model, attr)
1107+ MOI. throw_if_not_valid (model, ci)
1108+ f, s = model. vector_nonlinear_oracle_constraints[ci. value]
1109+ J = zeros (length (s. jacobian_structure))
1110+ x = [MOI. get (model, MOI. VariablePrimal (), xi) for xi in f. variables]
1111+ s. eval_jacobian (J, x)
1112+ λ = [_sense_dual (model) * _get_dual (model, r + 1 ) for r in model. constraint_mapping[ci]]
1113+ dual = zeros (MOI. dimension (s))
1114+ for ((row, col), J_rc) in zip (s. jacobian_structure, J)
1115+ dual[col] += λ[row] * J_rc
1116+ end
1117+ return dual
1118+ end
1119+
10151120# MOI.NLPBlock
10161121
10171122MOI. supports (:: Optimizer , :: MOI.NLPBlock ) = true
0 commit comments