From ca7722b8787999d45a8cdb4411f319d6e4619703 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Sat, 9 Aug 2025 15:28:33 -0500 Subject: [PATCH] wip --- GALAHAD.jl/src/GALAHAD.jl | 1 + GALAHAD.jl/src/callbacks.jl | 196 +++++++++++++++++++++++++++++++++++ GALAHAD.jl/test/test_arc.jl | 114 +++++--------------- GALAHAD.jl/test/test_bgo.jl | 152 ++++++--------------------- GALAHAD.jl/test/test_blls.jl | 17 ++- GALAHAD.jl/test/test_dgo.jl | 149 ++++++-------------------- GALAHAD.jl/test/test_expo.jl | 84 ++++----------- GALAHAD.jl/test/test_slls.jl | 17 ++- GALAHAD.jl/test/test_trb.jl | 131 +++++------------------ GALAHAD.jl/test/test_tru.jl | 116 +++++---------------- GALAHAD.jl/test/test_ugo.jl | 25 ++--- 11 files changed, 383 insertions(+), 619 deletions(-) create mode 100644 GALAHAD.jl/src/callbacks.jl diff --git a/GALAHAD.jl/src/GALAHAD.jl b/GALAHAD.jl/src/GALAHAD.jl index c3fd4c4762..235d2e4ec3 100644 --- a/GALAHAD.jl/src/GALAHAD.jl +++ b/GALAHAD.jl/src/GALAHAD.jl @@ -38,6 +38,7 @@ end # Utils. include("utils.jl") +include("callbacks.jl") # packages without dependencies. include("wrappers/bsc.jl") diff --git a/GALAHAD.jl/src/callbacks.jl b/GALAHAD.jl/src/callbacks.jl new file mode 100644 index 0000000000..d8c6517db8 --- /dev/null +++ b/GALAHAD.jl/src/callbacks.jl @@ -0,0 +1,196 @@ +export galahad_f, galahad_g, galahad_h +export galahad_hprod, galahad_shprod +export galahad_prec, galahad_constant_prec +export galahad_fgh, galahad_fc, galahad_gj, galahad_hl + +for (T, INT, suffix) in ((:Float32 , :Int32, "_s" ), + (:Float32 , :Int64, "_s_64"), + (:Float64 , :Int32, "_d" ), + (:Float64 , :Int64, "_d_64"), + (:Float128, :Int32, "_q" ), + (:Float128, :Int64, "_q_64")) + + julia_galahad_f_r = Symbol(:julia_galahad_f, suffix) + julia_galahad_g_r = Symbol(:julia_galahad_g, suffix) + julia_galahad_h_r = Symbol(:julia_galahad_h, suffix) + julia_galahad_hprod_r = Symbol(:julia_galahad_hprod, suffix) + julia_galahad_shprod_r = Symbol(:julia_galahad_shprod, suffix) + julia_galahad_fgh_r = Symbol(:julia_galahad_fgh, suffix) + julia_galahad_fc_r = Symbol(:julia_galahad_fc, suffix) + julia_galahad_gj_r = Symbol(:julia_galahad_gj, suffix) + julia_galahad_hl_r = Symbol(:julia_galahad_hl, suffix) + julia_galahad_prec_r = Symbol(:julia_galahad_prec, suffix) + julia_galahad_constant_prec_r = Symbol(:julia_galahad_constant_prec, suffix) + + @eval begin + function $julia_galahad_f_r(n::$INT, x::Ptr{$T}, f::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _f = unsafe_wrap(Vector{$T}, f, 1) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_f(_x, _f, _userdata) + else + _userdata.eval_f(_x, _f) + end + return $INT(0) + end + + galahad_f(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_f_r, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + + function $julia_galahad_g_r(n::$INT, x::Ptr{$T}, g::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _g = unsafe_wrap(Vector{$T}, g, n) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_g(_x, _g, _userdata) + else + _userdata.eval_g(_x, _g) + end + return $INT(0) + end + + galahad_g(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_g_r, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + + function $julia_galahad_h_r(n::$INT, ne::$INT, x::Ptr{$T}, hval::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _hval = unsafe_wrap(Vector{$T}, hval, ne) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_h(_x, _hval, _userdata) + else + _userdata.eval_h(_x, _hval) + end + return $INT(0) + end + + galahad_h(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_h_r, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + + function $julia_galahad_hprod_r(n::$INT, x::Ptr{$T}, u::Ptr{$T}, v::Ptr{$T}, got_h::Bool, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _u = unsafe_wrap(Vector{$T}, u, n) + _v = unsafe_wrap(Vector{$T}, v, n) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_hprod(_x, _u, _v, got_h, _userdata) + else + _userdata.eval_hprod(_x, _u, _v, got_h) + end + return $INT(0) + end + + galahad_hprod(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_hprod_r, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Bool, Ptr{Cvoid})) + + function $julia_galahad_shprod_r(n::$INT, x::Ptr{$T}, nnz_v::$INT, index_nz_v::Ptr{$INT}, + v::Ptr{$T}, nnz_u::Ptr{$INT}, index_nz_u::Ptr{$INT}, + u::Ptr{$T}, got_h::Bool, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _u = unsafe_wrap(Vector{$T}, u, n) + _v = unsafe_wrap(Vector{$T}, v, n) + _index_nz_v = unsafe_wrap(Vector{$INT}, index_nz_v, nnz_v) + _nnz_u = unsafe_wrap(Vector{$INT}, nnz_u, 1) + _index_nz_u = unsafe_wrap(Vector{$INT}, index_nz_u, n) # Is it right? + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_shprod(_x, nnz_v, _index_nz_v, _v, _nnz_u, _index_nz_u, _u, got_h, _userdata) + else + _userdata.eval_shprod(_x, nnz_v, _index_nz_v, _v, _nnz_u, _index_nz_u, _u, got_h) + end + return $INT(0) + end + + galahad_shprod(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_shprod_r, $INT, ($INT, Ptr{$T}, $INT, Ptr{$INT}, Ptr{$T}, Ptr{$INT}, Ptr{$INT}, Ptr{$T}, Bool, Ptr{Cvoid})) + + function $julia_galahad_fgh_r(x::$T, f::Ptr{$T}, g::Ptr{$T}, h::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _f = unsafe_wrap(Vector{$T}, f, 1) + _g = unsafe_wrap(Vector{$T}, g, 1) + _h = unsafe_wrap(Vector{$T}, h, 1) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _f[1] = _userdata.eval_f(x, _userdata) + _g[1] = _userdata.eval_g(x, _userdata) + _h[1] = _userdata.eval_h(x, _userdata) + else + _f[1] = _userdata.eval_f(x) + _g[1] = _userdata.eval_g(x) + _h[1] = _userdata.eval_h(x) + end + return $INT(0) + end + + galahad_fgh(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_fgh_r, $INT, ($T, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + + function $julia_galahad_fc_r(n::$INT, m::$INT, x::Ptr{$T}, f::Ptr{$T}, c::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _c = unsafe_wrap(Vector{$T}, c, m) + _f = unsafe_wrap(Vector{$T}, f, 1) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_fc(_x, _f, _c, _userdata) + else + _userdata.eval_fc(_x, _f, _c) + end + return $INT(0) + end + + galahad_fc(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_fc_r, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + + function $julia_galahad_gj_r(n::$INT, m::$INT, J_ne::$INT, x::Ptr{$T}, g::Ptr{$T}, jval::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _g = unsafe_wrap(Vector{$T}, g, n) + _jval = unsafe_wrap(Vector{$T}, jval, J_ne) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_gj(_x, _g, _jval, _userdata) + else + _userdata.eval_gj(_x, _g, _jval) + end + return $INT(0) + end + + galahad_gj(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_gj_r, $INT, ($INT, $INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + + function $julia_galahad_hl_r(n::$INT, m::$INT, H_ne::$INT, x::Ptr{$T}, y::Ptr{$T}, hval::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _y = unsafe_wrap(Vector{$T}, y, m) + _hval = unsafe_wrap(Vector{$T}, hval, H_ne) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_hl(_x, _y, _hval, _userdata) + else + _userdata.eval_hl(_x, _y, _hval) + end + return $INT(0) + end + + galahad_hl(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_hl_r, $INT, ($INT, $INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + + function $julia_galahad_prec_r(n::$INT, x::Ptr{$T}, u::Ptr{$T}, v::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _x = unsafe_wrap(Vector{$T}, x, n) + _u = unsafe_wrap(Vector{$T}, u, n) + _v = unsafe_wrap(Vector{$T}, v, n) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_prec(_x, _u, _v, _userdata) + else + _userdata.eval_prec(_x, _u, _v) + end + return $INT(0) + end + + galahad_prec(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_prec_r, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + + function $julia_galahad_constant_prec_r(n::$INT, v::Ptr{$T}, p::Ptr{$T}, userdata::Ptr{Cvoid})::$INT + _v = unsafe_wrap(Vector{$T}, v, n) + _p = unsafe_wrap(Vector{$T}, p, n) + _userdata = unsafe_pointer_to_objref(userdata) + if _userdata.pass_userdata + _userdata.eval_prec(_v, _p, _userdata) + else + _userdata.eval_prec(_v, _p) + end + return $INT(0) + end + + galahad_constant_prec(::Type{$T}, ::Type{$INT}) = @cfunction($julia_galahad_constant_prec_r, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + end +end diff --git a/GALAHAD.jl/test/test_arc.jl b/GALAHAD.jl/test/test_arc.jl index 9cabe50d81..52feae7f18 100644 --- a/GALAHAD.jl/test/test_arc.jl +++ b/GALAHAD.jl/test/test_arc.jl @@ -10,6 +10,12 @@ using Quadmath # Custom userdata struct mutable struct userdata_arc{T} p::T + pass_userdata::Bool + eval_f::Function + eval_g::Function + eval_h::Union{Function, Nothing} + eval_hprod::Union{Function, Nothing} + eval_prec::Function end function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="sytr", dls::String="potr") where {T,INT} @@ -21,15 +27,6 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - fun(_x, _f, _userdata) - end - - fun_ptr = @eval @cfunction($fun_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad(x::Vector{T}, g::Vector{T}, userdata::userdata_arc{T}) p = userdata.p @@ -39,15 +36,6 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - grad(_x, _g, _userdata) - end - - grad_ptr = @eval @cfunction($grad_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess(x::Vector{T}, hval::Vector{T}, userdata::userdata_arc{T}) hval[1] = 2.0 - cos(x[1]) @@ -58,15 +46,6 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - hess(_x, _hval, _userdata) - end - - hess_ptr = @eval @cfunction($hess_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Dense Hessian function hess_dense(x::Vector{T}, hval::Vector{T}, userdata::userdata_arc{T}) hval[1] = 2.0 - cos(x[1]) @@ -78,15 +57,6 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_dense_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - hess_dense(_x, _hval, _userdata) - end - - hess_dense_ptr = @eval @cfunction($hess_dense_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian-vector product function hessprod(x::Vector{T}, u::Vector{T}, v::Vector{T}, got_h::Bool, userdata::userdata_arc{T}) @@ -96,17 +66,6 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hessprod_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, - got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - hessprod(_x, _u, _v, got_h, _userdata) - end - - hessprod_ptr = @eval @cfunction($hessprod_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Bool, Ptr{Cvoid})) - # Apply preconditioner function prec(x::Vector{T}, u::Vector{T}, v::Vector{T}, userdata::userdata_arc{T}) u[1] = 0.5 * v[1] @@ -115,16 +74,6 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function prec_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - prec(_x, _u, _v, _userdata) - end - - prec_ptr = @eval @cfunction($prec_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Objective function function fun_diag(x::Vector{T}, f::Vector{T}, userdata::userdata_arc{T}) p = userdata.p @@ -132,15 +81,6 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_diag_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - fun_diag(_x, _f, _userdata) - end - - fun_diag_ptr = @eval @cfunction($fun_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad_diag(x::Vector{T}, g::Vector{T}, userdata::userdata_arc{T}) p = userdata.p @@ -150,15 +90,6 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_diag_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - grad_diag(_x, _g, _userdata) - end - - grad_diag_ptr = @eval @cfunction($grad_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess_diag(x::Vector{T}, hval::Vector{T}, userdata::userdata_arc{T}) hval[1] = -cos(x[1]) @@ -167,14 +98,12 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_diag_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_arc{T} - hess_diag(_x, _hval, _userdata) - end - - hess_diag_ptr = @eval @cfunction($hess_diag_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + # Pointer to C-compatible functions that wraps the Julia functions + obj_ptr = galahad_f(T, INT) + grad_ptr = galahad_g(T, INT) + hess_ptr = galahad_h(T, INT) + hessprod_ptr = galahad_hprod(T, INT) + prec_ptr = galahad_prec(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() @@ -182,8 +111,15 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s inform = Ref{arc_inform_type{T,INT}}() # Set user data - userdata = userdata_arc{T}(4) + pass_userdata = true + userdata = userdata_arc{T}(4, pass_userdata, fun, grad, hess, nothing, prec) userdata_ptr = pointer_from_objref(userdata) + userdata_dense = userdata_arc{T}(4, pass_userdata, fun, grad, hess_dense, nothing, prec) + userdata_dense_ptr = pointer_from_objref(userdata_dense) + userdata_nh = userdata_arc{T}(4, pass_userdata, fun, grad, nothing, hessprod, prec) + userdata_nh_ptr = pointer_from_objref(userdata_nh) + userdata_diag = userdata_arc{T}(4, pass_userdata, fun_diag, grad_diag, hess_diag, nothing, prec) + userdata_diag_ptr = pointer_from_objref(userdata_diag) # Set problem data n = INT(3) # dimension @@ -223,35 +159,35 @@ function test_arc(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s if d == 1 st = 'C' arc_import(T, INT, control, data, status, n, "coordinate", ne, H_row, H_col, C_NULL) - arc_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne, fun_ptr, grad_ptr, hess_ptr, prec_ptr) + arc_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # sparse by rows if d == 2 st = 'R' arc_import(T, INT, control, data, status, n, "sparse_by_rows", ne, C_NULL, H_col, H_ptr) - arc_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne, fun_ptr, grad_ptr, hess_ptr, prec_ptr) + arc_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # dense if d == 3 st = 'D' arc_import(T, INT, control, data, status, n, "dense", ne_dense, C_NULL, C_NULL, C_NULL) - arc_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne_dense, fun_ptr, grad_ptr, hess_dense_ptr, prec_ptr) + arc_solve_with_mat(T, INT, data, userdata_dense_ptr, status, n, x, g, ne_dense, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # diagonal if d == 4 st = 'I' arc_import(T, INT, control, data, status, n, "diagonal", n, C_NULL, C_NULL, C_NULL) - arc_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, n, fun_diag_ptr, grad_diag_ptr, hess_diag_ptr, prec_ptr) + arc_solve_with_mat(T, INT, data, userdata_diag_ptr, status, n, x, g, n, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # access by products if d == 5 st = 'P' arc_import(T, INT, control, data, status, n, "absent", ne, C_NULL, C_NULL, C_NULL) - arc_solve_without_mat(T, INT, data, userdata_ptr, status, n, x, g, fun_ptr, grad_ptr, hessprod_ptr, prec_ptr) + arc_solve_without_mat(T, INT, data, userdata_nh_ptr, status, n, x, g, obj_ptr, grad_ptr, hessprod_ptr, prec_ptr) end arc_information(T, INT, data, inform, status) diff --git a/GALAHAD.jl/test/test_bgo.jl b/GALAHAD.jl/test/test_bgo.jl index ec3411f3c5..6d52b5ab75 100644 --- a/GALAHAD.jl/test/test_bgo.jl +++ b/GALAHAD.jl/test/test_bgo.jl @@ -12,6 +12,13 @@ mutable struct userdata_bgo{T} p::T freq::T mag::T + pass_userdata::Bool + eval_f::Function + eval_g::Function + eval_h::Union{Function, Nothing} + eval_hprod::Function + eval_shprod::Union{Function, Nothing} + eval_prec::Function end function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="sytr", dls::String="potr") where {T,INT} @@ -26,15 +33,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - fun(_x, _f, _userdata) - end - - fun_ptr = @eval @cfunction($fun_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad(x::Vector{T}, g::Vector{T}, userdata::userdata_bgo{T}) p = userdata.p @@ -46,15 +44,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - grad(_x, _g, _userdata) - end - - grad_ptr = @eval @cfunction($grad_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess(x::Vector{T}, hval::Vector{T}, userdata::userdata_bgo{T}) p = userdata.p @@ -67,15 +56,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - hess(_x, _hval, _userdata) - end - - hess_ptr = @eval @cfunction($hess_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Dense Hessian function hess_dense(x::Vector{T}, hval::Vector{T}, userdata::userdata_bgo{T}) p = userdata.p @@ -89,15 +69,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_dense_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - hess_dense(_x, _hval, _userdata) - end - - hess_dense_ptr = @eval @cfunction($hess_dense_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian-vector product function hessprod(x::Vector{T}, u::Vector{T}, v::Vector{T}, got_h::Bool, userdata::userdata_bgo{T}) @@ -110,17 +81,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hessprod_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, - got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - hessprod(_x, _u, _v, got_h, _userdata) - end - - hessprod_ptr = @eval @cfunction($hessprod_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Bool, Ptr{Cvoid})) - # Sparse Hessian-vector product function shessprod(x::Vector{T}, nnz_v::INT, index_nz_v::Vector{INT}, v::Vector{T}, nnz_u::Vector{INT}, index_nz_u::Vector{INT}, @@ -163,21 +123,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function shessprod_c(n::INT, x::Ptr{T}, nnz_v::INT, index_nz_v::Ptr{INT}, - v::Ptr{T}, nnz_u::Ptr{INT}, index_nz_u::Ptr{INT}, - u::Ptr{T}, got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _index_nz_v = unsafe_wrap(Vector{INT}, index_nz_v, nnz_v) - _nnz_u = unsafe_wrap(Vector{INT}, nnz_u, 1) - _index_nz_u = unsafe_wrap(Vector{INT}, index_nz_u, n) # Is it right? - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - shessprod(_x, nnz_v, _index_nz_v, _v, _nnz_u, _index_nz_u, _u, got_h, _userdata) - end - - shessprod_ptr = @eval @cfunction($shessprod_c, $INT, ($INT, Ptr{$T}, $INT, Ptr{$INT}, Ptr{$T}, Ptr{$INT}, Ptr{$INT}, Ptr{$T}, Bool, Ptr{Cvoid})) - # Apply preconditioner function prec(x::Vector{T}, u::Vector{T}, v::Vector{T}, userdata::userdata_bgo{T}) @@ -187,16 +132,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function prec_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - prec(_x, _u, _v, _userdata) - end - - prec_ptr = @eval @cfunction($prec_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Objective function function fun_diag(x::Vector{T}, f::Vector{T}, userdata::userdata_bgo{T}) p = userdata.p @@ -207,15 +142,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_diag_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - fun_diag(_x, _f, _userdata) - end - - fun_diag_ptr = @eval @cfunction($fun_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad_diag(x::Vector{T}, g::Vector{T}, userdata::userdata_bgo{T}) p = userdata.p @@ -228,15 +154,6 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_diag_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - grad_diag(_x, _g, _userdata) - end - - grad_diag_ptr = @eval @cfunction($grad_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess_diag(x::Vector{T}, hval::Vector{T}, userdata::userdata_bgo{T}) freq = userdata.freq @@ -248,18 +165,9 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_diag_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - hess_diag(_x, _hval, _userdata) - end - - hess_diag_ptr = @eval @cfunction($hess_diag_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian-vector product function hessprod_diag(x::Vector{T}, u::Vector{T}, v::Vector{T}, - got_h::Bool, userdata::userdata_bgo{T}) + got_h::Bool, userdata::userdata_bgo{T}) freq = userdata.freq mag = userdata.mag @@ -269,15 +177,13 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hessprod_diag_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_bgo{T} - hessprod_diag(_x, _u, _v, got_h, _userdata) - end - - hessprod_diag_ptr = @eval @cfunction($hessprod_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Bool, Ptr{Cvoid})) + # Pointer to C-compatible functions that wraps the Julia functions + obj_ptr = galahad_f(T, INT) + grad_ptr = galahad_g(T, INT) + hess_ptr = galahad_h(T, INT) + hessprod_ptr = galahad_hprod(T, INT) + shessprod_ptr = galahad_shprod(T, INT) + prec_ptr = galahad_prec(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() @@ -285,8 +191,15 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s inform = Ref{bgo_inform_type{T,INT}}() # Set user data - userdata = userdata_bgo{T}(4, 10, 1000) + pass_userdata = true + userdata = userdata_bgo{T}(4, 10, 1000, pass_userdata, fun, grad, hess, hessprod, nothing, prec) userdata_ptr = pointer_from_objref(userdata) + userdata_dense = userdata_bgo{T}(4, 10, 1000, pass_userdata, fun, grad, hess_dense, hessprod, nothing, prec) + userdata_dense_ptr = pointer_from_objref(userdata_dense) + userdata_diag = userdata_bgo{T}(4, 10, 1000, pass_userdata, fun_diag, grad_diag, hess_diag, hessprod_diag, nothing, prec) + userdata_diag_ptr = pointer_from_objref(userdata_diag) + userdata_nh = userdata_bgo{T}(4, 10, 1000, pass_userdata, fun, grad, nothing, hessprod, shessprod, prec) + userdata_nh_ptr = pointer_from_objref(userdata_nh) # Set problem data n = INT(3) # dimension @@ -334,7 +247,7 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s "coordinate", ne, H_row, H_col, C_NULL) bgo_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, - ne, fun_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) + ne, obj_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) end # sparse by rows @@ -344,7 +257,7 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s "sparse_by_rows", ne, C_NULL, H_col, H_ptr) bgo_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, - ne, fun_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) + ne, obj_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) end # dense @@ -353,9 +266,8 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s bgo_import(T, INT, control, data, status, n, x_l, x_u, "dense", ne_dense, C_NULL, C_NULL, C_NULL) - bgo_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, - ne_dense, fun_ptr, grad_ptr, hess_dense_ptr, - hessprod_ptr, prec_ptr) + bgo_solve_with_mat(T, INT, data, userdata_dense_ptr, status, n, x, g, + ne_dense, obj_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) end # diagonal @@ -364,9 +276,8 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s bgo_import(T, INT, control, data, status, n, x_l, x_u, "diagonal", n, C_NULL, C_NULL, C_NULL) - bgo_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, - n, fun_diag_ptr, grad_diag_ptr, hess_diag_ptr, - hessprod_diag_ptr, prec_ptr) + bgo_solve_with_mat(T, INT, data, userdata_diag_ptr, status, n, x, g, + n, obj_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) end # access by products @@ -375,9 +286,8 @@ function test_bgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s bgo_import(T, INT, control, data, status, n, x_l, x_u, "absent", ne, C_NULL, C_NULL, C_NULL) - bgo_solve_without_mat(T, INT, data, userdata_ptr, status, n, x, g, - fun_ptr, grad_ptr, hessprod_ptr, - shessprod_ptr, prec_ptr) + bgo_solve_without_mat(T, INT, data, userdata_nh_ptr, status, n, x, g, + obj_ptr, grad_ptr, hessprod_ptr, shessprod_ptr, prec_ptr) end # Record solution information diff --git a/GALAHAD.jl/test/test_blls.jl b/GALAHAD.jl/test/test_blls.jl index 51a0d385ba..4173147280 100644 --- a/GALAHAD.jl/test/test_blls.jl +++ b/GALAHAD.jl/test/test_blls.jl @@ -10,6 +10,8 @@ using Quadmath # Custom userdata struct mutable struct userdata_blls{T} scale::T + pass_userdata::Bool + eval_prec::Function end function test_blls(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="sytr", dls::String="potr") where {T,INT} @@ -17,17 +19,11 @@ function test_blls(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String=" # Apply preconditioner function prec(v::Vector{T}, p::Vector{T}, userdata::userdata_blls{T}) p .= userdata.scale .* v - return INT(0) + return p end - function prec_c(n::INT, v::Ptr{T}, p::Ptr{T}, userdata::Ptr{Cvoid}) - _v = unsafe_wrap(Vector{T}, v, n) - _p = unsafe_wrap(Vector{T}, p, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_blls{T} - prec(_v, _p, _userdata) - end - - prec_ptr = @eval @cfunction($prec_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + # Pointer to a C-compatible function that wraps the Julia prec + prec_ptr = galahad_constant_prec(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() @@ -35,7 +31,8 @@ function test_blls(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String=" inform = Ref{blls_inform_type{T,INT}}() # Set user data - userdata = userdata_blls{T}(1) + pass_userdata = true + userdata = userdata_blls{T}(1, pass_userdata, prec) userdata_ptr = pointer_from_objref(userdata) # Set problem data diff --git a/GALAHAD.jl/test/test_dgo.jl b/GALAHAD.jl/test/test_dgo.jl index f03fcdd704..d3cd93113d 100644 --- a/GALAHAD.jl/test/test_dgo.jl +++ b/GALAHAD.jl/test/test_dgo.jl @@ -12,6 +12,13 @@ mutable struct userdata_dgo{T} p::T freq::T mag::T + pass_userdata::Bool + eval_f::Function + eval_g::Function + eval_h::Union{Function, Nothing} + eval_hprod::Function + eval_shprod::Union{Function, Nothing} + eval_prec::Function end function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="sytr", dls::String="potr") where {T,INT} @@ -26,15 +33,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - fun(_x, _f, _userdata) - end - - fun_ptr = @eval @cfunction($fun_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad(x::Vector{T}, g::Vector{T}, userdata::userdata_dgo{T}) p = userdata.p @@ -46,15 +44,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - grad(_x, _g, _userdata) - end - - grad_ptr = @eval @cfunction($grad_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess(x::Vector{T}, hval::Vector{T}, userdata::userdata_dgo{T}) p = userdata.p @@ -67,15 +56,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - hess(_x, _hval, _userdata) - end - - hess_ptr = @eval @cfunction($hess_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Dense Hessian function hess_dense(x::Vector{T}, hval::Vector{T}, userdata::userdata_dgo{T}) p = userdata.p @@ -89,15 +69,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_dense_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - hess_dense(_x, _hval, _userdata) - end - - hess_dense_ptr = @eval @cfunction($hess_dense_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian-vector product function hessprod(x::Vector{T}, u::Vector{T}, v::Vector{T}, got_h::Bool, userdata::userdata_dgo{T}) @@ -110,17 +81,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hessprod_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, - got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - hessprod(_x, _u, _v, got_h, _userdata) - end - - hessprod_ptr = @eval @cfunction($hessprod_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Bool, Ptr{Cvoid})) - # Sparse Hessian-vector product function shessprod(x::Vector{T}, nnz_v::INT, index_nz_v::Vector{INT}, v::Vector{T}, nnz_u::Vector{INT}, index_nz_u::Vector{INT}, @@ -163,21 +123,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function shessprod_c(n::INT, x::Ptr{T}, nnz_v::INT, index_nz_v::Ptr{INT}, - v::Ptr{T}, nnz_u::Ptr{INT}, index_nz_u::Ptr{INT}, - u::Ptr{T}, got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _index_nz_v = unsafe_wrap(Vector{INT}, index_nz_v, nnz_v) - _nnz_u = unsafe_wrap(Vector{INT}, nnz_u, 1) - _index_nz_u = unsafe_wrap(Vector{INT}, index_nz_u, n) # Is it right? - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - shessprod(_x, nnz_v, _index_nz_v, _v, _nnz_u, _index_nz_u, _u, got_h, _userdata) - end - - shessprod_ptr = @eval @cfunction($shessprod_c, $INT, ($INT, Ptr{$T}, $INT, Ptr{$INT}, Ptr{$T}, Ptr{$INT}, Ptr{$INT}, Ptr{$T}, Bool, Ptr{Cvoid})) - # Apply preconditioner function prec(x::Vector{T}, u::Vector{T}, v::Vector{T}, userdata::userdata_dgo{T}) u[1] = 0.5 * v[1] @@ -186,16 +131,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function prec_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - prec(_x, _u, _v, _userdata) - end - - prec_ptr = @eval @cfunction($prec_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Objective function function fun_diag(x::Vector{T}, f::Vector{T}, userdata::userdata_dgo{T}) p = userdata.p @@ -206,15 +141,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_diag_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - fun_diag(_x, _f, _userdata) - end - - fun_diag_ptr = @eval @cfunction($fun_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad_diag(x::Vector{T}, g::Vector{T}, userdata::userdata_dgo{T}) p = userdata.p @@ -227,15 +153,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_diag_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - grad_diag(_x, _g, _userdata) - end - - grad_diag_ptr = @eval @cfunction($grad_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess_diag(x::Vector{T}, hval::Vector{T}, userdata::userdata_dgo{T}) freq = userdata.freq @@ -247,15 +164,6 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_diag_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - hess_diag(_x, _hval, _userdata) - end - - hess_diag_ptr = @eval @cfunction($hess_diag_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian-vector product function hessprod_diag(x::Vector{T}, u::Vector{T}, v::Vector{T}, got_h::Bool, userdata::userdata_dgo{T}) @@ -268,15 +176,13 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hessprod_diag_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_dgo{T} - hessprod_diag(_x, _u, _v, got_h, _userdata) - end - - hessprod_diag_ptr = @eval @cfunction($hessprod_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Bool, Ptr{Cvoid})) + # Pointer to C-compatible functions that wraps the Julia functions + obj_ptr = galahad_f(T, INT) + grad_ptr = galahad_g(T, INT) + hess_ptr = galahad_h(T, INT) + hessprod_ptr = galahad_hprod(T, INT) + shessprod_ptr = galahad_shprod(T, INT) + prec_ptr = galahad_prec(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() @@ -284,8 +190,15 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s inform = Ref{dgo_inform_type{T,INT}}() # Set user data - userdata = userdata_dgo{T}(4.0, 10.0, 1000.0) + pass_userdata = true + userdata = userdata_dgo{T}(4, 10, 1000, pass_userdata, fun, grad, hess, hessprod, nothing, prec) userdata_ptr = pointer_from_objref(userdata) + userdata_dense = userdata_dgo{T}(4, 10, 1000, pass_userdata, fun, grad, hess_dense, hessprod, nothing, prec) + userdata_dense_ptr = pointer_from_objref(userdata_dense) + userdata_diag = userdata_dgo{T}(4, 10, 1000, pass_userdata, fun_diag, grad_diag, hess_diag, hessprod_diag, nothing, prec) + userdata_diag_ptr = pointer_from_objref(userdata_diag) + userdata_nh = userdata_dgo{T}(4, 10, 1000, pass_userdata, fun, grad, nothing, hessprod, shessprod, prec) + userdata_nh_ptr = pointer_from_objref(userdata_nh) # Set problem data n = INT(3) # dimension @@ -331,7 +244,7 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s "coordinate", ne, H_row, H_col, C_NULL) dgo_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, - ne, fun_ptr, grad_ptr, hess_ptr, + ne, obj_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) end @@ -342,7 +255,7 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s "sparse_by_rows", ne, C_NULL, H_col, H_ptr) dgo_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, - ne, fun_ptr, grad_ptr, hess_ptr, + ne, obj_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) end @@ -352,8 +265,8 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s dgo_import(T, INT, control, data, status, n, x_l, x_u, "dense", ne_dense, C_NULL, C_NULL, C_NULL) - dgo_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, - ne_dense, fun_ptr, grad_ptr, hess_dense_ptr, + dgo_solve_with_mat(T, INT, data, userdata_dense_ptr, status, n, x, g, + ne_dense, obj_ptr, grad_ptr, hess_ptr, hessprod_ptr, prec_ptr) end @@ -363,9 +276,9 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s dgo_import(T, INT, control, data, status, n, x_l, x_u, "diagonal", n, C_NULL, C_NULL, C_NULL) - dgo_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, - n, fun_diag_ptr, grad_diag_ptr, hess_diag_ptr, - hessprod_diag_ptr, prec_ptr) + dgo_solve_with_mat(T, INT, data, userdata_diag_ptr, status, n, x, g, + n, obj_ptr, grad_ptr, hess_ptr, + hessprod_ptr, prec_ptr) end # access by products @@ -374,8 +287,8 @@ function test_dgo(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s dgo_import(T, INT, control, data, status, n, x_l, x_u, "absent", ne, C_NULL, C_NULL, C_NULL) - dgo_solve_without_mat(T, INT, data, userdata_ptr, status, n, x, g, - fun_ptr, grad_ptr, hessprod_ptr, shessprod_ptr, prec_ptr) + dgo_solve_without_mat(T, INT, data, userdata_nh_ptr, status, n, x, g, + obj_ptr, grad_ptr, hessprod_ptr, shessprod_ptr, prec_ptr) end # Record solution information diff --git a/GALAHAD.jl/test/test_expo.jl b/GALAHAD.jl/test/test_expo.jl index e6f87f2305..6c88138815 100644 --- a/GALAHAD.jl/test/test_expo.jl +++ b/GALAHAD.jl/test/test_expo.jl @@ -10,6 +10,13 @@ using Quadmath # Custom userdata struct mutable struct userdata_expo{T} p::T + pass_userdata::Bool + eval_fc::Function + eval_gj::Function + eval_hl::Function + eval_fc_ptr::Ptr{Cvoid} + eval_gj_ptr::Ptr{Cvoid} + eval_hl_ptr::Ptr{Cvoid} end function test_expo(::Type{T}, ::Type{INT}; mode::String="direct", sls::String="sytr") where {T,INT} @@ -22,19 +29,9 @@ function test_expo(::Type{T}, ::Type{INT}; mode::String="direct", sls::String="s c[3] = userdata.p * x[1]^2 + x[2]^2 - userdata.p c[4] = x[1]^2 - x[2] c[5] = x[2]^2 - x[1] - return INT(0) + return f, c end - function eval_fc_c(n::INT, m::INT, x::Ptr{T}, f::Ptr{T}, c::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _c = unsafe_wrap(Vector{T}, c, m) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_expo{T} - eval_fc(_x, _f, _c, _userdata) - end - - eval_fc_ptr = @eval @cfunction($eval_fc_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # compute the gradient and Jacobian function eval_gj(x::Vector{T}, g::Vector{T}, jval::Vector{T}, userdata::userdata_expo{T}) g[1] = 2 * x[1] @@ -49,20 +46,9 @@ function test_expo(::Type{T}, ::Type{INT}; mode::String="direct", sls::String="s jval[8] = -1 jval[9] = -1 jval[10] = 2 * x[2] - return INT(0) - end - - function eval_gj_c(n::INT, m::INT, J_ne::INT, x::Ptr{T}, g::Ptr{T}, - jval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _jval = unsafe_wrap(Vector{T}, jval, J_ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_expo{T} - eval_gj(_x, _g, _jval, _userdata) + return g, jval end - eval_gj_ptr = @eval @cfunction($eval_gj_c, $INT, ($INT, $INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # compute the gradient and dense Jacobian function eval_gj_dense(x::Vector{T}, g::Vector{T}, jval::Vector{T}, userdata::userdata_expo{T}) g[1] = 2 * x[1] @@ -77,56 +63,29 @@ function test_expo(::Type{T}, ::Type{INT}; mode::String="direct", sls::String="s jval[8] = -1 jval[9] = -1 jval[10] = 2 * x[2] - return INT(0) - end - - function eval_gj_dense_c(n::INT, m::INT, J_ne::INT, x::Ptr{T}, g::Ptr{T}, - jval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _jval = unsafe_wrap(Vector{T}, jval, J_ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_expo{T} - eval_gj_dense(_x, _g, _jval, _userdata) + return g, jval end - eval_gj_dense_ptr = @eval @cfunction($eval_gj_dense_c, $INT, ($INT, $INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # compute the Hessian function eval_hl(x::Vector{T}, y::Vector{T}, hval::Vector{T}, userdata::userdata_expo{T}) hval[1] = 2 - 2 * (y[2] + userdata.p * y[3] + y[4]) hval[2] = 2 - 2 * (y[2] + y[3] + y[5]) - return INT(0) - end - - function eval_hl_c(n::INT, m::INT, H_ne::INT, x::Ptr{T}, y::Ptr{T}, - hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _y = unsafe_wrap(Vector{T}, y, m) - _hval = unsafe_wrap(Vector{T}, hval, H_ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_expo{T} - eval_hl(_x, _y, _hval, _userdata) + return hval end - eval_hl_ptr = @eval @cfunction($eval_hl_c, $INT, ($INT, $INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # compute the dense Hessian function eval_hl_dense(x::Vector{T}, y::Vector{T}, hval::Vector{T}, userdata::userdata_expo{T}) hval[1] = 2 - 2 * (y[2] + userdata.p * y[3] + y[4]) hval[2] = 0 hval[3] = 2 - 2* (y[2] + y[3] + y[5]) - return INT(0) + return hval end - function eval_hl_dense_c(n::INT, m::INT, H_ne::INT, x::Ptr{T}, y::Ptr{T}, - hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _y = unsafe_wrap(Vector{T}, y, m) - _hval = unsafe_wrap(Vector{T}, hval, H_ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_expo{T} - eval_hl_dense(_x, _y, _hval, _userdata) - end - - eval_hl_dense_ptr = @eval @cfunction($eval_hl_dense_c, $INT, ($INT, $INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + # Pointer to C-compatible functions that wraps the Julia functions for + # objective, contraints, gradient, jacobian and hessian of the problem + eval_fc_ptr = galahad_fc(T, INT) + eval_gj_ptr = galahad_gj(T, INT) + eval_hl_ptr = galahad_hl(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() @@ -134,8 +93,11 @@ function test_expo(::Type{T}, ::Type{INT}; mode::String="direct", sls::String="s inform = Ref{expo_inform_type{T,INT}}() # Set user data - userdata = userdata_expo{T}(9) + use_userdata = true + userdata = userdata_expo{T}(9, use_userdata, eval_fc, eval_gj, eval_hl, eval_fc_ptr, eval_gj_ptr, eval_hl_ptr) userdata_ptr = pointer_from_objref(userdata) + userdata_dense = userdata_expo{T}(9, use_userdata, eval_fc, eval_gj_dense, eval_hl_dense, eval_fc_ptr, eval_gj_ptr, eval_hl_ptr) + userdata_dense_ptr = pointer_from_objref(userdata_dense) # Set problem data n = INT(2) # variables @@ -223,9 +185,9 @@ function test_expo(::Type{T}, ::Type{INT}; mode::String="direct", sls::String="s "dense", h_ne_dense, C_NULL, C_NULL, C_NULL ) expo_solve_hessian_direct(T, INT, data, - userdata_ptr, status, n, m, j_ne_dense, h_ne_dense, + userdata_dense_ptr, status, n, m, j_ne_dense, h_ne_dense, c_l, c_u, x_l, x_u, x, y, z, c, gl, - eval_fc_ptr, eval_gj_dense_ptr, eval_hl_dense_ptr) + eval_fc_ptr, eval_gj_ptr, eval_hl_ptr) end # diagonal diff --git a/GALAHAD.jl/test/test_slls.jl b/GALAHAD.jl/test/test_slls.jl index eae74f7a57..98ff2e8b02 100644 --- a/GALAHAD.jl/test/test_slls.jl +++ b/GALAHAD.jl/test/test_slls.jl @@ -10,6 +10,8 @@ using Quadmath # Custom userdata struct mutable struct userdata_slls{T} scale::T + pass_userdata::Bool + eval_prec::Function end function test_slls(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="sytr", dls::String="potr") where {T,INT} @@ -17,17 +19,11 @@ function test_slls(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String=" # Apply preconditioner function prec(v::Vector{T}, p::Vector{T}, userdata::userdata_slls{T}) p .= userdata.scale .* v - return INT(0) + return p end - function prec_c(n::INT, v::Ptr{T}, p::Ptr{T}, userdata::Ptr{Cvoid}) - _v = unsafe_wrap(Vector{T}, v, n) - _p = unsafe_wrap(Vector{T}, p, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_slls{T} - prec(_v, _p, _userdata) - end - - prec_ptr = @eval @cfunction($prec_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + # Pointer to a C-compatible function that wraps the Julia prec + prec_ptr = galahad_constant_prec(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() @@ -35,7 +31,8 @@ function test_slls(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String=" inform = Ref{slls_inform_type{T,INT}}() # Set user data - userdata = userdata_slls{T}(1) + pass_userdata = true + userdata = userdata_slls{T}(1, pass_userdata, prec) userdata_ptr = pointer_from_objref(userdata) # Set problem data diff --git a/GALAHAD.jl/test/test_trb.jl b/GALAHAD.jl/test/test_trb.jl index 81162d6154..2588dc9bf3 100644 --- a/GALAHAD.jl/test/test_trb.jl +++ b/GALAHAD.jl/test/test_trb.jl @@ -10,6 +10,13 @@ using Quadmath # Custom userdata struct mutable struct userdata_trb{T} p::T + pass_userdata::Bool + eval_f::Function + eval_g::Function + eval_h::Union{Function, Nothing} + eval_hprod::Union{Function, Nothing} + eval_shprod::Union{Function, Nothing} + eval_prec::Function end function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="sytr", dls::String="potr") where {T,INT} @@ -21,15 +28,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - fun(_x, _f, _userdata) - end - - fun_ptr = @eval @cfunction($fun_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad(x::Vector{T}, g::Vector{T}, userdata::userdata_trb{T}) p = userdata.p @@ -39,15 +37,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - grad(_x, _g, _userdata) - end - - grad_ptr = @eval @cfunction($grad_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess(x::Vector{T}, hval::Vector{T}, userdata::userdata_trb{T}) hval[1] = 2.0 - cos(x[1]) @@ -58,15 +47,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - hess(_x, _hval, _userdata) - end - - hess_ptr = @eval @cfunction($hess_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Dense Hessian function hess_dense(x::Vector{T}, hval::Vector{T}, userdata::userdata_trb{T}) hval[1] = 2.0 - cos(x[1]) @@ -78,15 +58,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_dense_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - hess_dense(_x, _hval, _userdata) - end - - hess_dense_ptr = @eval @cfunction($hess_dense_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian-vector product function hessprod(x::Vector{T}, u::Vector{T}, v::Vector{T}, got_h::Bool, userdata::userdata_trb{T}) @@ -96,17 +67,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hessprod_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, - got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - hessprod(_x, _u, _v, got_h, _userdata) - end - - hessprod_ptr = @eval @cfunction($hessprod_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Bool, Ptr{Cvoid})) - # Sparse Hessian-vector product function shessprod(x::Vector{T}, nnz_v::INT, index_nz_v::Vector{INT}, v::Vector{T}, nnz_u::Vector{INT}, index_nz_u::Vector{INT}, @@ -146,21 +106,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function shessprod_c(n::INT, x::Ptr{T}, nnz_v::INT, index_nz_v::Ptr{INT}, - v::Ptr{T}, nnz_u::Ptr{INT}, index_nz_u::Ptr{INT}, - u::Ptr{T}, got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _index_nz_v = unsafe_wrap(Vector{INT}, index_nz_v, nnz_v) - _nnz_u = unsafe_wrap(Vector{INT}, nnz_u, 1) - _index_nz_u = unsafe_wrap(Vector{INT}, index_nz_u, n) # Is it right? - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - shessprod(_x, nnz_v, _index_nz_v, _v, _nnz_u, _index_nz_u, _u, got_h, _userdata) - end - - shessprod_ptr = @eval @cfunction($shessprod_c, $INT, ($INT, Ptr{$T}, $INT, Ptr{$INT}, Ptr{$T}, Ptr{$INT}, Ptr{$INT}, Ptr{$T}, Bool, Ptr{Cvoid})) - # Apply preconditioner function prec(x::Vector{T}, u::Vector{T}, v::Vector{T}, userdata::userdata_trb{T}) @@ -170,16 +115,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function prec_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - prec(_x, _u, _v, _userdata) - end - - prec_ptr = @eval @cfunction($prec_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Objective function function fun_diag(x::Vector{T}, f::Vector{T}, userdata::userdata_trb{T}) p = userdata.p @@ -187,15 +122,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_diag_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - fun_diag(_x, _f, _userdata) - end - - fun_diag_ptr = @eval @cfunction($fun_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad_diag(x::Vector{T}, g::Vector{T}, userdata::userdata_trb{T}) p = userdata.p @@ -205,15 +131,6 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_diag_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - grad_diag(_x, _g, _userdata) - end - - grad_diag_ptr = @eval @cfunction($grad_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess_diag(x::Vector{T}, hval::Vector{T}, userdata::userdata_trb{T}) hval[1] = -cos(x[1]) @@ -222,14 +139,13 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_diag_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_trb{T} - hess_diag(_x, _hval, _userdata) - end - - hess_diag_ptr = @eval @cfunction($hess_diag_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + # Pointer to C-compatible functions that wraps the Julia functions + obj_ptr = galahad_f(T, INT) + grad_ptr = galahad_g(T, INT) + hess_ptr = galahad_h(T, INT) + hessprod_ptr = galahad_hprod(T, INT) + shessprod_ptr = galahad_shprod(T, INT) + prec_ptr = galahad_prec(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() @@ -237,8 +153,15 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s inform = Ref{trb_inform_type{T,INT}}() # Set user data - userdata = userdata_trb{T}(4) + pass_userdata = true + userdata = userdata_trb{T}(4, pass_userdata, fun, grad, hess, nothing, nothing, prec) userdata_ptr = pointer_from_objref(userdata) + userdata_dense = userdata_trb{T}(4, pass_userdata, fun, grad, hess_dense, nothing, nothing, prec) + userdata_dense_ptr = pointer_from_objref(userdata_dense) + userdata_diag = userdata_trb{T}(4, pass_userdata, fun_diag, grad_diag, hess_diag, nothing, nothing, prec) + userdata_diag_ptr = pointer_from_objref(userdata_diag) + userdata_nh = userdata_trb{T}(4, pass_userdata, fun, grad, hess, hessprod, shessprod, prec) + userdata_nh_ptr = pointer_from_objref(userdata_nh) # Set problem data n = INT(3) # dimension @@ -274,35 +197,35 @@ function test_trb(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s if d == 1 st = 'C' trb_import(T, INT, control, data, status, n, "coordinate", ne, H_row, H_col, C_NULL) - trb_solve_with_mat(T, INT, data, userdata_ptr, status, n, x_l, x_u, x, g, ne, fun_ptr, grad_ptr, hess_ptr, prec_ptr) + trb_solve_with_mat(T, INT, data, userdata_ptr, status, n, x_l, x_u, x, g, ne, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # sparse by rows if d == 2 st = 'R' trb_import(T, INT, control, data, status, n, "sparse_by_rows", ne, C_NULL, H_col, H_ptr) - trb_solve_with_mat(T, INT, data, userdata_ptr, status, n, x_l, x_u, x, g, ne, fun_ptr, grad_ptr, hess_ptr, prec_ptr) + trb_solve_with_mat(T, INT, data, userdata_ptr, status, n, x_l, x_u, x, g, ne, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # dense if d == 3 st = 'D' trb_import(T, INT, control, data, status, n, "dense", ne_dense, C_NULL, C_NULL, C_NULL) - trb_solve_with_mat(T, INT, data, userdata_ptr, status, n, x_l, x_u, x, g, ne_dense, fun_ptr, grad_ptr, hess_dense_ptr, prec_ptr) + trb_solve_with_mat(T, INT, data, userdata_dense_ptr, status, n, x_l, x_u, x, g, ne_dense, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # diagonal if d == 4 st = 'I' trb_import(T, INT, control, data, status, n, "diagonal", n, C_NULL, C_NULL, C_NULL) - trb_solve_with_mat(T, INT, data, userdata_ptr, status, n, x_l, x_u, x, g, n, fun_diag_ptr, grad_diag_ptr, hess_diag_ptr, prec_ptr) + trb_solve_with_mat(T, INT, data, userdata_diag_ptr, status, n, x_l, x_u, x, g, n, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # access by products if d == 5 st = 'P' trb_import(T, INT, control, data, status, n, "absent", ne, C_NULL, C_NULL, C_NULL) - trb_solve_without_mat(T, INT, data, userdata_ptr, status, n, x_l, x_u, x, g, fun_ptr, grad_ptr, hessprod_ptr, shessprod_ptr, prec_ptr) + trb_solve_without_mat(T, INT, data, userdata_nh_ptr, status, n, x_l, x_u, x, g, obj_ptr, grad_ptr, hessprod_ptr, shessprod_ptr, prec_ptr) end # Record solution information diff --git a/GALAHAD.jl/test/test_tru.jl b/GALAHAD.jl/test/test_tru.jl index f36c054e0e..009ce0080c 100644 --- a/GALAHAD.jl/test/test_tru.jl +++ b/GALAHAD.jl/test/test_tru.jl @@ -10,6 +10,12 @@ using Quadmath # Custom userdata struct mutable struct userdata_tru{T} p::T + pass_userdata::Bool + eval_f::Function + eval_g::Function + eval_h::Union{Function, Nothing} + eval_hprod::Union{Function, Nothing} + eval_prec::Function end function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="sytr", dls::String="potr") where {T,INT} @@ -21,15 +27,6 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - fun(_x, _f, _userdata) - end - - fun_ptr = @eval @cfunction($fun_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad(x::Vector{T}, g::Vector{T}, userdata::userdata_tru{T}) p = userdata.p @@ -39,15 +36,6 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - grad(_x, _g, _userdata) - end - - grad_ptr = @eval @cfunction($grad_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess(x::Vector{T}, hval::Vector{T}, userdata::userdata_tru) hval[1] = 2.0 - cos(x[1]) @@ -58,15 +46,6 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - hess(_x, _hval, _userdata) - end - - hess_ptr = @eval @cfunction($hess_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Dense Hessian function hess_dense(x::Vector{T}, hval::Vector{T}, userdata::userdata_tru{T}) hval[1] = 2.0 - cos(x[1]) @@ -78,15 +57,6 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_dense_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - hess_dense(_x, _hval, _userdata) - end - - hess_dense_ptr = @eval @cfunction($hess_dense_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian-vector product function hessprod(x::Vector{T}, u::Vector{T}, v::Vector{T}, got_h::Bool, userdata::userdata_tru{T}) @@ -96,17 +66,6 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hessprod_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, - got_h::Bool, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - hessprod(_x, _u, _v, got_h, _userdata) - end - - hessprod_ptr = @eval @cfunction($hessprod_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Bool, Ptr{Cvoid})) - # Apply preconditioner function prec(x::Vector{T}, u::Vector{T}, v::Vector{T}, userdata::userdata_tru{T}) @@ -116,16 +75,6 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function prec_c(n::INT, x::Ptr{T}, u::Ptr{T}, v::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _u = unsafe_wrap(Vector{T}, u, n) - _v = unsafe_wrap(Vector{T}, v, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - prec(_x, _u, _v, _userdata) - end - - prec_ptr = @eval @cfunction($prec_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Objective function function fun_diag(x::Vector{T}, f::Vector{T}, userdata::userdata_tru{T}) p = userdata.p @@ -133,15 +82,6 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function fun_diag_c(n::INT, x::Ptr{T}, f::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _f = unsafe_wrap(Vector{T}, f, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - fun_diag(_x, _f, _userdata) - end - - fun_diag_ptr = @eval @cfunction($fun_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Gradient of the objective function grad_diag(x::Vector{T}, g::Vector{T}, userdata::userdata_tru{T}) p = userdata.p @@ -151,15 +91,6 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function grad_diag_c(n::INT, x::Ptr{T}, g::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _g = unsafe_wrap(Vector{T}, g, n) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - grad_diag(_x, _g, _userdata) - end - - grad_diag_ptr = @eval @cfunction($grad_diag_c, $INT, ($INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) - # Hessian of the objective function hess_diag(x::Vector{T}, hval::Vector{T}, userdata::userdata_tru{T}) hval[1] = -cos(x[1]) @@ -168,14 +99,12 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s return INT(0) end - function hess_diag_c(n::INT, ne::INT, x::Ptr{T}, hval::Ptr{T}, userdata::Ptr{Cvoid}) - _x = unsafe_wrap(Vector{T}, x, n) - _hval = unsafe_wrap(Vector{T}, hval, ne) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_tru{T} - hess_diag(_x, _hval, _userdata) - end - - hess_diag_ptr = @eval @cfunction($hess_diag_c, $INT, ($INT, $INT, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + # Pointer to C-compatible functions that wraps the Julia functions + obj_ptr = galahad_f(T, INT) + grad_ptr = galahad_g(T, INT) + hess_ptr = galahad_h(T, INT) + hessprod_ptr = galahad_hprod(T, INT) + prec_ptr = galahad_prec(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() @@ -183,13 +112,20 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s inform = Ref{tru_inform_type{T,INT}}() # Set user data - userdata = userdata_tru{T}(4) + pass_userdata = true + userdata = userdata_tru{T}(4, pass_userdata, fun, grad, hess, nothing, prec) userdata_ptr = pointer_from_objref(userdata) + userdata_dense = userdata_tru{T}(4, pass_userdata, fun, grad, hess_dense, nothing, prec) + userdata_dense_ptr = pointer_from_objref(userdata_dense) + userdata_diag = userdata_tru{T}(4, pass_userdata, fun_diag, grad_diag, hess_diag, nothing, prec) + userdata_diag_ptr = pointer_from_objref(userdata_diag) + userdata_nh = userdata_tru{T}(4, pass_userdata, fun, grad, hess, hessprod, prec) + userdata_nh_ptr = pointer_from_objref(userdata_nh) # Set problem data n = INT(3) # dimension ne = INT(5) # Hesssian elements - ne_dense = div(n * (n + 1), 2) # dense Hesssian elements + ne_dense = div(n * (n + 1), 2) |> INT # dense Hesssian elements H_row = INT[1, 2, 3, 3, 3] # Hessian H H_col = INT[1, 2, 1, 2, 3] # NB lower triangle H_ptr = INT[1, 2, 3, 6] # row pointers @@ -225,35 +161,35 @@ function test_tru(::Type{T}, ::Type{INT}; mode::String="reverse", sls::String="s st = 'C' # @reset control[].print_level = INT(1) tru_import(T, INT, control, data, status, n, "coordinate", ne, H_row, H_col, C_NULL) - tru_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne, fun_ptr, grad_ptr, hess_ptr, prec_ptr) + tru_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # sparse by rows if d == 2 st = 'R' tru_import(T, INT, control, data, status, n, "sparse_by_rows", ne, C_NULL, H_col, H_ptr) - tru_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne, fun_ptr, grad_ptr, hess_ptr, prec_ptr) + tru_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # dense if d == 3 st = 'D' tru_import(T, INT, control, data, status, n, "dense", ne_dense, C_NULL, C_NULL, C_NULL) - tru_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, ne_dense, fun_ptr, grad_ptr, hess_dense_ptr, prec_ptr) + tru_solve_with_mat(T, INT, data, userdata_dense_ptr, status, n, x, g, ne_dense, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # diagonal if d == 4 st = 'I' tru_import(T, INT, control, data, status, n, "diagonal", n, C_NULL, C_NULL, C_NULL) - tru_solve_with_mat(T, INT, data, userdata_ptr, status, n, x, g, n, fun_diag_ptr, grad_diag_ptr, hess_diag_ptr, prec_ptr) + tru_solve_with_mat(T, INT, data, userdata_diag_ptr, status, n, x, g, n, obj_ptr, grad_ptr, hess_ptr, prec_ptr) end # access by products if d == 5 st = 'P' tru_import(T, INT, control, data, status, n, "absent", ne, C_NULL, C_NULL, C_NULL) - tru_solve_without_mat(T, INT, data, userdata_ptr, status, n, x, g, fun_ptr, grad_ptr, hessprod_ptr, prec_ptr) + tru_solve_without_mat(T, INT, data, userdata_nh_ptr, status, n, x, g, obj_ptr, grad_ptr, hessprod_ptr, prec_ptr) end tru_information(T, INT, data, inform, status) diff --git a/GALAHAD.jl/test/test_ugo.jl b/GALAHAD.jl/test/test_ugo.jl index bd7c1391d5..1a0db23721 100644 --- a/GALAHAD.jl/test/test_ugo.jl +++ b/GALAHAD.jl/test/test_ugo.jl @@ -10,6 +10,10 @@ using Quadmath # Custom userdata struct mutable struct userdata_ugo{T} a::T + pass_userdata::Bool + eval_f::Function + eval_g::Function + eval_h::Function end function test_ugo(::Type{T}, ::Type{INT}; mode::String="reverse") where {T,INT} @@ -34,28 +38,17 @@ function test_ugo(::Type{T}, ::Type{INT}; mode::String="reverse") where {T,INT} return res end - # Evaluate test problem objective, first and second derivatives - function eval_fgh(x::T, f::Ptr{T}, g::Ptr{T}, h::Ptr{T}, userdata::Ptr{Cvoid})::INT - _f = unsafe_wrap(Vector{T}, f, 1) - _g = unsafe_wrap(Vector{T}, g, 1) - _h = unsafe_wrap(Vector{T}, h, 1) - _userdata = unsafe_pointer_to_objref(userdata)::userdata_ugo{T} - - _f[1] = objf(x, _userdata) - _g[1] = gradf(x, _userdata) - _h[1] = hessf(x, _userdata) - return INT(0) - end - - eval_fgh_ptr = @eval @cfunction($eval_fgh, $INT, ($T, Ptr{$T}, Ptr{$T}, Ptr{$T}, Ptr{Cvoid})) + # Pointer to a C-compatible function that wraps the Julia functions objf, gradf, and hessf + eval_fgh_ptr = galahad_fgh(T, INT) # Derived types data = Ref{Ptr{Cvoid}}() control = Ref{ugo_control_type{T,INT}}() inform = Ref{ugo_inform_type{T,INT}}() - # Set user data - userdata = userdata_ugo{T}(10) + # Boolean indicating whether objf, gradf, and hessf should receive "userdata" as their last argument + use_userdata = true + userdata = userdata_ugo{T}(10, use_userdata, objf, gradf, hessf) userdata_ptr = pointer_from_objref(userdata) # Initialize UGO