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