@@ -2,6 +2,42 @@ export cons_coord, cons_coord!, consjac
22
33using NLPModels, SparseArrays
44
5+ # Type conversion helpers for Issue #392: Preallocate more vectors
6+ """
7+ prepare_input!(workspace::Vector{T}, x::AbstractVector{S}) where {T, S}
8+
9+ Prepare input vector `x` for use with CUTEst functions, using preallocated workspace
10+ to avoid allocations when type conversion is needed.
11+
12+ Returns the input vector directly if no conversion is needed, or the workspace vector
13+ with converted values if type conversion is required.
14+ """
15+ @inline function prepare_input! (workspace:: Vector{T} , x:: AbstractVector{S} ) where {T, S}
16+ if S === T && typeof (x) <: Vector{T}
17+ return x # No conversion needed
18+ else
19+ resize! (workspace, length (x))
20+ workspace .= x
21+ return workspace
22+ end
23+ end
24+
25+ """
26+ prepare_output!(workspace::Vector{T}, target::AbstractVector{S}, source::AbstractVector{T}) where {T, S}
27+
28+ Prepare output by copying from source to target, using workspace for type conversion if needed.
29+ """
30+ @inline function prepare_output! (workspace:: Vector{T} , target:: AbstractVector{S} , source:: AbstractVector{T} ) where {T, S}
31+ if S === T && typeof (target) <: Vector{T}
32+ target .= source
33+ else
34+ resize! (workspace, length (source))
35+ workspace .= source
36+ target .= workspace
37+ end
38+ return target
39+ end
40+
541function NLPModels. obj (nlp:: CUTEstModel{T} , x:: StrideOneVector{T} ) where {T}
642 @lencheck nlp. meta. nvar x
743 if nlp. meta. ncon > 0
4076
4177function NLPModels. grad! (nlp:: CUTEstModel{T} , x:: AbstractVector , g:: AbstractVector ) where {T}
4278 @lencheck nlp. meta. nvar x g
43- x_ = Vector {T} (x)
44- g_ = Vector {T} (g)
45- grad! (nlp, x_, g_)
46- g .= g_
79+
80+ # Use type conversion helpers to avoid allocations (Issue #392)
81+ x_prepared = prepare_input! (nlp. input_workspace, x)
82+
83+ if typeof (g) <: Vector{T}
84+ grad! (nlp, x_prepared, g)
85+ else
86+ resize! (nlp. output_workspace, length (g))
87+ grad! (nlp, x_prepared, view (nlp. output_workspace, 1 : length (g)))
88+ g .= view (nlp. output_workspace, 1 : length (g))
89+ end
4790end
4891
4992function NLPModels. objcons! (
@@ -105,13 +148,15 @@ end
105148
106149function NLPModels. objgrad! (nlp:: CUTEstModel{T} , x:: AbstractVector , g:: StrideOneVector{T} ) where {T}
107150 @lencheck nlp. meta. nvar x g
108- objgrad! (nlp, Vector {T} (x), g)
151+ x_prepared = prepare_input! (nlp. input_workspace, x)
152+ objgrad! (nlp, x_prepared, g)
109153end
110154
111155function NLPModels. objgrad! (nlp:: CUTEstModel{T} , x:: AbstractVector , g:: AbstractVector ) where {T}
112156 @lencheck nlp. meta. nvar x g
157+ x_prepared = prepare_input! (nlp. input_workspace, x)
113158 gc = nlp. workspace_nvar
114- f, _ = objgrad! (nlp, Vector {T} (x) , gc)
159+ f, _ = objgrad! (nlp, x_prepared , gc)
115160 g .= gc
116161 return f, g
117162end
@@ -179,15 +224,15 @@ function cons_coord!(
179224 @lencheck nlp. meta. nvar x
180225 @lencheck nlp. meta. ncon c
181226 @lencheck nlp. meta. nnzj rows cols vals
182- rows_ = Vector {Cint} (undef, nlp . meta . nnzj)
183- cols_ = Vector {Cint} (undef, nlp . meta . nnzj )
184- vals_ = Vector {T} (undef , nlp. meta . nnzj )
185- c_ = Vector {T} (undef, nlp . meta . ncon)
186- cons_coord! (nlp, Vector {T} (x), c_, rows_, cols_, vals_)
187- rows .= rows_
188- cols .= cols_
189- vals .= vals_
190- c .= c_
227+
228+ # Use preallocated vectors instead of allocating new ones (Issue #392 )
229+ cons_coord! (nlp, Vector {T} (x) , nlp. cons_vals, nlp . jac_coord_rows, nlp . jac_coord_cols, nlp . jac_coord_vals )
230+
231+ # Copy results to output vectors
232+ rows .= nlp . jac_coord_rows
233+ cols .= nlp . jac_coord_cols
234+ vals .= nlp . jac_coord_vals
235+ c .= nlp . cons_vals
191236 return c, rows, cols, vals
192237end
193238
@@ -209,11 +254,17 @@ Usage:
209254"""
210255function cons_coord (nlp:: CUTEstModel{T} , x:: StrideOneVector{T} ) where {T}
211256 @lencheck nlp. meta. nvar x
212- c = Vector {T} (undef, nlp. meta. ncon)
213- rows = Vector {Cint} (undef, nlp. meta. nnzj)
214- cols = Vector {Cint} (undef, nlp. meta. nnzj)
215- vals = Vector {T} (undef, nlp. meta. nnzj)
216- cons_coord! (nlp, x, c, rows, cols, vals)
257+
258+ # Use preallocated vectors to avoid allocations (Issue #392)
259+ cons_coord! (nlp, x, nlp. cons_vals, nlp. jac_coord_rows, nlp. jac_coord_cols, nlp. jac_coord_vals)
260+
261+ # Return copies of the results to maintain API compatibility
262+ c = copy (nlp. cons_vals)
263+ rows = copy (nlp. jac_coord_rows)
264+ cols = copy (nlp. jac_coord_cols)
265+ vals = copy (nlp. jac_coord_vals)
266+
267+ return c, rows, cols, vals
217268end
218269
219270function cons_coord (nlp:: CUTEstModel{T} , x:: AbstractVector ) where {T}
@@ -630,9 +681,10 @@ function NLPModels.hess_coord!(
630681 @lencheck nlp. meta. nvar x
631682 @lencheck nlp. meta. ncon y
632683 @lencheck nlp. meta. nnzh vals
633- vals_ = Vector {T} (undef, nlp. meta. nnzh)
634- NLPModels. hess_coord! (nlp, Vector {T} (x), convert (Vector{T}, y), vals_, obj_weight = obj_weight)
635- vals .= vals_
684+
685+ # Use preallocated vector instead of allocating (Issue #392)
686+ NLPModels. hess_coord! (nlp, Vector {T} (x), convert (Vector{T}, y), nlp. hess_coord_vals, obj_weight = obj_weight)
687+ vals .= nlp. hess_coord_vals
636688 return vals
637689end
638690
0 commit comments