libprima / prima

PRIMA is a package for solving general nonlinear optimization problems without using derivatives. It provides the reference implementation for Powell's derivative-free optimization methods, i.e., COBYLA, UOBYQA, NEWUOA, BOBYQA, and LINCOA. PRIMA means Reference Implementation for Powell's methods with Modernization and Amelioration, P for Powell.
http://libprima.net
BSD 3-Clause "New" or "Revised" License
292 stars 36 forks source link

Add Julia wrappers #62

Closed amontoison closed 9 months ago

amontoison commented 10 months ago

@zaikunzhang

I have an issue to generate the wrappers of the 4 main functions with Clang.jl but it should be not too hard to fix. I started a discussion here.

github-actions[bot] commented 10 months ago

@check-spelling-bot Report

:red_circle: Please review

See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.

Unrecognized words (8)

ccall CEnum Cint Cvoid eead jll julia libprimac

To accept :heavy_check_mark: these unrecognized words as correct, run the following commands ... in a clone of the [git@github.com:amontoison/prima.git](https://github.com/amontoison/prima.git) repository on the `julia` branch ([:information_source: how do I use this?]( https://github.com/check-spelling/check-spelling/wiki/Accepting-Suggestions)): ``` sh curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/main/apply.pl' | perl - 'https://github.com/libprima/prima/actions/runs/6193859414/attempts/1' ```
Pattern suggestions :scissors: (1) You could add these patterns to .github/actions/spelling/patterns.txt: ``` # Automatically suggested patterns # hit-count: 1 file-count: 1 # uuid: \b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b ```
Warnings (1) See the [:open_file_folder: files](62/files/) view, the [:scroll:action log](https://github.com/libprima/prima/actions/runs/6193859414/job/16816003219#step:2:1) or [:angel: SARIF report](https://github.com/libprima/prima/security/code-scanning?query=is:open+pr:62) for details. [:information_source: Warnings](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions) | Count -|- [:information_source: candidate-pattern](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions#candidate-pattern) | 1 See [:information_source: Event descriptions](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions) for more information.
If the flagged items are :exploding_head: false positives If items relate to a ... * binary file (or some other file you wouldn't want to check at all). Please add a file path to the `excludes.txt` file matching the containing file. File paths are Perl 5 Regular Expressions - you can [test]( https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files. `^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md]( ../tree/HEAD/README.md) (on whichever branch you're using). * well-formed pattern. If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it, try adding it to the `patterns.txt` file. Patterns are Perl 5 Regular Expressions - you can [test]( https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines. Note that patterns can't match multiline strings.
zaikunzhang commented 10 months ago

Salut @amontoison Alexis,

Thank you so much for this nice initiative. It will be very useful.

As @jschueller did, you may consider temporarily disabling the tests that are not relevant during the development, e.g., lint_hosted.yml (unless you introduce changes to the Fortran implementation). They should be restored before we merge the PR.

I am adding @ragonneau Tom as a reviewer, as he knows Julia, whereas I am totally ignorant about it.

Let us keep in touch on this.

Merci beaucoup !

A+, Zaikun

github-actions[bot] commented 10 months ago

@check-spelling-bot Report

:red_circle: Please review

See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.

Unrecognized words (9)

ccall Cdouble CEnum Cint Cvoid eead jll julia libprimac

To accept :heavy_check_mark: these unrecognized words as correct, run the following commands ... in a clone of the [git@github.com:amontoison/prima.git](https://github.com/amontoison/prima.git) repository on the `julia` branch ([:information_source: how do I use this?]( https://github.com/check-spelling/check-spelling/wiki/Accepting-Suggestions)): ``` sh curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/main/apply.pl' | perl - 'https://github.com/libprima/prima/actions/runs/6205100379/attempts/1' ```
Pattern suggestions :scissors: (1) You could add these patterns to .github/actions/spelling/patterns.txt: ``` # Automatically suggested patterns # hit-count: 1 file-count: 1 # uuid: \b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b ```
Warnings (1) See the [:open_file_folder: files](62/files/) view, the [:scroll:action log](https://github.com/libprima/prima/actions/runs/6205100379/job/16847905405#step:2:1) or [:angel: SARIF report](https://github.com/libprima/prima/security/code-scanning?query=is:open+pr:62) for details. [:information_source: Warnings](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions) | Count -|- [:information_source: candidate-pattern](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions#candidate-pattern) | 1 See [:information_source: Event descriptions](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions) for more information.
If the flagged items are :exploding_head: false positives If items relate to a ... * binary file (or some other file you wouldn't want to check at all). Please add a file path to the `excludes.txt` file matching the containing file. File paths are Perl 5 Regular Expressions - you can [test]( https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files. `^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md]( ../tree/HEAD/README.md) (on whichever branch you're using). * well-formed pattern. If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it, try adding it to the `patterns.txt` file. Patterns are Perl 5 Regular Expressions - you can [test]( https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines. Note that patterns can't match multiline strings.
zaikunzhang commented 10 months ago

I have an issue to generate the wrappers of the 4 main functions with Clang.jl but it should be not too hard to fix. I started a discussion here.

Hi @amontoison Alexis,

Thanks to @jschueller Julien's efforts, the problems regarding https://github.com/JuliaInterop/Clang.jl/discussions/443 and https://github.com/libprima/prima/issues/58 are both solved in v0.7.1, the latter being re-solved without introducing non-standard directives.

Many thanks to both.

Zaikun

github-actions[bot] commented 10 months ago

@check-spelling-bot Report

:red_circle: Please review

See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.

Unrecognized words (8)

ccall Cdouble CEnum Cint Cvoid eead jll libprimac

To accept :heavy_check_mark: these unrecognized words as correct, run the following commands ... in a clone of the [git@github.com:amontoison/prima.git](https://github.com/amontoison/prima.git) repository on the `julia` branch ([:information_source: how do I use this?]( https://github.com/check-spelling/check-spelling/wiki/Accepting-Suggestions)): ``` sh curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/main/apply.pl' | perl - 'https://github.com/libprima/prima/actions/runs/6210866872/attempts/1' ```
Pattern suggestions :scissors: (1) You could add these patterns to .github/actions/spelling/patterns.txt: ``` # Automatically suggested patterns # hit-count: 1 file-count: 1 # uuid: \b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b ```
Warnings (1) See the [:open_file_folder: files](62/files/) view, the [:scroll:action log](https://github.com/libprima/prima/actions/runs/6210866872/job/16859523340#step:2:1) or [:angel: SARIF report](https://github.com/libprima/prima/security/code-scanning?query=is:open+pr:62) for details. [:information_source: Warnings](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions) | Count -|- [:information_source: candidate-pattern](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions#candidate-pattern) | 1 See [:information_source: Event descriptions](https://github.com/check-spelling/check-spelling/wiki/Event-descriptions) for more information.
If the flagged items are :exploding_head: false positives If items relate to a ... * binary file (or some other file you wouldn't want to check at all). Please add a file path to the `excludes.txt` file matching the containing file. File paths are Perl 5 Regular Expressions - you can [test]( https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files. `^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md]( ../tree/HEAD/README.md) (on whichever branch you're using). * well-formed pattern. If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it, try adding it to the `patterns.txt` file. Patterns are Perl 5 Regular Expressions - you can [test]( https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines. Note that patterns can't match multiline strings.
amontoison commented 10 months ago

@zaikunzhang I confirm that I can generate the Julia wrappers with the updated header file. It should be quite easy now to call PRIMA in Julia :smiley:

zaikunzhang commented 10 months ago

Hi Alexis @amontoison ,

This is great!

  1. How should users get started? Do they need to compile / install the package in some way? It would be nice to have a README like /README_mat.md.
  2. Would it be possible to include a simple example under julia/examples/, in the same way as matlab/examples/? A Julia version of matlab/examples/rosenbrock_example.m would be great!

Thank you very much!

A+, Zaikun

zaikunzhang commented 10 months ago

Unrecognized words (8)

ccall Cdouble CEnum Cint Cvoid eead jll libprimac

If these words are false positives, then you may put them in .github/actions/spelling/allow.txt.

Thanks.

amontoison commented 10 months ago
1. How should users get started? Do they need to compile / install the package in some way? It would be nice to have a README like `README_mat.md`.

The users don't need to compile PRIMA. It's already precompiled for them. They just need to use PRIMA_jll and load the Julia wrappers.

using PRIMA_jll

include("wrappers.jl")

calfun = ...
n = ...
x = ...
f = ...
xl = ...
xu = ...
nf = ...
rhobeg = ...
rhoend = ...
ftarget = ...
maxfun = ...
npt = ...
iprint = ...

info = prima_bobyqa(calfun, n, x, f, xl, xu, nf, rhobeg, rhoend, ftarget, maxfun, npt, iprint)
2. Would it be possible to include a simple example under `julia/examples/`, in the same way as `matlab/examples/`? A Julia version of `matlab/examples/rosenbrock_example.m` would be great!

I can find time to do that next week. Which algorithm is called by MATLAB, is it bobyqa, newuoa, uobyqa, cobyla or lincoa?

zaikunzhang commented 10 months ago

Which algorithm is called by MATLAB, is it bobyqa, newuoa, uobyqa, cobyla or lincoa?

Indeed, the MATLAB interface is quite sophisticated (for example, see how we interpret and preprocess the input from the user). Everything is wrapped under a single function called prima, which has the same signature as the MATLAB function fmincon from MathWorks, so users do not need to learn how to use prima. Basically, they just need to change fmincon to prima in their existing MATLAB code. That's all.

Coming back to your question, the user does not need to specify which solver to call --- prima will select the correct one according to the input, although it is also possible to choose one manually by setting the Algorithm option. In addition, the user does not need to input parameters like rhobeg and rhoend unless they want to, as prima will default the parameters to values that work well in general.

That said, if you look at matlab/examples/rosenbrock_example.m, you will see that users only need to focus on the definition of the problem itself, and then call prima. Everything else is handled by prima. For example, in the unconstrained case, the code to call prima is

[x, fx, exitflag, output] = prima(@chrosen, x0)  

The user only needs to define the objective function chrosen and starting point x0, but nothing else, unless he/she wants to.

Of course, I do not expect the Julia wrapper will do something as sophisticated as the MATLAB interface in the short term --- it took months for Tom and me to code the Python and MATLAB interfaces for PDFO, from which PRIMA inherits the MATLAB interface.

We can regard the current wrappers as the basis for using PRIMA in Julia, which is already extremely nice. In the future, there will be a more sophisticated and user-friendly version of PRIMA.jl built on it. It will be the equivalent of the MATLAB interface for PRIMA.

Coming back to your question again, we can call cobyla to solve nonlinearly constrained problems, lincoa for linearly constrained ones, bobyqa for bound constrained ones, and both uobyqa and newuoa for unconstrained ones.

Thanks.

Zaikun

zaikunzhang commented 10 months ago

The users don't need to compile PRIMA. It's already precompiled for them. They just need to use PRIMA_jll and load the Julia wrappers.

Great! Do they need to install PRIMA somehow, so that the precompiled binaries are stored at the correct place and Julia can find them?

using PRIMA_jll

include("wrappers.jl")

Is it standard to call it wrappers.jl? What if there is another package that has wrappers.jl as well? For example,

using A_jil include("wrappers.jl") using B_jil include("wrappers.jl")

Would there be a conflict?

Sorry for my ignorance about Julia. Thanks.

zaikunzhang commented 10 months ago

h has the same signature as the MATLAB function fmincon from MathWorks, so users do not need to learn how to use prima. Basically, they just need to change fmincon to prima in their existing MATLAB code. That's all.

Hi @amontoison Alexis, I have elaborated my idea on interfaces here: https://github.com/orgs/libprima/discussions/79 .

I suppose we are currently working on the basic interface defined there. (But we may make it a bit easier to use, by, for example, defaulting parameters to reasonable values if they are not provided by the user.) This is a nice start and already extremely valuable.

Merci !

emmt commented 10 months ago

Sorry for having missed this discussion so far.

Two points for the discussion:

  1. I would avoid using Clang.jl for automatically build the interface. First, it is quite an heavy solution and there are only 6 functions to integrate (the 5 algorithms plus the routine to retrieve the error messages). Second, it can only generates low level Julia code (similar to C prototype), whenever the C API of PRIMA library change, one will have to manually modify the code to add/remove/convert arguments and check their validity. Third and AFAIK, it is quite unusual to have some Julia code in artifacts.

  2. The Julia package manager imposes that the Julia package be a repository in itself with a given structure. My understanding is that Julia's interface to PRIMA cannot be part of the PRIMA library repository if we want users to just do:

    pkg> add PRIMA

    to install PRIMA in Julia.

These lead me to the conclusion that a separate repository is needed for the Julia interface to PRIMA library.

Based on @amontoison PRIMA_jll artifact, I have started to code a working Julia package PRIMA.jl which provides a high level Julia interface to all the algorithms of the PRIMA library. It turns out that this interface is very similar to the one elaborated by @zaikunzhang in https://github.com/orgs/libprima/discussions/79. This is is purely incidental and, to me, directly follows from the logic and consistency of the API of the PRIMA library. I have just finished documenting the PRIMA.jl package which is nearly ready for end-users.

bilderbuchi commented 10 months ago

2. The Julia package manager imposes that the Julia package be a repository in itself with a given structure.

Are you sure about this? I know that e.g. GLMakie resides in a repo subdirectory (but the repo root has a Julia package, too, maybe that's the reason). I could not find a mention of this in the docs on a quick search.

emmt commented 10 months ago

Well, this was my understanding. GLMakie (the GL backend for Makie) is part of the Makie Julia package and I guess that it needs this parent project to work. I would say that it is a sub-project of the Julia Makie project. All these are in a dedicated GIT repository. To mitigate my claim: it is simpler if the Julia API for PRIMA be a repository in its own. This is what is done by many other packages.

BTW, the PRIMA.jl package now exists, is ready for a try, and depends on the PRIMA_jl artefact.

bilderbuchi commented 10 months ago

GLMakie (the GL backend for Makie) is part of the Makie Julia package

Actually, they are dependencies of each other: https://github.com/MakieOrg/Makie.jl/blob/2b8b8a1472f2fd8692a64a554f3b85669c297e90/GLMakie/Project.toml#L14C1-L14C7

I think all of these being hosted together mainly looks like a convenience thing (maintenance, issue tracking,...). In the end, you're probably right and a separate repo eases things -- Prima.jl e.g. living in the libprima organisation seems like a natural fit, but I don't have skin in the game either way.

amontoison commented 9 months ago

Hi everyone, sorry for not answering earlier. We can create and register a Julia package as a subdirectory of any git repository but it's more relevant to create a standalone Julia repository PRIMA.jl like @emmt did. The package has more visibility.

A good idea is to move the repository into the libprima organization before that we register it if you add us to the organization @zaikunzhang. @emmt what do you think?

emmt commented 9 months ago

I totally agree with that. How shall I proceed?

amontoison commented 9 months ago

@zaikunzhang Should add us as collaborators of the libprima organization. After that you will be able to transfer the repository into the organization (tutorial). The last step is to register PRIMA.jl as an official Julia package.

zaikunzhang commented 9 months ago

Hi everyone,

Sorry for the slow response. I have sent the invitations. Thank you very much for contributing to libprima.

As for the registration of PRIMA.jl as an official Julia package, I suggest we also do it through libprima. I guess it will be beneficial for the long-term maintenance of the package.

Thanks.

Zaikun

emmt commented 9 months ago

Thanks for the invitation!

Now that I have accepted it, I am not sure how to move the repository PRIMA.jl implementing the Julia API into libprima. Shall I select Transfer ownership in the setings of the GitHub repository?

amontoison commented 9 months ago

Thanks for the invitation!

Now that I have accepted it, I am not sure how to move the repository PRIMA.jl implementing the Julia API into libprima. Shall I select Transfer ownership in the setings of the GitHub repository?

Yes, it's Transfer ownership. I suggest to do a fork with GitHub after the transfer to still have an emmt/PRIMA.jl. it will be connected to the main repo libprima/PRIMA.jl.

emmt commented 9 months ago

OK thanks for the answer and the suggestion.

I still have a couple of (silly) questions:

  1. I guess that, then, when I will push to this fork, I will have the opportunity to make a PR on the original (the one transferred in libprima)?
  2. Similar/related question: will I be able to push directly to the transferred repository?
  3. What about the pending PR to have PRIMA.jl be officially part of Julia General Registry? Should I cancel it or is there a way to redirect it to the transferred repository?
amontoison commented 9 months ago

OK thanks for the answer and the suggestion.

I still have a couple of (silly) questions:

1. I guess that, then, when I will push to this fork, I will have the opportunity to make a PR on the original (the one transferred in `libprima`)?

Yes, all GitHub members will be able to open a PR.

2. Similar/related question: will I be able to push directly to the transferred repository?

Yes, because you are a member of the libprima organization.

3. What about the pending PR to have `PRIMA.jl` be officially part of Julia _General Registry_? Should I cancel it or is there a way to redirect it to the transferred repository?

The PR is not merged so it's not an issue. We can retrigger the registration when the repository is in libprima. If the PR is merged, we can also change the url of the repository. I already did that for NOMAD.jl.

emmt commented 9 months ago

Thanks for all your explanations. I am doing the transfer right now!