function knitro_optimize(obj, ini, constraints=noconstraints();
box_lower=-floatmax(), box_upper=floatmax(),
admode=:forward, param_file=nothing)
arglen = length(ini)
wobj = WrappedFunction(obj)
derivatives = if admode == :forward
AutoFwdDerivs(wobj, length(ini))
elseif admode == :mixed
AutoMixedDerivs(wobj, length(ini))
else
throw(error("The current two options for admode are :forward or :mixed."))
end
model = Model(wobj, constraints, derivatives)
# Objective callback:
callback_obj = Objective(model)
# Objective gradient and constraint jacobian callback:
con_buf = zeros(constraints.ncon)
jac_buf = zeros(constraints.ncon, arglen)
callback_objg_constrj = GradJac(model, con_buf, jac_buf)
# Lagrangian hessian:
hvp = isnothing(param_file) ? false : any(==("hessopt 5"), eachline(param_file))
callback_lagh = LagHess(model, zeros(arglen, arglen), hvp)
# set up the problem:
kc = KNITRO.KN_new()
# load a parameter file if one is provided:
if !isnothing(param_file)
KNITRO.KN_load_param_file(kc, param_file)
end
# add the variables:
KNITRO.KN_add_vars(kc, arglen, C_NULL)
KNITRO.KN_set_var_lobnds_all(kc, prepare_bounds(arglen, box_lower))
KNITRO.KN_set_var_upbnds_all(kc, prepare_bounds(arglen, box_upper))
# add the constraints:
if constraints.ncon > 0
KNITRO.KN_add_cons(kc, constraints.ncon, C_NULL)
KNITRO.KN_set_con_lobnds_all(kc, constraints.box_lower)
KNITRO.KN_set_con_upbnds_all(kc, constraints.box_upper)
end
# set the init:
KNITRO.KN_set_var_primal_init_values_all(kc, copy(ini))
# Set the objective and constraint callback:
cb = KNITRO.KN_add_eval_callback(kc, true, Int32.(0:(constraints.ncon-1)), callback_obj)
# set the gradient and constraint jacobian:
(j_ix_1, j_ix_2) = dense_jac_structure(arglen, constraints.ncon)
KNITRO.KN_set_cb_grad(kc, cb, callback_objg_constrj,
jacIndexCons=j_ix_2,
jacIndexVars=j_ix_1)
# set the lagrangian hessian and allow for it to be called with sigma==0.0:
KNITRO.KN_set_cb_hess(kc, cb, KNITRO.KN_DENSE_ROWMAJOR, callback_lagh)
KNITRO.KN_set_int_param(kc, KNITRO.KN_PARAM_HESSIAN_NO_F, KNITRO.KN_HESSIAN_NO_F_ALLOW)
# solve the problem, extract output, free KNITRO objects, and return:
nStatus = KNITRO.KN_solve(kc)
(status, sol, x, lam) = KNITRO.KN_get_solution(kc)
KNITRO.KN_free(kc)
(status=status, minimizer=x, minval=sol)
end
# TODO (cg 2022/09/30 13:10): Accept a user-provided Jacobian.
function knitro_nlsolve(fun, ini; box_lower=-floatmax(), box_upper=floatmax())
# problem size:
n = length(ini)
callback_obj = NLSFun(fun)
callback_objg_constrj = NLSJac(fun, zeros(n), zeros(n, n))
# create problem and optimize:
kc = KNITRO.KN_new()
# add the variables:
KNITRO.KN_add_vars(kc, n, C_NULL)
KNITRO.KN_set_var_lobnds_all(kc, prepare_bounds(n, box_lower))
KNITRO.KN_set_var_upbnds_all(kc, prepare_bounds(n, box_upper))
# add the residuals:
KNITRO.KN_add_rsds(kc, n, C_NULL)
KNITRO.KN_add_rsd_constants_all(kc, fill(0.0, n))
# set the init:
KNITRO.KN_set_var_primal_init_values_all(kc, copy(ini))
# Set the objective and constraint callback:
cb = KNITRO.KN_add_lsq_eval_callback(kc, callback_obj)
# set the gradient and constraint jacobian:
KNITRO.KN_set_cb_rsd_jac(kc, cb, KNITRO.KN_DENSE_ROWMAJOR, callback_objg_constrj)
# solve the problem, extract output, free KNITRO objects, and return:
nStatus = KNITRO.KN_solve(kc)
(status, sol, x, lam) = KNITRO.KN_get_solution(kc)
KNITRO.KN_free(kc)
(status=status, minimizer=x)
end