diff --git a/GALAHAD.jl/gen/README.md b/GALAHAD.jl/gen/README.md index 95bb08c081..2766aae9d2 100644 --- a/GALAHAD.jl/gen/README.md +++ b/GALAHAD.jl/gen/README.md @@ -108,3 +108,20 @@ include("wrappers/abcd.jl") Now, the Julia wrappers for the `abcd` package are accessible upon loading the Julia interface with `using GALAHAD`. + +# Tests + +The file `examples.jl` help to generate Julia tests based on the C tests of a GALAHAD package. +- Create symbolic link +- Explain "tf", "t" or "" +- Call clean_example(...) + +```julia +(name == "abcd") && examples("abcd", "tf") +``` + +To test the new package named `abcd`, insert the following line in `GALAHAD.jl/test/runtests.jl`: + +```julia +include("test_abcd.jl") +``` diff --git a/GALAHAD.jl/gen/examples.jl b/GALAHAD.jl/gen/examples.jl index fbaa3bab35..50a564cf01 100644 --- a/GALAHAD.jl/gen/examples.jl +++ b/GALAHAD.jl/gen/examples.jl @@ -38,25 +38,28 @@ function examples(package::String, example::String) text = replace(text, "} #" => "] #") 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") + "C_dense", "H_diag", "C_diag", "H_scid", "C_scid", "Ao_val", "r", "M_val", "M_dense", + "M_diag", "y", "W") text = replace(text, "real_wp_ $var[] = {" => "$var = Float64[") end - for var in ("f", "power", "weight", "shift", "radius", "half_radius", "x_l", "x_u", "sigma") + for var in ("f", "power", "weight", "shift", "radius", "half_radius", "x_l", "x_u", "sigma", "rho_g", "rho_b") 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") + "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, "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") + "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, "int $var[] = {" => "$var = Cint[") end for val in ("1", "3", "5", "6", "7", "n", "n+m") 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") + for index in ("unit_m", "new_radius", "a_is", "m_is") 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 @@ -109,6 +112,10 @@ function examples(package::String, example::String) text = replace(text, "switch(d)\n" => "") 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 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) (example == "") && clean_example(package) diff --git a/GALAHAD.jl/test/runtests.jl b/GALAHAD.jl/test/runtests.jl index 57f73d371b..4440d1e2eb 100644 --- a/GALAHAD.jl/test/runtests.jl +++ b/GALAHAD.jl/test/runtests.jl @@ -13,8 +13,8 @@ include("test_bsc.jl") include("test_ccqp.jl") include("test_clls.jl") include("test_convert.jl") -# include("test_cqp.jl") -# include("test_cro.jl") +include("test_cqp.jl") +include("test_cro.jl") # include("test_dgo.jl") include("test_dps.jl") # include("test_dqp.jl") @@ -36,11 +36,11 @@ include("test_lpb.jl") include("test_lsqp.jl") include("test_lsrt.jl") include("test_lstr.jl") -# include("test_nls.jl") +## include("test_nls.jl") include("test_presolve.jl") include("test_psls.jl") -# include("test_qpa.jl") -# include("test_qpb.jl") +include("test_qpa.jl") +include("test_qpb.jl") include("test_roots.jl") # include("test_rpd.jl") # include("test_rqs.jl") @@ -49,11 +49,11 @@ include("test_sbls.jl") include("test_sec.jl") include("test_sha.jl") include("test_sils.jl") -# include("test_slls.jl") +## include("test_slls.jl") include("test_sls.jl") # include("test_trb.jl") -# include("test_trs.jl") -# include("test_tru.jl") +## include("test_trs.jl") +## include("test_tru.jl") include("test_ugo.jl") -# include("test_uls.jl") +include("test_uls.jl") include("test_wcp.jl") diff --git a/GALAHAD.jl/test/test_bgo.jl b/GALAHAD.jl/test/test_bgo.jl index e69de29bb2..6b633b7be6 100644 --- a/GALAHAD.jl/test/test_bgo.jl +++ b/GALAHAD.jl/test/test_bgo.jl @@ -0,0 +1,687 @@ +/* bgot2.c */ +/* Full test for the BGO C interface using Fortran sparse matrix indexing */ + +#include +#include +#include "galahad_precision.h" +#include "galahad_cfunctions.h" +#include "galahad_bgo.h" + +# Custom userdata struct +struct userdata_type { + real_wp_ p + real_wp_ freq + real_wp_ mag +] + +# Function prototypes +int fun(int n, const real_wp_ x[], real_wp_ *f, const void *) +int grad(int n, const real_wp_ x[], real_wp_ g[], const void *) +int hess(int n, int ne, const real_wp_ x[], real_wp_ hval[], const void *) +int hess_dense(int n, int ne, const real_wp_ x[], real_wp_ hval[], +const void *) +int hessprod(int n, const real_wp_ x[], real_wp_ u[], const real_wp_ v[], + bool got_h, const void *) +int shessprod(int n, const real_wp_ x[], int nnz_v, const int index_nz_v[], + const real_wp_ v[], int *nnz_u, int index_nz_u[], real_wp_ u[], + bool got_h, const void *) +int prec(int n, const real_wp_ x[], real_wp_ u[], const real_wp_ v[], + const void *) +int fun_diag(int n, const real_wp_ x[], real_wp_ *f, const void *) +int grad_diag(int n, const real_wp_ x[], real_wp_ g[], const void *) +int hess_diag(int n, int ne, const real_wp_ x[], real_wp_ hval[], + const void *) +int hessprod_diag(int n, const real_wp_ x[], real_wp_ u[], const real_wp_ v[], + bool got_h, const void *) +int shessprod_diag(int n, const real_wp_ x[], int nnz_v, +const int index_nz_v[], +const real_wp_ v[], int *nnz_u, int index_nz_u[], +real_wp_ u[], bool got_h, const void *) + +# test_bgo.jl +# Simple code to test the Julia interface to BGO + +using GALAHAD +using Test +using Printf +using Accessors + +function test_bgo() +# Derived types +data = Ref{Ptr{Cvoid}}() +control = Ref{bgo_control_type{Float64}}() +inform = Ref{bgo_inform_type{Float64}}() + +# Set user data +struct userdata_type userdata +userdata.p = 4.0 +userdata.freq = 10 +userdata.mag = 1000 + +# 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(int d=1 d <= 5 d++) + +# Initialize BGO +bgo_initialize(data, control, status) + +# Set user-defined control options +control[].f_indexing = true # Fortran sparse matrix indexing +control[].attempts_max = 10000 +control[].max_evals = 20000 +control[].sampling_strategy = 3 +control[].trb_control[].maxit = 100 +#control[].print_level = 1 + +# Start from 0 +x = Float64[0,0,0] + +switch(d) +# sparse co-ordinate storage +if d == 1 +st = 'C' +bgo_import(control, data, status, n, x_l, x_u, +"coordinate", ne, H_row, H_col, Cint[]) +bgo_solve_with_mat(data, userdata, status, n, x, g, +ne, fun, grad, hess, hessprod, prec) +end +# sparse by rows +if d == 2 +st = 'R' +bgo_import(control, data, status, n, x_l, x_u, +"sparse_by_rows", ne, Cint[], H_col, H_ptr) +bgo_solve_with_mat(data, userdata, status, n, x, g, +ne, fun, grad, hess, hessprod, prec) +end +# dense +if d == 3 +st = 'D' +bgo_import(control, data, status, n, x_l, x_u, +"dense", ne, Cint[], Cint[], Cint[]) +bgo_solve_with_mat(data, userdata, status, n, x, g, +ne, fun, grad, hess_dense, hessprod, prec) +end +# diagonal +if d == 4 +st = 'I' +bgo_import(control, data, status, n, x_l, x_u, +"diagonal", ne, Cint[], Cint[], Cint[]) +bgo_solve_with_mat(data, userdata, status, n, x, g, +ne, fun_diag, grad_diag, hess_diag, +hessprod_diag, prec) +end +case 5: # access by products +st = 'P' +bgo_import(control, data, status, n, x_l, x_u, +"absent", ne, Cint[], Cint[], Cint[]) +bgo_solve_without_mat(data, userdata, status, n, x, g, + fun, grad, hessprod, shessprod, prec) +end +] + +# Record solution information +bgo_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) +else +@printf("%c: BGO_solve exit status = %1i\n", st, inform[].status) + +# @printf("x: ") +# for(int i = 0 i < n i++) @printf("%f ", x[i]) +# @printf("\n") +# @printf("gradient: ") +# for(int i = 0 i < n i++) @printf("%f ", g[i]) +# @printf("\n") + +# Delete internal workspace +bgo_terminate(data, control, inform) +@printf("\n tests reverse-communication options\n\n") + +# reverse-communication input/output +int eval_status, nnz_u, nnz_v +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(int d=1 d <= 5 d++) + +# Initialize BGO +bgo_initialize(data, control, status) + +# Set user-defined control options +control[].f_indexing = true # Fortran sparse matrix indexing +control[].attempts_max = 10000 +control[].max_evals = 20000 +control[].sampling_strategy = 3 +control[].trb_control[].maxit = 100 +#control[].print_level = 1 + +# Start from 0 +x = Float64[0,0,0] + +switch(d) +# sparse co-ordinate storage +if d == 1 +st = 'C' +bgo_import(control, data, status, n, x_l, x_u, +"coordinate", ne, H_row, H_col, Cint[]) +while true # reverse-communication loop +bgo_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 == 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 +# sparse by rows +if d == 2 +st = 'R' +bgo_import(control, data, status, n, x_l, x_u, +"sparse_by_rows", ne, Cint[], H_col, H_ptr) +while true # reverse-communication loop +bgo_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 == 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 +# dense +if d == 3 +st = 'D' +bgo_import(control, data, status, n, x_l, x_u, +"dense", ne, Cint[], Cint[], Cint[]) +while true # reverse-communication loop +bgo_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 == 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 +# diagonal +if d == 4 +st = 'I' +bgo_import(control, data, status, n, x_l, x_u, +"diagonal", ne, Cint[], Cint[], Cint[]) +while true # reverse-communication loop +bgo_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 == 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 +case 5: # access by products +st = 'P' +bgo_import(control, data, status, n, x_l, x_u, +"absent", ne, Cint[], Cint[], Cint[]) +nnz_u = 0 +while true # reverse-communication loop +bgo_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 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 +] + +# Record solution information +bgo_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) +else +@printf("%c: BGO_solve exit status = %1i\n", st, inform[].status) + +# @printf("x: ") +# for(int i = 0 i < n i++) @printf("%f ", x[i]) +# @printf("\n") +# @printf("gradient: ") +# for(int i = 0 i < n i++) @printf("%f ", g[i]) +# @printf("\n") + +# Delete internal workspace +bgo_terminate(data, control, inform) +] + +# Objective function +int fun(int n, + const real_wp_ x[], + 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[0] + x[2] + p, 2) + pow(x[1] + x[2], 2) + mag * cos(freq*x[0]) + + x[0] + x[1] + x[2] +return 0 +] + +# Gradient of the objective +int grad(int n, + const real_wp_ x[], + real_wp_ g[], + 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] = 2.0 * (x[0] + x[2] + p) - mag * freq * sin(freq*x[0]) + 1 +g[1] = 2.0 * (x[1] + x[2]) + 1 +g[2] = 2.0 * (x[0] + x[2] + p) + 2.0 * (x[1] + x[2]) + 1 +return 0 +] + +# Hessian of the objective +int hess(int n, + int ne, + const real_wp_ x[], + real_wp_ hval[], + 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, +const real_wp_ x[], +real_wp_ hval[], +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, + const real_wp_ x[], + real_wp_ u[], + const real_wp_ v[], + 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, + const real_wp_ x[], + int nnz_v, + const int index_nz_v[], + const real_wp_ v[], + int *nnz_u, + int index_nz_u[], + real_wp_ u[], + 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, + const real_wp_ x[], + real_wp_ u[], + const real_wp_ v[], + 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, + const real_wp_ x[], + 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, + const real_wp_ x[], + real_wp_ g[], + 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, + const real_wp_ x[], + real_wp_ hval[], + 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, + const real_wp_ x[], + real_wp_ u[], + const real_wp_ v[], + 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, +const real_wp_ x[], +int nnz_v, +const int index_nz_v[], +const real_wp_ v[], +int *nnz_u, +int index_nz_u[], +real_wp_ u[], +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 + +@testset "BGO" begin + @test test_bgo() == 0 +end diff --git a/GALAHAD.jl/test/test_cqp.jl b/GALAHAD.jl/test/test_cqp.jl index 2bd6fe9914..215489b237 100644 --- a/GALAHAD.jl/test/test_cqp.jl +++ b/GALAHAD.jl/test/test_cqp.jl @@ -2,220 +2,227 @@ # Simple code to test the Julia interface to CQP using GALAHAD +using Test using Printf - -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = cqp_control_type{Float64}() -inform = cqp_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:7 - - # Initialize CQP - cqp_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' - - cqp_import( control, data, status, n, m, - "coordinate", H_ne, H_row, H_col, Cint[], - "coordinate", A_ne, A_row, A_col, Cint[] ) - - cqp_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' - - cqp_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 ) - - cqp_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] - - cqp_import( control, data, status, n, m, - "dense", H_ne, Cint[], Cint[], Cint[], - "dense", A_ne, Cint[], Cint[], Cint[] ) - - cqp_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' - - cqp_import( control, data, status, n, m, - "diagonal", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - cqp_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' - - cqp_import( control, data, status, n, m, - "scaled_identity", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - cqp_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_cqp() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{cqp_control_type{Float64}}() + inform = Ref{cqp_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:7 + # Initialize CQP + cqp_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' + cqp_import(control, data, status, n, m, + "coordinate", H_ne, H_row, H_col, Cint[], + "coordinate", A_ne, A_row, A_col, Cint[]) + + cqp_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' + cqp_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) + + cqp_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] + + cqp_import(control, data, status, n, m, + "dense", H_ne, Cint[], Cint[], Cint[], + "dense", A_ne, Cint[], Cint[], Cint[]) + + cqp_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' + cqp_import(control, data, status, n, m, + "diagonal", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + cqp_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' + cqp_import(control, data, status, n, m, + "scaled_identity", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + cqp_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' + cqp_import(control, data, status, n, m, + "identity", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + cqp_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 + + # zero + if d == 7 + st = 'Z' + cqp_import(control, data, status, n, m, + "zero", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + cqp_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 + + cqp_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: CQP_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 + cqp_terminate(data, control, inform) end - # identity - if d == 6 - global st = 'I' - - cqp_import( control, data, status, n, m, - "identity", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - cqp_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 - - # zero - if d == 7 - global st = 'Z' - - cqp_import( control, data, status, n, m, - "zero", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - cqp_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 - - cqp_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: CQP_solve exit status = %1i\n", st, inform.status) + # test shifted least-distance interface + for d in 1:1 + # Initialize CQP + cqp_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' + cqp_import(control, data, status, n, m, + "shifted_least_distance", H_ne, Cint[], Cint[], Cint[], + "coordinate", A_ne, A_row, A_col, Cint[]) + + cqp_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 + + cqp_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: CQP_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 + cqp_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 - cqp_terminate( data, control, inform ) + return 0 end -# test shifted least-distance interface -# Initialize CQP -cqp_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 -st = 'W' - -cqp_import( control, data, status, n, m, - "shifted_least_distance", H_ne, Cint[], Cint[], Cint[], - "coordinate", A_ne, A_row, A_col, Cint[] ) - -cqp_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 ) - -cqp_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: CQP_solve exit status = %1i\n", st, inform.status) +@testset "CQP" begin + @test test_cqp() == 0 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 -cqp_terminate( data, control, inform ) diff --git a/GALAHAD.jl/test/test_cro.jl b/GALAHAD.jl/test/test_cro.jl index abac1efb8f..ad59c7e57e 100644 --- a/GALAHAD.jl/test/test_cro.jl +++ b/GALAHAD.jl/test/test_cro.jl @@ -2,65 +2,76 @@ # Simple code to test the Julia interface to CRO using GALAHAD +using Test using Printf +using Accessors -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = cro_control_type{Float64}() -inform = cro_inform_type{Float64}() - -# Set problem dimensions -n = 11 # dimension -m = 3 # number of general constraints -m_equal = 1 # number of equality constraints - -# describe the objective function -H_ne = 21 -H_val = Float64[1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5,1.0] -H_col = Cint[1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11] -H_ptr = Cint[1,2,4,6,8,10,12,14,16,18,20,22] -g = Float64[0.5,-0.5,-1.0,-1.0,-1.0, -1.0,-1.0,-1.0,-1.0,-1.0,-0.5] - -# describe constraints -A_ne = 30 -A_val = Float64[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0] -A_col = Cint[1,2,3,4,5,6,7,8,9,10,11,3,4,5,6,7,8,9,10,11,2,3,4,5,6,7,8,9,10,11] -A_ptr = Cint[1,12,21,31] -c_l = Float64[10.0,9.0,-Inf] -c_u = Float64[10.0,Inf,10.0] -x_l = Float64[0.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0] -x_u = Float64[Inf,Inf,Inf,Inf,Inf,Inf,Inf,Inf,Inf,Inf,Inf] - -# provide optimal variables, Lagrange multipliers and dual variables -x = Float64[0.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0, 1.0,1.0,1.0] -c = Float64[10.0,9.0,10.0] -y = Float64[-1.0,1.5,-2.0] -z = Float64[2.0,4.0,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5] - -# provide interior-point constraint and variable status -c_stat = Cint[-1,-1,1] -x_stat = Cint[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] - -# Set output storage -status = Ref{Cint}() - -@printf(" Fortran sparse matrix indexing\n\n") - -# Initialize CRO -cro_initialize( data, control, status ) - -# Set user-defined control options -control.f_indexing = true # Fortran sparse matrix indexing - -# crossover the solution -cro_crossover_solution( data, control, inform, - n, m, m_equal, - H_ne, H_val, H_col, H_ptr, - A_ne, A_val, A_col, A_ptr, - g, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) - -@printf(" CRO_crossover exit status = %1i\n", inform.status) - -# Delete internal workspace -cro_terminate( data, control, inform ) +function test_cro() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{cro_control_type{Float64}}() + inform = Ref{cro_inform_type{Float64}}() + + # Set problem dimensions + n = 11 # dimension + m = 3 # number of general constraints + m_equal = 1 # number of equality constraints + + # describe the objective function + + H_ne = 21 + H_val = Float64[1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 1.0, + 0.5, 1.0, 0.5, 1.0, 0.5, 1.0] + H_col = Cint[1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11] + H_ptr = Cint[1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22] + g = Float64[0.5, -0.5, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -0.5] + + # describe constraints + + A_ne = 30 + A_val = Float64[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + A_col = Cint[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11] + A_ptr = Cint[1, 12, 21, 31] + c_l = Float64[10.0, 9.0, -Inf] + c_u = Float64[10.0, Inf, 10.0] + x_l = Float64[0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + x_u = Float64[Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf, Inf] + + # provide optimal variables, Lagrange multipliers and dual variables + x = Float64[0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + c = Float64[10.0, 9.0, 10.0] + y = Float64[-1.0, 1.5, -2.0] + z = Float64[2.0, 4.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5] + + # provide interior-point constraint and variable status + c_stat = Cint[-1, -1, 1] + x_stat = Cint[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] + + # Set output storage + status = Ref{Cint}() + @printf(" Fortran sparse matrix indexing\n\n") + + # Initialize CRO + cro_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + + # crossover the solution + cro_crossover_solution(data, control, inform, n, m, m_equal, H_ne, H_val, H_col, H_ptr, + A_ne, A_val, A_col, A_ptr, g, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) + + @printf(" CRO_crossover exit status = %1i\n", inform[].status) + + # Delete internal workspace + cro_terminate(data, control, inform) + + return 0 +end + +@testset "CRO" begin + @test test_cro() == 0 +end diff --git a/GALAHAD.jl/test/test_llst.jl b/GALAHAD.jl/test/test_llst.jl index 0d0d597c58..4e34d13ebe 100644 --- a/GALAHAD.jl/test/test_llst.jl +++ b/GALAHAD.jl/test/test_llst.jl @@ -134,7 +134,7 @@ function test_llst() 32, 32, 32, 32, 32, 32, 32, 32, 32, 0)) - # @reset control[].print_level = 1 + # @reset control[].print_level = Cint(1) # Set user-defined control options @reset control[].f_indexing = true # Fortran sparse matrix indexing diff --git a/GALAHAD.jl/test/test_nls.jl b/GALAHAD.jl/test/test_nls.jl index e69de29bb2..54cd373742 100644 --- a/GALAHAD.jl/test/test_nls.jl +++ b/GALAHAD.jl/test/test_nls.jl @@ -0,0 +1,620 @@ +# test_nls.jl +# Simple code to test the Julia interface to NLS + +using GALAHAD +using Test +using Printf +using Accessors + +# Custom userdata struct +struct userdata_type +p::Float64 +end + +function test_nls() + # compute the residuals + function res(n, m, x::Vector{Float64}, c::Vector{Float64}, userdata::userdata_type) + c[1] = pow(x[1], 2.0) + userdata.p + c[2] = x[1] + x[2]^(2.0) + c[3] = x[1] - x[2] + return 0 + end + + # compute the Jacobian + function jac(n, m, jne, x::Vector{Float64}, jval::Vector{Float64}, + userdata::userdata_type) + jval[1] = 2.0 * x[1] + jval[2] = 1.0 + jval[3] = 2.0 * x[2] + jval[4] = 1.0 + jval[5] = -1.0 + return 0 + end + + # compute the Hessian + function hess(n, m, hne, x::Vector{Float64}, y::Vector{Float64}, hval::Vector{Float64}, + userdata::userdata_type) + hval[1] = 2.0 * y[1] + hval[2] = 2.0 * y[2] + return 0 + end + + # compute Jacobian-vector products + function jacprod(n, m, x::Vector{Float64}, transpose::Bool, u::Vector{Float64}, + v::Vector{Float64}, got_j::Bool, userdata::userdata_type) + if transpose + u[1] = u[1] + 2.0 * x[1] * v[1] + v[2] + v[3] + u[2] = u[2] + 2.0 * x[2] * v[2] - v[3] + else + u[1] = u[1] + 2.0 * x[1] * v[1] + u[2] = u[2] + v[1] + 2.0 * x[2] * v[2] + u[3] = u[3] + v[1] - v[2] + end + return 0 + end + + # compute Hessian-vector products + function hessprod(n, m, x::Vector{Float64}, y::Vector{Float64}, u::Vector{Float64}, + v::Vector{Float64}, got_h::Bool, userdata::userdata_type) + u[1] = u[1] + 2.0 * y[1] * v[1] + u[2] = u[2] + 2.0 * y[2] * v[2] + return 0 + end + + # compute residual-Hessians-vector products + function rhessprods(n, m, pne, x::Vector{Float64}, v::Vector{Float64}, + pval::Vector{Float64}, got_h::Bool, userdata::userdata_type) + pval[1] = 2.0 * v[1] + pval[2] = 2.0 * v[2] + return 0 + end + + # # scale v + function scale(n, m, x::Vector{Float64}, u::Vector{Float64}, v::Vector{Float64}, + userdata::userdata_type) + u[1] = v[1] + u[2] = v[2] + return 0 + end + + # compute the dense Jacobian + function jac_dense(n, m, jne, x::Vector{Float64}, jval::Vector{Float64}, + userdata::userdata_type) + jval[1] = 2.0 * x[1] + jval[2] = 0.0 + jval[3] = 1.0 + jval[4] = 2.0 * x[2] + jval[5] = 1.0 + jval[6] = -1.0 + return 0 + end + + # compute the dense Hessian + function hess_dense(n, m, hne, x::Vector{Float64}, y::Vector{Float64}, + hval::Vector{Float64}, userdata::userdata_type) + hval[1] = 2.0 * y[1] + hval[2] = 0.0 + hval[3] = 2.0 * y[2] + return 0 + end + + # compute dense residual-Hessians-vector products + function rhessprods_dense(n, m, pne, x::Vector{Float64}, v::Vector{Float64}, + pval::Vector{Float64}, got_h::Bool, userdata::userdata_type) + pval[1] = 2.0 * v[1] + pval[2] = 0.0 + pval[3] = 0.0 + pval[4] = 2.0 * v[2] + pval[5] = 0.0 + pval[6] = 0.0 + return 0 + end + + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{nls_control_type{Float64}}() + inform = Ref{nls_inform_type{Float64}}() + + # Set user data + userdata = userdata_type(1.0) + + # Set problem data + n = 2 # # variables + m = 3 # # residuals + j_ne = 5 # Jacobian elements + h_ne = 2 # Hesssian elements + p_ne = 2 # residual-Hessians-vector products elements + J_row = Cint[1, 2, 2, 3, 3] # Jacobian J + J_col = Cint[1, 1, 2, 1, 2] # + J_ptr = Cint[1, 2, 4, 6] # row pointers + H_row = Cint[1, 2] # Hessian H + H_col = Cint[1, 2] # NB lower triangle + H_ptr = Cint[1, 2, 3] # row pointers + P_row = Cint[1, 2] # residual-Hessians-vector product matrix + P_ptr = Cint[1, 2, 3, 3] # column pointers + + # Set storage + g = zeros(Float64, n) # gradient + c = zeros(Float64, m) # residual + y = zeros(Float64, m) # multipliers + W = Float64[1.0, 1.0, 1.0] # weights + 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 NLS + nls_initialize(data, control, inform) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + # @reset control[].print_level = Cint(1) + @reset control[].jacobian_available = Cint(2) + @reset control[].hessian_available = Cint(2) + @reset control[].model = Cint(6) + x = Float64[1.5, 1.5] # starting point + W = Float64[1.0, 1.0, 1.0] # weights + + # sparse co-ordinate storage + if d == 1 + st = 'C' + nls_import(control, data, status, n, m, + "coordinate", j_ne, J_row, J_col, Cint[], + "coordinate", h_ne, H_row, H_col, Cint[], + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + nls_solve_with_mat(data, userdata, status, + n, m, x, c, g, res, j_ne, jac, + h_ne, hess, p_ne, rhessprods) + end + + # sparse by rows + if d == 2 + st = 'R' + nls_import(control, data, status, n, m, + "sparse_by_rows", j_ne, Cint[], J_col, J_ptr, + "sparse_by_rows", h_ne, Cint[], H_col, H_ptr, + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + nls_solve_with_mat(data, userdata, status, + n, m, x, c, g, res, j_ne, jac, + h_ne, hess, p_ne, rhessprods) + end + + # dense + if d == 3 + st = 'D' + nls_import(control, data, status, n, m, + "dense", j_ne, Cint[], Cint[], Cint[], + "dense", h_ne, Cint[], Cint[], Cint[], + "dense", p_ne, Cint[], Cint[], Cint[], W) + + nls_solve_with_mat(data, userdata, status, + n, m, x, c, g, res, j_ne, jac_dense, + h_ne, hess_dense, p_ne, rhessprods_dense) + end + + # diagonal + if d == 4 + st = 'I' + nls_import(control, data, status, n, m, + "sparse_by_rows", j_ne, Cint[], J_col, J_ptr, + "diagonal", h_ne, Cint[], Cint[], Cint[], + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + nls_solve_with_mat(data, userdata, status, + n, m, x, c, g, res, j_ne, jac, + h_ne, hess, p_ne, rhessprods) + end + + # access by products + if d == 5 + st = 'P' + nls_import(control, data, status, n, m, + "absent", j_ne, Cint[], Cint[], Cint[], + "absent", h_ne, Cint[], Cint[], Cint[], + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + nls_solve_without_mat(data, userdata, status, + n, m, x, c, g, res, jacprod, + hessprod, p_ne, rhessprods) + end + + nls_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: NLS_solve exit status = %1i\n", st, inform[].status) + end + + # Delete internal workspace + nls_terminate(data, control, inform) + end + + @printf("\n tests reverse-communication options\n\n") + # reverse-communication input/output + eval_status = Ref{Cint}() + u = zeros(Float64, max(m, n)) + v = zeros(Float64, max(m, n)) + J_val = zeros(Float64, j_ne) + J_dense = zeros(Float64, m * n) + H_val = zeros(Float64, h_ne) + H_dense = zeros(Float64, div(n * (n + 1), 2)) + H_diag = zeros(Float64, n) + P_val = zeros(Float64, p_ne) + P_dense = zeros(Float64, m * n) + got_j = false + got_h = false + + for d in 1:5 + # Initialize NLS + nls_initialize(data, control, inform) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + # @reset control[].print_level = Cint(1) + @reset control[].jacobian_available = 2 + @reset control[].hessian_available = 2 + @reset control[].model = 6 + x = Float64[1.5, 1.5] # starting point + W = Float64[1.0, 1.0, 1.0] # weights + + # sparse co-ordinate storage + if d == 1 + st = 'C' + nls_import(control, data, status, n, m, + "coordinate", j_ne, J_row, J_col, Cint[], + "coordinate", h_ne, H_row, H_col, Cint[], + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + terminated = false + while !terminated # reverse-communication loop + nls_solve_reverse_with_mat(data, status, eval_status, + n, m, x, c, g, j_ne, J_val, y, + h_ne, H_val, v, p_ne, P_val) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate c + eval_status[] = res(n, m, x, c, userdata) + elseif status[] == 3 # evaluate J + eval_status[] = jac(n, m, j_ne, x, J_val, userdata) + elseif status[] == 4 # evaluate H + eval_status[] = hess(n, m, h_ne, x, y, H_val, userdata) + elseif status[] == 7 # evaluate P + eval_status[] = rhessprods(n, m, p_ne, x, v, P_val, got_h, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # sparse by rows + if d == 2 + st = 'R' + nls_import(control, data, status, n, m, + "sparse_by_rows", j_ne, Cint[], J_col, J_ptr, + "sparse_by_rows", h_ne, Cint[], H_col, H_ptr, + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + terminated = false + while !terminated # reverse-communication loop + nls_solve_reverse_with_mat(data, status, eval_status, + n, m, x, c, g, j_ne, J_val, y, + h_ne, H_val, v, p_ne, P_val) + if status[] == 0 # successful termination + terminated[] = true + elseif status[] < 0 # error exit + terminated[] = true + elseif status[] == 2 # evaluate c + eval_status[] = res(n, m, x, c, userdata) + elseif status[] == 3 # evaluate J + eval_status[] = jac(n, m, j_ne, x, J_val, userdata) + elseif status[] == 4 # evaluate H + eval_status[] = hess(n, m, h_ne, x, y, H_val, userdata) + elseif status[] == 7 # evaluate P + eval_status[] = rhessprods(n, m, p_ne, x, v, P_val, got_h, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # dense + if d == 3 + st = 'D' + nls_import(control, data, status, n, m, + "dense", j_ne, Cint[], Cint[], Cint[], + "dense", h_ne, Cint[], Cint[], Cint[], + "dense", p_ne, Cint[], Cint[], Cint[], W) + + terminated = false + while !terminated # reverse-communication loop + nls_solve_reverse_with_mat(data, status, eval_status, + n, m, x, c, g, m * n, J_dense, y, + n * (n + 1) / 2, H_dense, v, m * n, + P_dense) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate c + eval_status[] = res(n, m, x, c, userdata) + elseif status[] == 3 # evaluate J + eval_status[] = jac_dense(n, m, j_ne, x, J_dense, userdata) + elseif status[] == 4 # evaluate H + eval_status[] = hess_dense(n, m, h_ne, x, y, H_dense, userdata) + elseif status[] == 7 # evaluate P + eval_status[] = rhessprods_dense(n, m, p_ne, x, v, P_dense, got_h, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # diagonal + if d == 4 + st = 'I' + nls_import(control, data, status, n, m, + "sparse_by_rows", j_ne, Cint[], J_col, J_ptr, + "diagonal", h_ne, Cint[], Cint[], Cint[], + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + terminated = false + while !terminated # reverse-communication loop + nls_solve_reverse_with_mat(data, status, eval_status, + n, m, x, c, g, j_ne, J_val, y, + n, H_diag, v, p_ne, P_val) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate c + eval_status[] = res(n, m, x, c, userdata) + elseif status[] == 3 # evaluate J + eval_status[] = jac(n, m, j_ne, x, J_val, userdata) + elseif status[] == 4 # evaluate H + eval_status[] = hess(n, m, h_ne, x, y, H_diag, userdata) + elseif status[] == 7 # evaluate P + eval_status[] = rhessprods(n, m, p_ne, x, v, P_val, got_h, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + # access by products + if d == 5 + st = 'P' + # @reset control[].print_level = Cint(1) + nls_import(control, data, status, n, m, + "absent", j_ne, Cint[], Cint[], Cint[], + "absent", h_ne, Cint[], Cint[], Cint[], + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + terminated = false + while !terminated # reverse-communication loop + nls_solve_reverse_without_mat(data, status, eval_status, + n, m, x, c, g, transpose, + u, v, y, p_ne, P_val) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate c + eval_status[] = res(n, m, x, c, userdata) + elseif status[] == 5 # evaluate u + J v or u + J'v + eval_status[] = jacprod(n, m, x, transpose, u, v, got_j, userdata) + elseif status[] == 6 # evaluate u + H v + eval_status[] = hessprod(n, m, x, y, u, v, got_h, userdata) + elseif status[] == 7 # evaluate P + eval_status[] = rhessprods(n, m, p_ne, x, v, P_val, got_h, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + nls_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: NLS_solve exit status = %1i\n", st, inform[].status) + end + + # Delete internal workspace + nls_terminate(data, control, inform) + end + + @printf("\n basic tests of models used, direct access\n\n") + for model in 3:8 + # Initialize NLS + nls_initialize(data, control, inform) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + # @reset control[].print_level = Cint(1) + @reset control[].jacobian_available = Cint(2) + @reset control[].hessian_available = Cint(2) + @reset control[].model = model + x = Float64[1.5, 1.5] # starting point + W = Float64[1.0, 1.0, 1.0] # weights + + nls_import(control, data, status, n, m, + "sparse_by_rows", j_ne, Cint[], J_col, J_ptr, + "sparse_by_rows", h_ne, Cint[], H_col, H_ptr, + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + nls_solve_with_mat(data, userdata, status, + n, m, x, c, g, res, j_ne, jac, + h_ne, hess, p_ne, rhessprods) + + nls_information(data, inform, status) + + if inform[].status == 0 + @printf(" %1i:%6i iterations. Optimal objective value = %5.2f status = %1i\n", + model, inform[].iter, inform[].obj, inform[].status) + else + @printf(" %i: NLS_solve exit status = %1i\n", model, inform[].status) + end + + # Delete internal workspace + nls_terminate(data, control, inform) + end + + @printf("\n basic tests of models used, access by products\n\n") + for model in 3:8 + # Initialize NLS + nls_initialize(data, control, inform) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + # @reset control[].print_level = Cint(1) + @reset control[].jacobian_available = Cint(2) + @reset control[].hessian_available = Cint(2) + @reset control[].model = model + x = Float64[1.5, 1.5] # starting point + W = Float64[1.0, 1.0, 1.0] # weights + + nls_import(control, data, status, n, m, + "absent", j_ne, Cint[], Cint[], Cint[], + "absent", h_ne, Cint[], Cint[], Cint[], + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + nls_solve_without_mat(data, userdata, status, + n, m, x, c, g, res, jacprod, + hessprod, p_ne, rhessprods) + + nls_information(data, inform, status) + + if inform[].status == 0 + @printf("P%1i:%6i iterations. Optimal objective value = %5.2f status = %1i\n", + model, inform[].iter, inform[].obj, inform[].status) + else + @printf("P%i: NLS_solve exit status = %1i\n", model, inform[].status) + end + + # Delete internal workspace + nls_terminate(data, control, inform) + end + + @printf("\n basic tests of models used, reverse access\n\n") + for model in 3:8 + # Initialize NLS + nls_initialize(data, control, inform) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + # @reset control[].print_level = Cint(1) + @reset control[].jacobian_available = Cint(2) + @reset control[].hessian_available = Cint(2) + @reset control[].model = model + x = Float64[1.5, 1.5] # starting point + W = Float64[1.0, 1.0, 1.0] # weights + + nls_import(control, data, status, n, m, + "sparse_by_rows", j_ne, Cint[], J_col, J_ptr, + "sparse_by_rows", h_ne, Cint[], H_col, H_ptr, + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + terminated = false + while !terminated # reverse-communication loop + nls_solve_reverse_with_mat(data, status, eval_status, + n, m, x, c, g, j_ne, J_val, y, + h_ne, H_val, v, p_ne, P_val) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate c + eval_status[] = res(n, m, x, c, userdata) + elseif status[] == 3 # evaluate J + eval_status[] = jac(n, m, j_ne, x, J_val, userdata) + elseif status[] == 4 # evaluate H + eval_status[] = hess(n, m, h_ne, x, y, H_val, userdata) + elseif status[] == 7 # evaluate P + eval_status[] = rhessprods(n, m, p_ne, x, v, P_val, got_h, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + + nls_information(data, inform, status) + + if inform[].status == 0 + @printf("P%1i:%6i iterations. Optimal objective value = %5.2f status = %1i\n", + model, inform[].iter, inform[].obj, inform[].status) + else + @printf(" %i: NLS_solve exit status = %1i\n", model, inform[].status) + end + + # Delete internal workspace + nls_terminate(data, control, inform) + end + + @printf("\n basic tests of models used, reverse access by products\n\n") + for model in 3:8 + # Initialize NLS + nls_initialize(data, control, inform) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + # @reset control[].print_level = 1 + @reset control[].jacobian_available = Cint(2) + @reset control[].hessian_available = Cint(2) + @reset control[].model = model + x = Float64[1.5, 1.5] # starting point + W = Float64[1.0, 1.0, 1.0] # weights + + nls_import(control, data, status, n, m, + "absent", j_ne, Cint[], Cint[], Cint[], + "absent", h_ne, Cint[], Cint[], Cint[], + "sparse_by_columns", p_ne, P_row, Cint[], P_ptr, W) + + terminated = false + while !terminated # reverse-communication loop + nls_solve_reverse_without_mat(data, status, eval_status, + n, m, x, c, g, transpose, + u, v, y, p_ne, P_val) + if status[] == 0 # successful termination + terminated = true + elseif status[] < 0 # error exit + terminated = true + elseif status[] == 2 # evaluate c + eval_status[] = res(n, m, x, c, userdata) + elseif status[] == 5 # evaluate u + J v or u + J'v + eval_status[] = jacprod(n, m, x, transpose, u, v, got_j, userdata) + elseif status[] == 6 # evaluate u + H v + eval_status[] = hessprod(n, m, x, y, u, v, got_h, userdata) + elseif status[] == 7 # evaluate P + eval_status[] = rhessprods(n, m, p_ne, x, v, P_val, got_h, userdata) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + + nls_information(data, inform, status) + + if inform[].status == 0 + @printf("P%1i:%6i iterations. Optimal objective value = %5.2f status = %1i\n", + model, inform[].iter, inform[].obj, inform[].status) + else + @printf("P%i: NLS_solve exit status = %1i\n", model, inform[].status) + end + + # Delete internal workspace + nls_terminate(data, control, inform) + end + + return 0 +end + +@testset "NLS" begin + @test test_nls() == 0 +end diff --git a/GALAHAD.jl/test/test_qpa.jl b/GALAHAD.jl/test/test_qpa.jl index 746598f1a4..f5ae6ded15 100644 --- a/GALAHAD.jl/test/test_qpa.jl +++ b/GALAHAD.jl/test/test_qpa.jl @@ -2,224 +2,235 @@ # Simple code to test the Julia interface to QPA using GALAHAD +using Test using Printf - -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = qpa_control_type{Float64}() -inform = qpa_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 -rho_g = 0.1 # penalty paramter for general constraints -rho_b = 0.1 # penalty paramter for simple bound constraints -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:7 - # Initialize QPA - qpa_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' - - qpa_import( control, data, status, n, m, - "coordinate", H_ne, H_row, H_col, Cint[], - "coordinate", A_ne, A_row, A_col, Cint[] ) - - qpa_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_qpa() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{qpa_control_type{Float64}}() + inform = Ref{qpa_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 + rho_g = 0.1 # penalty paramter for general constraints + rho_b = 0.1 # penalty paramter for simple bound constraints + 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:7 + # Initialize QPA + qpa_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' + qpa_import(control, data, status, n, m, + "coordinate", H_ne, H_row, H_col, Cint[], + "coordinate", A_ne, A_row, A_col, Cint[]) + + qpa_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' + qpa_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) + + qpa_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] + + qpa_import(control, data, status, n, m, + "dense", H_ne, Cint[], Cint[], Cint[], + "dense", A_ne, Cint[], Cint[], Cint[]) + + qpa_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' + qpa_import(control, data, status, n, m, + "diagonal", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + qpa_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' + qpa_import(control, data, status, n, m, + "scaled_identity", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + qpa_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' + qpa_import(control, data, status, n, m, + "identity", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + qpa_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 + + # zero + if d == 7 + st = 'Z' + qpa_import(control, data, status, n, m, + "zero", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + qpa_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 + + qpa_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: QPA_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 + qpa_terminate(data, control, inform) end - # sparse by rows - if d == 2 - global st = 'R' - - qpa_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 ) - - qpa_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] - - qpa_import( control, data, status, n, m, - "dense", H_ne, Cint[], Cint[], Cint[], - "dense", A_ne, Cint[], Cint[], Cint[] ) - - qpa_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' - - qpa_import( control, data, status, n, m, - "diagonal", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - qpa_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' - - qpa_import( control, data, status, n, m, - "scaled_identity", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - qpa_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' - - qpa_import( control, data, status, n, m, - "identity", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - qpa_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 - - # zero - if d == 7 - global st = 'Z' - - qpa_import( control, data, status, n, m, - "zero", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - qpa_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 - - qpa_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: QPA_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 - qpa_terminate( data, control, inform ) @printf("\n basic tests of l_1 qp storage formats\n\n") - - qpa_initialize( data, control, status ) + qpa_initialize(data, control, status) # Set user-defined control options - control.f_indexing = true # Fortran sparse matrix indexing + @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] + x = Float64[0.0, 0.0, 0.0] + y = Float64[0.0, 0.0] + z = Float64[0.0, 0.0, 0.0] # solve the l_1qp problem - qpa_import( control, data, status, n, m, - "coordinate", H_ne, H_row, H_col, Cint[], - "coordinate", A_ne, A_row, A_col, Cint[] ) + qpa_import(control, data, status, n, m, + "coordinate", H_ne, H_row, H_col, Cint[], + "coordinate", A_ne, A_row, A_col, Cint[]) - qpa_solve_l1qp( data, status, n, m, H_ne, H_val, g, f, rho_g, rho_b, - A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) + qpa_solve_l1qp(data, status, n, m, H_ne, H_val, g, f, rho_g, rho_b, + A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) - qpa_information( data, inform, status ) + qpa_information(data, inform, status) - if inform.status == 0 - @printf("%s %6i iterations. Optimal objective value = %5.2f status = %1i\n", "l1qp ", inform.iter, inform.obj, inform.status) + if inform[].status == 0 + @printf("%s %6i iterations. Optimal objective value = %5.2f status = %1i\n", + "l1qp ", inform[].iter, inform[].obj, inform[].status) else - @printf("%c: QPA_solve exit status = %1i\n", st, inform.status) + @printf("%c: QPA_solve exit status = %1i\n", st, inform[].status) end # Start from 0 - x .= 0.0 - y .= 0.0 - z .= 0.0 + for i in 1:n + x[i] = 0.0 + z[i] = 0.0 + end + for i in 1:m + y[i] = 0.0 + end # solve the bound constrained l_1qp problem - qpa_import( control, data, status, n, m, - "coordinate", H_ne, H_row, H_col, Cint[], - "coordinate", A_ne, A_row, A_col, Cint[] ) + qpa_import(control, data, status, n, m, + "coordinate", H_ne, H_row, H_col, Cint[], + "coordinate", A_ne, A_row, A_col, Cint[]) - qpa_solve_bcl1qp( data, status, n, m, H_ne, H_val, g, f, rho_g, - A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, - x_stat, c_stat ) + qpa_solve_bcl1qp(data, status, n, m, H_ne, H_val, g, f, rho_g, + A_ne, A_val, c_l, c_u, x_l, x_u, x, c, y, z, + x_stat, c_stat) - qpa_information( data, inform, status ) + qpa_information(data, inform, status) - if inform.status == 0 - @printf("%s %6i iterations. Optimal objective value = %5.2f status = %1i\n", "bcl1qp", inform.iter, inform.obj, inform.status) + if inform[].status == 0 + @printf("%s %6i iterations. Optimal objective value = %5.2f status = %1i\n", + "bcl1qp", inform[].iter, inform[].obj, inform[].status) else - @printf("%c: QPA_solve exit status = %1i\n", st, inform.status) + @printf("%c: QPA_solve exit status = %1i\n", st, inform[].status) end # Delete internal workspace - qpa_terminate( data, control, inform ) -end \ No newline at end of file + qpa_terminate(data, control, inform) + + return 0 +end + +@testset "QPA" begin + @test test_qpa() == 0 +end diff --git a/GALAHAD.jl/test/test_qpb.jl b/GALAHAD.jl/test/test_qpb.jl index 5354c16aab..85c4c778b1 100644 --- a/GALAHAD.jl/test/test_qpb.jl +++ b/GALAHAD.jl/test/test_qpb.jl @@ -2,170 +2,174 @@ # Simple code to test the Julia interface to QPB using GALAHAD +using Test using Printf - -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = qpb_control_type{Float64}() -inform = qpb_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:7 - # Initialize QPB - qpb_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' - - qpb_import( control, data, status, n, m, - "coordinate", H_ne, H_row, H_col, Cint[], - "coordinate", A_ne, A_row, A_col, Cint[] ) - - qpb_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' - - qpb_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 ) - - qpb_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_qpb() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{qpb_control_type{Float64}}() + inform = Ref{qpb_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:7 + # Initialize QPB + qpb_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' + qpb_import(control, data, status, n, m, + "coordinate", H_ne, H_row, H_col, Cint[], + "coordinate", A_ne, A_row, A_col, Cint[]) + + qpb_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' + qpb_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) + + qpb_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] + + qpb_import(control, data, status, n, m, + "dense", H_ne, Cint[], Cint[], Cint[], + "dense", A_ne, Cint[], Cint[], Cint[]) + + qpb_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' + qpb_import(control, data, status, n, m, + "diagonal", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + qpb_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' + qpb_import(control, data, status, n, m, + "scaled_identity", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + qpb_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' + qpb_import(control, data, status, n, m, + "identity", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + qpb_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 + + # zero + if d == 7 + st = 'Z' + qpb_import(control, data, status, n, m, + "zero", H_ne, Cint[], Cint[], Cint[], + "sparse_by_rows", A_ne, Cint[], A_col, A_ptr) + + qpb_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 + + qpb_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: QPB_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 + qpb_terminate(data, control, inform) 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] - - qpb_import( control, data, status, n, m, - "dense", H_ne, Cint[], Cint[], Cint[], - "dense", A_ne, Cint[], Cint[], Cint[] ) - - qpb_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' - - qpb_import( control, data, status, n, m, - "diagonal", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - qpb_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' - - qpb_import( control, data, status, n, m, - "scaled_identity", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - qpb_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' - - qpb_import( control, data, status, n, m, - "identity", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - qpb_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 - - # zero - if d == 7 - global st = 'Z' - - qpb_import( control, data, status, n, m, - "zero", H_ne, Cint[], Cint[], Cint[], - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - - qpb_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 - - qpb_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: QPB_solve exit status = %1i\n", st, inform.status) - end + return 0 +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 - qpb_terminate( data, control, inform ) +@testset "QPB" begin + @test test_qpb() == 0 end diff --git a/GALAHAD.jl/test/test_rqs.jl b/GALAHAD.jl/test/test_rqs.jl index e69de29bb2..bfdce1875e 100644 --- a/GALAHAD.jl/test/test_rqs.jl +++ b/GALAHAD.jl/test/test_rqs.jl @@ -0,0 +1,252 @@ +/* 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 + +using GALAHAD +using Test +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[]) + ] + 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) + ] +] + ] +] + +end + +@testset "RQS" begin + @test test_rqs() == 0 +end diff --git a/GALAHAD.jl/test/test_slls.jl b/GALAHAD.jl/test/test_slls.jl index e69de29bb2..647cc20c3e 100644 --- a/GALAHAD.jl/test/test_slls.jl +++ b/GALAHAD.jl/test/test_slls.jl @@ -0,0 +1,353 @@ +# test_slls.jl +# Simple code to test the Julia interface to SLLS + +using GALAHAD +using Test +using Printf +using Accessors + +# Custom userdata struct +struct userdata_type + scale::Float64 +end + +function test_slls() + # Apply preconditioner + function prec(n, 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 + + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{slls_control_type{Float64}}() + inform = Ref{slls_inform_type{Float64}}() + + # Set user data + userdata = userdata_type(1.0) + + # 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 # row pointer length + 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 # column pointer length + 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 = zeros(Float64, n) # variables + z = zeros(Float64, n) # dual variables + r = zeros(Float64, o) # residual + g = zeros(Float64, n) # gradient + + # Set output storage + x_stat = zeros(Cint, n) # variable status + st = "" + status = Ref{Cint}() + + # A = ( I ) and b = (i * e) + # (e^T) (n + 1) + + for i in 1:n + b[i] = i + end + b[n + 1] = n + 1 + + # A by rows + for i in 1:n + Ao_ptr[i] = i + Ao_row[i] = i + Ao_col[i] = i + 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 + Ao_val[n + i] = 1.0 + end + Ao_ptr[o + 1] = 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 + Ao_by_col_row[l] = j + 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 + 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 slls storage formats\n\n") + + for d in 1:5 + # Initialize SLLS + slls_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" + slls_import(control, data, status, n, o, + "coordinate", Ao_ne, Ao_row, Ao_col, 0, Cint[]) + + slls_solve_given_a(data, userdata, status, n, o, Ao_ne, Ao_val, b, x, z, r, g, x_stat, + prec) + end + + # sparse by rows + if d == 2 + st = "SR" + slls_import(control, data, status, n, o, + "sparse_by_rows", Ao_ne, Cint[], Ao_col, + Ao_ptr_ne, Ao_ptr) + + slls_solve_given_a(data, userdata, status, n, o, Ao_ne, Ao_val, b, x, z, r, g, x_stat, + prec) + end + + # dense by rows + if d == 3 + st = "DR" + slls_import(control, data, status, n, o, + "dense_by_rows", Ao_dense_ne, + Cint[], Cint[], 0, Cint[]) + + slls_solve_given_a(data, userdata, status, n, o, + Ao_dense_ne, Ao_dense, b, + x, z, r, g, x_stat, prec) + end + + # sparse by columns + if d == 4 + st = "SC" + slls_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) + + slls_solve_given_a(data, userdata, status, n, o, + Ao_ne, Ao_by_col_val, b, + x, z, r, g, x_stat, prec) + end + + # dense by columns + if d == 5 + st = "DC" + slls_import(control, data, status, n, o, + "dense_by_columns", Ao_dense_ne, + Cint[], Cint[], 0, Cint[]) + + slls_solve_given_a(data, userdata, status, n, o, Ao_dense_ne, Ao_by_col_dense, b, + x, z, r, g, x_stat, prec) + end + + slls_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: SLLS_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 + slls_terminate(data, control, inform) + end + + @printf("\n tests reverse-communication options\n\n") + # reverse-communication input/output + on = max(o, n) + eval_status = Ref{Cint}() + nz_v_start = Ref{Cint}() + nz_v_end = Ref{Cint}() + nz_p_end = Ref{Cint}() + nz_v = Vector(Cint, on) + nz_p = Vector(Cint, o) + mask = Vector(Cint, o) + v = Vector(Float64, on) + p = Vector(Float64, on) + + nz_p_end = 0 + + # Initialize SLLS + slls_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 + + slls_import_without_a(control, data, status, n, o) + + terminated = false + while !terminated # reverse-communication loop + slls_solve_reverse_a_prod(data, status, eval_status, n, o, b, + x, z, r, g, x_stat, v, p, + nz_v, nz_v_start, nz_v_end, + nz_p, nz_p_end) + 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:nz_v_end + i = nz_v[l] - 1 + 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 = 1 + for l in nz_v_start: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] == 0 + mask[n] = 1 + nz_p[nz_p_end] = o + nz_p_end = nz_p_end + 1 + p[n] = v[i] + else + p[n] = p[n] + v[i] + end + end + for l in 1:nz_p_end + mask[nz_p[l]] = 0 + end + elseif status[] == 6 # evaluate p = sparse A^Tv + for l in nz_v_start:nz_v_end + i = nz_v[l] - 1 + p[i] = v[i] + v[n] + 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 + slls_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("%s: SLLS_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 + slls_terminate(data, control, inform) + + return 0 +end + +@testset "SLLS" begin + @test test_slls() == 0 +end diff --git a/GALAHAD.jl/test/test_trs.jl b/GALAHAD.jl/test/test_trs.jl index f1c9130a46..48a5780a55 100644 --- a/GALAHAD.jl/test/test_trs.jl +++ b/GALAHAD.jl/test/test_trs.jl @@ -2,233 +2,239 @@ # Simple code to test the Julia interface to TRS using GALAHAD +using Test using Printf - -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = trs_control_type{Float64}() -inform = trs_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 -radius = 1.0 -c = Float64[0.0, 2.0, 0.0] - -st = ' ' -status = Ref{Cint}() -x = zeros(Float64, n) -ma = NTuple{3, Cchar}((32, 32, 32)) - -@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, " ") - end - - for storage_type = 1:4 - # Initialize TRS - trs_initialize( data, control, status ) - - # Set user-defined control options - control.f_indexing = true # fortran sparse matrix indexing - - # sparse co-ordinate storage - if d == 1 - global st = 'C' - - # import the control parameters and structural data - trs_import( control, data, status, n, - "coordinate", H_ne, H_row, H_col, Cint[] ) - - if m_is == 1 - trs_import_m( data, status, n, - "coordinate", M_ne, M_row, M_col, Cint[] ) - end - - if a_is == 1 - trs_import_a( data, status, m, - "coordinate", A_ne, A_row, A_col, Cint[] ) - end - - # solve the problem - if (a_is == 1) && (m_is == 1) - trs_solve_problem( data, status, n, - radius, f, c, H_ne, H_val, x, - M_ne, M_val, m, A_ne, A_val, Cint[] ) - elseif a_is == 1 - trs_solve_problem( data, status, n, - radius, f, c, H_ne, H_val, x, - 0, Cint[], m, A_ne, A_val, Cint[] ) - elseif m_is == 1 - trs_solve_problem( data, status, n, - radius, f, c, H_ne, H_val, x, - M_ne, M_val, 0, 0, Cint[], Cint[] ) - else - trs_solve_problem( data, status, n, - radius, f, c, H_ne, H_val, x, - 0, Cint[], 0, 0, Cint[], Cint[] ) - end - end - - # sparse by rows - if d == 2 - global st = 'R' - - # import the control parameters and structural data - trs_import( control, data, status, n, - "sparse_by_rows", H_ne, Cint[], H_col, H_ptr ) - - if m_is == 1 - trs_import_m( data, status, n, - "sparse_by_rows", M_ne, Cint[], M_col, M_ptr ) - end - - if a_is == 1 - trs_import_a( data, status, m, - "sparse_by_rows", A_ne, Cint[], A_col, A_ptr ) - end - - # solve the problem +using Accessors + +function test_trs() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{trs_control_type{Float64}}() + inform = Ref{trs_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 + radius = 1.0 + c = Float64[0.0, 2.0, 0.0] + + st = ' ' + status = Ref{Cint}() + x = zeros(Float64, n) + ma = "" + + @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) - trs_solve_problem( data, status, n, - radius, f, c, H_ne, H_val, x, - M_ne, M_val, m, A_ne, A_val, Cint[] ) + ma = "MA" elseif a_is == 1 - trs_solve_problem( data, status, n, - radius, f, c, H_ne, H_val, x, - 0, Cint[], m, A_ne, A_val, Cint[] ) + ma = "A " elseif m_is == 1 - trs_solve_problem( data, status, n, - radius, f, c, H_ne, H_val, x, - M_ne, M_val, 0, 0, Cint[], Cint[] ) + ma = "M " else - trs_solve_problem( data, status, n, - radius, f, c, H_ne, H_val, x, - 0, Cint[], 0, 0, Cint[], Cint[] ) + ma = " " end - end - - # dense - if d == 3 - global st = 'D' - - # import the control parameters and structural data - trs_import( control, data, status, n, - "dense", H_ne, Cint[], Cint[], Cint[] ) - if m_is == 1 - trs_import_m( data, status, n, - "dense", M_ne, Cint[], Cint[], Cint[] ) - end + for storage_type in 1:4 + # Initialize TRS + trs_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 + trs_import(control, data, status, n, + "coordinate", H_ne, H_row, H_col, Cint[]) + + if m_is == 1 + trs_import_m(data, status, n, + "coordinate", M_ne, M_row, M_col, Cint[]) + end + + if a_is == 1 + trs_import_a(data, status, m, + "coordinate", A_ne, A_row, A_col, Cint[]) + end + + # solve the problem + if (a_is == 1) && (m_is == 1) + trs_solve_problem(data, status, n, + radius, f, c, H_ne, H_val, x, + M_ne, M_val, m, A_ne, A_val, Cint[]) + elseif a_is == 1 + trs_solve_problem(data, status, n, + radius, f, c, H_ne, H_val, x, + 0, Cint[], m, A_ne, A_val, Cint[]) + elseif m_is == 1 + trs_solve_problem(data, status, n, + radius, f, c, H_ne, H_val, x, + M_ne, M_val, 0, 0, Cint[], Cint[]) + else + trs_solve_problem(data, status, n, + radius, f, c, H_ne, H_val, x, + 0, Cint[], 0, 0, Cint[], Cint[]) + end + end - if a_is == 1 - trs_import_a( data, status, m, - "dense", A_ne, Cint[], Cint[], Cint[] ) - end + # sparse by rows + if storage_type == 2 + st = 'R' + # import the control parameters and structural data + trs_import(control, data, status, n, + "sparse_by_rows", H_ne, Cint[], H_col, H_ptr) + + if m_is == 1 + trs_import_m(data, status, n, + "sparse_by_rows", M_ne, Cint[], M_col, M_ptr) + end + + if a_is == 1 + trs_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) + trs_solve_problem(data, status, n, + radius, f, c, H_ne, H_val, x, + M_ne, M_val, m, A_ne, A_val, Cint[]) + elseif a_is == 1 + trs_solve_problem(data, status, n, + radius, f, c, H_ne, H_val, x, + 0, Cint[], m, A_ne, A_val, Cint[]) + elseif m_is == 1 + trs_solve_problem(data, status, n, + radius, f, c, H_ne, H_val, x, + M_ne, M_val, 0, 0, Cint[], Cint[]) + else + trs_solve_problem(data, status, n, + radius, f, c, H_ne, H_val, x, + 0, Cint[], 0, 0, Cint[], Cint[]) + end + end - # solve the problem - if (a_is == 1) && (m_is == 1) - trs_solve_problem( data, status, n, - radius, f, c, H_dense_ne, H_dense, x, - M_dense_ne, M_dense, m, A_ne, A_val, Cint[] ) - elseif a_is == 1 - trs_solve_problem( data, status, n, - radius, f, c, H_dense_ne, H_dense, x, - 0, Cint[], m, A_ne, A_val, Cint[] ) - elseif m_is == 1 - trs_solve_problem( data, status, n, - radius, f, c, H_dense_ne, H_dense, x, - M_dense_ne, M_dense, 0, 0, Cint[], Cint[] ) - else - trs_solve_problem( data, status, n, - radius, f, c, H_dense_ne, H_dense, x, - 0, Cint[], 0, 0, Cint[], Cint[] ) - end - end + # dense + if storage_type == 3 + st = 'D' + # import the control parameters and structural data + trs_import(control, data, status, n, + "dense", H_ne, Cint[], Cint[], Cint[]) + + if m_is == 1 + trs_import_m(data, status, n, + "dense", M_ne, Cint[], Cint[], Cint[]) + end + + if a_is == 1 + trs_import_a(data, status, m, + "dense", A_ne, Cint[], Cint[], Cint[]) + end + + # solve the problem + if (a_is == 1) && (m_is == 1) + trs_solve_problem(data, status, n, + radius, f, c, H_dense_ne, H_dense, x, + M_dense_ne, M_dense, m, A_ne, A_val, + Cint[]) + elseif a_is == 1 + trs_solve_problem(data, status, n, + radius, f, c, H_dense_ne, H_dense, x, + 0, Cint[], m, A_ne, A_val, Cint[]) + elseif m_is == 1 + trs_solve_problem(data, status, n, + radius, f, c, H_dense_ne, H_dense, x, + M_dense_ne, M_dense, 0, 0, Cint[], Cint[]) + else + trs_solve_problem(data, status, n, + radius, f, c, H_dense_ne, H_dense, x, + 0, Cint[], 0, 0, Cint[], Cint[]) + end + end - # diagonal - if d == 4 - global st = 'L' + # diagonal + if storage_type == 4 + st = 'L' + # import the control parameters and structural data + trs_import(control, data, status, n, + "diagonal", H_ne, Cint[], Cint[], Cint[]) + + if m_is == 1 + trs_import_m(data, status, n, + "diagonal", M_ne, Cint[], Cint[], Cint[]) + end + + if a_is == 1 + trs_import_a(data, status, m, + "dense", A_ne, Cint[], Cint[], Cint[]) + end + + # solve the problem + if (a_is == 1) && (m_is == 1) + trs_solve_problem(data, status, n, + radius, f, c, n, H_diag, x, + n, M_diag, m, A_ne, A_val, Cint[]) + elseif a_is == 1 + trs_solve_problem(data, status, n, + radius, f, c, n, H_diag, x, + 0, Cint[], m, A_ne, A_val, Cint[]) + elseif m_is == 1 + trs_solve_problem(data, status, n, + radius, f, c, n, H_diag, x, + n, M_diag, 0, 0, Cint[], Cint[]) + else + trs_solve_problem(data, status, n, + radius, f, c, n, H_diag, x, + 0, Cint[], 0, 0, Cint[], Cint[]) + end + end - # import the control parameters and structural data - trs_import( control, data, status, n, - "diagonal", H_ne, Cint[], Cint[], Cint[] ) + trs_information(data, inform, status) - if m_is == 1 - trs_import_m( data, status, n, - "diagonal", M_ne, Cint[], Cint[], Cint[] ) - end + @printf("format %c%s: TRS_solve_problem exit status = %1i, f = %.2f\n", st, ma, + inform[].status, inform[].obj) - if a_is == 1 - trs_import_a( data, status, m, - "dense", A_ne, Cint[], Cint[], Cint[] ) - end + # @printf("x: ") + # for i = 1:n+m + # @printf("%f ", x[i]) + # end - # solve the problem - if (a_is == 1) && (m_is == 1) - trs_solve_problem( data, status, n, - radius, f, c, n, H_diag, x, - n, M_diag, m, A_ne, A_val, Cint[] ) - elseif a_is == 1 - trs_solve_problem( data, status, n, - radius, f, c, n, H_diag, x, - 0, Cint[], m, A_ne, A_val, Cint[] ) - elseif m_is == 1 - trs_solve_problem( data, status, n, - radius, f, c, n, H_diag, x, - n, M_diag, 0, 0, Cint[], Cint[] ) - else - trs_solve_problem( data, status, n, - radius, f, c, n, H_diag, x, - 0, Cint[], 0, 0, Cint[], Cint[] ) + # Delete internal workspace + trs_terminate(data, control, inform) end end + end - trs_information( data, inform, status ) - - @printf("format %c%s: TRS_solve_problem exit status = %1i, f = %.2f\n", st, ma, inform.status, inform.obj ) - # @printf("x: ") - # for i = 1:n+m - # @printf("%f ", x[i]) - # end + return 0 +end - # Delete internal workspace - trs_terminate( data, control, inform ) - end +@testset "TRS" begin + @test test_trs() == 0 end diff --git a/GALAHAD.jl/test/test_tru.jl b/GALAHAD.jl/test/test_tru.jl index e69de29bb2..45a4896ea8 100644 --- a/GALAHAD.jl/test/test_tru.jl +++ b/GALAHAD.jl/test/test_tru.jl @@ -0,0 +1,404 @@ +# test_tru.jl +# Simple code to test the Julia interface to TRU + +using GALAHAD +using Test +using Printf +using Accessors + +# Custom userdata struct +struct userdata_type + p::Float64 +end + +# Objective function +function fun(n, x::Vector{Float64}, f::Ref{Float64}, userdata::userdata_type) + p = userdata.p + f[] = (x[1] + x[3] + p)^2 + (x[2] + x[3])^2 + cos(x[1]) + return 0 +end + +# Gradient of the objective +function grad(n, x::Vector{Float64}, g::Vector{Float64}, userdata::userdata_type) + p = userdata.p + g[1] = 2.0 * (x[1] + x[3] + p) - sin(x[1]) + g[2] = 2.0 * (x[2] + x[3]) + g[3] = 2.0 * (x[1] + x[3] + p) + 2.0 * (x[2] + x[3]) + return 0 +end + +# Hessian of the objective +function hess(n, ne, x::Vector{Float64}, hval::Vector{Float64}, userdata::userdata_type) + hval[1] = 2.0 - cos(x[1]) + hval[2] = 2.0 + hval[3] = 2.0 + hval[4] = 2.0 + hval[5] = 4.0 + return 0 +end + +# Dense Hessian +function hess_dense(n, ne, x::Vector{Float64}, hval::Vector{Float64}, + userdata::userdata_type) + hval[1] = 2.0 - cos(x[1]) + hval[2] = 0.0 + hval[3] = 2.0 + hval[4] = 2.0 + hval[5] = 2.0 + hval[6] = 4.0 + return 0 +end + +# Hessian-vector product +function hessprod(n, x::Vector{Float64}, u::Vector{Float64}, v::Vector{Float64}, + got_h::Bool, userdata::userdata_type) + u[1] = u[1] + 2.0 * (v[1] + v[3]) - cos(x[1]) * v[1] + u[2] = u[2] + 2.0 * (v[2] + v[3]) + u[3] = u[3] + 2.0 * (v[1] + v[2] + 2.0 * v[3]) + return 0 +end + +# Apply preconditioner +function prec(n, x::Vector{Float64}, u::Vector{Float64}, v::Vector{Float64}, + userdata::userdata_type) + u[1] = 0.5 * v[1] + u[2] = 0.5 * v[2] + u[3] = 0.25 * v[3] + return 0 +end + +# Objective function +function fun_diag(n, x::Vector{Float64}, f::Ref{Float64}, userdata::userdata_type) + p = userdata.p + f[] = (x[3] + p)^2 + x[2]^2 + cos(x[1]) + return 0 +end + +# Gradient of the objective +function grad_diag(n, x::Vector{Float64}, g::Vector{Float64}, userdata::userdata_type) + p = userdata.p + g[1] = -sin(x[1]) + g[2] = 2.0 * x[2] + g[3] = 2.0 * (x[3] + p) + return 0 +end + +# Hessian of the objective +function hess_diag(n, ne, x::Vector{Float64}, hval::Vector{Float64}, + userdata::userdata_type) + hval[1] = -cos(x[1]) + hval[2] = 2.0 + hval[3] = 2.0 + return 0 +end + +# Hessian-vector product +function hessprod_diag(n, x::Vector{Float64}, u::Vector{Float64}, v::Vector{Float64}, + got_h::Bool, userdata::userdata_type) + u[1] = u[1] + -cos(x[1]) * v[1] + u[2] = u[2] + 2.0 * v[2] + u[3] = u[3] + 2.0 * v[3] + return 0 +end + +function test_tru() + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{tru_control_type{Float64}}() + inform = Ref{tru_inform_type{Float64}}() + + # Set user data + userdata = userdata_type(4.0) + + # Set problem data + n = 3 # dimension + ne = 5 # Hesssian elements + 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 TRU + tru_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + # @reset control[].print_level = Cint(1) + + # Start from 1.5 + x = Float64[1.5, 1.5, 1.5] + + # sparse co-ordinate storage + if d == 1 + st = 'C' + tru_import(control, data, status, n, "coordinate", + ne, H_row, H_col, Cint[]) + + tru_solve_with_mat(data, userdata, status, + n, x, g, ne, fun, grad, hess, prec) + end + + # sparse by rows + if d == 2 + st = 'R' + tru_import(control, data, status, n, "sparse_by_rows", + ne, Cint[], H_col, H_ptr) + + tru_solve_with_mat(data, userdata, status, + n, x, g, ne, fun, grad, hess, prec) + end + + # dense + if d == 3 + st = 'D' + tru_import(control, data, status, n, "dense", + ne, Cint[], Cint[], Cint[]) + + tru_solve_with_mat(data, userdata, status, + n, x, g, ne, fun, grad, hess_dense, prec) + end + + # diagonal + if d == 4 + st = 'I' + tru_import(control, data, status, n, "diagonal", + ne, Cint[], Cint[], Cint[]) + + tru_solve_with_mat(data, userdata, status, n, x, g, + ne, fun_diag, grad_diag, hess_diag, prec) + end + + # access by products + if d == 5 + st = 'P' + tru_import(control, data, status, n, "absent", + ne, Cint[], Cint[], Cint[]) + + tru_solve_without_mat(data, userdata, status, + n, x, g, fun, grad, hessprod, prec) + end + + tru_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: TRU_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 + tru_terminate(data, control, inform) + end + + @printf("\n tests reverse-communication options\n\n") + # reverse-communication input/output + eval_status = 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) + H_val = zeros(Float64, ne) + H_dense = zeros(Float64, div(n * (n + 1), 2)) + H_diag = zeros(Float64, n) + + for d in 1:5 + # Initialize TRU + tru_initialize(data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + # @reset control[].print_level = Cint(1) + # @reset control[].maxit = Cint(1) + + # Start from 1.5 + x = Float64[1.5, 1.5, 1.5] + + # sparse co-ordinate storage + if d == 1 + st = 'C' + tru_import(control, data, status, n, "coordinate", + ne, H_row, H_col, Cint[]) + + terminated = false + while !terminated # reverse-communication loop + tru_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[] == 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 + end + + # sparse by rows + if d == 2 + st = 'R' + tru_import(control, data, status, n, "sparse_by_rows", ne, + Cint[], H_col, H_ptr) + + terminated = false + while !terminated # reverse-communication loop + tru_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[] == 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 + end + + # dense + if d == 3 + st = 'D' + tru_import(control, data, status, n, "dense", + ne, Cint[], Cint[], Cint[]) + + terminated = false + while !terminated # reverse-communication loop + tru_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[] == 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 + end + + # diagonal + if d == 4 + st = 'I' + tru_import(control, data, status, n, "diagonal", + ne, Cint[], Cint[], Cint[]) + + terminated = false + while !terminated # reverse-communication loop + tru_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[] == 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 + end + + # access by products + if d == 5 + st = 'P' + tru_import(control, data, status, n, "absent", + ne, Cint[], Cint[], Cint[]) + + terminated = false + while !terminated # reverse-communication loop + tru_solve_reverse_without_mat(data, status, eval_status, + n, x, f, g, 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[] == 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) + else + @printf(" the value %1i of status should not occur\n", status) + end + end + end + + tru_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: TRU_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 + tru_terminate(data, control, inform) + end + + return 0 +end + +@testset "TRU" begin + @test test_tru() == 0 +end diff --git a/GALAHAD.jl/test/test_uls.jl b/GALAHAD.jl/test/test_uls.jl index a262d4d58c..112e22811d 100644 --- a/GALAHAD.jl/test/test_uls.jl +++ b/GALAHAD.jl/test/test_uls.jl @@ -2,152 +2,183 @@ # Simple code to test the Julia interface to ULS using GALAHAD +using Test using Printf +using Accessors + +function test_uls() + maxabsarray(a) = maximum(abs.(a)) + + # Derived types + data = Ref{Ptr{Cvoid}}() + control = Ref{uls_control_type{Float64}}() + inform = Ref{uls_inform_type{Float64}}() + + # Set problem data + m = 5 # column dimension of A + n = 5 # column dimension of A + ne = 7 # number of entries of A + dense_ne = 25 # number of elements of A as a dense matrix + row = Cint[1, 2, 2, 3, 3, 4, 5] # row indices + col = Cint[1, 1, 5, 2, 3, 3, 4] # column indices + ptr = Cint[1, 2, 4, 6, 7, 8] # pointers to indices + val = Float64[2.0, 3.0, 6.0, 4.0, 1.0, 5.0, 1.0] # values + dense = Float64[2.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 6.0, 0.0, 4.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0] + rhs = Float64[2.0, 33.0, 11.0, 15.0, 4.0] + rhst = Float64[8.0, 12.0, 23.0, 5.0, 12.0] + sol = Float64[1.0, 2.0, 3.0, 4.0, 5.0] + status = Ref{Cint}() + x = zeros(Float64, n) + error = zeros(Float64, n) + good_x = eps(Float64)^(1 / 3) + + @printf(" Fortran sparse matrix indexing\n\n") + @printf(" basic tests of storage formats\n\n") + @printf(" storage RHS refine RHST refine\n") + + for d in 1:3 + # Initialize ULS - use the gls solver + uls_initialize("getr", data, control, status) + + # Set user-defined control options + @reset control[].f_indexing = true # Fortran sparse matrix indexing + + # sparse co-ordinate storage + if d == 1 + @printf(" coordinate ") + uls_factorize_matrix(control, data, status, m, n, + "coordinate", ne, val, row, col, Cint[]) + end -# Function maxabsarray -maxabsarray(a) = maximum(abs.(a)) - -# Derived types -data = [Ptr{Ptr{Cvoid}}()] -control = uls_control_type{Float64}() -inform = uls_inform_type{Float64}() - -# Set problem data -m = 5 # column dimension of A -n = 5 # column dimension of A -ne = 7 # number of entries of A -dense_ne = 25 # number of elements of A as a dense matrix -row = Cint[1, 2, 2, 3, 3, 4, 5] # row indices -col = Cint[1, 1, 5, 2, 3, 3, 4] # column indices -ptr = Cint[1, 2, 4, 6, 7, 8] # pointers to indices -val = Float64[2.0, 3.0, 6.0, 4.0, 1.0, 5.0, 1.0] # values -dense = Float64[2.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 6.0, - 0.0, 4.0, 1.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 1.0, 0.0] -rhs = Float64[2.0, 33.0, 11.0, 15.0, 4.0] -rhst = Float64[8.0, 12.0, 23.0, 5.0, 12.0] -sol = Float64[1.0, 2.0, 3.0, 4.0, 5.0] -x = zeros(Float64, n) -error = zeros(Float64, n) - -good_x = eps(Float64)^(1/3) - -@printf(" Fortran sparse matrix indexing\n\n") -@printf(" basic tests of storage formats\n\n") -@printf(" storage RHS refine RHST refine\n") - -for d = 1:3 - # Initialize ULS - use the gls solver - uls_initialize( "getr", data, control, status ) - - # Set user-defined control options - control.f_indexing = true # Fortran sparse matrix indexing - - # sparse co-ordinate storage - if d == 1 - @printf(" coordinate ") - uls_factorize_matrix( control, data, status, m, n, - "coordinate", ne, val, row, col, Cint[] ) - end + # sparse by rows + if d == 2 + @printf(" sparse by rows ") + uls_factorize_matrix(control, data, status, m, n, + "sparse_by_rows", ne, val, Cint[], col, ptr) + end - # sparse by rows - if d == 2 - @printf(" sparse by rows ") - uls_factorize_matrix( control, data, status, m, n, - "sparse_by_rows", ne, val, Cint[], col, ptr ) - end + # dense + if d == 3 + @printf(" dense ") + uls_factorize_matrix(control, data, status, m, n, + "dense", dense_ne, dense, Cint[], Cint[], Cint[]) + end - # dense - if d == 3 - @printf(" dense ") - uls_factorize_matrix( control, data, status, m, n, - "dense", dense_ne, dense, Cint[], Cint[], Cint[] ) - end + # Set right-hand side and solve the system A x = b + for i in 1:n + x[i] = rhs[i] + end - # Set right-hand side and solve the system Ax = b - x .= rhs - trans = false - uls_solve_system( data, status, m, n, x, trans ) - uls_information( data, inform, status ) - - if inform.status == 0 - error .= x .- sol - norm_residual = maxabsarray(error) - if norm_residual < good_x - @printf(" ok ") + trans = false + uls_solve_system(data, status, m, n, x, trans) + uls_information(data, inform, status) + + if inform[].status == 0 + for i in 1:n + error[i] = x[i] - sol[i] + end + norm_residual = maxabsarray(error) + if norm_residual < good_x + @printf(" ok ") + else + @printf(" fail ") + end else - @printf(" fail ") + @printf(" ULS_solve exit status = %1i\n", inform[].status) + end + + # @printf("sol: ") + # for i = 1:n + # @printf("%f ", x[i]) + # end + + # resolve, this time using iterative refinement + @reset control[].max_iterative_refinements = Cint(1) + uls_reset_control(control, data, status) + + for i in 1:n + x[i] = rhs[i] end - else - @printf(" ULS_solve exit status = %1i\n", inform.status) - end - # @printf("sol: ") - # for i = 1:n - # @printf("%f ", x[i]) - # end - - # resolve, this time using iterative refinement - control.max_iterative_refinements = 1 - uls_reset_control( control, data, status ) - x .= rhs - uls_solve_system( data, status, m, n, x, trans ) - uls_information( data, inform, status ) - - if inform.status == 0 - error .= x .- sol - norm_residual = maxabsarray(error) - if norm_residual < good_x - @printf("ok ") + uls_solve_system(data, status, m, n, x, trans) + uls_information(data, inform, status) + + if inform[].status == 0 + for i in 1:n + error[i] = x[i] - sol[i] + end + norm_residual = maxabsarray(error) + if norm_residual < good_x + @printf("ok ") + else + @printf(" fail ") + end else - @printf(" fail ") + @printf(" ULS_solve exit status = %1i\n", inform[].status) + end + + # Set right-hand side and solve the system A^T x = b + for i in 1:n + x[i] = rhst[i] end - else - @printf(" ULS_solve exit status = %1i\n", inform.status) - end - # Set right-hand side and solve the system Aᵀx = b - x .= rhst - trans = true - uls_solve_system( data, status, m, n, x, trans ) - uls_information( data, inform, status ) - - if inform.status == 0 - error .= x .- sol - norm_residual = maxabsarray(error) - if norm_residual < good_x - @printf(" ok ") + trans = true + uls_solve_system(data, status, m, n, x, trans) + uls_information(data, inform, status) + + if inform[].status == 0 + for i in 1:n + error[i] = x[i] - sol[i] + end + norm_residual = maxabsarray(error) + if norm_residual < good_x + @printf(" ok ") + else + @printf(" fail ") + end else - @printf(" fail ") + @printf(" ULS_solve exit status = %1i\n", inform[].status) end - else - @printf(" ULS_solve exit status = %1i\n", inform.status) - end - # @printf("sol: ") - # for i = 1:n - # @printf("%f ", x[i]) - # end - - # resolve, this time using iterative refinement - control.max_iterative_refinements = 1 - uls_reset_control( control, data, status ) - x .= rhst - uls_solve_system( data, status, m, n, x, trans ) - uls_information( data, inform, status ) - - if inform.status == 0 - error .= x .- sol - norm_residual = maxabsarray(error) - if norm_residual < good_x - @printf("ok ") + # @printf("sol: ") + # for i = 1:n + # @printf("%f ", x[i]) + # end + + # resolve, this time using iterative refinement + @reset control[].max_iterative_refinements = Cint(1) + + uls_reset_control(control, data, status) + for i in 1:n + x[i] = rhst[i] + end + + uls_solve_system(data, status, m, n, x, trans) + uls_information(data, inform, status) + + if inform[].status == 0 + for i in 1:n + error[i] = x[i] - sol[i] + end + norm_residual = maxabsarray(error) + if norm_residual < good_x + @printf("ok ") + else + @printf(" fail ") + end else - @printf(" fail ") + @printf(" ULS_solve exit status = %1i\n", inform[].status) end - else - @printf(" ULS_solve exit status = %1i\n", inform.status) + + # Delete internal workspace + uls_terminate(data, control, inform) + @printf("\n") end - # Delete internal workspace - uls_terminate( data, control, inform ) + return 0 +end + +@testset "ULS" begin + @test test_uls() == 0 end