Sedumi.java

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

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import org.mklab.jmatx.matxengine.MaTXEngine;
import org.mklab.jmatx.matxengine.ParseException;
import org.mklab.matj.parser.statement.symbol.Constant;
import org.mklab.nfc.matrix.DoubleMatrix;


/**
 * mmファイルからjavaファイルを生成し、sedumi形式のデータを生成します。
 * 
 * @author Hiroaki Matsuo
 * @version $Revision$, 2010/01/25
 */
public class Sedumi {

  /**
   * SeDuMi形式で記述されたmmファイルを読み込み、SDPA形式のdatファイルを出力します。
   * 
   * @param mmFile mmファイル
   * @param datFile datファイル
   */
  public void SedumiLoad(String mmFile, String datFile) {
    MaTXEngine engine = new MaTXEngine();

    try {
      engine.load(mmFile);
    } catch (IOException e1) {
      throw new RuntimeException(e1);
    } catch (ParseException e1) {
      throw new RuntimeException(e1);
    }

    final Constant A = (Constant)engine.getVariable("A").getConstant(); //$NON-NLS-1$
    final Constant b = (Constant)engine.getVariable("b").getConstant(); //$NON-NLS-1$
    final Constant c = (Constant)engine.getVariable("c").getConstant(); //$NON-NLS-1$
    final Constant K_s = (Constant)engine.getVariable("K_s").getConstant(); //$NON-NLS-1$
    DoubleMatrix sedumiA = (DoubleMatrix)A.getValue();
    DoubleMatrix sedumib = (DoubleMatrix)b.getValue();
    DoubleMatrix sedumic = (DoubleMatrix)c.getValue();
    final int[] primitiveK_s = toIntArray((DoubleMatrix)K_s.getValue());
    final K k = new K(primitiveK_s);

    final SDPAM sdpam = convertToSedumi(sedumiA, sedumib, sedumic, k);
    try {
      sdpam.save(datFile);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * NFCの {@link DoubleMatrix}をJavaのプリミティブ配列に変換します。
   * 
   * @param matrix 変換する行列
   * @return int型配列
   */
  private int[] toIntArray(DoubleMatrix matrix) {
    final int[] data = new int[matrix.getRowSize() * matrix.getColumnSize()];
    for (int i = 0; i < data.length; i++) {
      data[i] = (int)matrix.getDoubleElement(i + 1);
    }
    return data;
  }

  /**
   * Sedumi形式の引数からYALMIPで扱うSedumi形式を生成します。
   * 
   * @param A A
   * @param b b
   * @param c c
   * @param k K
   * @return SDPAMのインスタンスを返します
   */
  public SDPAM convertToSedumi(DoubleMatrix A, DoubleMatrix b, DoubleMatrix c, K k) {
    double[][] F = new double[A.getRowSize()][A.getColumnSize() + c.getColumnSize()];

    for (int i = 0; i < 1; i++) {
      for (int j = 0; j < A.getRowSize(); j++) {
        F[j][i] = c.getElement(j + 1, i + 1).doubleValue();
      }
    }

    for (int i = 0; i < A.getColumnSize(); i++) {
      for (int j = 0; j < A.getRowSize(); j++) {
        F[j][i + 1] = -A.getElement(j + 1, i + 1).doubleValue();
      }
    }

    double[] d = new double[b.getRowSize()];
    for (int i = 0; i < b.getRowSize(); i++) {
      d[i] = -b.getElement(i + 1).doubleValue();
    }

    Sedumi2Sdpa sedumi = new Sedumi2Sdpa();
    return sedumi.convertToSDPAM(F, d, k);
  }

  /**
   * ASCIIコードのファイルからMMファイルを生成します
   * 
   * @param AFile A
   * @param bFile b
   * @param cFile c
   * @param KsFile Ks
   * @param mmFile mmFile
   */
  public void convertAsciiToMM(String AFile, String bFile, String cFile, String KsFile, String mmFile) {
    try (PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(new File(mmFile))))) {

      pw.print("A=["); //$NON-NLS-1$
      String str1;
      try (BufferedReader br1 = new BufferedReader(new FileReader(AFile))) {
        while ((str1 = br1.readLine()) != null) {
          str1 = str1.trim();
          str1 = str1.replace(" -", ",-"); //$NON-NLS-1$ //$NON-NLS-2$
          pw.println("[" + str1 + "]"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        pw.println("];"); //$NON-NLS-1$
        br1.close();
      }

      pw.print("b=["); //$NON-NLS-1$
      String str2;
      try (BufferedReader br2 = new BufferedReader(new FileReader(bFile))) {
        while ((str2 = br2.readLine()) != null) {
          str2 = str2.trim();
          str2 = str2.replace(" ", ","); //$NON-NLS-1$ //$NON-NLS-2$
          pw.println("[" + str2 + "]"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        pw.println("];"); //$NON-NLS-1$
        br2.close();
      }

      pw.print("c=["); //$NON-NLS-1$
      String str3;
      try (BufferedReader br3 = new BufferedReader(new FileReader(cFile))) {
        while ((str3 = br3.readLine()) != null) {
          str3 = str3.trim();
          str3 = str3.replace(" ", ","); //$NON-NLS-1$ //$NON-NLS-2$
          pw.println("[" + str3 + "]"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        pw.println("];"); //$NON-NLS-1$
        br3.close();
      }

      pw.print("K_s=["); //$NON-NLS-1$
      String str4;
      try (BufferedReader br4 = new BufferedReader(new FileReader(KsFile))) {
        while ((str4 = br4.readLine()) != null) {
          str4 = str4.trim();
          str4 = str4.replaceAll(" ", ","); //$NON-NLS-1$ //$NON-NLS-2$
          pw.println("[" + str4 + "]"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        pw.println("];"); //$NON-NLS-1$
        br4.close();
      }

      pw.close();
    } catch (FileNotFoundException e) {
      throw new RuntimeException(e);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * ASCII形式で保存されているファイルからMファイルを生成するメソッドです
   * 
   * @param AFile A
   * @param bFile b
   * @param cFile c
   * @param KsFile Ks
   * @param mFile mFile
   */
  public void convertAsciiToM(String AFile, String bFile, String cFile, String KsFile, String mFile) {
    try (PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(new File(mFile))))) {

      pw.print("A=["); //$NON-NLS-1$
      String str1;
      try (BufferedReader br1 = new BufferedReader(new FileReader(AFile))) {
        while ((str1 = br1.readLine()) != null) {
          pw.print(str1 + ";"); //$NON-NLS-1$
        }
        pw.println("]"); //$NON-NLS-1$
        br1.close();
      }

      pw.print("b=["); //$NON-NLS-1$
      String str2;
      try (BufferedReader br2 = new BufferedReader(new FileReader(bFile))) {
        while ((str2 = br2.readLine()) != null) {
          pw.print(str2 + ";"); //$NON-NLS-1$
        }
        pw.println("]"); //$NON-NLS-1$
        br2.close();
      }

      pw.print("c=["); //$NON-NLS-1$
      String str3;
      try (BufferedReader br3 = new BufferedReader(new FileReader(cFile))) {
        while ((str3 = br3.readLine()) != null) {
          pw.print(str3 + ";"); //$NON-NLS-1$
        }
        pw.println("]"); //$NON-NLS-1$
        br3.close();
      }

      pw.print("K_s=["); //$NON-NLS-1$
      String str4;
      try (BufferedReader br4 = new BufferedReader(new FileReader(KsFile))) {
        while ((str4 = br4.readLine()) != null) {
          pw.print(str4 + ";"); //$NON-NLS-1$
        }
        pw.println("]"); //$NON-NLS-1$
        br4.close();
      }

      pw.close();
    } catch (FileNotFoundException e) {
      throw new RuntimeException(e);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * MファイルをMMファイルに変換するメソッドです。
   * 
   * @param mFile Mファイル
   * @param mmFile MMファイル
   */
  public void convertToMM(String mFile, String mmFile) {
    try (BufferedReader br = new BufferedReader(new FileReader(mFile)); PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(new File(mmFile))))) {

      String str;
      String matxCode = ""; //$NON-NLS-1$

      while ((str = br.readLine()) != null) {
        String[] params = str.split("="); //$NON-NLS-1$
        matxCode = params[0] + " = "; //$NON-NLS-1$

        if (params[1].trim().startsWith("-")) { //$NON-NLS-1$
          String temp = params[1].trim().substring(1, params[1].length());
          matxCode += "-" + Matrix.convertMatX(temp) + ";"; //$NON-NLS-1$ //$NON-NLS-2$
        } else {
          matxCode += Matrix.convertMatX(params[1].trim()) + ";"; //$NON-NLS-1$
        }

        pw.println(matxCode);
      }

      pw.close();
      br.close();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * メインメソッドです。
   * 
   * @param args コマンドライン引数
   */
  public static void main(String[] args) {
    Sedumi sedumi = new Sedumi();

    String dir2 = "1"; //$NON-NLS-1$
    String dir = "SDPLIB_ASCII/hinf" + dir2; //$NON-NLS-1$
    String AFile = dir + "/A.txt"; //$NON-NLS-1$
    String bFile = dir + "/b.txt"; //$NON-NLS-1$
    String cFile = dir + "/c.txt"; //$NON-NLS-1$
    String KsFile = dir + "/Ks.txt"; //$NON-NLS-1$
    String mmFile = "hinf10.mm"; //$NON-NLS-1$
    String datFile = "hinf" + dir2 + "sedumi.dat-s"; //$NON-NLS-1$ //$NON-NLS-2$

    sedumi.convertAsciiToMM(AFile, bFile, cFile, KsFile, mmFile);
    System.out.println(datFile + "を生成中です。"); //$NON-NLS-1$
    sedumi.SedumiLoad(mmFile, datFile);
    System.out.println("ファイルが生成されました。"); //$NON-NLS-1$
  }
}