SkeletonDes2tf.java
/*
* Created on 2009/06/16
* Copyright (C) 2009 Koga Laboratory. All rights reserved.
*
*/
package org.mklab.tool.control;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.matrix.IntMatrix;
import org.mklab.nfc.scalar.DoubleNumber;
import org.mklab.nfc.scalar.DoubleNumberUtil;
import org.mklab.nfc.svd.SingularValueDecomposition;
import org.mklab.tool.matrix.Diag;
/**
* @author Anan
*
*/
public class SkeletonDes2tf {
/**
* @param A ゲイン行列
* @param B 入力行列
* @param C 出力行列
* @param D ゲイン行列
* @param E ディスクリプター行列
* @return {分子, 分母}
*/
public static List<DoubleMatrix> des2tf(final DoubleMatrix A, final DoubleMatrix B, final DoubleMatrix C, final DoubleMatrix D, final DoubleMatrix E) {
System.out.println("This algorithm that calculate descriptor to transfer function is defectiveness"); //$NON-NLS-1$
final SingularValueDecomposition<DoubleNumber,DoubleMatrix> udv = E.singularValueDecompose();
final DoubleMatrix u = udv.getU();
//final DoubleMatrix d = udv.getD();
final DoubleMatrix v = udv.getV();
final int rank = E.rank();
final DoubleMatrix d11 = E.singularValue().getSubVector(1, rank).inverseElementWise().vectorToDiagonal();
final int size = E.getRowSize() - rank;
final DoubleMatrix d22 = DoubleMatrix.unit(size);
final DoubleMatrix dDager = Diag.diag(d11, d22);
final DoubleMatrix E2 = dDager.multiply(u.transpose()).multiply(E).multiply(v);
final DoubleMatrix A2 = dDager.multiply(u.transpose()).multiply(A).multiply(v);
final DoubleMatrix B2 = dDager.multiply(u.transpose().multiply(B));
final DoubleMatrix C2 = C.multiply(v);
// u.multiply(d).multiply(v.transpose()).print("U*D*V'"); //$NON-NLS-1$
//
// dDager.print("Ddager"); //$NON-NLS-1$
// E2.print("Ddager*U'*E*V"); //$NON-NLS-1$
// A2.print("Ddager*U'*A*V"); //$NON-NLS-1$
// B2.print("Ddager*U'*B"); //$NON-NLS-1$
// C2.print("C*V"); //$NON-NLS-1$
final List<DoubleMatrix> controlableABCD = Canon.canon(A2, B2, C2, D.createZero(1), "controllable"); //$NON-NLS-1$
final DoubleMatrix Ab = controlableABCD.get(0);
final DoubleMatrix Bb = controlableABCD.get(1);
final DoubleMatrix Cb = controlableABCD.get(2);
final DoubleMatrix Db = controlableABCD.get(3);
final DoubleMatrix T = controlableABCD.get(4);
final DoubleMatrix Eb = T.inverse().multiply(E2).multiply(T);
final DoubleMatrix reversDenominator = Ab.getRowVector(Ab.getRowSize()).unaryMinus();
final DoubleMatrix fullDenominator = reversDenominator.flipLeftRight();
final DoubleMatrix denominator = stripLeadingZeros(fullDenominator, "denominator"); //$NON-NLS-1$
final DoubleMatrix reversNumerator = Cb.getRowVector(Cb.getRowSize());
final DoubleMatrix fullNumerator = (reversNumerator.add(D.multiply(reversDenominator).resize(reversNumerator.getRowSize(), reversNumerator.getColumnSize()))).flipLeftRight();
final DoubleMatrix numerator = stripLeadingZeros(fullNumerator, "numerator"); //$NON-NLS-1$
// denominator.resize(numerator.getRowSize(), numerator.getColumnSize()).print();
boolean debugFlag = false;
if (debugFlag == true) {
Ab.print("Ab"); //$NON-NLS-1$
Bb.print("Bb"); //$NON-NLS-1$
Cb.print("Cb"); //$NON-NLS-1$
Db.print("Db"); //$NON-NLS-1$
T.print("T"); //$NON-NLS-1$
Eb.print("Eb"); //$NON-NLS-1$
T.print("T"); //$NON-NLS-1$
}
// numerator.print("numerator");
// denominator.print("denominator");
DoubleMatrix Ti = T.inverse();
if (debugFlag == true) Ti.print("T~"); //$NON-NLS-1$
DoubleMatrix ta = T.getSubMatrix(1, rank, 1, rank);
DoubleMatrix tb = T.getSubMatrix(1, rank, rank + 1, T.getColumnSize());
DoubleMatrix tc = T.getSubMatrix(rank + 1, T.getRowSize(), 1, rank);
DoubleMatrix tA = Ti.getSubMatrix(1, rank, 1, rank);
DoubleMatrix tB = Ti.getSubMatrix(1, rank, rank + 1, T.getColumnSize());
DoubleMatrix tC = Ti.getSubMatrix(rank + 1, T.getRowSize(), 1, rank);
if (debugFlag == true) {
ta.print("a"); //$NON-NLS-1$
tb.print("b"); //$NON-NLS-1$
tc.print("c"); //$NON-NLS-1$
tA.print("A"); //$NON-NLS-1$
tB.print("B"); //$NON-NLS-1$
tC.print("C"); //$NON-NLS-1$
Ti.multiply(E2).multiply(T).print("T~*E*T"); //$NON-NLS-1$
Eb.roundToZeroElementWise(DoubleNumberUtil.EPS).print("Eb"); //$NON-NLS-1$
tA.multiply(ta).print();
tA.multiply(tb).print();
tC.multiply(ta).print();
tC.multiply(tb).print();
tA.roundToZeroElementWise(DoubleNumberUtil.EPS).print();
Eb.roundToZeroElementWise(DoubleNumberUtil.EPS).print();
}
DoubleMatrix Esb = Eb.getSubMatrix(1, rank, rank + 1, Eb.getColumnSize());
DoubleMatrix tE = Eb.createUnit();
tE.setSubMatrix(1, rank, rank + 1, Eb.getColumnSize(), Esb.unaryMinus());
if (debugFlag == true) {
tE.print();
Eb.multiply(tE).print();
Ab.multiply(tE).print();
Cb.multiply(tE).print();
}
return new ArrayList<>(Arrays.asList(new DoubleMatrix[] {numerator, denominator}));
}
/**
* 与えられたベクトルの次数を適当に下げます.
*
* @param fullMatrix full matrix
*
* @param identifier 分子ならば"numerator",分母ならば"denominator"
* @return 適当に次数を下げられたベクトル
*/
private static DoubleMatrix stripLeadingZeros(final DoubleMatrix fullMatrix, final String identifier) {
final IntMatrix idx = fullMatrix.compareElementWise(".!=", 0).find(); //$NON-NLS-1$
if (idx.length() > 0) {
return fullMatrix.getSubVector(idx.getIntElement(1), fullMatrix.length());
}
if (identifier.equals("numerator")) return fullMatrix.createOnes(1); //$NON-NLS-1$
if (identifier.equals("denominator")) return fullMatrix.createZero(1); //$NON-NLS-1$
throw new RuntimeException("分子ならば\"numerator\",分母ならば\"denominator\"を指定してください"); //$NON-NLS-1$
}
/**
* @param a ゲイン行列
* @param b 入力行列
* @param c 出力行列
* @param d ゲイン行列
* @param e ディスクリプター行列
* @param simplify 単純化するならばtrue
* @return {numerator, denominator}
*/
public static List<DoubleMatrix> des2tf(DoubleMatrix a, DoubleMatrix b, DoubleMatrix c, DoubleMatrix d, DoubleMatrix e, boolean simplify) {
if ((d.getRowSize() != 1 || d.getColumnSize() != 1) && simplify) {
throw new RuntimeException("現在、単純化はSISOシステムのみに対応しています."); //$NON-NLS-1$
}
return des2tf(a, b, c, d, e);
}
}