creating random dense symmetric matrix with desired condition number

I want to test my code on a large size matrix which should a dense symmetric with specific condition number. I wonder if there are built-in functions in Matlab for doing that?

Answers (1)

[modified to address the first comment below]
Hi othello, I don't know about built-in functions but there are ways to make your own matrices, e.g.
a = 2*rand(10,10)-1 + 2*rand(10,10)-1;
a = a+a'; % symmetric with random entries beween -2 and 2
C = 2345; % desired condition number
[u s v] = svd(a);
s = diag(s); % s is vector
% ===== linear stretch of existing s
s = s(1)*( 1-((C-1)/C)*(s(1)-s)/(s(1)-s(end))) ;
% =====
s = diag(s); % back to matrix
b = u*s*v';
cond(b)
ans = 2.3450e+03
%
%
% ===== log spacing example, where also norm(b) = 1 (induced matrix norm)
% s = exp(linspace(0,-log(C),length(s)));
% =====
The condition number is the ratio between the first and last diagonal entries in matrix s (which are sorted), so s is modified to make that ratio equal to C. This also works if the matrix has complex values and is Hermitian. You can also use normal random variables instead of uniform, etc. Seems to work, although something bad is going to happen eventually if you make C too large.

5 Comments

Nope. A decent idea, but this actually does NOT work. It MAY work some of the time, depending on the value of C. But it is relatively easy to choose a value of C that will make this scheme fail.
So, why do I claim that this MAY fail?
The condition number of a matrix is NOT the ratio of the first and last singular values. It is the ratio of the largest and SMALLEST singular values.
a = 2*rand(10,10)-1;
a = a+a';
svd(a)
ans =
4.58080178736462
4.53709793776632
3.97533050963259
3.73031220692586
2.53840739105403
2.50126338658107
2.16399284277328
0.873311342704311
0.676947566203514
0.126414987305412
So quick inspection of the singular values of a tells me that if C=5, your scheme will fail.
C = 5;
[u s v] = svd(a);
s(end,end) = s(1,1)/C;
b = u*s*v';
cond(b)
ans =
6.76684874288694
As you can see, setting C=5 did not yield a condition number of 5.
The point is, re-setting the singular values CAN be made to work. But you need to be slightly more careful about the algorithm you choose.
Hi John, yes, this is true. I was thinking of the case where the desired value of C is large, almost certainly larger than the existing condition number for the matrix a, in which case I believe it works since s is sorted. However, if the desired C is smaller than that, I agree that this method comes up short. I aim to modify the answer to rescale all of the entries of s.
Yes, you can do it, with careful coding. You need to make sure that the ratio of the largest to the smallest singular values is what you want. As long as you get that right, then the condition number will be as desired.
I forgot to mention in comments that I modified the code so now nothing is tbd. Works in every case I tried.
Yes. A complete linear or log transformation of the singular values will suffice. Anything like that will work, where all of the singular values move together. That way it does not allow the singular values to effectively change their sequence. Of course, if the small singular value was exactly zero, then there would be a problem. That event would be unlikely, starting from a random matrix. But even that can be solved. +1 now.

Sign in to comment.

Categories

Find more on Linear Algebra in Help Center and File Exchange

Asked:

on 7 May 2017

Edited:

on 10 May 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!