Added Project and Report
This commit is contained in:
223
Lessons/10-12/DIS.jl
Normal file
223
Lessons/10-12/DIS.jl
Normal file
@ -0,0 +1,223 @@
|
||||
using LinearAlgebra
|
||||
using Printf
|
||||
using Plots
|
||||
|
||||
function DIS(f;
|
||||
rangeplt::Union{Nothing, Tuple{Real, Real}}=nothing,
|
||||
sfgrd::Real=0,
|
||||
eps::Real=1e-6,
|
||||
MaxFeval::Integer=100,
|
||||
plt::Union{Plots.Plot, Nothing}=nothing,
|
||||
plotatend::Bool=true,
|
||||
Plotg::Integer=0
|
||||
)::Tuple{Real, String}
|
||||
|
||||
# Plotg
|
||||
# 1 = the function value / gap are plotted
|
||||
# 2 = the function and the model (if used) are plotted
|
||||
# all the rest: nothing is 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
|
||||
|
||||
(fxm, f1xm, _) = f(xm)
|
||||
if( f1xm > 0 )
|
||||
throw(DomainError(rangeplt, "f'(x_-) must be ≤ 0"))
|
||||
return (NaN, "empty")
|
||||
end
|
||||
|
||||
(fxp, f1xp, _) = f(xp)
|
||||
if( f1xp < 0 )
|
||||
throw(DomainError(rangeplt, "f'(x_+) must be ≥ 0"))
|
||||
return (NaN, "empty")
|
||||
end
|
||||
|
||||
if (sfgrd < 0) || (sfgrd ≥ 0.5)
|
||||
throw(DomainError(sfgrd, "sfgrd must be in [ 0 , 1/2 )"))
|
||||
return (NaN, "empty")
|
||||
end
|
||||
|
||||
if MaxFeval < 2
|
||||
throw(ArgumentError("At least two function computations are required"))
|
||||
return (NaN, "empty")
|
||||
end
|
||||
|
||||
# initializations - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
feval = 2
|
||||
status = "optimal"
|
||||
|
||||
if f1xm ≥ -eps
|
||||
return (xm, status)
|
||||
end
|
||||
|
||||
if f1xp ≤ eps
|
||||
return (xp, status)
|
||||
end
|
||||
|
||||
fbest = min(fxp, fxm)
|
||||
f1x = min(-f1xp, f1xm)
|
||||
|
||||
if Plotg == 1
|
||||
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
|
||||
|
||||
if iszero(sfgrd)
|
||||
println("Dichotomic search")
|
||||
else
|
||||
@printf("Dichotomic search with safeguarded interpolation (%1.4f)\n", sfgrd)
|
||||
end
|
||||
|
||||
if fStar > -Inf
|
||||
println("feval\trel gap\t\tx_-\t\tx_+\t\tx\t\tf'(x)")
|
||||
else
|
||||
println("feval\tfbest\t\tx_-\t\tx_+\t\tx\t\tf'(x)")
|
||||
end
|
||||
|
||||
# main loop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
x = 0
|
||||
|
||||
while true
|
||||
# stopping criteria - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if feval > MaxFeval
|
||||
status = "stopped"
|
||||
break
|
||||
end
|
||||
|
||||
# main logic- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if iszero(sfgrd)
|
||||
# compute the new point as the middle of the inteval
|
||||
x = (xm + xp) / 2
|
||||
else
|
||||
# compute the new point by safeguarded quadratic interpolation
|
||||
sfxp = xp - (xp - xm) * sfgrd
|
||||
sfxm = xm + (xp - xm) * sfgrd
|
||||
x = (xm * f1xp - xp * f1xm) / (f1xp - f1xm)
|
||||
x = max(sfxm, min(sfxp, x))
|
||||
end
|
||||
|
||||
(fx, f1x, _) = f(x) # compute f(x) and f'(x)
|
||||
|
||||
if fx < fbest
|
||||
fbest = fx
|
||||
end
|
||||
|
||||
feval += 1
|
||||
|
||||
# output statistics - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if fStar > -Inf
|
||||
gapk = (fbest - fStar) / max(abs(fStar), 1)
|
||||
|
||||
if Plotg == 1
|
||||
push!(gap, gapk)
|
||||
end
|
||||
else
|
||||
gapk = fbest
|
||||
end
|
||||
|
||||
@printf("%4d\t%1.4e\t%1.8e\t%1.8e\t%1.8e\t%1.4e\n", feval, gapk, xm, xp, x, f1x)
|
||||
|
||||
if Plotg == 2
|
||||
xmp = xm - (xp - xm) / 20
|
||||
xpp = xp + (xp - xm) / 20
|
||||
|
||||
for e in plt.series_list
|
||||
e[:linealpha] = 0
|
||||
end
|
||||
|
||||
xx = range(xmp, xpp, resolution)
|
||||
yy = map(v -> v[1], f.(xx))
|
||||
|
||||
xlims!(plt, (xmp, xpp))
|
||||
old_ylims = ylims(plt)
|
||||
ylims!(plt, (old_ylims[1], max(fxm, fxp)))
|
||||
plot!(plt, xx, yy)
|
||||
|
||||
if !iszero(sfgrd)
|
||||
a = (f1xp - f1xm) / (2 * (xp - xm))
|
||||
b = (xp * f1xm - xm * f1xp) / (xp - xm)
|
||||
# a xm^2 + b xm + c == fxm ==>
|
||||
# c == fxm - a xm^2 - b xm
|
||||
c = fxm - a * xm^2 - b * xm
|
||||
|
||||
xlims!(plt, (xmp, xpp))
|
||||
new_xticks = ([xmp, xm, sfxm, sfxp, xp, xpp],
|
||||
[@sprintf("%1.1g", xmp), "x-", "sx-", "sx+", "x+", @sprintf("%1.1g", xpp)])
|
||||
|
||||
xticks!(plt, new_xticks)
|
||||
plot!(plt, xx, @. a*xx^2 + b*xx + c)
|
||||
else
|
||||
new_xticks = ([xmp, xm, x, xp, xpp],
|
||||
[@sprintf("%1.1g", xmp), "x-", "x", "x+", @sprintf("%1.1g", xpp)])
|
||||
|
||||
xticks!(plt, new_xticks)
|
||||
end
|
||||
end
|
||||
# stopping criteria - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if abs(f1x) ≤ eps
|
||||
break
|
||||
end
|
||||
|
||||
# restrict the interval based on sign of the derivative in xn - - - - -
|
||||
if f1x < 0
|
||||
xm = x
|
||||
fxm = fx
|
||||
f1xm = f1x
|
||||
else
|
||||
xp = x
|
||||
fxp = fx
|
||||
f1xp = f1x
|
||||
end
|
||||
|
||||
if Plotg ≠ 0 && Interactive
|
||||
IJulia.clear_output(wait=true)
|
||||
display(plt)
|
||||
sleep(0.1)
|
||||
readline()
|
||||
end
|
||||
|
||||
# iterate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
end
|
||||
|
||||
if Plotg == 1
|
||||
plot!(plt,
|
||||
gap,
|
||||
linewidth=2)
|
||||
end
|
||||
|
||||
if plotatend && Plotg ≠ 0
|
||||
display(plt)
|
||||
end
|
||||
|
||||
(x, status)
|
||||
end
|
||||
Reference in New Issue
Block a user