Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update PRIMA.jl for the updated artifact #1

Merged
merged 1 commit into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ TypeUtils = "c3b1956e-8857-4d84-9b79-890df85b1e67"

[compat]
julia = "1.6"
PRIMA_jll = "0.7.0"
PRIMA_jll = "0.7.1"
TypeUtils = "0.3"

[extras]
Expand Down
7 changes: 7 additions & 0 deletions gen/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[deps]
Clang = "40e3b903-d033-50b4-a0cc-940c62c95e31"
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
PRIMA_jll = "eead6e0c-2d5b-5641-a95c-b722de96d551"

[compat]
julia = "1.6"
9 changes: 9 additions & 0 deletions gen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Wrapping headers

This directory contains a script that can be used to automatically generate wrappers from the C headers provided by PRIMA.
This is done using Clang.jl.

# Usage

Either run `julia wrapper.jl` directly, or include it and call the `main()` function.
Be sure to activate the project environment in this folder (`julia --project`), which will install `Clang.jl` and `JuliaFormatter.jl`.
13 changes: 13 additions & 0 deletions gen/prima.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[general]
use_julia_native_enum_type = true
print_using_CEnum = false
library_name = "libprimac"

[codegen]
use_julia_bool = true
always_NUL_terminated_string = true
use_ccall_macro = true

[codegen.macro]
macro_mode = "basic"
add_comment_for_skipped_macro = true
30 changes: 30 additions & 0 deletions gen/wrapper.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Script to parse PRIMA headers and generate Julia wrappers.
using PRIMA_jll
using Clang
using Clang.Generators
using JuliaFormatter

function main()

cd(@__DIR__)
include = joinpath(PRIMA_jll.artifact_dir, "include", "prima")
headers = [joinpath(include, "prima.h")]

options = load_options(joinpath(@__DIR__, "prima.toml"))
options["general"]["output_file_path"] = joinpath("..", "src", "wrappers.jl")

args = get_default_args()
push!(args, "-I$include")

ctx = create_context(headers, args, options)
build!(ctx)

path = options["general"]["output_file_path"]
format_file(path, YASStyle())
return nothing
end

# If we want to use the file as a script with `julia wrapper.jl`
if abspath(PROGRAM_FILE) == @__FILE__
main()
end
125 changes: 14 additions & 111 deletions src/PRIMA.jl
Original file line number Diff line number Diff line change
@@ -1,50 +1,24 @@
module PRIMA

using PRIMA_jll
const libprimac = PRIMA_jll.libprimac
include("wrappers.jl")

export bobyqa, cobyla, lincoa, newuoa, uobyqa

using TypeUtils
using PRIMA_jll
const libprimac = PRIMA_jll.libprimac

#------------------------------------------------------------------------------
# PUBLIC INTERFACE

# Verbosity level
@enum Message::Cint begin
MSG_NONE = 0 # No messages
MSG_EXIT = 1 # Exit reasons
MSG_RHO = 2 # Rho changes
MSG_FEVL = 3 # The object/constraint functions get evaluated
end

# Possible return values
@enum Status::Cint begin
SMALL_TR_RADIUS = 0
FTARGET_ACHIEVED = 1
TRSUBP_FAILED = 2
MAXFUN_REACHED = 3
MAXTR_REACHED = 20
NAN_INF_X = -1
NAN_INF_F = -2
NAN_INF_MODEL = -3
NO_SPACE_BETWEEN_BOUNDS = 6
DAMAGING_ROUNDING = 7
ZERO_LINEAR_CONSTRAINT = 8
INVALID_INPUT = 100
ASSERTION_FAILS = 101
VALIDATION_FAILS = 102
MEMORY_ALLOCATION_FAILS = 103
end

"""
PRIMA.reason(rc) -> str

yields a textual message explaining `rc`, the code returned by one of the PRIMA
optimizers.

"""
reason(status::Union{Integer,Status}) =
unsafe_string(@ccall libprimac.prima_get_rc_string(Integer(status)::Cint)::Cstring)
reason(status::Union{Integer,Status}) = unsafe_string(prima_get_rc_string(status))

# The high level wrappers.
for func in (:bobyqa, :newuoa, :uobyqa, :lincoa, :cobyla)
Expand Down Expand Up @@ -107,20 +81,7 @@ function bobyqa!(f, x::DenseVector{Cdouble};
fp = _push_wrapper(fw) # pointer to C-callable function
try
# Call low-level optimizer.
rc = @ccall libprimac.prima_bobyqa(
fp ::Ptr{Cvoid}, # C-type: prima_obj
n ::Cint,
x ::Ptr{Cdouble}, # n elements
fx ::Ref{Cdouble},
xl ::Ptr{Cdouble}, # const, n elements
xu ::Ptr{Cdouble}, # const, n elements
nf ::Ref{Cint},
rhobeg ::Cdouble,
rhoend ::Cdouble,
ftarget ::Cdouble,
maxfun ::Cint, # maxfun
npt ::Cint,
Integer(iprint) ::Cint)::Cint
rc = prima_bobyqa(calfun, n, x, f, xl, xu, nf, rhobeg, rhoend, ftarget, maxfun, npt, iprint)
return (fx[], Int(nf[]), rc)
finally
_pop_wrapper(fw)
Expand Down Expand Up @@ -159,18 +120,7 @@ function newuoa!(f, x::DenseVector{Cdouble};
fp = _push_wrapper(fw) # pointer to C-callable function
try
# Call low-level optimizer.
rc = @ccall libprimac.prima_newuoa(
fp ::Ptr{Cvoid}, # C-type: prima_obj
n ::Cint,
x ::Ptr{Cdouble}, # n elements
fx ::Ref{Cdouble},
nf ::Ref{Cint},
rhobeg ::Cdouble,
rhoend ::Cdouble,
ftarget ::Cdouble,
maxfun ::Cint,
npt ::Cint,
Integer(iprint) ::Cint)::Cint
rc = prima_newuoa(calfun, n, x, f, nf, rhobeg, rhoend, ftarget, maxfun, npt, iprint)
return (fx[], Int(nf[]), rc)
finally
_pop_wrapper(fw)
Expand Down Expand Up @@ -207,17 +157,7 @@ function uobyqa!(f, x::DenseVector{Cdouble};
fp = _push_wrapper(fw) # pointer to C-callable function
try
# Call low-level optimizer.
rc = @ccall libprimac.prima_uobyqa(
fp ::Ptr{Cvoid}, # C-type: prima_obj
n ::Cint,
x ::Ptr{Cdouble}, # n elements
fx ::Ref{Cdouble},
nf ::Ref{Cint},
rhobeg ::Cdouble,
rhoend ::Cdouble,
ftarget ::Cdouble,
maxfun ::Cint,
Integer(iprint) ::Cint)::Cint
rc = prima_uobyqa(calfun, n, x, f, nf, rhobeg, rhoend, ftarget, maxfun, iprint)
return (fx[], Int(nf[]), rc)
finally
_pop_wrapper(fw)
Expand Down Expand Up @@ -255,28 +195,9 @@ function cobyla!(f, x::DenseVector{Cdouble};

try
# Call low-level optimizer.
rc = GC.@preserve nlconstr ineqconstr eqconstr @ccall libprimac.prima_cobyla(
m_nlcon ::Cint,
fp ::Ptr{Cvoid}, # C-type: prima_objcon
n ::Cint,
x ::Ptr{Cdouble}, # n elements
fx ::Ref{Cdouble},
cstrv ::Ref{Cdouble},
nlcon_ptr ::Ptr{Cdouble}, # m_nlcon elements
m_ineq ::Cint,
A_ineq ::Ptr{Cdouble}, # const, m_ineq*n elements
b_ineq ::Ptr{Cdouble}, # const, m_ineq elements
m_eq ::Cint,
A_eq ::Ptr{Cdouble}, # const, m_eq*n elements
b_eq ::Ptr{Cdouble}, # const, m_eq elements
xl ::Ptr{Cdouble}, # const, n elements
xu ::Ptr{Cdouble}, # const, n elements
nf ::Ref{Cint},
rhobeg ::Cdouble,
rhoend ::Cdouble,
ftarget ::Cdouble,
maxfun ::Cint,
Integer(iprint) ::Cint)::Cint
rc = GC.@preserve nlconstr ineqconstr eqconstr prima_cobyla(m_nlcon, calcfc,
n, x, f, cstrv, nlconstr, m_ineq, Aineq, bineq, m_eq, Aeq, beq, xl, xu,
nf, rhobeg, rhoend, ftarget, maxfun, iprint)
return (fx[], Int(nf[]), rc, cstrv[])
finally
_pop_wrapper(fw)
Expand Down Expand Up @@ -311,27 +232,9 @@ function lincoa!(f, x::DenseVector{Cdouble};
fp = _push_wrapper(fw) # pointer to C-callable function
try
# Call low-level optimizer.
rc = GC.@preserve ineqconstr eqconstr @ccall libprimac.prima_lincoa(
fp ::Ptr{Cvoid}, # C-type: prima_objcon
n ::Cint,
x ::Ptr{Cdouble}, # n elements
fx ::Ref{Cdouble},
cstrv ::Ref{Cdouble},
m_ineq ::Cint,
A_ineq ::Ptr{Cdouble}, # const, m_ineq*n elements
b_ineq ::Ptr{Cdouble}, # const, m_ineq elements
m_eq ::Cint,
A_eq ::Ptr{Cdouble}, # const, m_eq*n elements
b_eq ::Ptr{Cdouble}, # const, m_eq elements
xl ::Ptr{Cdouble}, # const, n elements
xu ::Ptr{Cdouble}, # const, n elements
nf ::Ref{Cint},
rhobeg ::Cdouble,
rhoend ::Cdouble,
ftarget ::Cdouble,
maxfun ::Cint,
npt ::Cint,
Integer(iprint) ::Cint)::Cint
rc = GC.@preserve ineqconstr eqconstr prima_lincoa(calfun, n, x, f,
cstrv, m_ineq, Aineq, bineq, m_eq, Aeq, beq, xl, xu, nf,
rhobeg, rhoend, ftarget, maxfun, npt, iprint)
return (fx[], Int(nf[]), rc, cstrv[])
finally
_pop_wrapper(fw)
Expand Down
73 changes: 73 additions & 0 deletions src/wrappers.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
@enum prima_message::UInt32 begin
PRIMA_MSG_NONE = 0
PRIMA_MSG_EXIT = 1
PRIMA_MSG_RHO = 2
PRIMA_MSG_FEVL = 3
end

@enum prima_rc::Int32 begin
PRIMA_SMALL_TR_RADIUS = 0
PRIMA_FTARGET_ACHIEVED = 1
PRIMA_TRSUBP_FAILED = 2
PRIMA_MAXFUN_REACHED = 3
PRIMA_MAXTR_REACHED = 20
PRIMA_NAN_INF_X = -1
PRIMA_NAN_INF_F = -2
PRIMA_NAN_INF_MODEL = -3
PRIMA_NO_SPACE_BETWEEN_BOUNDS = 6
PRIMA_DAMAGING_ROUNDING = 7
PRIMA_ZERO_LINEAR_CONSTRAINT = 8
PRIMA_INVALID_INPUT = 100
PRIMA_ASSERTION_FAILS = 101
PRIMA_VALIDATION_FAILS = 102
PRIMA_MEMORY_ALLOCATION_FAILS = 103
end

function prima_get_rc_string(rc)
@ccall libprimac.prima_get_rc_string(rc::Cint)::Cstring
end

function prima_bobyqa(calfun, n, x, f, xl, xu, nf, rhobeg, rhoend, ftarget, maxfun, npt,
iprint)
@ccall libprimac.prima_bobyqa(calfun::Ptr{Cvoid}, n::Cint, x::Ptr{Cdouble},
f::Ptr{Cdouble}, xl::Ptr{Cdouble}, xu::Ptr{Cdouble},
nf::Ptr{Cint}, rhobeg::Cdouble, rhoend::Cdouble,
ftarget::Cdouble, maxfun::Cint, npt::Cint,
iprint::Cint)::Cint
end

function prima_newuoa(calfun, n, x, f, nf, rhobeg, rhoend, ftarget, maxfun, npt, iprint)
@ccall libprimac.prima_newuoa(calfun::Ptr{Cvoid}, n::Cint, x::Ptr{Cdouble},
f::Ptr{Cdouble}, nf::Ptr{Cint}, rhobeg::Cdouble,
rhoend::Cdouble, ftarget::Cdouble, maxfun::Cint,
npt::Cint, iprint::Cint)::Cint
end

function prima_uobyqa(calfun, n, x, f, nf, rhobeg, rhoend, ftarget, maxfun, iprint)
@ccall libprimac.prima_uobyqa(calfun::Ptr{Cvoid}, n::Cint, x::Ptr{Cdouble},
f::Ptr{Cdouble}, nf::Ptr{Cint}, rhobeg::Cdouble,
rhoend::Cdouble, ftarget::Cdouble, maxfun::Cint,
iprint::Cint)::Cint
end

function prima_cobyla(m_nlcon, calcfc, n, x, f, cstrv, nlconstr, m_ineq, Aineq, bineq, m_eq,
Aeq, beq, xl, xu, nf, rhobeg, rhoend, ftarget, maxfun, iprint)
@ccall libprimac.prima_cobyla(m_nlcon::Cint, calcfc::Ptr{Cvoid}, n::Cint,
x::Ptr{Cdouble}, f::Ptr{Cdouble}, cstrv::Ptr{Cdouble},
nlconstr::Ptr{Cdouble}, m_ineq::Cint, Aineq::Ptr{Cdouble},
bineq::Ptr{Cdouble}, m_eq::Cint, Aeq::Ptr{Cdouble},
beq::Ptr{Cdouble}, xl::Ptr{Cdouble}, xu::Ptr{Cdouble},
nf::Ptr{Cint}, rhobeg::Cdouble, rhoend::Cdouble,
ftarget::Cdouble, maxfun::Cint, iprint::Cint)::Cint
end

function prima_lincoa(calfun, n, x, f, cstrv, m_ineq, Aineq, bineq, m_eq, Aeq, beq, xl, xu,
nf, rhobeg, rhoend, ftarget, maxfun, npt, iprint)
@ccall libprimac.prima_lincoa(calfun::Ptr{Cvoid}, n::Cint, x::Ptr{Cdouble},
f::Ptr{Cdouble}, cstrv::Ptr{Cdouble}, m_ineq::Cint,
Aineq::Ptr{Cdouble}, bineq::Ptr{Cdouble}, m_eq::Cint,
Aeq::Ptr{Cdouble}, beq::Ptr{Cdouble}, xl::Ptr{Cdouble},
xu::Ptr{Cdouble}, nf::Ptr{Cint}, rhobeg::Cdouble,
rhoend::Cdouble, ftarget::Cdouble, maxfun::Cint,
npt::Cint, iprint::Cint)::Cint
end