diff --git a/src/ADNLPProblems/chebyquad.jl b/src/ADNLPProblems/chebyquad.jl new file mode 100644 index 00000000..ba7bd8bb --- /dev/null +++ b/src/ADNLPProblems/chebyquad.jl @@ -0,0 +1,75 @@ +export chebyquad + +function chebyquad(; use_nls::Bool = false, kwargs...) + model = use_nls ? :nls : :nlp + return chebyquad(Val(model); kwargs...) +end + +function _cheby_recurrence(xj, i::Integer) + i == 0 && return one(xj) + i == 1 && return xj + tk_prev = one(xj) + tk = xj + for _ = 2:i + tk_next = 2 * xj * tk - tk_prev + tk_prev = tk + tk = tk_next + end + return tk +end + +function chebyquad(::Val{:nlp}; n::Int = default_nvar, m::Int = n, type::Type{T} = Float64, kwargs...) where {T} + m = max(m, n) + function f(x; n = length(x)) + inv_n = one(eltype(x)) / n + s = zero(eltype(x)) + for i = 1:div(m + 1, 2) + acc = zero(eltype(x)) + for j = 1:n + acc += _cheby_recurrence(x[j], 2i - 1) + end + ri = inv_n * acc + s += ri * ri + end + for i = 1:div(m, 2) + acc = zero(eltype(x)) + for j = 1:n + acc += _cheby_recurrence(x[j], 2i) + end + ri = inv_n * acc + one(eltype(x)) / ((2i)^2 - 1) + s += ri * ri + end + return s / 2 + end + x0 = [j * one(T) / (n + one(T)) for j = 1:n] + return ADNLPModels.ADNLPModel(f, x0, name = "chebyquad"; kwargs...) +end + +function chebyquad(::Val{:nls}; n::Int = default_nvar, m::Int = n, type::Type{T} = Float64, kwargs...) where {T} + m = max(m, n) + function F!(r, x) + n = length(x) + m = length(r) + inv_n = one(eltype(x)) / n + for i = 1:div(m, 2) + acc_odd = zero(eltype(x)) + acc_even = zero(eltype(x)) + for j = 1:n + acc_odd += _cheby_recurrence(x[j], 2i - 1) + acc_even += _cheby_recurrence(x[j], 2i) + end + r[2i - 1] = inv_n * acc_odd + r[2i] = inv_n * acc_even + one(eltype(x)) / ((2i)^2 - 1) + end + if isodd(m) + acc = zero(eltype(x)) + for j = 1:n + acc += _cheby_recurrence(x[j], m) + end + r[m] = inv_n * acc + end + return r + end + x0 = [j * one(T) / (n + one(T)) for j = 1:n] + return ADNLPModels.ADNLSModel!(F!, x0, m, name = "chebyquad-nls"; kwargs...) +end diff --git a/src/Meta/chebyquad.jl b/src/Meta/chebyquad.jl new file mode 100644 index 00000000..2f9fde0d --- /dev/null +++ b/src/Meta/chebyquad.jl @@ -0,0 +1,56 @@ +chebyquad_meta = Dict( + :nvar => 100, + :variable_nvar => true, + :ncon => 0, + :variable_ncon => false, + :minimize => true, + :name => "chebyquad", + :has_equalities_only => false, + :has_inequalities_only => false, + :has_bounds => false, + :has_fixed_variables => false, + :objtype => :least_squares, + :contype => :unconstrained, + :best_known_lower_bound => 0.0, + :best_known_upper_bound => Inf, + :is_feasible => true, + :defined_everywhere => missing, + :origin => :unknown, + :implementation => :both, + :url => "https://bitbucket.org/optrove/sif/src/master/CHEBYQAD.SIF", + :notes => raw""" +The Chebyquad problem in variable dimension. This is a nonlinear least-squares +problem with n groups. The Hessian is full. + +classification SBR2-AN-V-0 +""", + :origin_notes => raw""" +Problem 35 in +J.J. More', B.S. Garbow and K.E. Hillstrom, +"Testing Unconstrained Optimization Software", +ACM Transactions on Mathematical Software, vol. 7(1), pp. 17-41, 1981. +See also Buckley#133 (p. 44). + +SIF input: Nick Gould, March 1990. +""", + :reference => raw""" +@article{MoreGarbowHillstrom1981, + author = {Mor{\'e}, Jorge J. and Garbow, Burton S. and Hillstrom, Kenneth E.}, + title = {Testing Unconstrained Optimization Software}, + journal = {ACM Transactions on Mathematical Software}, + year = {1981}, + volume = {7}, + number = {1}, + pages = {17--41}, + doi = {10.1145/355934.355936} +} +""", + :lib => "CUTEst:CHEBYQAD", +) +get_chebyquad_nvar(; n::Int = default_nvar, kwargs...) = n +get_chebyquad_ncon(; n::Int = default_nvar, kwargs...) = 0 +get_chebyquad_nlin(; n::Int = default_nvar, kwargs...) = 0 +get_chebyquad_nnln(; n::Int = default_nvar, kwargs...) = 0 +get_chebyquad_nequ(; n::Int = default_nvar, kwargs...) = 0 +get_chebyquad_nineq(; n::Int = default_nvar, kwargs...) = 0 +get_chebyquad_nls_nequ(; n::Int = default_nvar, m::Int = n, kwargs...) = max(m, n) diff --git a/src/PureJuMP/chebyquad.jl b/src/PureJuMP/chebyquad.jl new file mode 100644 index 00000000..faf27b2b --- /dev/null +++ b/src/PureJuMP/chebyquad.jl @@ -0,0 +1,33 @@ +export chebyquad + +function _cheby_recurrence(xj, i::Integer) + i == 0 && return one(xj) + i == 1 && return xj + tk_prev = one(xj) + tk = xj + for _ = 2:i + tk_next = 2 * xj * tk - tk_prev + tk_prev = tk + tk = tk_next + end + return tk +end + +"The Chebyshev quadrature problem in variable dimension" +function chebyquad(args...; n::Int = default_nvar, m::Int = n, kwargs...) + m = max(m, n) + nlp = Model() + @variable(nlp, x[j = 1:n], start = j / (n + 1)) + @objective( + nlp, + Min, + 0.5 * sum( + ((1 / n) * sum(_cheby_recurrence(x[j], 2i - 1) for j = 1:n))^2 for + i = 1:div(m + 1, 2) + ) + 0.5 * sum( + ((1 / n) * sum(_cheby_recurrence(x[j], 2i) for j = 1:n) + 1 / ((2i)^2 - 1))^2 for + i = 1:div(m, 2) + ), + ) + return nlp +end