From e102d7c77f9dc6852d5ad0c1055cb2d8ba851372 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Mon, 18 Nov 2024 15:27:07 -0600 Subject: [PATCH 1/5] Add an API for n-th order tensor products --- src/nlp/api.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/nlp/api.jl b/src/nlp/api.jl index c240c289..37ab0d79 100644 --- a/src/nlp/api.jl +++ b/src/nlp/api.jl @@ -11,6 +11,7 @@ export jth_hess_coord, jth_hess_coord!, jth_hess export jth_hprod, jth_hprod!, ghjvprod, ghjvprod! export hess_structure!, hess_structure, hess_coord!, hess_coord export hess, hprod, hprod!, hess_op, hess_op! +export tensor_projection export varscale, lagscale, conscale """ @@ -1298,6 +1299,21 @@ function hess_op!( return LinearOperator{T}(nlp.meta.nvar, nlp.meta.nvar, true, true, prod!, prod!, prod!) end +""" + P = tensor_projection(nlp, n, x, directions, args...) + +Returns the projection of the n-th derivative of the objective of `nlp` at `x` along the specified directions. + +#### Input arguments + +- `nlp::AbstractNLPModel`: An NLP model; +- `n::Int`: The order of the derivative to compute; +- `x::AbstractVector`: The point at which the derivative is evaluated; +- `directions::Tuple{Int, Vararg{Int}}`: A tuple of indices specifying the directions (e.g., `(1, 2)` for a tensor projection along the first and second axes); +- `args...`: A list of vectors, one for each direction specified in `directions`. +""" +function tensor_projection end + function varscale end function lagscale end function conscale end From c16f63f2825d4b40ff62f70819d2bf338fb131ff Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Mon, 18 Nov 2024 15:57:26 -0600 Subject: [PATCH 2/5] Add an in-place function tensor_projection! --- src/nlp/api.jl | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/nlp/api.jl b/src/nlp/api.jl index 37ab0d79..4e040081 100644 --- a/src/nlp/api.jl +++ b/src/nlp/api.jl @@ -11,7 +11,7 @@ export jth_hess_coord, jth_hess_coord!, jth_hess export jth_hprod, jth_hprod!, ghjvprod, ghjvprod! export hess_structure!, hess_structure, hess_coord!, hess_coord export hess, hprod, hprod!, hess_op, hess_op! -export tensor_projection +export tensor_projection, tensor_projection! export varscale, lagscale, conscale """ @@ -1306,13 +1306,33 @@ Returns the projection of the n-th derivative of the objective of `nlp` at `x` a #### Input arguments -- `nlp::AbstractNLPModel`: An NLP model; -- `n::Int`: The order of the derivative to compute; -- `x::AbstractVector`: The point at which the derivative is evaluated; -- `directions::Tuple{Int, Vararg{Int}}`: A tuple of indices specifying the directions (e.g., `(1, 2)` for a tensor projection along the first and second axes); +- `nlp`: An NLP model; +- `n`: The order of the derivative to compute; +- `x`: The point at which the derivative is evaluated; +- `directions`: A tuple of indices specifying the directions (e.g., `(1, 2)` for a tensor projection along the first and second axes); - `args...`: A list of vectors, one for each direction specified in `directions`. """ -function tensor_projection end +function tensor_projection( + nlp::AbstractNLPModel{T, S}, + n::Int, + x::AbstractVector, + directions::Tuple{Int, Vararg{Int}}, + args... +) where {T, S} + @lencheck nlp.meta.nvar x + m = n - length(directions) + @assert m ≥ 1 + dim = NTuple{m, Int}(nlp.meta.nvar for i = 1:m) + P = similar(x, dim) + return tensor_projection!(nlp, n, x, directions, P, args...) +end + +""" + tensor_projection!(nlp, n, x, directions, P, args...) + +In-place version of the function [`tensor_projection`](@ref) where the result is stored in `P`. +""" +function tensor_projection! end function varscale end function lagscale end From 56960d5b7dde02d9b763878dd5681d5761fb33cc Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Thu, 23 Jan 2025 15:18:12 -0600 Subject: [PATCH 3/5] Update api.jl --- src/nlp/api.jl | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/nlp/api.jl b/src/nlp/api.jl index 4e040081..4685f3b4 100644 --- a/src/nlp/api.jl +++ b/src/nlp/api.jl @@ -1300,37 +1300,31 @@ function hess_op!( end """ - P = tensor_projection(nlp, n, x, directions, args...) + p = tensor_projection(nlp, n, x, dimension, directions...) + p = tensor_projection(nlp, n, x, y, dimension, directions...) -Returns the projection of the n-th derivative of the objective of `nlp` at `x` along the specified directions. +Returns a vector `p` after `n-1` projections of the n-th derivative of the objective of `nlp` at `x` if only `x` is provided. +Otherwise when `x` and `y` are provided, we do `n-1` projections of the n-th derivative of the Lagrangian of `nlp` at `(x,y)`. #### Input arguments -- `nlp`: An NLP model; +- `nlp`: An [`AbstractNLPModel`](@ref); - `n`: The order of the derivative to compute; -- `x`: The point at which the derivative is evaluated; -- `directions`: A tuple of indices specifying the directions (e.g., `(1, 2)` for a tensor projection along the first and second axes); -- `args...`: A list of vectors, one for each direction specified in `directions`. -""" -function tensor_projection( - nlp::AbstractNLPModel{T, S}, - n::Int, - x::AbstractVector, - directions::Tuple{Int, Vararg{Int}}, - args... -) where {T, S} - @lencheck nlp.meta.nvar x - m = n - length(directions) - @assert m ≥ 1 - dim = NTuple{m, Int}(nlp.meta.nvar for i = 1:m) - P = similar(x, dim) - return tensor_projection!(nlp, n, x, directions, P, args...) -end +- `x`: The point at which the n-th derivative is evaluated; +- `dimension`: An integer that speficies the axis of the output subspace; +- `directions`: A collection of `n-1` directions for the projection. + +#### Output argument + +- `p`: vector storing the result of the tensor projection in the subspace represented by the axis `dimension`. +""" +function tensor_projection end """ - tensor_projection!(nlp, n, x, directions, P, args...) + tensor_projection!(nlp, n, x, dimension, p, args...) + tensor_projection!(nlp, n, x, y, dimension, p, args...) -In-place version of the function [`tensor_projection`](@ref) where the result is stored in `P`. +In-place version of the function [`tensor_projection`](@ref) where the result is stored in `p`. """ function tensor_projection! end From 19cc2ba157cbf67ce8d8450aa7c461f9a1f65a17 Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Thu, 23 Jan 2025 15:38:59 -0600 Subject: [PATCH 4/5] Improve the docstring of tensor_projection --- src/nlp/api.jl | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/nlp/api.jl b/src/nlp/api.jl index 4685f3b4..559c19b1 100644 --- a/src/nlp/api.jl +++ b/src/nlp/api.jl @@ -1300,23 +1300,28 @@ function hess_op!( end """ - p = tensor_projection(nlp, n, x, dimension, directions...) - p = tensor_projection(nlp, n, x, y, dimension, directions...) + p = tensor_projection(nlp, n, x, dimension, directions...) + p = tensor_projection(nlp, n, x, y, dimension, directions...) -Returns a vector `p` after `n-1` projections of the n-th derivative of the objective of `nlp` at `x` if only `x` is provided. -Otherwise when `x` and `y` are provided, we do `n-1` projections of the n-th derivative of the Lagrangian of `nlp` at `(x,y)`. +The `tensor_projection` function computes a projected vector `p` by applying `n-1` projections to the n-th derivative of either the objective or the Lagrangian of the given NLP model. +If only `x` is provided, the function computes the `n-1` projections of the **n-th derivative of the objective** of `nlp` at `x`. +If both `x` and `y` are provided, it computes the `n-1` projections of the **n-th derivative of the Lagrangian** of `nlp` at `(x, y)`. #### Input arguments -- `nlp`: An [`AbstractNLPModel`](@ref); -- `n`: The order of the derivative to compute; -- `x`: The point at which the n-th derivative is evaluated; -- `dimension`: An integer that speficies the axis of the output subspace; -- `directions`: A collection of `n-1` directions for the projection. +- `nlp`: An [`AbstractNLPModel`](@ref), representing the nonlinear programming model; +- `n`: An integer specifying the order of the derivative to compute; +- `x`: A vector representing the point where the n-th derivative is evaluated; +- `dimension`: An integer specifying the axis of the output subspace; +- `directions`: A collection of `n-1` directions used for the projection. + +#### Optional argument + +- `y`: A vector of Lagrange multipliers. #### Output argument -- `p`: vector storing the result of the tensor projection in the subspace represented by the axis `dimension`. +- `p`: A vector containing the result of the tensor projection into the subspace represented by the axis `dimension`. """ function tensor_projection end From 27ac328d08e3a5280773c02acdb06c115fd8ca7e Mon Sep 17 00:00:00 2001 From: Alexis Montoison Date: Wed, 29 Jan 2025 08:54:10 -0600 Subject: [PATCH 5/5] Add implementations for tensor_projection --- src/nlp/api.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/nlp/api.jl b/src/nlp/api.jl index 559c19b1..44dedd40 100644 --- a/src/nlp/api.jl +++ b/src/nlp/api.jl @@ -1325,6 +1325,21 @@ If both `x` and `y` are provided, it computes the `n-1` projections of the **n-t """ function tensor_projection end +function tensor_projection(nlp::AbstractNLPModel{T, S}, n::Int, x::AbstractVector, + dimension::Int, directions...) where {T, S} + @lencheck nlp.meta.nvar x + p = S(undef, nlp.meta.nvar) + return tensor_projection!(nlp, n, x, dimension, p, directions...) +end + +function tensor_projection(nlp::AbstractNLPModel{T, S}, n::Int, x::AbstractVector, + y::AbstractVector, dimension::Int, directions...) where {T, S} + @lencheck nlp.meta.nvar x + @lencheck nlp.meta.ncon y + p = S(undef, nlp.meta.nvar) + return tensor_projection!(nlp, n, x, y, dimension, p, directions...) +end + """ tensor_projection!(nlp, n, x, dimension, p, args...) tensor_projection!(nlp, n, x, y, dimension, p, args...)