Skip to content

Commit 5aaeab7

Browse files
tmigotclaude
andauthored
Add CLAUDE.md (#417)
* Add CLAUDE.md * Fix CLAUDE.md issues raised in PR review - Fix elementwise boolean operator (.&& → .&) in meta filter example - Soften three-file pattern to guideline, noting legacy exceptions - Generalize scalable n-adjustment guidance (not just max(2,n)) - Correct generate_meta() location to test/utils.jl Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 1dd55ab commit 5aaeab7

1 file changed

Lines changed: 201 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
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

Comments
 (0)