⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eigenvaluedecomposition.java

📁 代码是一个分类器的实现,其中使用了部分weka的源代码。可以将项目导入eclipse运行
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * This software is a cooperative product of The MathWorks and the National * Institute of Standards and Technology (NIST) which has been released to the * public domain. Neither The MathWorks nor NIST assumes any responsibility * whatsoever for its use by other parties, and makes no guarantees, expressed * or implied, about its quality, reliability, or any other characteristic. *//* * EigenvalueDecomposition.java * Copyright (C) 1999 The Mathworks and NIST * */package weka.core.matrix;import java.io.Serializable;/**  * Eigenvalues and eigenvectors of a real matrix.  * <P> * If A is symmetric, then A = V*D*V' where the eigenvalue matrix D is diagonal * and the eigenvector matrix V is orthogonal.  I.e. A = * V.times(D.times(V.transpose())) and V.times(V.transpose()) equals the * identity matrix. * <P> * If A is not symmetric, then the eigenvalue matrix D is block diagonal with * the real eigenvalues in 1-by-1 blocks and any complex eigenvalues, lambda + * i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda].  The columns of V * represent the eigenvectors in the sense that A*V = V*D, i.e. A.times(V) * equals V.times(D).  The matrix V may be badly conditioned, or even singular, * so the validity of the equation A = V*D*inverse(V) depends upon V.cond(). * <p/> * Adapted from the <a href="http://math.nist.gov/javanumerics/jama/" target="_blank">JAMA</a> package. * * @author The Mathworks and NIST  * @author Fracpete (fracpete at waikato dot ac dot nz) * @version $Revision: 1.2 $ */public class EigenvalueDecomposition   implements Serializable {  /**    * Row and column dimension (square matrix).   * @serial matrix dimension.   */  private int n;  /**    * Symmetry flag.   * @serial internal symmetry flag.   */  private boolean issymmetric;  /**    * Arrays for internal storage of eigenvalues.   * @serial internal storage of eigenvalues.   */  private double[] d, e;  /**    * Array for internal storage of eigenvectors.   * @serial internal storage of eigenvectors.   */  private double[][] V;  /**    * Array for internal storage of nonsymmetric Hessenberg form.   * @serial internal storage of nonsymmetric Hessenberg form.   */  private double[][] H;  /**    * Working storage for nonsymmetric algorithm.   * @serial working storage for nonsymmetric algorithm.   */  private double[] ort;  /**   * helper variables for the comples scalar division   * @see #cdiv(double,double,double,double)   */  private transient double cdivr, cdivi;  /**    * Symmetric Householder reduction to tridiagonal form.   * <p/>   * This is derived from the Algol procedures tred2 by Bowdler, Martin,   * Reinsch, and Wilkinson, Handbook for Auto. Comp., Vol.ii-Linear Algebra,   * and the corresponding Fortran subroutine in EISPACK.   */  private void tred2() {    for (int j = 0; j < n; j++) {      d[j] = V[n-1][j];    }    // Householder reduction to tridiagonal form.    for (int i = n-1; i > 0; i--) {      // Scale to avoid under/overflow.      double scale = 0.0;      double h = 0.0;      for (int k = 0; k < i; k++) {        scale = scale + Math.abs(d[k]);      }      if (scale == 0.0) {        e[i] = d[i-1];        for (int j = 0; j < i; j++) {          d[j] = V[i-1][j];          V[i][j] = 0.0;          V[j][i] = 0.0;        }      } else {        // Generate Householder vector.        for (int k = 0; k < i; k++) {          d[k] /= scale;          h += d[k] * d[k];        }        double f = d[i-1];        double g = Math.sqrt(h);        if (f > 0) {          g = -g;        }        e[i] = scale * g;        h = h - f * g;        d[i-1] = f - g;        for (int j = 0; j < i; j++) {          e[j] = 0.0;        }        // Apply similarity transformation to remaining columns.        for (int j = 0; j < i; j++) {          f = d[j];          V[j][i] = f;          g = e[j] + V[j][j] * f;          for (int k = j+1; k <= i-1; k++) {            g += V[k][j] * d[k];            e[k] += V[k][j] * f;          }          e[j] = g;        }        f = 0.0;        for (int j = 0; j < i; j++) {          e[j] /= h;          f += e[j] * d[j];        }        double hh = f / (h + h);        for (int j = 0; j < i; j++) {          e[j] -= hh * d[j];        }        for (int j = 0; j < i; j++) {          f = d[j];          g = e[j];          for (int k = j; k <= i-1; k++) {            V[k][j] -= (f * e[k] + g * d[k]);          }          d[j] = V[i-1][j];          V[i][j] = 0.0;        }      }      d[i] = h;    }    // Accumulate transformations.    for (int i = 0; i < n-1; i++) {      V[n-1][i] = V[i][i];      V[i][i] = 1.0;      double h = d[i+1];      if (h != 0.0) {        for (int k = 0; k <= i; k++) {          d[k] = V[k][i+1] / h;        }        for (int j = 0; j <= i; j++) {          double g = 0.0;          for (int k = 0; k <= i; k++) {            g += V[k][i+1] * V[k][j];          }          for (int k = 0; k <= i; k++) {            V[k][j] -= g * d[k];          }        }      }      for (int k = 0; k <= i; k++) {        V[k][i+1] = 0.0;      }    }    for (int j = 0; j < n; j++) {      d[j] = V[n-1][j];      V[n-1][j] = 0.0;    }    V[n-1][n-1] = 1.0;    e[0] = 0.0;  }   /**    * Symmetric tridiagonal QL algorithm.   * <p/>   * This is derived from the Algol procedures tql2, by Bowdler, Martin,   * Reinsch, and Wilkinson, Handbook for Auto. Comp., Vol.ii-Linear Algebra,   * and the corresponding Fortran subroutine in EISPACK.   */  private void tql2() {    for (int i = 1; i < n; i++) {      e[i-1] = e[i];    }    e[n-1] = 0.0;    double f = 0.0;    double tst1 = 0.0;    double eps = Math.pow(2.0,-52.0);    for (int l = 0; l < n; l++) {      // Find small subdiagonal element      tst1 = Math.max(tst1,Math.abs(d[l]) + Math.abs(e[l]));      int m = l;      while (m < n) {        if (Math.abs(e[m]) <= eps*tst1) {          break;        }        m++;      }      // If m == l, d[l] is an eigenvalue,      // otherwise, iterate.      if (m > l) {        int iter = 0;        do {          iter = iter + 1;  // (Could check iteration count here.)          // Compute implicit shift          double g = d[l];          double p = (d[l+1] - g) / (2.0 * e[l]);          double r = Maths.hypot(p,1.0);          if (p < 0) {            r = -r;          }          d[l] = e[l] / (p + r);          d[l+1] = e[l] * (p + r);          double dl1 = d[l+1];          double h = g - d[l];          for (int i = l+2; i < n; i++) {            d[i] -= h;          }          f = f + h;          // Implicit QL transformation.          p = d[m];          double c = 1.0;          double c2 = c;          double c3 = c;          double el1 = e[l+1];          double s = 0.0;          double s2 = 0.0;          for (int i = m-1; i >= l; i--) {            c3 = c2;            c2 = c;            s2 = s;            g = c * e[i];            h = c * p;            r = Maths.hypot(p,e[i]);            e[i+1] = s * r;            s = e[i] / r;            c = p / r;            p = c * d[i] - s * g;            d[i+1] = h + s * (c * g + s * d[i]);            // Accumulate transformation.            for (int k = 0; k < n; k++) {              h = V[k][i+1];              V[k][i+1] = s * V[k][i] + c * h;              V[k][i] = c * V[k][i] - s * h;            }          }          p = -s * s2 * c3 * el1 * e[l] / dl1;          e[l] = s * p;          d[l] = c * p;          // Check for convergence.        } while (Math.abs(e[l]) > eps*tst1);      }      d[l] = d[l] + f;      e[l] = 0.0;    }    // Sort eigenvalues and corresponding vectors.    for (int i = 0; i < n-1; i++) {      int k = i;      double p = d[i];      for (int j = i+1; j < n; j++) {        if (d[j] < p) {          k = j;          p = d[j];        }      }      if (k != i) {        d[k] = d[i];        d[i] = p;        for (int j = 0; j < n; j++) {          p = V[j][i];          V[j][i] = V[j][k];          V[j][k] = p;        }      }    }  }  /**   * Nonsymmetric reduction to Hessenberg form.   * <p/>   * This is derived from the Algol procedures orthes and ortran, by Martin   * and Wilkinson, Handbook for Auto. Comp., Vol.ii-Linear Algebra, and the   * corresponding Fortran subroutines in EISPACK.   */  private void orthes() {    int low = 0;    int high = n-1;    for (int m = low+1; m <= high-1; m++) {      // Scale column.      double scale = 0.0;      for (int i = m; i <= high; i++) {        scale = scale + Math.abs(H[i][m-1]);      }      if (scale != 0.0) {        // Compute Householder transformation.        double h = 0.0;        for (int i = high; i >= m; i--) {          ort[i] = H[i][m-1]/scale;          h += ort[i] * ort[i];        }        double g = Math.sqrt(h);        if (ort[m] > 0) {          g = -g;        }        h = h - ort[m] * g;        ort[m] = ort[m] - g;        // Apply Householder similarity transformation        // H = (I-u*u'/h)*H*(I-u*u')/h)        for (int j = m; j < n; j++) {          double f = 0.0;          for (int i = high; i >= m; i--) {            f += ort[i]*H[i][j];          }          f = f/h;          for (int i = m; i <= high; i++) {            H[i][j] -= f*ort[i];          }        }        for (int i = 0; i <= high; i++) {          double f = 0.0;          for (int j = high; j >= m; j--) {            f += ort[j]*H[i][j];          }          f = f/h;          for (int j = m; j <= high; j++) {            H[i][j] -= f*ort[j];          }        }        ort[m] = scale*ort[m];        H[m][m-1] = scale*g;      }    }    // Accumulate transformations (Algol's ortran).    for (int i = 0; i < n; i++) {      for (int j = 0; j < n; j++) {        V[i][j] = (i == j ? 1.0 : 0.0);      }    }    for (int m = high-1; m >= low+1; m--) {      if (H[m][m-1] != 0.0) {        for (int i = m+1; i <= high; i++) {          ort[i] = H[i][m-1];        }        for (int j = m; j <= high; j++) {          double g = 0.0;          for (int i = m; i <= high; i++) {            g += ort[i] * V[i][j];          }          // Double division avoids possible underflow          g = (g / ort[m]) / H[m][m-1];          for (int i = m; i <= high; i++) {            V[i][j] += g * ort[i];          }        }      }    }  }  /**    * Complex scalar division.   */  private void cdiv(double xr, double xi, double yr, double yi) {    double r,d;    if (Math.abs(yr) > Math.abs(yi)) {      r = yi/yr;      d = yr + r*yi;      cdivr = (xr + r*xi)/d;      cdivi = (xi - r*xr)/d;    } else {      r = yr/yi;      d = yi + r*yr;      cdivr = (r*xr + xi)/d;      cdivi = (r*xi - xr)/d;    }  }  /**   * Nonsymmetric reduction from Hessenberg to real Schur form.   * <p/>   * This is derived from the Algol procedure hqr2, by Martin and Wilkinson,   * Handbook for Auto. Comp., Vol.ii-Linear Algebra, and the corresponding   * Fortran subroutine in EISPACK.   */  private void hqr2() {    // Initialize    int nn = this.n;    int n = nn-1;    int low = 0;    int high = nn-1;    double eps = Math.pow(2.0,-52.0);    double exshift = 0.0;    double p=0,q=0,r=0,s=0,z=0,t,w,x,y;    // Store roots isolated by balanc and compute matrix norm    double norm = 0.0;    for (int i = 0; i < nn; i++) {      if (i < low | i > high) {        d[i] = H[i][i];        e[i] = 0.0;      }      for (int j = Math.max(i-1,0); j < nn; j++) {        norm = norm + Math.abs(H[i][j]);      }    }    // Outer loop over eigenvalue index    int iter = 0;    while (n >= low) {      // Look for single small sub-diagonal element      int l = n;      while (l > low) {        s = Math.abs(H[l-1][l-1]) + Math.abs(H[l][l]);        if (s == 0.0) {          s = norm;        }        if (Math.abs(H[l][l-1]) < eps * s) {          break;        }        l--;      }      // Check for convergence

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -