-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathchebyquad.jl
More file actions
79 lines (74 loc) · 2.1 KB
/
chebyquad.jl
File metadata and controls
79 lines (74 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
export chebyquad
function chebyquad(; use_nls::Bool = false, kwargs...)
model = use_nls ? :nls : :nlp
return chebyquad(Val(model); kwargs...)
end
function Cheby(xj, i)
# Use standard Chebyshev definition with robust handling of tiny excursions:
# T_i(x) = cos(i * acos(x)) for |x| ≤ 1
# T_i(x) = cosh(i * acosh(x)) for x > 1
# T_i(x) = (-1)^i * cosh(i * acosh(-x)) for x < -1
if xj > 1
return cosh(i * acosh(xj))
elseif xj < -1
return (-1)^i * cosh(i * acosh(-xj))
else
# Clamp only for acos to guard against tiny floating-point/AD excursions.
xj_clamped = min(max(xj, -1), 1)
return cos(i * acos(xj_clamped))
end
end
function chebyquad(
::Val{:nlp};
n::Int = default_nvar,
m::Int = n,
type::Type{T} = Float64,
chebyshev = Cheby,
kwargs...,
) where {T}
m = max(m, n)
function f(x; n = length(x), m = m, chebyshev = chebyshev)
inv_n = one(T) / n
half = one(T) / 2
return half * sum(
(inv_n * sum(chebyshev(x[j], 2i) for j = 1:n) + one(T) / ((2i)^2 - 1))^2 for
i = 1:div(m, 2)
) +
half * sum(
(inv_n * sum(chebyshev(x[j], 2i - 1) for j = 1:n))^2 for i = 1:div(m + 1, 2)
)
end
step = one(T) / (n + one(T))
x0 = Vector{T}(undef, n)
for j = 1:n
x0[j] = j * step
end
return ADNLPModels.ADNLPModel(f, x0, name = "chebyquad"; kwargs...)
end
function chebyquad(
::Val{:nls};
n::Int = default_nvar,
m::Int = n,
type::Type{T} = Float64,
chebyshev = Cheby,
kwargs...,
) where {T}
m = max(m, n)
function F!(r, x; n = length(x), m = length(r), chebyshev = chebyshev)
inv_n = one(T) / n
for i = 1:div(m, 2)
r[2i] = inv_n * sum(chebyshev(x[j], 2i) for j = 1:n) + one(T) / ((2i)^2 - 1)
r[2i - 1] = inv_n * sum(chebyshev(x[j], 2i - 1) for j = 1:n)
end
if mod(m, 2) == 1
r[m] = inv_n * sum(chebyshev(x[j], m) for j = 1:n)
end
return r
end
step = one(T) / (n + one(T))
x0 = Vector{T}(undef, n)
for j = 1:n
x0[j] = j * step
end
return ADNLPModels.ADNLSModel!(F!, x0, m, name = "chebyquad-nls"; kwargs...)
end