# [R] Changing a matrix based on eigen value

David Winsemius dwinsemius at comcast.net
Thu Jul 21 15:54:51 CEST 2011

```On Jul 21, 2011, at 12:22 AM, B. Jonathan B. Jonathan wrote:

> Thanks David for your pointer. Here my original matrix is VCV matrix
> which is the utmost important matrix in finance. However in reality
> what happens is that due to incomplete data. lot of missing values
> (or some other problems) that matrix may be unstable like min eigen
> value is negative or very close to zero etc.
>
> My goal is to make that unstable matrix stable for further
> calculation. Here I want to make the min eigen "quite far from zero
> in positive quadrant", however still do not want to loose much
> information that is hidden in my original matrix (what I call it
> "Real information").
>
> I want to have a control on: How far min eigen value I want from zero.
>
>
> Thanks,
> On Thu, Jul 21, 2011 at 9:27 AM, David Winsemius <dwinsemius at comcast.net
> > wrote:
>
> On Jul 20, 2011, at 11:17 PM, B. Jonathan B. Jonathan wrote:
>
> It is not any homework problem. I just need some pointer. Given that
> I think
> I would be able to carry forward.
>
> Then what kind of problem _is_ it? You say:
>
> "nearest matrix"   ... using what measure for distance or similarity?
>
> "... keep all other properties (whatever are those) of my original
> matrix "mat" as unaltered as possible."
>
>     ... this really does leave your question looking ... what would
> be kind? ... perhaps the word "nebulous" would be apt? How are we
> supposed to make choices for you in the absence of any goals?
>
> --
> David
>

On Jul 20, 2011, at 1:06 PM, B. Jonathan B. Jonathan wrote:

> Dear all, my question is not directly related to R, however I
> believe that
> experts here would not mind anything to have a look on my problem.
>
> Please consider a symmetric matrix and it's eigen values:
>
>> set.seed(1)
>> mat <- matrix(rnorm(36), 6)
>> mat <- mat %*% t(mat) # symmetric matrix
>> mat
>          [,1]       [,2]        [,3]       [,4]       [,5]        [,6]
> [1,]  3.920570  1.9339770  1.29012167 -1.4627174 -1.5655953
> -1.82083435
> [2,]  1.933977  5.8501784 -1.70504980  0.7195951  1.4252209
> -3.11543738
> [3,]  1.290122 -1.7050498  3.31434984 -0.6324029  0.1860666
> -0.08234236
> [4,] -1.462717  0.7195951 -0.63240294  5.4179467  0.9003576
> -3.61864495
> [5,] -1.565595  1.4252209  0.18606662  0.9003576  4.5248002
> 0.52702347
> [6,] -1.820834 -3.1154374 -0.08234236 -3.6186449  0.5270235
> 6.02038872
>> eigen(mat)\$values
>  11.4213448  7.3302845  5.7033748  3.9863332  0.4827576  0.1241385
>
> Here my goal is to find the "nearest matrix" of "mat" for which the
> minimum
> eigen value is 0.20

Still waiting for a specific definition of "near".

If all you want to get is an output that matches your minimum
eigenvalue specification it is very nearly trivial but probably not
optimal "solution"::

mat*0.2/0.1241385    # but is this meaningful?
> det(mat*0.2/0.1241385)
 1994.896   # big change in determinant, by factor of
(0.2/0.1241385)^6

> (I would rather want to fix some arbitrary value). While
> finding that nearest matrix, I would like to keep all other properties
> (whatever are those)

Yes, _what_ are those "all other properties"? Ratios of elements?
Determinant? Condition number? You've hinted at why are you asking
this question, but still have not presented any specifics on how a
strategy would be assessed. I freely admit that I was very surprised
upon Google-searching to see how much applicability has developed in
physics from the notion of random symmetric matrices. I had not been
aware of Wigner's fascinating results in nuclear physics nor the other
findings that have emerged in the last 50 years.

(I also found that multiplying the diagonal elements of 'mat' by a
very small fraction and leaving all other elements the same could
achieve the same sort of result.

mat2 <- mat
> det(mat)
 114.072
> eigen(mat)\$values/eigen(mat)\$values  # original condition
number
 92.00486

diag(mat2) <- diag(mat)*1.01679
eigen(mat2)\$values
> det(mat2)
 228.4126
> eigen(mat2)\$values/eigen(mat2)\$values # new condition number
 57.58801

But that factor to be applied to the diagonal seems arbitrary at least
to the extent that it is not any power of 0.2/0.1241385 that I can
determine.

Played with changing the "lower-right corner element with very little
effect. Then looking at eigenvector for the lowest eigenvalue,

> eigen(mat)\$vectors[6,]
 -0.66846249  0.10870793  0.32972715  0.07842753  0.60828836
0.23760238

.... and noting that its highest components in absolute magnitude
were the first and fifth..... found that small alterations in the 5th
diagonal also raised the eigenvalue.

> mat2[5,5] <- mat[5,5]*1.110125 ... is this close to  1.01679^6
> eigen(mat2)\$values
 0.1999991
> det(mat2)
 199.4463  # so the impact on the det() is a bit less that

> mat2[5,5] <- mat[5,5]*1.110125
> eigen(mat2)\$values/eigen(mat2)\$values
 57.12198   very similar to diag-manipulated result

> of my original matrix "mat" as unaltered as possible.
>
> Is there any algorithm to achieve that?

I used successive approximation for the second method and third
methods. You could, therefore, probably get optim() to do it. There is
a literature on the effect of perturbations of matrices on
eigenvalues, but I am not at all versed in it. Heck, I'm not
particularly well-versed in matrix algebra for that matter. So these
experiments should be seen as an effort at sel-learning on my part