NodeIdentityFunctionEquation.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.ArrayList;
import java.util.List;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.nleq.NonLinearFunction;
import org.mklab.nfc.ode.SolverStopException;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.tool.control.system.BlockSystem;
import org.mklab.tool.control.system.SystemOperator;
/**
* 値が決定されていないノードの値を計算するための「x = f(x)」を満たす恒等関数を表すクラスです。
*
* @author koga
* @version $Revision: 1.6 $
* @param <RS> type of real scalar
* @param <RM> type of real matrix
* @param <CS> type of complex scalar
* @param <CM> type of complex matrix
*/
public class NodeIdentityFunctionEquation<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>> implements NonLinearFunction<RS,RM> {
/** 隣接行列 */
protected SystemOperator<RS,RM,CS,CM>[][] matrix;
/** ノードの仮の値 */
protected List<RM> nodeTmpValue;
/** 各ループ内で最も次数の小さなノードの番号のリスト(ノード番号は1から始まる) */
protected List<Integer> minimumNode;
/** ノードの数 */
protected int nodeSize;
/** ブロックシステム */
protected BlockSystem<RS,RM,CS,CM> blockSystem;
/** unit of scalar */
private RS sunit;
/**
* 新しく生成された<code>NodeEquation</code>オブジェクトを初期化します。
*
* @param blockSystem ブロックシステム
* @param matrix 隣接行列
* @param nodeTmpValue ノードの仮の値
* @param minimumNode 各ループ内で最も次数の小さなノードの番号のリスト
*/
public NodeIdentityFunctionEquation(final BlockSystem<RS,RM,CS,CM> blockSystem, final SystemOperator<RS,RM,CS,CM>[][] matrix, final List<RM> nodeTmpValue, final List<Integer> minimumNode) {
this.blockSystem = blockSystem;
this.nodeSize = nodeTmpValue.size();
this.matrix = matrix;
this.nodeTmpValue = nodeTmpValue;
this.minimumNode = minimumNode;
this.sunit = nodeTmpValue.get(0).getElement(1,1).createUnit();
}
/**
* @see org.mklab.nfc.nleq.NonLinearFunction#eval(org.mklab.nfc.matrix.NumericalMatrix)
*/
public RM eval(final RM x) throws SolverStopException {
ArrayList<RM> xx = new ArrayList<>(this.nodeSize);
// 次数最小ノードの値を1個のベクトルから分離します。
int offset = 0;
for (int i : this.minimumNode) {
int n = this.nodeTmpValue.get(i - 1).length();
xx.set(i - 1, x.getSubVector(offset + 1, offset + n));
offset = offset + n;
}
List<RM> nodeValue = new ArrayList<>(this.nodeSize);
SystemOperator<RS,RM,CS,CM>[][] matrixLocal = new SystemOperator[this.nodeSize][this.nodeSize];
List<RM> nodeTmpValueLocal = new ArrayList<>(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.set(row, this.nodeTmpValue.get(row));
}
// 与えられた次数最小ノードの値を用いて、自身を含む各ノードの値を計算します。
calcNonMinimumNodeValues(nodeValue, xx, matrixLocal, nodeTmpValueLocal);
// 次数最小ノードの値を1個のベクトルに結合します。
RM newX = this.sunit.createZeroGrid(0, 1);
for (int i : this.minimumNode) {
newX = newX.appendDown(nodeValue.get(i - 1));
}
return newX;
}
/**
* 与えられた次数最小ノードの値から他のノードの値を計算します。
*
* @param nodeValue ノードの値
* @param xx 次数最小ノードの値の配列
* @param matrixLocal 隣接行列
* @param nodeTmpValueLocal ノードの仮の値
* @exception SolverStopException ソルバーが停止された場合
*/
protected void calcNonMinimumNodeValues(final List<RM> nodeValue, final List<RM> xx, final SystemOperator<RS,RM,CS,CM>[][] matrixLocal, final List<RM> nodeTmpValueLocal) throws SolverStopException {
for (int i : this.minimumNode) {
nodeValue.set(i - 1, xx.get(i - 1));
}
while (this.blockSystem.calcOutputOfDirectFeedthroughSystem(matrixLocal, nodeValue, nodeTmpValueLocal, false)) {
this.blockSystem.setNodeValueOfNoInputNode(matrixLocal, nodeValue, nodeTmpValueLocal, false);
}
}
}