|
| 1 | +# CLAUDE.md — OptimizationProblems.jl |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +**OptimizationProblems.jl** (v0.9.3) is a Julia package providing ~680+ nonlinear programming (NLP) test problems for benchmarking and developing optimization solvers. It is part of the [JuliaSmoothOptimizers](https://github.com/JuliaSmoothOptimizers) ecosystem and integrates with NLPModels, ADNLPModels, and JuMP. |
| 6 | + |
| 7 | +**Central registry:** `OptimizationProblems.meta` is a `DataFrame` built at load time from `src/Meta/`. It gives instant access to metadata (nvar, ncon, objtype, origin, bounds, feasibility, …) for all problems **without instantiating any model** — extremely useful for filtering and analysis. |
| 8 | + |
| 9 | +```julia |
| 10 | +using OptimizationProblems |
| 11 | +# Filter unconstrained problems with ≤ 50 variables |
| 12 | +df = OptimizationProblems.meta |
| 13 | +df[(df.ncon .== 0) .& (df.nvar .≤ 50), :] |
| 14 | +``` |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## Repository Structure |
| 19 | + |
| 20 | +``` |
| 21 | +src/ |
| 22 | + OptimizationProblems.jl # Main module — builds meta DataFrame |
| 23 | + ADNLPProblems/ |
| 24 | + ADNLPProblems.jl # Module loader (lazy, requires ADNLPModels) |
| 25 | + <name>.jl # One file per problem |
| 26 | + PureJuMP/ |
| 27 | + PureJuMP.jl # Module loader (always loaded) |
| 28 | + <name>.jl # One file per problem |
| 29 | + Meta/ |
| 30 | + <name>.jl # One metadata file per problem |
| 31 | +test/ # Julia unit test suite |
| 32 | +docs/ # Documenter.jl docs (make.jl, src/) |
| 33 | + src/contributing.md # Authoritative contributor guidelines |
| 34 | +benchmark/ # BenchmarkTools suite (own Project.toml) |
| 35 | +data/ # .jld2 data files for mesh-heavy problems |
| 36 | +``` |
| 37 | + |
| 38 | +--- |
| 39 | + |
| 40 | +## Three-File Pattern |
| 41 | + |
| 42 | +New problems should provide exactly three files sharing the same base name. (Some existing problems are JuMP-only and lack an `ADNLPProblems` file; a few files also define multiple problems — see `triangle.jl` — but these are legacy exceptions.) |
| 43 | + |
| 44 | +### `src/ADNLPProblems/<name>.jl` |
| 45 | + |
| 46 | +AD-based model. Lazy-loaded (only available when `ADNLPModels` is imported). |
| 47 | + |
| 48 | +```julia |
| 49 | +export <name> |
| 50 | + |
| 51 | +function <name>(; n::Int = default_nvar, type::Type{T} = Float64, kwargs...) where {T} |
| 52 | + # x0 must be Vector{T}, objective must return type T |
| 53 | + f(x) = ... |
| 54 | + x0 = ones(T, n) |
| 55 | + return ADNLPModels.ADNLPModel(f, x0, name = "<name>"; kwargs...) |
| 56 | +end |
| 57 | +``` |
| 58 | + |
| 59 | +### `src/PureJuMP/<name>.jl` |
| 60 | + |
| 61 | +JuMP algebraic model. Always loaded. Short docstring above the function. |
| 62 | + |
| 63 | +```julia |
| 64 | +export <name> |
| 65 | + |
| 66 | +"Short description of the problem." |
| 67 | +function <name>(args...; n::Int = default_nvar, kwargs...) |
| 68 | + nlp = Model() |
| 69 | + # define variables, constraints, objective |
| 70 | + return nlp |
| 71 | +end |
| 72 | +``` |
| 73 | + |
| 74 | +### `src/Meta/<name>.jl` |
| 75 | + |
| 76 | +Metadata dictionary. Does **not** export the problem function. |
| 77 | + |
| 78 | +```julia |
| 79 | +<name>_meta = Dict( |
| 80 | + :nvar => 10, |
| 81 | + :variable_nvar => false, |
| 82 | + :ncon => 0, |
| 83 | + :variable_ncon => false, |
| 84 | + :minimize => true, |
| 85 | + :name => "<name>", |
| 86 | + :has_equalities_only => false, |
| 87 | + :has_inequalities_only => false, |
| 88 | + :has_bounds => false, |
| 89 | + :has_fixed_variables => false, |
| 90 | + :objtype => :other, # see valid values below |
| 91 | + :contype => :unconstrained, # see valid values below |
| 92 | + :best_known_lower_bound => -Inf, |
| 93 | + :best_known_upper_bound => Inf, |
| 94 | + :is_feasible => true, |
| 95 | + :defined_everywhere => true, |
| 96 | + :origin => :academic, # see valid values below |
| 97 | + # Additional fields (branch move-docstring-to-metadata): |
| 98 | + :url => "https://...", # must match ^https?:// |
| 99 | + :notes => raw"""""", # problem description |
| 100 | + :origin_notes => raw"""""", # provenance |
| 101 | + :reference => raw"""@type{key, ...}""", # BibTeX, balanced braces |
| 102 | + :lib => "CUTEst:NAME", # library codes, comma-separated |
| 103 | +) |
| 104 | +``` |
| 105 | + |
| 106 | +**Valid values:** |
| 107 | +- `:objtype`: `:none`, `:constant`, `:linear`, `:quadratic`, `:sum_of_squares`, `:other`, `:least_squares` |
| 108 | +- `:contype`: `:unconstrained`, `:linear`, `:quadratic`, `:general` |
| 109 | +- `:origin`: `:academic`, `:modelling`, `:real`, `:unknown` |
| 110 | + |
| 111 | +--- |
| 112 | + |
| 113 | +## Scalable Problems |
| 114 | + |
| 115 | +Problems that accept a variable size use `n::Int = default_nvar` (default = 100). |
| 116 | + |
| 117 | +- Adjust invalid `n` to the closest valid value silently with `@warn`, never throw an error. The exact adjustment depends on the problem's constraints on `n` (minimum size, divisibility, parity, etc.). |
| 118 | +- Export getter functions for the Meta file: `get_<name>_nvar`, `get_<name>_ncon`, `get_<name>_nlin`, `get_<name>_nnln`, `get_<name>_nequ`, `get_<name>_nineq` |
| 119 | +- Reference: `src/ADNLPProblems/arglina.jl`, `src/PureJuMP/arglina.jl`, `src/Meta/arglina.jl` |
| 120 | + |
| 121 | +--- |
| 122 | + |
| 123 | +## Nonlinear Least-Squares (NLS) Problems |
| 124 | + |
| 125 | +- Set `:objtype => :least_squares` in the meta file |
| 126 | +- Support `use_nls=true/false` keyword: returns `ADNLSModel` or `ADNLPModel` |
| 127 | +- Export `get_<name>_nls_nequ` |
| 128 | +- `residual!(nls, x, Fx)` must be allocation-free |
| 129 | +- Reference: `src/ADNLPProblems/lanczos1.jl`, `src/ADNLPProblems/brownal.jl` |
| 130 | + |
| 131 | +--- |
| 132 | + |
| 133 | +## Code Formatting |
| 134 | + |
| 135 | +Uses [JuliaFormatter.jl](https://github.com/domluna/JuliaFormatter.jl). Config is in `.JuliaFormatter.toml`: |
| 136 | + |
| 137 | +| Setting | Value | |
| 138 | +|---------|-------| |
| 139 | +| `margin` | 100 | |
| 140 | +| `indent` | 2 | |
| 141 | +| `normalize_line_endings` | `"unix"` | |
| 142 | + |
| 143 | +Format the codebase locally: |
| 144 | + |
| 145 | +```julia |
| 146 | +using JuliaFormatter |
| 147 | +format(".") |
| 148 | +``` |
| 149 | + |
| 150 | +--- |
| 151 | + |
| 152 | +## Testing |
| 153 | + |
| 154 | +The test suite uses Julia's `Test` stdlib with `Distributed` for parallel execution. |
| 155 | + |
| 156 | +``` |
| 157 | +julia --project test/runtests.jl |
| 158 | +``` |
| 159 | + |
| 160 | +Key test files: |
| 161 | + |
| 162 | +| File | Purpose | |
| 163 | +|------|---------| |
| 164 | +| `test/test-defined-problems.jl` | Verifies all meta entries have working implementations | |
| 165 | +| `test/test-scalable.jl` | Validates scalable problem sizing and getter formulas | |
| 166 | +| `test/test-in-place-residual.jl` | Allocation checks for NLS residuals | |
| 167 | +| `test/utils.jl` | Helpers: `generate_meta()`, `test_multi_precision()` | |
| 168 | + |
| 169 | +**Always test:** |
| 170 | +- Multiple sizes for scalable problems: `n = 5`, `n = default_nvar`, large `n` |
| 171 | +- Both `Float32` and `Float64` |
| 172 | +- Allocation-free in-place APIs (`cons_nln!`, `residual!`) |
| 173 | + |
| 174 | +--- |
| 175 | + |
| 176 | +## Good Reference Problems |
| 177 | + |
| 178 | +| Category | Examples | |
| 179 | +|----------|---------| |
| 180 | +| Unconstrained, scalable | `arwhead`, `arglina` | |
| 181 | +| Constrained | `hs100`, `catmix` | |
| 182 | +| Least squares (NLS) | `lanczos1`, `brownal` | |
| 183 | +| With data files | `catmix`, `rocket` | |
| 184 | + |
| 185 | +--- |
| 186 | + |
| 187 | +## Benchmarks |
| 188 | + |
| 189 | +The `benchmark/` directory has its own Julia environment. Run locally: |
| 190 | + |
| 191 | +``` |
| 192 | +julia benchmark/run_local.jl |
| 193 | +``` |
| 194 | + |
| 195 | +Benchmarks cover constructor time and objective evaluation for both `ADNLPProblems` and `PureJuMP`, using `BenchmarkTools.jl`. |
| 196 | + |
| 197 | +--- |
| 198 | + |
| 199 | +## Full Contributor Guidelines |
| 200 | + |
| 201 | +See [`docs/src/contributing.md`](docs/src/contributing.md) for the complete checklist when adding or modifying problems, including the full reviewer checklist for meta fields, implementation consistency, type stability, and allocation requirements. |
0 commit comments