File: svd_example_test.go

package info (click to toggle)
golang-gonum-v1-gonum 0.15.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 18,792 kB
  • sloc: asm: 6,252; fortran: 5,271; sh: 377; ruby: 211; makefile: 98
file content (112 lines) | stat: -rw-r--r-- 3,161 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// 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
}