Files
cmdla/10-04/getQf.m
2023-10-29 02:06:02 +01:00

279 lines
8.6 KiB
Matlab

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