IntervalDerivativeFunctionEvaluation.java

/*
 * Created on 2004/12/06
 * Copyright (C) 2004 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.cga.derivative;

import java.util.ArrayList;
import java.util.List;

import org.mklab.cga.interval.matrix.IntervalNumericalMatrix;
import org.mklab.cga.interval.scalar.IntervalNumericalScalar;
import org.mklab.nfc.matrix.NumericalMatrix;
import org.mklab.nfc.scalar.NumericalScalar;


/**
 * 非線形方程式の変数に値を代入したときの計算値とその微分値、ヤコビ行列を求めるクラスです。
 * 
 * @author hiroki
 * @version $Revision: 1.7 $.2004/12/06
 * @param <IDS> 区間微分スカラーの型
 * @param <IDM> 区間微分行列の型
 * @param <IS> 区間スカラーの型
 * @param <IM> 区間行列の型
 * @param <S> スカラーの型
 * @param <M> 行列の型
 */
public class IntervalDerivativeFunctionEvaluation<IDS extends IntervalDerivativeNumber<IDS ,IDM,IS,IM,S,M>, IDM extends IntervalDerivativeMatrix<IDS,IDM,IS,IM,S,M>, IS extends IntervalNumericalScalar<IS,IM,S,M>,  IM extends IntervalNumericalMatrix<IS,IM,S,M>, S extends NumericalScalar<S,M>, M extends NumericalMatrix<S,M> > {

  /** 関数定義オブジェクト */
  private IntervalDerivativeFunction<IDS,IDM,IS,IM,S,M> idfunc;

  /**
   * コンストラクタ
   * 
   * @param eq 関数オブジェクト
   */
  public IntervalDerivativeFunctionEvaluation(IntervalDerivativeFunction<IDS,IDM,IS,IM,S,M> eq) {
    this.idfunc = eq;
  }

  /**
   * 関数に<code>x0</code>を代入したときの値、微分値、ヤコビ行列を求めます。
   * 
   * @param x0 関数に代入する値
   * @return 関数の値、微分値、ヤコビ行列の配列
   */
  public List<IM> getValues(IDS[] x0) {
    IS iunit = x0[0].getX();

    IDS[] ad = this.idfunc.func(x0);// f(x)の値とdf(x)の値をもとめる。

    /* Jacobianを求める */
    int variableSize = x0.length;
    int functionSize = ad.length;

    IS[][] xElement = iunit.createArray(ad.length, 1);
    IS[][] dxElement =iunit.createArray(ad.length, 1);

    for (int i = 0; i < functionSize; i++) {
      xElement[i][0] = ad[i].getX();
      dxElement[i][0] = ad[i].getDX();
    }

    IM x =  xElement[0][0].createGrid(xElement);
    IM dx = dxElement[0][0].createGrid(dxElement);

    IM jacobian = null;
    IS[][] jacobiElement = iunit.createArray(functionSize, variableSize);
    for (int i = 0; i < functionSize; i++) {
      for (int j = 0; j < variableSize; j++) {
        jacobiElement[i][j] = x0[0].getX().createZero();
      }
    }

    IDS[] ad1;

    // すべての変数を定数として設定します。
    for (int i = 0; i < variableSize; i++) {
      x0[i].setDX(iunit.createZero());
    }

    for (int i = 0; i < variableSize; i++) {
      x0[i].setDX(iunit.createUnit());// 偏微分を行いたいものだけ変数に変更します
      ad1 = this.idfunc.func(x0);

      for (int j = 0; j < functionSize; j++) {
        jacobiElement[j][i] = ad1[j].getDX();
      }
      x0[i].setDX(iunit.createZero());// 次の偏微分のため変数に変更した値を定数に戻す

    }

    jacobian = jacobiElement[0][0].createGrid(jacobiElement);

    List<IM> ans = new ArrayList<>();
    ans.add(x);
    ans.add(dx);
    ans.add(jacobian);
    return ans;
  }
}