github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/lapack/testlapack/test_matrices.go (about)

     1  // Copyright ©2016 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package testlapack
     6  
     7  import (
     8  	"math"
     9  
    10  	"golang.org/x/exp/rand"
    11  
    12  	"github.com/jingcheng-WU/gonum/blas/blas64"
    13  )
    14  
    15  // A123 is the non-symmetric singular matrix
    16  //      [ 1 2 3 ]
    17  //  A = [ 4 5 6 ]
    18  //      [ 7 8 9 ]
    19  // It has three distinct real eigenvalues.
    20  type A123 struct{}
    21  
    22  func (A123) Matrix() blas64.General {
    23  	return blas64.General{
    24  		Rows:   3,
    25  		Cols:   3,
    26  		Stride: 3,
    27  		Data: []float64{
    28  			1, 2, 3,
    29  			4, 5, 6,
    30  			7, 8, 9,
    31  		},
    32  	}
    33  }
    34  
    35  func (A123) Eigenvalues() []complex128 {
    36  	return []complex128{16.116843969807043, -1.116843969807043, 0}
    37  }
    38  
    39  func (A123) LeftEV() blas64.General {
    40  	return blas64.General{
    41  		Rows:   3,
    42  		Cols:   3,
    43  		Stride: 3,
    44  		Data: []float64{
    45  			-0.464547273387671, -0.570795531228578, -0.677043789069485,
    46  			-0.882905959653586, -0.239520420054206, 0.403865119545174,
    47  			0.408248290463862, -0.816496580927726, 0.408248290463863,
    48  		},
    49  	}
    50  }
    51  
    52  func (A123) RightEV() blas64.General {
    53  	return blas64.General{
    54  		Rows:   3,
    55  		Cols:   3,
    56  		Stride: 3,
    57  		Data: []float64{
    58  			-0.231970687246286, -0.785830238742067, 0.408248290463864,
    59  			-0.525322093301234, -0.086751339256628, -0.816496580927726,
    60  			-0.818673499356181, 0.612327560228810, 0.408248290463863,
    61  		},
    62  	}
    63  }
    64  
    65  // AntisymRandom is a anti-symmetric random matrix. All its eigenvalues are
    66  // imaginary with one zero if the order is odd.
    67  type AntisymRandom struct {
    68  	mat blas64.General
    69  }
    70  
    71  func NewAntisymRandom(n int, rnd *rand.Rand) AntisymRandom {
    72  	a := zeros(n, n, n)
    73  	for i := 0; i < n; i++ {
    74  		for j := i + 1; j < n; j++ {
    75  			r := rnd.NormFloat64()
    76  			a.Data[i*a.Stride+j] = r
    77  			a.Data[j*a.Stride+i] = -r
    78  		}
    79  	}
    80  	return AntisymRandom{a}
    81  }
    82  
    83  func (a AntisymRandom) Matrix() blas64.General {
    84  	return cloneGeneral(a.mat)
    85  }
    86  
    87  func (AntisymRandom) Eigenvalues() []complex128 {
    88  	return nil
    89  }
    90  
    91  // Circulant is a generally non-symmetric matrix given by
    92  //  A[i,j] = 1 + (j-i+n)%n.
    93  // For example, for n=5,
    94  //      [ 1 2 3 4 5 ]
    95  //      [ 5 1 2 3 4 ]
    96  //  A = [ 4 5 1 2 3 ]
    97  //      [ 3 4 5 1 2 ]
    98  //      [ 2 3 4 5 1 ]
    99  // It has real and complex eigenvalues, some possibly repeated.
   100  type Circulant int
   101  
   102  func (c Circulant) Matrix() blas64.General {
   103  	n := int(c)
   104  	a := zeros(n, n, n)
   105  	for i := 0; i < n; i++ {
   106  		for j := 0; j < n; j++ {
   107  			a.Data[i*a.Stride+j] = float64(1 + (j-i+n)%n)
   108  		}
   109  	}
   110  	return a
   111  }
   112  
   113  func (c Circulant) Eigenvalues() []complex128 {
   114  	n := int(c)
   115  	w := rootsOfUnity(n)
   116  	ev := make([]complex128, n)
   117  	for k := 0; k < n; k++ {
   118  		ev[k] = complex(float64(n), 0)
   119  	}
   120  	for i := n - 1; i > 0; i-- {
   121  		for k := 0; k < n; k++ {
   122  			ev[k] = ev[k]*w[k] + complex(float64(i), 0)
   123  		}
   124  	}
   125  	return ev
   126  }
   127  
   128  // Clement is a generally non-symmetric matrix given by
   129  //  A[i,j] = i+1  if j == i+1,
   130  //         = n-i  if j == i-1,
   131  //         = 0    otherwise.
   132  // For example, for n=5,
   133  //      [ . 1 . . . ]
   134  //      [ 4 . 2 . . ]
   135  //  A = [ . 3 . 3 . ]
   136  //      [ . . 2 . 4 ]
   137  //      [ . . . 1 . ]
   138  // It has n distinct real eigenvalues.
   139  type Clement int
   140  
   141  func (c Clement) Matrix() blas64.General {
   142  	n := int(c)
   143  	a := zeros(n, n, n)
   144  	for i := 0; i < n; i++ {
   145  		if i < n-1 {
   146  			a.Data[i*a.Stride+i+1] = float64(i + 1)
   147  		}
   148  		if i > 0 {
   149  			a.Data[i*a.Stride+i-1] = float64(n - i)
   150  		}
   151  	}
   152  	return a
   153  }
   154  
   155  func (c Clement) Eigenvalues() []complex128 {
   156  	n := int(c)
   157  	ev := make([]complex128, n)
   158  	for i := range ev {
   159  		ev[i] = complex(float64(-n+2*i+1), 0)
   160  	}
   161  	return ev
   162  }
   163  
   164  // Creation is a singular non-symmetric matrix given by
   165  //  A[i,j] = i  if j == i-1,
   166  //         = 0  otherwise.
   167  // For example, for n=5,
   168  //      [ . . . . . ]
   169  //      [ 1 . . . . ]
   170  //  A = [ . 2 . . . ]
   171  //      [ . . 3 . . ]
   172  //      [ . . . 4 . ]
   173  // Zero is its only eigenvalue.
   174  type Creation int
   175  
   176  func (c Creation) Matrix() blas64.General {
   177  	n := int(c)
   178  	a := zeros(n, n, n)
   179  	for i := 1; i < n; i++ {
   180  		a.Data[i*a.Stride+i-1] = float64(i)
   181  	}
   182  	return a
   183  }
   184  
   185  func (c Creation) Eigenvalues() []complex128 {
   186  	return make([]complex128, int(c))
   187  }
   188  
   189  // Diagonal is a diagonal matrix given by
   190  //  A[i,j] = i+1  if i == j,
   191  //         = 0    otherwise.
   192  // For example, for n=5,
   193  //      [ 1 . . . . ]
   194  //      [ . 2 . . . ]
   195  //  A = [ . . 3 . . ]
   196  //      [ . . . 4 . ]
   197  //      [ . . . . 5 ]
   198  // It has n real eigenvalues {1,...,n}.
   199  type Diagonal int
   200  
   201  func (d Diagonal) Matrix() blas64.General {
   202  	n := int(d)
   203  	a := zeros(n, n, n)
   204  	for i := 0; i < n; i++ {
   205  		a.Data[i*a.Stride+i] = float64(i)
   206  	}
   207  	return a
   208  }
   209  
   210  func (d Diagonal) Eigenvalues() []complex128 {
   211  	n := int(d)
   212  	ev := make([]complex128, n)
   213  	for i := range ev {
   214  		ev[i] = complex(float64(i), 0)
   215  	}
   216  	return ev
   217  }
   218  
   219  // Downshift is a non-singular upper Hessenberg matrix given by
   220  //  A[i,j] = 1  if (i-j+n)%n == 1,
   221  //         = 0  otherwise.
   222  // For example, for n=5,
   223  //      [ . . . . 1 ]
   224  //      [ 1 . . . . ]
   225  //  A = [ . 1 . . . ]
   226  //      [ . . 1 . . ]
   227  //      [ . . . 1 . ]
   228  // Its eigenvalues are the complex roots of unity.
   229  type Downshift int
   230  
   231  func (d Downshift) Matrix() blas64.General {
   232  	n := int(d)
   233  	a := zeros(n, n, n)
   234  	a.Data[n-1] = 1
   235  	for i := 1; i < n; i++ {
   236  		a.Data[i*a.Stride+i-1] = 1
   237  	}
   238  	return a
   239  }
   240  
   241  func (d Downshift) Eigenvalues() []complex128 {
   242  	return rootsOfUnity(int(d))
   243  }
   244  
   245  // Fibonacci is an upper Hessenberg matrix with 3 distinct real eigenvalues. For
   246  // example, for n=5,
   247  //      [ . 1 . . . ]
   248  //      [ 1 1 . . . ]
   249  //  A = [ . 1 1 . . ]
   250  //      [ . . 1 1 . ]
   251  //      [ . . . 1 1 ]
   252  type Fibonacci int
   253  
   254  func (f Fibonacci) Matrix() blas64.General {
   255  	n := int(f)
   256  	a := zeros(n, n, n)
   257  	if n > 1 {
   258  		a.Data[1] = 1
   259  	}
   260  	for i := 1; i < n; i++ {
   261  		a.Data[i*a.Stride+i-1] = 1
   262  		a.Data[i*a.Stride+i] = 1
   263  	}
   264  	return a
   265  }
   266  
   267  func (f Fibonacci) Eigenvalues() []complex128 {
   268  	n := int(f)
   269  	ev := make([]complex128, n)
   270  	if n == 0 || n == 1 {
   271  		return ev
   272  	}
   273  	phi := 0.5 * (1 + math.Sqrt(5))
   274  	ev[0] = complex(phi, 0)
   275  	for i := 1; i < n-1; i++ {
   276  		ev[i] = 1 + 0i
   277  	}
   278  	ev[n-1] = complex(1-phi, 0)
   279  	return ev
   280  }
   281  
   282  // Gear is a singular non-symmetric matrix with real eigenvalues. For example,
   283  // for n=5,
   284  //      [ . 1 . . 1 ]
   285  //      [ 1 . 1 . . ]
   286  //  A = [ . 1 . 1 . ]
   287  //      [ . . 1 . 1 ]
   288  //      [-1 . . 1 . ]
   289  type Gear int
   290  
   291  func (g Gear) Matrix() blas64.General {
   292  	n := int(g)
   293  	a := zeros(n, n, n)
   294  	if n == 1 {
   295  		return a
   296  	}
   297  	for i := 0; i < n-1; i++ {
   298  		a.Data[i*a.Stride+i+1] = 1
   299  	}
   300  	for i := 1; i < n; i++ {
   301  		a.Data[i*a.Stride+i-1] = 1
   302  	}
   303  	a.Data[n-1] = 1
   304  	a.Data[(n-1)*a.Stride] = -1
   305  	return a
   306  }
   307  
   308  func (g Gear) Eigenvalues() []complex128 {
   309  	n := int(g)
   310  	ev := make([]complex128, n)
   311  	if n == 0 || n == 1 {
   312  		return ev
   313  	}
   314  	if n == 2 {
   315  		ev[0] = complex(0, 1)
   316  		ev[1] = complex(0, -1)
   317  		return ev
   318  	}
   319  	w := 0
   320  	ev[w] = math.Pi / 2
   321  	w++
   322  	phi := (n - 1) / 2
   323  	for p := 1; p <= phi; p++ {
   324  		ev[w] = complex(float64(2*p)*math.Pi/float64(n), 0)
   325  		w++
   326  	}
   327  	phi = n / 2
   328  	for p := 1; p <= phi; p++ {
   329  		ev[w] = complex(float64(2*p-1)*math.Pi/float64(n), 0)
   330  		w++
   331  	}
   332  	for i, v := range ev {
   333  		ev[i] = complex(2*math.Cos(real(v)), 0)
   334  	}
   335  	return ev
   336  }
   337  
   338  // Grcar is an upper Hessenberg matrix given by
   339  //  A[i,j] = -1  if i == j+1,
   340  //         = 1   if i <= j and j <= i+k,
   341  //         = 0   otherwise.
   342  // For example, for n=5 and k=2,
   343  //      [  1  1  1  .  . ]
   344  //      [ -1  1  1  1  . ]
   345  //  A = [  . -1  1  1  1 ]
   346  //      [  .  . -1  1  1 ]
   347  //      [  .  .  . -1  1 ]
   348  // The matrix has sensitive eigenvalues but they are not given explicitly.
   349  type Grcar struct {
   350  	N int
   351  	K int
   352  }
   353  
   354  func (g Grcar) Matrix() blas64.General {
   355  	n := g.N
   356  	a := zeros(n, n, n)
   357  	for k := 0; k <= g.K; k++ {
   358  		for i := 0; i < n-k; i++ {
   359  			a.Data[i*a.Stride+i+k] = 1
   360  		}
   361  	}
   362  	for i := 1; i < n; i++ {
   363  		a.Data[i*a.Stride+i-1] = -1
   364  	}
   365  	return a
   366  }
   367  
   368  func (Grcar) Eigenvalues() []complex128 {
   369  	return nil
   370  }
   371  
   372  // Hanowa is a non-symmetric non-singular matrix of even order given by
   373  //  A[i,j] = alpha    if i == j,
   374  //         = -i-1     if i < n/2 and j == i + n/2,
   375  //         = i+1-n/2  if i >= n/2 and j == i - n/2,
   376  //         = 0        otherwise.
   377  // The matrix has complex eigenvalues.
   378  type Hanowa struct {
   379  	N     int // Order of the matrix, must be even.
   380  	Alpha float64
   381  }
   382  
   383  func (h Hanowa) Matrix() blas64.General {
   384  	if h.N&0x1 != 0 {
   385  		panic("lapack: matrix order must be even")
   386  	}
   387  	n := h.N
   388  	a := zeros(n, n, n)
   389  	for i := 0; i < n; i++ {
   390  		a.Data[i*a.Stride+i] = h.Alpha
   391  	}
   392  	for i := 0; i < n/2; i++ {
   393  		a.Data[i*a.Stride+i+n/2] = float64(-i - 1)
   394  	}
   395  	for i := n / 2; i < n; i++ {
   396  		a.Data[i*a.Stride+i-n/2] = float64(i + 1 - n/2)
   397  	}
   398  	return a
   399  }
   400  
   401  func (h Hanowa) Eigenvalues() []complex128 {
   402  	if h.N&0x1 != 0 {
   403  		panic("lapack: matrix order must be even")
   404  	}
   405  	n := int(h.N)
   406  	ev := make([]complex128, n)
   407  	for i := 0; i < n/2; i++ {
   408  		ev[2*i] = complex(h.Alpha, float64(-i-1))
   409  		ev[2*i+1] = complex(h.Alpha, float64(i+1))
   410  	}
   411  	return ev
   412  }
   413  
   414  // Lesp is a tridiagonal, generally non-symmetric matrix given by
   415  //  A[i,j] = -2*i-5   if i == j,
   416  //         = 1/(i+1)  if i == j-1,
   417  //         = j+1      if i == j+1.
   418  // For example, for n=5,
   419  //      [  -5    2    .    .    . ]
   420  //      [ 1/2   -7    3    .    . ]
   421  //  A = [   .  1/3   -9    4    . ]
   422  //      [   .    .  1/4  -11    5 ]
   423  //      [   .    .    .  1/5  -13 ].
   424  // The matrix has sensitive eigenvalues but they are not given explicitly.
   425  type Lesp int
   426  
   427  func (l Lesp) Matrix() blas64.General {
   428  	n := int(l)
   429  	a := zeros(n, n, n)
   430  	for i := 0; i < n; i++ {
   431  		a.Data[i*a.Stride+i] = float64(-2*i - 5)
   432  	}
   433  	for i := 0; i < n-1; i++ {
   434  		a.Data[i*a.Stride+i+1] = float64(i + 2)
   435  	}
   436  	for i := 1; i < n; i++ {
   437  		a.Data[i*a.Stride+i-1] = 1 / float64(i+1)
   438  	}
   439  	return a
   440  }
   441  
   442  func (Lesp) Eigenvalues() []complex128 {
   443  	return nil
   444  }
   445  
   446  // Rutis is the 4×4 non-symmetric matrix
   447  //      [ 4 -5  0  3 ]
   448  //  A = [ 0  4 -3 -5 ]
   449  //      [ 5 -3  4  0 ]
   450  //      [ 3  0  5  4 ]
   451  // It has two distinct real eigenvalues and a pair of complex eigenvalues.
   452  type Rutis struct{}
   453  
   454  func (Rutis) Matrix() blas64.General {
   455  	return blas64.General{
   456  		Rows:   4,
   457  		Cols:   4,
   458  		Stride: 4,
   459  		Data: []float64{
   460  			4, -5, 0, 3,
   461  			0, 4, -3, -5,
   462  			5, -3, 4, 0,
   463  			3, 0, 5, 4,
   464  		},
   465  	}
   466  }
   467  
   468  func (Rutis) Eigenvalues() []complex128 {
   469  	return []complex128{12, 1 + 5i, 1 - 5i, 2}
   470  }
   471  
   472  // Tris is a tridiagonal matrix given by
   473  //  A[i,j] = x  if i == j-1,
   474  //         = y  if i == j,
   475  //         = z  if i == j+1.
   476  // If x*z is negative, the matrix has complex eigenvalues.
   477  type Tris struct {
   478  	N       int
   479  	X, Y, Z float64
   480  }
   481  
   482  func (t Tris) Matrix() blas64.General {
   483  	n := t.N
   484  	a := zeros(n, n, n)
   485  	for i := 1; i < n; i++ {
   486  		a.Data[i*a.Stride+i-1] = t.X
   487  	}
   488  	for i := 0; i < n; i++ {
   489  		a.Data[i*a.Stride+i] = t.Y
   490  	}
   491  	for i := 0; i < n-1; i++ {
   492  		a.Data[i*a.Stride+i+1] = t.Z
   493  	}
   494  	return a
   495  }
   496  
   497  func (t Tris) Eigenvalues() []complex128 {
   498  	n := int(t.N)
   499  	ev := make([]complex128, n)
   500  	for i := range ev {
   501  		angle := float64(i+1) * math.Pi / float64(n+1)
   502  		arg := t.X * t.Z
   503  		if arg >= 0 {
   504  			ev[i] = complex(t.Y+2*math.Sqrt(arg)*math.Cos(angle), 0)
   505  		} else {
   506  			ev[i] = complex(t.Y, 2*math.Sqrt(-arg)*math.Cos(angle))
   507  		}
   508  	}
   509  	return ev
   510  }
   511  
   512  // Wilk4 is a 4×4 lower triangular matrix with 4 distinct real eigenvalues.
   513  type Wilk4 struct{}
   514  
   515  func (Wilk4) Matrix() blas64.General {
   516  	return blas64.General{
   517  		Rows:   4,
   518  		Cols:   4,
   519  		Stride: 4,
   520  		Data: []float64{
   521  			0.9143e-4, 0.0, 0.0, 0.0,
   522  			0.8762, 0.7156e-4, 0.0, 0.0,
   523  			0.7943, 0.8143, 0.9504e-4, 0.0,
   524  			0.8017, 0.6123, 0.7165, 0.7123e-4,
   525  		},
   526  	}
   527  }
   528  
   529  func (Wilk4) Eigenvalues() []complex128 {
   530  	return []complex128{
   531  		0.9504e-4, 0.9143e-4, 0.7156e-4, 0.7123e-4,
   532  	}
   533  }
   534  
   535  // Wilk12 is a 12×12 lower Hessenberg matrix with 12 distinct real eigenvalues.
   536  type Wilk12 struct{}
   537  
   538  func (Wilk12) Matrix() blas64.General {
   539  	return blas64.General{
   540  		Rows:   12,
   541  		Cols:   12,
   542  		Stride: 12,
   543  		Data: []float64{
   544  			12, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   545  			11, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   546  			10, 10, 10, 9, 0, 0, 0, 0, 0, 0, 0, 0,
   547  			9, 9, 9, 9, 8, 0, 0, 0, 0, 0, 0, 0,
   548  			8, 8, 8, 8, 8, 7, 0, 0, 0, 0, 0, 0,
   549  			7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0,
   550  			6, 6, 6, 6, 6, 6, 6, 5, 0, 0, 0, 0,
   551  			5, 5, 5, 5, 5, 5, 5, 5, 4, 0, 0, 0,
   552  			4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 0, 0,
   553  			3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0,
   554  			2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
   555  			1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   556  		},
   557  	}
   558  }
   559  
   560  func (Wilk12) Eigenvalues() []complex128 {
   561  	return []complex128{
   562  		32.2288915015722210,
   563  		20.1989886458770691,
   564  		12.3110774008685340,
   565  		6.9615330855671154,
   566  		3.5118559485807528,
   567  		1.5539887091319704,
   568  		0.6435053190136506,
   569  		0.2847497205488856,
   570  		0.1436465181918488,
   571  		0.0812276683076552,
   572  		0.0495074140194613,
   573  		0.0310280683208907,
   574  	}
   575  }
   576  
   577  // Wilk20 is a 20×20 lower Hessenberg matrix. If the parameter is 0, the matrix
   578  // has 20 distinct real eigenvalues. If the parameter is 1e-10, the matrix has 6
   579  // real eigenvalues and 7 pairs of complex eigenvalues.
   580  type Wilk20 float64
   581  
   582  func (w Wilk20) Matrix() blas64.General {
   583  	a := zeros(20, 20, 20)
   584  	for i := 0; i < 20; i++ {
   585  		a.Data[i*a.Stride+i] = float64(i + 1)
   586  	}
   587  	for i := 0; i < 19; i++ {
   588  		a.Data[i*a.Stride+i+1] = 20
   589  	}
   590  	a.Data[19*a.Stride] = float64(w)
   591  	return a
   592  }
   593  
   594  func (w Wilk20) Eigenvalues() []complex128 {
   595  	if float64(w) == 0 {
   596  		ev := make([]complex128, 20)
   597  		for i := range ev {
   598  			ev[i] = complex(float64(i+1), 0)
   599  		}
   600  		return ev
   601  	}
   602  	return nil
   603  }
   604  
   605  // Zero is a matrix with all elements equal to zero.
   606  type Zero int
   607  
   608  func (z Zero) Matrix() blas64.General {
   609  	n := int(z)
   610  	return zeros(n, n, n)
   611  }
   612  
   613  func (z Zero) Eigenvalues() []complex128 {
   614  	n := int(z)
   615  	return make([]complex128, n)
   616  }