Package com.opengamma.analytics.math.matrix

Source Code of com.opengamma.analytics.math.matrix.CommonsMatrixAlgebra

/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.matrix;

import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.lang.Validate;
import org.apache.commons.math.linear.Array2DRowRealMatrix;
import org.apache.commons.math.linear.EigenDecomposition;
import org.apache.commons.math.linear.EigenDecompositionImpl;
import org.apache.commons.math.linear.LUDecomposition;
import org.apache.commons.math.linear.LUDecompositionImpl;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.linear.RealVector;
import org.apache.commons.math.linear.SingularValueDecomposition;
import org.apache.commons.math.linear.SingularValueDecompositionImpl;

import com.opengamma.analytics.math.util.wrapper.CommonsMathWrapper;

/**
* Provides matrix algebra by using the <a href = "http://commons.apache.org/math/api-2.1/index.html">Commons library</a>.
*/
public class CommonsMatrixAlgebra extends MatrixAlgebra {

  /**
   * {@inheritDoc}
   */
  @Override
  public double getCondition(final Matrix<?> m) {
    Validate.notNull(m, "m");
    if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      final SingularValueDecomposition svd = new SingularValueDecompositionImpl(temp);
      return svd.getConditionNumber();
    }
    throw new IllegalArgumentException("Can only find condition number of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public double getDeterminant(final Matrix<?> m) {
    Validate.notNull(m, "m");
    if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      final LUDecomposition lud = new LUDecompositionImpl(temp);
      return lud.getDeterminant();
    }
    throw new IllegalArgumentException("Can only find determinant of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public double getInnerProduct(final Matrix<?> m1, final Matrix<?> m2) {
    Validate.notNull(m1, "m1");
    Validate.notNull(m2, "m2");
    if (m1 instanceof DoubleMatrix1D && m2 instanceof DoubleMatrix1D) {
      final RealVector t1 = CommonsMathWrapper.wrap((DoubleMatrix1D) m1);
      final RealVector t2 = CommonsMathWrapper.wrap((DoubleMatrix1D) m2);
      return t1.dotProduct(t2);
    }
    throw new IllegalArgumentException("Can only find inner product of DoubleMatrix1D; have " + m1.getClass() + " and " + m2.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleMatrix2D getInverse(final Matrix<?> m) {
    Validate.notNull(m, "matrix was null");
    if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      final SingularValueDecomposition sv = new SingularValueDecompositionImpl(temp);
      final RealMatrix inv = sv.getSolver().getInverse();
      return CommonsMathWrapper.unwrap(inv);
    }
    throw new IllegalArgumentException("Can only find inverse of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public double getNorm1(final Matrix<?> m) {
    Validate.notNull(m, "m");
    if (m instanceof DoubleMatrix1D) {
      final RealVector temp = CommonsMathWrapper.wrap((DoubleMatrix1D) m);
      return temp.getL1Norm();
    } else if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      // TODO find if commons implements this anywhere, so we are not doing it
      // by hand
      double max = 0.0;
      for (int col = temp.getColumnDimension() - 1; col >= 0; col--) {
        max = Math.max(max, temp.getColumnVector(col).getL1Norm());
      }
      return max;

    }
    throw new IllegalArgumentException("Can only find norm1 of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public double getNorm2(final Matrix<?> m) {
    Validate.notNull(m, "m");
    if (m instanceof DoubleMatrix1D) {
      final RealVector temp = CommonsMathWrapper.wrap((DoubleMatrix1D) m);
      return temp.getNorm();
    } else if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      final SingularValueDecomposition svd = new SingularValueDecompositionImpl(temp);
      return svd.getNorm();
    }
    throw new IllegalArgumentException("Can only find norm2 of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public double getNormInfinity(final Matrix<?> m) {
    Validate.notNull(m, "m");
    if (m instanceof DoubleMatrix1D) {
      final RealVector temp = CommonsMathWrapper.wrap((DoubleMatrix1D) m);
      return temp.getLInfNorm();
    } else if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      //REVIEW Commons getNorm() is wrong - it returns the column norm
      // TODO find if commons implements this anywhere, so we are not doing it
      // by hand
      double max = 0.0;
      for (int row = temp.getRowDimension() - 1; row >= 0; row--) {
        max = Math.max(max, temp.getRowVector(row).getL1Norm());
      }
      return max;
    }
    throw new IllegalArgumentException("Can only find normInfinity of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleMatrix2D getOuterProduct(final Matrix<?> m1, final Matrix<?> m2) {
    Validate.notNull(m1, "m1");
    Validate.notNull(m2, "m2");
    if (m1 instanceof DoubleMatrix1D && m2 instanceof DoubleMatrix1D) {
      final RealVector t1 = CommonsMathWrapper.wrap((DoubleMatrix1D) m1);
      final RealVector t2 = CommonsMathWrapper.wrap((DoubleMatrix1D) m2);
      return CommonsMathWrapper.unwrap(t1.outerProduct(t2));
    }
    throw new IllegalArgumentException("Can only find outer product of DoubleMatrix1D; have " + m1.getClass() + " and " + m2.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleMatrix2D getPower(final Matrix<?> m, final int p) {
    Validate.notNull(m, "m");
    return getPower(m, (double) p);
  }

  /**
   * Returns a real matrix raised to some real power
   * Currently this method is limited to symmetric matrices only as Commons Math does not support the diagonalization of asymmetric matrices 
   * @param m The <strong>symmetric</strong> matrix to take the power of.
   * @param p The power to raise to matrix to
   * @return The result
   */
  @Override
  public DoubleMatrix2D getPower(final Matrix<?> m, final double p) {
    if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      final EigenDecomposition eigen = new EigenDecompositionImpl(temp, 0.0);
      final double[] rEigenValues = eigen.getRealEigenvalues();
      final double[] iEigenValues = eigen.getImagEigenvalues();
      final int n = rEigenValues.length;
      final double[][] d = new double[n][n];
      for (int i = n - 1; i >= 0; --i) {
        d[i][i] = Math.pow(rEigenValues[i], p);
        if (iEigenValues[i] != 0.0) {
          throw new NotImplementedException("Cannot handle complex eigenvalues in getPower");
        }
      }
      final RealMatrix res = eigen.getV().multiply((new Array2DRowRealMatrix(d)).multiply(eigen.getVT()));
      return CommonsMathWrapper.unwrap(res);
    }
    throw new IllegalArgumentException("Can only find pow of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public double getTrace(final Matrix<?> m) {
    Validate.notNull(m, "m");
    if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      return temp.getTrace();
    }
    throw new IllegalArgumentException("Can only find trace of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public DoubleMatrix2D getTranspose(final Matrix<?> m) {
    Validate.notNull(m, "m");
    if (m instanceof DoubleMatrix2D) {
      final RealMatrix temp = CommonsMathWrapper.wrap((DoubleMatrix2D) m);
      return CommonsMathWrapper.unwrap(temp.transpose());
    }
    throw new IllegalArgumentException("Can only find transpose of DoubleMatrix2D; have " + m.getClass());
  }

  /**
   * {@inheritDoc}
   * The following combinations of input matrices m1 and m2 are allowed:
   * <ul>
   * <li> m1 = 2-D matrix, m2 = 2-D matrix, returns $\mathbf{C} = \mathbf{AB}$
   * <li> m1 = 2-D matrix, m2 = 1-D matrix, returns $\mathbf{C} = \mathbf{A}b$
   * </ul>
   */
  @Override
  public Matrix<?> multiply(final Matrix<?> m1, final Matrix<?> m2) {
    Validate.notNull(m1, "m1");
    Validate.notNull(m2, "m2");
    Validate.isTrue(!(m1 instanceof DoubleMatrix1D), "Cannot have 1D matrix as first argument");
    if (m1 instanceof DoubleMatrix2D) {
      final RealMatrix t1 = CommonsMathWrapper.wrap((DoubleMatrix2D) m1);
      RealMatrix t2;
      if (m2 instanceof DoubleMatrix1D) {
        t2 = CommonsMathWrapper.wrapAsMatrix((DoubleMatrix1D) m2);
      } else if (m2 instanceof DoubleMatrix2D) {
        t2 = CommonsMathWrapper.wrap((DoubleMatrix2D) m2);
      } else {
        throw new IllegalArgumentException("Can only have 1D or 2D matrix as second argument");
      }
      return CommonsMathWrapper.unwrap(t1.multiply(t2));
    }
    throw new IllegalArgumentException("Can only multiply 2D and 1D matrices");
  }

}
TOP

Related Classes of com.opengamma.analytics.math.matrix.CommonsMatrixAlgebra

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.