first commit with current lessons

This commit is contained in:
elvis
2023-10-29 02:06:02 +01:00
parent ececf6cfcb
commit b3fc9cb021
204 changed files with 31603 additions and 0 deletions

111
10-04/genQf.jl Normal file
View 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