MaximaExpressionProcessor.java

/*
 * Created on 2008/01/30
 * Copyright (C) 2008 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.tool.control.system.rpn;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.rpn.AbstractExpressionProcessor;
import org.mklab.nfc.rpn.ReversePolishNotationOperand;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.tool.control.system.SystemOperator;


/**
 * 逆ポーランド記法を数式に関して評価し、Maximaを用いて変数に数値を代入した評価値を求めるクラスです。
 * 
 * @author Anan
 * @version $Revision: 1.10 $, 2008/01/30
 * @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 MaximaExpressionProcessor<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>> extends AbstractExpressionProcessor<RS,RM> {
  
  
  /**
   * 新しく生成された<code>MaximaExpressionProcessor</code>オブジェクトを初期化します。
   */
  public MaximaExpressionProcessor() {
    setHasCancellation(false);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String getResult(ReversePolishNotationOperand<RS,RM> operand) {
    final String result = super.getResult(operand);
    if (result == "0") { //$NON-NLS-1$
      return "0"; //$NON-NLS-1$
    }

    try {
      final Maxima<RS,RM,CS,CM> maxima = new Maxima<>();
      maxima.open();
      
      final StringBuilder commands = new StringBuilder();

      commands.append(maxima.getDeclearOfSystems((SystemOperator<RS,RM,CS,CM>)operand));

      final String lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$
      commands.append("ttyoff:false;" + lineSeparator); //$NON-NLS-1$

      final String replacedResult = result.replaceAll("1/", "division"); //$NON-NLS-1$ //$NON-NLS-2$
      commands.append("ans:rat(" + replacedResult + ",s);" + lineSeparator); //$NON-NLS-1$ //$NON-NLS-2$

      
      maxima.sendComand(commands);
      final String ans = maxima.receiveResult();
      final String replacedAns = ans.replaceAll("division", "1/"); //$NON-NLS-1$ //$NON-NLS-2$
      return convertMaximaToMatx(replacedAns);
    } catch (IOException e) {
      throw new IllegalArgumentException(e);
    }
  }

  /**
   * Maximaのコードに対応するMaTXのコードを返します。
   * 
   * @param maximaCode Maximaのコード
   * @return Maximaのコードに対応するMaTXのコード
   */
  private String convertMaximaToMatx(final String maximaCode) {
    final Pattern pattern1 = Pattern.compile("(matrix\\()"); //$NON-NLS-1$
    final Matcher matcher1 = pattern1.matcher(maximaCode);
    final String str1 = matcher1.replaceAll("["); //$NON-NLS-1$

    final Pattern pattern2 = Pattern.compile("\\](,)\\["); //$NON-NLS-1$
    final Matcher matcher2 = pattern2.matcher(str1);
    final String str2 = matcher2.replaceAll("]["); //$NON-NLS-1$

    final Pattern pattern3 = Pattern.compile("\\]\\)"); //$NON-NLS-1$
    final Matcher matcher3 = pattern3.matcher(str2);
    final String str3 = matcher3.replaceAll("]]"); //$NON-NLS-1$

    final Pattern pattern4 = Pattern.compile(" . "); //$NON-NLS-1$
    final Matcher matcher4 = pattern4.matcher(str3);
    final String str4 = matcher4.replaceAll("*"); //$NON-NLS-1$

    return str4;
  }

  /**
   * {@inheritDoc}
   */
  public String getLeftParenthesis() {
    return "("; //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public String getRightParenthesis() {
    return ")"; //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public String getInverseString() {
    return "^(-1)"; //$NON-NLS-1$
  }

  /**
   * {@inheritDoc}
   */
  public String getMultiplicationString() {
    return "*"; //$NON-NLS-1$
  }
}