Skip to content

Commit fb4953f

Browse files
arnavk23tmigotdpo
authored
Add ipopt method for AbstractNLSModel (#132)
* Add ipopt method for AbstractNLSModel - Implement ipopt(nls::AbstractNLSModel) as requested in issue #131 - Add FeasibilityFormNLS function to convert NLS models for optimization - Add comprehensive tests for AbstractNLSModel support - Export FeasibilityFormNLS function for user access Resolves #131 * Use FeasibilityFormNLS from NLPModelsModifiers.jl - Remove local FeasibilityFormNLS implementation - Import FeasibilityFormNLS from NLPModelsModifiers package - Update tests to work with the external implementation - Add NLPModelsModifiers to dependencies * Update test/runtests.jl Co-authored-by: Tangi Migot <[email protected]> * Update src/NLPModelsIpopt.jl Co-authored-by: Tangi Migot <[email protected]> * Update src/NLPModelsIpopt.jl Co-authored-by: Dominique <[email protected]> * Make tests robust to solver variations, fix syntax errors, and ensure all tests pass * Update NLPModelsIpopt.jl * Update src/NLPModelsIpopt.jl Co-authored-by: Dominique <[email protected]> * Update src/NLPModelsIpopt.jl Co-authored-by: Dominique <[email protected]> * Update src/NLPModelsIpopt.jl Co-authored-by: Dominique <[email protected]> * Update src/NLPModelsIpopt.jl Co-authored-by: Dominique <[email protected]> * Update Project.toml Co-authored-by: Tangi Migot <[email protected]> * Update test/runtests.jl Co-authored-by: Tangi Migot <[email protected]> * changes * stats * Changes made according to @tmigot * passing failing FreeBSD check * Update Project.toml Co-authored-by: Tangi Migot <[email protected]> * Update test/runtests.jl Co-authored-by: Tangi Migot <[email protected]> * Update test/runtests.jl Co-authored-by: Tangi Migot <[email protected]> * Update test/runtests.jl Co-authored-by: Tangi Migot <[email protected]> * Update test/runtests.jl Co-authored-by: Tangi Migot <[email protected]> * Update test/runtests.jl * Update test/runtests.jl --------- Co-authored-by: Tangi Migot <[email protected]> Co-authored-by: Dominique <[email protected]>
1 parent d181d04 commit fb4953f

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ version = "0.10.4"
55
[deps]
66
Ipopt = "b6b21f68-93f8-5de0-b562-5493be1d77c9"
77
NLPModels = "a4795742-8479-5a88-8948-cc11e1c8c1a6"
8+
NLPModelsModifiers = "e01155f1-5c6f-4375-a9d8-616dd036575f"
89
SolverCore = "ff4d7338-4cf1-434d-91df-b86cb86fb843"
910

1011
[compat]
1112
Ipopt = "1"
12-
NLPModels = "0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21"
13+
NLPModels = "0.19, 0.20, 0.21"
14+
NLPModelsModifiers = "0.7"
1315
SolverCore = "0.3"
1416
julia = "^1.6"
1517

src/NLPModelsIpopt.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module NLPModelsIpopt
33
export ipopt, IpoptSolver, reset!, solve!
44

55
using NLPModels, Ipopt, SolverCore
6+
using NLPModelsModifiers: FeasibilityFormNLS
67

78
const ipopt_statuses = Dict(
89
0 => :first_order,
@@ -181,6 +182,44 @@ function ipopt(nlp::AbstractNLPModel; kwargs...)
181182
return solve!(solver, nlp, stats; kwargs...)
182183
end
183184

185+
"""
186+
ipopt(nls::AbstractNLSModel; kwargs...)
187+
188+
Solve the least-squares problem `nls` using `IPOPT` by moving the nonlinear residual to the constraints.
189+
190+
# Arguments
191+
- `nls::AbstractNLSModel`: The least-squares problem to solve.
192+
193+
For advanced usage, first define an `IpoptSolver` to preallocate the memory used in the algorithm, and then call `solve!`:
194+
solver = IpoptSolver(nls)
195+
solve!(solver, nls; kwargs...)
196+
197+
# Examples
198+
```julia
199+
using NLPModelsIpopt, ADNLPModels
200+
nls = ADNLSModel(x -> [x[1] - 1, x[2] - 2], [0.0, 0.0], 2)
201+
stats = ipopt(nls, print_level = 0)
202+
```
203+
"""
204+
function ipopt(ff_nls::FeasibilityFormNLS; kwargs...)
205+
solver = IpoptSolver(ff_nls)
206+
stats = GenericExecutionStats(ff_nls)
207+
stats = solve!(solver, ff_nls, stats; kwargs...)
208+
209+
return stats
210+
end
211+
212+
function ipopt(nls::AbstractNLSModel; kwargs...)
213+
ff_nls = FeasibilityFormNLS(nls)
214+
stats = ipopt(ff_nls; kwargs...)
215+
216+
stats.solution = length(stats.solution) >= nls.meta.nvar ? stats.solution[1:nls.meta.nvar] : stats.solution
217+
stats.multipliers_L = length(stats.multipliers_L) >= nls.meta.nvar ? stats.multipliers_L[1:nls.meta.nvar] : stats.multipliers_L
218+
stats.multipliers_U = length(stats.multipliers_U) >= nls.meta.nvar ? stats.multipliers_U[1:nls.meta.nvar] : stats.multipliers_U
219+
stats.multipliers = length(stats.multipliers) >= nls.meta.ncon ? stats.multipliers[end-nls.meta.ncon+1:end] : stats.multipliers
220+
return stats
221+
end
222+
184223
function SolverCore.solve!(
185224
solver::IpoptSolver,
186225
nlp::AbstractNLPModel,

test/runtests.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using ADNLPModels, NLPModelsIpopt, NLPModels, Ipopt, SolverCore, Test
2+
using NLPModelsModifiers: FeasibilityFormNLS
23

34
@testset "Restart NLPModelsIpopt" begin
45
nlp = ADNLPModel(x -> (x[1] - 1)^2 + 100 * (x[2] - x[1]^2)^2, [-1.2; 1.0])
@@ -107,3 +108,12 @@ end
107108
@test stats.primal_feas 0.0
108109
@test stats.dual_feas 0.0 atol = 1.49e-8
109110
end
111+
112+
@testset "ipopt with AbstractNLSModel" begin
113+
nls = ADNLSModel(x -> [x[1] - 1, x[2] - 2], [0.0, 0.0], 2)
114+
stats = ipopt(nls, print_level = 0)
115+
@test isapprox(stats.solution, [1.0, 2.0], rtol = 1e-6)
116+
@test stats.status == :first_order
117+
@test stats.iter >= 0
118+
@test isapprox(stats.dual_feas, 0.0; atol=1e-8)
119+
end

0 commit comments

Comments
 (0)