📄 svd.java
字号:
package dragon.matrix.factorize;
import dragon.matrix.*;
/**
* <p>Singular Value Decompositin</p>
* <p>Copyright: Copyright (c) 2006</p>
* <p>Company: Drexel University</p>
* @author Xiaodan Zhang
* @version 1.0
* Notes: this java class is derived from the JAVA Package.
*/
public class SVD extends AbstractFactorization implements java.io.Serializable {
private static final long serialVersionUID = 1L;
/** Arrays for internal storage of U and V.
@serial internal storage of U.
@serial internal storage of V.
*/
private double[][] U, V;
/** Array for internal storage of singular values.
@serial internal storage of singular values.
*/
private double[] s;
/** Row and column dimensions.
@serial row dimension.
@serial column dimension.
*/
private int m, n, dimension;
public SVD() {
}
public static void main(String[] args) {
int i, j;
SVD svd;
double[] arrSingularValue;
DoubleDenseMatrix left, middle;
IntSuperSparseMatrix matrix = new IntSuperSparseMatrix("xu/query1/relationcpt/all/termdoc.matrix");
matrix.finalizeData();
svd = new SVD();
svd.factorize(matrix, 12);
left = svd.getLeftMatrix();
middle =svd.getMiddleMatrix();
//product of left and middle matrix
for(i=0;i<left.rows();i++){
for(j=0;j<middle.columns();j++){
left.setDouble(i,j,left.getDouble(i,j)*middle.getDouble(j,j));
}
}
//calculate term cosine
arrSingularValue = svd.getSingularValues();
for (i = 0; i < arrSingularValue.length; i++) {
System.out.println(arrSingularValue[i]);
}
}
public void factorize(SparseMatrix matrix, int dimension) {
// Derived from LINPACK code.
// Initialize.
double[][] A;
int r, v;
int[] indexList;
double[] scoreList;
this.m = matrix.rows();
this.n = matrix.columns();
this.dimension = dimension;
A = new double[m][n];
for (r = 0; r < m; r++) {
indexList = matrix.getNonZeroColumnsInRow(r);
scoreList = matrix.getNonZeroDoubleScoresInRow(r);
for (v = 0; v < indexList.length; v++)
A[r][indexList[v]] = scoreList[v];
}
/* Apparently the failing cases are only a proper subset of (m<n),
so let's not throw error. Correct fix to come later?
if (m<n) {
throw new IllegalArgumentException("Jama SVD only works for m >= n"); }
*/
int nu = Math.min(m, n);
s = new double[Math.min(m + 1, n)];
U = new double[m][nu];
V = new double[n][n];
double[] e = new double[n];
double[] work = new double[m];
boolean wantu = true;
boolean wantv = true;
// Reduce A to bidiagonal form, storing the diagonal elements
// in s and the super-diagonal elements in e.
int nct = Math.min(m - 1, n);
int nrt = Math.max(0, Math.min(n - 2, m));
for (int k = 0; k < Math.max(nct, nrt); k++) {
System.out.println(new java.util.Date()+" processing "+k);
if (k < nct) {
// Compute the transformation for the k-th column and
// place the k-th diagonal in s[k].
// Compute 2-norm of k-th column without under/overflow.
s[k] = 0;
for (int i = k; i < m; i++) {
s[k] = hypot(s[k], A[i][k]);
}
if (s[k] != 0.0) {
if (A[k][k] < 0.0) {
s[k] = -s[k];
}
for (int i = k; i < m; i++) {
A[i][k] /= s[k];
}
A[k][k] += 1.0;
}
s[k] = -s[k];
}
for (int j = k + 1; j < n; j++) {
if ( (k < nct) & (s[k] != 0.0)) {
// Apply the transformation.
double t = 0;
for (int i = k; i < m; i++) {
t += A[i][k] * A[i][j];
}
t = -t / A[k][k];
for (int i = k; i < m; i++) {
A[i][j] += t * A[i][k];
}
}
// Place the k-th row of A into e for the
// subsequent calculation of the row transformation.
e[j] = A[k][j];
}
if (wantu & (k < nct)) {
// Place the transformation in U for subsequent back
// multiplication.
for (int i = k; i < m; i++) {
U[i][k] = A[i][k];
}
}
if (k < nrt) {
// Compute the k-th row transformation and place the
// k-th super-diagonal in e[k].
// Compute 2-norm without under/overflow.
e[k] = 0;
for (int i = k + 1; i < n; i++) {
e[k] = hypot(e[k], e[i]);
}
if (e[k] != 0.0) {
if (e[k + 1] < 0.0) {
e[k] = -e[k];
}
for (int i = k + 1; i < n; i++) {
e[i] /= e[k];
}
e[k + 1] += 1.0;
}
e[k] = -e[k];
if ( (k + 1 < m) & (e[k] != 0.0)) {
// Apply the transformation.
for (int i = k + 1; i < m; i++) {
work[i] = 0.0;
}
for (int j = k + 1; j < n; j++) {
for (int i = k + 1; i < m; i++) {
work[i] += e[j] * A[i][j];
}
}
for (int j = k + 1; j < n; j++) {
double t = -e[j] / e[k + 1];
for (int i = k + 1; i < m; i++) {
A[i][j] += t * work[i];
}
}
}
if (wantv) {
// Place the transformation in V for subsequent
// back multiplication.
for (int i = k + 1; i < n; i++) {
V[i][k] = e[i];
}
}
}
}
// Set up the final bidiagonal matrix or order p.
int p = Math.min(n, m + 1);
if (nct < n) {
s[nct] = A[nct][nct];
}
if (m < p) {
s[p - 1] = 0.0;
}
if (nrt + 1 < p) {
e[nrt] = A[nrt][p - 1];
}
e[p - 1] = 0.0;
// If required, generate U.
if (wantu) {
for (int j = nct; j < nu; j++) {
for (int i = 0; i < m; i++) {
U[i][j] = 0.0;
}
U[j][j] = 1.0;
}
for (int k = nct - 1; k >= 0; k--) {
if (s[k] != 0.0) {
for (int j = k + 1; j < nu; j++) {
double t = 0;
for (int i = k; i < m; i++) {
t += U[i][k] * U[i][j];
}
t = -t / U[k][k];
for (int i = k; i < m; i++) {
U[i][j] += t * U[i][k];
}
}
for (int i = k; i < m; i++) {
U[i][k] = -U[i][k];
}
U[k][k] = 1.0 + U[k][k];
for (int i = 0; i < k - 1; i++) {
U[i][k] = 0.0;
}
} else {
for (int i = 0; i < m; i++) {
U[i][k] = 0.0;
}
U[k][k] = 1.0;
}
}
}
// If required, generate V.
if (wantv) {
for (int k = n - 1; k >= 0; k--) {
if ( (k < nrt) & (e[k] != 0.0)) {
for (int j = k + 1; j < nu; j++) {
double t = 0;
for (int i = k + 1; i < n; i++) {
t += V[i][k] * V[i][j];
}
t = -t / V[k + 1][k];
for (int i = k + 1; i < n; i++) {
V[i][j] += t * V[i][k];
}
}
}
for (int i = 0; i < n; i++) {
V[i][k] = 0.0;
}
V[k][k] = 1.0;
}
}
// Main iteration loop for the singular values.
int pp = p - 1;
int iter = 0;
double eps = Math.pow(2.0, -52.0);
double tiny = Math.pow(2.0, -966.0);
while (p > 0) {
int k, kase;
// Here is where a test for too many iterations would go.
// This section of the program inspects for
// negligible elements in the s and e arrays. On
// completion the variables kase and k are set as follows.
// kase = 1 if s(p) and e[k-1] are negligible and k<p
// kase = 2 if s(k) is negligible and k<p
// kase = 3 if e[k-1] is negligible, k<p, and
// s(k), ..., s(p) are not negligible (qr step).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -