first commit with current lessons
This commit is contained in:
1224
10-04/GMQ.ipynb
Normal file
1224
10-04/GMQ.ipynb
Normal file
File diff suppressed because one or more lines are too long
247
10-04/GMQ.jl
Normal file
247
10-04/GMQ.jl
Normal file
@ -0,0 +1,247 @@
|
||||
using LinearAlgebra
|
||||
using Printf
|
||||
using Plots
|
||||
|
||||
function gmq(Q::Matrix, q::Vector; x::Union{Vector, Nothing}=nothing, fStar::Real=-Inf, alpha::Real=0 , MaxIter::Int=1000 , eps::Real=1e-6, plt::Union{Plots.Plot, Nothing}=nothing, Plotf::Int=2, printing::Bool=true)::Tuple{Vector, String}
|
||||
# Plotf
|
||||
# 0 = nothing is plotted
|
||||
# 1 = the function value / gap are plotted
|
||||
# 2 = the level sets of f and the trajectory are plotted (when n = 2)
|
||||
|
||||
Interactive = true # if we pause at every iteration
|
||||
|
||||
Streamlined = true # if the streamlined version of the algorithm, with
|
||||
# only one O( n^2 ) operation per iteration, is used
|
||||
|
||||
# reading and checking input- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if !isreal(Q)
|
||||
throw(ArgumentError(Q, "Q not a real matrix"))
|
||||
end
|
||||
|
||||
n = size(Q, 1)
|
||||
|
||||
if n <= 1
|
||||
throw(ArgumentError(Q, "Q is too small"))
|
||||
end
|
||||
|
||||
if n != size(Q, 2)
|
||||
throw(ArgumentError(Q, "Q is not square"))
|
||||
end
|
||||
|
||||
if !isreal(q)
|
||||
throw(ArgumentError(q, "q not a real vector"))
|
||||
end
|
||||
|
||||
if size(q, 1) != n
|
||||
throw(ArgumentError(q, "q size does not match with Q"))
|
||||
end
|
||||
|
||||
if x == nothing
|
||||
x = zeros(n, 1)
|
||||
end
|
||||
|
||||
if !isreal(x)
|
||||
throw(ArgumentError(x, "x not a real vector"))
|
||||
end
|
||||
|
||||
if size(x, 1) != n
|
||||
throw(ArgumentError(x, "x size does not match with Q"))
|
||||
end
|
||||
|
||||
if MaxIter < 1
|
||||
throw(ArgumentError(MaxIter, "MaxIter too small"))
|
||||
end
|
||||
|
||||
if eps < 0
|
||||
throw(ArgumentError(eps, "eps can not be negative"))
|
||||
end
|
||||
|
||||
# initializations - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if printing
|
||||
print("Gradient method for quadratic functions ")
|
||||
if alpha == 0
|
||||
print("(optimal stepsize)\n")
|
||||
else
|
||||
print("(fixed stepsize)\n")
|
||||
end
|
||||
|
||||
print("iter\tf(x)\t\t\t||g||")
|
||||
end
|
||||
|
||||
if fStar > - Inf
|
||||
if printing
|
||||
print("\t\tgap\t\trate")
|
||||
end
|
||||
prevf = Inf
|
||||
end
|
||||
if printing
|
||||
if alpha == 0
|
||||
print("\t\talpha")
|
||||
end
|
||||
|
||||
print("\n\n")
|
||||
end
|
||||
|
||||
i = 0;
|
||||
if Plotf == 1
|
||||
gap = []
|
||||
end
|
||||
|
||||
if Streamlined
|
||||
g = Q * x + q
|
||||
end
|
||||
|
||||
if Plotf == 1 && plt == nothing
|
||||
plt = plot(yscale = :log,
|
||||
xlims=(0, MaxIter),
|
||||
ylims=(1e-15, Inf),
|
||||
guidefontsize=16)
|
||||
elseif Plotf == 2 && plt == nothing
|
||||
plt = plot()
|
||||
end
|
||||
|
||||
status = ""
|
||||
|
||||
# main loop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
while true
|
||||
if !Streamlined
|
||||
g = Q * x + q
|
||||
end
|
||||
|
||||
ng = norm(g)
|
||||
|
||||
f = dot((g + q)', x) / 2 # 1/2 x^T Q x + q x
|
||||
# = 1/2 ( x^T Q x + 2 q x )
|
||||
# = 1/2 x^T ( Q x + q + q )
|
||||
# = 1/2 ( q + g ) x
|
||||
i += 1
|
||||
|
||||
if printing
|
||||
@printf("%4d\t%1.8e\t\t%1.4e", i, f, ng)
|
||||
end
|
||||
if fStar > -Inf
|
||||
gapk = (f - fStar)/maximum([abs(fStar), 1])
|
||||
if printing
|
||||
@printf("\t%1.4e", gapk)
|
||||
|
||||
if prevf < Inf
|
||||
@printf("\t%1.4e", (f - fStar)/(prevf - fStar))
|
||||
else
|
||||
@printf("\t\t")
|
||||
end
|
||||
end
|
||||
|
||||
prevf = f
|
||||
|
||||
if Plotf == 1
|
||||
push!(gap, gapk)
|
||||
end
|
||||
end
|
||||
|
||||
# stopping criteria - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if ng <= eps
|
||||
status = "optimal"
|
||||
if alpha == 0 && printing
|
||||
print("\n")
|
||||
end
|
||||
break
|
||||
end
|
||||
|
||||
if i > MaxIter
|
||||
status = "stopped"
|
||||
if alpha == 0 && printing
|
||||
print("\n")
|
||||
end
|
||||
break
|
||||
end
|
||||
|
||||
# compute step size - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# meanwhile, check if f is unbounded below
|
||||
# note that if alpha > 0 this is only used for the unboundedness check
|
||||
# which is a bit of a waste, but there you go; anyway, in the
|
||||
# streamlined version this only costs O( n )
|
||||
|
||||
if Streamlined
|
||||
v = Q * g;
|
||||
den = dot(g', v)
|
||||
else
|
||||
den = dot(g', Q * g)
|
||||
end
|
||||
|
||||
if den <= 1e-14
|
||||
# this is actually two different cases:
|
||||
# - g' * Q * g = 0, i.e., f is linear along g, and since the
|
||||
# gradient is not zero, it is unbounded below
|
||||
#
|
||||
# - g' * Q * g < 0, i.e., g is a direction of negative curvature for
|
||||
# f, which is then necessarily unbounded below
|
||||
if printing
|
||||
if alpha == 0
|
||||
print("\n")
|
||||
end
|
||||
@printf("g' * Q * g = %1.4e ==> unbounded\n", den)
|
||||
end
|
||||
status = "unbounded"
|
||||
break
|
||||
end
|
||||
|
||||
if alpha > 0
|
||||
t = alpha
|
||||
else
|
||||
t = ng^2 / den # stepsize
|
||||
if printing
|
||||
@printf("\t%1.2e", t)
|
||||
end
|
||||
end
|
||||
|
||||
if printing
|
||||
print("\n")
|
||||
end
|
||||
|
||||
# compute new point - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
# possibly plot the trajectory
|
||||
if n == 2 && Plotf == 2
|
||||
PXY = hcat(vec(x), vec(x - t * g))
|
||||
plot!(PXY[1,:],
|
||||
PXY[2,:],
|
||||
linestyle=:solid,
|
||||
linewidth=2,
|
||||
markershape=:circle,
|
||||
seriescolor=colorant"black",
|
||||
label="")
|
||||
end
|
||||
|
||||
x = x - t * g
|
||||
|
||||
if Streamlined
|
||||
g = g - t * v
|
||||
end
|
||||
|
||||
if Interactive
|
||||
#readline()
|
||||
end
|
||||
|
||||
if Plotf != 0
|
||||
#IJulia.clear_output(true)
|
||||
#display(plt)
|
||||
end
|
||||
end
|
||||
|
||||
if Plotf == 1
|
||||
plot!(plt,
|
||||
gap,
|
||||
linewidth=2,
|
||||
seriescolor=colorant"black")
|
||||
display(plt)
|
||||
elseif Plotf == 2
|
||||
display(plt)
|
||||
end
|
||||
(vec(x), status)
|
||||
end
|
||||
319
10-04/GMQ.m
Normal file
319
10-04/GMQ.m
Normal file
@ -0,0 +1,319 @@
|
||||
function [ x , status ] = GMQ( Q , q , varargin )
|
||||
|
||||
%function [ x , status ] = GMQ( Q , q , x , fStar , alpha , MaxIter , eps )
|
||||
%
|
||||
% Apply the Gradient Method (a.k.a., Steepest Descent algorithm) to the
|
||||
% minimization of the quadratic function
|
||||
%
|
||||
% f( x ) = 1/2 x^T Q x + q x
|
||||
%
|
||||
% Input:
|
||||
%
|
||||
% - Q ([ n x n ] real symmetric matrix, not necessarily positive
|
||||
% semidefinite): the quadratic part of f
|
||||
%
|
||||
% - q ([ n x 1 ] real column vector): the linear part of f
|
||||
%
|
||||
% - x ([ n x 1 ] real column vector or empty, optional): the point where to
|
||||
% start the algorithm from; if not provided or empty, the all-0 n-vector
|
||||
% is used
|
||||
%
|
||||
% - fStar (real scalar, optional, default value Inf): optimal value of f.
|
||||
% if a non-Inf value is provided it is used to print out stasistics about
|
||||
% the convergence speed of the algorithm
|
||||
%
|
||||
% - alpha (real scalar, optional, default value 0): if alpha > 0, then the
|
||||
% fixed-stepsize version of the algorithm is run with alpha as the fixed
|
||||
% stepsize, otherwise the standard exact line search is used
|
||||
%
|
||||
% - MaxIter (integer scalar, optional, default value 1000): the maximum
|
||||
% number of iterations
|
||||
%
|
||||
% - eps (real scalar, optional, default value 1e-6): the accuracy in the
|
||||
% stopping criterion: the algorithm is stopped when the norm of the
|
||||
% gradient is less than or equal to eps
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - x ([ n x 1 ] real column vector): either the best solution found so far
|
||||
% (possibly the optimal one) or a direction proving the problem is
|
||||
% unbounded below, depending on case
|
||||
%
|
||||
% - 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 norm of the gradient at x
|
||||
% is less than the required threshold
|
||||
%
|
||||
% = 'unbounded': the algorithm terminated having proven that the problem
|
||||
% is unbounded below: x contains a direction along which f is
|
||||
% decreasing to - Inf, either because f is linear along x and the
|
||||
% directional derivative is not zero, or because x is a direction with
|
||||
% negative curvature
|
||||
%
|
||||
% = '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
|
||||
%
|
||||
%{
|
||||
=======================================
|
||||
Author: Antonio Frangioni
|
||||
Date: 26-12-22
|
||||
Version 0.2
|
||||
Copyright Antonio Frangioni
|
||||
=======================================
|
||||
%}
|
||||
|
||||
Plotf = 2;
|
||||
% 0 = nothing is plotted
|
||||
% 1 = the function value / gap are plotted
|
||||
% 2 = the level sets of f and the trajectory are plotted (when n = 2)
|
||||
|
||||
Interactive = true; % if we pause at every iteration
|
||||
|
||||
Streamlined = true; % if the streamlined version of the algorithm, with
|
||||
% only one O( n^2 ) operation per iteration, is used
|
||||
|
||||
% reading and checking input- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if ~ isreal( Q )
|
||||
error( 'Q not a real matrix' );
|
||||
end
|
||||
|
||||
n = size( Q , 1 );
|
||||
|
||||
if n <= 1
|
||||
error( 'Q is too small' );
|
||||
end
|
||||
|
||||
if n ~= size( Q , 2 )
|
||||
error( 'Q is not square' );
|
||||
end
|
||||
|
||||
if ~ isreal( q )
|
||||
error( 'q not a real vector' );
|
||||
end
|
||||
|
||||
if size( q , 2 ) ~= 1
|
||||
error( 'q is not a (column) vector' );
|
||||
end
|
||||
|
||||
if size( q , 1 ) ~= n
|
||||
error( 'q size does not match with Q' );
|
||||
end
|
||||
|
||||
if isempty( varargin ) || isempty( varargin{ 1 } )
|
||||
x = zeros( n , 1 );
|
||||
else
|
||||
x = varargin{ 1 };
|
||||
|
||||
if ~ isreal( x )
|
||||
error( 'x not a real vector' );
|
||||
end
|
||||
|
||||
if size( x , 2 ) ~= 1
|
||||
error( 'x is not a (column) vector' );
|
||||
end
|
||||
|
||||
if size( x , 1 ) ~= n
|
||||
error( 'x size does not match with Q' );
|
||||
end
|
||||
end
|
||||
|
||||
if length( varargin ) > 1
|
||||
fStar = varargin{ 2 };
|
||||
if ~ isreal( fStar ) || ~ isscalar( fStar )
|
||||
error( 'fStar is not a real scalar' );
|
||||
end
|
||||
else
|
||||
fStar = - Inf;
|
||||
end
|
||||
|
||||
if length( varargin ) > 2
|
||||
alpha = varargin{ 3 };
|
||||
if ~ isreal( alpha ) || ~ isscalar( alpha )
|
||||
error( 'alpha is not a real scalar' );
|
||||
end
|
||||
else
|
||||
alpha = 0;
|
||||
end
|
||||
|
||||
if length( varargin ) > 3
|
||||
MaxIter = round( varargin{ 4 } );
|
||||
if ~ isscalar( MaxIter )
|
||||
error( 'MaxIter is not an integer scalar' );
|
||||
end
|
||||
if MaxIter < 1
|
||||
error( 'MaxIter too small' );
|
||||
end
|
||||
else
|
||||
MaxIter = 1000;
|
||||
end
|
||||
|
||||
if length( varargin ) > 4
|
||||
eps = varargin{ 5 };
|
||||
if ~ isreal( eps ) || ~ isscalar( eps )
|
||||
error( 'eps is not a real scalar' );
|
||||
end
|
||||
if eps < 0
|
||||
error( 'eps can not be negative' );
|
||||
end
|
||||
else
|
||||
eps = 1e-6;
|
||||
end
|
||||
|
||||
% initializations - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
fprintf( 'Gradient method for quadratic functions ' );
|
||||
if alpha == 0
|
||||
fprintf( '(optimal stepsize)\n' );
|
||||
else
|
||||
fprintf( '(fixed stepsize)\n' );
|
||||
end
|
||||
fprintf( 'iter\tf(x)\t\t\t||g||');
|
||||
if fStar > - Inf
|
||||
fprintf( '\t\tgap\t\trate');
|
||||
prevf = Inf;
|
||||
end
|
||||
if alpha == 0
|
||||
fprintf( '\t\talpha' );
|
||||
end
|
||||
fprintf( '\n\n' );
|
||||
|
||||
i = 0;
|
||||
|
||||
if Plotf == 1
|
||||
gap = [];
|
||||
end
|
||||
|
||||
if Streamlined
|
||||
g = Q * x + q;
|
||||
end
|
||||
|
||||
% main loop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
while true
|
||||
% compute function value and gradient - - - - - - - - - - - - - - - - -
|
||||
|
||||
if ~ Streamlined
|
||||
g = Q * x + q;
|
||||
end
|
||||
|
||||
ng = norm( g );
|
||||
f = ( g + q )' * x / 2; % 1/2 x^T Q x + q x = 1/2 ( x^T Q x + 2 q x )
|
||||
% = 1/2 x^T ( Q x + q + q ) = 1/2 ( q + g ) x
|
||||
i = i + 1;
|
||||
|
||||
% output statistics - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
fprintf( '%4d\t%1.8e\t\t%1.4e' , i , f , ng );
|
||||
if fStar > - Inf
|
||||
gapk = ( f - fStar ) / max( [ abs( fStar ) 1 ] );
|
||||
|
||||
fprintf( '\t%1.4e' , gapk );
|
||||
if prevf < Inf
|
||||
fprintf( '\t%1.4e' , ( f - fStar ) / ( prevf - fStar ) );
|
||||
else
|
||||
fprintf( '\t\t' );
|
||||
end
|
||||
prevf = f;
|
||||
|
||||
if Plotf == 1
|
||||
gap( end + 1 ) = gapk;
|
||||
semilogy( gap , 'Color' , 'k' , 'LineWidth' , 2 );
|
||||
xlim( [ 0 MaxIter ] );
|
||||
ylim( [ 1e-15 inf ] );
|
||||
ax = gca;
|
||||
ax.FontSize = 16;
|
||||
ax.Position = [ 0.03 0.07 0.95 0.92 ];
|
||||
ax.Toolbar.Visible = 'off';
|
||||
end
|
||||
end
|
||||
|
||||
% stopping criteria - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if ng <= eps
|
||||
status = 'optimal';
|
||||
if alpha == 0
|
||||
fprintf( '\n' );
|
||||
end
|
||||
break;
|
||||
end
|
||||
|
||||
if i > MaxIter
|
||||
status = 'stopped';
|
||||
if alpha == 0
|
||||
fprintf( '\n' );
|
||||
end
|
||||
break;
|
||||
end
|
||||
|
||||
% compute step size - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% meanwhile, check if f is unbounded below
|
||||
% note that if alpha > 0 this is only used for the unboundedness check
|
||||
% which is a bit of a waste, but there you go; anyway, in the
|
||||
% streamlined version this only costs O( n )
|
||||
|
||||
if Streamlined
|
||||
v = Q * g;
|
||||
den = g' * v;
|
||||
else
|
||||
den = g' * Q * g;
|
||||
end
|
||||
|
||||
if den <= 1e-14
|
||||
% this is actually two different cases:
|
||||
%
|
||||
% - g' * Q * g = 0, i.e., f is linear along g, and since the
|
||||
% gradient is not zero, it is unbounded below
|
||||
%
|
||||
% - g' * Q * g < 0, i.e., g is a direction of negative curvature for
|
||||
% f, which is then necessarily unbounded below
|
||||
%
|
||||
if alpha == 0
|
||||
fprintf( '\n' );
|
||||
end
|
||||
fprintf( 'g'' * Q * g = %1.4e ==> unbounded\n' , den );
|
||||
status = 'unbounded';
|
||||
break;
|
||||
end
|
||||
|
||||
if alpha > 0
|
||||
t = alpha;
|
||||
else
|
||||
t = ng^2 / den; % stepsize
|
||||
fprintf( '\t%1.2e' , t );
|
||||
end
|
||||
|
||||
fprintf( '\n' );
|
||||
|
||||
% compute new point - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
% possibly plot the trajectory
|
||||
if n == 2 && Plotf == 2
|
||||
PXY = [ x , x - t * g ];
|
||||
line( 'XData' , PXY( 1 , : ) , 'YData' , PXY( 2 , : ) , ...
|
||||
'LineStyle' , '-' , 'LineWidth' , 2 , 'Marker' , 'o' , ...
|
||||
'Color' , [ 0 0 0 ] );
|
||||
end
|
||||
|
||||
x = x - t * g;
|
||||
|
||||
if Streamlined
|
||||
g = g - t * v;
|
||||
end
|
||||
|
||||
% iterate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if Interactive
|
||||
pause;
|
||||
end
|
||||
end
|
||||
|
||||
% end of main loop- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
end % the end- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
111
10-04/genQf.jl
Normal file
111
10-04/genQf.jl
Normal file
@ -0,0 +1,111 @@
|
||||
using Random
|
||||
using LinearAlgebra
|
||||
|
||||
function genQf(n::Integer; fseed::Integer=0, rank::Real=1.1, conv::Real=1, ecc::Real=0.99, dom::Real=1, box::Real=1, q::Union{Vector, Nothing}=nothing, v::Union{Real, Nothing}=nothing)::Tuple{Matrix, Union{Vector, Nothing}, Union{Real, Nothing}}
|
||||
if n <= 0
|
||||
throw(ArgumentError(n, "n must be > 0"))
|
||||
end
|
||||
if rank <= 0
|
||||
throw(ArgumentError(rank, "rank must be > 0"))
|
||||
end
|
||||
if !(0 <= conv <= 1)
|
||||
throw(ArgumentError(conv, "conv must be in [0, 1]"))
|
||||
end
|
||||
if !(0 <= ecc < 1)
|
||||
throw(ArgumentError(ecc, "ecc must be in [0, 1)"))
|
||||
end
|
||||
if dom < 0
|
||||
throw(ArgumentError(dom, "dom must be >= 0"))
|
||||
end
|
||||
if box == 0
|
||||
throw(ArgumentError(box, "box must not be 0"))
|
||||
end
|
||||
|
||||
Random.seed!(fseed)
|
||||
|
||||
# generate Q- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# first step: generate the appropriate rank and positive / negative
|
||||
# definiteness
|
||||
|
||||
r = round(Int, rank * n)
|
||||
p = round(Int, r * conv)
|
||||
|
||||
if p > 0
|
||||
G = rand(p, n)
|
||||
Q = G' * G
|
||||
else
|
||||
Q = zeros(n, n)
|
||||
end
|
||||
|
||||
if r > p
|
||||
G = rand(r - p, n)
|
||||
Q = Q - (G' * G)
|
||||
end
|
||||
|
||||
# second step: if dom ~= 1, modify the diagonal
|
||||
# increase or decrease randomly each element by [ - 1/3 , 1/3 ] of its
|
||||
# initial value, then multiply it by dom
|
||||
|
||||
if dom != 1
|
||||
D = diag(Q)
|
||||
D = D .* (1 .+ (2 .* rand(n, 1) .- 1) ./ 3)
|
||||
D = dom * D
|
||||
@view(Q[diagind(Q)]) .= D
|
||||
end
|
||||
|
||||
# compute eigenvalue decomposition
|
||||
F = eigen(Q); # V * D * V' = Q , D( 1 , 1 ) = \lambda_n
|
||||
V = F.vectors
|
||||
D = F.values
|
||||
|
||||
if D[1] > 1e-14
|
||||
# modify eccentricity only if \lambda_n > 0, for when \lambda_n = 0 the
|
||||
# eccentricity is 1 by default
|
||||
#
|
||||
# the formula is:
|
||||
#
|
||||
# \lambda_i - \lambda_n 2 * ecc
|
||||
# \lambda_i = \lambda_n + --------------------- * \lambda_n -------
|
||||
# \lambda_1 - \lambda_n 1 - ecc
|
||||
#
|
||||
# This leaves \lambda_n unchanged, and modifies all the other ones
|
||||
# proportionally so that
|
||||
#
|
||||
# \lambda_1 - \lambda_n
|
||||
# --------------------- = ecc (exercise: check)
|
||||
# \lambda_1 - \lambda_n
|
||||
l = D[1] .* ones(n) + ((D[1] / (D[n] - D[1])) * (2 * ecc / (1 - ecc))) .* (D - D[1] .* ones(n))
|
||||
Q = V * diagm(l) * V';
|
||||
end
|
||||
|
||||
if q != nothing || v != nothing
|
||||
# if so required generate q- - - - - - - - - - - - - - - - - - - - - - -
|
||||
#
|
||||
# we first generate the unconstrained minimum x_* of the problem in the
|
||||
# box [ - abs( box ) , abs( box ) ] and then we set q = - Q * x_*
|
||||
|
||||
x = 2 * abs(box) .* rand(n) .- abs(box)
|
||||
q = -Q * x
|
||||
|
||||
# if so required, we now randomly destroy the alignment between q and
|
||||
# the image of Q so as to make it hard to solve Q x = q
|
||||
|
||||
if ( box < 0 ) && (D[1] <= 1e-14 )
|
||||
q = q .* ((4/3) .* rand(n) .- (2/3))
|
||||
end
|
||||
end
|
||||
|
||||
if v != nothing
|
||||
# if so required compute v. - - - - - - - - - - - - - - - - - - - - -
|
||||
# v is finite-valued only if either Q is strictly positive definite
|
||||
# or it is positive semidefinite but q has been constructed in such
|
||||
# a was that Q * x + q = 0 has a solution (that is the x we have)
|
||||
if (D[1] > 1e-14) || ((D[1] > -1e-14) && (box > 0))
|
||||
v = dot(q', x) / 2
|
||||
else
|
||||
v = -Inf
|
||||
end
|
||||
end
|
||||
|
||||
return (Q, q, v)
|
||||
end
|
||||
278
10-04/getQf.m
Normal file
278
10-04/getQf.m
Normal file
@ -0,0 +1,278 @@
|
||||
function [ Q , varargout ] = genQf( n , varargin )
|
||||
|
||||
%function [ Q , q , v ] = genQf( n , seed , rank , conv , ecc , dom , box )
|
||||
%
|
||||
% Produces the data structure encoding a Quadratic function
|
||||
%
|
||||
% f( x ) = (1/2) x^T * Q * x + q * x
|
||||
%
|
||||
% Input:
|
||||
%
|
||||
% - n (integer, scalar): the size of the problem
|
||||
%
|
||||
% - seed (integer, default 0): the seed for the random number generator
|
||||
%
|
||||
% - rank (real, scalar, default 1.1): Q will be obtained as Q = G^T G, with
|
||||
% G a m \times n random matrix with m = rank * n (almost, see "conv"
|
||||
% below). If rank > 1 then Q can be expected to be full-rank, if
|
||||
% rank < 1 it will not
|
||||
%
|
||||
% - conv (real, scalar, default 1): a parameter controlling whether Q is
|
||||
% positive (semi)definite, negative (semi)definite, or indefinite. This
|
||||
% is done by actually computing Q as Q = G_+^T G_+ - G_-^T G_-. The m
|
||||
% rows of G are partitioned according to conv, i.e., m * conv rows are
|
||||
% put in G_+ while m * ( 1 - conv ) rows are put in G_-. Hence, conv = 1
|
||||
% means that Q is positive (semi)definite, conv = 1 means that Q is
|
||||
% negative (semi)definite, and any value in the middle means that Q is
|
||||
% indefinite, with "close to 1" meaning "almost positive (semi)definite",
|
||||
% and "close to 0" meaning "almost negative (semi)definite"
|
||||
%
|
||||
% - ecc (real, scalar, default 0.99): the eccentricity of Q, i.e., the
|
||||
% ratio ( \lambda_1 - \lambda_n ) / ( \lambda_1 + \lambda_n ), with
|
||||
% \lambda_1 the largest eigenvalue and \lambda_n the smallest one. Note
|
||||
% that this makes sense only if \lambda_n > 0, for otherwise the
|
||||
% eccentricity is always 1; hence, this setting is ignored if
|
||||
% \lambda_n = 0, i.e., Q is not full-rank (see above). An eccentricity of
|
||||
% 0 means that all eigenvalues are equal, as eccentricity -> 1 the
|
||||
% largest eigenvalue gets larger and larger w.r.t. the smallest one
|
||||
%
|
||||
% - dom (real, scalar, default 1): possibly modifies the matrix by making
|
||||
% it more or less diagonally dominant. This is obtained by multiplying
|
||||
% each diagonal element by a random number uniformly picked in the
|
||||
% interval [ 2 * diag / 3 , 4 * diag / 3 ] (and therefore with average
|
||||
% value diag). If diag >> 1 this increases the diagonal dominance, if
|
||||
% diag << 1 this decreases it. The operation is only performed if
|
||||
% diag ~= 1.
|
||||
%
|
||||
% - box (real, scalar, default 1): this parameter controls the generation
|
||||
% of q. This is done by first randomly generating one (tentatively)
|
||||
% optimal solution x_* to the unconstrained minimization of f( x ) in the
|
||||
% symmetric hypercube of size 2 * abs( box ), i.e., by uniformly drawing
|
||||
% each of its entries in the interval [ - abs( box ) , abs( box ) ];
|
||||
% then, q is generated as - Q * x_*, so that Q * x_* + q = 0. This
|
||||
% ensures that f( x ) is bounded below if Q is positive semidefinite, and
|
||||
% bounded above if Q is negative semidefinite. However, we also want to
|
||||
% be able to create problems that are positive semidefinite but not
|
||||
% bounded below, which means that the system Q x + q = 0 must not have a
|
||||
% solution. This first of all requires Q to be low-rank (some of the
|
||||
% eigenvalues actually = 0), which can be obtained by putting rank < 1.
|
||||
% Then, if box < 0 the vector q obtained as above is modified by
|
||||
% multiplying each of its entries by a random number uniformly picked in
|
||||
% the interval [ 2 / 3 , 4 / 3 ], which makes it unlikely that the system
|
||||
% Q x = q still has a solution. However, this makes sense only if Q is
|
||||
% rank-deficient, hence this is done only if Q is not strictly positive
|
||||
% definite (for otherwise the system always has a solution).
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - Q: n \times n symmetric real matrix, which is either positive
|
||||
% (semi)definite, negative (semi)definite, or indefinite according
|
||||
% to the value of the conv parameter
|
||||
%
|
||||
% - q: n \times 1 real vector, optional
|
||||
%
|
||||
% - v: real, optional: the optimal value of the optimizattion problem
|
||||
% min{ f( x ) : x \in \R^n }. This is -\infty if Q is not positive
|
||||
% semidefinite (see conv above). It is -\infty even if Q is positive
|
||||
% semidefinite but rank deficient (see rank above) and the system
|
||||
% Q x + q = 0 has no solution. If instead Q is positive semidefinite
|
||||
% (whatever its rank) and the system Q x + q = 0 has a solution x_*,
|
||||
% then x_* is an optimal solution to the problem and
|
||||
%
|
||||
% v = f( x_* ) = (1/2) x_*^T * Q * x_* + q * x_*
|
||||
% = (1/2) [ x_*^T * Q * x_* + q * x_* ] + (1/2) q * x_*
|
||||
% = (1/2) x_*^T ( Q * x_* + q * ) + (1/2) q * x_*
|
||||
% = (1/2) q * x_*
|
||||
%
|
||||
%{
|
||||
=======================================
|
||||
Author: Antonio Frangioni
|
||||
Date: 15-08-22
|
||||
Version 0.10
|
||||
Copyright Antonio Frangioni
|
||||
=======================================
|
||||
%}
|
||||
|
||||
if ~ isscalar( n ) || ~ isreal( n )
|
||||
error( 'n not a real scalar' );
|
||||
end
|
||||
n = round( n );
|
||||
if n <= 0
|
||||
error( 'n must be > 0' );
|
||||
end
|
||||
|
||||
if isempty( varargin )
|
||||
seed = 0;
|
||||
else
|
||||
seed = varargin{ 1 };
|
||||
if ~ isscalar( seed ) || ~ isreal( seed )
|
||||
error( 'actv not a real scalar' );
|
||||
end
|
||||
|
||||
seed = round( seed );
|
||||
end
|
||||
|
||||
if length( varargin ) > 1
|
||||
rank = varargin{ 2 };
|
||||
if ~ isscalar( rank ) || ~ isreal( rank )
|
||||
error( 'rank not a real scalar' );
|
||||
end
|
||||
|
||||
if rank <= 0
|
||||
error( 'rank must be > 0' );
|
||||
end
|
||||
else
|
||||
rank = 1.1;
|
||||
end
|
||||
|
||||
if length( varargin ) > 2
|
||||
conv = varargin{ 3 };
|
||||
if ~ isscalar( conv ) || ~ isreal( conv )
|
||||
error( 'conv not a real scalar' );
|
||||
end
|
||||
|
||||
if ( conv < 0 ) || ( conv > 1 )
|
||||
error( 'conv must be in [0, 1)' );
|
||||
end
|
||||
else
|
||||
conv = 1;
|
||||
end
|
||||
|
||||
if length( varargin ) > 3
|
||||
ecc = varargin{ 4 };
|
||||
if ~ isscalar( ecc ) || ~ isreal( ecc )
|
||||
error( 'ecc not a real scalar' );
|
||||
end
|
||||
|
||||
if ecc < 0 || ecc >= 1
|
||||
error( 'ecc must be in [0, 1)' );
|
||||
end
|
||||
else
|
||||
ecc = 0.99;
|
||||
end
|
||||
|
||||
if length( varargin ) > 4
|
||||
dom = varargin{ 5 };
|
||||
if ~ isscalar( dom )
|
||||
error( 'dom not a scalar' );
|
||||
end
|
||||
|
||||
if dom < 0
|
||||
error( 'dom must be >= 0' );
|
||||
end
|
||||
else
|
||||
dom = 1;
|
||||
end
|
||||
|
||||
if length( varargin ) > 5
|
||||
box = varargin{ 6 };
|
||||
if ~ isscalar( box )
|
||||
error( 'box not a scalar' );
|
||||
end
|
||||
|
||||
if box == 0
|
||||
error( 'box must not be 0' );
|
||||
end
|
||||
else
|
||||
box = 1;
|
||||
end
|
||||
|
||||
rng( seed );
|
||||
|
||||
% generate Q- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% first step: generate the appropriate rank and positive / negative
|
||||
% definiteness
|
||||
|
||||
r = round( rank * n );
|
||||
p = round( r * conv );
|
||||
|
||||
if p > 0
|
||||
G = rand( p , n );
|
||||
Q = G' * G;
|
||||
else
|
||||
Q = zeros( n , n );
|
||||
end
|
||||
|
||||
if r > p
|
||||
G = rand( r - p , n );
|
||||
Q = Q - G' * G;
|
||||
end
|
||||
|
||||
% second step: if dom ~= 1, modify the diagonal
|
||||
% increase or decrease randomly each element by [ - 1/3 , 1/3 ] of its
|
||||
% initial value, then multiply it by dom
|
||||
if dom ~= 1
|
||||
D = diag( Q );
|
||||
D = D .* ( 1 + ( 2 * rand( n , 1 ) - 1 ) / 3 );
|
||||
D = dom * D;
|
||||
Q = spdiags( D , 0 , Q );
|
||||
Q = full( Q );
|
||||
end
|
||||
|
||||
% compute eigenvalue decomposition
|
||||
[ V , D ] = eig( Q ); % V * D * V' = Q , D( 1 , 1 ) = \lambda_n
|
||||
|
||||
if D( 1 , 1 ) > 1e-14
|
||||
% modify eccentricity only if \lambda_n > 0, for when \lambda_n = 0 the
|
||||
% eccentricity is 1 by default
|
||||
%
|
||||
% the formula is:
|
||||
%
|
||||
% \lambda_i - \lambda_n 2 * ecc
|
||||
% \lambda_i = \lambda_n + --------------------- * \lambda_n -------
|
||||
% \lambda_1 - \lambda_n 1 - ecc
|
||||
%
|
||||
% This leaves \lambda_n unchanged, and modifies all the other ones
|
||||
% proportionally so that
|
||||
%
|
||||
% \lambda_1 - \lambda_n
|
||||
% --------------------- = ecc (exercise: check)
|
||||
% \lambda_1 - \lambda_n
|
||||
|
||||
d = diag( D );
|
||||
l = d( 1 ) * ones( n , 1 ) + ( d( 1 ) / ( d( n ) - d( 1 ) ) ) * ...
|
||||
( 2 * ecc / ( 1 - ecc ) ) * ...
|
||||
( d - d( 1 ) * ones( n , 1 ) );
|
||||
|
||||
Q = V * diag( l ) * V';
|
||||
end
|
||||
|
||||
if nargout > 0
|
||||
% if so required generate q- - - - - - - - - - - - - - - - - - - - - - -
|
||||
%
|
||||
% we first generate the unconstrained minimum x_* of the problem in the
|
||||
% box [ - abs( box ) , abs( box ) ] and then we set q = - Q * x_*
|
||||
|
||||
x = 2 * abs( box ) * rand( n , 1 ) - abs( box );
|
||||
|
||||
q = - Q * x;
|
||||
|
||||
% if so required, we now randomly destroy the alignment between q and
|
||||
% the image of Q so as to make it hard to solve Q x = q
|
||||
|
||||
if ( box < 0 ) && ( D( 1 , 1 ) <= 1e-14 )
|
||||
q = q .* ( ( 4 / 3 ) * rand( n , 1 ) - 2 / 3 );
|
||||
end
|
||||
|
||||
varargout{ 1 } = q;
|
||||
|
||||
if nargout > 1
|
||||
% if so required compute v. - - - - - - - - - - - - - - - - - - - - -
|
||||
% v is finite-valued only if either Q is strictly positive definite
|
||||
% or it is positive semidefinite but q has been constructed in such
|
||||
% a was that Q * x + q = 0 has a solution (that is the x we have)
|
||||
|
||||
if ( D( 1 , 1 ) > 1e-14 ) || ...
|
||||
( ( D( 1 , 1 ) > -1e-14 ) && ( box > 0 ) )
|
||||
v = q' * x / 2;
|
||||
else
|
||||
v = - Inf;
|
||||
end
|
||||
|
||||
varargout{ 2 } = v;
|
||||
end
|
||||
end
|
||||
|
||||
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
end
|
||||
383
10-04/lesson.ipynb
Normal file
383
10-04/lesson.ipynb
Normal file
@ -0,0 +1,383 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "a88398a0-03e1-458f-ba48-518fb151b1b3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"using Plots\n",
|
||||
"using LinearAlgebra"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "deac13e6-b3dd-4c8d-9c15-504052e60c6d",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3×3 Matrix{Float64}:\n",
|
||||
" 0.693988 0.0373642 0.306196\n",
|
||||
" 0.475249 0.0523086 0.525352\n",
|
||||
" 0.275428 0.0212671 0.431897"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"A = rand(3,3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "a7cfa41c-b406-475b-8a8e-bc56cab68cfa",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"SVD{Float64, Float64, Matrix{Float64}, Vector{Float64}}\n",
|
||||
"U factor:\n",
|
||||
"3×3 Matrix{Float64}:\n",
|
||||
" -0.649854 0.735055 0.193349\n",
|
||||
" -0.624454 -0.371326 -0.687149\n",
|
||||
" -0.433297 -0.567284 0.700316\n",
|
||||
"singular values:\n",
|
||||
"3-element Vector{Float64}:\n",
|
||||
" 1.1253009779161582\n",
|
||||
" 0.27878010490969024\n",
|
||||
" 0.013851237498536341\n",
|
||||
"Vt factor:\n",
|
||||
"3×3 Matrix{Float64}:\n",
|
||||
" -0.770554 -0.0587937 -0.634658\n",
|
||||
" 0.636347 -0.0144316 -0.771268\n",
|
||||
" 0.0361865 -0.998166 0.0485336"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"U, S, V = svd(A) #singular decomposition"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"id": "c6fdc076-bfc8-46e9-97c2-5427f4c49395",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3×3 BitMatrix:\n",
|
||||
" 1 0 0\n",
|
||||
" 0 1 0\n",
|
||||
" 0 0 1"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3×3 BitMatrix:\n",
|
||||
" 1 0 0\n",
|
||||
" 0 1 0\n",
|
||||
" 0 0 1"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3×3 BitMatrix:\n",
|
||||
" 0 0 0\n",
|
||||
" 0 0 0\n",
|
||||
" 0 0 0"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"display(U'*U .> 0.00001)\n",
|
||||
"display(V'*V .> 0.00001)\n",
|
||||
"display(A - (U * Diagonal(S) * V') .> 0.00001)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "37b7a415-d7ea-4d00-b704-7d79e562d899",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3-element Vector{Float64}:\n",
|
||||
" 0.019506810588402184\n",
|
||||
" 0.2433655332706062\n",
|
||||
" 0.9153216003851385"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3-element Vector{Float64}:\n",
|
||||
" 1.1253009779161582\n",
|
||||
" 0.27878010490969024\n",
|
||||
" 0.013851237498536341"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"display(eigvals(A))\n",
|
||||
"display(svd(A).S)\n",
|
||||
"# singular values are more spread out"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 39,
|
||||
"id": "5a4893c6-074c-4479-ac8a-9ad8db295d0a",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((3, 3), (3,), (5, 3))"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"((5, 3), (3,), (3, 3))"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# svd exists also for rectangular matrices\n",
|
||||
"U, S, V = svd(rand(3, 5))\n",
|
||||
"display((size(U), size(S), size(V)))\n",
|
||||
"U, S, V = svd(rand(5, 3))\n",
|
||||
"display((size(U), size(S), size(V)))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"id": "380565b8-f15d-4f3f-9a0f-85fc82809bdd",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3-element Vector{Float64}:\n",
|
||||
" 2.302775637731995\n",
|
||||
" 1.3027756377319948\n",
|
||||
" 0.0"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"svdvals([2 0 1;0 1 1; 0 0 0; 0 0 0]) # rank is 2 -> so 2 non zero values"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"id": "deb05175-6a64-4c40-ab5c-e614ef85797f",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}}\n",
|
||||
"values:\n",
|
||||
"3-element Vector{Float64}:\n",
|
||||
" 4.440892098500626e-15\n",
|
||||
" 1.697224362268007\n",
|
||||
" 5.302775637731994\n",
|
||||
"vectors:\n",
|
||||
"3×3 Matrix{Float64}:\n",
|
||||
" -0.333333 0.444872 -0.831251\n",
|
||||
" -0.666667 -0.734656 -0.125841\n",
|
||||
" 0.666667 -0.51222 -0.541467"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3×3 Matrix{Float64}:\n",
|
||||
" 4.0 0.0 2.0\n",
|
||||
" 0.0 1.0 1.0\n",
|
||||
" 2.0 1.0 2.0"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"A = [2 0 1;0 1 1; 0 0 0];\n",
|
||||
"display(eigen(A' * A))\n",
|
||||
"U, S, V = svd(A);\n",
|
||||
"display(V * Diagonal(S)' * Diagonal(S) * V')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 32,
|
||||
"id": "60516aff-16aa-41e6-a56d-6cad04547e55",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3×3 Matrix{Float64}:\n",
|
||||
" 1.0 -1.0 0.0\n",
|
||||
" 0.0 1.0 0.0\n",
|
||||
" 0.0 0.0 0.5"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"3×3 Matrix{Float64}:\n",
|
||||
" 1.0 -1.0 0.0\n",
|
||||
" -1.11022e-16 1.0 0.0\n",
|
||||
" 0.0 0.0 0.5"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"A = [1 1 0; 0 1 0; 0 0 2];\n",
|
||||
"display(inv(A))\n",
|
||||
"F = svd(A);\n",
|
||||
"display(F.V * Diagonal(F.S .^ -1) * F.U') # we can get the inverse from the svd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 46,
|
||||
"id": "cd9e606f-957d-4803-9ab8-f7b23c455e13",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(2.0, false)"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\"frobenius norm: 2.6457513110645907\""
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"display((opnorm(A), opnorm(A) == norm(A))) # use opnorm for the matrix norm\n",
|
||||
"display(\"frobenius norm: $(norm(A))\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 57,
|
||||
"id": "9c469ac2-4d2e-4eba-9c6e-c63ec1fc06ae",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"2×2 Matrix{Float64}:\n",
|
||||
" 1.27357 1.80721\n",
|
||||
" 2.87898 4.08529"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Eckhart-Young theorem\n",
|
||||
"# the min X with respect to opnorm(A-X) with rank less than or equal to k is:\n",
|
||||
"A = [1 2;3 4];\n",
|
||||
"F = svd(A);\n",
|
||||
"X = F.U[:,1] .* F.S[1, 1] * F.V[:, 1]';\n",
|
||||
"display(X)\n",
|
||||
"display(rank(X))"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Julia 1.9.3",
|
||||
"language": "julia",
|
||||
"name": "julia-1.9"
|
||||
},
|
||||
"language_info": {
|
||||
"file_extension": ".jl",
|
||||
"mimetype": "application/julia",
|
||||
"name": "julia",
|
||||
"version": "1.9.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
67
10-04/optQf.m
Normal file
67
10-04/optQf.m
Normal file
@ -0,0 +1,67 @@
|
||||
function v = optQf( Q , q )
|
||||
|
||||
%function v = optQf( Q , q )
|
||||
%
|
||||
% Given the data structure encoding a Quadratic function
|
||||
%
|
||||
% f( x ) = (1/2) x^T * Q * x + q * x
|
||||
%
|
||||
% returns the value of f() in the "putative minimum" (or maximum), i.e.,
|
||||
% the point
|
||||
%
|
||||
% xStar = Q \ -q;
|
||||
%
|
||||
% Input:
|
||||
%
|
||||
% - Q ([ n x n ] real symmetric matrix, not necessarily positive
|
||||
% semidefinite): the quadratic part of f
|
||||
%
|
||||
% - q ([ n x 1 ] real column vector): the linear part of f
|
||||
%
|
||||
% Output:
|
||||
%
|
||||
% - f( xStar )
|
||||
%
|
||||
%{
|
||||
=======================================
|
||||
Author: Antonio Frangioni
|
||||
Date: 30-09-22
|
||||
Version 0.10
|
||||
Copyright Antonio Frangioni
|
||||
=======================================
|
||||
%}
|
||||
|
||||
if ~ isreal( Q )
|
||||
error( 'Q not a real matrix' );
|
||||
end
|
||||
|
||||
n = size( Q , 1 );
|
||||
|
||||
if n <= 1
|
||||
error( 'Q is too small' );
|
||||
end
|
||||
|
||||
if n ~= size( Q , 2 )
|
||||
error( 'Q is not square' );
|
||||
end
|
||||
|
||||
if ~ isreal( q )
|
||||
error( 'q not a real vector' );
|
||||
end
|
||||
|
||||
if size( q , 2 ) ~= 1
|
||||
error( 'q is not a (column) vector' );
|
||||
end
|
||||
|
||||
if size( q , 1 ) ~= n
|
||||
error( 'q size does not match with Q' );
|
||||
end
|
||||
|
||||
% "solve the problem" - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
% ignore if Q is singular
|
||||
|
||||
xStar = Q \ -q;
|
||||
|
||||
v = 0.5 * xStar' * Q * xStar + q' * xStar;
|
||||
|
||||
end
|
||||
11
10-04/plotQ.jl
Normal file
11
10-04/plotQ.jl
Normal file
@ -0,0 +1,11 @@
|
||||
using LinearAlgebra
|
||||
using Plots
|
||||
|
||||
function plotQ(Q::Matrix, q::Vector, xyrange::Tuple{Tuple{Number, Number}, Tuple{Number, Number}})::Plots.Plot
|
||||
f(x, y) = dot((1/2) * hcat(x, y) * Q, vcat(x, y)) + dot(q', vcat(x, y))
|
||||
xrange = LinRange(xyrange[1][1], xyrange[2][1], 200)
|
||||
yrange = LinRange(xyrange[1][2], xyrange[2][2], 200)
|
||||
z = @. f(xrange', yrange)
|
||||
plt = contour(xrange, yrange, z)
|
||||
plt
|
||||
end
|
||||
11
10-04/plotQ.m
Normal file
11
10-04/plotQ.m
Normal file
@ -0,0 +1,11 @@
|
||||
function plotQ( Q , q , range )
|
||||
|
||||
f = @(x,y) 0.5 * [ x y ] * Q * [ x ; y ] + q' * [ x ; y ];
|
||||
|
||||
warning( 'off' , 'all' );
|
||||
|
||||
fcontour( f , range , 'LineColor' , 'k' , 'LineWidth' , 1 );
|
||||
|
||||
warning( 'on' , 'all' );
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user