~cgeoga/StandaloneKNITRO.jl

StandaloneKNITRO.jl/src/knitro_optimize.jl -rw-r--r-- 3.6 KiB
954584dd — Chris Geoga Small tweaks with hvp options. 1 year, 3 months ago
                                                                                
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
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