SDPAM.java

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

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.scalar.AbstractScalar;


/**
 * SDPA-M形式のデータを表すクラスです。
 * 
 * @author Hiroaki Matsuo
 * @version $Revision$, 2010/01/20
 */
public class SDPAM {

  /** */
  private int mDIM;
  /** */
  private int nBLOCK;
  /** */
  private List<Integer> bLOCKsTRUCT;
  /** */
  private double[] c;
  /** */
  private DoubleMatrix[][] sdpamF;

  /**
   * 新しく生成された{@link SDPAM}オブジェクトを初期化します。
   * 
   * @param mDIM mDIM
   * @param nBLOCK nBLOCK
   * @param bLOCKsTRUCT bLOCKsTRUCT
   * @param c c
   * @param sdpamF sdpamF
   */
  public SDPAM(int mDIM, int nBLOCK, List<Integer> bLOCKsTRUCT, double[] c, DoubleMatrix[][] sdpamF) {
    this.mDIM = mDIM;
    this.nBLOCK = nBLOCK;
    this.bLOCKsTRUCT = bLOCKsTRUCT;
    this.c = c;
    this.sdpamF = sdpamF;
    AbstractScalar.setDefaultFormat("%.16E"); //$NON-NLS-1$
  }

  /**
   * ファイルに保存します。
   * 
   * @param output 出力先ファイル
   * @throws IOException ファイルを参照できない場合
   */
  public void save(File output) throws IOException {
    try (final BufferedWriter writer = new BufferedWriter(new FileWriter(output))) {
      writer.write(getSDPADatString("%g")); //$NON-NLS-1$
      writer.close();
    }
  }

  /**
   * ファイルに保存します。
   * 
   * @param fileName ファイル名
   * @throws IOException ファイルを参照できない場合
   */
  public void save(String fileName) throws IOException {
    if (fileName.endsWith(".dat-s")) { //$NON-NLS-1$
      save(new File(fileName), getSDPADatSString());
    } else {
      save(new File(fileName), getSDPADatString("%g")); //$NON-NLS-1$
    }
  }

  /**
   * ファイルに保存します。
   * 
   * @param file ファイル
   * @param context context
   * @throws IOException ファイルを参照できない場合
   */
  private void save(File file, String context) throws IOException {
    try (final BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
      writer.write(context);
      writer.close();
    }
  }

  /**
   * SDPADat-s形式の文字列を返します
   * 
   * @return SDPA-DAT-s形式の文字列
   */
  public String getSDPADatSString() {
    final StringWriter sw = new StringWriter();
    try (final PrintWriter pw = new PrintWriter(new BufferedWriter(sw))) {

      pw.print(this.mDIM);
      pw.println("=mDIM"); //$NON-NLS-1$
      pw.print(this.nBLOCK);
      pw.println("=nBLOCK"); //$NON-NLS-1$

      if (this.bLOCKsTRUCT.size() > 1) {
        pw.print("("); //$NON-NLS-1$
        for (int i = 0; i < this.bLOCKsTRUCT.size(); i++) {
          pw.print(this.bLOCKsTRUCT.get(i));
          if (i == this.bLOCKsTRUCT.size() - 1) {
            pw.print(")"); //$NON-NLS-1$
          } else {
            pw.print(","); //$NON-NLS-1$
          }
        }
      } else {
        pw.print(this.bLOCKsTRUCT.get(0));
      }

      pw.println("=bLOCKsTRUCT"); //$NON-NLS-1$
      pw.print("{"); //$NON-NLS-1$

      for (int i = 0; i < this.c.length; i++) {
        pw.print(this.c[i]);
        if (i == this.c.length - 1) {
          pw.println("}"); //$NON-NLS-1$
        } else {
          pw.print(","); //$NON-NLS-1$
        }
      }

      int x = this.sdpamF[0].length;
      int y = this.sdpamF.length;

      for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
          DoubleMatrix F = this.sdpamF[j][i];
          for (int row = 1; row <= F.getRowSize(); row++) {
            for (int column = row; column <= F.getColumnSize(); column++) {
              if (F.getElement(row, column).doubleValue() != 0) {
                pw.print(i);
                pw.print(" "); //$NON-NLS-1$
                pw.print(j + 1);
                pw.print(" "); //$NON-NLS-1$
                pw.print(row);
                pw.print(" "); //$NON-NLS-1$
                pw.print(column);
                pw.print(" "); //$NON-NLS-1$
                pw.println(String.valueOf(F.getElement(row, column)).replace("E", "e")); //$NON-NLS-1$ //$NON-NLS-2$
              }
            }
          }
        }
      }

      pw.close();
    }

    return sw.toString();
  }

  /**
   * SDPA-DAT形式の文字列を返します。
   * 
   * @param realNumberFormat 実数の表示フォーマット
   * @return SDPA-DAT形式の文字列
   */
  public String getSDPADatString(String realNumberFormat) {
    final StringWriter sw = new StringWriter();
    try (final PrintWriter pw = new PrintWriter(new BufferedWriter(sw))) {

      pw.print(this.mDIM);
      pw.println("=mDIM"); //$NON-NLS-1$
      pw.print(this.nBLOCK);
      pw.println("=nBLOCK"); //$NON-NLS-1$

      if (this.bLOCKsTRUCT.size() > 1) {
        pw.print("("); //$NON-NLS-1$
        for (int i = 0; i < this.bLOCKsTRUCT.size(); i++) {
          pw.print(this.bLOCKsTRUCT.get(i));
          if (i == this.bLOCKsTRUCT.size() - 1) {
            pw.print(")"); //$NON-NLS-1$
          } else {
            pw.print(","); //$NON-NLS-1$
          }
        }
      } else {
        pw.print(this.bLOCKsTRUCT.get(0));
      }

      pw.println("=bLOCKsTRUCT"); //$NON-NLS-1$
      pw.print("{"); //$NON-NLS-1$

      for (int i = 0; i < this.c.length; i++) {
        pw.print(this.c[i]);
        if (i == this.c.length - 1) {
          pw.println("}"); //$NON-NLS-1$
        } else {
          pw.print(","); //$NON-NLS-1$
        }
      }
      int y = this.sdpamF.length;
      int x = this.sdpamF[0].length;

      for (int i = 0; i < x; i++) {
        if (y > 1) {
          pw.println("{"); //$NON-NLS-1$
        }
        for (int j = 0; j < y; j++) {
          if (this.bLOCKsTRUCT.get(j).intValue() > 1) {
            pw.print("{"); //$NON-NLS-1$
          }
          DoubleMatrix F = this.sdpamF[j][i];
          for (int row = 1; row <= F.getRowSize(); row++) {
            pw.print("{"); //$NON-NLS-1$
            for (int column = 1; column <= F.getColumnSize(); column++) {
              pw.print(F.getElement(row, column).toString(realNumberFormat));
              if (column == F.getColumnSize()) {
                pw.print("}"); //$NON-NLS-1$
              } else {
                pw.print(","); //$NON-NLS-1$
              }
            }

            if (row == F.getRowSize()) {
              if (this.bLOCKsTRUCT.get(j).intValue() > 1) {
                pw.println("}"); //$NON-NLS-1$
              } else {
                pw.println(""); //$NON-NLS-1$
              }

            } else {
              pw.print(","); //$NON-NLS-1$
            }
          }
        }
        if (y > 1) {
          pw.println("}"); //$NON-NLS-1$
        }
      }
      pw.close();
    }

    return sw.toString();
  }

  /**
   * DIMの値を取得します
   * 
   * @return mDIM
   */
  public int getmDIM() {
    return this.mDIM;
  }

  /**
   * nBLOCKの値を取得します
   * 
   * @return nBLOCK
   */
  public int getnBLOCK() {
    return this.nBLOCK;
  }

  /**
   * bLOCKsTRUCTの値を取得します
   * 
   * @return bLOCKsTRUCT
   */
  public List<Integer> getbLOCKsTRUCT() {
    return this.bLOCKsTRUCT;
  }

  /**
   * cの値を取得します
   * 
   * @return c
   */
  public double[] getC() {
    return this.c;
  }

  /**
   * SdpamFの値を取得します
   * 
   * @return sdpamF
   */
  public DoubleMatrix[][] getSdpamF() {
    return this.sdpamF;
  }
}