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
|
||||
325
Lessons/10-12/DIS.m
Normal file
325
Lessons/10-12/DIS.m
Normal file
@ -0,0 +1,325 @@
|
||||
function [ x , status ] = DIS( f , varargin )
|
||||
|
||||
%function [ x , status ] = DIS( f , range , sfgrd , delta , MaxFeval )
|
||||
%
|
||||
% Apply the classical Dichotomic Search for the minimization of the
|
||||
% provided one-dimensional function f, which must have the following
|
||||
% interface:
|
||||
%
|
||||
% [ v , varargout ] = f( x )
|
||||
%
|
||||
% Input:
|
||||
%
|
||||
% - x is either a scalar real denoting the input of f(), or [] (empty).
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - v (real, scalar): if x == [] this is the best known lower bound on
|
||||
% the global optimum of f() on the standard interval in which f() is
|
||||
% supposed to be minimised (see next). If x ~= [] then v = f(x).
|
||||
%
|
||||
% - g (real, either scalar or a [ 2 x 1 ] matrix denoting an interval) is
|
||||
% the first optional argument. This also depends on x. if x == [] then
|
||||
% g is a [ 2 x 1 ] matrix denoting the standard interval in which f()
|
||||
% is supposed to be minimised (into which v is the minimum). f() is
|
||||
% never called with x ~= [].
|
||||
%
|
||||
% IMPORTANT NOTE: the function requires f() to be able to provide the first
|
||||
% derivative, and it requires that the interval
|
||||
% [ x_- , x_+ ] is chosen such that f'( x_- ) <= 0 and f'( x_+ ) >= 0.
|
||||
%
|
||||
% The Dichotomic Search can either be "blind" (new point right in the
|
||||
% middle of the interval) or using a safeguarded quadratic Interpolation
|
||||
% to choose it, as dictated by the other [optional] input parameters:
|
||||
%
|
||||
% - range: (either [ 2 x 1 ] real vector or [], default []): the range
|
||||
% in which the local minimum has to be seached; if range == [], the
|
||||
% default range point provided by f() is used.
|
||||
%
|
||||
% - sfgrd (real scalar, default value 0): if sfgrd == 0, the Dichotomic
|
||||
% Search is "blind", i .e., the new point is always chosen right in the
|
||||
% middle of the current interval. Otherwise, it must be 0 < sfgrd < 0.5
|
||||
% and a safeguarded quadratic Interpolation technique is used to choose
|
||||
% it, where it is guaranteed that at least ( 1 - sfgrd ) of the current
|
||||
% interval will be discarded.
|
||||
%
|
||||
% - eps (real scalar, default value 1e-6): the accuracy in the stopping
|
||||
% criterion: the algorithm is stopped when a point is found such that
|
||||
% the absolute value of the derivative is less than or equal to eps.
|
||||
%
|
||||
% - MaxFeval (integer scalar, default value 100): the maximum number of
|
||||
% function evaluations (hence, iterations will be not more than
|
||||
% MaxFeval - 2 because at each iteration one function evaluation is
|
||||
% performed, except in the first one when two are).
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - x (real scalar): the best solution found so far.
|
||||
%
|
||||
% - status (string): a string describing the status of the algorithm at
|
||||
% termination
|
||||
%
|
||||
% = 'optimal': the algorithm terminated having proven that x is a(n
|
||||
% approximately) optimal solution, i.e., the diameter of the
|
||||
% restricted range is less than or equal to delta.
|
||||
%
|
||||
% = 'empty': the provided range is empty (x_- > x_+) and therefore
|
||||
% such is the optimization problem
|
||||
%
|
||||
% = 'stopped': the algorithm terminated having exhausted the maximum
|
||||
% number of iterations: x is the best solution found so far, but not
|
||||
% necessarily the optimal one
|
||||
%
|
||||
% = 'error': the algorithm found a numerical error that prevents it from
|
||||
% continuing optimization
|
||||
%
|
||||
% TODO: implement a warm-op phase whereby if f'( x_- ) > 0 then x_- is
|
||||
% "quickly moved left" until the derivative is negative, and,
|
||||
% symmetrically, if f'( x_+ ) < 0 then it is "quickly moved right".
|
||||
%
|
||||
%{
|
||||
=======================================
|
||||
Author: Antonio Frangioni
|
||||
Date: 09-08-21
|
||||
Version 0.10
|
||||
Copyright Antonio Frangioni
|
||||
=======================================
|
||||
%}
|
||||
|
||||
Plotg = 1;
|
||||
% 1 = the function value / gap are plotted
|
||||
% 2 = the function and the model (if used) are plotted
|
||||
% all the rest: nothing is plotted
|
||||
|
||||
Interactive = true; % if we pause at every iteration
|
||||
|
||||
% reading and checking input- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if ~ isa( f , 'function_handle' )
|
||||
error( 'f not a function' );
|
||||
end
|
||||
|
||||
if isempty( varargin ) || isempty( varargin{ 1 } )
|
||||
[ fStar , range ] = f( [] );
|
||||
else
|
||||
fStar = - Inf; % if the range is not the standard one, we can't trust
|
||||
% the standard global minima
|
||||
range = varargin{ 1 };
|
||||
end
|
||||
|
||||
if ~ isreal( range )
|
||||
error( 'range not a real vector' );
|
||||
end
|
||||
|
||||
if ( size( range , 1 ) ~= 1 ) || ( size( range , 2 ) ~= 2 )
|
||||
error( 'range is not a [ 1 x 2 ] vector' );
|
||||
end
|
||||
|
||||
xm = range( 1 ); % x_-
|
||||
xp = range( 2 ); % x_+
|
||||
|
||||
if xm > xp
|
||||
fprintf( 'range is empty\n' );
|
||||
x = NaN;
|
||||
status = 'empty';
|
||||
return;
|
||||
end
|
||||
|
||||
[ fxm , f1xm ] = f( xm );
|
||||
if( f1xm > 0 )
|
||||
error( 'f''( x_- ) must be <= 0' );
|
||||
end
|
||||
|
||||
[ fxp , f1xp ] = f( xp );
|
||||
if( f1xp < 0 )
|
||||
error( 'f''( x_+ ) must be >= 0' );
|
||||
end
|
||||
|
||||
if length( varargin ) > 1
|
||||
sfgrd = varargin{ 2 };
|
||||
if ~ isreal( sfgrd ) || ~ isscalar( sfgrd )
|
||||
error( 'sfgrd is not a real scalar' );
|
||||
end
|
||||
if ( sfgrd < 0 ) || ( sfgrd >= 0.5 )
|
||||
error( 'sfgrd must be in [ 0 , 1/2 )' );
|
||||
end
|
||||
else
|
||||
sfgrd = 0;
|
||||
end
|
||||
|
||||
if length( varargin ) > 2
|
||||
eps = varargin{ 3 };
|
||||
if ~ isreal( eps ) || ~ isscalar( eps )
|
||||
error( 'eps is not a real scalar' );
|
||||
end
|
||||
else
|
||||
eps = 1e-6;
|
||||
end
|
||||
|
||||
if length( varargin ) > 3
|
||||
MaxFeval = round( varargin{ 4 } );
|
||||
if ~ isscalar( MaxFeval )
|
||||
error( 'MaxFeval is not an integer scalar' );
|
||||
end
|
||||
else
|
||||
MaxFeval = 100;
|
||||
end
|
||||
|
||||
% initializations - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
feval = 2;
|
||||
|
||||
status = 'optimal';
|
||||
|
||||
if f1xm >= - eps
|
||||
x = xm;
|
||||
return;
|
||||
end
|
||||
|
||||
if f1xp <= eps
|
||||
x = xp;
|
||||
return;
|
||||
end
|
||||
|
||||
fbest = min( [ fxp fxm ] );
|
||||
f1x = min( [ -f1xp f1xm ] );
|
||||
|
||||
if Plotg == 1
|
||||
gap = [];
|
||||
end
|
||||
|
||||
if sfgrd == 0
|
||||
fprintf( 'Dichotomic search\n');
|
||||
else
|
||||
fprintf( ...
|
||||
'Dichotomic search with safeguarded interpolation (%1.4f)\n' , sfgrd );
|
||||
end
|
||||
if fStar > - Inf
|
||||
fprintf( 'feval\trel gap\t\tx_-\t\tx_+\t\tx\t\tf''(x)\n');
|
||||
else
|
||||
fprintf( 'feval\tfbest\t\tx_-\t\tx_+\t\tx\t\tf''(x)\n');
|
||||
end
|
||||
|
||||
% main loop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
while true
|
||||
|
||||
% stopping criteria - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if feval > MaxFeval
|
||||
status = 'stopped';
|
||||
break;
|
||||
end
|
||||
|
||||
% main logic- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if sfgrd == 0
|
||||
% 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 = feval + 1;
|
||||
|
||||
% output statistics - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if fStar > - Inf
|
||||
gapk = ( fbest - fStar ) / max( [ abs( fStar ) 1 ] );
|
||||
|
||||
if Plotg == 1
|
||||
gap( end + 1 ) = gapk;
|
||||
semilogy( gap , 'Color' , 'k' , 'LineWidth' , 2 );
|
||||
xlim( [ 0 35 ] );
|
||||
ylim( [ 1e-15 inf ] );
|
||||
ax = gca;
|
||||
ax.FontSize = 16;
|
||||
ax.Position = [ 0.03 0.07 0.95 0.92 ];
|
||||
ax.Toolbar.Visible = 'off';
|
||||
end
|
||||
else
|
||||
gapk = fbest;
|
||||
end
|
||||
fprintf( '%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;
|
||||
|
||||
warning( 'off' , 'all' );
|
||||
fplot( @(x) f( x ) , [ xmp xpp ] , 'Color' , 'k' , ...
|
||||
'LineWidth' , 1 );
|
||||
|
||||
xlim( [ xmp xpp ] );
|
||||
yticks( [] );
|
||||
ax = gca;
|
||||
ax.FontSize = 16;
|
||||
ax.Toolbar.Visible = 'off';
|
||||
ax.Position = [ 0.025 0.05 0.95 0.95 ];
|
||||
if sfgrd ~= 0
|
||||
hold on;
|
||||
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;
|
||||
fplot( @(x) a * x^2 + b * x + c , [ xmp xpp ] , ...
|
||||
'Color' , 'b' , 'LineWidth' , 1 );
|
||||
xticks( [ xmp xm sfxm sfxp xp xpp ] );
|
||||
xticklabels( { num2str( xmp , '%1.1g' ) , 'x-' , 'sx-' , ...
|
||||
'sx+' , 'x+' , num2str( xpp , '%1.1g' ) } );
|
||||
else
|
||||
xticks( [ xmp xm x xp xpp ] );
|
||||
xticklabels( { num2str( xmp , '%1.1g' ) , 'x-' , 'x' , ...
|
||||
'x+' , num2str( xpp , '%1.1g' ) } );
|
||||
end
|
||||
warning( 'on' , 'all' );
|
||||
hold off;
|
||||
end
|
||||
|
||||
% check stopping condition- - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
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 Interactive
|
||||
pause;
|
||||
end
|
||||
|
||||
% iterate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
end
|
||||
|
||||
% end of main loop- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
end % the end- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
187
Lessons/10-12/GRS.jl
Normal file
187
Lessons/10-12/GRS.jl
Normal file
@ -0,0 +1,187 @@
|
||||
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
|
||||
252
Lessons/10-12/GRS.m
Normal file
252
Lessons/10-12/GRS.m
Normal file
@ -0,0 +1,252 @@
|
||||
function [ x , status ] = GRS( f , varargin )
|
||||
|
||||
%function [ x , status ] = GRS( f , range , delta , MaxFeval )
|
||||
%
|
||||
% Apply the classical Golden Ratio Search for the minimization of the
|
||||
% provided one-dimensional function f, which must have the following
|
||||
% interface:
|
||||
%
|
||||
% [ v , varargout ] = f( x )
|
||||
%
|
||||
% Input:
|
||||
%
|
||||
% - x is either a scalar real denoting the input of f(), or [] (empty).
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - v (real, scalar): if x == [] this is the best known lower bound on
|
||||
% the global optimum of f() on the standard interval in which f() is
|
||||
% supposed to be minimised (see next). If x ~= [] then v = f(x).
|
||||
%
|
||||
% - g (real, either scalar or a [ 2 x 1 ] matrix denoting an interval) is
|
||||
% the first optional argument. This also depends on x. if x == [] then
|
||||
% g is a [ 2 x 1 ] matrix denoting the standard interval in which f()
|
||||
% is supposed to be minimised (into which v is the minimum). f() is
|
||||
% never called with x ~= [].
|
||||
%
|
||||
% The other [optional] input parameters are:
|
||||
%
|
||||
% - range: (either [ 2 x 1 ] real vector or [], default []): the range
|
||||
% in which the local minimum has to be seached; if range == [], the
|
||||
% default range point provided by f() is used.
|
||||
%
|
||||
% - delta (real scalar, default value 1e-6): the accuracy in the stopping
|
||||
% criterion: the algorithm is stopped when the diameter of the
|
||||
% restricted range is less than or equal to delta.
|
||||
%
|
||||
% - MaxFeval (integer scalar, default value 100): the maximum number of
|
||||
% function evaluations (hence, iterations will be not more than
|
||||
% MaxFeval - 2 because at each iteration one function evaluation is
|
||||
% performed, except in the first one when two are).
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - x (real scalar): the best solution found so far.
|
||||
%
|
||||
% - status (string): a string describing the status of the algorithm at
|
||||
% termination
|
||||
%
|
||||
% = 'optimal': the algorithm terminated having proven that x is a(n
|
||||
% approximately) optimal solution, i.e., the diameter of the
|
||||
% restricted range is less than or equal to delta.
|
||||
%
|
||||
% = 'empty': the provided range is empty (x_- > x_+) and therefore
|
||||
% such is the optimization problem
|
||||
%
|
||||
% = 'stopped': the algorithm terminated having exhausted the maximum
|
||||
% number of iterations: x is the best solution found so far, but not
|
||||
% necessarily the optimal one
|
||||
%
|
||||
% = 'error': the algorithm found a numerical error that prevents it from
|
||||
% continuing optimization
|
||||
%
|
||||
%{
|
||||
=======================================
|
||||
Author: Antonio Frangioni
|
||||
Date: 09-08-21
|
||||
Version 0.10
|
||||
Copyright Antonio Frangioni
|
||||
=======================================
|
||||
%}
|
||||
|
||||
Plotg = 1;
|
||||
% 0 = nothing is plotted
|
||||
% 1 = the function value / gap are plotted
|
||||
% 2 = the function and the test points used are plotted
|
||||
|
||||
Interactive = true; % if we pause at every iteration
|
||||
|
||||
% reading and checking input- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if ~ isa( f , 'function_handle' )
|
||||
error( 'f not a function' );
|
||||
end
|
||||
|
||||
if isempty( varargin ) || isempty( varargin{ 1 } )
|
||||
[ fStar , range ] = f( [] );
|
||||
else
|
||||
fStar = - Inf; % if the range is not the standard one, we can't trust
|
||||
% the standard global minima
|
||||
range = varargin{ 1 };
|
||||
end
|
||||
|
||||
if ~ isreal( range )
|
||||
error( 'range not a real vector' );
|
||||
end
|
||||
|
||||
if ( size( range , 1 ) ~= 1 ) || ( size( range , 2 ) ~= 2 )
|
||||
error( 'range is not a [ 1 x 2 ] vector' );
|
||||
end
|
||||
|
||||
xm = range( 1 ); % x_-
|
||||
xp = range( 2 ); % x_+
|
||||
|
||||
if xm > xp
|
||||
fprintf( 'range is empty\n' );
|
||||
x = NaN;
|
||||
status = 'empty';
|
||||
return;
|
||||
end
|
||||
|
||||
if length( varargin ) > 1
|
||||
delta = varargin{ 2 };
|
||||
if ~ isreal( delta ) || ~ isscalar( delta )
|
||||
error( 'delta is not a real scalar' );
|
||||
end
|
||||
else
|
||||
delta = 1e-6;
|
||||
end
|
||||
|
||||
if length( varargin ) > 2
|
||||
MaxFeval = round( varargin{ 3 } );
|
||||
if ~ isscalar( MaxFeval )
|
||||
error( 'MaxFeval is not an integer scalar' );
|
||||
end
|
||||
if MaxFeval < 2
|
||||
error( 'at least two function computations are required' );
|
||||
end
|
||||
else
|
||||
MaxFeval = 100;
|
||||
end
|
||||
|
||||
% initializations - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
r = ( sqrt( 5 ) - 1 ) / 2;
|
||||
|
||||
xmp = xm + ( 1 - r ) * ( xp - xm ); % x'_-
|
||||
xpp = xm + r * ( xp - xm ); % x'_+
|
||||
|
||||
fxmp = f( xmp ); % f( x'_- )
|
||||
fxpp = f( xpp ); % f( x'_+ )
|
||||
|
||||
feval = 2;
|
||||
|
||||
if fxmp <= fxpp
|
||||
fx = fxmp;
|
||||
else
|
||||
fx = fxpp;
|
||||
end
|
||||
|
||||
status = 'optimal';
|
||||
|
||||
if Plotg
|
||||
gap = [];
|
||||
end
|
||||
|
||||
fprintf( 'Golden ratio search\n');
|
||||
if fStar > - Inf
|
||||
fprintf( 'feval\trel gap\t\tx_-\t\tx_+\n');
|
||||
else
|
||||
fprintf( '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
|
||||
gap( end + 1 ) = gapk;
|
||||
semilogy( gap , 'Color' , 'k' , 'LineWidth' , 2 );
|
||||
xlim( [ 0 35 ] );
|
||||
ylim( [ 1e-15 inf ] );
|
||||
ax = gca;
|
||||
ax.FontSize = 16;
|
||||
ax.Position = [ 0.03 0.07 0.95 0.92 ];
|
||||
ax.Toolbar.Visible = 'off';
|
||||
end
|
||||
else
|
||||
gapk = fx;
|
||||
end
|
||||
fprintf( '%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;
|
||||
|
||||
warning( 'off' , 'all' );
|
||||
fplot( @(x) f( x ) , [ xbot xtop ] , 'Color' , 'k' , ...
|
||||
'LineWidth' , 1 );
|
||||
|
||||
xlim( [ xbot xtop ] );
|
||||
yticks( [] );
|
||||
ax = gca;
|
||||
ax.FontSize = 16;
|
||||
ax.Position = [ 0.025 0.05 0.95 0.95 ];
|
||||
ax.Toolbar.Visible = 'off';
|
||||
xticks( [ xbot xm xmp xpp xp xtop ] );
|
||||
xticklabels( { num2str( xbot , '%1.1g' ) , 'x-' , 'x''-' , ...
|
||||
'x''+' , 'x+' , num2str( xtop , '%1.1g' ) } );
|
||||
warning( 'on' , 'all' );
|
||||
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 );
|
||||
else
|
||||
xm = xmp; xmp = xpp; xpp = xm + r * ( xp - xm );
|
||||
fxmp = fxpp; fx = fxpp; fxpp = f( xpp );
|
||||
end
|
||||
|
||||
feval = feval + 1;
|
||||
|
||||
if Interactive
|
||||
pause;
|
||||
end
|
||||
|
||||
% iterate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
end
|
||||
|
||||
% end of main loop- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
% select final answer
|
||||
|
||||
if fxmp <= fxpp
|
||||
x = xmp;
|
||||
else
|
||||
x = xpp;
|
||||
end
|
||||
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
end % the end- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
206
Lessons/10-12/UNM.jl
Normal file
206
Lessons/10-12/UNM.jl
Normal file
@ -0,0 +1,206 @@
|
||||
using LinearAlgebra
|
||||
using Printf
|
||||
using Plots
|
||||
using LaTeXStrings
|
||||
|
||||
function UNM(f;
|
||||
x::Union{Nothing, Real}=nothing,
|
||||
eps::Real=1e-6,
|
||||
finf::Real=1e+8,
|
||||
MaxFeval::Integer=30,
|
||||
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 second-order model are plotted
|
||||
# 3 = the function, the first-order model and the second-order model are
|
||||
# plotted (the first-order model has no role in the algorithm, but
|
||||
# this shows how much better the second-order model is than the
|
||||
# first-order one)
|
||||
|
||||
resolution = 1000
|
||||
|
||||
Interactive = false
|
||||
|
||||
# reading and checking input- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
(fStar, _, _, rangeplt) = f(nothing)
|
||||
|
||||
if x == nothing
|
||||
x = rangeplt[1]
|
||||
end
|
||||
|
||||
if finf ≤ 0
|
||||
throw(DomainError(finf, "finf must be in > 0"))
|
||||
end
|
||||
|
||||
if MaxFeval < 2
|
||||
throw(ArgumentError("At least two function computations are required"))
|
||||
return (NaN, "empty")
|
||||
end
|
||||
|
||||
# initializations - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
feval = 0
|
||||
status = "optimal"
|
||||
fbest = Inf
|
||||
|
||||
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)
|
||||
elseif Plotg == 3 && plt == nothing
|
||||
plt = plot(legend = false)
|
||||
end
|
||||
|
||||
|
||||
println("Univariate Newton's Method")
|
||||
|
||||
if fStar > -Inf
|
||||
println("feval\trel gap\t\tx\t\tf(x)\t\tf'(x)\t\tf''(x)")
|
||||
else
|
||||
println("feval\tfbest\t\tx\t\tf'(x)\t\tf'(x)\t\tf''(x)")
|
||||
end
|
||||
|
||||
# main loop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
while true
|
||||
# compute f(x), f'(x), f''(x) - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
(fx, f1x, f2x) = f(x)
|
||||
|
||||
feval += 1
|
||||
|
||||
if fx < fbest
|
||||
fbest = fx
|
||||
end
|
||||
|
||||
if abs(f2x) ≤ 1e-16
|
||||
status = "stopped"
|
||||
@printf("numerical issue: f''(x) = %1.4e\n", f2x)
|
||||
break
|
||||
end
|
||||
|
||||
# main logic- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
xn = x - f1x/f2x
|
||||
|
||||
# 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.4e\t%1.4e\t%1.4e\n", feval, gapk, x, fx, f1x, f2x)
|
||||
|
||||
if Plotg > 1
|
||||
xm = min(x, xn) - abs(x - xn) / 5
|
||||
xp = max(x, xn) + abs(x - xn) / 5
|
||||
|
||||
xx = range(xm, xp, resolution)
|
||||
yy = map(v -> v[1], f.(xx))
|
||||
|
||||
for e in plt.series_list
|
||||
e[:linealpha] = 0
|
||||
end
|
||||
|
||||
old_ylims = ylims(plt)
|
||||
ylims!(plt, (minimum(yy), max(yy[1], yy[end])))
|
||||
|
||||
xlims!(plt, (xm, xp))
|
||||
|
||||
plot!(plt, xx, yy)
|
||||
|
||||
if Plotg == 3
|
||||
# first-order model is
|
||||
# f( y ) = f( x ) + f'( x )( y - x )
|
||||
# = [ f( x ) - f'( x ) x ]
|
||||
# + f'( x ) y
|
||||
b = f1x
|
||||
c = fx - f1x*x
|
||||
|
||||
yy = b .* xx .+ c
|
||||
plot!(plt, xx, yy)
|
||||
end
|
||||
# second-order model is
|
||||
# f( y ) = f( x ) + f'( x )( y - x ) + f''( x )( y - x )^2 / 2
|
||||
# = [ f( x ) - f'( x ) x + f''( x ) x^2 / 2 ]
|
||||
# + [ f'( x ) - f''( x ) x ] y
|
||||
# + f''( x )y^2 / 2
|
||||
a = f2x/2
|
||||
b = f1x - f2x*x
|
||||
c = fx - f1x*x + f2x*x^2 / 2
|
||||
|
||||
yy = @. a * xx^2 + b * xx + c
|
||||
plot!(plt, xx, yy)
|
||||
|
||||
new_xticks = []
|
||||
if x < xn
|
||||
new_xticks = ([xm, x, xn, xp],
|
||||
[@sprintf("%1.1g", xm), L"x^k", L"x^{k+1}", @sprintf("%1.1g", xp)])
|
||||
else
|
||||
new_xticks = ([xm, xn, x, xp],
|
||||
[@sprintf("%1.1g", xm), L"x^{k+1}", L"x^k", @sprintf("%1.1g", xp)])
|
||||
end
|
||||
xticks!(plt, new_xticks)
|
||||
end
|
||||
|
||||
# stopping criteria - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if abs(f1x) ≤ eps
|
||||
break
|
||||
end
|
||||
|
||||
if feval > MaxFeval
|
||||
status = "stopped"
|
||||
break
|
||||
end
|
||||
|
||||
if abs(fx) > finf
|
||||
status = "error"
|
||||
break
|
||||
end
|
||||
|
||||
if Plotg ≠ 0 && Interactive
|
||||
IJulia.clear_output(wait=true)
|
||||
display(plt)
|
||||
sleep(0.1)
|
||||
readline()
|
||||
end
|
||||
|
||||
# iterate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
x = xn
|
||||
end
|
||||
|
||||
if Plotg == 1
|
||||
plot!(plt,
|
||||
gap,
|
||||
linewidth=2)
|
||||
end
|
||||
|
||||
if plotatend && Plotg ≠ 0
|
||||
display(plt)
|
||||
end
|
||||
|
||||
(x, status)
|
||||
end
|
||||
290
Lessons/10-12/UNM.m
Normal file
290
Lessons/10-12/UNM.m
Normal file
@ -0,0 +1,290 @@
|
||||
function [ x , status ] = UNM( f , varargin )
|
||||
|
||||
%function [ x , status ] = UNM( f , x , eps , finf , MaxFeval )
|
||||
%
|
||||
% Apply the pure, non-globalised Newton Method for the minimization (or
|
||||
% maximization, since the method does not distinguish between the two) of
|
||||
% the provided one-dimensional (Univariate) function f, which must have
|
||||
% the following interface:
|
||||
%
|
||||
% [ v , varargout ] = f( x )
|
||||
%
|
||||
% Input:
|
||||
%
|
||||
% - x is either a scalar real denoting the input of f(), or [] (empty).
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - v (real, scalar): if x == [] this is the best known lower bound on
|
||||
% the global optimum of f() on the standard interval in which f() is
|
||||
% supposed to be minimised (see next). If x ~= [] then v = f(x).
|
||||
%
|
||||
% - g (real, either scalar or a [ 2 x 1 ] matrix denoting an interval) is
|
||||
% the first optional argument. This also depends on x. if x == [] then
|
||||
% g is a [ 2 x 1 ] matrix denoting the standard interval in which f()
|
||||
% is supposed to be minimised (into which v is the minimum). f() is
|
||||
% never called with x ~= [].
|
||||
%
|
||||
% - H (real, scalar) is the second optional argument. This must only be
|
||||
% specified if x ~= [], and it is the second derivative h = f''(x).
|
||||
% If no such information is available, the function throws error.
|
||||
%
|
||||
% IMPORTANT NOTE: the function requires f() to be able to provide both the
|
||||
% first and the second derivative.
|
||||
%
|
||||
% The other [optional] input parameters:
|
||||
%
|
||||
% - x: (either a real scalar or [], default []): the starting point; if
|
||||
% x == [], the left extreme of default range point provided by f() is
|
||||
% used.
|
||||
%
|
||||
% - eps (real scalar, default value 1e-6): the accuracy in the stopping
|
||||
% criterion: the algorithm is stopped when a point is found such that
|
||||
% the absolute value of the derivative is less than or equal to eps.
|
||||
%
|
||||
% - finf (real scalar, default value 1e+8): since the non-globalised
|
||||
% Newton Method may diverge, a very rough divergence test is
|
||||
% implemented whereby if | f( x ) | >= finf then the algorithm is
|
||||
% stopped with an error condition.
|
||||
%
|
||||
% - MaxFeval (integer scalar, default value 30): the maximum number of
|
||||
% function evaluations (hence, iterations will be not more than
|
||||
% MaxFeval - 2 because at each iteration one function evaluation is
|
||||
% performed, except in the first one when two are).
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - x (real scalar): the best solution found so far.
|
||||
%
|
||||
% - status (string): a string describing the status of the algorithm at
|
||||
% termination
|
||||
%
|
||||
% = 'optimal': the algorithm terminated having proven that x is a(n
|
||||
% approximately) optimal solution, i.e., the diameter of the
|
||||
% restricted range is less than or equal to delta.
|
||||
%
|
||||
% = 'stopped': the algorithm terminated having exhausted the maximum
|
||||
% number of iterations: x is the best solution found so far, but not
|
||||
% necessarily the optimal one
|
||||
%
|
||||
% = 'error': the algorithm found a numerical error that prevents it from
|
||||
% continuing optimization, such as finding f''( x ) very close to 0,
|
||||
% or it is found to be diverging (see finf above).
|
||||
%
|
||||
%{
|
||||
=======================================
|
||||
Author: Antonio Frangioni
|
||||
Date: 29-09-21
|
||||
Version 0.20
|
||||
Copyright Antonio Frangioni
|
||||
=======================================
|
||||
%}
|
||||
|
||||
Plotg = 3;
|
||||
% 1 = the function value / gap are plotted
|
||||
% 2 = the function and the second-order model are plotted
|
||||
% 3 = the function, the first-order model and the second-order model are
|
||||
% plotted (the first-order model has no role in the algorithm, but
|
||||
% this shows how much better the second-order model is than the
|
||||
% first-order one)
|
||||
% all the rest: nothing is plotted
|
||||
|
||||
Interactive = true; % if we pause at every iteration
|
||||
|
||||
% reading and checking input- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if ~ isa( f , 'function_handle' )
|
||||
error( 'f not a function' );
|
||||
end
|
||||
|
||||
[ fStar , range ] = f( [] );
|
||||
|
||||
if isempty( varargin ) || isempty( varargin{ 1 } )
|
||||
x = range( 1 );
|
||||
else
|
||||
x = varargin{ 1 };
|
||||
|
||||
if ~ isreal( x ) || ~ isscalar( x )
|
||||
error( 'x not a real scakar' );
|
||||
end
|
||||
end
|
||||
|
||||
if length( varargin ) > 1
|
||||
eps = varargin{ 2 };
|
||||
if ~ isreal( eps ) || ~ isscalar( eps )
|
||||
error( 'eps is not a real scalar' );
|
||||
end
|
||||
else
|
||||
eps = 1e-6;
|
||||
end
|
||||
|
||||
if length( varargin ) > 2
|
||||
finf = varargin{ 3 };
|
||||
if ~ isreal( finf ) || ~ isscalar( finf )
|
||||
error( 'finf is not a real scalar' );
|
||||
end
|
||||
if finf <= 0
|
||||
error( 'finf must be in > 0' );
|
||||
end
|
||||
else
|
||||
finf = 1e+8;
|
||||
end
|
||||
|
||||
if length( varargin ) > 3
|
||||
MaxFeval = round( varargin{ 4 } );
|
||||
if ~ isscalar( MaxFeval )
|
||||
error( 'MaxFeval is not an integer scalar' );
|
||||
end
|
||||
else
|
||||
MaxFeval = 30;
|
||||
end
|
||||
|
||||
% initializations - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
feval = 0;
|
||||
|
||||
status = 'optimal';
|
||||
|
||||
fbest = Inf;
|
||||
|
||||
if Plotg == 1
|
||||
gap = [];
|
||||
end
|
||||
|
||||
fprintf( 'Univariate Newton''s Method\n');
|
||||
if fStar > - Inf
|
||||
fprintf( 'feval\trel gap\t\tx\t\tf(x)\t\tf''(x)\t\tf''''(x)\n');
|
||||
else
|
||||
fprintf( 'feval\tfbest\t\tx\t\tf''(x)\t\tf''(x)\t\tf''''(x)\n');
|
||||
end
|
||||
|
||||
% main loop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
while true
|
||||
|
||||
% compute f( x ), f'( x ), f''( x ) - - - - - - - - - - - - - - - - - -
|
||||
|
||||
[ fx , f1x , f2x ] = f( x );
|
||||
|
||||
feval = feval + 1;
|
||||
|
||||
if fx < fbest
|
||||
fbest = fx;
|
||||
end
|
||||
|
||||
if abs( f2x ) <= 1e-16
|
||||
status = 'stopped';
|
||||
fprintf( 'numerical issue: f''''(x) = %1.4e\n' , f2x );
|
||||
break;
|
||||
end
|
||||
|
||||
% main logic- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
xn = x - f1x / f2x;
|
||||
|
||||
[ fx , f1x ] = f( x ); % compute f( x ) and f'( x )
|
||||
|
||||
% output statistics - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if fStar > - Inf
|
||||
gapk = ( fbest - fStar ) / max( [ abs( fStar ) 1 ] );
|
||||
|
||||
if Plotg == 1
|
||||
gap( end + 1 ) = gapk;
|
||||
semilogy( gap , 'Color' , 'k' , 'LineWidth' , 2 );
|
||||
xlim( [ 0 35 ] );
|
||||
ylim( [ 1e-15 inf ] );
|
||||
ax = gca;
|
||||
ax.FontSize = 16;
|
||||
ax.Position = [ 0.03 0.07 0.95 0.92 ];
|
||||
ax.Toolbar.Visible = 'off';
|
||||
end
|
||||
else
|
||||
gapk = fbest;
|
||||
end
|
||||
|
||||
fprintf( '%4d\t%1.4e\t%1.8e\t%1.4e\t%1.4e\t%1.4e\n' , feval , ...
|
||||
gapk , x , fx , f1x , f2x );
|
||||
|
||||
if Plotg > 1
|
||||
xm = min( [ x xn ] ) - abs( x - xn ) / 5;
|
||||
xp = max( [ x xn ] ) + abs( x - xn ) / 5;
|
||||
|
||||
warning( 'off' , 'all' );
|
||||
fplot( @(x) f( x ) , [ xm xp ] , 'Color' , 'k' , 'LineWidth' , 1 );
|
||||
|
||||
xlim( [ xm xp ] );
|
||||
yticks( [] );
|
||||
ax = gca;
|
||||
ax.FontSize = 16;
|
||||
ax.Toolbar.Visible = 'off';
|
||||
|
||||
hold on;
|
||||
if Plotg == 3
|
||||
% first-order model is
|
||||
% f( y ) = f( x ) + f'( x )( y - x )
|
||||
% = [ f( x ) - f'( x ) x ]
|
||||
% + f'( x ) y
|
||||
b = f1x;
|
||||
c = fx - f1x * x;
|
||||
fplot( @(x) b * x + c , [ xm xp ] , ...
|
||||
'Color' , 'r' , 'LineWidth' , 1 );
|
||||
end
|
||||
% second-order model is
|
||||
% f( y ) = f( x ) + f'( x )( y - x ) + f''( x )( y - x )^2 / 2
|
||||
% = [ f( x ) - f'( x ) x + f''( x ) x^2 / 2 ]
|
||||
% + [ f'( x ) - f''( x ) x ] y
|
||||
% + f''( x )y^2 / 2
|
||||
a = f2x / 2;
|
||||
b = f1x - f2x * x;
|
||||
c = fx - f1x * x + f2x * x^2 / 2;
|
||||
fplot( @(x) a * x^2 + b * x + c , [ xm xp ] , ...
|
||||
'Color' , 'b' , 'LineWidth' , 1 );
|
||||
if x < xn
|
||||
xticks( [ xm x xn xp ] );
|
||||
xticklabels( { num2str( xm , '%1.1g' ) , 'x^k' , ...
|
||||
'x^{k+1}' , num2str( xp , '%1.1g' ) } );
|
||||
else
|
||||
xticks( [ xm xn x xp ] );
|
||||
xticklabels( { num2str( xm , '%1.1g' ) , 'x^{k+1}' , ...
|
||||
'x^k' , num2str( xp , '%1.1g' ) } );
|
||||
end
|
||||
warning( 'on' , 'all' );
|
||||
hold off;
|
||||
end
|
||||
|
||||
% stopping criteria - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if abs( f1x ) <= eps
|
||||
break;
|
||||
end
|
||||
|
||||
if feval > MaxFeval
|
||||
status = 'stopped';
|
||||
break;
|
||||
end
|
||||
|
||||
if abs( fx ) > finf
|
||||
status = 'error';
|
||||
break;
|
||||
end
|
||||
|
||||
if Interactive
|
||||
pause;
|
||||
end
|
||||
|
||||
% iterate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
x = xn;
|
||||
end
|
||||
|
||||
% end of main loop- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
end % the end- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
1315
Lessons/10-12/lesson.ipynb
generated
Normal file
1315
Lessons/10-12/lesson.ipynb
generated
Normal file
File diff suppressed because one or more lines are too long
65
Lessons/10-12/oneDTestFunctions.jl
Normal file
65
Lessons/10-12/oneDTestFunctions.jl
Normal file
@ -0,0 +1,65 @@
|
||||
using LinearAlgebra
|
||||
|
||||
function custom(x::Union{Nothing, Number})::Tuple{Number, Number, Number, Union{Nothing, Tuple{Number, Number}}}
|
||||
# custom 10-th degree polynomial
|
||||
# f = @(x) 91 * x^2 / 30 - 19 * x^3 / 6 - 54 * x^4 / 25 ...
|
||||
# + 93 * x^5 / 23 - 23 * x^6 / 36 - 121 * x^7 / 93 ...
|
||||
# + 72 * x^8 / 91 - 13 * x^9 / 74 + 9 * x^10 / 640
|
||||
#
|
||||
# f'(x)
|
||||
# (9*x^9)/64 - (117*x^8)/74 + (576*x^7)/91 - (847*x^6)/93
|
||||
# - (23*x^5)/6 + (465*x^4)/23 - (216*x^3)/25 - (19*x^2)/2 + (91*x)/15
|
||||
#
|
||||
# f''(x)
|
||||
# (81*x^8)/64 - (468*x^7)/37 + (576*x^6)/13 - (1694*x^5)/31
|
||||
# - (115*x^4)/6 + (1860*x^3)/23 - (648*x^2)/25 - 19*x + 91/15
|
||||
|
||||
if x == nothing # informative call
|
||||
return (0, 0, 0, (-0.5, 3))
|
||||
else
|
||||
f(x) = 91 * x^2 / 30 - 19 * x^3 / 6 - 54 * x^4 / 25 +
|
||||
93 * x^5 / 23 - 23 * x^6 / 36 - 121 * x^7 / 93 +
|
||||
72 * x^8 / 91 - 13 * x^9 / 74 + 9 * x^10 / 640
|
||||
Df(x) = 91 * x / 15 - 19 * x^2 / 2 - 216 * x^3 / 25 + 465 * x^4 / 23 -
|
||||
23 * x^5 / 6 - 847 * x^6 / 93 + 576 * x^7 / 91 -
|
||||
117 * x^8 / 74 + 9 * x^9 / 64
|
||||
DDf(x) = 91 / 15 - 19 * x - 648 * x^2 / 25 + 1860 * x^3 / 23 -
|
||||
115 * x^4 / 6 - 1694 * x^5 / 31 + 576 * x^6 / 13 -
|
||||
468 * x^7 / 37 + 81 * x^8 / 64
|
||||
return (f(x), Df(x), DDf(x), nothing)
|
||||
end
|
||||
end # custom
|
||||
|
||||
|
||||
|
||||
function genericquad(Q::Matrix, q::Vector, x::Nothing)::Tuple{Number, Nothing, Nothing, Tuple{Vector, Vector}}
|
||||
# generic quadratic function f(x) = x' * Q * x / 2 + q' * x
|
||||
# informative call
|
||||
|
||||
if minimum(eigvals(Q)) > 1e-14
|
||||
xStar = Q \ -q
|
||||
v = 0.5 * dot(xStar', Q, xStar) + dot(q', xStar)
|
||||
else
|
||||
v = -Inf
|
||||
end
|
||||
return (v, nothing, nothing, ([-0.5, -0.5], [3, 3]))
|
||||
end # genericquad
|
||||
|
||||
function genericquad(Q::Matrix, q::Vector, x::Vector)::Tuple{Number, Vector, Matrix, Nothing}
|
||||
# generic quadratic function f(x) = x' * Q * x / 2 + q' * x
|
||||
|
||||
if !(size(x) == (2,))
|
||||
throw(ArgumentError("genericquad: x is of wrong size"))
|
||||
end
|
||||
v = 0.5 * dot(x', Q, x) + dot(q', x) # f(x)
|
||||
v2 = Q * x + q # \nabla f(x)
|
||||
v3 = Q # \nabla^2 f(x)
|
||||
|
||||
return (v, v2, v3, nothing)
|
||||
end # genericquad
|
||||
|
||||
|
||||
|
||||
function oneDTestFunctions()::Array{Any}
|
||||
return [custom, x -> genericquad([6 -2;-2 6], [10; 5], x)]
|
||||
end
|
||||
128
Lessons/10-12/oneDTestFunctions.m
Normal file
128
Lessons/10-12/oneDTestFunctions.m
Normal file
@ -0,0 +1,128 @@
|
||||
function TF = oneDTestFunctions()
|
||||
|
||||
%function TF = oneDTestFunctions()
|
||||
%
|
||||
% Produces a cell array of function handlers, useful to test unconstrained
|
||||
% one-dimensional optimization algorithms.
|
||||
%
|
||||
% Each function in the array has the following interface:
|
||||
%
|
||||
% [ v , varargout ] = f( x )
|
||||
%
|
||||
% Input:
|
||||
%
|
||||
% - x is either a scalar real denoting the input of f(), or [] (empty).
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - v (real, scalar): if x == [] this is the best known lower bound on
|
||||
% the global optimum of f() on the standard interval in which f() is
|
||||
% supposed to be minimised (see next). If x ~= [] then v = f(x).
|
||||
%
|
||||
% - g (real, either scalar or a [ 1 x 2 ] matrix denoting an interval) is
|
||||
% the first optional argument. This also depends on x. if x == [] then
|
||||
% g is a [ 1 x 2 ] matrix denoting the standard interval in which f()
|
||||
% is supposed to be minimised (into which v is the minimum). If x ~= []
|
||||
% then g is a scalar containing the dervative g = f'(x) (or a
|
||||
% subgradient of f() in x if f() is not differentiable at x).
|
||||
%
|
||||
% - H (real, scalar) is the second optional argument. This must only be
|
||||
% specified if x ~= [], and it is the second derivative h = f''(x).
|
||||
% If no such information is available, the function throws error.
|
||||
%
|
||||
% The current list of functions is the following:
|
||||
%
|
||||
% 1 Taylored nasty 10-th degree polynomial with a local minimum in 0
|
||||
% (with value 0), a local minimum around -1, a saddle point around
|
||||
% +1, a local maximum around +2 and another local minimum around +3.
|
||||
% Thought to be plotted in [ -1.2 , 3.1 ], and minimised in
|
||||
% [ -0.5 , 3 ] (the global minimim there being 0). Note that, by
|
||||
% taking [ -1 , 3 ] instead, blind dycothomic search would hit jackpot
|
||||
% in two iterations by sheer luck.
|
||||
%
|
||||
%{
|
||||
=======================================
|
||||
Author: Antonio Frangioni
|
||||
Date: 08-11-18
|
||||
Version 1.01
|
||||
Copyright Antonio Frangioni
|
||||
=======================================
|
||||
%}
|
||||
|
||||
TF = cell( 1 , 1 );
|
||||
%TF{ 1 } = @(x) genericquad( [ 6 -2 ; -2 6 ] , [ 10 ; 5 ] , x );
|
||||
TF{ 1 } = @custom;
|
||||
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
% function [ v , varargout ] = genericquad( Q , q , x )
|
||||
% % generic quadratic function f(x) = x' * Q * x / 2 + q' * x
|
||||
%
|
||||
% if isempty( x ) % informative call
|
||||
% if min( eig( Q ) ) > 1e-14
|
||||
% xStar = Q \ -q;
|
||||
% v = 0.5 * xStar' * Q * xStar + q' * xStar;
|
||||
% else
|
||||
% v = - Inf;
|
||||
% end
|
||||
% if nargout > 1
|
||||
% varargout{ 1 } = [ 0 ; 0 ];
|
||||
% end
|
||||
% else
|
||||
% if ~ isequal( size( x ) , [ 2 1 ] )
|
||||
% error( 'genericquad: x is of wrong size' );
|
||||
% end
|
||||
% v = 0.5 * x' * Q * x + q' * x; % f(x)
|
||||
% if nargout > 1
|
||||
% varargout{ 1 } = Q * x + q; % \nabla f(x)
|
||||
% if nargout > 2
|
||||
% varargout{ 2 } = Q; % \nabla^2 f(x)
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
% end % genericquad
|
||||
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
function [ v , varargout ] = custom( x )
|
||||
% custom 10-th degree polynomial
|
||||
% syms x
|
||||
% f = @(x) 91 * x^2 / 30 - 19 * x^3 / 6 - 54 * x^4 / 25 ...
|
||||
% + 93 * x^5 / 23 - 23 * x^6 / 36 - 121 * x^7 / 93 ...
|
||||
% + 72 * x^8 / 91 - 13 * x^9 / 74 + 9 * x^10 / 640
|
||||
%
|
||||
% diff( f , x )
|
||||
% 9*x^9)/64 - (117*x^8)/74 + (576*x^7)/91 - (847*x^6)/93
|
||||
% - (23*x^5)/6 + (465*x^4)/23 - (216*x^3)/25 - (19*x^2)/2 + (91*x)/15
|
||||
%
|
||||
% diff( f , x , 2 )
|
||||
% (81*x^8)/64 - (468*x^7)/37 + (576*x^6)/13 - (1694*x^5)/31
|
||||
% - (115*x^4)/6 + (1860*x^3)/23 - (648*x^2)/25 - 19*x + 91/15
|
||||
|
||||
if isempty( x ) % informative call
|
||||
v = 0;
|
||||
if nargout > 1
|
||||
varargout{ 1 } = [ -0.5 3 ];
|
||||
end
|
||||
else
|
||||
v = 91 * x^2 / 30 - 19 * x^3 / 6 - 54 * x^4 / 25 ...
|
||||
+ 93 * x^5 / 23 - 23 * x^6 / 36 - 121 * x^7 / 93 ...
|
||||
+ 72 * x^8 / 91 - 13 * x^9 / 74 + 9 * x^10 / 640;
|
||||
if nargout > 1
|
||||
g = 91 * x / 15 - 19 * x^2 / 2 - 216 * x^3 / 25 + 465 * x^4 / 23 ...
|
||||
- 23 * x^5 / 6 - 847 * x^6 / 93 + 576 * x^7 / 91 ...
|
||||
- 117 * x^8 / 74 + 9 * x^9 / 64;
|
||||
varargout{ 1 } = g; % f'(x)
|
||||
if nargout > 2
|
||||
h = 91 / 15 - 19 * x - 648 * x^2 / 25 + 1860 * x^3 / 23 ...
|
||||
- 115 * x^4 / 6 - 1694 * x^5 / 31 + 576 * x^6 / 13 ...
|
||||
- 468 * x^7 / 37 + 81 * x^8 / 64;
|
||||
varargout{ 2 } = h; % f''(x)
|
||||
end
|
||||
end
|
||||
end
|
||||
end % custom
|
||||
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user