@@ -2666,6 +2666,177 @@ function Base.:(==)(x::Reified{S}, y::Reified{S}) where {S}
26662666 return x. set == y. set
26672667end
26682668
2669+ """
2670+ VectorNonlinearOracle(;
2671+ dimension::Int,
2672+ l::Vector{Float64},
2673+ u::Vector{Float64},
2674+ eval_f::Function,
2675+ jacobian_structure::Vector{Tuple{Int,Int}},
2676+ eval_jacobian::Function,
2677+ hessian_lagrangian_structure::Vector{Tuple{Int,Int}} = Tuple{Int,Int}[],
2678+ eval_hessian_lagrangian::Union{Nothing,Function} = nothing,
2679+ ) <: AbstractVectorSet
2680+
2681+ The set:
2682+ ```math
2683+ S = \\ {x \\ in \\ mathbb{R}^{dimension}: l \\ le f(x) \\ le u\\ }
2684+ ```
2685+ where ``f`` is defined by the vectors `l` and `u`, and the callback oracles
2686+ `eval_f`, `eval_jacobian`, and `eval_hessian_lagrangian`.
2687+
2688+ ## f
2689+
2690+ The `eval_f` function must have the signature
2691+ ```julia
2692+ eval_f(ret::AbstractVector, x::AbstractVector)::Nothing
2693+ ```
2694+ which fills ``f(x)`` into the dense vector `ret`.
2695+
2696+ ## Jacobian
2697+
2698+ The `eval_jacobian` function must have the signature
2699+ ```julia
2700+ eval_jacobian(ret::AbstractVector, x::AbstractVector)::Nothing
2701+ ```
2702+ which fills the sparse Jacobian ``\\ nabla f(x)`` into `ret`.
2703+
2704+ The one-indexed sparsity structure must be provided in the `jacobian_structure`
2705+ argument.
2706+
2707+ ## Hessian
2708+
2709+ The `eval_hessian_lagrangian` function is optional.
2710+
2711+ If `eval_hessian_lagrangian === nothing`, Ipopt will use a Hessian approximation
2712+ instead of the exact Hessian.
2713+
2714+ If `eval_hessian_lagrangian` is a function, it must have the signature
2715+ ```julia
2716+ eval_hessian_lagrangian(
2717+ ret::AbstractVector,
2718+ x::AbstractVector,
2719+ μ::AbstractVector,
2720+ )::Nothing
2721+ ```
2722+ which fills the sparse Hessian of the Lagrangian ``\\ sum \\ mu_i \\ nabla^2 f_i(x)``
2723+ into `ret`.
2724+
2725+ The one-indexed sparsity structure must be provided in the
2726+ `hessian_lagrangian_structure` argument.
2727+
2728+ ## Example
2729+
2730+ To model the set:
2731+ ```math
2732+ \\ begin{align}
2733+ 0 \\ le & x^2 \\ le 1
2734+ 0 \\ le & y^2 + z^3 - w \\ le 0
2735+ \\ end{align}
2736+ ```
2737+ do
2738+ ```jldoctest
2739+ julia> import MathOptInterface as MOI
2740+
2741+ julia> set = MOI.VectorNonlinearOracle(;
2742+ dimension = 3,
2743+ l = [0.0, 0.0],
2744+ u = [1.0, 0.0],
2745+ eval_f = (ret, x) -> begin
2746+ ret[1] = x[2]^2
2747+ ret[2] = x[3]^2 + x[4]^3 - x[1]
2748+ return
2749+ end,
2750+ jacobian_structure = [(1, 2), (2, 1), (2, 3), (2, 4)],
2751+ eval_jacobian = (ret, x) -> begin
2752+ ret[1] = 2.0 * x[2]
2753+ ret[2] = -1.0
2754+ ret[3] = 2.0 * x[3]
2755+ ret[4] = 3.0 * x[4]^2
2756+ return
2757+ end,
2758+ hessian_lagrangian_structure = [(2, 2), (3, 3), (4, 4)],
2759+ eval_hessian_lagrangian = (ret, x, u) -> begin
2760+ ret[1] = 2.0 * u[1]
2761+ ret[2] = 2.0 * u[2]
2762+ ret[3] = 6.0 * x[4] * u[2]
2763+ return
2764+ end,
2765+ );
2766+
2767+ julia> set
2768+ VectorNonlinearOracle(;
2769+ dimension = 3,
2770+ l = [0.0, 0.0],
2771+ u = [1.0, 0.0],
2772+ ...,
2773+ )
2774+ ```
2775+ """
2776+ struct VectorNonlinearOracle{T} <: AbstractVectorSet
2777+ input_dimension:: Int
2778+ output_dimension:: Int
2779+ l:: Vector{T}
2780+ u:: Vector{T}
2781+ eval_f:: Function
2782+ jacobian_structure:: Vector{Tuple{Int,Int}}
2783+ eval_jacobian:: Function
2784+ hessian_lagrangian_structure:: Vector{Tuple{Int,Int}}
2785+ eval_hessian_lagrangian:: Union{Nothing,Function}
2786+
2787+ function VectorNonlinearOracle (;
2788+ dimension:: Int ,
2789+ l:: Vector{T} ,
2790+ u:: Vector{T} ,
2791+ eval_f:: Function ,
2792+ jacobian_structure:: Vector{Tuple{Int,Int}} ,
2793+ eval_jacobian:: Function ,
2794+ # The hessian_lagrangian is optional.
2795+ hessian_lagrangian_structure:: Vector{Tuple{Int,Int}} = Tuple{Int,Int}[],
2796+ eval_hessian_lagrangian:: Union{Nothing,Function} = nothing ,
2797+ ) where {T}
2798+ if length (l) != length (u)
2799+ throw (DimenionMismatch ())
2800+ end
2801+ return new {T} (
2802+ dimension,
2803+ length (l),
2804+ l,
2805+ u,
2806+ eval_f,
2807+ jacobian_structure,
2808+ eval_jacobian,
2809+ hessian_lagrangian_structure,
2810+ eval_hessian_lagrangian,
2811+ )
2812+ end
2813+ end
2814+
2815+ dimension (s:: VectorNonlinearOracle ) = s. input_dimension
2816+
2817+ function Base. copy (s:: VectorNonlinearOracle )
2818+ return VectorNonlinearOracle (;
2819+ dimension = s. input_dimension,
2820+ l = copy (s. l),
2821+ u = copy (s. u),
2822+ eval_f = s. eval_f,
2823+ jacobian_structure = copy (s. jacobian_structure),
2824+ eval_jacobian = s. eval_jacobian,
2825+ hessian_lagrangian_structure = copy (s. hessian_lagrangian_structure),
2826+ eval_hessian_lagrangian = s. eval_hessian_lagrangian,
2827+ )
2828+ end
2829+
2830+ function Base. show (io:: IO , s:: VectorNonlinearOracle{T} ) where {T}
2831+ println (io, " VectorNonlinearOracle{T}(;" )
2832+ println (io, " dimension = " , s. input_dimension, " ," )
2833+ println (io, " l = " , s. l, " ," )
2834+ println (io, " u = " , s. u, " ," )
2835+ println (io, " ...," )
2836+ print (io, " )" )
2837+ return
2838+ end
2839+
26692840# TODO (odow): these are not necessarily isbits. They may not be safe to return
26702841# without copying if the number is BigFloat, for example.
26712842function Base. copy (
0 commit comments