187 lines
4.8 KiB
Julia
187 lines
4.8 KiB
Julia
|
|
using Plots
|
|||
|
|
using LinearAlgebra
|
|||
|
|
using Printf
|
|||
|
|
|
|||
|
|
function GRS(f;
|
|||
|
|
rangeplt::Union{Nothing, Tuple{Real, Real}}=nothing,
|
|||
|
|
delta::Real=1e-6,
|
|||
|
|
MaxFeval::Integer=100,
|
|||
|
|
plt::Union{Plots.Plot, Nothing}=nothing,
|
|||
|
|
plotatend::Bool=true,
|
|||
|
|
Plotg::Integer=0
|
|||
|
|
)::Tuple{Real, String}
|
|||
|
|
|
|||
|
|
# Plotg
|
|||
|
|
# 0 = nothing is plotted
|
|||
|
|
# 1 = the function value / gap are plotted
|
|||
|
|
# 2 = the function and the test points used are plotted
|
|||
|
|
|
|||
|
|
resolution = 1000
|
|||
|
|
|
|||
|
|
Interactive = false # if we pause at every iteration
|
|||
|
|
|
|||
|
|
# reading and checking input- - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
|
|||
|
|
if rangeplt == nothing
|
|||
|
|
(fStar, _, _, rangeplt) = f(nothing)
|
|||
|
|
else
|
|||
|
|
fStar = -Inf
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
xm = rangeplt[1] # x_-
|
|||
|
|
xp = rangeplt[2] # x_+
|
|||
|
|
|
|||
|
|
if xm > xp
|
|||
|
|
throw(ArgumentError("rangeplt is empty"))
|
|||
|
|
return (NaN, "empty")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if MaxFeval < 2
|
|||
|
|
throw(ArgumentError("At least two function computations are required"))
|
|||
|
|
return (NaN, "empty")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
# initializations - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
|
|||
|
|
r = (sqrt( 5 ) - 1)/2
|
|||
|
|
|
|||
|
|
xmp = xm + (1 - r) * (xp - xm) # x'_-
|
|||
|
|
xpp = xm + r * (xp - xm) # x'_+
|
|||
|
|
|
|||
|
|
fxmp = f(xmp)[1] # f(x'_-)
|
|||
|
|
fxpp = f(xpp)[1] # f(x'_+)
|
|||
|
|
|
|||
|
|
feval = 2
|
|||
|
|
|
|||
|
|
if fxmp ≤ fxpp
|
|||
|
|
fx = fxmp
|
|||
|
|
else
|
|||
|
|
fx = fxpp
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
status = "optimal"
|
|||
|
|
|
|||
|
|
if Plotg > 0
|
|||
|
|
gap = []
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if Plotg == 1 && plt == nothing
|
|||
|
|
plt = plot(yscale = :log,
|
|||
|
|
xlims=(0, 35),
|
|||
|
|
ylims=(1e-15, Inf),
|
|||
|
|
guidefontsize=16)
|
|||
|
|
elseif Plotg == 2 && plt == nothing
|
|||
|
|
plt = plot(legend = false)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
print("Golden ratio search\n")
|
|||
|
|
if fStar > -Inf
|
|||
|
|
print("feval\trel gap\t\tx_-\t\tx_+\n")
|
|||
|
|
else
|
|||
|
|
print("feval\tfbest\t\tx_-\t\tx_+\n")
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
# main loop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
|
|||
|
|
while xp - xm > delta
|
|||
|
|
|
|||
|
|
# output statistics - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
|
|||
|
|
if fStar > -Inf
|
|||
|
|
gapk = (fx - fStar) / max(abs(fStar), 1)
|
|||
|
|
|
|||
|
|
if Plotg == 1
|
|||
|
|
push!(gap, gapk)
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
gapk = fx
|
|||
|
|
end
|
|||
|
|
@printf("%4d\t%1.4e\t%1.8e\t%1.8e\n", feval, gapk, xm, xp)
|
|||
|
|
|
|||
|
|
if Plotg == 2
|
|||
|
|
xbot = xm - ( xp - xm ) / 20;
|
|||
|
|
xtop = xp + ( xp - xm ) / 20;
|
|||
|
|
|
|||
|
|
if !isempty(plt.series_list)
|
|||
|
|
plt.series_list[end][:linealpha] = 0
|
|||
|
|
end
|
|||
|
|
xx = range(xbot, xtop, resolution)
|
|||
|
|
yy = map(v -> v[1], f.(xx))
|
|||
|
|
xlims!(plt, (xbot, xtop))
|
|||
|
|
old_ylims = ylims(plt)
|
|||
|
|
ylims!(plt, (old_ylims[1], max(fxmp, fxpp)))
|
|||
|
|
plot!(plt, xx, yy)
|
|||
|
|
|
|||
|
|
# old_xticks = xticks(plt[1])
|
|||
|
|
new_xticks = ([xbot, xm, xmp, xpp, xp, xtop],
|
|||
|
|
[@sprintf("%1.1g", xbot), "x-", "x''-", "x''+", "x+", @sprintf("%1.1g", xtop)])
|
|||
|
|
# keep_indices = findall(x -> all(x .≠ new_xticks[1]), old_xticks[1])
|
|||
|
|
# merged_xticks = (old_xticks[1][keep_indices] ∪ new_xticks[1],
|
|||
|
|
# old_xticks[2][keep_indices] ∪ new_xticks[2])
|
|||
|
|
# xticks!(merged_xticks)
|
|||
|
|
xticks!(plt, new_xticks)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
# stopping criteria - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
if feval > MaxFeval
|
|||
|
|
status = "stopped"
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
# main logic- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
|
|||
|
|
if fxmp <= fxpp
|
|||
|
|
xp = xpp
|
|||
|
|
xpp = xmp
|
|||
|
|
xmp = xm + (1 - r) * (xp - xm)
|
|||
|
|
|
|||
|
|
fxpp = fxmp
|
|||
|
|
fx = fxmp
|
|||
|
|
fxmp = f(xmp)[1]
|
|||
|
|
else
|
|||
|
|
xm = xmp
|
|||
|
|
xmp = xpp
|
|||
|
|
xpp = xm + r * (xp - xm)
|
|||
|
|
|
|||
|
|
fxmp = fxpp
|
|||
|
|
fx = fxpp
|
|||
|
|
fxpp = f(xpp)[1]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
feval += 1
|
|||
|
|
|
|||
|
|
if Plotg ≠ 0 && Interactive
|
|||
|
|
IJulia.clear_output(wait=true)
|
|||
|
|
display(plt)
|
|||
|
|
sleep(0.1)
|
|||
|
|
readline()
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
# iterate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
# end of main loop- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|||
|
|
|
|||
|
|
# select final answer
|
|||
|
|
if fxmp ≤ fxpp
|
|||
|
|
x = xmp
|
|||
|
|
else
|
|||
|
|
x = xpp
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if Plotg == 1
|
|||
|
|
plot!(plt,
|
|||
|
|
gap,
|
|||
|
|
linewidth=2)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
if plotatend && Plotg ≠ 0
|
|||
|
|
display(plt)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
(x, status)
|
|||
|
|
end
|