Skip to content

Add MathOptInterface conformance tests and JuMP documentation - #14

Merged
pjssilva merged 1 commit into
pjssilva:masterfrom
joaquimg:jump-solvers-table
Aug 20, 2026
Merged

Add MathOptInterface conformance tests and JuMP documentation#14
pjssilva merged 1 commit into
pjssilva:masterfrom
joaquimg:jump-solvers-table

Conversation

@joaquimg

Copy link
Copy Markdown
Contributor

Add MathOptInterface conformance tests and JuMP documentation

Groundwork for listing Algencan in the JuMP supported-solvers table.
JuMP's checklist for adding a solver asks for a MOI.Test.runtests
run and a JuMP usage example; this adds both, along with one bug fix found on the
way.

Why there is no Algencan.Optimizer

Algencan does not need an MOI wrapper of its own. AlgencanSolver is a
SolverCore.AbstractOptimizationSolver, and NLPModelsJuMP.Optimizer is the
generic MOI wrapper for exactly that:

model = Model(NLPModelsJuMP.Optimizer)
set_attribute(model, "solver", NLPModelsAlgencan.AlgencanSolver)

This is the same arrangement as Percival.jl, which is already in the JuMP table
on that basis — NLPModelsJuMP's own test/MOI_wrapper.jl drives the conformance
suite with Percival.PercivalSolver.

test/MOI_wrapper.jl

541 of the 561 MOI.Test tests pass, 2264 assertions.

The exclude list was derived empirically, by running every test in the suite
individually and recording each verdict, rather than copied from NLPModelsJuMP.
It comes to 20 exclusions in four groups, each explained in the file:

Cause Tests Whose limitation
Second-derivative oracles requested unconditionally from a raw MOI.NLPBlock evaluator (Unsupported feature Hess/HessVec/JacVec) 9 NLPModelsJuMP
No global infeasibility or unboundedness certificate — reports LOCALLY_INFEASIBLE 7 Algencan, by design
Converges to an infeasible stationary point from the test's starting point 3 Algencan, by design
Unknown model attributes ignored rather than raising MOI.UnsupportedAttribute 1 NLPModelsJuMP

Two notes for reviewers:

  • test_linear_integration_delete_variables is excluded in NLPModelsJuMP with a
    # FIXME Segfault comment. It passes here, so it is not excluded.
  • The conformance suite takes roughly 20 minutes. If that is too much across the
    whole CI matrix, it could be gated to a single platform.

Fix: verbose and max_iter keyword arguments

solver.options is built as a Dict{Symbol,Any}, but these two were stored
under String keys, so neither could ever be set:

julia> algencan(nlp; verbose = 0)
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Symbol

julia> algencan(nlp; max_iter = 5)
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Symbol

Both are documented keyword arguments. Two characters each, plus a testset
covering them — nothing exercised them before, which is how this went unnoticed.

The JuMP path was unaffected, which is the other reason it stayed hidden:
MOI.Silent() arrives as a solve! keyword and that branch already used a
symbol. Happy to pull this into its own PR if you would rather keep the diff to
tests and docs.

README

New ## Use with JuMP section with a worked example (both snippets in it were
run), plus ## Affiliation and ## Getting help — the latter two are what
JuMP's checklist asks for before a package can appear in the /solvers section
of their documentation.

It documents two rough edges rather than papering over them:

  • set_silent(model) suppresses the iteration table but not Algencan's banner
    and parameter listing. Algencan 3.1.1 writes those to standard output
    unconditionally: ITERATIONS-OUTPUT-DETAIL -1 does not stop them, and
    outputfnm duplicates output to the file rather than diverting it. Honouring
    MOI.Silent() fully would mean redirecting the process's stdout around the
    ccall, which seemed too intrusive to decide here.
  • Constraint duals are not mapped onto MOI. Algencan computes the multipliers;
    they remain available as stats.multipliers.

Follow-up

Once this lands, the JuMP-side PR is a single row in docs/src/installation.md:

| [Algencan](https://www.ime.usp.br/~egbirgin/tango/)                            | [NLPModelsAlgencan.jl](https://github.com/pjssilva/NLPModelsAlgencan.jl)         |        | GPL      | NLP                       |

JuMP's checklist for adding a solver to its supported-solvers table asks for a
MOI.Test.runtests run and a JuMP usage example. This adds both.

test/MOI_wrapper.jl runs the conformance suite through NLPModelsJuMP.Optimizer
with AlgencanSolver, the same arrangement Percival.jl is listed on. 541 of the
561 tests pass. The exclude list was derived by running every test in the suite
individually rather than copied from NLPModelsJuMP; the 20 exclusions are
grouped by cause and each group is explained in the file.

Also fixes `verbose` and `max_iter`, which were stored under String keys in a
Dict{Symbol,Any} and so threw a MethodError for any non-default value, and adds
a testset covering them. The MOI path was unaffected, since MOI.Silent() arrives
as a solve! keyword and that branch already used a symbol.

README gains a "Use with JuMP" section, plus the Affiliation and Getting help
sections JuMP asks for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@joaquimg

Copy link
Copy Markdown
Contributor Author

These would be ideal for: jump-dev/JuMP.jl#4218

Some are not essential, so let me know if you dont like some of it.

@pjssilva
pjssilva merged commit dad2f48 into pjssilva:master Aug 20, 2026
3 checks passed
@pjssilva

Copy link
Copy Markdown
Owner

Hi, Joaquim.

Sorry for taking a while, but I was finishing the work to support MA86 and MA97 when available, and classes started.

Thanks a lot for the PR, I will merge it. It would be nice to be in the JuMP table.

I reproduced your figures here on a clean resolve: 561 test functions in MOI.Test, 20 excluded, 541 run, 2264 assertions, all passing.

I also ran it against MathOptInterface 1.40 and 1.52. All 20 exclusion regexes still match live test names in both, and none of the ten tests added between those releases fail, so the list looks stable across versions rather than tied to the one you developed against.

No need to split the verbose/max_iter fix — the test that proves it belongs with it.

After the merge I will fix a couple of comments and some details and release 0.10.1

@joaquimg

Copy link
Copy Markdown
Contributor Author

Fantastic! Let me know when 0.10.1 is out and I will use that in the JuMP docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants