Files
cmdla/10-12/GRS.jl
2023-10-29 02:06:02 +01:00

187 lines
4.8 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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