mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 15:16:59 +08:00
113 lines
3.1 KiB
Go
113 lines
3.1 KiB
Go
// Copyright ©2020 The Gonum Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package mat_test
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"gonum.org/v1/gonum/mat"
|
|
)
|
|
|
|
func ExampleSVD_SolveTo() {
|
|
// The system described by A is rank deficient.
|
|
a := mat.NewDense(5, 3, []float64{
|
|
-1.7854591879711257, -0.42687285925779594, -0.12730256811265162,
|
|
-0.5728984211439724, -0.10093393134001777, -0.1181901192353067,
|
|
1.2484316018707418, 0.5646683943038734, -0.48229492403243485,
|
|
0.10174927665169475, -0.5805410929482445, 1.3054473231942054,
|
|
-1.134174808195733, -0.4732430202414438, 0.3528489486370508,
|
|
})
|
|
|
|
// Perform an SVD retaining all singular vectors.
|
|
var svd mat.SVD
|
|
ok := svd.Factorize(a, mat.SVDFull)
|
|
if !ok {
|
|
log.Fatal("failed to factorize A")
|
|
}
|
|
|
|
// Determine the rank of the A matrix with a near zero condition threshold.
|
|
const rcond = 1e-15
|
|
rank := svd.Rank(rcond)
|
|
if rank == 0 {
|
|
log.Fatal("zero rank system")
|
|
}
|
|
|
|
b := mat.NewDense(5, 2, []float64{
|
|
-2.318, -4.35,
|
|
-0.715, 1.451,
|
|
1.836, -0.119,
|
|
-0.357, 3.094,
|
|
-1.636, 0.021,
|
|
})
|
|
|
|
// Find a least-squares solution using the determined parts of the system.
|
|
var x mat.Dense
|
|
svd.SolveTo(&x, b, rank)
|
|
|
|
fmt.Printf("singular values = %v\nrank = %d\nx = %.15f",
|
|
format(svd.Values(nil), 4, rcond), rank, mat.Formatted(&x, mat.Prefix(" ")))
|
|
|
|
// Output:
|
|
// singular values = [2.685 1.526 <1e-15]
|
|
// rank = 2
|
|
// x = ⎡ 1.212064313552347 1.507467451093930⎤
|
|
// ⎢ 0.415400738264774 -0.624498607705372⎥
|
|
// ⎣-0.183184442255280 2.221334193689124⎦
|
|
}
|
|
|
|
func ExampleSVD_SolveVecTo() {
|
|
// The system described by A is rank deficient.
|
|
a := mat.NewDense(5, 3, []float64{
|
|
-1.7854591879711257, -0.42687285925779594, -0.12730256811265162,
|
|
-0.5728984211439724, -0.10093393134001777, -0.1181901192353067,
|
|
1.2484316018707418, 0.5646683943038734, -0.48229492403243485,
|
|
0.10174927665169475, -0.5805410929482445, 1.3054473231942054,
|
|
-1.134174808195733, -0.4732430202414438, 0.3528489486370508,
|
|
})
|
|
|
|
// Perform an SVD retaining all singular vectors.
|
|
var svd mat.SVD
|
|
ok := svd.Factorize(a, mat.SVDFull)
|
|
if !ok {
|
|
log.Fatal("failed to factorize A")
|
|
}
|
|
|
|
// Determine the rank of the A matrix with a near zero condition threshold.
|
|
const rcond = 1e-15
|
|
rank := svd.Rank(rcond)
|
|
if rank == 0 {
|
|
log.Fatal("zero rank system")
|
|
}
|
|
|
|
b := mat.NewVecDense(5, []float64{-2.318, -0.715, 1.836, -0.357, -1.636})
|
|
|
|
// Find a least-squares solution using the determined parts of the system.
|
|
var x mat.VecDense
|
|
svd.SolveVecTo(&x, b, rank)
|
|
|
|
fmt.Printf("singular values = %v\nrank = %d\nx = %.15f",
|
|
format(svd.Values(nil), 4, rcond), rank, mat.Formatted(&x, mat.Prefix(" ")))
|
|
|
|
// Output:
|
|
// singular values = [2.685 1.526 <1e-15]
|
|
// rank = 2
|
|
// x = ⎡ 1.212064313552347⎤
|
|
// ⎢ 0.415400738264774⎥
|
|
// ⎣-0.183184442255280⎦
|
|
}
|
|
|
|
func format(vals []float64, prec int, eps float64) []string {
|
|
s := make([]string, len(vals))
|
|
for i, v := range vals {
|
|
if v < eps {
|
|
s[i] = fmt.Sprintf("<%.*g", prec, eps)
|
|
continue
|
|
}
|
|
s[i] = fmt.Sprintf("%.*g", prec, v)
|
|
}
|
|
return s
|
|
}
|