package de.lmu.ifi.dbs.elki.math.linearalgebra; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2011 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import java.util.Arrays; import java.util.Comparator; import java.util.List; /** * Helper class which encapsulates an array of eigenpairs (i.e. an array of * eigenvectors and their corresponding eigenvalues). This class is used to sort * eigenvectors (and -values). * * @author Elke Achtert * * @apiviz.composedOf de.lmu.ifi.dbs.elki.math.linearalgebra.EigenPair */ public class SortedEigenPairs { /** * The array of eigenpairs. */ private EigenPair[] eigenPairs; /** * Creates a new empty SortedEigenPairs object. Can only be called from the * copy() method. */ private SortedEigenPairs() { // nothing to do here. } /** * Creates a new SortedEigenPairs object from the specified eigenvalue * decomposition. The eigenvectors are sorted according to the specified * order. * * @param evd the underlying eigenvalue decomposition * @param ascending a boolean that indicates ascending order */ public SortedEigenPairs(EigenvalueDecomposition evd, final boolean ascending) { double[] eigenvalues = evd.getRealEigenvalues(); Matrix eigenvectors = evd.getV(); this.eigenPairs = new EigenPair[eigenvalues.length]; for(int i = 0; i < eigenvalues.length; i++) { double e = java.lang.Math.abs(eigenvalues[i]); Vector v = eigenvectors.getColumnVector(i); eigenPairs[i] = new EigenPair(v, e); } Comparator comp = new Comparator() { @Override public int compare(EigenPair o1, EigenPair o2) { int comp = o1.compareTo(o2); if(!ascending) { comp = -1 * comp; } return comp; } }; Arrays.sort(eigenPairs, comp); } /** * Creates a new SortedEigenPairs object from the specified list. The * eigenvectors are sorted in descending order. * * @param eigenPairs the eigenpairs to be sorted */ public SortedEigenPairs(List eigenPairs) { Comparator comp = new Comparator() { @Override public int compare(EigenPair o1, EigenPair o2) { return -1 * o1.compareTo(o2); } }; this.eigenPairs = eigenPairs.toArray(new EigenPair[eigenPairs.size()]); Arrays.sort(this.eigenPairs, comp); } /** * Returns the sorted eigenvalues. * * @return the sorted eigenvalues */ public double[] eigenValues() { double[] eigenValues = new double[eigenPairs.length]; for(int i = 0; i < eigenPairs.length; i++) { EigenPair eigenPair = eigenPairs[i]; eigenValues[i] = eigenPair.getEigenvalue(); } return eigenValues; } /** * Returns the sorted eigenvectors. * * @return the sorted eigenvectors */ public Matrix eigenVectors() { Matrix eigenVectors = new Matrix(eigenPairs.length, eigenPairs.length); for(int i = 0; i < eigenPairs.length; i++) { EigenPair eigenPair = eigenPairs[i]; eigenVectors.setColumnVector(i, eigenPair.getEigenvector()); } return eigenVectors; } /** * Returns the first n sorted eigenvectors as a matrix. * * @param n the number of eigenvectors (columns) to be returned * @return the first n sorted eigenvectors */ public Matrix eigenVectors(int n) { Matrix eigenVectors = new Matrix(eigenPairs.length, n); for(int i = 0; i < n; i++) { EigenPair eigenPair = eigenPairs[i]; eigenVectors.setColumnVector(i, eigenPair.getEigenvector()); } return eigenVectors; } /** * Returns the last n sorted eigenvectors as a matrix. * * @param n the number of eigenvectors (columns) to be returned * @return the last n sorted eigenvectors */ public Matrix reverseEigenVectors(int n) { Matrix eigenVectors = new Matrix(eigenPairs.length, n); for(int i = 0; i < n; i++) { EigenPair eigenPair = eigenPairs[eigenPairs.length - 1 - i]; eigenVectors.setColumnVector(i, eigenPair.getEigenvector()); } return eigenVectors; } /** * Returns the eigenpair at the specified index. * * @param index the index of the eigenpair to be returned * @return the eigenpair at the specified index */ public EigenPair getEigenPair(int index) { return eigenPairs[index]; } /** * Returns the number of the eigenpairs. * * @return the number of the eigenpairs */ public int size() { return eigenPairs.length; } /** * Returns a string representation of this EigenPair. * * @return a string representation of this EigenPair */ @Override public String toString() { StringBuffer result = new StringBuffer(); for(EigenPair eigenPair : eigenPairs) { result.append("\n").append(eigenPair); } return result.toString(); } /** * Returns a deep copy of this object * * @return new copy */ public SortedEigenPairs copy() { SortedEigenPairs cp = new SortedEigenPairs(); cp.eigenPairs = this.eigenPairs.clone(); return cp; } }