AbstractLinearSystem.java
/*
* Created on 2009/06/18
* Copyright (C) 2009 Koga Laboratory. All rights reserved.
*
*/
package org.mklab.tool.control;
import java.io.CharArrayWriter;
import java.io.Serializable;
import java.util.List;
import org.mklab.nfc.matrix.AnyRealRationalPolynomialMatrix;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.IntMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.tool.matrix.Diag;
import org.mklab.tool.matrix.Simplify;
/**
* 線形システムの抽象クラスです。
*
* @author Anan
* @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 abstract class AbstractLinearSystem<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 Serializable, Cloneable, LinearSystem<RS,RM,CS,CM> {
/** バージョン番号 */
private static final long serialVersionUID = -7441324992413004621L;
/** プロパーならばtrue */
protected boolean proper = true;
/** 厳密にプロバーならばtrue */
protected boolean strictlyProper = true;
/** 伝達関数行列 */
//protected AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> G = null;
protected AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> G = null;
/** 時間領域でのシステムの種類 */
protected TimeDomainType timeDomainType = TimeDomainType.CONTINUOUS;
/** 入力数 */
protected int inputSize;
/** 状態数 */
protected int stateSize;
/** 出力数 */
protected int outputSize;
/** システム行列 */
protected RM a = null;
/** 入力行列 */
protected RM b = null;
/** 出力行列 */
protected RM c = null;
/** ゲイン行列 */
protected RM d = null;
/** E行列 */
protected RM e = null;
/** 指数 */
protected IntMatrix index = null;
/** システム行列の式 */
private String[][] aSymbol;
/** 入力行列の式 */
private String[][] bSymbol;
/** 出力行列の式 */
private String[][] cSymbol;
/** ゲイン行列の式 */
private String[][] dSymbol;
/** ディスクリプタ行列の式 */
private String[][] eSymbol;
/** 入力ポートのタグ */
protected List<String> inputPortTags;
/** 出力ポートのタグ */
protected List<String> outputPortTags;
/** 状態のタグ */
private List<String> stateTags;
/**
* 2個のシステムが等しいか判定します。
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object opponent) {
if (this == opponent) {
return true;
}
if (opponent == null) {
return false;
}
if (opponent.getClass() != getClass()) {
return false;
}
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g1 = getTransferFunctionMatrix();
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g2 = ((LinearSystem<RS,RM,CS,CM>)opponent).getTransferFunctionMatrix();
return g1.equals(g2);
}
/**
* 2個のシステムが等しいか判定します。
*
* @param opponent 対象となる線形システム
* @param tolerance 許容誤差
* @return 2個のシステムが等しいければtrue、そうでなければfalse
*/
public boolean equals(final Object opponent, final double tolerance) {
if (this == opponent) {
return true;
}
if (opponent == null) {
return false;
}
if (opponent.getClass() != getClass()) {
return false;
}
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g1 = getTransferFunctionMatrix();
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g2 = ((ProperLinearSystem<RS,RM,CS,CM>)opponent).getTransferFunctionMatrix();
return g1.equals(g2, tolerance);
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int hashCode = 1;
hashCode = 31 * hashCode + (int)(+serialVersionUID ^ (serialVersionUID >>> 32));
hashCode = 31 * hashCode + (this.proper ? 1231 : 1237);
hashCode = 31 * hashCode + (this.strictlyProper ? 1231 : 1237);
hashCode = 31 * hashCode + (this.G == null ? 0 : this.G.hashCode());
hashCode = 31 * hashCode + this.inputSize;
hashCode = 31 * hashCode + this.stateSize;
hashCode = 31 * hashCode + this.outputSize;
hashCode = 31 * hashCode + (this.a == null ? 0 : this.a.hashCode());
hashCode = 31 * hashCode + (this.b == null ? 0 : this.b.hashCode());
hashCode = 31 * hashCode + (this.c == null ? 0 : this.c.hashCode());
hashCode = 31 * hashCode + (this.d == null ? 0 : this.d.hashCode());
hashCode = 31 * hashCode + (this.inputPortTags == null ? 0 : this.inputPortTags.hashCode());
hashCode = 31 * hashCode + (this.outputPortTags == null ? 0 : this.outputPortTags.hashCode());
return hashCode;
}
/**
* 行番号を1からに設定します。
*
* @param matrix 行列の文字列
*/
protected void resetRowNumber(final String[] matrix) {
for (int i = 1; i < matrix.length; i++) {
matrix[i] = matrix[i].replaceFirst("\\(\\s*\\d+\\)", String.format("(% 3d)", Integer.valueOf(i))); //$NON-NLS-1$//$NON-NLS-2$
}
}
/**
* フォーマットされた状態のタグを返します。
*
* @return フォーマットされた状態のタグ
*/
protected String[] getSymbolicState() {
final int stateLength = getSymbolicStateLength();
final int outputLength = getSymbolicOutputLength();
final int length = Math.max(stateLength, outputLength);
final String[] symbolicStates = new String[getSubSystemSize()];
for (int i = 0; i < getSubSystemSize(); i++) {
final String stateTag = this.stateTags.get(i);
final String format = "%" + length + "s"; //$NON-NLS-1$ //$NON-NLS-2$
symbolicStates[i] = String.format(format, stateTag);
}
return symbolicStates;
}
/**
* フォーマットされた出力のタグを返します。
*
* @return フォーマットされた出力のタグ
*/
protected String[] getSymbolicOutput() {
final int stateLength = getSymbolicStateLength();
final int outputLength = getSymbolicOutputLength();
final int length = Math.max(stateLength, outputLength);
final String[] symbolicOutputs = new String[this.outputPortTags.size()];
for (int i = 0; i < this.outputPortTags.size(); i++) {
final String outputPortaTag = this.outputPortTags.get(i);
final String format = "%" + length + "s"; //$NON-NLS-1$ //$NON-NLS-2$
symbolicOutputs[i] = String.format(format, outputPortaTag);
}
return symbolicOutputs;
}
/**
* フォーマットされた入力のタグを返します。
*
* @return フォーマットされた入力のタグ
*/
protected String[] getSymbolicInput() {
final int stateLength = getSymbolicStateLength();
final int inputLength = getSymbolicInputLength();
final int length = Math.max(stateLength, inputLength);
final String[] symbolicInputs = new String[this.inputPortTags.size()];
for (int i = 0; i < this.inputPortTags.size(); i++) {
final String inputPortaTag = this.inputPortTags.get(i);
final String format = "%" + length + "s"; //$NON-NLS-1$ //$NON-NLS-2$
symbolicInputs[i] = String.format(format, inputPortaTag);
}
return symbolicInputs;
}
/**
* 状態のタグの最大長を返します。
*
* @return 状態のタグの最大長
*/
private int getSymbolicStateLength() {
int stateLength = 0;
for (final String stateTag : this.stateTags) {
if (stateLength < stateTag.length()) {
stateLength = stateTag.length();
}
}
return stateLength;
}
/**
* 入力ポートのタグの最大長を返します。
*
* @return 入力ポートのタグの最大長
*/
private int getSymbolicInputLength() {
int inputLength = 0;
for (final String inputPortTag : this.inputPortTags) {
if (inputLength < inputPortTag.length()) {
inputLength = inputPortTag.length();
}
}
return inputLength;
}
/**
* 出力ポートのタグの最大長を返します。
*
* @return 出力ポートのタグの最大長
*/
private int getSymbolicOutputLength() {
int outputLength = 0;
for (final String outputPortTag : this.outputPortTags) {
if (outputLength < outputPortTag.length()) {
outputLength = outputPortTag.length();
}
}
return outputLength;
}
/**
* Aの数式を返します。
*
* @return Aの数式
*/
public String getSymbolicA() {
final StringBuffer string = new StringBuffer();
final int[] columnLengthes = getColumnLengthesOfABCD();
for (int row = 0; row < getSubSystemSize(); row++) {
for (int column = 0; column < getSubSystemSize(); column++) {
final String format = "%" + columnLengthes[column] + "s"; //$NON-NLS-1$ //$NON-NLS-2$
string.append(String.format(format, this.aSymbol[row][column]));
if (column != getSubSystemSize() - 1) {
string.append(" "); //$NON-NLS-1$
}
}
string.append(System.getProperty("line.separator")); //$NON-NLS-1$
}
return string.toString();
}
/**
* Bの数式を返します。
*
* @return Bの数式
*/
public String getSymbolicB() {
final StringBuffer string = new StringBuffer();
final int[] columnLengthes = getColumnLengthesOfABCD();
for (int row = 0; row < getSubSystemSize(); row++) {
for (int column = 0; column < getInputPortSize(); column++) {
final String format = "%" + columnLengthes[column + getSubSystemSize()] + "s"; //$NON-NLS-1$ //$NON-NLS-2$
string.append(String.format(format, this.bSymbol[row][column]));
if (column != getInputSize() - 1) {
string.append(" "); //$NON-NLS-1$
}
}
string.append(System.getProperty("line.separator")); //$NON-NLS-1$
}
return string.toString();
}
/**
* Cの数式を返します。
*
* @return Cの数式
*/
public String getSymbolicC() {
final StringBuffer string = new StringBuffer();
final int[] columnLengthes = getColumnLengthesOfABCD();
for (int row = 0; row < getOutputPortSize(); row++) {
for (int column = 0; column < getSubSystemSize(); column++) {
final String format = "%" + columnLengthes[column] + "s"; //$NON-NLS-1$ //$NON-NLS-2$
string.append(String.format(format, this.cSymbol[row][column]));
if (column != getSubSystemSize() - 1) {
string.append(" "); //$NON-NLS-1$
}
}
string.append(System.getProperty("line.separator")); //$NON-NLS-1$
}
return string.toString();
}
/**
* Dの数式を返します。
*
* @return Dの数式
*/
public String getSymbolicD() {
final StringBuffer string = new StringBuffer();
final int[] columnLengthes = getColumnLengthesOfABCD();
for (int row = 0; row < getOutputPortSize(); row++) {
for (int column = 0; column < getInputPortSize(); column++) {
final String format = "%" + columnLengthes[column + getSubSystemSize()] + "s"; //$NON-NLS-1$ //$NON-NLS-2$
string.append(String.format(format, this.dSymbol[row][column]));
if (column != getInputPortSize() - 1) {
string.append(" "); //$NON-NLS-1$
}
}
string.append(System.getProperty("line.separator")); //$NON-NLS-1$
}
return string.toString();
}
/**
* Eの数式を返します。
*
* @return Eの数式
*/
public String getSymbolicE() {
final StringBuffer string = new StringBuffer();
final int[] columnLengthes = getColumnLengthesOfABCD();
for (int row = 0; row < getSubSystemSize(); row++) {
for (int column = 0; column < getSubSystemSize(); column++) {
final String format = "%" + columnLengthes[column] + "s"; //$NON-NLS-1$ //$NON-NLS-2$
string.append(String.format(format, this.eSymbol[row][column]));
if (column != getSubSystemSize() - 1) {
string.append(" "); //$NON-NLS-1$
}
}
string.append(System.getProperty("line.separator")); //$NON-NLS-1$
}
return string.toString();
}
/**
* 上部と下部を分割する水平線を描きます。
*
* @param string 生成する文字列
* @param columnLengthes 各列の文字列の長さ
*/
protected void drawHorizontalLine(final StringBuffer string, final int[] columnLengthes) {
int firstLength = 0;
for (int i = 0; i < getSubSystemSize(); i++) {
firstLength += columnLengthes[i];
if (i != getSubSystemSize() - 1) {
firstLength += 2;
}
}
int secondLength = 0;
for (int i = 0; i < getInputPortSize(); i++) {
secondLength += columnLengthes[i + getSubSystemSize()];
if (i != getInputPortSize() - 1) {
secondLength += 2;
}
}
for (int i = 0; i < firstLength; i++) {
string.append("-"); //$NON-NLS-1$
}
string.append("+"); //$NON-NLS-1$
for (int i = 0; i < secondLength; i++) {
string.append("-"); //$NON-NLS-1$
}
}
/**
* 列毎の成分の長さの最大値を返します。
*
* @return 列毎の成分の長さの最大値
*/
protected int[] getColumnLengthesOfABCD() {
final int[] columnLengthes = new int[getSubSystemSize() + getInputPortSize()];
for (int column = 0; column < getSubSystemSize(); column++) {
final int aLength = getMaxLengthColumnWise(this.aSymbol, column);
final int cLength = getMaxLengthColumnWise(this.cSymbol, column);
columnLengthes[column] = aLength > cLength ? aLength : cLength;
}
for (int column = 0; column < getInputPortSize(); column++) {
final int bLength = getMaxLengthColumnWise(this.bSymbol, column);
final int dLength = getMaxLengthColumnWise(this.dSymbol, column);
columnLengthes[column + getSubSystemSize()] = bLength > dLength ? bLength : dLength;
}
return columnLengthes;
}
/**
* 指定された列の成分の最大の長さを返します。
*
* @param matrix 対象となる行列
* @param column 指定列
* @return 指定された列の成分の最大の長さ
*/
protected int getMaxLengthColumnWise(final String[][] matrix, final int column) {
int length = 0;
for (int row = 0; row < matrix.length; row++) {
if (matrix[row] != null && matrix[row][column] != null && matrix[row][column].length() > length) {
length = matrix[row][column].length();
}
}
return length;
}
/**
* プロパーであるか判定します。
*
* @return プロパーならばtrue、そうでなければfalse
*/
public boolean isProper() {
return this.proper;
}
/**
* 厳密にプロパーであるか判定します。
*
* @return 厳密にプロパーならばtrue、そうでなければfalse
*/
public boolean isStrictlyProper() {
return this.strictlyProper;
}
/**
* 1入力1出力(SISO)であるか判定します。
*
* @return SISO(1入力1出力)システムならばtrue、そうでなければfalse
*/
public boolean isSISO() {
return getInputSize() == 1 && getOutputSize() == 1;
}
/**
* A行列(システム行列)を返します。
*
* @return A行列(システム行列)
*/
public RM getA() {
return this.a;
}
/**
* B行列(入力行列)を返します。
*
* @return B行列(入力行列)
*/
public RM getB() {
return this.b;
}
/**
* C行列(出力行列)を返します。
*
* @return C行列(出力行列)
*/
public RM getC() {
return this.c;
}
/**
* E行列(ディスクリプタ行列)を返します。
*
* @return the e
*/
public RM getE() {
return this.e;
}
/**
* D行列(ゲイン行列)を返します。
*
* @return D行列(ゲイン行列)
*/
public RM getD() {
return this.d;
}
/**
* 状態の数を返します。
*
* @return 状態の数
*/
public int getStateSize() {
return this.stateSize;
}
/**
* 入力の数を返します。
*
* @return 入力の数
*/
public int getInputSize() {
return this.inputSize;
}
/**
* 出力の数を返します。
*
* @return 出力の数
*/
public int getOutputSize() {
return this.outputSize;
}
/**
* システムの伝達関数行列を返します。
*
* <p>生成されるシステムを簡単化します。
*
* @return 伝達関数行列
*/
public AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> getTransferFunctionMatrix() {
return getTransferFunctionMatrix(true);
}
/**
* システム<code>opponent</code>との和(並列結合)でできるシステムを返します。
*
* <p>結合システムは簡単化されます。
*
* @param opponent 結合する(加えられる)システム
* @return システム<code>opponent</code>との和(並列結合)でできるシステム
*/
public LinearSystem<RS,RM,CS,CM> add(final LinearSystem<RS,RM,CS,CM> opponent) {
return add(opponent, true);
}
/**
* システム<code>opponent</code>との和(並列結合)でできるシステムを返します。
*
* @param opponent 結合する(加えられる)システム
* @param simplify 簡単化するならばtrue、そうでなければfalse
* @return システム<code>opponent</code>との和(並列結合)でできるシステム
*/
public LinearSystem<RS,RM,CS,CM> add(final LinearSystem<RS,RM,CS,CM> opponent, final boolean simplify) {
if (isProper() && opponent.isProper()) {
RM ansA = Diag.diag(this.a, ((AbstractLinearSystem<RS,RM,CS,CM>)opponent).a);
RM ansB = this.b.appendDown(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).b);
RM ansC = this.c.appendRight(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).c);
RM ansD = this.d.add(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).d);
if (simplify) {
List<RM> abcd = Minreal.minreal(ansA, ansB, ansC, ansD);
ansA = abcd.get(0);
ansB = abcd.get(1);
ansC = abcd.get(2);
ansD = abcd.get(3);
}
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG;
if (isProper()) {
ansG = getTransferFunctionMatrix(simplify).add(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G);
} else if (opponent.isProper()) {
ansG = this.G.add(opponent.getTransferFunctionMatrix(simplify));
} else {
ansG = this.G.add(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G);
}
if (simplify) {
ansG = Simplify.simplify(ansG);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* 定数行列<code>constantMatrix</code>を右から掛けてできるシステムを返します。
*
* @param constantMatrix 定数行列
* @return 定数行列<code>constantMatrix</code>を右から掛けてできるシステム
*/
public LinearSystem<RS,RM,CS,CM> multiply(final RM constantMatrix) {
if (isProper()) {
final RM ansB = this.b.multiply(constantMatrix);
final RM ansD = this.d.multiply(constantMatrix);
return LinearSystemFactory.createLinearSystem(this.a.createClone(), ansB, this.c.createClone(), ansD);
}
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> constantRationalPolynomialMatrix = this.G.getElement(1,1).getNumerator().createGrid(constantMatrix).toRational();
return LinearSystemFactory.createLinearSystem(this.G.multiply(constantRationalPolynomialMatrix));
}
/**
* 定数行列<code>constantMatrix</code>を左から掛けてできるシステムを返します。
*
* @param constantMatrix 定数行列
* @return 定数行列<code>constantMatrix</code>を左から掛けてできるシステム
*/
public LinearSystem<RS,RM,CS,CM> leftMultiply(final RM constantMatrix) {
if (isProper()) {
final RM ansC = constantMatrix.multiply(this.c);
final RM ansD = constantMatrix.multiply(this.d);
return LinearSystemFactory.createLinearSystem(this.a.createClone(), this.b.createClone(), ansC, ansD);
}
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> constantRationalPolynomialMatrix = this.G.getElement(1,1).getNumerator().createGrid(constantMatrix).toRational();
return LinearSystemFactory.createLinearSystem(constantRationalPolynomialMatrix.multiply(this.G));
}
/**
* システム<code>opponent</code>との積(直列結合)(右からの積)でできるシステムを返します。
*
* <p>結合システムを簡単化します。
*
* @param opponent 結合するシステム(入力側に掛けられるシステム)
* @return システム<code>opponent</code>との積(直列結合)(右からの積)でできるシステム
*/
public LinearSystem<RS,RM,CS,CM> multiply(final LinearSystem<RS,RM,CS,CM> opponent) {
return multiply(opponent, true);
}
/**
* システム<code>opponent</code>との積(直列結合)(右からの積)でできるシステムを返します。
*
* @param opponent 結合するシステム(入力側に掛けられるシステム)
* @param simplify 簡単化するならばtrue、そうでなければfalse
* @return システム<code>opponent</code>との積(直列結合)(右からの積)でできるシステム
*/
public LinearSystem<RS,RM,CS,CM> multiply(final LinearSystem<RS,RM,CS,CM> opponent, final boolean simplify) {
if (isProper() && opponent.isProper()) {
if (isSISO() && !opponent.isSISO()) {
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g1 = getTransferFunctionMatrix(simplify);
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g2 = opponent.getTransferFunctionMatrix(simplify);
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG = g2.multiply(g1.getElement(1, 1));
if (simplify) {
ansG = Simplify.simplify(ansG);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
if (!isSISO() && opponent.isSISO()) {
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g1 = getTransferFunctionMatrix(simplify);
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g2 = opponent.getTransferFunctionMatrix(simplify);
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG = g1.multiply(g2.getElement(1, 1));
if (simplify) {
ansG = Simplify.simplify(ansG);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
RM ansA = this.a.appendRight(this.b.multiply(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).c)).appendDown(
this.a.createZero(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).stateSize, this.stateSize).appendRight(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).a));
RM ansB = this.b.multiply(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).d).appendDown(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).b);
RM ansC = this.c.appendRight(this.d.multiply(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).c));
RM ansD = this.d.multiply(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).d);
if (simplify) {
List<RM> abcd = Minreal.minreal(ansA, ansB, ansC, ansD);
ansA = abcd.get(0);
ansB = abcd.get(1);
ansC = abcd.get(2);
ansD = abcd.get(3);
}
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g1, g2;
if (isProper()) {
g1 = getTransferFunctionMatrix(simplify);
g2 = ((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G;
} else if (opponent.isProper()) {
g1 = this.G;
g2 = opponent.getTransferFunctionMatrix(simplify);
} else {
g1 = this.G;
g2 = ((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G;
}
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG;
if (isSISO()) {
ansG = g2.multiply(g1.getElement(1, 1));
} else if (opponent.isSISO()) {
ansG = g1.multiply(g2.getElement(1, 1));
} else {
ansG = g1.multiply(g2);
}
if (simplify) {
ansG = Simplify.simplify(ansG);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* システム<code>opponent</code>との差(符合が異なる並列結合)でできるシステムを返します。
*
* <p>結合システムを簡単化します。
*
* @param opponent 結合するシステム(引かれるシステム)
* @return システム<code>opponent</code>との差(符合が異なる並列結合)でできるシステム
*/
public LinearSystem<RS,RM,CS,CM> subtract(final LinearSystem<RS,RM,CS,CM> opponent) {
return subtract(opponent, true);
}
/**
* システム<code>opponent</code>との差(符合が異なる並列結合)でできるシステムを返します。
*
* @param opponent 結合するシステム(引かれるシステム)
* @param simplify 簡単化するならばtrue、そうでなければfalse
* @return システム<code>opponent</code>との差(符合が異なる並列結合)でできるシステム
*/
public LinearSystem<RS,RM,CS,CM> subtract(final LinearSystem<RS,RM,CS,CM> opponent, final boolean simplify) {
if (isProper() && opponent.isProper()) {
RM ansA = Diag.diag(this.a, ((AbstractLinearSystem<RS,RM,CS,CM>)opponent).a);
RM ansB = this.b.appendDown(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).b);
RM ansC = this.c.appendRight(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).c.unaryMinus());
RM ansD = this.d.add(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).d.unaryMinus());
if (simplify) {
final List<RM> abcd = Minreal.minreal(ansA, ansB, ansC, ansD);
ansA = abcd.get(0);
ansB = abcd.get(1);
ansC = abcd.get(2);
ansD = abcd.get(3);
}
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG;
if (isProper()) {
ansG = getTransferFunctionMatrix(simplify).subtract(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G);
} else if (opponent.isProper()) {
ansG = this.G.subtract(opponent.getTransferFunctionMatrix(simplify));
} else {
ansG = this.G.subtract(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G);
}
if (simplify) {
ansG = Simplify.simplify(ansG);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* 入力または出力の符合を反転にしてできるシステムを返します。
*
* @return 入力または出力の符合を反転にしてできるシステム
*/
public LinearSystem<RS,RM,CS,CM> unaryMinus() {
if (isProper()) {
final RM ansA = this.a.createClone();
final RM ansB = this.b.unaryMinus();
final RM ansC = this.c.createClone();
final RM ansD = this.d.unaryMinus();
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
return LinearSystemFactory.createLinearSystem(this.G.unaryMinus());
}
/**
* 逆システム(入力と出力を逆にしたシステム)を返します。
*
* <p>生成されたシステムを簡単化します。
*
* @return 逆システム(入力と出力を逆にしたシステム)
*/
public LinearSystem<RS,RM,CS,CM> inverse() {
return inverse(true);
}
/**
* 逆システム(入力と出力を逆にしたシステム)を返します。
*
* @param simplify 生成されたシステムを簡単化するならばtrue、そうでなければfalse
* @return 逆システム(入力と出力を逆にしたシステム)
*
*/
public LinearSystem<RS,RM,CS,CM> inverse(final boolean simplify) {
if (isProper()) {
RM ansA = this.a.subtract(this.b.multiply(this.d.leftDivide(this.c)));
RM ansB = this.b.multiply(this.d.inverse());
RM ansC = this.d.leftDivide(this.c).unaryMinus();
RM ansD = this.d.inverse();
if (simplify) {
final List<RM> abcd = Minreal.minreal(ansA, ansB, ansC, ansD);
ansA = abcd.get(0);
ansB = abcd.get(1);
ansC = abcd.get(2);
ansD = abcd.get(3);
}
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG = this.G.inverse();
if (simplify) {
ansG = Simplify.simplify(ansG);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* 転置してできるシステムを返します。
*
* @return 転置してできるシステム
*/
public LinearSystem<RS,RM,CS,CM> transpose() {
if (isProper()) {
final RM ansA = this.a.transpose();
final RM ansB = this.c.transpose();
final RM ansC = this.b.transpose();
final RM ansD = this.d.transpose();
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
return LinearSystemFactory.createLinearSystem(this.G.transpose());
}
/**
* 複素共役転置してできるシステムを返します。
*
* @return 複素共役転置してできるシステム
*/
public LinearSystem<RS,RM,CS,CM> conjugateTranspose() {
if (isProper()) {
final RM ansA = this.a.conjugateTranspose();
final RM ansB = this.c.conjugateTranspose();
final RM ansC = this.b.conjugateTranspose();
final RM ansD = this.d.conjugateTranspose();
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
return LinearSystemFactory.createLinearSystem(this.G.conjugateTranspose());
}
/**
* システム<code>feedbackElement</code>をフィードバック結合(負帰還)してできるシステムを返します。
*
* <p>生成されるシステムを簡単化します。
*
* @param feedbackElement フィードバック結合するシステム
* @return システム<code>feedbackElement</code>をフィードバック結合(負帰還)してできるシステム
*
* <p>feedback-connected system
*/
public LinearSystem<RS,RM,CS,CM> feedback(final LinearSystem<RS,RM,CS,CM> feedbackElement) {
return feedback(feedbackElement, true, true);
}
/**
* システム<code>feedbackElement</code>をフィードバック結合してできるシステムを返します。
*
* <p>生成されるシステムを簡単化します。
*
* @param feedbackElement フィードバック要素
* @param negative ネガティブフィードバックならばtrue、そうでなければfalse
* @return システム<code>feedbackElement</code>をフィードバック結合(負帰還)してできるシステム
*/
public LinearSystem<RS,RM,CS,CM> feedback(final LinearSystem<RS,RM,CS,CM> feedbackElement, final boolean negative) {
return feedback(feedbackElement, negative, true);
}
/**
* システムfeedbackElementをフィードバック結合してできるシステムを返します。
*
* @param feedbackElement フィードバック要素
* @param negative ネガティブフィードバックならばtrue、そうでなければfalse
* @param simplify 生成されたシステムを簡単化するならばtrue、そうでなければfalse
* @return フィードバック結合してできるシステム
*/
public LinearSystem<RS,RM,CS,CM> feedback(final LinearSystem<RS,RM,CS,CM> feedbackElement, final boolean negative, final boolean simplify) {
if (isProper() && feedbackElement.isProper()) {
RM ansA, ansB, ansC, ansD;
if (negative) {
// T1 = I + D2*D1
// T2 = I + D1*D2
final RM T1 = this.d.createUnit(this.outputSize).add(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).d.multiply(this.d));
final RM T2 = this.d.createUnit(this.outputSize).add(this.d.multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).d));
if (T1.isFullRank() == false) {
throw new RuntimeException(Messages.getString("LinearSystem.27")); //$NON-NLS-1$
}
if (T2.isFullRank() == false) {
throw new RuntimeException(Messages.getString("LinearSystem.28")); //$NON-NLS-1$
}
// A = [[A1-B1/T1*D2*C1 -B1/T1*C2 ]
// [ B2/T2*C1 A2-B2/T2*D1*C2]];
final RM a11 = this.a.subtract(this.b.divide(T1).multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).d).multiply(this.c));
final RM a12 = this.b.divide(T1).multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).c).unaryMinus();
final RM a21 = ((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).b.divide(T2).multiply(this.c);
final RM a22 = ((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).a
.subtract(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).b.divide(T2).multiply(this.d).multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).c));
ansA = a11.appendRight(a12).appendDown(a21.appendRight(a22));
// B = [[ B1/T1 ]
// [B2/T2*D1]];
final RM b1 = this.b.divide(T1);
final RM b2 = ((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).b.divide(T2).multiply(this.d);
ansB = b1.appendDown(b2);
// [T2\C1, -T2\D1*C2];
ansC = T2.leftDivide(this.c).appendRight(T2.leftDivide(this.d).multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).c).unaryMinus());
// [T2\D1]
ansD = T2.leftDivide(this.d);
} else {
// T1 = I - D2*D1
// T2 = I - D1*D2
final RM T1 = this.d.createUnit(this.outputSize).subtract(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).d.multiply(this.d));
final RM T2 = this.d.createUnit(this.outputSize).subtract(this.d.multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).d));
if (T1.isFullRank() == false) {
throw new RuntimeException(Messages.getString("LinearSystem.29")); //$NON-NLS-1$
}
if (T2.isFullRank() == false) {
throw new RuntimeException(Messages.getString("LinearSystem.30")); //$NON-NLS-1$
}
// A = [[A1+B1/T1*D2*C1 B1/T1*C2 ]
// [ B2/T2*C1 A2+B2/T2*D1*C2]];
final RM a11 = this.a.add(this.b.divide(T1).multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).d).multiply(this.c));
final RM a12 = this.b.divide(T1).multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).c);
final RM a21 = ((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).b.divide(T2).multiply(this.c);
final RM a22 = ((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).a.add(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).b.divide(T2).multiply(this.d).multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).c));
ansA = a11.appendRight(a12).appendDown(a21.appendRight(a22));
// B = [[ B1/T1 ]
// [B2/T2*D1]];
final RM b1 = this.b.divide(T1);
final RM b2 = ((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).b.divide(T2).multiply(this.d);
ansB = b1.appendDown(b2);
// [T2\C1, T2\D1*C2];
ansC = T2.leftDivide(this.c).appendRight(T2.leftDivide(this.d).multiply(((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).c));
// [T2\D1]
ansD = T2.leftDivide(this.d);
}
if (simplify) {
final List<RM> abcd = Minreal.minreal(ansA, ansB, ansC, ansD);
ansA = abcd.get(0);
ansB = abcd.get(1);
ansC = abcd.get(2);
ansD = abcd.get(3);
}
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g1, g2;
if (isProper()) {
g1 = getTransferFunctionMatrix(simplify);
g2 = ((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).G;
} else if (feedbackElement.isProper()) {
g1 = this.G;
g2 = feedbackElement.getTransferFunctionMatrix(simplify);
} else {
g1 = this.G;
g2 = ((AbstractLinearSystem<RS,RM,CS,CM>)feedbackElement).G;
}
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> g1g2 = g1.multiply(g2);
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG;
if (negative) {
ansG = g1g2.createUnit(g1g2.getRowSize()).add(g1g2).inverse().multiply(g1);
} else {
ansG = g1g2.createUnit(g1g2.getRowSize()).subtract(g1g2).inverse().multiply(g1);
}
if (simplify) {
ansG = Simplify.simplify(ansG);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* 単一フィードバック(ネガティブフィードバック)してできるシステムを返します。
*
* <p>生成されるシステムを簡単化します。
*
* @return 単一フィードバック(ネガティブフィードバック)してできるシステム
*
* <p>unity feedback connected system
*/
public LinearSystem<RS,RM,CS,CM> unityFeedback() {
return unityFeedback(true, true);
}
/**
* 単一フィードバックしてできるシステムを返します。
*
* <p>生成されるシステムを簡単化します。
*
* @param negative ネガティブフィードバックならばtrue、そうでなければfalse
*
* @return フィードバック結合してできるシステム
*/
public LinearSystem<RS,RM,CS,CM> unityFeedback(final boolean negative) {
return unityFeedback(negative, true);
}
/**
* 単一フィードバックしてできるシステムを返します。
*
* @param negative ネガティブフィードバックならばtrue、そうでなければfalse
* @param simplify 生成されるシステムを簡単化するならばtrue、そうでなければfalse
* @return フィードバック結合してできるシステム
*/
public LinearSystem<RS,RM,CS,CM> unityFeedback(final boolean negative, final boolean simplify) {
if (isProper()) {
RM ansA, ansB, ansC, ansD;
if (negative) {
final RM T = this.d.createUnit(this.d.getRowSize()).add(this.d);
if (T.isFullRank() == false) {
throw new RuntimeException(Messages.getString("LinearSystem.31")); //$NON-NLS-1$
}
ansA = this.a.subtract(this.b.divide(T).multiply(this.c));
ansB = this.b.multiply(T.inverse());
ansC = this.c.subtract(this.d.divide(T).multiply(this.c));
ansD = this.d.multiply(T.inverse());
} else {
final RM T = this.d.createUnit(this.d.getRowSize()).subtract(this.d);
if (T.isFullRank() == false) {
throw new RuntimeException(Messages.getString("LinearSystem.32")); //$NON-NLS-1$
}
ansA = this.a.add(this.b.divide(T).multiply(this.c));
ansB = this.b.multiply(T.inverse());
ansC = this.c.add(this.d.divide(T).multiply(this.c));
ansD = this.d.multiply(T.inverse());
}
if (simplify) {
final List<RM> abcd = Minreal.minreal(ansA, ansB, ansC, ansD);
ansA = abcd.get(0);
ansB = abcd.get(1);
ansC = abcd.get(2);
ansD = abcd.get(3);
}
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG;
if (negative) {
ansG = this.G.createUnit(this.G.getRowSize()).add(this.G).inverse().multiply(this.G);
} else {
ansG = this.G.createUnit(this.G.getRowSize()).subtract(this.G).inverse().multiply(this.G);
}
if (simplify) {
ansG = Simplify.simplify(ansG);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* システム<code>opponent</code>を行方向に結合した(出力を加算する)システムを返します。
*
* <p>生成されるシステムを簡単化します。
*
* @param opponent 結合するシステム
* @return システム<code>opponent</code>を行方向に結合した(出力を加算する)システム
*
* <p>row-wise connected system
*/
public LinearSystem<RS,RM,CS,CM> appendRight(final LinearSystem<RS,RM,CS,CM> opponent) {
return appendRight(opponent, true);
}
/**
* システム<code>opponent</code>を行方向に結合した(出力を加算する)システムを返します。
*
* @param opponent 結合するシステム
* @param simplify 生成されるシステムを簡単化するならばtrue、そうでなければfalse
* @return システム<code>opponent</code>を行方向に結合した(出力を加算する)システム
*
* <p>row-wise connected system
*/
public LinearSystem<RS,RM,CS,CM> appendRight(final LinearSystem<RS,RM,CS,CM> opponent, final boolean simplify) {
if (isProper() && opponent.isProper()) {
RM ansA = Diag.diag(this.a, ((AbstractLinearSystem<RS,RM,CS,CM>)opponent).a);
RM ansB = Diag.diag(this.b, ((AbstractLinearSystem<RS,RM,CS,CM>)opponent).b);
RM ansC = this.c.appendRight(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).c);
RM ansD = this.d.appendRight(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).d);
if (simplify) {
final List<RM> abcd = Minreal.minreal(ansA, ansB, ansC, ansD);
ansA = abcd.get(0);
ansB = abcd.get(1);
ansC = abcd.get(2);
ansD = abcd.get(3);
}
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG;
if (this.isProper()) {
ansG = getTransferFunctionMatrix(simplify).appendRight(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G);
} else if (opponent.isProper()) {
ansG = this.G.appendRight(opponent.getTransferFunctionMatrix(simplify));
} else {
ansG = this.G.appendRight(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* システム<code>opponent</code>を列方向に結合した(同一の入力を加える)システムを返します。
*
* <p>生成されるシステムを簡単化します。
*
* @param opponent 結合するシステム
* @return システム<code>opponent</code>を列方向に結合した(同一の入力を加える)システム
*
* <p>column-wise connected system
*/
public LinearSystem<RS,RM,CS,CM> appendDown(final LinearSystem<RS,RM,CS,CM> opponent) {
return appendDown(opponent, true);
}
/**
* システム<code>opponent</code>を列方向に結合した(同一の入力を加える)システムを返します。
*
* @param opponent 結合するシステム
* @param simplify 生成されるシステムを簡単化するならばtrue、そうでなければfalse
* @return システム<code>opponent</code>を列方向に結合した(同一の入力を加える)システム
*
* <p>column-wise connected system
*/
public LinearSystem<RS,RM,CS,CM> appendDown(final LinearSystem<RS,RM,CS,CM> opponent, final boolean simplify) {
if (isProper() && opponent.isProper()) {
RM ansA = Diag.diag(this.a, ((AbstractLinearSystem<RS,RM,CS,CM>)opponent).a);
RM ansB = this.b.appendDown(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).b);
RM ansC = Diag.diag(this.c, ((AbstractLinearSystem<RS,RM,CS,CM>)opponent).c);
RM ansD = this.d.appendDown(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).d);
if (simplify) {
final List<RM> abcd = Minreal.minreal(ansA, ansB, ansC, ansD);
ansA = abcd.get(0);
ansB = abcd.get(1);
ansC = abcd.get(2);
ansD = abcd.get(3);
}
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG;
if (this.isProper()) {
ansG = getTransferFunctionMatrix(simplify).appendDown(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G);
} else if (opponent.isProper()) {
ansG = this.G.appendDown(opponent.getTransferFunctionMatrix(simplify));
} else {
ansG = this.G.appendDown(((AbstractLinearSystem<RS,RM,CS,CM>)opponent).G);
}
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* 最小実現したシステムを返します。
*
* @return 最小実現したシステム
*
* <p>minimal realization
*/
public LinearSystem<RS,RM,CS,CM> simplify() {
RS sunit = this.a.getElement(1,1).createUnit();
return simplify(sunit.create(-1));
}
// /**
// * 最小実現したシステムを返します。
// *
// * @param tolerance 許容誤差
// * @return 最小実現したシステム
// *
// * <p>minimal realization
// */
// public LinearSystem<RS,RM,CS,CM> simplify(RS tolerance) {
// return simplify(new RS(tolerance));
// }
/**
* 最小実現したシステムを返します。
*
* @param tolerance 許容誤差
* @return 最小実現したシステム
*
* <p>minimal realization
*/
public LinearSystem<RS,RM,CS,CM> simplify(RS tolerance) {
if (isProper()) {
final List<RM> abcd = Minreal.minreal(this.a, this.b, this.c, this.d, tolerance);
RM ansA = abcd.get(0);
RM ansB = abcd.get(1);
RM ansC = abcd.get(2);
RM ansD = abcd.get(3);
return LinearSystemFactory.createLinearSystem(ansA, ansB, ansC, ansD);
}
final AnyRealRationalPolynomialMatrix<RS,RM,CS,CM> ansG = Simplify.simplify(this.G);
return LinearSystemFactory.createLinearSystem(ansG);
}
/**
* 時間領域でのシステムの種類を設定します。
*
* @param type 時間領域でのシステムの種類
*/
public void setTimeDomainType(final TimeDomainType type) {
this.timeDomainType = type;
}
/**
* 時間領域でのシステムの種類を返します。
*
* @return 時間領域でのシステムの種類
*/
public TimeDomainType getTimeDomainType() {
return this.timeDomainType;
}
/**
* 連続時間システムであるか判定します。
*
* @return 連続時間システムならばtrue、そうでなければfalse
*/
public boolean isContinuous() {
return this.timeDomainType == TimeDomainType.CONTINUOUS;
}
/**
* 離散時間システムであるか判定します。
*
* @return 離散時間システムならばtrue、そうでなければfalse
*/
public boolean isDiscrete() {
return this.timeDomainType == TimeDomainType.DISCRETE;
}
/**
* サンプル値システムであるか判定します。
*
* @return サンプル値システムならばtrue、そうでなければfalse
*/
public boolean isSampled() {
return this.timeDomainType == TimeDomainType.SAMPLED;
}
/**
* 数値の出力フォーマットを設定します。
*
* @param format 数値の出力フォーマット
*/
public void setFormat(final String format) {
this.a.setElementFormat(format);
this.b.setElementFormat(format);
this.c.setElementFormat(format);
this.d.setElementFormat(format);
if (this.e != null) {
this.e.setElementFormat(format);
}
if (this.G != null) {
this.G.setElementFormat(format);
}
}
/**
* 数値の出力フォーマットを返します。
*
* @return 数値の出力フォーマット
*/
public String getFormat() {
return this.a.getElementFormat();
}
/**
* 状態空間実現の係数行列の数式を設定します。
*
* @param aSymbol A行列の数式
* @param bSymbol B行列の数式
* @param cSymbol C行列の数式
* @param dSymbol D行列の数式
* @param eSymbol E行列の数式
*/
public void setSymbolicString(final String[][] aSymbol, final String[][] bSymbol, final String[][] cSymbol, final String[][] dSymbol, final String[][] eSymbol) {
this.aSymbol = aSymbol;
this.bSymbol = bSymbol;
this.cSymbol = cSymbol;
this.dSymbol = dSymbol;
this.eSymbol = eSymbol;
}
/**
* サブシステムの数を返します。
*
* @return サブシステムの数
*/
protected int getSubSystemSize() {
return this.aSymbol.length;
}
/**
* 入力ポートの数を返します。
*
* @return 入力ポートの数
*/
protected int getInputPortSize() {
return this.bSymbol.length != 0 ? this.bSymbol[0].length : this.dSymbol[0].length;
}
/**
* 出力ポートの数を返します。
*
* @return 出力ポートの数
*/
protected int getOutputPortSize() {
return this.cSymbol.length;
}
/**
* 入力ポートのタグを返します。
*
* @return 入力ポートのタグ
*/
public List<String> getInputPortTags() {
return this.inputPortTags;
}
/**
* 入力ポートのタグを設定します。
*
* @param inputPortTags 入力ポートのタグ
*/
public void setInputPortTags(List<String> inputPortTags) {
this.inputPortTags = inputPortTags;
}
/**
* 出力ポートのタグを返します。
*
* @return 出力ポートのタグ
*/
public List<String> getOutputPortTags() {
return this.outputPortTags;
}
/**
* 出力ポートのタグを設定します。
*
* @param outputPortTags 出力ポートのタグ
*/
public void setOutputTags(List<String> outputPortTags) {
this.outputPortTags = outputPortTags;
}
/**
* 状態のタグを返します。
*
* @return 状態のタグ
*/
public List<String> getStateTags() {
return this.stateTags;
}
/**
* 状態のタグを設定します。
*
* @param stateTags 状態のタグ
*/
public void setStateTags(List<String> stateTags) {
this.stateTags = stateTags;
}
/**
* A行列の文字列をString[][]で返します。 (テストケースのための一時的なものです。)
*
* @return String[][](aSymbol)
*/
protected String[][] getSymbolicAMatrix() {
return this.aSymbol;
}
/**
* B行列の文字列をString[][]で返します。 (テストケースのための一時的なものです。)
*
* @return String[][](bSymbol)
*/
protected String[][] getSymbolicBMatrix() {
return this.bSymbol;
}
/**
* C行列の文字列をString[][]で返します。 (テストケースのための一時的なものです。)
*
* @return String[][](cSymbol)
*/
protected String[][] getSymbolicCMatrix() {
return this.cSymbol;
}
/**
* D行列の文字列をString[][]で返します。 (テストケースのための一時的なものです。)
*
* @return String[][](dSymbol)
*/
protected String[][] getSymbolicDMatrix() {
return this.dSymbol;
}
/**
* eSymbolを返します.(一時的実装)
*
* @return eSymbol
*/
protected String[][] getSymbolicEMatrix() {
return this.eSymbol;
}
/**
* @see org.mklab.nfc.matrix.GridElement#clone()
*/
@Override
abstract public Object clone();
/**
* 表示文字列を返します。
*
* @return 表示文字列
*/
public String getPrintingString() {
try (final CharArrayWriter output = new CharArrayWriter()) {
print(output);
final String printString = output.toString();
return printString;
}
}
/**
* 指数を返します。
* @return 指数
*/
public IntMatrix getIndex() {
return this.index;
}
/**
* 指数を設定します。
* @param index 指数
*/
public void setIndex(IntMatrix index) {
this.index = index;
}
}