Parameter.java

package org.mklab.sdpj.algorithm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;

import org.mklab.mpf.ap.MPFloat;
import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.DoubleNumber;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.sdpj.iocenter.IO;
import org.mklab.sdpj.tool.Tools;


/**
 * class <code>Parameter</code> is the setting parameter of solving SDP problem efficiently and correctly, 
 * which is based on the experiential data of computing experiment. About more detail information,
 * please refer to web site:
 *  <a href = "http://sdpa.sourceforge.net/" style=text-decoration:none>
 * <tt>http://sdpa.sourceforge.net/</tt></a>.  
 * <br>パラメータを表すクラスです。
 * 
 * @author koga
 * @version $Revision$, 2009/04/24
 * @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 Parameter<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>> {

  /**maximum iteration of computing, which is <code>400</code> by default. */
  public int maxIteration;
  /**parameter <code>epsilonStar</code>, which control the precision of solution. */
  public RS epsilonStar;
  /**parameter <code>lambdaStar</code>, which is initial value of solving SDP problem, is <code>100</code> by default. */
  public RS lambdaStar;
  /**parameter <code>omegaStar</code>, which is experiential data.*/
  public RS omegaStar;
  /**lower bound of SDP solution, which is <code>-100,000</code> by default. */
  public RS lowerBound;
  /**upper bound of SDP solution, which is <code>100,000</code> by default. */
  public RS upperBound;
  /**parameter <code>betaStar</code>, which is experiential data. */
  public RS betaStar;
  /**parameter <code>betaBar</code>, which which control the speed of numerical convergence of computing. */
  public RS betaBar;
  /**parameter <code>gammaStar</code>, which is experiential data.*/
  public RS gammaStar;
  /**parameter <code>epsilonDash</code>, which control the precision of solution. */
  public RS epsilonDash;
  /**unit based on a specific data type */
  private RS unit;

  /**
   * constructor of class <code>Parameter</code>
   * <br>新しく生成された{@link Parameter}オブジェクトを初期化します。
   * 
   * @param unit unit based on a specified data type
   */
  public Parameter(RS unit) {
    this.unit = unit;
    if (this.unit instanceof DoubleNumber) {
      DoubleNumber.setDisplayAsZero(false);
    }
  }

  /**
   * an unit based on a specific data type.
   * 
   * @return unit
   */
  public RS getUnit() {
    return this.unit;
  }

  /**
   * パラメータタイプに従ったパラメータを設定します。
   * 
   * @param type パラメータタイプ
   */
  public void setDefaultParameter(ParameterType type) {
    RS ten = this.unit.create(10);
    if (type == ParameterType.PARAMETER_MP115_DEFAULT) {//MPFloat用のパラメータ      
      this.maxIteration = 200;
      this.epsilonStar = ten.power(-30);
      this.lambdaStar = ten.power(4);
      this.omegaStar = this.unit.create(2);
      this.lowerBound = ten.power(5).unaryMinus();
      this.upperBound = this.lowerBound.unaryMinus();
      this.betaStar = this.unit.createUnit().divide(10);
      this.betaBar = this.unit.create(3).divide(10);
      this.gammaStar = this.unit.create(9).divide(10);
      this.epsilonDash = ten.power(-30);
    } else if (type == ParameterType.PARAMETER_MP115_STABLE) {
      this.maxIteration = 1000;
      this.epsilonStar = ten.power(-30);
      this.lambdaStar = ten.power(2);
      this.omegaStar = this.unit.create(2);
      this.lowerBound = ten.power(5).unaryMinus();
      this.upperBound = this.lowerBound.unaryMinus();
      this.betaStar = this.unit.create(2).divide(10);
      this.betaBar = this.unit.create(4).divide(10);
      this.gammaStar = this.unit.create(5).divide(10);
      this.epsilonDash = ten.power(-30);
    } else if (type == ParameterType.PARAMETER_STABLE) {
      this.maxIteration = 1000;
      this.epsilonStar = ten.power(-7);
      this.lambdaStar = ten.power(2);
      this.omegaStar = this.unit.createUnit().multiply(2);
      this.lowerBound = ten.power(5).unaryMinus();
      this.upperBound = ten.power(5);
      this.betaStar = this.unit.create(2).divide(10);
      this.betaBar = this.unit.create(4).divide(10);
      this.gammaStar = this.unit.create(5).divide(10);
      this.epsilonDash = ten.power(-7);
    } else if (type == ParameterType.PARAMETER_AGGRESSIVE) {
      this.maxIteration = 100;
      this.epsilonStar = ten.power(-7);
      this.lambdaStar = ten.power(2);
      this.omegaStar = this.unit.createUnit().multiply(2);
      this.lowerBound = ten.power(5).unaryMinus();
      this.upperBound = ten.power(5);
      this.betaStar = this.unit.createUnit().divide(100);
      this.betaBar = this.unit.create(2).divide(100);
      this.gammaStar = this.unit.create(98).divide(100);
      this.epsilonDash = ten.power(-7);
    } else {
      this.maxIteration = 100;
      this.epsilonStar = ten.power(-7);
      this.lambdaStar = ten.power(2);
      this.omegaStar = this.unit.create(2);
      this.lowerBound = ten.power(5).unaryMinus();
      this.upperBound = ten.power(5);
      this.betaStar = this.unit.createUnit().divide(10);
      this.betaBar = this.unit.create(2).divide(10);
      this.gammaStar = this.unit.create(9).divide(10);
      this.epsilonDash = ten.power(-7);
    }
  }

  /**
   * デフォルトパラメータを設定します。
   */
  public void setDefaultParameter() {
    this.setDefaultParameter(ParameterType.PARAMETER_DEFAULT);
  }

  /**
   * ファイルからパラメータを読み込みます。 コメント文は無いものと考えています。 |[数字][その他] TODO
   * IOで定義したパターンを使ってマッチさせると結果をStringでとってきてそのままMPFloatに渡せるかと。。。
   * 
   * @param parameterFile パラメータファイル
   * @throws IOException ファイルを読み込めない場合
   */
  public void readFile(File parameterFile) throws IOException {
    try (BufferedReader buffer = new BufferedReader(new FileReader(parameterFile))) {
      this.maxIteration = IO.readInteger(buffer.readLine());
      this.epsilonStar = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      this.lambdaStar = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      this.omegaStar = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      this.lowerBound = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      this.upperBound = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      this.betaStar = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      this.betaBar = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      this.gammaStar = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      this.epsilonDash = this.unit.valueOf(IO.readOtherStringRealNumber(buffer.readLine()));
      buffer.close();
    }
  }

  /**
   * 出力します。
   * 
   * @param output 出力先
   */
  public void display(PrintStream output) {
    Tools.message(this.toString(), output);
  }

  /**
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    StringBuffer message = new StringBuffer();
    message.append("betaBar      :  " + this.betaBar); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("betaStar     :  " + this.betaStar); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("epsilonDash  :  " + this.epsilonDash); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("epsilonStar  :  " + this.epsilonStar); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("gammaStar    :  " + this.gammaStar); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("lambdaStar   :  " + this.lambdaStar); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("lowerBound   :  " + this.lowerBound); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("maxIteration :  " + this.maxIteration); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("omegaStar    :  " + this.omegaStar); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$
    message.append("upperBound   :  " + this.upperBound); //$NON-NLS-1$
    message.append("\n"); //$NON-NLS-1$

    if (this.betaBar instanceof MPFloat) {
      message.append("The data type is based on : MPFloat\n"); //$NON-NLS-1$
      message.append("approximate significant digits : " + MPFloat.getDefaultNumberOfPrecisionDigits()); //$NON-NLS-1$
    }

    if (this.betaBar instanceof DoubleNumber) {
      message.append("The data type is based on : double\n"); //$NON-NLS-1$
      message.append("approximate significant digits : 16"); //$NON-NLS-1$
    }
    message.append("\n"); //$NON-NLS-1$
    return message.toString();
  }
}