Simplify.java

/*
 * $Id: Simplify.java,v 1.23 2008/03/26 14:31:23 koga Exp $
 * 
 * Copyright (C) 2004 Koga Laboratory. All rights reserved.
 */
package org.mklab.tool.matrix;

import java.util.List;

import org.mklab.nfc.matrix.AnyRealRationalPolynomialMatrix;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.matrix.DoubleRationalPolynomialMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.AnyRealPolynomial;
import org.mklab.nfc.scalar.AnyRealRationalPolynomial;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.DoublePolynomial;
import org.mklab.nfc.scalar.DoubleRationalPolynomial;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.tool.control.Ss2tfn;
import org.mklab.tool.control.Tfm2ss;


/**
 * 有理多項式を単純化するクラスです。
 * 
 * <p>Simplify a rational polynomial matrix
 * 
 * @author koga
 * @version $Revision: 1.23 $
 * @see org.mklab.tool.control.Minreal
 */
public class Simplify {

  /**
   * メインメソッド
   * 
   * @param args コマンドライン引数
   */
  public static void main(String[] args) {
    DoublePolynomial s = new DoublePolynomial("s"); //$NON-NLS-1$
    DoubleRationalPolynomial g = new DoubleRationalPolynomial(s.add(1), s.add(1).multiply(s.add(2)));
    DoubleRationalPolynomial g2 = simplify(g);
    s.print();
    g.print();
    g2.print();
  }

  /**
   * 許容誤差 <code>tolerance</code>は、<code>minreal()</code> に渡されます。
   * 
   * @param originalSystem 元のシステム
   * @param tolerance 許容誤差
   * @return simplified rational polynomial
   */
  public static DoubleRationalPolynomial simplify(DoubleRationalPolynomial originalSystem, double tolerance) {
    DoublePolynomial n = originalSystem.getNumerator();
    DoublePolynomial d = originalSystem.getDenominator();

    if (n.getDegree() > d.getDegree()) {
      List<DoubleMatrix> tmp = Deconv.deconv(n.getCoefficients(), d.getCoefficients());
      DoubleMatrix q = tmp.get(0);
      DoubleMatrix r = tmp.get(1);
      DoubleRationalPolynomial newSystem = new DoubleRationalPolynomial(new DoublePolynomial(r), d);
      List<DoubleMatrix> tmp2 = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {newSystem})), 1, tolerance);
      /*
      if (tolerance >= 0) {
        tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {newSystem})), 1, tolerance);
      } else {
        tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {newSystem})), 1);
      }
      */

      DoubleMatrix A = tmp2.get(0);
      DoubleMatrix B = tmp2.get(1);
      DoubleMatrix C = tmp2.get(2);
      DoubleMatrix D = tmp2.get(3);

      newSystem = Ss2tfn.ss2tfn(A, B, C, D).add(new DoublePolynomial(q));
      return newSystem;
    }

    List<DoubleMatrix> tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {originalSystem})), 1, tolerance);
    /*
    if (tolerance >= 0) {
      tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {originalSystem})), 1, tolerance);
    } else {
      tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {originalSystem})), 1);
    }
    */

    DoubleMatrix A = tmp.get(0);
    DoubleMatrix B = tmp.get(1);
    DoubleMatrix C = tmp.get(2);
    DoubleMatrix D = tmp.get(3);

    DoubleRationalPolynomial newSystem = Ss2tfn.ss2tfn(A, B, C, D);
    return newSystem;
  }

  /**
   * 有理多項式 <code>g</code> を <code>minreal()</code> を用いて 簡単化します。
   * 
   * @param g 有利多項式
   * @return simplified rational polynomial
   */
  public static DoubleRationalPolynomial simplify(DoubleRationalPolynomial g) {
    double tolerance = -1.0;
    return simplify(g, tolerance);
  }

  /**
   * <code>tolerance</code>は、<code>minreal()</code> に渡されます。
   * 
   * @param G 有利多項式行列
   * @param tolerance 許容誤差
   * @return simplified matrix
   */
  public static DoubleRationalPolynomialMatrix simplify(DoubleRationalPolynomialMatrix G, double tolerance) {
    DoubleRationalPolynomialMatrix GG = new DoubleRationalPolynomialMatrix(G.getRowSize(), G.getColumnSize());

    for (int i = 1; i <= G.getRowSize(); i++) {
      for (int j = 1; j <= G.getColumnSize(); j++) {
        DoubleRationalPolynomial g = G.getElement(i, j);
        GG.setElement(i, j, simplify(g, tolerance));
        /*
        if (tolerance >= 0) {
          GG.setElement(i, j, simplify(g, tolerance));
        } else {
          GG.setElement(i, j, simplify(g));
        }
        */
      }
    }

    return GG;
  }

  /**
   * 有理多項式行列 <code>G</code> の成分を <code>minreal()</code> を用いて単純化します。
   * 
   * @param G 有利多項式行列
   * @return simplified matrix
   */
  public static DoubleRationalPolynomialMatrix simplify(DoubleRationalPolynomialMatrix G) {
    double tolerance = -1.0;
    return simplify(G, tolerance);
  }

  /**
   * <code>tolerance</code>は、<code>minreal()</code> に渡されます。
   * 
   * @param G 有利多項式行列
   * @param tolerance 許容誤差
   * @return simplified matrix
   * @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 static <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>> AnyRealRationalPolynomialMatrix<RS, RM, CS, CM> simplify(
      AnyRealRationalPolynomialMatrix<RS, RM, CS, CM> G, RS tolerance) {
    AnyRealRationalPolynomial<RS, RM, CS, CM>[][] gg = G.getElement(1, 1).createArray(G.getRowSize(), G.getColumnSize());
    AnyRealRationalPolynomialMatrix<RS, RM, CS, CM> GG = new AnyRealRationalPolynomialMatrix<>(G.getRowSize(), G.getColumnSize(), gg);

    for (int i = 1; i <= G.getRowSize(); i++) {
      for (int j = 1; j <= G.getColumnSize(); j++) {
        AnyRealRationalPolynomial<RS, RM, CS, CM> g = G.getElement(i, j);
        GG.setElement(i, j, simplify(g, tolerance));
        /*
        if (tolerance >= 0) {
          GG.setElement(i, j, simplify(g, tolerance));
        } else {
          GG.setElement(i, j, simplify(g));
        }
        */
      }
    }

    return GG;
  }

  /**
   * 有理多項式行列 <code>G</code> の成分を <code>minreal()</code> を用いて単純化します。
   * 
   * @param G 有利多項式行列
   * @return simplified matrix
   * @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 static <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>> AnyRealRationalPolynomialMatrix<RS, RM, CS, CM> simplify(
      AnyRealRationalPolynomialMatrix<RS, RM, CS, CM> G) {
    RS sunit = G.getElement(1, 1).getNumerator().getCoefficient(0).createUnit();
    RS tolerance = sunit.create(-1);
    return simplify(G, tolerance);
  }

  /**
   * 有理多項式 <code>g</code> を <code>minreal()</code> を用いて 簡単化します。
   * 
   * @param g 有利多項式
   * @return simplified rational polynomial
   * @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 static <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>> AnyRealRationalPolynomial<RS, RM, CS, CM> simplify(
      AnyRealRationalPolynomial<RS, RM, CS, CM> g) {
    RS sunit = g.getNumerator().getCoefficient(0).createUnit();
    RS tolerance = sunit.create(-1);
    return simplify(g, tolerance);
  }

  /**
   * 許容誤差 <code>tolerance</code>は、<code>minreal()</code> に渡されます。
   * 
   * @param originalSystem 元のシステム
   * @param tolerance 許容誤差
   * @return simplified rational polynomial
   * @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 static <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>> AnyRealRationalPolynomial<RS, RM, CS, CM> simplify(
      AnyRealRationalPolynomial<RS, RM, CS, CM> originalSystem, RS tolerance) {
    AnyRealPolynomial<RS, RM, CS, CM> n = originalSystem.getNumerator();
    AnyRealPolynomial<RS, RM, CS, CM> d = originalSystem.getDenominator();

    if (n.getDegree() > d.getDegree()) {
      List<RM> tmp = Deconv.deconv(n.getCoefficients(), d.getCoefficients());
      RM q = tmp.get(0);
      RM r = tmp.get(1);
      AnyRealRationalPolynomial<RS, RM, CS, CM> newSystem = new AnyRealRationalPolynomial<>(new AnyRealPolynomial<>(r), d);

      AnyRealRationalPolynomial<RS, RM, CS, CM>[] ns = newSystem.createArray(1);
      ns[0] = newSystem;
      List<RM> tmp2 = Tfm2ss.tfm2ss(newSystem.createGrid(ns), 1, tolerance);
      /*
      if (tolerance >= 0) {
        tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {newSystem})), 1, tolerance);
      } else {
        tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {newSystem})), 1);
      }
      */

      RM A = tmp2.get(0);
      RM B = tmp2.get(1);
      RM C = tmp2.get(2);
      RM D = tmp2.get(3);

      newSystem = Ss2tfn.ss2tfn(A, B, C, D).add(new AnyRealPolynomial<>(q));
      return newSystem;
    }

    AnyRealRationalPolynomial<RS, RM, CS, CM>[] rp = originalSystem.createArray(1);
    rp[0] = originalSystem;

    List<RM> tmp = Tfm2ss.tfm2ss(originalSystem.createGrid(rp), 1, tolerance);
    /*
    if (tolerance >= 0) {
      tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {originalSystem})), 1, tolerance);
    } else {
      tmp = Tfm2ss.tfm2ss((new DoubleRationalPolynomialMatrix(new DoubleRationalPolynomial[] {originalSystem})), 1);
    }
    */

    RM A = tmp.get(0);
    RM B = tmp.get(1);
    RM C = tmp.get(2);
    RM D = tmp.get(3);

    AnyRealRationalPolynomial<RS, RM, CS, CM> newSystem = Ss2tfn.ss2tfn(A, B, C, D);
    return newSystem;
  }

}