From 0a07832811693422069ae4b4be307653d5d257c2 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Mon, 12 Feb 2024 12:57:47 -0500 Subject: [PATCH] More tests for the Julia interfaces --- GALAHAD.jl/gen/examples.jl | 57 +-- GALAHAD.jl/test/UGO.SPC | 0 GALAHAD.jl/test/runtests.jl | 12 +- GALAHAD.jl/test/test_blls.jl | 393 ++++++++++++++++---- GALAHAD.jl/test/test_bllsb.jl | 21 +- GALAHAD.jl/test/test_clls.jl | 21 +- GALAHAD.jl/test/test_dgo.jl | 670 ++++++++++++++++++++++++++++++++++ GALAHAD.jl/test/test_dps.jl | 10 +- GALAHAD.jl/test/test_dqp.jl | 406 ++++++++++---------- GALAHAD.jl/test/test_eqp.jl | 62 +--- GALAHAD.jl/test/test_fdc.jl | 96 ++--- GALAHAD.jl/test/test_llsr.jl | 219 +++++++++++ GALAHAD.jl/test/test_llst.jl | 30 +- GALAHAD.jl/test/test_nls.jl | 2 +- GALAHAD.jl/test/test_psls.jl | 8 +- GALAHAD.jl/test/test_rqs.jl | 455 +++++++++++------------ GALAHAD.jl/test/test_trb.jl | 510 ++++++++++++++++++++++++++ GALAHAD.jl/test/test_ugo.jl | 5 +- 18 files changed, 2257 insertions(+), 720 deletions(-) create mode 100644 GALAHAD.jl/test/UGO.SPC diff --git a/GALAHAD.jl/gen/examples.jl b/GALAHAD.jl/gen/examples.jl index 5ae658cbf8..b83aa14dfa 100644 --- a/GALAHAD.jl/gen/examples.jl +++ b/GALAHAD.jl/gen/examples.jl @@ -19,6 +19,10 @@ function examples(package::String, example::String) dst = "../test/test_" * package * ".jl" text = replace(text, " " => "") text = replace(text, "int main(void) {\n\n" => "# test_$package.jl\n# Simple code to test the Julia interface to " * uppercase(package) * "\n\nusing GALAHAD\nusing Test\nusing Printf\nusing Accessors\n\nfunction test_$package()\n") + text = replace(text, "\" i_ipc_ \"" => "i") + text = replace(text, "\" d_ipc_ \"" => "d") + text = replace(text, "ipc_" => "int") + text = replace(text, "rpc_" => "real_wp_") text = replace(text, "//" => "#") text = replace(text, ";" => "") text = replace(text, "&" => "") @@ -27,6 +31,7 @@ function examples(package::String, example::String) text = replace(text, "printf" => "@printf") text = replace(text, "else if" => "elseif") text = replace(text, "}else{" => "else") + text = replace(text, "}elseif" => "elseif") text = replace(text, "} else {" => "else") text = replace(text, "void *data" => "data = Ref{Ptr{Cvoid}}()") text = replace(text, "struct $(package)_control_type control" => "control = Ref{$(package)_control_type{Float64}}()") @@ -39,38 +44,38 @@ function examples(package::String, example::String) for var in ("A_val", "A_dense", "b", "c", "c_l", "c_u", "x_l", "x_u", "y_l", "y_u", "z_l", "z_u", "g", "x_0", "w", "x", "y", "z", "val", "dense", "rhs", "rhst", "sol", "H_val", "H_dense", "C_val", "C_dense", "H_diag", "C_diag", "H_scid", "C_scid", "Ao_val", "r", "M_val", "M_dense", - "M_diag", "y", "W") - text = replace(text, "rpc_ $var[] = {" => "$var = Float64[") + "M_diag", "y", "W", "Ao_dense") + text = replace(text, "real_wp_ $var[] = {" => "$var = Float64[") end for var in ("f", "power", "weight", "shift", "radius", "half_radius", "x_l", "x_u", "sigma", "rho_g", "rho_b") - text = replace(text, "rpc_ $var =" => "$var =") + text = replace(text, "real_wp_ $var =" => "$var =") end for var in ("n", "ne", "m", "A_ne", "A_dense_ne", "H_ne", "H_dense_ne", "C_dense_ne", "C_ne", "dense_ne", "o", "Ao_ne", "Ao_ptr_ne", "A_ptr_ne", "m_equal", - "M_ne", "M_dense_ne", "j_ne", "h_ne", "p_ne") - text = replace(text, "ipc_ $var =" => "$var =") + "M_ne", "M_dense_ne", "j_ne", "h_ne", "p_ne", "Ao_dense_ne") + text = replace(text, "int $var =" => "$var =") end for var in ("A_row", "A_col", "A_ptr", "row", "col", "ptr", "c_stat", "x_stat", "H_row", "H_col", "H_ptr", "C_row", "C_col", "C_ptr", "Ao_col", "Ao_ptr", "Ao_row", "M_row", "M_col", "M_ptr", "J_row", "J_col", "J_ptr", "P_row", "P_ptr") - text = replace(text, "ipc_ $var[] = {" => "$var = Cint[") + text = replace(text, "int $var[] = {" => "$var = Cint[") end for val in ("1", "3", "5", "6", "7", "n", "n+m") - text = replace(text, "for( ipc_ d=1 d <= $val d++){" => "for d = 1:$val") - text = replace(text, "for(ipc_ d=1 d <= $val d++){" => "for d = 1:$val") + text = replace(text, "for( int d=1 d <= $val d++){" => "for d = 1:$val") + text = replace(text, "for(int d=1 d <= $val d++){" => "for d = 1:$val") end for index in ("unit_m", "new_radius", "a_is", "m_is") - text = replace(text, "for( ipc_ $index=0 $index <= 1 $index++){" => "for $index = 0:1") - text = replace(text, "for(ipc_ $index=0 $index <= 1 $index++){" => "for $index = 0:1") + text = replace(text, "for( int $index=0 $index <= 1 $index++){" => "for $index = 0:1") + text = replace(text, "for(int $index=0 $index <= 1 $index++){" => "for $index = 0:1") end - for val in ("c", "g", "u", "v", "x", "r", "vector", "h_vector", "error") - text = replace(text, "rpc_ $val[n]" => "$val = zeros(Float64, n)") - text = replace(text, "rpc_ $val[m]" => "$val = zeros(Float64, m)") - text = replace(text, "rpc_ $val[o]" => "$val = zeros(Float64, o)") + for val in ("c", "g", "u", "v", "x", "w", "z", "x_l", "x_u", "r", "vector", "h_vector", "error") + text = replace(text, "real_wp_ $val[n]" => "$val = zeros(Float64, n)") + text = replace(text, "real_wp_ $val[m]" => "$val = zeros(Float64, m)") + text = replace(text, "real_wp_ $val[o]" => "$val = zeros(Float64, o)") end for val in ("x_stat", "c_stat", "index_nz_u", "index_nz_v", "depen") - text = replace(text, "ipc_ $val[n]" => "$val = zeros(Cint, n)") - text = replace(text, "ipc_ $val[m]" => "$val = zeros(Cint, m)") + text = replace(text, "int $val[n]" => "$val = zeros(Cint, n)") + text = replace(text, "int $val[m]" => "$val = zeros(Cint, m)") end text = replace(text, "if(" => "if ") @@ -81,9 +86,9 @@ function examples(package::String, example::String) text = replace(text, "}\n" => "]\n") text = replace(text, "NULL" => "Cint[]") text = replace(text, "char st" => "st = ' '") - text = replace(text, "ipc_ status" => "status = Ref{Cint}()") - text = replace(text, "ipc_ n_depen" => "n_depen = Ref{Cint}()") - text = replace(text, "rpc_ radius" => "radius = Ref{Float64}()") + text = replace(text, "int status" => "status = Ref{Cint}()") + text = replace(text, "int n_depen" => "n_depen = Ref{Cint}()") + text = replace(text, "real_wp_ radius" => "radius = Ref{Float64}()") text = replace(text, " ]" => "]") text = replace(text, "== 0)" => "== 0") text = replace(text, "case 1: # sparse co-ordinate storage" => "# sparse co-ordinate storage\nif d == 1") @@ -94,14 +99,18 @@ function examples(package::String, example::String) text = replace(text, "case 6: # identity" => "# identity\nif d == 6") text = replace(text, "case 7: # zero" => "# zero\nif d == 7") text = replace(text, "break\n" => "end\n") - text = replace(text, "ipc_ maxabsarray(rpc_ a[], ipc_ n, rpc_ *maxabs)" => "maxabsarray(a) = maximum(abs.(a))") + text = replace(text, "int maxabsarray(real_wp_ a[], int n, real_wp_ *maxabs)" => "maxabsarray(a) = maximum(abs.(a))") for i = 0:5 text = replace(text, "( status == $i ) {" => "status == $i") end text = replace(text, "( status < 0 ) {" => "status < 0") text = replace(text, "while(true)" => "while true") - text = replace(text, "for( ipc_ i = 0 i < n i++)" => "for i = 1:n") - text = replace(text, "for( ipc_ i = 0 i < m i++)" => "for i = 1:m") + text = replace(text, "for( int i = 0 i < n i++)" => "for i = 1:n") + text = replace(text, "for( int i = 0 i < m i++)" => "for i = 1:m") + text = replace(text, "for( int i = 1 i < n i++)" => "for i = 2:n") + text = replace(text, "for( int i = 1 i < m i++)" => "for i = 2:m") + text = replace(text, "for( int i = 2 i < n i++)" => "for i = 3:n") + text = replace(text, "for( int i = 2 i < m i++)" => "for i = 3:m") text = replace(text, "constrastatus = Ref{Cint}()" => "constraint status") text = replace(text, "}#" => "] #") text = replace(text, "#for" => "# for") @@ -113,8 +122,8 @@ function examples(package::String, example::String) text = replace(text, "for(i=0 i "for i = 1:n\n") text = replace(text, "}\n" => "end\n") for var in ("x", "u", "v", "hval", "g") - text = replace(text, "const rpc_ $var[]" => "var::Vector{Float64}") - text = replace(text, "rpc_ $var[]" => "$var::Vector{Float64}") + text = replace(text, "const real_wp_ $var[]" => "var::Vector{Float64}") + text = replace(text, "real_wp_ $var[]" => "$var::Vector{Float64}") end text = text * "end\n\n@testset \"" * uppercase(package) * "\" begin\n @test test_$package() == 0\nend\n" write(dst, text) diff --git a/GALAHAD.jl/test/UGO.SPC b/GALAHAD.jl/test/UGO.SPC new file mode 100644 index 0000000000..e69de29bb2 diff --git a/GALAHAD.jl/test/runtests.jl b/GALAHAD.jl/test/runtests.jl index 4440d1e2eb..e913ee6bbf 100644 --- a/GALAHAD.jl/test/runtests.jl +++ b/GALAHAD.jl/test/runtests.jl @@ -5,7 +5,7 @@ include("test_structures.jl") # include("test_arc.jl") # include("test_bgo.jl") -# include("test_blls.jl") +## include("test_blls.jl") include("test_bllsb.jl") # include("test_bqp.jl") include("test_bqpb.jl") @@ -15,11 +15,11 @@ include("test_clls.jl") include("test_convert.jl") include("test_cqp.jl") include("test_cro.jl") -# include("test_dgo.jl") +## include("test_dgo.jl") include("test_dps.jl") -# include("test_dqp.jl") +include("test_dqp.jl") include("test_eqp.jl") -# include("test_fdc.jl") +include("test_fdc.jl") include("test_fit.jl") include("test_glrt.jl") include("test_gls.jl") @@ -28,7 +28,7 @@ include("test_hash.jl") include("test_ir.jl") include("test_l2rt.jl") include("test_lhs.jl") -# include("test_llsr.jl") +## include("test_llsr.jl") ## include("test_llst.jl") include("test_lms.jl") include("test_lpa.jl") @@ -43,7 +43,7 @@ include("test_qpa.jl") include("test_qpb.jl") include("test_roots.jl") # include("test_rpd.jl") -# include("test_rqs.jl") +## include("test_rqs.jl") include("test_sbls.jl") ## include("test_scu.jl") include("test_sec.jl") diff --git a/GALAHAD.jl/test/test_blls.jl b/GALAHAD.jl/test/test_blls.jl index dda558113a..0b5d8bc813 100644 --- a/GALAHAD.jl/test/test_blls.jl +++ b/GALAHAD.jl/test/test_blls.jl @@ -2,107 +2,362 @@ # Simple code to test the Julia interface to BLLS using GALAHAD +using Test using Printf +using Accessors -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = blls_control_type{Float64}() -inform = blls_inform_type{Float64}() - -# Set problem data -n = 3 # dimension -o = 4 # number of observations -Ao_ne = 7 # design matrix elements -Ao_row = Cint[1, 1, 2, 2, 3, 3, 4] # row indices -Ao_col = Cint[1, 2, 2, 1, 3, 2] # column indices -Ao_ptr_ne = o + 1 # row pointer length -Ao_ptr = Cint[1, 3, 5, 7, 8] # row pointers -Ao_val = Float64[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] # values -b = Float64[2.0, 2.0, 3.0, 1.0] # observations -x_l = Float64[-1.0, -Inf, -Inf] # variable lower bound -x_u = Float64[1.0, Inf, 2.0] # variable upper bound -sigma = 1.0 # regularization weight -w = Float64[1.0, 1.0, 1.0, 2.0] # values - -# Set output storage -r = zeros(Float64, o) # residuals -g = zeros(Float64, n) # gradient -x_stat = zeros(Cint, n) # variable status -st = ' ' -status = Ref{Cint}() - -@printf(" Fortran sparse matrix indexing\n\n") -@printf(" basic tests of blls storage formats\n\n") - -for d = 1:3 +# Custom userdata struct +struct userdata_type + scale::Float64 +end - # Initialize BLLS - blls_initialize( data, control, status ) +function test_blls() + # Apply preconditioner + function prec(n::Int, var::Vector{Float64}, p::Vector{Float64}, userdata::userdata_type) + scale = userdata.scale + for i in 1:n + p[i] = scale * v[i] + end + return 0 + end - # Set user-defined control options - control.f_indexing = true # Fortran sparse matrix indexing + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{blls_control_type{Float64}}() + inform = Ref{blls_inform_type{Float64}}() - # Start from 0 - x = Float64[0.0,0.0,0.0] - z = Float64[0.0,0.0,0.0] + # Set user data + userdata = userdata_type(1.0) - # sparse co-ordinate storage - if d == 1 - global st = 'C' + # Set problem data + n = 10 # dimension + o = n + 1 # number of residuals + Ao_ne = 2 * n # sparse Jacobian elements + Ao_dense_ne = o * n # dense Jacobian elements + # row-wise storage + Ao_row = zeros(Cint, Ao_ne) # row indices, + Ao_col = zeros(Cint, Ao_ne) # column indices + Ao_ptr_ne = o + 1 # number of row pointers + Ao_ptr = zeros(Cint, Ao_ptr_ne) # row pointers + Ao_val = zeros(Float64, Ao_ne) # values + Ao_dense = zeros(Float64, Ao_dense_ne) # dense values + # column-wise storage + Ao_by_col_row = zeros(Cint, Ao_ne) # row indices, + Ao_by_col_ptr_ne = n + 1 # number of column pointers + Ao_by_col_ptr = zeros(Cint, Ao_by_col_ptr_ne) # column pointers + Ao_by_col_val = zeros(Float64, Ao_ne) # values + Ao_by_col_dense = zeros(Float64, Ao_dense_ne) # dense values + b = zeros(Float64, o) # linear term in the objective + x_l = zeros(Float64, n) # variable lower bound + x_u = zeros(Float64, n) # variable upper bound + x = zeros(Float64, n) # variables + z = zeros(Float64, n) # dual variables + r = zeros(Float64, o) # residual + g = zeros(Float64, n) # gradient + w = zeros(Float64, o) # weights - blls_import( control, data, status, n, o, - "coordinate", Ao_ne, Ao_row, Ao_col, 0, Cint[] ) + # Set output storage + x_stat = zeros(Cint, n) # variable status + st = ' ' + status = Ref{Cint}() - blls_solve_blls_given_a( data, status, n, o, m, Ao_ne, Ao_val, b, sigma, - x_l, x_u, x, z, r, g, x_stat, w, nothing ) + x_l[1] = -1.0 + for i in 2:n + x_l[i] = -Inf + end + x_u[1] = 1.0 + x_u[2] = Inf + for i in 3:n + x_u[i] = 2.0 end - # sparse by rows - if d == 2 - global st = 'R' + # A = ( I ) and b = (i * e) + # (e^T) (n + 1) - blls_import( control, data, status, n, o, - "sparse_by_rows", Ao_ne, Cint[], Ao_col, Ao_ptr_ne, Ao_ptr ) + for i in 1:n + b[i] = i + 1 + end + b[n + 1] = n + 1 + w[1] = 2.0 + w[2] = 1.0 + for i in 3:o + w[i] = 1.0 + end - blls_solve_blls_given_a( data, status, n, o, Ao_ne, Ao_val, b, sigma, - x_l, x_u, x, z, r, g, x_stat, w, nothing ) + # # A by rows + for i in 1:n + Ao_ptr[i] = i + 1 + Ao_row[i] = i + 1 + Ao_col[i] = i + 1 + Ao_val[i] = 1.0 + end + Ao_ptr[n + 1] = n + 1 + for i in 1:n + Ao_row[n + i] = o + Ao_col[n + i] = i + 1 + Ao_val[n + i] = 1.0 end + Ao_ptr[o] = Ao_ne + 1 + l = 0 + for i in 1:n + for j in 1:n + l = l + 1 + if i == j + Ao_dense[l] = 1.0 + else + Ao_dense[l] = 0.0 + end + end + end + for j in 1:n + l = l + 1 + Ao_dense[l] = 1.0 + end + + # # A by columns + l = 0 + for j in 1:n + l = l + 1 + Ao_by_col_ptr[j] = l + 1 + Ao_by_col_row[l] = j + 1 + Ao_by_col_val[l] = 1.0 + l = l + 1 + Ao_by_col_row[l] = o + Ao_by_col_val[l] = 1.0 + end + Ao_by_col_ptr[n + 1] = Ao_ne + 1 + l = 0 + for j in 1:n + for i in 1:n + l = l + 1 + if i == j + Ao_by_col_dense[l] = 1.0 + else + Ao_by_col_dense[l] = 0.0 + end + end + l = l + 1 + Ao_by_col_dense[l] = 1.0 + end + + @printf(" fortran sparse matrix indexing\n\n") + @printf(" basic tests of blls storage formats\n\n") + + for d in 1:5 + + # Initialize BLLS + blls_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # fortran sparse matrix indexing + + # Start from 0 + for i in 1:n + x[i] = 0.0 + z[i] = 0.0 + end + + # sparse co-ordinate storage + if d == 1 + st = "CO" + blls_import(control, data, status, n, o, + "coordinate", Ao_ne, Ao_row, Ao_col, 0, Cint[]) + + blls_solve_given_a(data, userdata, status, n, o, + Ao_ne, Ao_val, b, x_l, x_u, + x, z, r, g, x_stat, w, prec) + end + + # sparse by rows + if d == 2 + st = "SR" + blls_import(control, data, status, n, o, + "sparse_by_rows", Ao_ne, Cint[], Ao_col, + Ao_ptr_ne, Ao_ptr) + + blls_solve_given_a(data, userdata, status, n, o, + Ao_ne, Ao_val, b, x_l, x_u, + x, z, r, g, x_stat, w, prec) + end - # dense - if d == 3 - global st = 'D' + # dense by rows + if d == 3 + st = "DR" + blls_import(control, data, status, n, o, + "dense_by_rows", Ao_dense_ne, + Cint[], Cint[], 0, Cint[]) - Ao_dense_ne = 12 # number of elements of Ao - Ao_dense = Float64[1.0, 1.0, 0.0, 0.0, 1.0, 1.0, - 1.0, 0.0, 1.0, 0.0, 1.0, 0.0] + blls_solve_given_a(data, userdata, status, n, o, + Ao_dense_ne, Ao_dense, b, x_l, x_u, + x, z, r, g, x_stat, w, prec) + end - blls_import( control, data, status, n, o, - "dense", Ao_ne, Cint[], Cint[], 0, Cint[] ) + # sparse by columns + if d == 4 + st = "SC" + blls_import(control, data, status, n, o, + "sparse_by_columns", Ao_ne, Ao_by_col_row, + Cint[], Ao_by_col_ptr_ne, Ao_by_col_ptr) - blls_solve_blls_given_a( data, status, n, o, Ao_dense_ne, Ao_dense, b, - sigma, x_l, x_u, x, z, r, g, x_stat, w, nothing ) + blls_solve_given_a(data, userdata, status, n, o, + Ao_ne, Ao_by_col_val, b, x_l, x_u, + x, z, r, g, x_stat, w, prec) + end + + # dense by columns + if d == 5 + st = "DC" + blls_import(control, data, status, n, o, + "dense_by_columns", Ao_dense_ne, + Cint[], Cint[], 0, Cint[]) + + blls_solve_given_a(data, userdata, status, n, o, + Ao_dense_ne, Ao_by_col_dense, b, x_l, x_u, + x, z, r, g, x_stat, w, prec) + end + + blls_information(data, inform, status) + + if inform[].status == 0 + @printf("%s:%6i iterations. Optimal objective value = %5.2f status = %1i\n", + st, inform[].iter, inform[].obj, inform[].status) + else + @printf("%s: BLLS_solve exit status = %1i\n", st, inform[].status) + end + + # @printf("x: ") + # for i = 1:n + # @printf("%f ", x[i]) + # @printf("\n") + # @printf("gradient: ") + # for i = 1:n + # @printf("%f ", g[i]) + # @printf("\n") + + # Delete internal workspace + blls_terminate(data, control, inform) + @printf("\n tests reverse-communication options\n\n") + end + + # reverse-communication input/output + on = max(o, n) + # int eval_status, nz_v_start, nz_v_end, nz_p_end + # int nz_v[on], nz_p[o], mask[o] + # real_wp_ v[on], p[on] + + nz_p_end = 0 + + # Initialize BLLS + blls_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # fortran sparse matrix indexing + + # Start from 0 + for i in 1:n + x[i] = 0.0 + z[i] = 0.0 + end + + st = "RC" + for i in 1:o + mask[i] = 0 end + blls_import_without_a(control, data, status, n, o) - blls_information( data, inform, status ) + terminated = false + while !terminated # reverse-communication loop + blls_solve_reverse_a_prod(data, status, eval_status, n, o, b, + x_l, x_u, x, z, r, g, x_stat, v, p, + nz_v, nz_v_start, nz_v_end, + nz_p, nz_p_end, w) - if inform.status == 0 - @printf("%c:%6i iterations. Optimal objective value = %5.2f status = %1i\n", st, inform.iter, inform.obj, inform.status) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate p = Av + p[n + 1] = 0.0 + for i in 1:n + p[i] = v[i] + p[n + 1] = p[n + 1] + v[i] + end + elseif status[] == 3 # evaluate p = A^Tv + for i in 1:n + p[i] = v[i] + v[n + 1] + end + elseif status[] == 4 # evaluate p = Av for sparse v + p[n + 1] = 0.0 + for i in 1:n + p[i] = 0.0 + end + for l in (nz_v_start - 1):nz_v_end + i = nz_v[l] + p[i] = v[i] + p[n + 1] = p[n + 1] + v[i] + end + elseif status[] == 5 # evaluate p = sparse Av for sparse v + nz_p_end = 0 + for l in (nz_v_start - 1):nz_v_end + i = nz_v[l] - 1 + if mask[i] == 0 + mask[i] = 1 + nz_p[nz_p_end] = i + 1 + nz_p_end = nz_p_end + 1 + p[i] = v[i] + end + if mask[n + 1] == 0 + mask[n + 1] = 1 + nz_p[nz_p_end] = o + nz_p_end = nz_p_end + 1 + p[n + 1] = v[i] + else + p[n + 1] = p[n + 1] + v[i] + end + for l in 1:nz_p_end + mask[nz_p[l] - 1] = 0 + end + end + elseif status[] == 6 # evaluate p = sparse A^Tv + for l in (nz_v_start - 1):nz_v_end + i = nz_v[l] - 1 + p[i] = v[i] + v[n + 1] + end + elseif status[] == 7 # evaluate p = P^{-}v + for i in 1:n + p[i] = userdata.scale * v[i] + end + else + @printf(" the value %1i of status should not occur\n", status) + end + eval_status = 0 + end + + # Record solution information + blls_information(data, inform, status) + + # Print solution details + if inform[].status == 0 + @printf("%s:%6i iterations. Optimal objective value = %5.2f status = %1i\n", + st, inform[].iter, inform[].obj, inform[].status) else - @printf("%c: BLLS_solve exit status = %1i\n", st, inform.status) + @printf("%s: BLLS_solve exit status = %1i\n", st, inform[].status) end # @printf("x: ") # for i = 1:n # @printf("%f ", x[i]) - # end # @printf("\n") # @printf("gradient: ") # for i = 1:n # @printf("%f ", g[i]) - # end # @printf("\n") # Delete internal workspace - blls_terminate( data, control, inform ) + return blls_terminate(data, control, inform) +end + +@testset "BLLS" begin + @test test_blls() == 0 end diff --git a/GALAHAD.jl/test/test_bllsb.jl b/GALAHAD.jl/test/test_bllsb.jl index 8fe0ad5a09..3c251b9602 100644 --- a/GALAHAD.jl/test/test_bllsb.jl +++ b/GALAHAD.jl/test/test_bllsb.jl @@ -36,25 +36,8 @@ function test_bllsb() # Set user-defined control options @reset control[].f_indexing = true # Fortran sparse matrix indexing - @reset control[].symmetric_linear_solver = convert(NTuple{31,Int8}, - (112, 111, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) - - @reset control[].fdc_control.symmetric_linear_solver = convert(NTuple{31,Int8}, - (112, 111, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) + @reset control[].symmetric_linear_solver = galahad_linear_solver("potr") + @reset control[].fdc_control.symmetric_linear_solver = galahad_linear_solver("potr") @reset control[].fdc_control.use_sls = true # Start from 0 diff --git a/GALAHAD.jl/test/test_clls.jl b/GALAHAD.jl/test/test_clls.jl index fbd39f59c3..8bab23fcdf 100644 --- a/GALAHAD.jl/test/test_clls.jl +++ b/GALAHAD.jl/test/test_clls.jl @@ -41,25 +41,8 @@ function test_clls() # Set user-defined control options @reset control[].f_indexing = true # Fortran sparse matrix indexing - @reset control[].symmetric_linear_solver = convert(NTuple{31,Int8}, - (112, 111, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) - - @reset control[].fdc_control.symmetric_linear_solver = convert(NTuple{31,Int8}, - (112, 111, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) + @reset control[].symmetric_linear_solver = galahad_linear_solver("potr") + @reset control[].fdc_control.symmetric_linear_solver = galahad_linear_solver("potr") @reset control[].fdc_control.use_sls = true # Start from 0 diff --git a/GALAHAD.jl/test/test_dgo.jl b/GALAHAD.jl/test/test_dgo.jl index e69de29bb2..689eb7d1cc 100644 --- a/GALAHAD.jl/test/test_dgo.jl +++ b/GALAHAD.jl/test/test_dgo.jl @@ -0,0 +1,670 @@ +# test_dgo.jl +# Simple code to test the Julia interface to DGO + +using GALAHAD +using Test +using Printf +using Accessors + +# Custom userdata struct +struct userdata_type + p::Float64 + freq::Float64 + mag::Float64 +end + +function test_dgo() + + # Objective function + function fun(n::Int, var::Vector{Float64}, f::Ref{Float64}, userdata::userdata_type) + p = userdata.p + freq = userdata.freq + mag = userdata.mag + + f[] = (x[1] + x[3] + p)^2 + (x[2] + x[3])^2 + mag * cos(freq * x[1]) + x[1] + x[2] + + x[3] + return 0 + end + + # Gradient of the objective + function grad(n::Int, var::Vector{Float64}, g::Vector{Float64}, userdata::userdata_type) + p = userdata.p + freq = userdata.freq + mag = userdata.mag + + g[1] = 2.0 * (x[1] + x[3] + p) - mag * freq * sin(freq * x[1]) + 1 + g[2] = 2.0 * (x[2] + x[3]) + 1 + g[3] = 2.0 * (x[1] + x[3] + p) + 2.0 * (x[2] + x[3]) + 1 + return 0 + end + + # # Hessian of the objective + # int hess(int n, + # int ne, + # var::Vector{Float64}, + # hval::Vector{Float64}, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # hval[0] = 2.0 - mag * freq * freq * cos(freq*x[0]) + # hval[1] = 2.0 + # hval[2] = 2.0 + # hval[3] = 2.0 + # hval[4] = 4.0 + # return 0 + # ] + + # # Dense Hessian + # int hess_dense(int n, + # int ne, + # var::Vector{Float64}, + # hval::Vector{Float64}, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # hval[0] = 2.0 - mag * freq * freq * cos(freq*x[0]) + # hval[1] = 0.0 + # hval[2] = 2.0 + # hval[3] = 2.0 + # hval[4] = 2.0 + # hval[5] = 4.0 + # return 0 + # ] + + # # Hessian-vector product + # int hessprod(int n, + # var::Vector{Float64}, + # u::Vector{Float64}, + # var::Vector{Float64}, + # bool got_h, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # u[0] = u[0] + 2.0 * (v[0] + v[2]) + # - mag * freq * freq * cos(freq*x[0]) * v[0] + # u[1] = u[1] + 2.0 * (v[1] + v[2]) + # u[2] = u[2] + 2.0 * (v[0] + v[1] + 2.0 * v[2]) + # return 0 + # ] + + # # Sparse Hessian-vector product + # int shessprod(int n, + # var::Vector{Float64}, + # int nnz_v, + # const int index_nz_v[], + # var::Vector{Float64}, + # int *nnz_u, + # int index_nz_u[], + # u::Vector{Float64}, + # bool got_h, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # real_wp_ p[] = {0., 0., 0.] + # bool used[] = {false, false, false] + # for(int i = 0 i < nnz_v i++) + # int j = index_nz_v[i] + # switch(j) + # case 1: + # p[0] = p[0] + 2.0 * v[0] + # - mag * freq * freq * cos(freq*x[0]) * v[0] + # used[0] = true + # p[2] = p[2] + 2.0 * v[0] + # used[2] = true + # end + # case 2: + # p[1] = p[1] + 2.0 * v[1] + # used[1] = true + # p[2] = p[2] + 2.0 * v[1] + # used[2] = true + # end + # case 3: + # p[0] = p[0] + 2.0 * v[2] + # used[0] = true + # p[1] = p[1] + 2.0 * v[2] + # used[1] = true + # p[2] = p[2] + 4.0 * v[2] + # used[2] = true + # end + # ] + # ] + # *nnz_u = 0 + # for(int j = 0 j < 3 j++) + # if used[j]) + # u[j] = p[j] + # *nnz_u = *nnz_u + 1 + # index_nz_u[*nnz_u-1] = j+1 + # ] + # ] + # return 0 + # ] + + # # Apply preconditioner + # int prec(int n, + # var::Vector{Float64}, + # u::Vector{Float64}, + # var::Vector{Float64}, + # const void *userdata) + # u[0] = 0.5 * v[0] + # u[1] = 0.5 * v[1] + # u[2] = 0.25 * v[2] + # return 0 + # ] + + # # Objective function + # int fun_diag(int n, + # var::Vector{Float64}, + # real_wp_ *f, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ p = myuserdata->p + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # *f = pow(x[2] + p, 2) + pow(x[1], 2) + mag * cos(freq*x[0]) + # + x[0] + x[1] + x[2] + # return 0 + # ] + + # # Gradient of the objective + # int grad_diag(int n, + # var::Vector{Float64}, + # g::Vector{Float64}, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ p = myuserdata->p + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # g[0] = -mag * freq * sin(freq*x[0]) + 1 + # g[1] = 2.0 * x[1] + 1 + # g[2] = 2.0 * (x[2] + p) + 1 + # return 0 + # ] + + # # Hessian of the objective + # int hess_diag(int n, + # int ne, + # var::Vector{Float64}, + # hval::Vector{Float64}, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # hval[0] = -mag * freq * freq * cos(freq*x[0]) + # hval[1] = 2.0 + # hval[2] = 2.0 + # return 0 + # ] + + # # Hessian-vector product + # int hessprod_diag(int n, + # var::Vector{Float64}, + # u::Vector{Float64}, + # var::Vector{Float64}, + # bool got_h, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # u[0] = u[0] + -mag * freq * freq * cos(freq*x[0]) * v[0] + # u[1] = u[1] + 2.0 * v[1] + # u[2] = u[2] + 2.0 * v[2] + # return 0 + # ] + + # # Sparse Hessian-vector product + # int shessprod_diag(int n, + # var::Vector{Float64}, + # int nnz_v, + # const int index_nz_v[], + # var::Vector{Float64}, + # int *nnz_u, + # int index_nz_u[], + # u::Vector{Float64}, + # bool got_h, + # const void *userdata) + # struct userdata_type *myuserdata = (struct userdata_type *) userdata + # real_wp_ freq = myuserdata->freq + # real_wp_ mag = myuserdata->mag + + # real_wp_ p[] = {0., 0., 0.] + # bool used[] = {false, false, false] + # for(int i = 0 i < nnz_v i++) + # int j = index_nz_v[i] + # switch(j) + # case 1: + # p[0] = p[0] - mag * freq * freq * cos(freq*x[0]) * v[0] + # used[0] = true + # end + # case 2: + # p[1] = p[1] + 2.0 * v[1] + # used[1] = true + # end + # case 3: + # p[2] = p[2] + 2.0 * v[2] + # used[2] = true + # end + # ] + # ] + # *nnz_u = 0 + # for(int j = 0 j < 3 j++) + # if used[j]) + # u[j] = p[j] + # *nnz_u = *nnz_u + 1 + # index_nz_u[*nnz_u-1] = j+1 + # ] + # ] + # return 0 + # ] + # end + + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{dgo_control_type{Float64}}() + inform = Ref{dgo_inform_type{Float64}}() + + # Set user data + userdata = userdata_type(4.0, 10.0, 1000.0) + + # Set problem data + n = 3 # dimension + ne = 5 # Hesssian elements + x_l = Float64[-10, -10, -10] + x_u = Float64[0.5, 0.5, 0.5] + H_row = Cint[1, 2, 3, 3, 3] # Hessian H + H_col = Cint[1, 2, 1, 2, 3] # NB lower triangle + H_ptr = Cint[1, 2, 3, 6] # row pointers + + # Set storage + g = zeros(Float64, n) # gradient + st = ' ' + status = Ref{Cint}() + + @printf(" Fortran sparse matrix indexing\n\n") + @printf(" tests options for all-in-one storage format\n\n") + + for d in 1:5 + + # Initialize DGO + dgo_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + @reset control[].maxit = 2500 + # @reset control[].trb_control[].maxit = 100 + # @reset control[].print_level = 1 + + # Start from 0 + x = Float64[0, 0, 0] + + # sparse co-ordinate storage + if d == 1 + st = 'C' + dgo_import(control, data, status, n, x_l, x_u, + "coordinate", ne, H_row, H_col, Cint[]) + + dgo_solve_with_mat(data, userdata, status, n, x, g, + ne, fun, grad, hess, hessprod, prec) + end + + # sparse by rows + if d == 2 + st = 'R' + dgo_import(control, data, status, n, x_l, x_u, + "sparse_by_rows", ne, Cint[], H_col, H_ptr) + + dgo_solve_with_mat(data, userdata, status, n, x, g, + ne, fun, grad, hess, hessprod, prec) + end + + # dense + if d == 3 + st = 'D' + dgo_import(control, data, status, n, x_l, x_u, + "dense", ne, Cint[], Cint[], Cint[]) + + dgo_solve_with_mat(data, userdata, status, n, x, g, + ne, fun, grad, hess_dense, hessprod, prec) + end + + # diagonal + if d == 4 + st = 'I' + dgo_import(control, data, status, n, x_l, x_u, + "diagonal", ne, Cint[], Cint[], Cint[]) + + dgo_solve_with_mat(data, userdata, status, n, x, g, + ne, fun_diag, grad_diag, hess_diag, + hessprod_diag, prec) + end + + # access by products + if d == 5 + st = 'P' + dgo_import(control, data, status, n, x_l, x_u, + "absent", ne, Cint[], Cint[], Cint[]) + + dgo_solve_without_mat(data, userdata, status, n, x, g, + fun, grad, hessprod, shessprod, prec) + end + + # Record solution information + dgo_information(data, inform, status) + + if inform[].status[] == 0 + @printf("%c:%6i evaluations. Optimal objective value = %5.2f status = %1i\n", st, + inform[].f_eval, inform[].obj, inform[].status) + elseif inform[].status[] == -18 + @printf("%c:%6i evaluations. Best objective value = %5.2f status = %1i\n", st, + inform[].f_eval, inform[].obj, inform[].status) + else + @printf("%c: DGO_solve exit status = %1i\n", st, inform[].status) + end + + # @printf("x: ") + # for i in 1:n + # @printf("%f ", x[i]) + # end + # @printf("\n") + # @printf("gradient: ") + # for i in 1:n + # @printf("%f ", g[i]) + # end + # @printf("\n") + + # Delete internal workspace + dgo_terminate(data, control, inform) + end + + @printf("\n tests reverse-communication options\n\n") + + # reverse-communication input/output + eval_status = Ref{Cint}() + nnz_u = Ref{Cint}() + nnz_v = Ref{Cint}() + f = 0.0 + u = zeros(Float64, n) + v = zeros(Float64, n) + index_nz_u = zeros(Cint, n) + index_nz_v = zeros(Cint, n) + # real_wp_ H_val[ne], H_dense[n*(n+1)/2], H_diag[n] + + for d in 1:5 + # Initialize DGO + dgo_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + @reset control[].maxit = 2500 + # @reset control[].trb_control[].maxit = 100 + # @reset control[].print_level = 1 + + # Start from 0 + x = Float64[0.0, 0.0, 0.0] + + # sparse co-ordinate storage + if d == 1 + st = 'C' + dgo_import(control, data, status, n, x_l, x_u, "coordinate", ne, H_row, H_col, Cint[]) + + terminated = false + while !terminated # reverse-communication loop + dgo_solve_reverse_with_mat(data, status, eval_status, n, x, f, g, ne, H_val, u, v) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate f + eval_status = fun(n, x, f, userdata) + elseif status[] == 3 # evaluate g + eval_status = grad(n, x, g, userdata) + elseif status[] == 4 # evaluate H + eval_status = hess(n, ne, x, H_val, userdata) + elseif status[] == 5 # evaluate Hv product + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 6 # evaluate the product with P + eval_status = prec(n, x, u, v, userdata) + elseif status[] == 23 # evaluate f and g + eval_status = fun(n, x, f, userdata) + eval_status = grad(n, x, g, userdata) + elseif status[] == 25 # evaluate f and Hv product + eval_status = fun(n, x, f, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 35 # evaluate g and Hv product + eval_status = grad(n, x, g, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 235 # evaluate f, g and Hv product + eval_status = fun(n, x, f, userdata) + eval_status = grad(n, x, g, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # sparse by rows + if d == 2 + st = 'R' + dgo_import(control, data, status, n, x_l, x_u, + "sparse_by_rows", ne, Cint[], H_col, H_ptr) + + terminated = false + while !terminated # reverse-communication loop + dgo_solve_reverse_with_mat(data, status, eval_status, + n, x, f, g, ne, H_val, u, v) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate f + eval_status = fun(n, x, f, userdata) + elseif status[] == 3 # evaluate g + eval_status = grad(n, x, g, userdata) + elseif status[] == 4 # evaluate H + eval_status = hess(n, ne, x, H_val, userdata) + elseif status[] == 5 # evaluate Hv product + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 6 # evaluate the product with P + eval_status = prec(n, x, u, v, userdata) + elseif status[] == 23 # evaluate f and g + eval_status = fun(n, x, f, userdata) + eval_status = grad(n, x, g, userdata) + elseif status[] == 25 # evaluate f and Hv product + eval_status = fun(n, x, f, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 35 # evaluate g and Hv product + eval_status = grad(n, x, g, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 235 # evaluate f, g and Hv product + eval_status = fun(n, x, f, userdata) + eval_status = grad(n, x, g, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # dense + if d == 3 + st = 'D' + dgo_import(control, data, status, n, x_l, x_u, + "dense", ne, Cint[], Cint[], Cint[]) + + terminated = false + while !terminated # reverse-communication loop + dgo_solve_reverse_with_mat(data, status, eval_status, + n, x, f, g, n * (n + 1) / 2, + H_dense, u, v) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate f + eval_status = fun(n, x, f, userdata) + elseif status[] == 3 # evaluate g + eval_status = grad(n, x, g, userdata) + elseif status[] == 4 # evaluate H + eval_status = hess_dense(n, n * (n + 1) / 2, x, H_dense, + userdata) + elseif status[] == 5 # evaluate Hv product + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 6 # evaluate the product with P + eval_status = prec(n, x, u, v, userdata) + elseif status[] == 23 # evaluate f and g + eval_status = fun(n, x, f, userdata) + eval_status = grad(n, x, g, userdata) + elseif status[] == 25 # evaluate f and Hv product + eval_status = fun(n, x, f, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 35 # evaluate g and Hv product + eval_status = grad(n, x, g, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 235 # evaluate f, g and Hv product + eval_status = fun(n, x, f, userdata) + eval_status = grad(n, x, g, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # diagonal + if d == 4 + st = 'I' + dgo_import(control, data, status, n, x_l, x_u, + "diagonal", ne, Cint[], Cint[], Cint[]) + + terminated = false + while !terminated # reverse-communication loop + dgo_solve_reverse_with_mat(data, status, eval_status, + n, x, f, g, n, H_diag, u, v) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate f + eval_status = fun_diag(n, x, f, userdata) + elseif status[] == 3 # evaluate g + eval_status = grad_diag(n, x, g, userdata) + elseif status[] == 4 # evaluate H + eval_status = hess_diag(n, n, x, H_diag, userdata) + elseif status[] == 5 # evaluate Hv product + eval_status = hessprod_diag(n, x, u, v, false, + userdata) + elseif status[] == 6 # evaluate the product with P + eval_status = prec(n, x, u, v, userdata) + elseif status[] == 23 # evaluate f and g + eval_status = fun_diag(n, x, f, userdata) + eval_status = grad_diag(n, x, g, userdata) + elseif status[] == 25 # evaluate f and Hv product + eval_status = fun_diag(n, x, f, userdata) + eval_status = hessprod_diag(n, x, u, v, false, + userdata) + elseif status[] == 35 # evaluate g and Hv product + eval_status = grad_diag(n, x, g, userdata) + eval_status = hessprod_diag(n, x, u, v, false, + userdata) + elseif status[] == 235 # evaluate f, g and Hv product + eval_status = fun_diag(n, x, f, userdata) + eval_status = grad_diag(n, x, g, userdata) + eval_status = hessprod_diag(n, x, u, v, false, + userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # access by products + if d == 5 + st = 'P' + dgo_import(control, data, status, n, x_l, x_u, + "absent", ne, Cint[], Cint[], Cint[]) + + nnz_u = 0 + terminated = false + while !terminated # reverse-communication loop + dgo_solve_reverse_without_mat(data, status, eval_status, + n, x, f, g, u, v, index_nz_v, + nnz_v, index_nz_u, nnz_u) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate f + eval_status = fun(n, x, f, userdata) + elseif status[] == 3 # evaluate g + eval_status = grad(n, x, g, userdata) + elseif status[] == 5 # evaluate Hv product + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 6 # evaluate the product with P + eval_status = prec(n, x, u, v, userdata) + elseif status[] == 7 # evaluate sparse Hess-vect product + eval_status = shessprod(n, x, nnz_v, index_nz_v, v, + nnz_u, index_nz_u, u, + false, userdata) + elseif status[] == 23 # evaluate f and g + eval_status = fun(n, x, f, userdata) + eval_status = grad(n, x, g, userdata) + elseif status[] == 25 # evaluate f and Hv product + eval_status = fun(n, x, f, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 35 # evaluate g and Hv product + eval_status = grad(n, x, g, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + elseif status[] == 235 # evaluate f, g and Hv product + eval_status = fun(n, x, f, userdata) + eval_status = grad(n, x, g, userdata) + eval_status = hessprod(n, x, u, v, false, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # Record solution information + dgo_information(data, inform, status) + + if inform[].status[] == 0 + @printf("%c:%6i evaluations. Optimal objective value = %5.2f status = %1i\n", st, + inform[].f_eval, inform[].obj, inform[].status) + elseif inform[].status[] == -18 + @printf("%c:%6i evaluations. Best objective value = %5.2f status = %1i\n", st, + inform[].f_eval, inform[].obj, inform[].status) + else + @printf("%c: DGO_solve exit status = %1i\n", st, inform[].status) + end + + # @printf("x: ") + # for i in 1:n + # @printf("%f ", x[i]) + # end + # @printf("\n") + # @printf("gradient: ") + # for i in 1:n + # @printf("%f ", g[i]) + # end + # @printf("\n") + + # Delete internal workspace + dgo_terminate(data, control, inform) + end +end + +@testset "DGO" begin + @test test_dgo() == 0 +end diff --git a/GALAHAD.jl/test/test_dps.jl b/GALAHAD.jl/test/test_dps.jl index 1b0119d443..f4cd8b6925 100644 --- a/GALAHAD.jl/test/test_dps.jl +++ b/GALAHAD.jl/test/test_dps.jl @@ -39,14 +39,8 @@ function test_dps() dps_initialize(data, control, status) # Set user-defined control options - @reset control[].f_indexing = true # fortran sparse matrix indexing - @reset control[].symmetric_linear_solver = convert(NTuple{31,Int8}, - (115, 121, 116, 114, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, - 0)) + @reset control[].f_indexing = true # fortran sparse matrix indexing + @reset control[].symmetric_linear_solver = galahad_linear_solver("sytr") # sparse co-ordinate storage if storage_type == 1 diff --git a/GALAHAD.jl/test/test_dqp.jl b/GALAHAD.jl/test/test_dqp.jl index 711d39e4ad..978239df7c 100644 --- a/GALAHAD.jl/test/test_dqp.jl +++ b/GALAHAD.jl/test/test_dqp.jl @@ -2,209 +2,217 @@ # Simple code to test the Julia interface to DQP using GALAHAD +using Test using Printf - -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = dqp_control_type{Float64}() -inform = dqp_inform_type{Float64}() - -# Set problem data -n = 3 # dimension -m = 2 # number of general constraints -H_ne = 3 # Hesssian elements -H_row = Cint[1, 2, 3] # row indices, NB lower triangle -H_col = Cint[1, 2, 3] # column indices, NB lower triangle -H_ptr = Cint[1, 2, 3, 4] # row pointers -H_val = Float64[1.0, 1.0, 1.0] # values -g = Float64[0.0, 2.0, 0.0] # linear term in the objective -f = 1.0 # constant term in the objective -A_ne = 4 # Jacobian elements -A_row = Cint[1, 1, 2, 2] # row indices -A_col = Cint[1, 2, 2, 3] # column indices -A_ptr = Cint[1, 3, 5] # row pointers -A_val = Float64[2.0, 1.0, 1.0, 1.0] # values -c_l = Float64[1.0, 2.0] # constraint lower bound -c_u = Float64[2.0, 2.0] # constraint upper bound -x_l = Float64[-1.0, -Inf, -Inf] # variable lower bound -x_u = Float64[1.0, Inf, 2.0] # variable upper bound - -# Set output storage -c = zeros(Float64, m) # constraint values -x_stat = zeros(Cint, n) # variable status -c_stat = zeros(Cint, m) # constraint status -st = ' ' -status = Ref{Cint}() - -@printf(" Fortran sparse matrix indexing\n\n") -@printf(" basic tests of qp storage formats\n\n") - -for d = 1:6 - # Initialize DQP - dqp_initialize( data, control, status ) - - # Set user-defined control options - control.f_indexing = true # Fortran sparse matrix indexing - - # Start from 0 - x = Float64[0.0,0.0,0.0] - y = Float64[0.0,0.0] - z = Float64[0.0,0.0,0.0] - - # sparse co-ordinate storage - if d == 1 - global st = 'C' - - dqp_import( control, data, status, n, m, - "coordinate", H_ne, H_row, H_col, Cint[], - "coordinate", A_ne, A_row, A_col, Cint[] ) - - dqp_solve_qp( data, status, n, m, H_ne, H_val, g, f, - A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) - end - - # sparse by rows - if d == 2 - global st = 'R' - - dqp_import( control, data, status, n, m, - "sparse_by_rows", H_ne, Cint[], H_col, H_ptr, - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - dqp_solve_qp( data, status, n, m, H_ne, H_val, g, f, - A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) - end - - # dense - if d == 3 - global st = 'D' - H_dense_ne = 6 # number of elements of H - A_dense_ne = 6 # number of elements of A - H_dense = Float64[1.0, 0.0, 1.0, 0.0, 0.0, 1.0] - A_dense = Float64[2.0, 1.0, 0.0, 0.0, 1.0, 1.0] - - dqp_import( control, data, status, n, m, - "dense", H_ne, Cint[], Cint[], Cint[], - "dense", A_ne, Cint[], Cint[], Cint[] ) - - dqp_solve_qp( data, status, n, m, H_dense_ne, H_dense, g, f, - A_dense_ne, A_dense, c_l, c_u, x_l, x_u, - x, c, y, z, x_stat, c_stat ) - end - - # diagonal - if d == 4 - global st = 'L' - - dqp_import( control, data, status, n, m, - "diagonal", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - dqp_solve_qp( data, status, n, m, H_ne, H_val, g, f, - A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) - end - - # scaled identity - if d == 5 - global st = 'S' - - dqp_import( control, data, status, n, m, - "scaled_identity", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - dqp_solve_qp( data, status, n, m, H_ne, H_val, g, f, - A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) - end - - # identity - if d == 6 - global st = 'I' - - dqp_import( control, data, status, n, m, - "identity", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - dqp_solve_qp( data, status, n, m, H_ne, H_val, g, f, - A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) +using Accessors + +function test_dqp() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{dqp_control_type{Float64}}() + inform = Ref{dqp_inform_type{Float64}}() + + # Set problem data + n = 3 # dimension + m = 2 # number of general constraints + H_ne = 3 # Hesssian elements + H_row = Cint[1, 2, 3] # row indices, NB lower triangle + H_col = Cint[1, 2, 3] # column indices, NB lower triangle + H_ptr = Cint[1, 2, 3, 4] # row pointers + H_val = Float64[1.0, 1.0, 1.0] # values + g = Float64[0.0, 2.0, 0.0] # linear term in the objective + f = 1.0 # constant term in the objective + A_ne = 4 # Jacobian elements + A_row = Cint[1, 1, 2, 2] # row indices + A_col = Cint[1, 2, 2, 3] # column indices + A_ptr = Cint[1, 3, 5] # row pointers + A_val = Float64[2.0, 1.0, 1.0, 1.0] # values + c_l = Float64[1.0, 2.0] # constraint lower bound + c_u = Float64[2.0, 2.0] # constraint upper bound + x_l = Float64[-1.0, -Inf, -Inf] # variable lower bound + x_u = Float64[1.0, Inf, 2.0] # variable upper bound + + # Set output storage + c = zeros(Float64, m) # constraint values + x_stat = zeros(Cint, n) # variable status + c_stat = zeros(Cint, m) # constraint status + st = ' ' + status = Ref{Cint}() + + @printf(" Fortran sparse matrix indexing\n\n") + @printf(" basic tests of qp storage formats\n\n") + + for d in 1:6 + + # Initialize DQP + dqp_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + + # Start from 0 + x = Float64[0.0, 0.0, 0.0] + y = Float64[0.0, 0.0] + z = Float64[0.0, 0.0, 0.0] + + # sparse co-ordinate storage + if d == 1 + st = 'C' + dqp_import(control, data, status, n, m, + "coordinate", H_ne, H_row, H_col, Cint[], + "coordinate", A_ne, A_row, A_col, Cint[]) + + dqp_solve_qp(data, status, n, m, H_ne, H_val, g, f, + A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) + end + + # sparse by rows + if d == 2 + st = 'R' + dqp_import(control, data, status, n, m, + "sparse_by_rows", H_ne, Cint[], H_col, H_ptr, + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + dqp_solve_qp(data, status, n, m, H_ne, H_val, g, f, + A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) + end + + # dense + if d == 3 + st = 'D' + H_dense_ne = 6 # number of elements of H + A_dense_ne = 6 # number of elements of A + H_dense = Float64[1.0, 0.0, 1.0, 0.0, 0.0, 1.0] + A_dense = Float64[2.0, 1.0, 0.0, 0.0, 1.0, 1.0] + + dqp_import(control, data, status, n, m, + "dense", H_ne, Cint[], Cint[], Cint[], + "dense", A_ne, Cint[], Cint[], Cint[]) + + dqp_solve_qp(data, status, n, m, H_dense_ne, H_dense, g, f, + A_dense_ne, A_dense, c_l, c_u, x_l, x_u, + x, c, y, z, x_stat, c_stat) + end + + # diagonal + if d == 4 + st = 'L' + dqp_import(control, data, status, n, m, + "diagonal", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + dqp_solve_qp(data, status, n, m, H_ne, H_val, g, f, + A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) + end + + # scaled identity + if d == 5 + st = 'S' + dqp_import(control, data, status, n, m, + "scaled_identity", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + dqp_solve_qp(data, status, n, m, H_ne, H_val, g, f, + A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) + end + + # identity + if d == 6 + st = 'I' + dqp_import(control, data, status, n, m, + "identity", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + dqp_solve_qp(data, status, n, m, H_ne, H_val, g, f, + A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) + end + + dqp_information(data, inform, status) + + if inform[].status == 0 + @printf("%c:%6i iterations. Optimal objective value = %5.2f status = %1i\n", st, + inform[].iter, inform[].obj, inform[].status) + else + @printf("%c: DQP_solve exit status = %1i\n", st, inform[].status) + end + + # @printf("x: ") + # for i = 1:n + # @printf("%f ", x[i]) + # end + # @printf("\n") + # @printf("gradient: ") + # for i = 1:n + # @printf("%f ", g[i]) + # end + # @printf("\n") + + # Delete internal workspace + dqp_terminate(data, control, inform) end - dqp_information( data, inform, status ) - - if inform.status == 0 - @printf("%c:%6i iterations. Optimal objective value = %5.2f status = %1i\n", st, inform.iter, inform.obj, inform.status) - else - @printf("%c: DQP_solve exit status = %1i\n", st, inform.status) + # test shifted least-distance interface + for d in 1:1 + + # Initialize DQP + dqp_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + + # Start from 0 + x = Float64[0.0, 0.0, 0.0] + y = Float64[0.0, 0.0] + z = Float64[0.0, 0.0, 0.0] + + # Set shifted least-distance data + + w = Float64[1.0, 1.0, 1.0] + x_0 = Float64[0.0, 0.0, 0.0] + + # sparse co-ordinate storage + if d == 1 + st = 'W' + dqp_import(control, data, status, n, m, + "shifted_least_distance", H_ne, Cint[], Cint[], Cint[], + "coordinate", A_ne, A_row, A_col, Cint[]) + + dqp_solve_sldqp(data, status, n, m, w, x_0, g, f, + A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) + end + + dqp_information(data, inform, status) + + if inform[].status == 0 + @printf("%c:%6i iterations. Optimal objective value = %5.2f status = %1i\n", st, + inform[].iter, inform[].obj, inform[].status) + else + @printf("%c: DQP_solve exit status = %1i\n", st, inform[].status) + end + + # @printf("x: ") + # for i = 1:n + # @printf("%f ", x[i]) + # end + # @printf("\n") + # @printf("gradient: ") + # for i = 1:n + # @printf("%f ", g[i]) + # end + # @printf("\n") + + # Delete internal workspace + dqp_terminate(data, control, inform) end - - # @printf("x: ") - # for i = 1:n - # @printf("%f ", x[i]) - # end - # @printf("\n") - # @printf("gradient: ") - # for i = 1:n - # @printf("%f ", g[i]) - # end - # @printf("\n") - - # Delete internal workspace - dqp_terminate( data, control, inform ) + return 0 end -# test shifted least-distance interface -for d = 1:1 - # Initialize DQP - dqp_initialize( data, control, status ) - - # Set user-defined control options - control.f_indexing = true # Fortran sparse matrix indexing - - # Start from 0 - x = Float64[0.0,0.0,0.0] - y = Float64[0.0,0.0] - z = Float64[0.0,0.0,0.0] - - # Set shifted least-distance data - w = Float64[1.0,1.0,1.0] - x_0 = Float64[0.0,0.0,0.0] - - # sparse co-ordinate storage - if d == 1 - global st = 'W' - - dqp_import( control, data, status, n, m, - "shifted_least_distance", H_ne, Cint[], Cint[], Cint[], - "coordinate", A_ne, A_row, A_col, Cint[] ) - - dqp_solve_sldqp( data, status, n, m, w, x_0, g, f, - A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) - end - - dqp_information( data, inform, status ) - - if inform.status == 0 - @printf("%c:%6i iterations. Optimal objective value = %5.2f status = %1i\n", st, inform.iter, inform.obj, inform.status) - else - @printf("%c: DQP_solve exit status = %1i\n", st, inform.status) - end - - # @printf("x: ") - # for i = 1:n - # @printf("%f ", x[i]) - # end - # @printf("\n") - # @printf("gradient: ") - # for i = 1:n - # @printf("%f ", g[i]) - # end - # @printf("\n") - - # Delete internal workspace - dqp_terminate( data, control, inform ) +@testset "DQP" begin + @test test_dqp() == 0 end diff --git a/GALAHAD.jl/test/test_eqp.jl b/GALAHAD.jl/test/test_eqp.jl index 70e54818f3..3c2c79fe21 100644 --- a/GALAHAD.jl/test/test_eqp.jl +++ b/GALAHAD.jl/test/test_eqp.jl @@ -45,34 +45,9 @@ function test_eqp() # Set user-defined control options @reset control[].f_indexing = true # Fortran sparse matrix indexing @reset control[].fdc_control.use_sls = true - solver = "sytr" - @reset control[].fdc_control.symmetric_linear_solver = convert(NTuple{31,Int8}, - (115, 121, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) - @reset control[].sbls_control.symmetric_linear_solver = convert(NTuple{31,Int8}, - (115, 121, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) - @reset control[].sbls_control.definite_linear_solver = convert(NTuple{31,Int8}, - (115, 121, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) + @reset control[].fdc_control.symmetric_linear_solver = galahad_linear_solver("sytr") + @reset control[].sbls_control.symmetric_linear_solver = galahad_linear_solver("sytr") + @reset control[].sbls_control.definite_linear_solver = galahad_linear_solver("sytr") # Start from 0 x = Float64[0.0, 0.0, 0.0] @@ -191,34 +166,9 @@ function test_eqp() # Initialize EQP eqp_initialize(data, control, status) @reset control[].fdc_control.use_sls = true - solver = "sytr" - @reset control[].fdc_control.symmetric_linear_solver = convert(NTuple{31,Int8}, - (115, 121, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) - @reset control[].sbls_control.symmetric_linear_solver = convert(NTuple{31,Int8}, - (115, 121, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) - @reset control[].sbls_control.definite_linear_solver = convert(NTuple{31,Int8}, - (115, 121, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) + @reset control[].fdc_control.symmetric_linear_solver = galahad_linear_solver("sytr") + @reset control[].sbls_control.symmetric_linear_solver = galahad_linear_solver("sytr") + @reset control[].sbls_control.definite_linear_solver = galahad_linear_solver("sytr") # Set user-defined control options @reset control[].f_indexing = true # Fortran sparse matrix indexing diff --git a/GALAHAD.jl/test/test_fdc.jl b/GALAHAD.jl/test/test_fdc.jl index ade26ca225..91570e6c57 100644 --- a/GALAHAD.jl/test/test_fdc.jl +++ b/GALAHAD.jl/test/test_fdc.jl @@ -2,53 +2,61 @@ # Simple code to test the Julia interface to FDC using GALAHAD +using Test using Printf - -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = fdc_control_type{Float64}() -inform = fdc_inform_type{Float64}() - -# Set problem data -m = 3 # number of rows -n = 4 # number of columns -A_ne = 10 # number of nonzeros -A_col = Cint[1, 2, 3, 4, 1, 2, 3, 4, 2, 4] # column indices -A_ptr = Cint[1, 5, 9, 11] # row pointers -A_val = Float64[1.0, 2.0, 3.0, 4.0, 2.0, -4.0, 6.0, -8.0, 5.0, 10.0] -b = Float64[5.0, 10.0, 0.0] - -# Set output storage -depen = zeros(Cint, m) # dependencies, if any -n_depen = Ref{Cint}() -status = Ref{Cint}() - -@printf(" Fortran sparse matrix indexing\n") - -# Initialize FDC -fdc_initialize( data, control, status ) - -# Set user-defined control options -control.f_indexing = true # Fortran sparse matrix indexing - -# Start from 0 -fdc_find_dependent_rows( control, data, inform, status, m, n, A_ne, - A_col, A_ptr, A_val, b, n_depen, depen ) - -if status == 0 - if n_depen == 0 - @printf("FDC_find_dependent - no dependent rows, status = %i\n", status) +using Accessors + +function test_fdc() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{fdc_control_type{Float64}}() + inform = Ref{fdc_inform_type{Float64}}() + + # Set problem data + m = 3 # number of rows + n = 4 # number of columns + A_ne = 10 # number of nonzeros + A_col = Cint[1, 2, 3, 4, 1, 2, 3, 4, 2, 4] # column indices + A_ptr = Cint[1, 5, 9, 11] # row pointers + A_val = Float64[1.0, 2.0, 3.0, 4.0, 2.0, -4.0, 6.0, -8.0, 5.0, 10.0] + b = Float64[5.0, 10.0, 0.0] + + # Set output storage + depen = zeros(Cint, m) # dependencies, if any + n_depen = Ref{Cint}() + status = Ref{Cint}() + + @printf(" Fortran sparse matrix indexing\n") + + # Initialize FDC + fdc_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + + # Start from 0 + fdc_find_dependent_rows(control, data, inform, status, m, n, A_ne, A_col, A_ptr, A_val, b, + n_depen, depen) + + if status[] == 0 + if n_depen == 0 + @printf("FDC_find_dependent - no dependent rows, status = %i\n", status[]) + else + @printf("FDC_find_dependent - dependent rows(s):") + for i in 1:n_depen + @printf(" %i", depen[i]) + end + @printf(", status = %i\n", status[]) + end else - @printf("FDC_find_dependent - dependent rows(s):" ) + @printf("FDC_find_dependent - exit status = %1i\n", status[]) end - for i = 1:n_depen - @printf(" %i", depen[i]) - end - @printf(", status = %i\n", status) -else - @printf("FDC_find_dependent - exit status = %1i\n", status) + # Delete internal workspace + fdc_terminate(data, control, inform) + return 0 end -# Delete internal workspace -fdc_terminate( data, control, inform ) +@testset "FDC" begin + @test test_fdc() == 0 +end diff --git a/GALAHAD.jl/test/test_llsr.jl b/GALAHAD.jl/test/test_llsr.jl index e69de29bb2..09fdc0f450 100644 --- a/GALAHAD.jl/test/test_llsr.jl +++ b/GALAHAD.jl/test/test_llsr.jl @@ -0,0 +1,219 @@ +# test_llsr.jl +# Simple code to test the Julia interface to LLSR + +using GALAHAD +using Test +using Printf +using Accessors + +function test_llsr() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{llsr_control_type{Float64}}() + inform = Ref{llsr_inform_type{Float64}}() + + # Set problem data + # set dimensions + m = 100 + n = 2 * m + 1 + + # # A = (I : Diag(1:n) : e) + A_ne = 3 * m + A_row = zeros(Cint, A_ne) + A_col = zeros(Cint, A_ne) + A_ptr = zeros(Cint, m + 1) + A_val = zeros(Float64, A_ne) + + # store A in sparse formats + l = 1 + for i in 1:m + A_ptr[i] = l + 1 + A_row[l] = i + A_col[l] = i + A_val[l] = 1.0 + l = l + 1 + A_row[l] = i + A_col[l] = m + i + A_val[l] = i + l = l + 1 + A_row[l] = i + A_col[l] = n + A_val[l] = 1.0 + l = l + 1 + end + A_ptr[m + 1] = l + 1 + + # store A in dense format + A_dense_ne = m * n + A_dense_val = zeros(Float64, A_dense_ne) + for i in 1:A_dense_ne + A_dense_val[i] = 0.0 + end + l = 0 + for i in 1:m + A_dense_val[l + i] = 1.0 + A_dense_val[l + m + i] = i + A_dense_val[l + n] = 1.0 + l = l + n + end + + # S = diag(1:n)**2 + S_ne = n + S_row = zeros(Cint, S_ne) + S_col = zeros(Cint, S_ne) + S_ptr = zeros(Cint, n + 1) + S_val = zeros(Float64, S_ne) + + # store S in sparse formats + for i in 1:n + S_row[i] = i + S_col[i] = i + S_ptr[i] = i + S_val[i] = i * i + end + S_ptr[n + 1] = n + 1 + + # store S in dense format + S_dense_ne = div(n * (n + 1), 2) + S_dense_val = zeros(Float64, S_dense_ne) + for i in 1:S_dense_ne + S_dense_val[i] = 0.0 + end + l = 0 + for i in 1:n + S_dense_val[l + i] = i * i + l = l + i + end + + # b is a vector of ones + b = ones(Float64, m) # observations + + # cubic regularization, weight is one + power = 3.0 + weight = 1.0 + + # Set output storage + x = zeros(Float64, n) # solution + st = ' ' + status = Ref{Cint}() + + @printf(" Fortran sparse matrix indexing\n\n") + @printf(" basic tests of problem storage formats\n\n") + + # loop over storage formats + for d in 1:4 + + # Initialize LLSR + llsr_initialize(data, control, status) + @reset control[].definite_linear_solver = galahad_linear_solver("potr") + @reset control[].sbls_control.symmetric_linear_solver = galahad_linear_solver("sytr") + @reset control[].sbls_control.definite_linear_solver = galahad_linear_solver("potr") + # @reset control[].print_level = 1 + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + + # use s or not (1 or 0) + for use_s in 0:1 + + # sparse co-ordinate storage + if d == 1 + st = 'C' + llsr_import(control, data, status, m, n, + "coordinate", A_ne, A_row, A_col, Cint[]) + + if use_s == 0 + llsr_solve_problem(data, status, m, n, power, weight, + A_ne, A_val, b, x, 0, Cint[]) + else + llsr_import_scaling(control, data, status, n, + "coordinate", S_ne, S_row, + S_col, Cint[]) + + llsr_solve_problem(data, status, m, n, power, weight, + A_ne, A_val, b, x, S_ne, S_val) + end + end + + # sparse by rows + if d == 2 + st = 'R' + llsr_import(control, data, status, m, n, + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + if use_s == 0 + llsr_solve_problem(data, status, m, n, power, weight, + A_ne, A_val, b, x, 0, Cint[]) + else + llsr_import_scaling(control, data, status, n, + "sparse_by_rows", S_ne, Cint[], + S_col, S_ptr) + + llsr_solve_problem(data, status, m, n, power, weight, + A_ne, A_val, b, x, S_ne, S_val) + end + end + + # dense + if d == 3 + st = 'D' + llsr_import(control, data, status, m, n, + "dense", A_dense_ne, Cint[], Cint[], Cint[]) + if use_s == 0 + llsr_solve_problem(data, status, m, n, power, weight, + A_dense_ne, A_dense_val, b, x, + 0, Cint[]) + else + llsr_import_scaling(control, data, status, n, + "dense", S_dense_ne, + Cint[], Cint[], Cint[]) + + llsr_solve_problem(data, status, m, n, power, weight, + A_dense_ne, A_dense_val, b, x, + S_dense_ne, S_dense_val) + end + end + + # diagonal + if d == 4 + st = 'I' + llsr_import(control, data, status, m, n, + "coordinate", A_ne, A_row, A_col, Cint[]) + if use_s == 0 + llsr_solve_problem(data, status, m, n, power, weight, + A_ne, A_val, b, x, 0, Cint[]) + else + llsr_import_scaling(control, data, status, n, + "diagonal", S_ne, Cint[], Cint[], Cint[]) + + llsr_solve_problem(data, status, m, n, power, weight, + A_ne, A_val, b, x, S_ne, S_val) + end + end + + llsr_information(data, inform, status) + + if inform[].status == 0 + @printf("storage type %c%1i: status = %1i, ||r|| = %5.2f\n", st, use_s, + inform[].status, inform[].r_norm) + else + @printf("storage type %c%1i: LLSR_solve exit status = %1i\n", st, use_s, + inform[].status) + end + end + + # @printf("x: ") + # for i = 1:n + # @printf("%f ", x[i]) + # end + # @printf("\n") + + # Delete internal workspace + llsr_terminate(data, control, inform) + end + return 0 +end + +@testset "LLSR" begin + @test test_llsr() == 0 +end diff --git a/GALAHAD.jl/test/test_llst.jl b/GALAHAD.jl/test/test_llst.jl index 4e34d13ebe..1ecc37c8ca 100644 --- a/GALAHAD.jl/test/test_llst.jl +++ b/GALAHAD.jl/test/test_llst.jl @@ -107,33 +107,9 @@ function test_llst() # Initialize LLST llst_initialize(data, control, status) - @reset control[].definite_linear_solver = convert(NTuple{31,Int8}, - (112, 111, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) - @reset control[].sbls_control.symmetric_linear_solver = convert(NTuple{31,Int8}, - (115, 121, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) - @reset control[].sbls_control.definite_linear_solver = convert(NTuple{31,Int8}, - (112, 111, 116, 114, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, - 32, 0)) + @reset control[].definite_linear_solver = galahad_linear_solver("potr") + @reset control[].sbls_control.symmetric_linear_solver = galahad_linear_solver("potr") + @reset control[].sbls_control.definite_linear_solver = galahad_linear_solver("potr") # @reset control[].print_level = Cint(1) # Set user-defined control options diff --git a/GALAHAD.jl/test/test_nls.jl b/GALAHAD.jl/test/test_nls.jl index 54cd373742..2e6e7e2796 100644 --- a/GALAHAD.jl/test/test_nls.jl +++ b/GALAHAD.jl/test/test_nls.jl @@ -8,7 +8,7 @@ using Accessors # Custom userdata struct struct userdata_type -p::Float64 + p::Float64 end function test_nls() diff --git a/GALAHAD.jl/test/test_psls.jl b/GALAHAD.jl/test/test_psls.jl index 1a807a5fc4..0324e0daa2 100644 --- a/GALAHAD.jl/test/test_psls.jl +++ b/GALAHAD.jl/test/test_psls.jl @@ -35,13 +35,7 @@ function test_psls() psls_initialize(data, control, status) @reset control[].preconditioner = Cint(2) # band preconditioner @reset control[].semi_bandwidth = Cint(1) # semibandwidth - @reset control[].definite_linear_solver = convert(NTuple{31,Int8}, - (115, 105, 108, 115, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, - 0)) + @reset control[].definite_linear_solver = galahad_linear_solver("sils") # Set user-defined control options @reset control[].f_indexing = true # fortran sparse matrix indexing diff --git a/GALAHAD.jl/test/test_rqs.jl b/GALAHAD.jl/test/test_rqs.jl index bfdce1875e..10a02e9b94 100644 --- a/GALAHAD.jl/test/test_rqs.jl +++ b/GALAHAD.jl/test/test_rqs.jl @@ -1,13 +1,3 @@ -/* rqstf.c */ -/* Full test for the RQS C interface using Fortran sparse matrix indexing */ - -#include -#include -#include -#include "galahad_precision.h" -#include "galahad_cfunctions.h" -#include "galahad_rqs.h" - # test_rqs.jl # Simple code to test the Julia interface to RQS @@ -17,234 +7,225 @@ using Printf using Accessors function test_rqs() -# Derived types -data = Ref{Ptr{Cvoid}}() -control = Ref{rqs_control_type{Float64}}() -inform = Ref{rqs_inform_type{Float64}}() - -# Set problem data -n = 3 # dimension of H -m = 1 # dimension of A -H_ne = 4 # number of elements of H -M_ne = 3 # number of elements of M -A_ne = 3 # number of elements of A -H_dense_ne = 6 # number of elements of H -M_dense_ne = 6 # number of elements of M -H_row = Cint[1, 2, 3, 3] # row indices, NB lower triangle -H_col = Cint[1, 2, 3, 1] -H_ptr = Cint[1, 2, 3, 5] -M_row = Cint[1, 2, 3] # row indices, NB lower triangle -M_col = Cint[1, 2, 3] -M_ptr = Cint[1, 2, 3, 4] -A_row = Cint[1, 1, 1} -A_col = Cint[1, 2, 3] -A_ptr = Cint[1, 4] -H_val = Float64[1.0, 2.0, 3.0, 4.0] -M_val = Float64[1.0, 2.0, 1.0] -A_val = Float64[1.0, 1.0, 1.0] -H_dense = Float64[1.0, 0.0, 2.0, 4.0, 0.0, 3.0] -M_dense = Float64[1.0, 0.0, 2.0, 0.0, 0.0, 1.0] -H_diag = Float64[1.0, 0.0, 2.0] -M_diag = Float64[1.0, 2.0, 1.0] -f = 0.96 -power = 3.0 -weight = 1.0 -c = Float64[0.0, 2.0, 0.0] - -st = ' ' -status = Ref{Cint}() -x = zeros(Float64, n) -char ma[3] - -@printf(" Fortran sparse matrix indexing\n\n") - -@printf(" basic tests of storage formats\n\n") - -for a_is = 0:1 # add a linear constraint? - for m_is = 0:1 # include a scaling matrix? - -if (a_is == 1 m_is == 1) { - strcpy(ma, "MA") - -elseif (a_is == 1) { - strcpy(ma, "A ") - -elseif (m_is == 1) { - strcpy(ma, "M ") - -else { - strcpy(ma, " ") -for(int storage_type=1 storage_type <= 4 storage_type++) - - # Initialize RQS - rqs_initialize(data, control, status) - - # Set user-defined control options - control[].f_indexing = true # fortran sparse matrix indexing - - switch(storage_type) - # sparse co-ordinate storage -if d == 1 - st = 'C' - # import the control parameters and structural data - rqs_import(control, data, status, n, - "coordinate", H_ne, H_row, H_col, Cint[]) - if (m_is == 1) { -rqs_import_m(data, status, n, - "coordinate", M_ne, M_row, M_col, Cint[]) - ] - if (a_is == 1) { -rqs_import_a(data, status, m, - "coordinate", A_ne, A_row, A_col, Cint[]) - ] - # solve the problem - if (a_is == 1 m_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, H_ne, H_val, x, - M_ne, M_val, m, A_ne, A_val, Cint[]) - ] - elseif (a_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, H_ne, H_val, x, - 0, Cint[], m, A_ne, A_val, Cint[]) - ] - elseif (m_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, H_ne, H_val, x, - M_ne, M_val, 0, 0, Cint[], Cint[]) - ] - else { -rqs_solve_problem(data, status, n, - power, weight, f, c, H_ne, H_val, x, - 0, Cint[], 0, 0, Cint[], Cint[]) - ] - end - @printf(" case %1i break\n", storage_type) - # sparse by rows -if d == 2 - st = 'R' - # import the control parameters and structural data - rqs_import(control, data, status, n, - "sparse_by_rows", H_ne, Cint[], H_col, H_ptr) - if (m_is == 1) { -rqs_import_m(data, status, n, - "sparse_by_rows", M_ne, Cint[], M_col, M_ptr) - ] - if (a_is == 1) { -rqs_import_a(data, status, m, - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) - ] - # solve the problem - if (a_is == 1 m_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, H_ne, H_val, x, - M_ne, M_val, m, A_ne, A_val, Cint[]) - ] - elseif (a_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, H_ne, H_val, x, - 0, Cint[], m, A_ne, A_val, Cint[]) - ] - elseif (m_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, H_ne, H_val, x, - M_ne, M_val, 0, 0, Cint[], Cint[]) - ] - else { -rqs_solve_problem(data, status, n, - power, weight, f, c, H_ne, H_val, x, - 0, Cint[], 0, 0, Cint[], Cint[]) - ] - end - # dense -if d == 3 - st = 'D' - # import the control parameters and structural data - rqs_import(control, data, status, n, - "dense", H_ne, Cint[], Cint[], Cint[]) - if (m_is == 1) { -rqs_import_m(data, status, n, - "dense", M_ne, Cint[], Cint[], Cint[]) - ] - if (a_is == 1) { -rqs_import_a(data, status, m, - "dense", A_ne, Cint[], Cint[], Cint[]) - ] - # solve the problem - if (a_is == 1 m_is == 1) { -rqs_solve_problem(data, status, n, power, weight, - f, c, H_dense_ne, H_dense, x, - M_dense_ne, M_dense, m, A_ne, A_val, - Cint[]) - ] - elseif (a_is == 1) { -rqs_solve_problem(data, status, n, power, weight, - f, c, H_dense_ne, H_dense, x, - 0, Cint[], m, A_ne, A_val, Cint[]) - ] - elseif (m_is == 1) { -rqs_solve_problem(data, status, n, power, weight, - f, c, H_dense_ne, H_dense, x, - M_dense_ne, M_dense, 0, 0, Cint[], Cint[]) - ] - else { -rqs_solve_problem(data, status, n, power, weight, - f, c, H_dense_ne, H_dense, x, - 0, Cint[], 0, 0, Cint[], Cint[]) - ] - end - # diagonal -if d == 4 - st = 'L' - # import the control parameters and structural data - rqs_import(control, data, status, n, - "diagonal", H_ne, Cint[], Cint[], Cint[]) - if (m_is == 1) { -rqs_import_m(data, status, n, - "diagonal", M_ne, Cint[], Cint[], Cint[]) - ] - if (a_is == 1) { -rqs_import_a(data, status, m, - "dense", A_ne, Cint[], Cint[], Cint[]) - ] - # solve the problem - if (a_is == 1 m_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, n, H_diag, x, - n, M_diag, m, A_ne, A_val, Cint[]) - ] - elseif (a_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, n, H_diag, x, - 0, Cint[], m, A_ne, A_val, Cint[]) - ] - elseif (m_is == 1) { -rqs_solve_problem(data, status, n, - power, weight, f, c, n, H_diag, x, - n, M_diag, 0, 0, Cint[], Cint[]) - ] - else { -rqs_solve_problem(data, status, n, - power, weight, f, c, n, H_diag, x, - 0, Cint[], 0, 0, Cint[], Cint[]) - ] + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{rqs_control_type{Float64}}() + inform = Ref{rqs_inform_type{Float64}}() + + # Set problem data + n = 3 # dimension of H + m = 1 # dimension of A + H_ne = 4 # number of elements of H + M_ne = 3 # number of elements of M + A_ne = 3 # number of elements of A + H_dense_ne = 6 # number of elements of H + M_dense_ne = 6 # number of elements of M + H_row = Cint[1, 2, 3, 3] # row indices, NB lower triangle + H_col = Cint[1, 2, 3, 1] + H_ptr = Cint[1, 2, 3, 5] + M_row = Cint[1, 2, 3] # row indices, NB lower triangle + M_col = Cint[1, 2, 3] + M_ptr = Cint[1, 2, 3, 4] + A_row = Cint[1, 1, 1] + A_col = Cint[1, 2, 3] + A_ptr = Cint[1, 4] + H_val = Float64[1.0, 2.0, 3.0, 4.0] + M_val = Float64[1.0, 2.0, 1.0] + A_val = Float64[1.0, 1.0, 1.0] + H_dense = Float64[1.0, 0.0, 2.0, 4.0, 0.0, 3.0] + M_dense = Float64[1.0, 0.0, 2.0, 0.0, 0.0, 1.0] + H_diag = Float64[1.0, 0.0, 2.0] + M_diag = Float64[1.0, 2.0, 1.0] + f = 0.96 + power = 3.0 + weight = 1.0 + c = Float64[0.0, 2.0, 0.0] + + st = ' ' + status = Ref{Cint}() + x = zeros(Float64, n) + + @printf(" Fortran sparse matrix indexing\n\n") + @printf(" basic tests of storage formats\n\n") + + for a_is in 0:1 # add a linear constraint? + for m_is in 0:1 # include a scaling matrix? + if (a_is == 1) && (m_is == 1) + ma = "MA" + elseif a_is == 1 + ma = "A" + elseif m_is == 1 + ma = "M" + else + ma = "" + end + + for storage_type in 1:4 + + # Initialize RQS + rqs_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # fortran sparse matrix indexing + + # sparse co-ordinate storage + if storage_type == 1 + st = 'C' + # import the control parameters and structural data + rqs_import(control, data, status, n, + "coordinate", H_ne, H_row, H_col, Cint[]) + if m_is == 1 + rqs_import_m(data, status, n, + "coordinate", M_ne, M_row, M_col, Cint[]) + end + if a_is == 1 + rqs_import_a(data, status, m, + "coordinate", A_ne, A_row, A_col, Cint[]) + end + + # solve the problem + if (a_is == 1) && (m_is == 1) + rqs_solve_problem(data, status, n, + power, weight, f, c, H_ne, H_val, x, + M_ne, M_val, m, A_ne, A_val, Cint[]) + elseif a_is == 1 + rqs_solve_problem(data, status, n, + power, weight, f, c, H_ne, H_val, x, + 0, Cint[], m, A_ne, A_val, Cint[]) + elseif m_is == 1 + rqs_solve_problem(data, status, n, + power, weight, f, c, H_ne, H_val, x, + M_ne, M_val, 0, 0, Cint[], Cint[]) + else + rqs_solve_problem(data, status, n, + power, weight, f, c, H_ne, H_val, x, + 0, Cint[], 0, 0, Cint[], Cint[]) + end + end + + # sparse by rows + if storage_type == 2 + st = 'R' + # import the control parameters and structural data + rqs_import(control, data, status, n, + "sparse_by_rows", H_ne, Cint[], H_col, H_ptr) + if m_is == 1 + rqs_import_m(data, status, n, + "sparse_by_rows", M_ne, Cint[], M_col, M_ptr) + end + if a_is == 1 + rqs_import_a(data, status, m, + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + end + + # solve the problem + if (a_is == 1) && (m_is == 1) + rqs_solve_problem(data, status, n, + power, weight, f, c, H_ne, H_val, x, + M_ne, M_val, m, A_ne, A_val, Cint[]) + elseif a_is == 1 + rqs_solve_problem(data, status, n, + power, weight, f, c, H_ne, H_val, x, + 0, Cint[], m, A_ne, A_val, Cint[]) + elseif m_is == 1 + rqs_solve_problem(data, status, n, + power, weight, f, c, H_ne, H_val, x, + M_ne, M_val, 0, 0, Cint[], Cint[]) + else + rqs_solve_problem(data, status, n, + power, weight, f, c, H_ne, H_val, x, + 0, Cint[], 0, 0, Cint[], Cint[]) + end + end + + # dense + if storage_type == 3 + st = 'D' + # import the control parameters and structural data + rqs_import(control, data, status, n, + "dense", H_ne, Cint[], Cint[], Cint[]) + if m_is == 1 + rqs_import_m(data, status, n, + "dense", M_ne, Cint[], Cint[], Cint[]) + end + + if a_is == 1 + rqs_import_a(data, status, m, + "dense", A_ne, Cint[], Cint[], Cint[]) + end + + # solve the problem + if (a_is == 1) && (m_is == 1) + rqs_solve_problem(data, status, n, power, weight, + f, c, H_dense_ne, H_dense, x, + M_dense_ne, M_dense, m, A_ne, A_val, + Cint[]) + elseif a_is == 1 + rqs_solve_problem(data, status, n, power, weight, + f, c, H_dense_ne, H_dense, x, + 0, Cint[], m, A_ne, A_val, Cint[]) + elseif m_is == 1 + rqs_solve_problem(data, status, n, power, weight, + f, c, H_dense_ne, H_dense, x, + M_dense_ne, M_dense, 0, 0, Cint[], Cint[]) + else + rqs_solve_problem(data, status, n, power, weight, + f, c, H_dense_ne, H_dense, x, + 0, Cint[], 0, 0, Cint[], Cint[]) + end + end + + # diagonal + if storage_type == 4 + st = 'L' + # import the control parameters and structural data + rqs_import(control, data, status, n, + "diagonal", H_ne, Cint[], Cint[], Cint[]) + if m_is == 1 + rqs_import_m(data, status, n, + "diagonal", M_ne, Cint[], Cint[], Cint[]) + end + if a_is == 1 + rqs_import_a(data, status, m, + "dense", A_ne, Cint[], Cint[], Cint[]) + end + + # solve the problem + if (a_is == 1) && (m_is == 1) + rqs_solve_problem(data, status, n, + power, weight, f, c, n, H_diag, x, + n, M_diag, m, A_ne, A_val, Cint[]) + elseif a_is == 1 + rqs_solve_problem(data, status, n, + power, weight, f, c, n, H_diag, x, + 0, Cint[], m, A_ne, A_val, Cint[]) + elseif m_is == 1 + rqs_solve_problem(data, status, n, + power, weight, f, c, n, H_diag, x, + n, M_diag, 0, 0, Cint[], Cint[]) + else + rqs_solve_problem(data, status, n, + power, weight, f, c, n, H_diag, x, + 0, Cint[], 0, 0, Cint[], Cint[]) + end + end + + rqs_information(data, inform, status) + + @printf("format %c%s: RQS_solve_problem exit status = %1i, f = %.2f\n", st, ma, + inform[].status, inform[].obj_regularized) + + # @printf("x: ") + # for(int i = 0 i < n+m i++) + # @printf("%f ", x[i]) + # end + + # Delete internal workspace + rqs_terminate(data, control, inform) + end + end end - ] - - rqs_information(data, inform, status) - - @printf("format %c%s: RQS_solve_problem exit status = %1i, f = %.2f\n", - st, ma, inform[].status, inform[].obj_regularized) - # @printf("x: ") - # for(int i = 0 i < n+m i++) @printf("%f ", x[i]) - - # Delete internal workspace - rqs_terminate(data, control, inform) - ] -] - ] -] - + return 0 end @testset "RQS" begin diff --git a/GALAHAD.jl/test/test_trb.jl b/GALAHAD.jl/test/test_trb.jl index e69de29bb2..c78a988f86 100644 --- a/GALAHAD.jl/test/test_trb.jl +++ b/GALAHAD.jl/test/test_trb.jl @@ -0,0 +1,510 @@ +/* trbtf.c */ +/* Full test for the TRB C interface using Fortran sparse matrix indexing */ + +#include +#include +#include "galahad_precision.h" +#include "galahad_cfunctions.h" +#include "galahad_trb.h" + +# Custom userdata struct +struct userdata_type { + real_wp_ p +] + +# Function prototypes +int fun(int n, var::Vector{Float64}, real_wp_ *f, const void *) +int grad(int n, var::Vector{Float64}, g::Vector{Float64}, const void *) +int hess(int n, int ne, var::Vector{Float64}, hval::Vector{Float64}, const void *) +int hess_dense(int n, int ne, var::Vector{Float64}, hval::Vector{Float64}, + const void *) +int hessprod(int n, var::Vector{Float64}, u::Vector{Float64}, var::Vector{Float64}, + bool got_h, const void *) +int shessprod(int n, var::Vector{Float64}, int nnz_v, const int index_nz_v[], +var::Vector{Float64}, int *nnz_u, int index_nz_u[], +u::Vector{Float64}, bool got_h, const void *) +int prec(int n, var::Vector{Float64}, u::Vector{Float64}, var::Vector{Float64}, + const void *) +int fun_diag(int n, var::Vector{Float64}, real_wp_ *f, const void *) +int grad_diag(int n, var::Vector{Float64}, g::Vector{Float64}, const void *) +int hess_diag(int n, int ne, var::Vector{Float64}, hval::Vector{Float64}, +const void *) +int hessprod_diag(int n, var::Vector{Float64}, u::Vector{Float64}, +var::Vector{Float64}, bool got_h, const void *) +int shessprod_diag(int n, var::Vector{Float64}, int nnz_v, +const int index_nz_v[], +var::Vector{Float64}, int *nnz_u, int index_nz_u[], +u::Vector{Float64}, bool got_h, const void *) + +# test_trb.jl +# Simple code to test the Julia interface to TRB + +using GALAHAD +using Test +using Printf +using Accessors + +function test_trb() +# Derived types +data = Ref{Ptr{Cvoid}}() +control = Ref{trb_control_type{Float64}}() +inform = Ref{trb_inform_type{Float64}}() + +# Set user data +struct userdata_type userdata +userdata.p = 4.0 + +# Set problem data +n = 3 # dimension +ne = 5 # Hesssian elements +x_l = Float64[-10,-10,-10] +x_u = Float64[0.5,0.5,0.5] +H_row = Cint[1, 2, 3, 3, 3] # Hessian H +H_col = Cint[1, 2, 1, 2, 3] # NB lower triangle +H_ptr = Cint[1, 2, 3, 6] # row pointers + +# Set storage +g = zeros(Float64, n) # gradient +st = ' ' = ' ' +status = Ref{Cint}() + +@printf(" Fortran sparse matrix indexing\n\n") + +@printf(" tests options for all-in-one storage format\n\n") + +for d = 1:5 + +# Initialize TRB +trb_initialize(data, control, status) + +# Set user-defined control options +control[].f_indexing = true # Fortran sparse matrix indexing +#control[].print_level = 1 + +# Start from 1.5 +x = Float64[1.5,1.5,1.5] + +# sparse co-ordinate storage +if d == 1 +st = 'C' +trb_import(control, data, status, n, x_l, x_u, +"coordinate", ne, H_row, H_col, Cint[]) +trb_solve_with_mat(data, userdata, status, n, x, g, ne, +fun, grad, hess, prec) +end +# sparse by rows +if d == 2 +st = 'R' +trb_import(control, data, status, n, x_l, x_u, +"sparse_by_rows", ne, Cint[], H_col, H_ptr) +trb_solve_with_mat(data, userdata, status, n, x, g, ne, +fun, grad, hess, prec) +end +# dense +if d == 3 +st = 'D' +trb_import(control, data, status, n, x_l, x_u, +"dense", ne, Cint[], Cint[], Cint[]) +trb_solve_with_mat(data, userdata, status, n, x, g, ne, +fun, grad, hess_dense, prec) +end +# diagonal +if d == 4 +st = 'I' +trb_import(control, data, status, n, x_l, x_u, +"diagonal", ne, Cint[], Cint[], Cint[]) +trb_solve_with_mat (data, userdata, status, n, x, g, ne, +fun_diag, grad_diag, hess_diag, prec) +end +case 5: # access by products +st = 'P' +trb_import(control, data, status, n, x_l, x_u, +"absent", ne, Cint[], Cint[], Cint[]) +trb_solve_without_mat(data, userdata, status, n, x, g, + fun, grad, hessprod, shessprod, prec) +end +] +# Record solution information +trb_information(data, inform, status) + +# Print solution details +if inform[].status == 0 +@printf("%c:%6i iterations. Optimal objective value = %5.2f status = %1i\n", + st, inform[].iter, inform[].obj, inform[].status) +else +@printf("%c: TRB_solve exit status = %1i\n", st, inform[].status) + +# @printf("x: ") +# for i = 1:n +# @printf("%f ", x[i]) +# @printf("\n") +# @printf("gradient: ") +# for i = 1:n +# @printf("%f ", g[i]) +# @printf("\n") + +# Delete internal workspace +trb_terminate(data, control, inform) +@printf("\n tests reverse-communication options\n\n") + +# reverse-communication input/output +int eval_status, nnz_v +int nnz_u +f = 0.0 +u = zeros(Float64, n), v[n] +index_nz_u = zeros(Cint, n), index_nz_v[n] +real_wp_ H_val[ne], H_dense[n*(n+1)/2], H_diag[n] +for d = 1:5 + +# Initialize TRB +trb_initialize(data, control, status) + +# Set user-defined control options +control[].f_indexing = true # Fortran sparse matrix indexing +#control[].print_level = 1 + +# Start from 1.5 +x = Float64[1.5,1.5,1.5] + +# sparse co-ordinate storage +if d == 1 +st = 'C' +trb_import(control, data, status, n, x_l, x_u, +"coordinate", ne, H_row, H_col, Cint[]) +while true # reverse-communication loop +trb_solve_reverse_with_mat(data, status, eval_status, +n, x, f, g, ne, H_val, u, v) +if status == 0 # successful termination +end +elseif status < 0) # error exit +end +elseif status == 2) # evaluate f +eval_status = fun(n, x, f, userdata) +elseif status == 3) # evaluate g +eval_status = grad(n, x, g, userdata) +elseif status == 4) # evaluate H +eval_status = hess(n, ne, x, H_val, userdata) +elseif status == 6) # evaluate the product with P +eval_status = prec(n, x, u, v, userdata) +else +@printf(" the value %1i of status should not occur\n", status) +end +] +] +end +# sparse by rows +if d == 2 +st = 'R' +trb_import(control, data, status, n, x_l, x_u, +"sparse_by_rows", ne, Cint[], H_col, H_ptr) +while true # reverse-communication loop +trb_solve_reverse_with_mat(data, status, eval_status, +n, x, f, g, ne, H_val, u, v) +if status == 0 # successful termination +end +elseif status < 0) # error exit +end +elseif status == 2) # evaluate f +eval_status = fun(n, x, f, userdata) +elseif status == 3) # evaluate g +eval_status = grad(n, x, g, userdata) +elseif status == 4) # evaluate H +eval_status = hess(n, ne, x, H_val, userdata) +elseif status == 6) # evaluate the product with P +eval_status = prec(n, x, u, v, userdata) +else +@printf(" the value %1i of status should not occur\n", status) +end +] +] +end +# dense +if d == 3 +st = 'D' +trb_import(control, data, status, n, x_l, x_u, +"dense", ne, Cint[], Cint[], Cint[]) +while true # reverse-communication loop +trb_solve_reverse_with_mat(data, status, eval_status, +n, x, f, g, n*(n+1)/2, H_dense, +u, v) +if status == 0 # successful termination +end +elseif status < 0) # error exit +end +elseif status == 2) # evaluate f +eval_status = fun(n, x, f, userdata) +elseif status == 3) # evaluate g +eval_status = grad(n, x, g, userdata) +elseif status == 4) # evaluate H +eval_status = hess_dense(n, n*(n+1)/2, x, H_dense, + userdata) +elseif status == 6) # evaluate the product with P +eval_status = prec(n, x, u, v, userdata) +else +@printf(" the value %1i of status should not occur\n", status) +end +] +] +end +# diagonal +if d == 4 +st = 'I' +trb_import(control, data, status, n, x_l, x_u, +"diagonal", ne, Cint[], Cint[], Cint[]) +while true # reverse-communication loop +trb_solve_reverse_with_mat(data, status, eval_status, +n, x, f, g, n, H_diag, u, v) +if status == 0 # successful termination +end +elseif status < 0) # error exit +end +elseif status == 2) # evaluate f +eval_status = fun_diag(n, x, f, userdata) +elseif status == 3) # evaluate g +eval_status = grad_diag(n, x, g, userdata) +elseif status == 4) # evaluate H +eval_status = hess_diag(n, n, x, H_diag, userdata) +elseif status == 6) # evaluate the product with P +eval_status = prec(n, x, u, v, userdata) +else +@printf(" the value %1i of status should not occur\n", status) +end +] +] +end +case 5: # access by products +st = 'P' +trb_import(control, data, status, n, x_l, x_u, +"absent", ne, Cint[], Cint[], Cint[]) +nnz_u = 0 +while true # reverse-communication loop +trb_solve_reverse_without_mat(data, status, eval_status, + n, x, f, g, u, v, index_nz_v, + nnz_v, index_nz_u, nnz_u) +if status == 0 # successful termination +end +elseif status < 0) # error exit +end +elseif status == 2) # evaluate f +eval_status = fun(n, x, f, userdata) +elseif status == 3) # evaluate g +eval_status = grad(n, x, g, userdata) +elseif status == 5) # evaluate H +eval_status = hessprod(n, x, u, v, false, userdata) +elseif status == 6) # evaluate the product with P +eval_status = prec(n, x, u, v, userdata) +elseif status == 7) # evaluate sparse Hessian-vect prod +eval_status = shessprod(n, x, nnz_v, index_nz_v, v, + nnz_u, index_nz_u, u, + false, userdata) +else +@printf(" the value %1i of status should not occur\n", status) +end +] +] +end +] + +# Record solution information +trb_information(data, inform, status) + +# Print solution details +if inform[].status == 0 +@printf("%c:%6i iterations. Optimal objective value = %5.2f status = %1i\n", + st, inform[].iter, inform[].obj, inform[].status) +else +@printf("%c: TRB_solve exit status = %1i\n", st, inform[].status) + +# @printf("x: ") +# for i = 1:n +# @printf("%f ", x[i]) +# @printf("\n") +# @printf("gradient: ") +# for i = 1:n +# @printf("%f ", g[i]) +# @printf("\n") + +# Delete internal workspace +trb_terminate(data, control, inform) +] + +# Objective function +int fun(int n, var::Vector{Float64}, real_wp_ *f, const void *userdata) +struct userdata_type *myuserdata = (struct userdata_type *) userdata +real_wp_ p = myuserdata->p + +*f = pow(x[0] + x[2] + p, 2) + pow(x[1] + x[2], 2) + cos(x[0]) +return 0 +] + +# Gradient of the objective +int grad(int n, var::Vector{Float64}, g::Vector{Float64}, const void *userdata) +struct userdata_type *myuserdata = (struct userdata_type *) userdata +real_wp_ p = myuserdata->p + +g[0] = 2.0 * (x[0] + x[2] + p) - sin(x[0]) +g[1] = 2.0 * (x[1] + x[2]) +g[2] = 2.0 * (x[0] + x[2] + p) + 2.0 * (x[1] + x[2]) +return 0 +] + +# Hessian of the objective +int hess(int n, int ne, var::Vector{Float64}, hval::Vector{Float64}, + const void *userdata) +hval[0] = 2.0 - cos(x[0]) +hval[1] = 2.0 +hval[2] = 2.0 +hval[3] = 2.0 +hval[4] = 4.0 +return 0 +] + +# Dense Hessian +int hess_dense(int n, int ne, var::Vector{Float64}, hval::Vector{Float64}, +const void *userdata) +hval[0] = 2.0 - cos(x[0]) +hval[1] = 0.0 +hval[2] = 2.0 +hval[3] = 2.0 +hval[4] = 2.0 +hval[5] = 4.0 +return 0 +] + +# Hessian-vector product +int hessprod(int n, var::Vector{Float64}, u::Vector{Float64}, var::Vector{Float64}, + bool got_h, const void *userdata) +u[0] = u[0] + 2.0 * (v[0] + v[2]) - cos(x[0]) * v[0] +u[1] = u[1] + 2.0 * (v[1] + v[2]) +u[2] = u[2] + 2.0 * (v[0] + v[1] + 2.0 * v[2]) +return 0 +] + +# Sparse Hessian-vector product +int shessprod(int n, var::Vector{Float64}, int nnz_v, const int index_nz_v[], + var::Vector{Float64}, int *nnz_u, int index_nz_u[], u::Vector{Float64}, + bool got_h, const void *userdata) +real_wp_ p[] = {0., 0., 0.] +bool used[] = {false, false, false] +for(int i = 0 i < nnz_v i++) +int j = index_nz_v[i] +switch(j) +case 1: +p[0] = p[0] + 2.0 * v[0] - cos(x[0]) * v[0] +used[0] = true +p[2] = p[2] + 2.0 * v[0] +used[2] = true +end +case 2: +p[1] = p[1] + 2.0 * v[1] +used[1] = true +p[2] = p[2] + 2.0 * v[1] +used[2] = true +end +case 3: +p[0] = p[0] + 2.0 * v[2] +used[0] = true +p[1] = p[1] + 2.0 * v[2] +used[1] = true +p[2] = p[2] + 4.0 * v[2] +used[2] = true +end +] +] +*nnz_u = 0 +for(int j = 0 j < 3 j++) +if used[j]) +u[j] = p[j] +*nnz_u = *nnz_u + 1 +index_nz_u[*nnz_u-1] = j+1 +] +] +return 0 +] + +# Apply preconditioner +int prec(int n, var::Vector{Float64}, u::Vector{Float64}, var::Vector{Float64}, + const void *userdata) + u[0] = 0.5 * v[0] + u[1] = 0.5 * v[1] + u[2] = 0.25 * v[2] + return 0 +] + + # Objective function +int fun_diag(int n, var::Vector{Float64}, real_wp_ *f, const void *userdata) +struct userdata_type *myuserdata = (struct userdata_type *) userdata +real_wp_ p = myuserdata->p + +*f = pow(x[2] + p, 2) + pow(x[1], 2) + cos(x[0]) +return 0 +] + +# Gradient of the objective +int grad_diag(int n, var::Vector{Float64}, g::Vector{Float64}, const void *userdata) +struct userdata_type *myuserdata = (struct userdata_type *) userdata +real_wp_ p = myuserdata->p + +g[0] = -sin(x[0]) +g[1] = 2.0 * x[1] +g[2] = 2.0 * (x[2] + p) +return 0 +] + +# Hessian of the objective +int hess_diag(int n, int ne, var::Vector{Float64}, hval::Vector{Float64}, + const void *userdata) +hval[0] = -cos(x[0]) +hval[1] = 2.0 +hval[2] = 2.0 +return 0 +] + +# Hessian-vector product +int hessprod_diag(int n, var::Vector{Float64}, u::Vector{Float64}, var::Vector{Float64}, + bool got_h, const void *userdata) +u[0] = u[0] + - cos(x[0]) * v[0] +u[1] = u[1] + 2.0 * v[1] +u[2] = u[2] + 2.0 * v[2] +return 0 +] + +# Sparse Hessian-vector product +int shessprod_diag(int n, var::Vector{Float64}, int nnz_v, +const int index_nz_v[], +var::Vector{Float64}, int *nnz_u, int index_nz_u[], +u::Vector{Float64}, bool got_h, const void *userdata) +real_wp_ p[] = {0., 0., 0.] +bool used[] = {false, false, false] +for(int i = 0 i < nnz_v i++) +int j = index_nz_v[i] +switch(j) +case 0: +p[0] = p[0] - cos(x[0]) * v[0] +used[0] = true +end +case 1: +p[1] = p[1] + 2.0 * v[1] +used[1] = true +end +case 2: +p[2] = p[2] + 2.0 * v[2] +used[2] = true +end +] +] +*nnz_u = 0 +for(int j = 0 j < 3 j++) +if used[j]) +u[j] = p[j] +*nnz_u = *nnz_u + 1 +index_nz_u[*nnz_u-1] = j+1 +] +] +return 0 +] +end + +@testset "TRB" begin + @test test_trb() == 0 +end diff --git a/GALAHAD.jl/test/test_ugo.jl b/GALAHAD.jl/test/test_ugo.jl index 1511878f7d..cc10243021 100644 --- a/GALAHAD.jl/test/test_ugo.jl +++ b/GALAHAD.jl/test/test_ugo.jl @@ -42,10 +42,7 @@ function test_ugo() @reset control[].print_level = Cint(1) # control.prefix = "'ugo: '" - @reset control[].prefix = convert(NTuple{31,Int8}, - (34, 39, 117, 103, 111, 58, 32, 39, 34, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 0)) + @reset control[].prefix = galahad_linear_solver("'ugo: '") # Read options from specfile specfile = "UGO.SPC"