From 114515a9ba36329c0a99e1791a498b6d05c39994 Mon Sep 17 00:00:00 2001 From: arnavk23 Date: Sun, 15 Mar 2026 14:59:00 +0530 Subject: [PATCH 01/14] Improve contributing.md: clarify requirements for adding new problems, including constraints, compatibility, meta fields, allocation, and scalability --- docs/src/contributing.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index 1fc1c9b2..d41f32f6 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -1,5 +1,4 @@ # Contributing to OptimizationProblems.jl - First off, thanks for taking the time to contribute! ## Bug reports and discussions @@ -19,12 +18,12 @@ Here is a to-do list, to help you add new problems: - `src/ADNLPProblems/problem_name.jl` - `src/PureJuMP/problem_name.jl` - `src/Meta/problem_name.jl` -In both cases, the function must have the same name `problem_name` as the file. +In both cases, the function must have the same name `problem_name` as the file and the objective must be callable at the starting point and should not return NaN unless expected. * When submitting a problem, please pay particular attention to the documentation. We would like to gather as much information as possible on the provenance of problems, other problem sets where the problems are present, and general information on the problem. The documentation should be added to the file in the `PureJuMP` folder. * New problems can be scalable, see [ADNLPProblems/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl) and [PureJuMP/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/PureJuMP/arglina.jl) for examples. In that case, the first keyword parameter should be the number of variables `n::Int` and have the default value `default_nvar` (constant predefined in the module). If your problem has restrictions on the number of variables, e.g., `n` should be odd, or `n` should have the form `4k + 3`, then, instead of throwing errors when the restrictions are not satisfied, you should instead use the number of variables to be as close to `n` as possible. For example, if you want `n` odd and `n = 100` is passed, you can internally convert to `n = 99`. If you want `n = 4k + 3`, and `n = 100` is passed, then compute `k = round(Int, (n - 3) / 4)` and update `n`. -* A first version of the `meta` can be generated using `generate_meta`. A `String` is returned that can be copy-pasted into the `Meta` folder, and then edited. - +* A first version of the `meta` can be generated using `generate_meta`. A `String` is returned that can be copy-pasted into the `Meta` folder, and then edited. Ensure all meta fields are accurate and complete including `nvar`, `ncon`, linear/nonlinear counts, feasibility, origin, objtype, contype and best-known bounds. +* For problem implementation in both ADNLP and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. ```julia using ADNLPModels, Distributed, NLPModels, NLPModelsJuMP, OptimizationProblems, Test include("test/utils.jl") @@ -33,7 +32,10 @@ The documentation should be added to the file in the `PureJuMP` folder. create_meta_files(String["catmix", "gasoil", "glider", "methanol", "pinene", "rocket", "steering"]) ``` -* Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API. +* Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API +and should support the `nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. +* For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free with the objectives agree (or differ by a factor of 2 for LS). +* For variable-size problems, verify that different values of `n` produce correct `nvar`, meta formulas predict actual values and instantiation works at various sizes. ## Templates for the new functions From bab2d3b125f167f1439ab947610b0e175cb80d0a Mon Sep 17 00:00:00 2001 From: arnavk23 Date: Sun, 15 Mar 2026 15:04:46 +0530 Subject: [PATCH 02/14] Clarify meta field completeness and validation requirements in meta.md, as suggested by validation analysis PDF --- docs/src/meta.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/src/meta.md b/docs/src/meta.md index f22909d4..61d83f9d 100644 --- a/docs/src/meta.md +++ b/docs/src/meta.md @@ -8,10 +8,16 @@ using OptimizationProblems Each problem has its own metadata structure, and there is a global metadata structure regrouping all the information. +> **Meta field completeness:** +> All meta fields must be accurate and complete, including `nvar`, `ncon`, linear/nonlinear counts, bounds, minimize, feasibility ordering, origin, objtype, contype, and best-known bounds. Meta validation is enforced by the test suite. Incomplete or incorrect meta fields may cause solver failures or benchmarking errors. + ## Problem's metadata Each problem's metadata is accessible with `OptimizationProblems.nameoftheproblem_meta` and regroups in a `Dict` most of the essential information regarding each problem. +> **Meta validation:** +> Meta fields are used for problem classification, filtering, and benchmarking. Ensure all fields are correct and consistent with the actual problem implementation. The test suite checks meta field accuracy. + ```@example 1 OptimizationProblems.AMPGO02_meta ``` From 45090ce6c04f77d38b648cde27aaf536bdfb7416 Mon Sep 17 00:00:00 2001 From: arnavk23 Date: Sun, 15 Mar 2026 15:05:55 +0530 Subject: [PATCH 03/14] Add note to benchmark.md about compatibility and meta field validation requirements for benchmarking, as suggested by validation analysis PDF --- docs/src/benchmark.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/benchmark.md b/docs/src/benchmark.md index c258f8d9..910d2f06 100644 --- a/docs/src/benchmark.md +++ b/docs/src/benchmark.md @@ -1,5 +1,7 @@ # Run a benchmark with OptimizationProblems.jl +> **Note:** When benchmarking, ensure that problems from ADNLP and PureJuMP implementations are strictly compatible (same initial point, bounds, constraints, and objective/constraint values within tolerance). Use meta fields for filtering and validation. Meta field completeness and accuracy are enforced by the test suite and are critical for reliable benchmarking. + In this more advanced tutorial, we use the problems from `OptimizationProblems` to run a benchmark for unconstrained problems. The tutorial will use: - [JSOSolvers](https://github.com/JuliaSmoothOptimizers/JSOSolvers.jl): This package provides optimization solvers in pure Julia for unconstrained and bound-constrained optimization. From fe9dcca0045295ad375f4ea172f4c466c36fb00c Mon Sep 17 00:00:00 2001 From: Arnav Kapoor Date: Sun, 15 Mar 2026 15:08:24 +0530 Subject: [PATCH 04/14] Update meta.md for improved clarity on meta fields Clarified requirements for meta field completeness and validation. --- docs/src/meta.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/src/meta.md b/docs/src/meta.md index 61d83f9d..d4fa70d9 100644 --- a/docs/src/meta.md +++ b/docs/src/meta.md @@ -7,17 +7,12 @@ using OptimizationProblems ``` Each problem has its own metadata structure, and there is a global metadata structure regrouping all the information. - -> **Meta field completeness:** -> All meta fields must be accurate and complete, including `nvar`, `ncon`, linear/nonlinear counts, bounds, minimize, feasibility ordering, origin, objtype, contype, and best-known bounds. Meta validation is enforced by the test suite. Incomplete or incorrect meta fields may cause solver failures or benchmarking errors. +All meta fields must be accurate and complete including `nvar`, `ncon`, linear/nonlinear counts, feasibility, origin, objtype, contype and best-known bounds. Meta validation is enforced by the test suite. Incomplete or incorrect meta fields may cause solver failures or benchmarking errors. ## Problem's metadata Each problem's metadata is accessible with `OptimizationProblems.nameoftheproblem_meta` and regroups in a `Dict` most of the essential information regarding each problem. -> **Meta validation:** -> Meta fields are used for problem classification, filtering, and benchmarking. Ensure all fields are correct and consistent with the actual problem implementation. The test suite checks meta field accuracy. - ```@example 1 OptimizationProblems.AMPGO02_meta ``` From 092c66c699f25b940ad5d6305347463a72f9ff89 Mon Sep 17 00:00:00 2001 From: Arnav Kapoor Date: Sun, 29 Mar 2026 23:40:02 +0530 Subject: [PATCH 05/14] Apply suggestions from code review Co-authored-by: Tangi Migot --- docs/src/benchmark.md | 2 -- docs/src/contributing.md | 2 +- docs/src/meta.md | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/src/benchmark.md b/docs/src/benchmark.md index 910d2f06..c258f8d9 100644 --- a/docs/src/benchmark.md +++ b/docs/src/benchmark.md @@ -1,7 +1,5 @@ # Run a benchmark with OptimizationProblems.jl -> **Note:** When benchmarking, ensure that problems from ADNLP and PureJuMP implementations are strictly compatible (same initial point, bounds, constraints, and objective/constraint values within tolerance). Use meta fields for filtering and validation. Meta field completeness and accuracy are enforced by the test suite and are critical for reliable benchmarking. - In this more advanced tutorial, we use the problems from `OptimizationProblems` to run a benchmark for unconstrained problems. The tutorial will use: - [JSOSolvers](https://github.com/JuliaSmoothOptimizers/JSOSolvers.jl): This package provides optimization solvers in pure Julia for unconstrained and bound-constrained optimization. diff --git a/docs/src/contributing.md b/docs/src/contributing.md index d41f32f6..922f4c4d 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -22,7 +22,7 @@ In both cases, the function must have the same name `problem_name` as the file a * When submitting a problem, please pay particular attention to the documentation. We would like to gather as much information as possible on the provenance of problems, other problem sets where the problems are present, and general information on the problem. The documentation should be added to the file in the `PureJuMP` folder. * New problems can be scalable, see [ADNLPProblems/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl) and [PureJuMP/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/PureJuMP/arglina.jl) for examples. In that case, the first keyword parameter should be the number of variables `n::Int` and have the default value `default_nvar` (constant predefined in the module). If your problem has restrictions on the number of variables, e.g., `n` should be odd, or `n` should have the form `4k + 3`, then, instead of throwing errors when the restrictions are not satisfied, you should instead use the number of variables to be as close to `n` as possible. For example, if you want `n` odd and `n = 100` is passed, you can internally convert to `n = 99`. If you want `n = 4k + 3`, and `n = 100` is passed, then compute `k = round(Int, (n - 3) / 4)` and update `n`. -* A first version of the `meta` can be generated using `generate_meta`. A `String` is returned that can be copy-pasted into the `Meta` folder, and then edited. Ensure all meta fields are accurate and complete including `nvar`, `ncon`, linear/nonlinear counts, feasibility, origin, objtype, contype and best-known bounds. +* A first version of the `meta` can be generated using `generate_meta`. A `String` is returned that can be copy-pasted into the `Meta` folder, and then edited. Ensure all meta fields are accurate and complete. * For problem implementation in both ADNLP and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. ```julia using ADNLPModels, Distributed, NLPModels, NLPModelsJuMP, OptimizationProblems, Test diff --git a/docs/src/meta.md b/docs/src/meta.md index d4fa70d9..f22909d4 100644 --- a/docs/src/meta.md +++ b/docs/src/meta.md @@ -7,7 +7,6 @@ using OptimizationProblems ``` Each problem has its own metadata structure, and there is a global metadata structure regrouping all the information. -All meta fields must be accurate and complete including `nvar`, `ncon`, linear/nonlinear counts, feasibility, origin, objtype, contype and best-known bounds. Meta validation is enforced by the test suite. Incomplete or incorrect meta fields may cause solver failures or benchmarking errors. ## Problem's metadata From 8cab328cc9df6a5e6bde6c8b2f01b7a9e517b17e Mon Sep 17 00:00:00 2001 From: arnavk23 Date: Tue, 31 Mar 2026 01:56:33 +0530 Subject: [PATCH 06/14] addressing review comments --- docs/src/contributing.md | 49 +++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index 922f4c4d..c51ee63c 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -1,4 +1,5 @@ # Contributing to OptimizationProblems.jl + First off, thanks for taking the time to contribute! ## Bug reports and discussions @@ -18,12 +19,11 @@ Here is a to-do list, to help you add new problems: - `src/ADNLPProblems/problem_name.jl` - `src/PureJuMP/problem_name.jl` - `src/Meta/problem_name.jl` -In both cases, the function must have the same name `problem_name` as the file and the objective must be callable at the starting point and should not return NaN unless expected. +In both cases, the function must have the same name `problem_name` as the file. * When submitting a problem, please pay particular attention to the documentation. We would like to gather as much information as possible on the provenance of problems, other problem sets where the problems are present, and general information on the problem. The documentation should be added to the file in the `PureJuMP` folder. * New problems can be scalable, see [ADNLPProblems/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl) and [PureJuMP/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/PureJuMP/arglina.jl) for examples. In that case, the first keyword parameter should be the number of variables `n::Int` and have the default value `default_nvar` (constant predefined in the module). If your problem has restrictions on the number of variables, e.g., `n` should be odd, or `n` should have the form `4k + 3`, then, instead of throwing errors when the restrictions are not satisfied, you should instead use the number of variables to be as close to `n` as possible. For example, if you want `n` odd and `n = 100` is passed, you can internally convert to `n = 99`. If you want `n = 4k + 3`, and `n = 100` is passed, then compute `k = round(Int, (n - 3) / 4)` and update `n`. -* A first version of the `meta` can be generated using `generate_meta`. A `String` is returned that can be copy-pasted into the `Meta` folder, and then edited. Ensure all meta fields are accurate and complete. -* For problem implementation in both ADNLP and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. +* A first version of the `meta` can be generated using `generate_meta`. A `String` is returned that can be copy-pasted into the `Meta` folder, and then edited. ```julia using ADNLPModels, Distributed, NLPModels, NLPModelsJuMP, OptimizationProblems, Test include("test/utils.jl") @@ -32,11 +32,6 @@ The documentation should be added to the file in the `PureJuMP` folder. create_meta_files(String["catmix", "gasoil", "glider", "methanol", "pinene", "rocket", "steering"]) ``` -* Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API -and should support the `nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. -* For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free with the objectives agree (or differ by a factor of 2 for LS). -* For variable-size problems, verify that different values of `n` produce correct `nvar`, meta formulas predict actual values and instantiation works at various sizes. - ## Templates for the new functions In order to standardize the new functions, we offer here a template for both AD and JuMP models. @@ -74,3 +69,41 @@ function function_name(; n::Int = default_nvar, type::Type{T} = Float64, kwargs. return nlp end ``` + +## Validating new problems + +* Ensure all meta fields are accurate and complete. +* For problem implementation in both ADNLP and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. +* The objective of implementations must be callable at the starting point and should not return NaN unless expected. +* Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API +and should support the `nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. +* For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free with the objectives agree (or differ by a factor of 2 for LS). +* For variable-size problems, verify that different values of `n` produce correct `nvar`, meta formulas predict actual values and instantiation works at various sizes. + +## Reviewer Checklist for New Problems + +**Meta** +- [ ] Every new problem (ADNLP or PureJuMP) is registered in Meta, with all fields (origin, objtype, contype, bounds, best-known, etc.) filled correctly. +- [ ] Meta formulas for variable sizes match actual model behavior. + +**Definition** +- [ ] No extra or spurious exports are introduced. +- [ ] Model name matches the file and function name. + +**Implementation** +- [ ] Objective and constraint values agree within tolerance at test points. +- [ ] Number of variables and constraints match. + +**Sanity & Robustness** +- [ ] Objective is callable at the starting point and does not return NaN (unless documented). +- [ ] Model instantiates without error for all supported types (Float32, Float64). +- [ ] For scalable problems, changing n updates nvar and all related meta fields. + +**Least-Squares & In-Place APIs** +- [ ] If least-squares, ADNLP constructor supports `nls=true/false` for both ADNLPModel and ADNLSModel. +- [ ] In-place nonlinear constraint evaluation (`nln!`) and least-squares residuals (`residual!`) are allocation-free. +- [ ] For least-squares, objectives for NLP and NLS agree (or differ by a factor of 2, as appropriate). + +**Zero-Allocation & Performance** +- [ ] All in-place APIs (constraints, residuals) are allocation-free (Julia ≥ 1.7). +- [ ] No unnecessary allocations in tight loops or callbacks. From ca197e521c1909065eafaf5705dad13ce39111ad Mon Sep 17 00:00:00 2001 From: Arnav Kapoor Date: Tue, 31 Mar 2026 02:06:46 +0530 Subject: [PATCH 07/14] Update contributing.md --- docs/src/contributing.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index c51ee63c..6d09078e 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -24,6 +24,7 @@ In both cases, the function must have the same name `problem_name` as the file. The documentation should be added to the file in the `PureJuMP` folder. * New problems can be scalable, see [ADNLPProblems/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl) and [PureJuMP/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/PureJuMP/arglina.jl) for examples. In that case, the first keyword parameter should be the number of variables `n::Int` and have the default value `default_nvar` (constant predefined in the module). If your problem has restrictions on the number of variables, e.g., `n` should be odd, or `n` should have the form `4k + 3`, then, instead of throwing errors when the restrictions are not satisfied, you should instead use the number of variables to be as close to `n` as possible. For example, if you want `n` odd and `n = 100` is passed, you can internally convert to `n = 99`. If you want `n = 4k + 3`, and `n = 100` is passed, then compute `k = round(Int, (n - 3) / 4)` and update `n`. * A first version of the `meta` can be generated using `generate_meta`. A `String` is returned that can be copy-pasted into the `Meta` folder, and then edited. + ```julia using ADNLPModels, Distributed, NLPModels, NLPModelsJuMP, OptimizationProblems, Test include("test/utils.jl") @@ -32,6 +33,8 @@ The documentation should be added to the file in the `PureJuMP` folder. create_meta_files(String["catmix", "gasoil", "glider", "methanol", "pinene", "rocket", "steering"]) ``` +* Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API + ## Templates for the new functions In order to standardize the new functions, we offer here a template for both AD and JuMP models. @@ -75,8 +78,7 @@ end * Ensure all meta fields are accurate and complete. * For problem implementation in both ADNLP and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. * The objective of implementations must be callable at the starting point and should not return NaN unless expected. -* Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API -and should support the `nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. +* Problems modeled with `ADNLPModels` should support the `nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. * For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free with the objectives agree (or differ by a factor of 2 for LS). * For variable-size problems, verify that different values of `n` produce correct `nvar`, meta formulas predict actual values and instantiation works at various sizes. From 6a204aba35eaafe77c37e6c202c8a9d0e244b263 Mon Sep 17 00:00:00 2001 From: Arnav Kapoor Date: Tue, 31 Mar 2026 02:08:09 +0530 Subject: [PATCH 08/14] Fix punctuation and formatting in contributing.md Corrected punctuation and formatting in the contributing guidelines. --- docs/src/contributing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index 6d09078e..0b799a5f 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -33,7 +33,7 @@ The documentation should be added to the file in the `PureJuMP` folder. create_meta_files(String["catmix", "gasoil", "glider", "methanol", "pinene", "rocket", "steering"]) ``` -* Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API +* Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API. ## Templates for the new functions @@ -96,7 +96,7 @@ end - [ ] Objective and constraint values agree within tolerance at test points. - [ ] Number of variables and constraints match. -**Sanity & Robustness** +**Sanity** - [ ] Objective is callable at the starting point and does not return NaN (unless documented). - [ ] Model instantiates without error for all supported types (Float32, Float64). - [ ] For scalable problems, changing n updates nvar and all related meta fields. @@ -106,6 +106,6 @@ end - [ ] In-place nonlinear constraint evaluation (`nln!`) and least-squares residuals (`residual!`) are allocation-free. - [ ] For least-squares, objectives for NLP and NLS agree (or differ by a factor of 2, as appropriate). -**Zero-Allocation & Performance** +**Zero-Allocation** - [ ] All in-place APIs (constraints, residuals) are allocation-free (Julia ≥ 1.7). - [ ] No unnecessary allocations in tight loops or callbacks. From b2d09845638b96c6591586187aac9dce0599dbf7 Mon Sep 17 00:00:00 2001 From: Arnav Kapoor Date: Wed, 1 Apr 2026 15:50:05 +0530 Subject: [PATCH 09/14] Apply suggestions from code review Co-authored-by: Tangi Migot --- docs/src/contributing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index 0b799a5f..ee3068a6 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -76,8 +76,8 @@ end ## Validating new problems * Ensure all meta fields are accurate and complete. -* For problem implementation in both ADNLP and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. -* The objective of implementations must be callable at the starting point and should not return NaN unless expected. +* For problem implementation in both ADNLPProblems and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. +* The objective of implementations must be callable at the starting point. * Problems modeled with `ADNLPModels` should support the `nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. * For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free with the objectives agree (or differ by a factor of 2 for LS). * For variable-size problems, verify that different values of `n` produce correct `nvar`, meta formulas predict actual values and instantiation works at various sizes. @@ -107,5 +107,5 @@ end - [ ] For least-squares, objectives for NLP and NLS agree (or differ by a factor of 2, as appropriate). **Zero-Allocation** -- [ ] All in-place APIs (constraints, residuals) are allocation-free (Julia ≥ 1.7). +- [ ] All in-place APIs (constraints, residuals) are allocation-free. - [ ] No unnecessary allocations in tight loops or callbacks. From ddbfd6e8ceec28819afaea7ff88ba87a0e2d5cd8 Mon Sep 17 00:00:00 2001 From: Arnav Kapoor Date: Fri, 3 Apr 2026 02:05:30 +0530 Subject: [PATCH 10/14] Enhance contributing.md with NLS problem guidelines Added guidelines for handling Nonlinear Least Squares (NLS) problems in contributing documentation. --- docs/src/contributing.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index ee3068a6..806d45cc 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -82,6 +82,23 @@ end * For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free with the objectives agree (or differ by a factor of 2 for LS). * For variable-size problems, verify that different values of `n` produce correct `nvar`, meta formulas predict actual values and instantiation works at various sizes. +### Nonlinear Least Squares (NLS) Problems + +If your problem is a nonlinear least squares (NLS), please follow these guidelines: +* Use `ADNLSModels` for the ADNLPProblems implementation (see [ADNLPModels.jl](https://github.com/JuliaSmoothOptimizers/ADNLPModels.jl)). +* Set the `:objtype` entry in the meta file to `:least_squares`. +* Add a getter for the number of NLS equations, named `get_problemname_nls_nequ`. +* In the `PureJuMP` file, clearly document that the problem is a nonlinear least squares (NLS) problem and explain how users can construct both the standard and NLS variants. +* Explicitly state that the NLS variant can be accessed by passing the keyword argument `use_nls=true` when constructing the problem, e.g.: + ```julia + # Standard model (ADNLPModel) + myprob_nlp = myprob() + # Least-squares model (ADNLSModel) + myprob_nls = myprob(use_nls=true) + ``` +* Make sure this information is also reflected in the meta file, so users and tools can easily discover the NLS capability. +See existing NLS problems (e.g., [`lanczos1`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/lanczos1.jl), [`lanczos2`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/lanczos2.jl), [`brownal`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/brownal.jl)) for templates. + ## Reviewer Checklist for New Problems **Meta** From 5e11b7a5f2ab9abdd802f2111a3f96c2feb538b0 Mon Sep 17 00:00:00 2001 From: Arnav Kapoor Date: Fri, 3 Apr 2026 02:06:14 +0530 Subject: [PATCH 11/14] Apply suggestions from code review Co-authored-by: Tangi Migot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/src/contributing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index 806d45cc..75ac34ff 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -79,7 +79,7 @@ end * For problem implementation in both ADNLPProblems and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. * The objective of implementations must be callable at the starting point. * Problems modeled with `ADNLPModels` should support the `nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. -* For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free with the objectives agree (or differ by a factor of 2 for LS). +* For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free and that the objectives agree (or differ by a factor of 2 for LS). * For variable-size problems, verify that different values of `n` produce correct `nvar`, meta formulas predict actual values and instantiation works at various sizes. ### Nonlinear Least Squares (NLS) Problems @@ -115,12 +115,12 @@ See existing NLS problems (e.g., [`lanczos1`](https://github.com/JuliaSmoothOpti **Sanity** - [ ] Objective is callable at the starting point and does not return NaN (unless documented). -- [ ] Model instantiates without error for all supported types (Float32, Float64). +- [ ] Model instantiates without error for different types, e.g. Float32 and Float64. - [ ] For scalable problems, changing n updates nvar and all related meta fields. **Least-Squares & In-Place APIs** - [ ] If least-squares, ADNLP constructor supports `nls=true/false` for both ADNLPModel and ADNLSModel. -- [ ] In-place nonlinear constraint evaluation (`nln!`) and least-squares residuals (`residual!`) are allocation-free. +- [ ] In-place nonlinear constraint evaluation (`cons_nln!(nlp, x, cx)`) and least-squares residuals (`residual!`) are allocation-free. - [ ] For least-squares, objectives for NLP and NLS agree (or differ by a factor of 2, as appropriate). **Zero-Allocation** From a72b9f26117d044c0144b8dafadefbebcd170a40 Mon Sep 17 00:00:00 2001 From: arnavk23 Date: Fri, 3 Apr 2026 02:28:31 +0530 Subject: [PATCH 12/14] addressing review comments --- docs/src/contributing.md | 50 ++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index 75ac34ff..59cbae10 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -34,6 +34,7 @@ The documentation should be added to the file in the `PureJuMP` folder. ``` * Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API. +* In particular, the initial point `x0` should be a `Vector{T}`, the objective evaluation should return values of type `T`, and the `name` keyword should be passed to `ADNLPModel`/`ADNLSModel` with a meaningful problem name. ## Templates for the new functions @@ -68,6 +69,7 @@ export function_name function function_name(; n::Int = default_nvar, type::Type{T} = Float64, kwargs...) where {T} # define f # define x0 + # ensure x0 isa Vector{T} and f(x) returns T # nlp = ADNLPModels.ADNLPModel(f, x0, name = "function_name"; kwargs...) return nlp end @@ -76,11 +78,31 @@ end ## Validating new problems * Ensure all meta fields are accurate and complete. -* For problem implementation in both ADNLPProblems and PureJuMP, use the same initial point, variable bounds, constraint bounds and ensure objective and constraint values match within a relative tolerance. +* For implementations in both `ADNLPProblems` and `PureJuMP`, use the same initial point, variable bounds, constraint bounds and explicitly compare the two models to ensure objective and constraint values match within a relative tolerance. * The objective of implementations must be callable at the starting point. -* Problems modeled with `ADNLPModels` should support the `nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. +* For `ADNLPModels` problems, the objective should return values of type `T` from `type::Type{T}` and the initial point should be typed consistently (`x0::Vector{T}`). +* Pass a meaningful `name` keyword to `ADNLPModel`/`ADNLSModel` constructors (typically matching the problem/function name). +* For least-squares problems, support the `use_nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. * For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free and that the objectives agree (or differ by a factor of 2 for LS). -* For variable-size problems, verify that different values of `n` produce correct `nvar`, meta formulas predict actual values and instantiation works at various sizes. +* For constrained problems, ensure in-place constraint evaluations (e.g., `cons_nln!`) are allocation-free. +* Objective evaluations should have minimal allocations (preferably zero allocations in hot paths). +* For variable-size problems, validate at multiple sizes (for example `n = 5`, `n = default_nvar`, and a larger `n`) and check all of the following: + - model instantiation succeeds for each tested `n`; + - effective `nvar` matches the intended rule (including any internal adjustment such as odd `n` or `4k + 3` constraints); + - metadata formulas (`nvar`, `nnzh`, `nnzj`, etc.) match the instantiated model values. + +Optional (recommended): provide a local solver sanity check showing that a standard solver can solve the model from the provided starting point. This is not a hard requirement for CI or review. + +```julia +using OptimizationProblems, OptimizationProblems.ADNLPProblems +using NLPModelsIpopt + +nlp = problem_name() +stats = ipopt(nlp) +stats.status +``` + +For least-squares problems, you may also run the same check with `problem_name(use_nls=true)`. ### Nonlinear Least Squares (NLS) Problems @@ -101,28 +123,36 @@ See existing NLS problems (e.g., [`lanczos1`](https://github.com/JuliaSmoothOpti ## Reviewer Checklist for New Problems +- [ ] First check: the problem is added in exactly these three files with the same base name: `src/ADNLPProblems/problem_name.jl`, `src/PureJuMP/problem_name.jl`, and `src/Meta/problem_name.jl`. + Example: [`arglina` in ADNLPProblems](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl), [`arglina` in PureJuMP](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/PureJuMP/arglina.jl), and [`arglina` in Meta](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/Meta/arglina.jl). + **Meta** -- [ ] Every new problem (ADNLP or PureJuMP) is registered in Meta, with all fields (origin, objtype, contype, bounds, best-known, etc.) filled correctly. +- [ ] The corresponding meta file exists (`src/Meta/problem_name.jl`), the problem name matches the AD and JuMP files, and `OptimizationProblems.meta` contains the problem entry. +- [ ] All meta fields (origin, objtype, contype, bounds, best-known, etc.) are filled correctly. - [ ] Meta formulas for variable sizes match actual model behavior. **Definition** - [ ] No extra or spurious exports are introduced. - [ ] Model name matches the file and function name. +- [ ] The implemented objective, constraints, and bounds match the mathematical problem definition from the cited reference/documentation. **Implementation** -- [ ] Objective and constraint values agree within tolerance at test points. +- [ ] Objective and constraint values agree (ADNLPProblems vs PureJuMP) within tolerance at test points. - [ ] Number of variables and constraints match. +- [ ] For `type::Type{T}`, `x0 isa Vector{T}` and objective values are of type `T`. +- [ ] `ADNLPModel`/`ADNLSModel` constructors receive a meaningful `name` keyword. **Sanity** - [ ] Objective is callable at the starting point and does not return NaN (unless documented). - [ ] Model instantiates without error for different types, e.g. Float32 and Float64. -- [ ] For scalable problems, changing n updates nvar and all related meta fields. +- [ ] For scalable problems, changing `n` updates `nvar` and all related meta fields, and the effective number of variables remains as close as possible to the requested `n` when internal adjustments are required. + +**Zero-Allocation** +- [ ] All in-place APIs (constraints, residuals) are allocation-free. +- [ ] No unnecessary allocations in tight loops or callbacks. +- [ ] Objective evaluation has minimal allocations (ideally allocation-free in performance-critical paths). **Least-Squares & In-Place APIs** - [ ] If least-squares, ADNLP constructor supports `nls=true/false` for both ADNLPModel and ADNLSModel. - [ ] In-place nonlinear constraint evaluation (`cons_nln!(nlp, x, cx)`) and least-squares residuals (`residual!`) are allocation-free. - [ ] For least-squares, objectives for NLP and NLS agree (or differ by a factor of 2, as appropriate). - -**Zero-Allocation** -- [ ] All in-place APIs (constraints, residuals) are allocation-free. -- [ ] No unnecessary allocations in tight loops or callbacks. From 29d50d445e57e26f6e9f2f32b75909edc927e9f8 Mon Sep 17 00:00:00 2001 From: Arnav Kapoor Date: Mon, 6 Apr 2026 20:03:35 +0530 Subject: [PATCH 13/14] Apply suggestions from code review Co-authored-by: Tangi Migot --- docs/src/contributing.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index 59cbae10..6a67af56 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -67,9 +67,8 @@ Next, we describe the `ADNLPProblems` file `function_name.jl`. export function_name function function_name(; n::Int = default_nvar, type::Type{T} = Float64, kwargs...) where {T} - # define f - # define x0 - # ensure x0 isa Vector{T} and f(x) returns T + # define f (ensure f(x0) is of type T) + # define x0 (ensure x0 isa Vector{T}) # nlp = ADNLPModels.ADNLPModel(f, x0, name = "function_name"; kwargs...) return nlp end @@ -78,20 +77,19 @@ end ## Validating new problems * Ensure all meta fields are accurate and complete. -* For implementations in both `ADNLPProblems` and `PureJuMP`, use the same initial point, variable bounds, constraint bounds and explicitly compare the two models to ensure objective and constraint values match within a relative tolerance. -* The objective of implementations must be callable at the starting point. +* Implementations in `ADNLPProblems` and `PureJuMP` must use the same initial point, variable bounds, constraint bounds. The two models must have matching objective and constraint values match (within a relative tolerance). +* The implemented objective function must be callable at the starting point. * For `ADNLPModels` problems, the objective should return values of type `T` from `type::Type{T}` and the initial point should be typed consistently (`x0::Vector{T}`). -* Pass a meaningful `name` keyword to `ADNLPModel`/`ADNLSModel` constructors (typically matching the problem/function name). +* Pass a meaningful `name` keyword to `ADNLPModel` constructors (typically matching the problem/function name). * For least-squares problems, support the `use_nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. * For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free and that the objectives agree (or differ by a factor of 2 for LS). * For constrained problems, ensure in-place constraint evaluations (e.g., `cons_nln!`) are allocation-free. -* Objective evaluations should have minimal allocations (preferably zero allocations in hot paths). +* Objective function evaluations should have minimal allocations. * For variable-size problems, validate at multiple sizes (for example `n = 5`, `n = default_nvar`, and a larger `n`) and check all of the following: - model instantiation succeeds for each tested `n`; - effective `nvar` matches the intended rule (including any internal adjustment such as odd `n` or `4k + 3` constraints); - metadata formulas (`nvar`, `nnzh`, `nnzj`, etc.) match the instantiated model values. - -Optional (recommended): provide a local solver sanity check showing that a standard solver can solve the model from the provided starting point. This is not a hard requirement for CI or review. +* Optional (recommended): provide a local solver sanity check showing that a standard solver can solve the model from the provided starting point. This is not a hard requirement for CI or review. ```julia using OptimizationProblems, OptimizationProblems.ADNLPProblems From 9b3140571e83dacc96646a0252f41b8da2bcb849 Mon Sep 17 00:00:00 2001 From: arnavk23 Date: Tue, 7 Apr 2026 02:30:20 +0530 Subject: [PATCH 14/14] addressing review comments --- docs/src/contributing.md | 41 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/docs/src/contributing.md b/docs/src/contributing.md index 6a67af56..8d0a2ba5 100644 --- a/docs/src/contributing.md +++ b/docs/src/contributing.md @@ -20,9 +20,10 @@ Here is a to-do list, to help you add new problems: - `src/PureJuMP/problem_name.jl` - `src/Meta/problem_name.jl` In both cases, the function must have the same name `problem_name` as the file. +The function should be exported from `src/ADNLPProblems/problem_name.jl` and `src/PureJuMP/problem_name.jl`. Do not add exports in `src/Meta/problem_name.jl`. * When submitting a problem, please pay particular attention to the documentation. We would like to gather as much information as possible on the provenance of problems, other problem sets where the problems are present, and general information on the problem. The documentation should be added to the file in the `PureJuMP` folder. -* New problems can be scalable, see [ADNLPProblems/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl) and [PureJuMP/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/PureJuMP/arglina.jl) for examples. In that case, the first keyword parameter should be the number of variables `n::Int` and have the default value `default_nvar` (constant predefined in the module). If your problem has restrictions on the number of variables, e.g., `n` should be odd, or `n` should have the form `4k + 3`, then, instead of throwing errors when the restrictions are not satisfied, you should instead use the number of variables to be as close to `n` as possible. For example, if you want `n` odd and `n = 100` is passed, you can internally convert to `n = 99`. If you want `n = 4k + 3`, and `n = 100` is passed, then compute `k = round(Int, (n - 3) / 4)` and update `n`. +* New problems can be scalable, see [ADNLPProblems/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl) and [PureJuMP/arglina.jl](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/PureJuMP/arglina.jl) for examples. In that case, the first keyword parameter should be the number of variables `n::Int` and have the default value `default_nvar` (constant predefined in the module). If your problem has restrictions on the number of variables, e.g., `n` should be odd, or `n` should have the form `4k + 3`, then, instead of throwing errors when the restrictions are not satisfied, you should instead use the number of variables to be as close to `n` as possible. For example, if you want `n` odd and `n = 100` is passed, you can internally convert to `n = 99`. If you want `n = 4k + 3`, and `n = 100` is passed, then compute `k = round(Int, (n - 3) / 4)` and update `n`. When such an internal adjustment is made, emit a warning indicating the requested `n` and the effective value used. * A first version of the `meta` can be generated using `generate_meta`. A `String` is returned that can be copy-pasted into the `Meta` folder, and then edited. ```julia @@ -34,7 +35,7 @@ The documentation should be added to the file in the `PureJuMP` folder. ``` * Problems modeled with `ADNLPModels` should be type-stable, i.e. they should all have keyword argument `type::Type{T} = Float64` where `T` is the type of the initial guess and the type used by the `NLPModel` API. -* In particular, the initial point `x0` should be a `Vector{T}`, the objective evaluation should return values of type `T`, and the `name` keyword should be passed to `ADNLPModel`/`ADNLSModel` with a meaningful problem name. +* In particular, the initial point `x0` should be a `Vector{T}`, and the `name` keyword should be passed to `ADNLPModel`/`ADNLSModel` with a meaningful problem name. ## Templates for the new functions @@ -76,20 +77,19 @@ end ## Validating new problems -* Ensure all meta fields are accurate and complete. -* Implementations in `ADNLPProblems` and `PureJuMP` must use the same initial point, variable bounds, constraint bounds. The two models must have matching objective and constraint values match (within a relative tolerance). -* The implemented objective function must be callable at the starting point. -* For `ADNLPModels` problems, the objective should return values of type `T` from `type::Type{T}` and the initial point should be typed consistently (`x0::Vector{T}`). -* Pass a meaningful `name` keyword to `ADNLPModel` constructors (typically matching the problem/function name). -* For least-squares problems, support the `use_nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. -* For least-squares problems, instantiate both `ADNLPModel` and `ADNLSModel` and ensure `residual!(nls, x, Fx)` is allocation-free and that the objectives agree (or differ by a factor of 2 for LS). -* For constrained problems, ensure in-place constraint evaluations (e.g., `cons_nln!`) are allocation-free. -* Objective function evaluations should have minimal allocations. -* For variable-size problems, validate at multiple sizes (for example `n = 5`, `n = default_nvar`, and a larger `n`) and check all of the following: +* Ensure all meta fields are accurate and complete, e.g. `:origin`, `:objtype`, and `:name` in [`src/Meta/arglina.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/Meta/arglina.jl). +* Implementations in `ADNLPProblems` and `PureJuMP` must use the same initial point, variable bounds, and constraint bounds; compare `arglina` in [`src/ADNLPProblems/arglina.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl) and [`src/PureJuMP/arglina.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/PureJuMP/arglina.jl). +* The implemented objective function must be callable at the starting point, e.g. `obj(nlp, nlp.meta.x0)` in [`src/ADNLPProblems/lanczos1.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/lanczos1.jl). +* For `ADNLPModels` problems, the objective should return values of type `T` from `type::Type{T}` and the initial point should be typed consistently (`x0::Vector{T}`), for example `Float32` in [`src/ADNLPProblems/brownal.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/brownal.jl). +* Pass a meaningful `name` keyword to `ADNLPModel` constructors, for example `name = "arglina"` in [`src/ADNLPProblems/arglina.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl). +* For constrained problems, ensure in-place constraint evaluations (e.g., `cons_nln!`) are allocation-free, for example the checks in [`test/test-utils.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/test/test-utils.jl). +* Objective function evaluations should have minimal allocations, for example `@allocated obj(nlp, x0)` in the same test style used by [`test/test-utils.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/test/test-utils.jl). +* For variable-size problems, validate at multiple sizes (for example `n = 5`, `n = default_nvar`, and a larger `n`) and check all of the following, e.g. [`arglina`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/arglina.jl) and [`test/test-scalable.jl`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/test/test-scalable.jl): - model instantiation succeeds for each tested `n`; - effective `nvar` matches the intended rule (including any internal adjustment such as odd `n` or `4k + 3` constraints); + - if `n` is internally adjusted, the effective value is the closest feasible one to the requested `n`, and a warning is emitted; - metadata formulas (`nvar`, `nnzh`, `nnzj`, etc.) match the instantiated model values. -* Optional (recommended): provide a local solver sanity check showing that a standard solver can solve the model from the provided starting point. This is not a hard requirement for CI or review. +* Optional (recommended): provide a local solver sanity check showing that a standard solver can solve the model from the provided starting point, e.g. `ipopt(arglina())` or `ipopt(lanczos1())`. ```julia using OptimizationProblems, OptimizationProblems.ADNLPProblems @@ -105,18 +105,15 @@ For least-squares problems, you may also run the same check with `problem_name(u ### Nonlinear Least Squares (NLS) Problems If your problem is a nonlinear least squares (NLS), please follow these guidelines: -* Use `ADNLSModels` for the ADNLPProblems implementation (see [ADNLPModels.jl](https://github.com/JuliaSmoothOptimizers/ADNLPModels.jl)). +* Use `ADNLSModels` for the ADNLPProblems implementation (see [ADNLPModels.jl documentation](https://jso.dev/ADNLPModels.jl/stable/)). * Set the `:objtype` entry in the meta file to `:least_squares`. * Add a getter for the number of NLS equations, named `get_problemname_nls_nequ`. +* Support the `use_nls=true/false` keyword to allow both `ADNLPModel` and `ADNLSModel` instantiation from the same problem. +* Instantiate both `ADNLPModel` and `ADNLSModel`, ensure `residual!(nls, x, Fx)` is allocation-free, and check that objectives agree (or differ by a factor of 2 for LS). * In the `PureJuMP` file, clearly document that the problem is a nonlinear least squares (NLS) problem and explain how users can construct both the standard and NLS variants. -* Explicitly state that the NLS variant can be accessed by passing the keyword argument `use_nls=true` when constructing the problem, e.g.: - ```julia - # Standard model (ADNLPModel) - myprob_nlp = myprob() - # Least-squares model (ADNLSModel) - myprob_nls = myprob(use_nls=true) - ``` +* Explicitly state that the NLS variant can be accessed by passing the keyword argument `use_nls=true` when constructing the problem. * Make sure this information is also reflected in the meta file, so users and tools can easily discover the NLS capability. +* In validation, also run the local solver sanity check with `problem_name(use_nls=true)`. See existing NLS problems (e.g., [`lanczos1`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/lanczos1.jl), [`lanczos2`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/lanczos2.jl), [`brownal`](https://github.com/JuliaSmoothOptimizers/OptimizationProblems.jl/blob/main/src/ADNLPProblems/brownal.jl)) for templates. ## Reviewer Checklist for New Problems @@ -127,10 +124,12 @@ See existing NLS problems (e.g., [`lanczos1`](https://github.com/JuliaSmoothOpti **Meta** - [ ] The corresponding meta file exists (`src/Meta/problem_name.jl`), the problem name matches the AD and JuMP files, and `OptimizationProblems.meta` contains the problem entry. - [ ] All meta fields (origin, objtype, contype, bounds, best-known, etc.) are filled correctly. +- [ ] The problem origin/provenance is clearly documented and consistent between the `PureJuMP` problem documentation and the `:origin` meta entry. - [ ] Meta formulas for variable sizes match actual model behavior. **Definition** - [ ] No extra or spurious exports are introduced. +- [ ] The problem function is exported in `src/ADNLPProblems/problem_name.jl` and `src/PureJuMP/problem_name.jl`, and not exported in `src/Meta/problem_name.jl`. - [ ] Model name matches the file and function name. - [ ] The implemented objective, constraints, and bounds match the mathematical problem definition from the cited reference/documentation.