Sdplib.java

/*
 * Created on 2010/09/09
 * Copyright (C) 2010 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.sdpj.benchmark;

import java.io.IOException;

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.solver.Sdpj;


/**
 * Class <tt> Sdplib </tt> is designed to run <code>SDPJ</code> or <code>VSDPJ</code> automatically for solving all 
 * of problems of <i>SDPLIB1.2</i>. More detail information about usage of <code>SDPJ</code> or <code>VSDPJ</code>, you can 
 * refer to Class {@link org.mklab.sdpj.solver.Sdpj <tt>Sdpj</tt>}. 
 * 
 * <br><br>
 * The details usage of class <code>Sdplib</code> is introduced as follows:
 * <blockquote><tt>
 *  Example:<br><br>
 *        //Testing SDPJ by solving problems "hinf" of sdplib<br>
 *        <code>Sdplib sdpj = new test(); // default solver of class Sdplib is SDPJ. </code><br>
 *        <code>sdpj.runTest("hinf");</code><br>
 *        <br>
 *        //Testing SDPJ by solving problems "hinf" of sdplib<br>
 *        <code>Sdplib sdpj = new test("sdpj");</code><br>
 *        <code>sdpj.runTest("hinf");</code><br>
 *       <br>
 *        //Testing VSDPJ by solving problems "hinf" of sdplib<br>
 *        <code>Sdplib vsdpj = new test("vsdpj");</code><br>
 *        <code>vsdpj.runTest("hinf");</code><br>
 *       <br>
 *       .... <br>
 *       etc. Testing <code>SDPJ</code> can use all problems of sdplib can be tested  automatically. 
 * </tt></blockquote>
 *   when you use class <code>Sdplib</code> to test <code>SDPJ</code> or <code>VSDPJ</code>, if you want to change some 
 *   setting, as for parameter setting, please refer the codes of class <code>Sdplib</code>. The default settings of 
 *   class <code>Sdplib</code> are multiple precision arithmetic based on MPFloat using precision <code>77</code> 
 *   and the default stable parameter setting based on multiple precision arithmetic. At last, if you want to know about 
 *   what is <i>SDPLIB1.2</i>, please refer to web site:
 *   <a href = "http://euler.nmt.edu/~brian/sdplib/sdplib.html" style=text-decoration:none>
 *   <tt>http://euler.nmt.edu/~brian/sdplib/sdplib.html</tt></a>.<br><br>
 *   
 *   <br>
 * 
 * 
 * @author wu
 * @version 0.1.2, 2012/01/16 
 * @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 Sdplib<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>> {

  //define the switch parameters to control program 
  //for solving all sorts of problems of sdplib.
  /**switch of problems of hinf */
  private boolean isHinf;
  /**switch of problems of arch */
  private boolean isArch;
  /**switch of problems of gpp */
  private boolean isGpp;
  /**switch of problems of infp */
  private boolean isInfp;
  /**switch of problems of infd */
  private boolean isInfd;
  /**switch of problems of maxG */
  private boolean isMaxg;
  /**switch of problems of mcp */
  private boolean isMcp;
  /**switch of problems of gap */
  private boolean isQap;
  /**switch of problems of qpg */
  private boolean isQpg;
  /**switch of problems of ss */
  private boolean isSs;
  /**switch of problems of theta */
  private boolean isTheta;
  /**switch of problems of thetag */
  private boolean isThetag;
  /**switch of problems of truss */
  private boolean isTruss;
  /**switch of problems of equalg */
  private boolean isEqualg;
  /**switch of problems of control */
  private boolean isControl;

  //define the path of data file  
  /**base path of testing problem files */
  private final  String folder = "sdplib/"; //$NON-NLS-1$
  /**path of problem files of hinf */
  private final  String hinf = this.folder + "hinf0.dat-s"; //$NON-NLS-1$
  /**path of problem files of arch  */
  private final  String arch = this.folder + "arch0.dat-s"; //$NON-NLS-1$
  /**path of problem files of gpp */
  private final  String gpp = this.folder + "gpp0.dat-s"; //$NON-NLS-1$
  /**path of problem files of infp */
  private final  String infp = this.folder + "infp0.dat-s"; //$NON-NLS-1$
  /**path of problem files of infd */
  private final  String infd = this.folder + "infd0.dat-s"; //$NON-NLS-1$
  /**path of problem files of maxG */
  private final  String maxG = this.folder + "maxG0.dat-s"; //$NON-NLS-1$
  /**path of problem files of mcp */
  private final  String mcp = this.folder + "mcp0.dat-s"; //$NON-NLS-1$
  /**path of problem files of qap */
  private final  String gap = this.folder + "qap0.dat-s"; //$NON-NLS-1$
  /**path of problem files of qpg */
  private final  String qpG = this.folder + "qpG0.dat-s"; //$NON-NLS-1$
  /**path of problem files of ss */
  private final  String ss = this.folder + "ss30.dat-s"; //$NON-NLS-1$
  /**path of problem files of theta */
  private final  String theta = this.folder + "theta0.dat-s"; //$NON-NLS-1$
  /**path of problem files of thetag */
  private final  String thetaG = this.folder + "thetaG0.dat-s"; //$NON-NLS-1$
  /**path of problem files of truss */
  private final  String truss = this.folder + "truss0.dat-s"; //$NON-NLS-1$
  /**path of problem files of equalg */
  private final  String equalG = this.folder + "equalG0.dat-s"; //$NON-NLS-1$
  /**path of problem files of control */
  private final  String control = this.folder + "control0.dat-s"; //$NON-NLS-1$

  //define the temporal parameters
  /**path of problem file solved*/
  private String problem; 
  /**replace target string for changing problem file name  */
  private String target; 
  /**unit based on data type */
  private RS unit;
  /**precision of numerical arithmetic */
  private int precision;
  /**define solver, which is "SDPJ" or "VSDPJ" */
  private String solver;

  
//  /**
//   * 新しく生成された<code>Sdplib</code>オブジェクトを初期化します。
//   */
//  @SuppressWarnings("unchecked")
//  public Sdplib() {
//    //Initialize a data type
//    this.unit = new MPFloat(1);
//    this.solver = "sdpj"; //$NON-NLS-1$
//    this.setInitialization(); 
//  }

  
//  /**
//   * 新しく生成された<code>Sdplib</code>オブジェクトを初期化します。
//   * @param solver name of solver, which is "SDPJ" or "VSDPJ"
//   */
//  @SuppressWarnings("unchecked")
//  public Sdplib(String solver) {
//    //Initialize a data type
//    this.unit = new MPFloat(1);
//    this.solver = solver; 
//    this.setInitialization(); 
//  }

  
  /**
   * 新しく生成された<code>Sdplib</code>オブジェクトを初期化します。
   * @param unit unit based on data type used
   */
  public Sdplib(RS unit) { 
    //Initialize a data type
     this.unit = unit;
     this.solver = "sdpj"; //$NON-NLS-1$
     this.setInitialization(); 
  }

  /**
   * 新しく生成された<code>Sdplib</code>オブジェクトを初期化します。
   * @param unit unit based on data type used
   * @param solver name of solver, which is "SDPJ" or "VSDPJ"
   */
  public Sdplib(RS unit, String solver) {
    //Initialize a data type
    this.unit = unit;
    this.solver = solver; 
    this.setInitialization(); 
  }
  
  /**
   * set a base initialization of setting.
   */
  private void setInitialization() {
    this.precision = 77;
    this.initializeSwitch();
  }
  
  
  /**
   * initialize the switches of problems, which should be solved.
   */
  private void initializeSwitch() {
    //Initialize switches of testing problems. 
    this.isHinf = false;
    this.isArch = false;
    this.isGpp = false;
    this.isInfp = false;
    this.isInfd = false;
    this.isMaxg = false;
    this.isMcp = false;
    this.isQap = false;
    this.isQpg = false;
    this.isSs = false;
    this.isTheta = false;
    this.isThetag = false;
    this.isTruss = false;
    this.isEqualg = false;
    this.isControl = false;
  }
  
  /**
   * NOTE: if you don't know what meaning is for the hinf,arch,etc.
   * please refer to web: http://euler.nmt.edu/~brian/sdplib/sdplib.html
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合 is input or output exception
   */
  public void runTest(String name) throws IOException {
    this.testHinf(name);        //test problem hinf
    this.testArch(name);        //test problem arch
    this.testGpp(name);         //test problem gpp
    this.testInfp(name);        //test problem infp
    this.testInfd(name);        //test problem infd
    this.testMaxG(name);        //test problem maxG
    this.testMcp(name);         //test problem mcp
    this.testGap(name);         //test problem qap
    this.testQpG(name);         //test problem qpG
    this.testSs(name);          //test problem ss
    this.testTheta(name);       //test problem theta
    this.testThetaG(name);      //test problem thetaG
    this.testTruss(name);       //test problem truss
    this.testEqualG(name);      //test problem equalG
    this.testControl(name);     //test problem control
  }

  /**
   * solve the problem of sdplib by SDPJ
   * 
   * @param replacement replace string
   * @throws IOException 読み込めない場合
   */
  private void run(String replacement) throws IOException {
    this.problem = this.problem.replaceAll(this.target, replacement);
    if (this.unit instanceof MPFloat) {
       if (this.solver.toLowerCase().equals("sdpj") == true) {  //$NON-NLS-1$
          Sdpj<RS,RM,CS,CM> sdpj = new Sdpj<>(this.unit, this.problem);
          sdpj.setParameterType(ParameterType.PARAMETER_MP115_STABLE);
          sdpj.setPrecision(this.precision);
          sdpj.run();
       }else {
         System.err.println("Please decide a solver(\"SDPJ\" or \"VSDPJ\") correctly!"); //$NON-NLS-1$
         System.exit(0);
       }
    }else if (this.unit instanceof DoubleNumber) {
      if (this.solver.toLowerCase().equals("sdpj") == true) { //$NON-NLS-1$
          Sdpj<RS,RM,CS,CM> sdpj = new Sdpj<>(this.unit, this.problem);
          sdpj.setParameterType(ParameterType.PARAMETER_DEFAULT);
          sdpj.run();
      }else {
          System.err.println("Please decide a solver(\"SDPJ\" or \"VSDPJ\") correctly!"); //$NON-NLS-1$
          System.exit(0);
      }
    }else {
      System.err.println("Please decide a data type correctly!"); //$NON-NLS-1$
      System.exit(0);
    }
  }

  /**
   * test solver SDPJ with using problems of hinf
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private void testHinf(String name) throws IOException {
    if (name.toLowerCase().equals("hinf") == true) { //$NON-NLS-1$
      this.isHinf = true;
    }
    if (this.isHinf == true) {
      this.problem = this.hinf;
      for (Integer i = 0; i < 15;) {
        this.target = (i++).toString();
        this.run(i.toString());
      }
    }
  }

  /**
   * test solver SDPJ with using problems of arch
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private void testArch(String name) throws IOException {
    if (name.toLowerCase().equals("arch") == true) { //$NON-NLS-1$
      this.isArch = true;
    }
    if (this.isArch == true) {
      this.problem = this.arch;
      this.target = "0"; //$NON-NLS-1$
      for (Integer i = 0; i <= 8; i += 2) {
        if (i != 6) {
          this.run(i.toString());
          this.target = i.toString();
        }
      }
    }
  }

  /**
   * test solver SDPJ with using problems of gpp
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private  void testGpp(String name) throws IOException {
    if (name.toLowerCase().equals("gpp") == true) { //$NON-NLS-1$
      this.isGpp = true;
    }
    if (this.isGpp == true) {
      this.problem = this.gpp;
      this.target = "0"; //$NON-NLS-1$
      String replacement = "100"; //$NON-NLS-1$
      for (Integer i = 0; i < 13; i++) {
        if (i == 0) {
          this.run(replacement);
          this.target = replacement;
        }
        if (i > 0 && i <= 4) {
          replacement = "124-" + i.toString(); //$NON-NLS-1$
          this.run(replacement);
          this.target = replacement;
        }
        if (i > 4 && i <= 8) {
          replacement = "250-" + Integer.valueOf(i - 4).toString(); //$NON-NLS-1$
          this.run(replacement);
          this.target = replacement;
        }
        if (i > 8 && i <= 12) {
          replacement = "500-" + Integer.valueOf(i - 8).toString(); //$NON-NLS-1$
          this.run(replacement);
          this.target = replacement;
        }
      }
    }
  }

  /**
   * test solver SDPJ with using problems of infp
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private void testInfp(String name) throws IOException {
    if (name.toLowerCase().equals("infp") == true) { //$NON-NLS-1$
      this.isInfp = true;
    }
    if (this.isInfp == true) {
      this.problem = this.infp;
      for (Integer i = 0; i < 2;) {
        this.target = (i++).toString();
        this.run(i.toString());
      }
    }
  }

  /**
   * test solver SDPJ with using problems of infd
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private  void testInfd(String name) throws IOException {
    if (name.toLowerCase().equals("infd") == true) { //$NON-NLS-1$
      this.isInfd = true;
    }
    if (this.isInfd == true) {
      this.problem = this.infd;
      for (Integer i = 0; i < 2;) {
        this.target = (i++).toString();
        this.run(i.toString());
      }
    }
  }

  /**
   * test solver SDPJ with using problems of maxG
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  private void testMaxG(String name) throws IOException {
    if (name.toLowerCase().equals("maxG") == true) { //$NON-NLS-1$
      this.isMaxg = true;
    }
    if (this.isMaxg == true) {
      this.problem = this.maxG;
      this.target = "0"; //$NON-NLS-1$
      String replacement = ""; //$NON-NLS-1$
      for (int i = 0; i < 5; i++) {
        switch (i) {
          case 0:
            replacement = "11";break;//$NON-NLS-1$
          case 1:
            replacement = "32";break;//$NON-NLS-1$
          case 2:
            replacement = "51";break;//$NON-NLS-1$
          case 3:
            replacement = "55";break; //$NON-NLS-1$
          case 4:
            replacement = "60";break;//$NON-NLS-1$
          default:
            break;
        }
        this.run(replacement);
        this.target = replacement;
      }
    }
  }

  /**
   * test solver SDPJ with using problems of mcp
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private void testMcp(String name) throws IOException {
    if (name.toLowerCase().equals("mcp") == true) { //$NON-NLS-1$
      this.isMcp = true;
    }
    if (this.isMcp == true) {
      this.problem = this.mcp;
      this.target = "0"; //$NON-NLS-1$
      String replacement = "100"; //$NON-NLS-1$
      for (Integer i = 0; i < 13; i++) {
        if (i == 0) {
          this.run(replacement);
          this.target = replacement;
        }
        if (i > 0 && i <= 4) {
          replacement = "124-" + i.toString(); //$NON-NLS-1$
          this.run(replacement);
          this.target = replacement;
        }
        if (i > 4 && i <= 8) {
          replacement = "250-" + Integer.valueOf(i - 4).toString(); //$NON-NLS-1$
          this.run(replacement);
          this.target = replacement;
        }
        if (i > 8 && i <= 12) {
          replacement = "500-" + Integer.valueOf(i - 8).toString(); //$NON-NLS-1$
          this.run(replacement);
          this.target = replacement;
        }
      }
    }
  }

  /**
   * test solver SDPJ with using problems of qap
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private void testGap(String name) throws IOException {
    if (name.toLowerCase().equals("qap") == true) { //$NON-NLS-1$
      this.isQap = true;
    }
    if (this.isQap == true) {
      this.problem = this.gap;
      this.target = "0"; //$NON-NLS-1$
      for (Integer i = 5; i <= 10; i++) {
        this.run(i.toString());
        this.target = i.toString();
      }
    }
  }

  /**
   * test solver SDPJ with using problems of qpg
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  private void testQpG(String name) throws IOException {
    if (name.toLowerCase().equals("qpg") == true) { //$NON-NLS-1$
      this.isQpg = true;
    }
    if (this.isQpg) {
      this.problem = this.qpG;
      this.target = "0"; //$NON-NLS-1$
      String replacement = "11"; //$NON-NLS-1$
      this.run(replacement);
      this.target = replacement;
      replacement = "51"; //$NON-NLS-1$
      this.run(replacement);
    }
  }

  /**
   * test solver SDPJ with using problems of ss
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  private void testSs(String name) throws IOException {
    if (name.toLowerCase().equals("ss") == true) { //$NON-NLS-1$
      this.isSs = true;
    }
    if (this.isSs == true) {
      this.problem = this.ss;
      this.target = ""; //$NON-NLS-1$
      this.run(this.target); 
    }
  }

  /**
   * test solver SDPJ with using problems of theta
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private void testTheta(String name) throws IOException {
    if (name.toLowerCase().equals("theta") == true) { //$NON-NLS-1$
      this.isTheta = true;
    }
    if (this.isTheta == true) {
      this.problem = this.theta;
      for (Integer i = 0; i < 6;) {
        this.target = (i++).toString();
        this.run(i.toString());
      }
    }
  }

  /**
   * test solver SDPJ with using problems of thetag
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  private  void testThetaG(String name) throws IOException {
    if (name.toLowerCase().equals("thetag") == true) { //$NON-NLS-1$
      this.isThetag = true;
    }
    if (this.isThetag == true) {
      this.problem = this.thetaG;
      this.target = "0"; //$NON-NLS-1$
      String replacement = "11"; //$NON-NLS-1$
      this.run(replacement);
      this.target = replacement;
      replacement = "51"; //$NON-NLS-1$
      this.run(replacement);
    }
  }

  /**
   * test solver SDPJ with using problems of truss
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private  void testTruss(String name) throws IOException {
    if (name.toLowerCase().equals("truss") == true) { //$NON-NLS-1$
      this.isTruss = true;
    }
    if (this.isTruss == true) {
      this.problem = this.truss;
      for (Integer i = 0; i < 8;) {
        this.target = (i++).toString();
        this.run(i.toString());
      }
    }
  }

  /**
   * test solver SDPJ with using problems of equal
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  private void testEqualG(String name) throws IOException {
    if (name.toLowerCase().equals("equalg") == true) { //$NON-NLS-1$
      this.isEqualg = true;
    }
    if (this.isEqualg == true) {
      this.problem = this.equalG;
      this.target = "0"; //$NON-NLS-1$
      String replacement = "11"; //$NON-NLS-1$
      this.run(replacement);
      this.target = replacement;
      replacement = "51"; //$NON-NLS-1$
      this.run(replacement);
    }
  }

  /**
   * test solver SDPJ with using problems of control
   * 
   * @param name name of problem folder
   * @throws IOException 読み込めない場合
   */
  @SuppressWarnings("boxing")
  private void testControl(String name) throws IOException {
    if (name.toLowerCase().equals("control") == true) { //$NON-NLS-1$
      this.isControl = true;
    }
    if (this.isControl == true) {
      this.problem = this.control;
      for (Integer i = 0; i < 11;) {
        this.target = (i++).toString();
        this.run(i.toString());
      }
    }
  }

  /**
   * @param unit unitを設定します。
   */
  public void setUnit(RS unit) {
    this.unit = unit;
  }

  /**
   * @return unitを返します。
   */
  public RS getUnit() {
    return this.unit;
  }

  /**
   * @param precision precisionを設定します。
   */
  public void setPrecision(int precision) {
    this.precision = precision;
  }

  /**
   * @return precisionを返します。
   */
  public int getPrecision() {
    return this.precision;
  }


  /**
   * @param solver solverを設定します。
   */
  public void setSolver(String solver) {
    this.solver = solver;
  }


  /**
   * @return solverを返します。
   */
  public String getSolver() {
    return this.solver;
  }

}