Added Project and Report

This commit is contained in:
elvis
2024-07-30 14:43:25 +02:00
parent c828453e94
commit 3ad6f7f86f
311 changed files with 13490 additions and 3280 deletions

223
Lessons/10-12/DIS.jl Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because one or more lines are too long

View 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

View 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