-
Notifications
You must be signed in to change notification settings - Fork 2
/
power_method.java
111 lines (92 loc) · 3.26 KB
/
power_method.java
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
/**
* Uses the power method to find and return dominant
* eigenvalue, vector, and number of iterations.
*
* @author Siddarth Senthilkumar
* @version 2.0
*/
public class power_method {
public static final int MAX_ITERATIONS = 100;
/**
* Implements power method to find approximation
* of largest eigenvalue and corresponding eigenvector
* @param a The nxn matrix
* @param tol The error tolerance
* @param u An initial approximation vector
* @return The approximated eigenvalue, eigenvector,
* and number of iterations for desired tolerance
*/
public static PowerObject power_method(Matrix a, double tol, Vector u) {
// Get largest value from u - initial eigenvalue guess
double largest = u.get(0);
for (int i = 1; i < u.numElements(); i++) {
if (Math.abs(u.get(i)) - Math.abs(largest) > 0) {
largest = u.get(i);
}
}
double previous = largest;
// Factor out that value from u
u = MatrixCalculator.multiply(u, 1. / largest);
PowerObject powerInfo = new PowerObject(largest, u);
// Do one iteration - necessary for recursive method to do check on previous eigenvalue
// Get Au
Vector au = MatrixCalculator.multiply(a, u);
// Get largest in Au
largest = au.get(0);
for (int i = 1; i < au.numElements(); i++) {
if (Math.abs(au.get(i)) - Math.abs(largest) > 0) {
largest = au.get(i);
}
}
// u = Au / ||largest in Au||
u = MatrixCalculator.multiply(au, 1. / largest);
// Update values in powerInfo
powerInfo.setEigenvalue(largest);
powerInfo.setEigenvector(u);
powerInfo.incrementIterations();
// Keep updating powerInfo and u until tolerance is fine
u = power_method(a, tol, u, previous, powerInfo);
return powerInfo;
}
/**
* Recursively calculates new eigenvector with power method
* @param a The nxn matrix
* @param tol The error tolerance
* @param u An initial approximation vector
* @param prev The previous eigenvalue
* @param powerInfo The PowerObject containing return data
* @return The approximated eigenvalue, eigenvector,
* and number of iterations for desired tolerance
*/
private static Vector power_method(Matrix a, double tol, Vector u, double prev, PowerObject powerInfo) {
if (powerInfo.getIterations() >= MAX_ITERATIONS) {
// If after MAX_ITERATIONS iterations, the error has not been reduced to tol or less,
// this matrix does not converge.
powerInfo.setConverges(false);
return u;
}
double thisPrevious = powerInfo.getEigenvalue();
if (Math.abs(Math.abs(thisPrevious) - Math.abs(prev)) - tol <= 0) {
// Difference between current largest eigenvalue and previous eigenvalue is less than or equal to tolerance
// We are done iterating.
return u;
}
// Tolerance not enough. need another iteration
Vector au = MatrixCalculator.multiply(a, u);
// Get au's largest
double largest = au.get(0);
for (int i = 1; i < au.numElements(); i++) {
if (Math.abs(au.get(i)) - Math.abs(largest) > 0) {
largest = au.get(i);
}
}
// Divide au by its largest and set it to u
u = MatrixCalculator.multiply(au, 1. / largest);
// Update powerInfo
powerInfo.setEigenvalue(largest);
powerInfo.setEigenvector(u);
powerInfo.incrementIterations();
// Check again if tolerance is fine
return power_method(a, tol, u, thisPrevious, powerInfo);
}
}