Dbalreal.java

/*
 * $Id: Dbalreal.java,v 1.20 2008/03/23 14:29:08 koga Exp $
 *
 * Copyright (C) 2004 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.scalar.DoubleNumber;
import org.mklab.nfc.svd.SingularValueDecomposition;
import org.mklab.tool.matrix.Chol;


/**
 * 離散時間系の平衡実現を求めるクラスです。
 * 
 * <p>Discrete-time balanced realization
 * 
 * @author koga
 * @version $Revision: 1.20 $
 * @see org.mklab.tool.control.Balreal
 * @see org.mklab.tool.control.Minreal
 */
public class Dbalreal {

  /**
   * 与えられたシステム<code>(A,B,C)</code>の平衡実現を返します。
   * 
   * <p>グラミアンの対角成分を含むベクトル<code>G</code>と 相似変換のための行列<code>T</code>を返します。
   * 
   * @param A 元のA行列
   * @param B 元のB行列
   * @param C 元のC行列
   * @return { Ab, Bb, Cb, G, T } (平衡実現) (balanced realization)
   */
  public static List<DoubleMatrix> dbalreal(DoubleMatrix A, DoubleMatrix B, DoubleMatrix C) {
    String message;
    if ((message = Abcdchk.abcdchk(A, B, C)).length() > 0) {
      throw new IllegalArgumentException(message);
    }

    DoubleMatrix Gc = Dgramian.dgramian(A, B);
    DoubleMatrix Go = Dgramian.dgramian(A.conjugateTranspose(), C.conjugateTranspose());
    DoubleMatrix R = Chol.chol(Gc);

    SingularValueDecomposition<DoubleNumber,DoubleMatrix> tmp = R.multiply(Go).multiply(R.conjugateTranspose()).singularValueDecompose();
    DoubleMatrix U = tmp.getU();
    DoubleMatrix D = tmp.getD();
    DoubleMatrix V = tmp.getV();
    D = D.multiplyElementWise(U.conjugateTranspose().multiply(V).signumElementWise());

    DoubleNumber unit = A.getElement(1, 1);
    DoubleNumber power = unit.createUnit().divide(4).unaryMinus();

    DoubleMatrix T = R.conjugateTranspose().multiply(V).multiply(D.diagonalToVector().powerElementWise(power).vectorToDiagonal());
    DoubleMatrix Ab = T.leftDivide(A).multiply(T);
    DoubleMatrix Bb = T.leftDivide(B);
    DoubleMatrix Cb = C.multiply(T);
    DoubleMatrix G = Dgramian.dgramian(Ab, Bb).diagonalToVector().conjugateTranspose();

    return new ArrayList<>(Arrays.asList(new DoubleMatrix[] {Ab, Bb, Cb, G, T}));
    //return new MatxList(new Object[] {Ab, Bb, Cb, G, T});
  }

}