AbstractIntervalNumericalMatrix.java

/*
 * Created on 2010/06/30
 * Copyright (C) 2010 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.cga.interval.matrix;

import org.mklab.cga.interval.scalar.IntervalNumericalScalar;
import org.mklab.cga.util.IntervalUtil;
import org.mklab.nfc.matrix.IntMatrix;
import org.mklab.nfc.matrix.MatrixSizeException;
import org.mklab.nfc.matrix.NormType;
import org.mklab.nfc.matrix.NumericalMatrix;
import org.mklab.nfc.scalar.NumericalScalar;


/**
 * 数値区間行列を表す抽象クラスです。
 * 
 * @author koga
 * @version $Revision$, 2010/06/30
 * @param <IS> 区間スカラーの型
 * @param <IM> 区間行列の型
 * @param <S> スカラーの型
 * @param <M> 行列の型
 */
public abstract class AbstractIntervalNumericalMatrix<IS extends IntervalNumericalScalar<IS,IM,S,M>, IM extends IntervalNumericalMatrix<IS,IM,S,M>, S extends NumericalScalar<S,M>, M extends NumericalMatrix<S,M> > extends AbstractIntervalMatrix<IS,IM,S,M> implements IntervalNumericalMatrix<IS,IM,S,M>{

  /** */
  private static final long serialVersionUID = 4781790569822382029L;
  
  /**
   * 新しく生成された<code>AbstractNumericalIntervalMatrix</code>オブジェクトを初期化します。
   */
  public AbstractIntervalNumericalMatrix() {
    super();
  }

  /**
   * rowSize行, columnSize列の実数区間行列を作成します。 ただし、行列の中身は零行列です。
   * 
   * @param rowSize 行数
   * @param columnSize 列数
   */
  public AbstractIntervalNumericalMatrix(final int rowSize, final int columnSize) {
    super(rowSize, columnSize);
  }



  /**
   * {@inheritDoc}
   */
  public S norms(final NormType normType) {
    return IntervalUtil.norm((IM)this, normType);
  }
  
  /**
   * Returns norm.
   * 
   * @return norm
   */
  public IS norm() {
    IM singularValue = singularValue();
    return singularValue.getElement(1);
  }


  
  /**
   * {@inheritDoc}
   */
  public IS determinant() {
    if (isSquare() == false) {
      throw new MatrixSizeException(MatrixSizeException.NOT_A_SQUARE_MATRIX);
    }

    int rowSize = getRowSize();

    if (rowSize == 1) {
      return getElement(1, 1);
    }

    if (rowSize == 2) {
     IS a11 = getElement(1, 1);
     IS a12 = getElement(1, 2);
     IS a21 = getElement(2, 1);
     IS a22 = getElement(2, 2);

      return a11.multiply(a22).subtract(a12.multiply(a21));
    }

    if (rowSize == 3) {
     IS a11 = getElement(1, 1);
     IS a12 = getElement(1, 2);
     IS a13 = getElement(1, 3);
     IS a21 = getElement(2, 1);
     IS a22 = getElement(2, 2);
     IS a23 = getElement(2, 3);
     IS a31 = getElement(3, 1);
     IS a32 = getElement(3, 2);
     IS a33 = getElement(3, 3);

     IS tmp1 = a11.multiply(a22).multiply(a33); /* a(1,1)*a(2,2)*a(3,3) */
     IS tmp2 = a12.multiply(a23).multiply(a31); /* a(1,2)*a(2,3)*a(3,1) */
     IS tmp3 = a13.multiply(a21).multiply(a32); /* a(1,3)*a(2,1)*a(3,2) */

     IS det = tmp1.add(tmp2).add(tmp3);

     IS tmp4 = a13.multiply(a22).multiply(a31); /* a(1,3)*a(2,2)*a(3,1) */
     IS tmp5 = a12.multiply(a21).multiply(a33); /* a(1,2)*a(2,1)*a(3,3) */
     IS tmp6 = a11.multiply(a23).multiply(a32); /* a(1,1)*a(2,3)*a(3,2) */

      return det.subtract(tmp4).subtract(tmp5).subtract(tmp6);
    }

   IS det = getElement(1, 1).createZero();

    /* Discard the first column */
    IM m1 = getColumnVectors(2, getColumnSize());

    int m1r = m1.getRowSize();
    int m1c = m1.getColumnSize();

    for (int i = 1; i <= m1r; i++) {
      IM m2;
      if (i == 1) {
        m2 = getSubMatrix(2, m1r, 1, m1c);
      } else if (i == m1r) {
        m2 = getSubMatrix(1, m1r - 1, 1, m1c);
      } else {
        IM m3 = getSubMatrix(1, i - 1, 1, m1c);
        IM m4 = getSubMatrix(i + 1, m1r, 1, m1c);
        m2 = m3.appendDown(m4);
      }

     IS subDet = getElement(i, 1).multiply(m2.determinant());

      if (i % 2 != 0) {
        det = det.add(subDet);
      } else {
        det = det.subtract(subDet);
      }
    }
    return det;
  }


  /**
   * {@inheritDoc}
   */
  public IS sum() {
    return sumRowWise().sumColumnWise().getElement(1, 1);
  }

  /**
   * {@inheritDoc}
   */
  public IS mean() {
    return sumRowWise().sumColumnWise().getElement(1, 1).divide(getRowSize() * getColumnSize());
  }

  /**
   * {@inheritDoc}
   */
  public IS variance() {
    IM zeroMean = subtractElementWise(mean());
    return zeroMean.powerElementWise(2).sum().divide(getRowSize() * getColumnSize() - 1);
  }

  /**
   * {@inheritDoc}
   */
  public IS product() {
    return productRowWise().productColumnWise().getElement(1, 1);
  }

  /**
   * {@inheritDoc}
   */
  public IS trace() {
    return diagonalToVector().sum();
  }

  /**
   * {@inheritDoc}
   */
  public IM leftDivideElementWise(final IM value) {
    return leftDivideElementWise(value);
  }

  /**
   * {@inheritDoc}
   */
  public IM powerElementWise(IM order) {
    return powerElementWise(order);
  }

  /**
   * {@inheritDoc}
   */
  public IM powerElementWise(int orderr) {
    IM ans = createOnes();
    for (int i = 0; i <= orderr; i++) {
      ans = ans.multiplyElementWise((IM)this);
    }
    return ans;
  }

  /**
   * {@inheritDoc}
   */
  public IM powerElementWise(final IntMatrix order) {
    if (hasSameRowSize(order) == false || hasSameColumnSize(order) == false) {
      throw new MatrixSizeException(MatrixSizeException.NOT_SAME_SIZE);
    }

    IM ans = createZero();
    for (int row = 1; row <= getRowSize(); row++) {
      for (int column = 1; column <= getColumnSize(); column++) {
        IS value = getElement(row, column);
        int valueOrder = order.getIntElement(row, column);
        ans.setElement(row, column, value.power(valueOrder));
      }
    }

    return ans;
  }

}