DoubleNodeIdentityFunctionEquation.java
/**
* $Id: NodeIdentityFunctionEquation.java,v 1.6 2008/03/12 14:38:29 koga Exp $
*
* Copyright (C) 2004-2005 Koga Laboratory. All rights reserved.
*/
package org.mklab.tool.control.system.graph;
import java.util.List;
import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.nleq.NonLinearFunction;
import org.mklab.nfc.ode.SolverStopException;
import org.mklab.nfc.scalar.DoubleNumber;
import org.mklab.tool.control.system.DoubleBlockSystem;
import org.mklab.tool.control.system.DoubleSystemOperator;
/**
* 値が決定されていないノードの値を計算するための「x = f(x)」を満たす恒等関数を表すクラスです。
*
* @author koga
* @version $Revision: 1.6 $
*/
public class DoubleNodeIdentityFunctionEquation implements NonLinearFunction<DoubleNumber,DoubleMatrix> {
/** 隣接行列 */
protected DoubleSystemOperator[][] matrix;
/** ノードの仮の値 */
protected DoubleMatrix[] nodeTmpValue;
/** 各ループ内で最も次数の小さなノードの番号のリスト(ノード番号は1から始まる) */
protected List<Integer> minimumNode;
/** ノードの数 */
protected int nodeSize;
/** ブロックシステム */
protected DoubleBlockSystem blockSystem;
/**
* 新しく生成された<code>NodeEquation</code>オブジェクトを初期化します。
*
* @param blockSystem ブロックシステム
* @param matrix 隣接行列
* @param nodeTmpValue ノードの仮の値
* @param minimumNode 各ループ内で最も次数の小さなノードの番号のリスト
*/
public DoubleNodeIdentityFunctionEquation(final DoubleBlockSystem blockSystem, final DoubleSystemOperator[][] matrix, final DoubleMatrix[] nodeTmpValue, final List<Integer> minimumNode) {
this.blockSystem = blockSystem;
this.nodeSize = nodeTmpValue.length;
this.matrix = matrix;
this.nodeTmpValue = nodeTmpValue;
this.minimumNode = minimumNode;
}
/**
* @see org.mklab.nfc.nleq.NonLinearFunction#eval(org.mklab.nfc.matrix.NumericalMatrix)
*/
public DoubleMatrix eval(final DoubleMatrix x) throws SolverStopException {
DoubleMatrix[] xx = new DoubleMatrix[this.nodeSize];
// 次数最小ノードの値を1個のベクトルから分離します。
int offset = 0;
for (int i : this.minimumNode) {
int n = this.nodeTmpValue[i - 1].length();
xx[i - 1] = x.getSubVector(offset + 1, offset + n);
offset = offset + n;
}
DoubleMatrix[] nodeValue = new DoubleMatrix[this.nodeSize];
DoubleSystemOperator[][] matrixLocal = new DoubleSystemOperator[this.nodeSize][this.nodeSize];
DoubleMatrix[] nodeTmpValueLocal = new DoubleMatrix[this.nodeSize];
for (int row = 0; row < this.nodeSize; row++) {
for (int column = 0; column < this.nodeSize; column++) {
matrixLocal[row][column] = this.matrix[row][column];
}
nodeTmpValueLocal[row] = this.nodeTmpValue[row];
}
// 与えられた次数最小ノードの値を用いて、自身を含む各ノードの値を計算します。
calcNonMinimumNodeValues(nodeValue, xx, matrixLocal, nodeTmpValueLocal);
// 次数最小ノードの値を1個のベクトルに結合します。
DoubleMatrix newX = new DoubleMatrix(0, 1);
for (int i : this.minimumNode) {
newX = newX.appendDown(nodeValue[i - 1]);
}
return newX;
}
/**
* 与えられた次数最小ノードの値から他のノードの値を計算します。
*
* @param nodeValue ノードの値
* @param xx 次数最小ノードの値の配列
* @param matrixLocal 隣接行列
* @param nodeTmpValueLocal ノードの仮の値
* @exception SolverStopException ソルバーが停止された場合
*/
protected void calcNonMinimumNodeValues(final DoubleMatrix[] nodeValue, final DoubleMatrix[] xx, final DoubleSystemOperator[][] matrixLocal, final DoubleMatrix[] nodeTmpValueLocal) throws SolverStopException {
for (int i : this.minimumNode) {
nodeValue[i - 1] = xx[i - 1];
}
while (this.blockSystem.calcOutputOfDirectFeedthroughSystem(matrixLocal, nodeValue, nodeTmpValueLocal, false)) {
this.blockSystem.setNodeValueOfNoInputNode(matrixLocal, nodeValue, nodeTmpValueLocal, false);
}
}
}