Sdpj.java

/*
 * Created on 2011/02/21
 * Copyright (C) 2011 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.sdpj.solver;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

import org.mklab.mpf.ap.EFFloat;
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.algorithm.ParameterType;
import org.mklab.sdpj.algorithm.PhaseType;
import org.mklab.sdpj.algorithm.Solution;
import org.mklab.sdpj.algorithm.SolveInfo;
import org.mklab.sdpj.iocenter.Vsolution;
import org.mklab.sdpj.problem.Problem;
import org.mklab.sdpj.tool.Tools;


/**
 * <p> The <tt>class Sdpj</tt> is defined for users to use SDPJ simply and correctly based on eclipse. We designed the 2 standard types of SDPJ usage. <p> The details of 2 standard types of usage is
 * introduced as follows: 
 * 
 * <ul>
 * 
 * <li>Constructor <code>Sdpj(param_1, ..., param_n)</code>:<br>
 * 
 * Example:<br> 
 * 
 * <code>Sdpj sdpj = new {link #Sdpj(NumericalScalar, int, String, String, String, String)};</code><br>
 * 
 * <code>sdpj.{@link #run()};</code><br>
 * 
 * where it is an example usage of SDPJ. You have not to set the all of parameters of constructor <br> 
 * 
 * <code>Sdpj(NumericalScalar, int, String, String, String, String)</code>. If you set partial parameters<br>
 * 
 * of the constructor, other parameters should be set by default. <br>
 * 
 * </li> 
 * 
 * <li>Setter functions:<br>
 * 
 * Example:<br>
 * 
 * <code>Sdpj sdpj = new {@link #Sdpj()};</code><br>
 * 
 * <code>String ProblemFile; </code><br>
 * 
 * <code>String SolutionFile; </code><br>
 * 
 * <code>String InitialFile; </code><br>
 * 
 * <code>String ParameterFile; </code><br>
 * 
 * <code>E unit = new MPFloat(1);</code><br>
 * 
 * <code>sdpj.{@link #setProblemFile(String)};</code><br>
 * 
 * <code>sdpj.{@link #setSolutionFile(String)};</code><br>
 * 
 * <code>sdpj.{@link #setParameterFile(String)};</code><br>
 * 
 * <code>sdpj.{@link #setInitialFile(String)};</code><br> <code>sdpj.
 * {link #setDataType(NumericalScalar)};</code><br>
 * 
 * <code>sdpj.{@link #run()};</code><br>
 * 
 * where it is an example usage of SDPJ based on setting functions. You have not set the all of parameters of setter<br>
 * 
 * functions like as <code>sdpj.setProblemFile(ProblemFile)</code>. And you can set partial parameters what you want to set,<br>
 * 
 * The others should be set by default.<br>
 * 
 * </li>
 * 
 * </ul>
 * 
 * <br>....<br> Additional explanation is the usage of SDPJ, which can mix the 2 standard types of usage. You should try these usage by yourself<br> and I think you can use SDPJ flexibly for
 * solving SDP problem. If you want to know more detail information about the usage of SDPJ,<br> you can call the function <code>{@link #showUsage()}</code><br>
 * 
 * @author wu
 * @version 0.6.3, 2011/02/21
 * @param <RS> type of real scalar
 * @param <RM> type of real matrix
 * @param <CS> type of complex scalar
 * @param <CM> type of complex Matrix
 * @since 0.6.2
 */
public class Sdpj<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>> {

  /**
   * The numerical arithmetic accuracy, which you want to use.
   */
  private int precision;
  /**
   * The data type you want to use for the numerical arithmetic.
   */
  private RS unit;
  /**
   * The SDP problem you want to solve by SDPJ.
   */
  private String ProblemFile;
  /**
   * The define a file name for saving the result of SDPJ.
   */
  private String SolutionFile;
  /**
   * The initial parameter value for solving SDP problem by SDPJ.
   */
  private String ParameterFile;
  /**
   * The initial value for solving SDP problem more efficiently by SDPJ.
   */
  private String initialFile;
  /**
   * If you want not to input a parameter file, you can set Class {@link org.mklab.sdpj.algorithm.ParameterType <tt>ParameterType</tt>}.
   */
  private ParameterType parameterType;
  /**
   * If you set an initial value to SDPJ, <code>isInitialFile</code> is True; else false.
   */
  private boolean isInitialFile;
  /**
   * If you set an parameter file, <code>isParameter</code> is True; else false.
   */
  private boolean isParameter;
  /**
   * If the SDP problem data saved in file is the sparse format, <code>isDataSparse</code> is True; else false.
   */
  private boolean isDataSparse;
  /**
   * If the initial data saved in file is the sparse format, <code>isInitialSparse</code> is True; else false.
   */
  private boolean isInitialSparse;
  /**
   * Define an output object for saving the result of SDPJ.
   */
  private PrintStream Save;

  /**
   * Save the elapsed time of verifying solution.
   */
  private static double elapsedTime;

  /** If Use the function of Class <code>Vsolution</code>, True; else, False */
  private boolean isVsolution = false;

  /** Control the displaying of computing information */
  private boolean isDisplay = true;

  /** Show the status of SDP solution */
  private PhaseType phaseValue;

  /** if use class <code>Vsdpj</code>, true; else, false. */
  private boolean isVsdpj = false;

  /** define a variable <code>vsolution</code> of class <code>Vsolution</code> */
  private Vsolution<RS,RM,CS,CM> vsolution;

  /** define a variable <code>problem</code> of class <code>Problem</code> */
  private Problem<RS,RM,CS,CM> problem;

  /** elapsed time of solving SDP problem */
  private double elapsedTIME;

  /** define a variable <code>currentPt</code> of class <code>Solution</code> */
  private Solution<RS,RM,CS,CM> currentPt;

  /** define a variable <code>solver</code> of class <code>Solver</code> */
  private Solver<RS,RM,CS,CM> solver;

  /**
   * define a variable <code>solutionInformation</code> of class <code>SolveInfo</code>
   */
  private SolveInfo<RS,RM,CS,CM> solutionInformation;

  /**
   * 新しく生成された<code>sdpj</code>オブジェクトを初期化します。<br> Constructor <code>Sdpj(RS unit)</code> do nothing.
   */
  public Sdpj() {
    // do nothing
  }

  /**
   * Constructor <code>Sdpj(RS unit)</code> is for setting a data type, on which the SDPJ will run the numerical arithmetic based.
   * 
   * @param unit The data type such as "<code>MPFloat</code>", " <code>DoubleNumber</code>"
   */
  public Sdpj(RS unit) {
    this.unit = unit;
    this.setPrecision();
  }

  /**
   * 新しく生成された<code>Sdpj</code>オブジェクトを初期化します。<br> Constructor <code>Sdpj(String InputFile, String Id)</code> can initialize the input and output data <code>{@link #ProblemFile}</code> and <code>
   * {@link #SolutionFile}</code><br> or set a initial data such as <code>{@link #ParameterFile}</code> and <code>{@link #initialFile}</code>
   * 
   * @param InputFile The name of inputting file, <code>String</code> data type
   * @param Id The identification of a kind of files, <code>String</code> data type
   */
  public Sdpj(String InputFile, String Id) {
    if (Id.contains("-")) { //$NON-NLS-1$
      if (Id.toLowerCase().contains("p")) { //$NON-NLS-1$
        this.ParameterFile = InputFile;
        this.isParameter = true;
      } else if (Id.toLowerCase().contains("i")) { //$NON-NLS-1$
        this.initialFile = InputFile;
        this.isInitialFile = true;
        this.isInitialSparse = this.isSparse(this.initialFile);
      } else {
        System.err.println("The ID can not be recognized!"); //$NON-NLS-1$
        System.err.println("The correct ID is \"-p\" or \"-i\""); //$NON-NLS-1$
        System.exit(0);
      }
    } else {
      this.ProblemFile = InputFile;
      this.isDataSparse = this.isSparse(this.ProblemFile);
      this.SolutionFile = Id;
    }
  }

  /**
   * 新しく生成された<code>sdpj</code>オブジェクトを初期化します。<br> Constructor <code>Sdpj(String ProblemFile)</code> initialize a SDP problem, which should be solved by SDPJ
   * 
   * @param ProblemFile The SDP problem data
   */
  public Sdpj(String ProblemFile) {
    this.ProblemFile = ProblemFile;
    this.isDataSparse = isSparse(this.ProblemFile);
    final String target = Tools.getFileName(this.ProblemFile);
    this.SolutionFile = target + ".sdpj"; //$NON-NLS-1$
  }

  // /**
  // * 新しく生成された<code>sdpj</code>オブジェクトを初期化します。
  // * @param ProblemFile the parameter <code>ProblemFile</code> is a SDP
  // problem.
  // * @param SolutionFile the parameter <code>SolutionFile</code> for saving
  // the result of solver.
  // */
  // public Sdpj(String ProblemFile, String SolutionFile) {
  // this.ProblemFile = ProblemFile;
  // this.SolutionFile = SolutionFile;
  // this.unit = (E)new MPFloat(1);
  // this.setPrecision();
  // this.isDataSparse = isSparse(this.ProblemFile);
  // }

  /**
   * 新しく生成された<code>Sdpj</code>オブジェクトを初期化します。<br> Constructor <code>Sdpj(RS unit, int Precision)</code> initialize the data type <code>{@link #unit}</code> and the <code>{@link #precision}</code>.
   * 
   * @param unit The data type such as "<code>MPFloat</code>", " <code>DoubleNumber</code>"
   * @param Precision The computing accuracy, which is digits by decimal
   */
  public Sdpj(RS unit, int Precision) {
    this.setDataType(unit, Precision);
  }

  /**
   * 新しく生成された<code>Sdpj</code>オブジェクトを初期化します。<br> Constructor <code>Sdpj(RS unit, String ProblemFile)</code> initialize the data type <code>{@link #unit}</code> and the SDP problem <code>
   * {@link #ProblemFile}</code>
   * 
   * @param unit The data type
   * @param ProblemFile The SDP problem
   */
  public Sdpj(RS unit, String ProblemFile) {
    this.unit = unit;
    this.setPrecision();
    this.ProblemFile = ProblemFile;
    final String target = Tools.getFileName(this.ProblemFile);
    this.SolutionFile = target + ".sdpj"; //$NON-NLS-1$
    this.isDataSparse = isSparse(this.ProblemFile);
  }

  /**
   * 新しく生成された<code>sdpj</code>オブジェクトを初期化します。<br> Constructor <code>Sdpj(RS unit, String ProblemFile, String SolutionFile)</code> initialize the data type <code>{@link #unit}</code>, the SDP problem
   * <code>{@link #ProblemFile}</code> and the output file <code>{@link #SolutionFile}</code>
   * 
   * @param unit The data type
   * @param ProblemFile The SDP problem
   * @param SolutionFile The output file for saving the result of solver
   */
  public Sdpj(RS unit, String ProblemFile, String SolutionFile) {
    this.unit = unit;
    this.setPrecision();
    this.ProblemFile = ProblemFile;
    this.SolutionFile = SolutionFile;
    this.isDataSparse = isSparse(this.ProblemFile);
  }

  /**
   * 新しく生成された<code>sdpj</code>オブジェクトを初期化します。<br> Constructor <code>Sdpj(RS unit, int Precision, String ProblemFile, String SolutionFile)</code> initialize the data type <code>{@link #unit}</code>,
   * accuracy <code>{@link #precision}</code>, the SDP problem <code>{@link #ProblemFile}</code> and the output file <code>{@link #SolutionFile}</code>
   * 
   * @param unit The data type.
   * @param Precision The parameter <code>Precision</code> , which is accuracy.
   * @param ProblemFile The parameter <code>ProblemFile</code> is a SDP problem.
   * @param SolutionFile The parameter <code>SolutionFile</code> for saving the result of solver.
   */
  public Sdpj(RS unit, int Precision, String ProblemFile, String SolutionFile) {
    this.unit = unit;
    this.precision = Precision;
    this.setPrecision(this.precision);
    this.ProblemFile = ProblemFile;
    this.SolutionFile = SolutionFile;
    this.isDataSparse = isSparse(this.ProblemFile);
  }

  /**
   * 新しく生成された<code>sdpj</code>オブジェクトを初期化します。<br> Constructor <code>Sdpj(RS unit, int Precision, String ProblemFile, String SolutionFile, String SetFile, String Id)</code> initialize the data type
   * <code>{@link #unit}</code>, accuracy <code>{@link #precision}</code>, the SDP problem <code>{@link #ProblemFile}</code>, the output file <code>{@link #SolutionFile}</code>, the initial data such
   * as <code>{@link #ParameterFile}</code> or <code>{@link #initialFile}</code>, and <code>Id</code>, which mean the kind of files.
   * 
   * @param unit The data type is "MPFloat" or "DoubleNumber"
   * @param Precision The numerical arithmetic accuracy
   * @param ProblemFile The SDP problem
   * @param SolutionFile The file name of saving the result of SDPJ
   * @param SetFile The file is maybe an initial file or a parameter file
   * @param Id The format of Id is "-p" or "-i"
   */
  public Sdpj(RS unit, int Precision, String ProblemFile, String SolutionFile, String SetFile, String Id) {
    this.unit = unit;
    this.precision = Precision;
    this.setPrecision(this.precision);
    this.ProblemFile = ProblemFile;
    this.SolutionFile = SolutionFile;
    this.isDataSparse = isSparse(this.ProblemFile);
    setFileById(SetFile, Id);
  }

  /**
   * The function <code>run()</code> solve the SDP problem.
   * 
   * @throws IOException If an I/O error occurs.
   */
  public void run() throws IOException {
    showHeadMessage();
    // Solver<RS,RM,CS,CM> solver = new Solver<RS,RM,CS,CM>(this.unit);
    this.solver = new Solver<>(this.unit);

    this.solver.setDataFile(this.ProblemFile);
    this.solver.setInitFile(this.initialFile);
    this.solver.setOutFile(this.SolutionFile);
    this.solver.setParaFile(this.ParameterFile);
    this.solver.setIsInitFile(this.isInitialFile);
    this.solver.setIsInitSparse(this.isInitialSparse);
    this.solver.setIsDataSparse(this.isDataSparse);
    this.solver.setIsParameter(this.isParameter);
    this.solver.setParameterType(this.parameterType);
    this.solver.setPrintStreamForDisplay(System.out);
    this.solver.setPrintStreamForSave(this.Save);
    this.solver.setVsolution(this.isVsolution);
    this.solver.setDisplay(this.isDisplay);
    this.solver.setVsdpj(this.isVsdpj);

    final double D10E9 = Math.pow(10, 9);
    final double StartTime = System.nanoTime();
    this.solver.run();
    if (this.isVsdpj == true) {
      this.phaseValue = this.solver.getPhaseValue(); // get the Value of
      // status of SDP
      // solution
      this.vsolution = this.solver.getVsolution();
      this.problem = this.solver.getProblem();
      this.setSolutionInformation(this.solver.getSolutionInformation());
      // this.currentPt = solver.getSolution();
    }

    final double EndTime = System.nanoTime();
    final double value = (EndTime - StartTime) / D10E9;
    this.elapsedTIME = value; // save the elapsed time of computing SDP
    // solution.
    if (this.isDisplay == true) {
      if (elapsedTime == 0.0) {
        System.out.printf("The elapsed time of solving this SDP problem is : %.3f seconds\n\n\n", Double.valueOf(value)); //$NON-NLS-1$
        this.Save.printf("The elapsed time of solving this SDP problem is : %.3f seconds\n\n", Double.valueOf(value)); //$NON-NLS-1$
      } else {
        System.out.printf("The elapsed time of solving and verifying this SDP problem is : %.3f + %.3f = %.3f seconds\n\n", //$NON-NLS-1$
            Double.valueOf(value - elapsedTime), Double.valueOf(elapsedTime), Double.valueOf(value));
        this.Save.printf("The elapsed time of solving and verifying this SDP problem is : %.3f + %.3f = %.3f seconds\n\n", //$NON-NLS-1$
            Double.valueOf(value), Double.valueOf(elapsedTime), Double.valueOf(value));
      }
    }
    elapsedTime = 0.0; // clear the existed data, or reset variable
    // elapsedTime.
  }

  /**
   * @param isDisplay isDisplayを設定します。
   */
  public void setDisplay(boolean isDisplay) {
    this.isDisplay = isDisplay;
  }

  /**
   * @return isDisplayを返します。
   */
  public boolean isDisplay() {
    return this.isDisplay;
  }

  /**
   * @param Save an output object for saving the result of SDPJ
   */
  public void setSave(PrintStream Save) {
    this.Save = Save;
  }

  /**
   * @param vsolution vsolutionを設定します。
   */
  public void setVsolution(boolean vsolution) {
    this.isVsolution = vsolution;
  }

  /**
   * @return vsolutionを返します。
   */
  public boolean isVsolution() {
    return this.isVsolution;
  }

  /**
   * @param phaseValue phaseValueを設定します。
   */
  public void setPhaseValue(PhaseType phaseValue) {
    this.phaseValue = phaseValue;
  }

  /**
   * @return phaseValueを返します。
   */
  public PhaseType getPhaseValue() {
    return this.phaseValue;
  }

  /**
   * The function <code>setFileById(String SetFile, String Id)</code> set the initial data to <code>{@link #ParameterFile}</code> or <code>{@link #initialFile}</code>.
   * 
   * @param SetFile The file is maybe an initial file or a parameter file
   * @param Id The format of Id is "-p" or "-i"
   */
  private void setFileById(String SetFile, String Id) {
    if (Id.contains("-")) { //$NON-NLS-1$
      if (Id.toLowerCase().contains("p")) { //$NON-NLS-1$
        this.ParameterFile = SetFile;
        this.isParameter = true;
      } else if (Id.toLowerCase().contains("i")) { //$NON-NLS-1$
        this.initialFile = SetFile;
        this.isInitialFile = true;
        this.isInitialSparse = this.isSparse(this.initialFile);
      } else {
        System.err.println("The ID can not be recognized!"); //$NON-NLS-1$
        System.err.println("The correct ID is \"-p\" or \"-i\""); //$NON-NLS-1$
        System.exit(0);
      }
    } else {
      System.err.println("The ID can not be recognized!"); //$NON-NLS-1$
      System.err.println("The correct ID is \"-p\" or \"-i\""); //$NON-NLS-1$
      System.exit(0);
    }
  }

  /**
   * The function <code>setParameterType(ParameterType parameterType)</code> set the parameter type {@link org.mklab.sdpj.algorithm.ParameterType <tt>ParameterType</tt>}
   * 
   * @param parameterType The {@link org.mklab.sdpj.algorithm.ParameterType <tt>ParameterType</tt>} value to decide parameter type
   */
  public void setParameterType(ParameterType parameterType) {
    this.parameterType = parameterType;
    this.isParameter = false;
    this.ParameterFile = null;
  }

  /**
   * The function <code>setParameterFile(String ParameterFile)</code> set a parameter <code>{@link #ParameterFile}</code>.
   * 
   * @param ParameterFile The <code>String</code> value
   */
  public void setParameterFile(String ParameterFile) {
    this.ParameterFile = ParameterFile;
    this.isParameter = true;
    this.parameterType = null;
  }

  /**
   * The function <code>setInitialFile(String InitialFile)</code> set a initial value <code>{@link #initialFile}</code>
   * 
   * @param InitialFile Setting a initial value for solving the SDP problem more effectively
   */
  public void setInitialFile(String InitialFile) {
    this.initialFile = InitialFile;
    this.isInitialFile = true;
    this.isInitialSparse = this.isSparse(this.initialFile);
  }

  /**
   * The function <code>setProblemFile(String ProblemFile)</code> set a SDP problem <code>{@link #ParameterFile}</code>.
   * 
   * @param ProblemFile Setting a SDP problem, which you want to solve
   */
  public void setProblemFile(String ProblemFile) {
    this.ProblemFile = ProblemFile;
    this.isDataSparse = isSparse(this.ProblemFile);
    if (this.SolutionFile == null) {
      final String target = Tools.getFileName(this.ParameterFile);
      this.SolutionFile = target + ".sdpj"; //$NON-NLS-1$
    }
  }

  /**
   * The function <code>setSolutionFile(String SolutionFile)</code> set a output file <code>{@link #SolutionFile}</code>.
   * 
   * @param SolutionFile If you want to specify a output file name
   */
  public void setSolutionFile(String SolutionFile) {
    this.SolutionFile = SolutionFile;
  }

  /**
   * The function <code>setDataType(RS unit)</code> set a data type <code>{@link #unit}</code>.
   * 
   * @param unit If you want to specify a data type, which you want to use
   */
  public void setDataType(RS unit) {
    this.unit = unit;
    this.setPrecision();
  }

  /**
   * The function <code>setDataType(RS unit, int Precision)</code> set a data type <code>{@link #unit}</code> and accuracy <code>{@link #precision}</code>.
   * 
   * @param unit If you want to specify a data type, which you want to use
   * @param Precision If you want to specify a accuracy, which you want to use
   */
  public void setDataType(RS unit, int Precision) {
    this.unit = unit;
    this.precision = Precision;
    this.setPrecision(this.precision);
  }

  /**
   * The function <code>setPrecision(int Precision)</code> set an accuracy <code>{@link #precision}</code>
   * 
   * @param Precision A accuracy
   */
  public void setPrecision(int Precision) {
    if (this.unit instanceof MPFloat) {
      this.precision = Precision;
      MPFloat.setDefaultPrecisionDigits(this.precision);
    } else if (this.unit instanceof EFFloat) {
      this.precision = Precision;
      EFFloat.setDefaultPrecisionDigits(this.precision);
    } else if (this.unit instanceof DoubleNumber) {
      System.err.println("The solver is based on double precision arithmetic, you can not change the precision!"); //$NON-NLS-1$
      System.exit(0);
    } else {
//      System.err.println("Please decide a data type correctly!"); //$NON-NLS-1$
      throw new RuntimeException("Please decide a data type correctly!"); //$NON-NLS-1$
    }
  }

  /**
   * The function <code>isSparse</code> is to judge the data is saved in sparse or dense based on the file format, which is ".dat-s" or ".dat" . If the file format is ".dat", which mean that the data
   * saved in file is dense, the ".dat-s" mean that the data saved is sparse.
   * 
   * @param File The <code>String</code> data type
   * @return The <code>boolean</code> value
   */
  private boolean isSparse(String File) {
    final int length = File.length();
    if (File.charAt(length - 1) == 's' && File.charAt(length - 2) == '-') {
      return true;
    }
    return false;
  }

  /**
   * Set considerable precision based on the specified data type.
   */
  private void setPrecision() {
    if (this.unit instanceof MPFloat || this.unit instanceof EFFloat) {
      this.precision = 64;
      MPFloat.setDefaultPrecisionDigits(this.precision);
    } else if (this.unit instanceof DoubleNumber) {
      this.precision = 16;
    } else {
      //System.err.println("Please decide a data type correctly!"); //$NON-NLS-1$
      throw new RuntimeException("Please decide a data type correctly!"); //$NON-NLS-1$
    }
  }

  /**
   * The function <code>showHeadMessage()</code> show the head message.
   * 
   * @throws FileNotFoundException If an I/O error occurs.
   */
  private void showHeadMessage() throws FileNotFoundException {
    if (this.unit instanceof MPFloat) {
      if (this.isDisplay == true) {
        System.out.println("\nSDPJ is based on the datatype : MPFloat"); //$NON-NLS-1$
        System.out.println("SDPJ approximate significant digits : " + MPFloat.getDefaultNumberOfPrecisionDigits()); //$NON-NLS-1$ 
      }
      if (this.parameterType == null && this.ParameterFile == null) {
        this.parameterType = ParameterType.PARAMETER_MP115_DEFAULT;
      }
    }
    else if (this.unit instanceof EFFloat) {
      if (this.isDisplay == true) {
        System.out.println("\nSDPJ is based on the datatype : EFFloat"); //$NON-NLS-1$
        System.out.println("SDPJ approximate significant digits : " + MPFloat.getDefaultNumberOfPrecisionDigits()); //$NON-NLS-1$ 
      }
      if (this.parameterType == null && this.ParameterFile == null) {
        this.parameterType = ParameterType.PARAMETER_MP115_DEFAULT;
      }
    }
    else if (this.unit instanceof DoubleNumber) {
      DoubleNumber.setDisplayAsZero(false);
      if (this.isDisplay == true) {
        System.out.println("\nSDPJ is based on the datatype : double"); //$NON-NLS-1$
        System.out.println("SDPJ approximate significant digits : 16"); //$NON-NLS-1$
      }
      if (this.parameterType == null && this.ParameterFile == null) {
        this.parameterType = ParameterType.PARAMETER_DEFAULT;
      }
    } else {
//      System.err.println("Please decide a data type correctly!"); //$NON-NLS-1$
      throw new RuntimeException("Please decide a data type correctly!"); //$NON-NLS-1$
    }

    StringBuffer buff = new StringBuffer();
    buff.append("SDPJ start at " + new java.util.Date() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
    buff.append("data      is " + this.ProblemFile); //$NON-NLS-1$
    if (this.isDataSparse) {
      buff.append(" : sparse\n"); //$NON-NLS-1$
    } else {
      buff.append(" : dense\n"); //$NON-NLS-1$
    }
    if (this.ParameterFile != null) {
      buff.append("parameter is " + this.ParameterFile + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
    }
    if (this.SolutionFile != null) {
      buff.append("out       is " + this.SolutionFile + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
    }
    if (this.isInitialFile) {
      if (this.isInitialSparse) {
        buff.append(" : sparse\n"); //$NON-NLS-1$
      } else {
        buff.append(" : dense\n"); //$NON-NLS-1$
      }
    } else {
      buff.append("\n"); //$NON-NLS-1$
    }
    if (this.ParameterFile == null) {
      if (this.parameterType == ParameterType.PARAMETER_DEFAULT) {
        buff.append("set       is Double DEFAULT\n");// << endl; //$NON-NLS-1$
      } else if (this.parameterType == ParameterType.PARAMETER_AGGRESSIVE) {
        buff.append("set       is Double AGGRESSIVE\n");// << endl; //$NON-NLS-1$
      } else if (this.parameterType == ParameterType.PARAMETER_STABLE) {
        buff.append("set       is Double STABLE\n");// << endl; //$NON-NLS-1$
      } else if (this.parameterType == ParameterType.PARAMETER_MP115_DEFAULT) {
        buff.append("set       is MPFloat DEFAULT\n");// << endl; //$NON-NLS-1$
      } else if (this.parameterType == ParameterType.PARAMETER_MP115_STABLE) {
        buff.append("set       is MPFloat STABLE\n");// << endl; //$NON-NLS-1$
      }
    }
    if (this.ProblemFile == null) {
      System.err.println("The solver can not find a SDP problem file!"); //$NON-NLS-1$
      System.exit(0);
    }
    this.Save = new PrintStream(new FileOutputStream(new File(this.SolutionFile)));
    Tools.message(new String(buff), this.Save);
    if (this.isDisplay == true) {
      Tools.message(new String(buff), System.out);
    }
  }

  /**
   * Set the elapsed time of verifying solution
   * 
   * @param time The elapsed time of verifing solution of SDPJ
   */
  public static void setElapsedTime(double time) {
    elapsedTime = time;
  }

  /**
   * Get the elapsed time of verifying solution
   * 
   * @return The elapsed time of verifing solution of SDPJ
   */
  public static double getElapsedTime() {
    return elapsedTime;
  }

  /**
   * If users do not initialize class Sdpj correctly, the function <code>showUsage()</code> will be called to show how to use it correctly.
   */
  public static void showUsage() {
    StringBuffer buff = new StringBuffer();
    buff.append("\n"); //$NON-NLS-1$
    buff.append("************************ Please initialize class Sdpj correctly ***********************\n"); //$NON-NLS-1$
    buff.append("\n"); //$NON-NLS-1$
    buff.append("Usage of the contructor Sdpj(param_1, ..., param_n):\n"); //$NON-NLS-1$ 
    buff.append("Type (1): new Sdpj()\n"); //$NON-NLS-1$
    buff.append("Type (2): new Sdpj(ProblemFile)\n"); //$NON-NLS-1$ 
    buff.append("Type (3): new Sdpj(ProblemFile, SolutionFile)\n"); //$NON-NLS-1$ 
    buff.append("Type (4): new Sdpj(DataType, ProblemFile, SolutinFile)\n"); //$NON-NLS-1$ 
    buff.append("Type (5): new Sdpj(DataType, Precision, ProblemFile, SolutionFile)\n"); //$NON-NLS-1$ 
    buff.append("Type (6): new Sdpj(DataType, Precision, isSparse, ProblemFile, SolutionFile)\n"); //$NON-NLS-1$ 
    buff.append("Type (7): new Sdpj(DataType, Precision, isSparse, ProblemFile, SolutionFile, SetFile, ID)\n"); //$NON-NLS-1$ 
    buff.append("..., and so on.\n\n"); //$NON-NLS-1$ 
    buff.append("Usage of setter function:\n"); //$NON-NLS-1$ 
    buff.append("  ProblemFile: setProblemFile(ProblemFile)\n"); //$NON-NLS-1$ 
    buff.append(" SolutionFile: setSolutionFile(SolutionFile)\n"); //$NON-NLS-1$ 
    buff.append("ParamerteFile: setParameterFile(ParameterFile)\n"); //$NON-NLS-1$ 
    buff.append("  InitialFile: setIntialFile(InitialFile)\n"); //$NON-NLS-1$ 
    buff.append("     DataType: setDataType(DataType)\n"); //$NON-NLS-1$ 
    buff.append("    Precision: setPrecision(Precision)\n"); //$NON-NLS-1$ 
    buff.append("..., and so on.\n\n"); //$NON-NLS-1$ 
    buff.append("\n"); //$NON-NLS-1$ 
    buff.append("Note:\n ProblemFile is String, such as \"sdplib/hinf1.dat-s\"\n"); //$NON-NLS-1$ 
    buff.append(" SolutionFile is String, such as \"sdplib/hinf1.result\"\n"); //$NON-NLS-1$
    buff.append(" ParameterFile is a parameter file which SDPJ should based on \n"); //$NON-NLS-1$
    buff.append(" InitialFile is an initial value for solving SDP problem more efficiently by SDPJ\n"); //$NON-NLS-1$
    buff.append(" DataType is a data type that we should compute based on, is \"new MPFloat(1)\" by default\n"); //$NON-NLS-1$
    buff.append(" Precision is an accuracy, which we should use based on MPFloat, is \"64\" by default\n"); //$NON-NLS-1$
    buff.append(" isSparse is a boolean data type, which just show whether data saved is sparse or not\n"); //$NON-NLS-1$

    buff.append("***************************************************************************************\n"); //$NON-NLS-1$

    System.out.println(new String(buff));
  }

  /**
   * @param isVsdpj isVsdpjを設定します。
   */
  public void setVsdpj(boolean isVsdpj) {
    this.isVsdpj = isVsdpj;
  }

  /**
   * @return isVsdpjを返します。
   */
  public boolean isVsdpj() {
    return this.isVsdpj;
  }

  /**
   * @param vsolution vsolutionを設定します。
   */
  public void setVsolution(Vsolution<RS,RM,CS,CM> vsolution) {
    this.vsolution = vsolution;
  }

  /**
   * @return vsolutionを返します。
   */
  public Vsolution<RS,RM,CS,CM> getVsolution() {
    return this.vsolution;
  }

  /**
   * @param problem problemを設定します。
   */
  public void setProblem(Problem<RS,RM,CS,CM> problem) {
    this.problem = problem;
  }

  /**
   * @return problemを返します。
   */
  public Problem<RS,RM,CS,CM> getProblem() {
    return this.problem;
  }

  /**
   * @param elapsedTIME elapsedTIMEを設定します。
   */
  public void setElapsedTIME(double elapsedTIME) {
    this.elapsedTIME = elapsedTIME;
  }

  /**
   * @return elapsedTIMEを返します。
   */
  public double getElapsedTIME() {
    return this.elapsedTIME;
  }

  /**
   * @param currentPt currentPtを設定します。
   */
  public void setCurrentPt(Solution<RS,RM,CS,CM> currentPt) {
    this.currentPt = currentPt;
  }

  /**
   * @return currentPtを返します。
   */
  public Solution<RS,RM,CS,CM> getCurrentPt() {
    return this.currentPt;
  }

  /**
   * @param solutionInformation solutionInformationを設定します。
   */
  public void setSolutionInformation(SolveInfo<RS,RM,CS,CM> solutionInformation) {
    this.solutionInformation = solutionInformation;
  }

  /**
   * @return solutionInformationを返します。
   */
  public SolveInfo<RS,RM,CS,CM> getSolutionInformation() {
    return this.solutionInformation;
  }

  /**
   * @param solver solverを設定します。
   */
  public void setSolver(Solver<RS,RM,CS,CM> solver) {
    this.solver = solver;
  }

  /**
   * @return solverを返します。
   */
  public Solver<RS,RM,CS,CM> getSolver() {
    return this.solver;
  }
}