ComplexNonlinearEquationVerifier.java
- /*
- * Created on 2004/12/02
- * Copyright (C) 2004 Koga Laboratory. All rights reserved.
- *
- */
- package org.mklab.cga.nonlinear;
- import java.util.List;
- import org.mklab.cga.derivative.IntervalDerivativeComplexMatrix;
- import org.mklab.cga.derivative.IntervalDerivativeComplexNumber;
- import org.mklab.cga.derivative.IntervalDerivativeFunction;
- import org.mklab.cga.derivative.IntervalDerivativeFunctionEvaluation;
- import org.mklab.cga.derivative.IntervalDerivativeRealMatrix;
- import org.mklab.cga.derivative.IntervalDerivativeRealNumber;
- import org.mklab.cga.interval.matrix.IntervalComplexNumericalMatrix;
- import org.mklab.cga.interval.matrix.IntervalRealNumericalMatrix;
- import org.mklab.cga.interval.scalar.IntervalComplexNumericalScalar;
- import org.mklab.cga.interval.scalar.IntervalRealNumericalScalar;
- import org.mklab.cga.util.IntervalUtil;
- import org.mklab.nfc.matrix.ComplexNumericalMatrix;
- import org.mklab.nfc.matrix.NormType;
- import org.mklab.nfc.matrix.RealNumericalMatrix;
- import org.mklab.nfc.scalar.ComplexNumericalScalar;
- import org.mklab.nfc.scalar.RealNumericalScalar;
- /**
- * 非線形方程式の精度保証を行うクラスです。
- *
- * @author hiroki
- * @version $Revision: 1.24 $.2004/12/02
- * @param <RIDS> 実区間微分スカラーの型
- * @param <RIDM> 実区間微分行列の型
- * @param <CIDS> 複素区間微分スカラーの型
- * @param <CIDM> 複素区間微分行列の型
- * @param <RIS> 実区間スカラーの型
- * @param <RIM> 実区間行列の型
- * @param <CIS> 複素区間スカラーの型
- * @param <CIM> 複素区間行列の型
- * @param <RS> 実スカラーの型
- * @param <RM> 実行列の型
- * @param <CS> 複素スカラーの型
- * @param <CM> 複素行列の型
- */
- 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>>{
- /** 関数オブジェクト */
- private IntervalDerivativeFunction<CIDS,CIDM,CIS,CIM,CS,CM> function;
- // /** 初期値 */
- // private M initialValue;
- //
- // /** 初期値区間 */
- // private IM intervalInitialValue;
- /** 非線形方程式の解 */
- private CIM solution;
- /**
- * コンストラクタ
- *
- * @param function 関数オブジェクト
- */
- public ComplexNonlinearEquationVerifier(IntervalDerivativeFunction<CIDS,CIDM,CIS,CIM,CS,CM> function) {
- this.function = function;
- }
- /**
- * 非線型方程式の解を精度保証付きで求めます。
- *
- * @param xs 初期値
- * @param idm idm
- * @return 非線形方程式の解
- */
- public CIM solve(CM xs, CIDM idm) {
- CIDS ids = idm.getElement(1,1);
- CIS is = ids.getX();
- CIM im = idm.getX();
-
- int n = xs.getRowSize();
- double sqrtN = Math.sqrt(n);
- CM xss = xs.createClone();
- CM xsold = xss;
- CS element = xs.getElement(1);
- CM dxs = xs.createZero();
- CM dxsnew = (xs).absElementWise();
- int k = 0;
- CM y_x;
- CM y_dx = null;
- CIDS[] idxss = ids.createArray(xs.getRowSize());
- IntervalDerivativeFunctionEvaluation<CIDS,CIDM,CIS,CIM,CS,CM> nee = new IntervalDerivativeFunctionEvaluation<>(this.function);
- List<CIM> value1;
- while (dxsnew.compareElementWise(".<", dxs.multiply(5)).anyTrue() //$NON-NLS-1$
- && (dxsnew).norm(NormType.TWO).isGreaterThan((xs).norm(NormType.TWO).multiply(sqrtN * 1e-14)) && k < 100 || k < 3) {
- k = k + 1;
- dxs = dxsnew.createClone();
- xsold = xss.createClone();
- for (int i = 0; i < xss.getRowSize(); i++) {
- idxss[i] = ids.create(is.create((xss).getElement(i + 1)), is.create(element.createUnit()));
- }
- value1 = nee.getValues(idxss);
- // f(x)
- y_x = value1.get(0).getMiddle();
- // ヤコビ行列
- y_dx = value1.get(2).getMiddle();
- xss = xss.subtract(y_dx.leftDivide(y_x));
- dxsnew = xss.subtract(xsold).absElementWise();
- }
- CIM ixss = im.create(xss);
- for (int i = 0; i < xss.getRowSize(); i++) {
- idxss[i] = ids.create(ixss.getElement(i + 1), is.create(element.createUnit()));
- }
- // f(xss)とdf(xss)とヤコビ行列を求める
- List<CIM> values = nee.getValues(idxss);
- // apporoximate inver of IntervalDerivativeFunctionEvaluation
- // TODO 区間にしてから、逆行列?
- CIM R = im.create(y_dx.inverse());
- // initialization of interval iteration
- // TODO 多倍長だと?
- CIM Z = R.unaryMinus().multiply(values.get(0));
- CIM X = Z.createClone();
- boolean ready = false;
- k = 0;
- CIM Y = null;
- while (ready == false && k < 10) {
- CM xRadius = X.getSupremum().subtract(X.getInfimum()).divide(2);
-
- CIM E = im.create(xRadius.multiply(element.createUnit().divide(element.createUnit().multiply(10)))).multiply(is.createInfSup(element.createUnit().unaryMinus(), element.createUnit()))
- .addElementWise(is.createInfSup(element.getMachineEpsilon().unaryMinus(), element.getMachineEpsilon()));
- k = k + 1;
- // TODO 本当はhull(X+E,0)?
- Y = X.add(E);
- CIM Yold = Y.createClone();
- for (int i = 0; i < xs.getColumnSize(); i++) {
- idxss[i] = ids.create(Y.add(im.create(xss)).getElement(i + 1), is.create(element.createUnit()));
- }
- values = nee.getValues(idxss);
- // f(xs+Y)
- // ? IntervalMatrix Iy_x = values[0];
- // ヤコビ行列
- CIM Iy_dx = values.get(2);
- CIM C = im.create(xs.createUnit(n)).subtract(R.multiply(Iy_dx));
- int i = 0;
- // improved interval iteration
- while (!ready && i < 2) {
- i = i + 1;
- X = Z.add(C.multiply(Y));
- ready = IntervalUtil.in0forRump(X, Y).allTrue();
- Y = IntervalUtil.intersect(X, Yold);
- }
- }
- if (ready) {
- X = Y.add(im.create(xss));
- } else {
- throw new IllegalArgumentException();
- // TODO 例外投げるか、NaNを返すようにする
- }
- return X;
- }
- /**
- * 非線型方程式の解を精度保証付きで求めます。
- *
- * <p>初期値区間に真の解が含まれる場合、非線形方程式の真の解を含むより小さな区間を返します。
- *
- * @param xs 初期値区間
- * @param idm idm
- * @return 非線形方程式の解
- */
- public CIM solve(CIM xs, CIDM idm) {
- CIDS ids = idm.getElement(1,1);
- CIS is = ids.getX();
- CIM im = idm.getX();
-
- IntervalDerivativeFunctionEvaluation<CIDS,CIDM,CIS,CIM,CS,CM> nee = new IntervalDerivativeFunctionEvaluation<>(this.function);
- CIM X = xs.createClone();
- CS element = (xs.getMiddle()).getElement(1);
-
- boolean ready = false;
- int k = 0;
- // TODO kの値はどれくらい?
- while (ready == false && k < 10) {
- k = k + 1;
- CIDS[] idxs = ids.createArray(X.getRowSize());
- for (int i = 0; i < X.getRowSize(); i++) {
- idxs[i] = ids.create(is.create(X.getMiddle().getElement(i + 1)), is.create(element.createUnit()));
- }
- // f(xs)とdf(xs)とヤコビ行列を求める
- List<CIM> values = nee.getValues(idxs);
- CM y_dx = values.get(2).getMiddle();
- // apporoximate inver of IntervalDerivativeFunctionEvaluation
- CIM R = im.create(y_dx.inverse());
- // initialization of interval iteration
- CIM Z = R.unaryMinus().multiply(values.get(0));
- CIM Y = X.subtract(im.create(X.getMiddle()));
- CIDS[] idX = ids.createArray(X.getRowSize());
- for (int i = 0; i < X.getRowSize(); i++) {
- idX[i] = ids. create(X.getElement(i + 1), is.create(element.createUnit()));
- }
- values = nee.getValues(idX);
- // ヤコビ行列 f'(X)
- CIM Iy_dx = values.get(2);
- int n = X.getRowSize();
- CIM C = im.create(xs.getMiddle().createUnit(n)).subtract(R.multiply(Iy_dx));
- CIM nextX = Z.add(C.multiply(Y)).add(im.create(X.getMiddle()));
- ready = IntervalUtil.in0forRump(nextX, X).allTrue();
- // 不動点定理によれば、元の集合を返すべき
- // if (ready) {
- // X = (IntervalMatrix)nextX.clone();
- // }
- }
- // if (ready == false) {
- // throw new IllegalArgumentException();
- // }
- return X;
- }
- // /**
- // *
- // */
- // public void solve() {
- // if (this.initialValue != null) {
- // this.solution = this.solve(this.initialValue);
- // } else {
- // this.solution = this.solve(this.intervalInitialValue);
- // }
- // }
- // /**
- // * 初期値を設定します。
- // *
- // * @param initialValue 初期値
- // */
- // public void setInitialValue(M initialValue) {
- // this.initialValue = initialValue;
- // }
- //
- // /**
- // * 初期値区間を設定します。
- // *
- // * @param intervalInitialValue 初期値区間
- // */
- // public void setIntervalInitialValue(IM intervalInitialValue) {
- // this.intervalInitialValue = intervalInitialValue;
- // }
- }