ComplexNonlinearEquationVerifier.java

  1. /*
  2.  * Created on 2004/12/02
  3.  * Copyright (C) 2004 Koga Laboratory. All rights reserved.
  4.  *
  5.  */
  6. package org.mklab.cga.nonlinear;

  7. import java.util.List;

  8. import org.mklab.cga.derivative.IntervalDerivativeComplexMatrix;
  9. import org.mklab.cga.derivative.IntervalDerivativeComplexNumber;
  10. import org.mklab.cga.derivative.IntervalDerivativeFunction;
  11. import org.mklab.cga.derivative.IntervalDerivativeFunctionEvaluation;
  12. import org.mklab.cga.derivative.IntervalDerivativeRealMatrix;
  13. import org.mklab.cga.derivative.IntervalDerivativeRealNumber;
  14. import org.mklab.cga.interval.matrix.IntervalComplexNumericalMatrix;
  15. import org.mklab.cga.interval.matrix.IntervalRealNumericalMatrix;
  16. import org.mklab.cga.interval.scalar.IntervalComplexNumericalScalar;
  17. import org.mklab.cga.interval.scalar.IntervalRealNumericalScalar;
  18. import org.mklab.cga.util.IntervalUtil;
  19. import org.mklab.nfc.matrix.ComplexNumericalMatrix;
  20. import org.mklab.nfc.matrix.NormType;
  21. import org.mklab.nfc.matrix.RealNumericalMatrix;
  22. import org.mklab.nfc.scalar.ComplexNumericalScalar;
  23. import org.mklab.nfc.scalar.RealNumericalScalar;


  24. /**
  25.  * 非線形方程式の精度保証を行うクラスです。
  26.  *
  27.  * @author hiroki
  28.  * @version $Revision: 1.24 $.2004/12/02
  29.  * @param <RIDS> 実区間微分スカラーの型
  30.  * @param <RIDM> 実区間微分行列の型
  31.  * @param <CIDS> 複素区間微分スカラーの型
  32.  * @param <CIDM> 複素区間微分行列の型
  33.  * @param <RIS> 実区間スカラーの型
  34.  * @param <RIM> 実区間行列の型
  35.  * @param <CIS> 複素区間スカラーの型
  36.  * @param <CIM> 複素区間行列の型
  37.  * @param <RS> 実スカラーの型
  38.  * @param <RM> 実行列の型
  39.  * @param <CS> 複素スカラーの型
  40.  * @param <CM> 複素行列の型
  41.  */
  42. public class ComplexNonlinearEquationVerifier<RIDS extends IntervalDerivativeRealNumber<RIDS,RIDM,CIDS,CIDM,RIS,RIM,CIS,CIM,RS,RM,CS,CM>, RIDM extends IntervalDerivativeRealMatrix<RIDS,RIDM,CIDS,CIDM,RIS,RIM,CIS,CIM,RS,RM,CS,CM>, CIDS extends IntervalDerivativeComplexNumber<RIDS,RIDM,CIDS,CIDM,RIS,RIM,CIS,CIM,RS,RM,CS,CM>, CIDM extends IntervalDerivativeComplexMatrix<RIDS,RIDM,CIDS,CIDM,RIS,RIM,CIS,CIM,RS,RM,CS,CM>, RIS extends IntervalRealNumericalScalar<RIS,RIM,CIS,CIM,RS,RM,CS,CM>, RIM extends IntervalRealNumericalMatrix<RIS,RIM,CIS,CIM,RS,RM,CS,CM>, CIS extends IntervalComplexNumericalScalar<RIS,RIM,CIS,CIM,RS,RM,CS,CM>, CIM extends IntervalComplexNumericalMatrix<RIS,RIM,CIS,CIM,RS,RM,CS,CM>, RS extends RealNumericalScalar<RS,RM,CS,CM>, RM extends RealNumericalMatrix<RS,RM,CS,CM>, CS extends ComplexNumericalScalar<RS,RM,CS,CM>, CM extends ComplexNumericalMatrix<RS,RM,CS,CM>>{

  43.   /** 関数オブジェクト */
  44.   private IntervalDerivativeFunction<CIDS,CIDM,CIS,CIM,CS,CM> function;

  45. //  /** 初期値 */
  46. //  private M initialValue;
  47. //
  48. //  /** 初期値区間 */
  49. //  private IM intervalInitialValue;

  50.   /** 非線形方程式の解 */
  51.   private CIM solution;

  52.   /**
  53.    * コンストラクタ
  54.    *
  55.    * @param function 関数オブジェクト
  56.    */
  57.   public ComplexNonlinearEquationVerifier(IntervalDerivativeFunction<CIDS,CIDM,CIS,CIM,CS,CM> function) {
  58.     this.function = function;
  59.   }

  60.   /**
  61.    * 非線型方程式の解を精度保証付きで求めます。
  62.    *
  63.    * @param xs 初期値
  64.    * @param idm idm
  65.    * @return 非線形方程式の解
  66.    */
  67.   public CIM solve(CM xs, CIDM idm) {
  68.     CIDS ids = idm.getElement(1,1);
  69.     CIS is = ids.getX();
  70.     CIM im = idm.getX();
  71.    
  72.     int n = xs.getRowSize();
  73.     double sqrtN = Math.sqrt(n);

  74.     CM xss = xs.createClone();
  75.     CM xsold = xss;

  76.     CS element = xs.getElement(1);

  77.     CM dxs = xs.createZero();
  78.     CM dxsnew = (xs).absElementWise();

  79.     int k = 0;

  80.     CM y_x;
  81.     CM y_dx = null;

  82.     CIDS[] idxss = ids.createArray(xs.getRowSize());
  83.     IntervalDerivativeFunctionEvaluation<CIDS,CIDM,CIS,CIM,CS,CM> nee = new IntervalDerivativeFunctionEvaluation<>(this.function);

  84.     List<CIM> value1;

  85.     while (dxsnew.compareElementWise(".<", dxs.multiply(5)).anyTrue() //$NON-NLS-1$
  86.         && (dxsnew).norm(NormType.TWO).isGreaterThan((xs).norm(NormType.TWO).multiply(sqrtN * 1e-14)) && k < 100 || k < 3) {
  87.       k = k + 1;
  88.       dxs = dxsnew.createClone();
  89.       xsold = xss.createClone();

  90.       for (int i = 0; i < xss.getRowSize(); i++) {
  91.         idxss[i] = ids.create(is.create((xss).getElement(i + 1)), is.create(element.createUnit()));
  92.       }
  93.       value1 = nee.getValues(idxss);
  94.       // f(x)
  95.       y_x = value1.get(0).getMiddle();
  96.       // ヤコビ行列
  97.       y_dx = value1.get(2).getMiddle();
  98.       xss = xss.subtract(y_dx.leftDivide(y_x));
  99.       dxsnew = xss.subtract(xsold).absElementWise();
  100.     }

  101.     CIM ixss = im.create(xss);

  102.     for (int i = 0; i < xss.getRowSize(); i++) {
  103.       idxss[i] = ids.create(ixss.getElement(i + 1),  is.create(element.createUnit()));
  104.     }

  105.     // f(xss)とdf(xss)とヤコビ行列を求める
  106.     List<CIM> values = nee.getValues(idxss);
  107.     // apporoximate inver of IntervalDerivativeFunctionEvaluation
  108.     // TODO 区間にしてから、逆行列?
  109.     CIM R = im.create(y_dx.inverse());
  110.     // initialization of interval iteration
  111.     // TODO 多倍長だと?
  112.     CIM Z = R.unaryMinus().multiply(values.get(0));
  113.     CIM X = Z.createClone();

  114.     boolean ready = false;
  115.     k = 0;
  116.     CIM Y = null;

  117.     while (ready == false && k < 10) {
  118.       CM xRadius = X.getSupremum().subtract(X.getInfimum()).divide(2);
  119.      
  120.       CIM E = im.create(xRadius.multiply(element.createUnit().divide(element.createUnit().multiply(10)))).multiply(is.createInfSup(element.createUnit().unaryMinus(), element.createUnit()))
  121.             .addElementWise(is.createInfSup(element.getMachineEpsilon().unaryMinus(), element.getMachineEpsilon()));

  122.       k = k + 1;
  123.       // TODO 本当はhull(X+E,0)?
  124.       Y = X.add(E);
  125.       CIM Yold = Y.createClone();

  126.       for (int i = 0; i < xs.getColumnSize(); i++) {
  127.         idxss[i] = ids.create(Y.add(im.create(xss)).getElement(i + 1), is.create(element.createUnit()));
  128.       }

  129.       values = nee.getValues(idxss);
  130.       // f(xs+Y)
  131.       // ? IntervalMatrix Iy_x = values[0];
  132.       // ヤコビ行列
  133.       CIM Iy_dx = values.get(2);
  134.       CIM C = im.create(xs.createUnit(n)).subtract(R.multiply(Iy_dx));

  135.       int i = 0;
  136.       // improved interval iteration
  137.       while (!ready && i < 2) {
  138.         i = i + 1;
  139.         X = Z.add(C.multiply(Y));
  140.         ready = IntervalUtil.in0forRump(X, Y).allTrue();
  141.         Y = IntervalUtil.intersect(X, Yold);
  142.       }
  143.     }

  144.     if (ready) {
  145.       X = Y.add(im.create(xss));
  146.     } else {
  147.       throw new IllegalArgumentException();
  148.       // TODO 例外投げるか、NaNを返すようにする
  149.     }

  150.     return X;
  151.   }

  152.   /**
  153.    * 非線型方程式の解を精度保証付きで求めます。
  154.    *
  155.    * <p>初期値区間に真の解が含まれる場合、非線形方程式の真の解を含むより小さな区間を返します。
  156.    *
  157.    * @param xs 初期値区間
  158.    * @param idm idm
  159.    * @return 非線形方程式の解
  160.    */
  161.   public CIM solve(CIM xs, CIDM idm) {
  162.     CIDS ids = idm.getElement(1,1);
  163.     CIS is = ids.getX();
  164.     CIM im = idm.getX();
  165.    
  166.     IntervalDerivativeFunctionEvaluation<CIDS,CIDM,CIS,CIM,CS,CM> nee = new IntervalDerivativeFunctionEvaluation<>(this.function);
  167.     CIM X = xs.createClone();

  168.     CS element = (xs.getMiddle()).getElement(1);
  169.    
  170.     boolean ready = false;
  171.     int k = 0;
  172.     // TODO kの値はどれくらい?
  173.     while (ready == false && k < 10) {
  174.       k = k + 1;

  175.       CIDS[] idxs = ids.createArray(X.getRowSize());
  176.       for (int i = 0; i < X.getRowSize(); i++) {
  177.         idxs[i] = ids.create(is.create(X.getMiddle().getElement(i + 1)), is.create(element.createUnit()));
  178.       }

  179.       // f(xs)とdf(xs)とヤコビ行列を求める
  180.       List<CIM> values = nee.getValues(idxs);
  181.       CM y_dx = values.get(2).getMiddle();
  182.       // apporoximate inver of IntervalDerivativeFunctionEvaluation
  183.       CIM R = im.create(y_dx.inverse());
  184.       // initialization of interval iteration
  185.       CIM Z = R.unaryMinus().multiply(values.get(0));
  186.       CIM Y = X.subtract(im.create(X.getMiddle()));

  187.       CIDS[] idX = ids.createArray(X.getRowSize());
  188.       for (int i = 0; i < X.getRowSize(); i++) {
  189.         idX[i] = ids. create(X.getElement(i + 1),  is.create(element.createUnit()));
  190.       }

  191.       values = nee.getValues(idX);
  192.       // ヤコビ行列 f'(X)
  193.       CIM Iy_dx = values.get(2);
  194.       int n = X.getRowSize();
  195.       CIM C = im.create(xs.getMiddle().createUnit(n)).subtract(R.multiply(Iy_dx));

  196.       CIM nextX = Z.add(C.multiply(Y)).add(im.create(X.getMiddle()));
  197.       ready = IntervalUtil.in0forRump(nextX, X).allTrue();

  198.       // 不動点定理によれば、元の集合を返すべき      
  199.       //      if (ready) {
  200.       //        X = (IntervalMatrix)nextX.clone();
  201.       //      }

  202.     }

  203.     //    if (ready == false) {
  204.     //      throw new IllegalArgumentException();
  205.     //    }

  206.     return X;
  207.   }

  208. //  /**
  209. //   *
  210. //   */
  211. //  public void solve() {
  212. //    if (this.initialValue != null) {
  213. //      this.solution = this.solve(this.initialValue);
  214. //    } else {
  215. //      this.solution = this.solve(this.intervalInitialValue);
  216. //    }
  217. //  }

  218. //  /**
  219. //   * 初期値を設定します。
  220. //   *
  221. //   * @param initialValue 初期値
  222. //   */
  223. //  public void setInitialValue(M initialValue) {
  224. //    this.initialValue = initialValue;
  225. //  }
  226. //
  227. //  /**
  228. //   * 初期値区間を設定します。
  229. //   *
  230. //   * @param intervalInitialValue 初期値区間
  231. //   */
  232. //  public void setIntervalInitialValue(IM intervalInitialValue) {
  233. //    this.intervalInitialValue = intervalInitialValue;
  234. //  }
  235. }