Matrix.java
/*
* Created on 2009/11/12
* Copyright (C) 2009 Koga Laboratory. All rights reserved.
*
*/
package org.mklab.sdpj.convert;
import java.util.HashMap;
import java.util.Stack;
import java.util.Vector;
/**
* 行列のような式を扱うクラスです.
*
* @author kai
* @version $Revision$, 2009/12/02
*/
public class Matrix {
/** 行列を一時的に置き換える時に利用するための文字列 */
private static final String REPLACE_STRING = "<#"; //$NON-NLS-1$
/** 行列を一時的に置き換える時に利用する時に割り振る数字 */
private static int number = 0;
/** MaTX */
private static final String MATX = "MATX"; //$NON-NLS-1$
/** Matlab */
private static final String MATLAB = "MATLAB"; //$NON-NLS-1$
/** 値 */
private String value;
/** 部分行列 */
private Vector<Vector<Matrix>> matrix = new Vector<>();
/** 転置であるかどうか */
private boolean transposition = false;
/**
* Matrixを表示します.
*/
public void printMatrix() {
System.out.println(getString());
}
/**
* 文字列として返します.
*
* @return MatrixString
*/
public String getString() {
String matrixString = ""; //$NON-NLS-1$
if (this.getMatrix().isEmpty()) {
return this.getValue();
}
for (int i = 0; i < getRowSize(); i++) {
for (int j = 0; j < getRowColumnSize(i); j++) {
if (getElement(i, j).getValue() != null) {
if (getRowColumnSize(i) == (j + 1)) {
matrixString += getElement(i, j).getValue();
} else {
matrixString += getElement(i, j).getValue() + " "; //$NON-NLS-1$
}
} else {
Matrix subMatrix = new Matrix();
subMatrix.setMatrix(getElement(i, j).getMatrix());
matrixString += "["; //$NON-NLS-1$
subMatrix.printMatrix();
matrixString += "]"; //$NON-NLS-1$
}
}
if (getRowSize() != (i + 1)) {
matrixString += "\n"; //$NON-NLS-1$
}
}
return matrixString;
}
/**
* 行のサイズを返します.
*
* @return rowSize
*/
public int getRowSize() {
return getMatrix().size();
}
/**
* row行目の列のサイズを返します.
*
* @param row 行を指定します
* @return row columnSize
*/
public int getRowColumnSize(int row) {
return getMatrix().get(row).size();
}
/**
* row行,column列の要素を返します.
*
* @param row 行
* @param column 列
* @return Matrix
*/
public Matrix getElement(int row, int column) {
return getMatrix().get(row).get(column);
}
/**
* 行を追加します.
*
* @param rowVector 行
*/
public void addRowVector(Vector<Matrix> rowVector) {
getMatrix().add(rowVector);
}
/**
* @param value valueを設定します。
*/
public void setValue(String value) {
this.value = value;
}
/**
* @return valueを返します。
*/
public String getValue() {
return this.value;
}
/**
* @param matrix matrixを設定します。
*/
public void setMatrix(Vector<Vector<Matrix>> matrix) {
this.matrix = matrix;
}
/**
* @return matrixを返します。
*/
public Vector<Vector<Matrix>> getMatrix() {
return this.matrix;
}
/**
* @param transposition transpositionを設定します。
*/
public void setTransposition(boolean transposition) {
this.transposition = transposition;
}
/**
* @return transpositionを返します。
*/
public boolean isTransposition() {
return this.transposition;
}
/**
* MatrixをMaTX文法に変換します.
*
* @param matrix Matrix
* @return MaTX文法式
*/
public static String matrixToMaTX(Matrix matrix) {
return matrixTo(MATX, matrix);
}
/**
* MatrixをMatlab文法に変換します.
*
* @param matrix Matrix
* @return Matlab文法式
*/
public static String matrixToMatlab(Matrix matrix) {
String matlab = matrixTo(MATLAB, matrix);
// [ と ]の部分をきれいにしているはず
matlab = matlab.replaceAll("\u005D;\\u005B", ";"); //$NON-NLS-1$ //$NON-NLS-2$
matlab = matlab.replaceAll("\u005D;\\u005D", ";]"); //$NON-NLS-1$ //$NON-NLS-2$
matlab = matlab.replaceAll("\u005D\u005D*", "]"); //$NON-NLS-1$ //$NON-NLS-2$
matlab = matlab.replaceAll("\\u005B\\u005B*", "["); //$NON-NLS-1$ //$NON-NLS-2$
return matlab;
}
/**
* Matrixからmatlabもしくは、MaTX文法に変換します
*
* @param formula Matlab文法 or MaTX文法
* @param matrix 行列
* @return 変換行列式
*/
private static String matrixTo(String formula, Matrix matrix) {
String grammer = ""; //$NON-NLS-1$
String tmp = ""; //$NON-NLS-1$
if (matrix.getValue() != null) {
if (formula.equals(MATX)) {
grammer = "[" + matrix.getValue() + "]"; //$NON-NLS-1$//$NON-NLS-2$
// grammer = matrix.getValue();
} else if (formula.equals(MATLAB)) {
grammer = matrix.getValue();
}
return grammer;
}
for (int i = 0; i < matrix.getRowSize(); i++) {
for (int j = 0; j < matrix.getRowColumnSize(i); j++) {
if (matrix.getElement(i, j).getValue() != null) {
//一列の場合
if (matrix.getRowColumnSize(i) == (j + 1)) {
tmp = tmp + matrix.getElement(i, j).getValue();
}
//複数列の場合
else {
tmp = tmp + matrix.getElement(i, j).getValue() + ", "; //$NON-NLS-1$
}
} else {
Matrix subMatrix = new Matrix();
// subMatrix.setMatrix(matrix.getElement(i, j).getMatrix());
subMatrix = matrix.getElement(i, j);
subMatrix.setTransposition(matrix.getElement(i, j).isTransposition());
String tmp2 = ""; //$NON-NLS-1$
if (formula.equals(MATX)) {
tmp2 = matrixTo(MATX, subMatrix);
} else if (formula.equals(MATLAB)) {
tmp2 = matrixTo(MATLAB, subMatrix);
}
//一列の場合
if (matrix.getRowColumnSize(i) == (j + 1)) {
tmp = tmp + tmp2;
}
//複数列の場合
else {
tmp = tmp + tmp2 + ", "; //$NON-NLS-1$
}
}
}
//一行の場合
if (matrix.getRowSize() == 1) {
grammer = tmp;
}
//複数行の場合
else {
if (formula.equals(MATX)) {
grammer = grammer + "[" + tmp + "]"; //$NON-NLS-1$ //$NON-NLS-2$
} else if (formula.equals(MATLAB)) {
grammer = grammer + tmp + ";"; //$NON-NLS-1$
}
}
tmp = ""; //$NON-NLS-1$
}
grammer = "[" + grammer + "]"; //$NON-NLS-1$ //$NON-NLS-2$
if (matrix.isTransposition()) {
grammer = grammer + "'"; //$NON-NLS-1$
}
return grammer;
}
/**
* Matlab文法の行列式をMatX文法に変換します
*
* @param matlabFormula Matlab文法式
* @return MatXFormula
*/
public static String convertMatX(String matlabFormula) {
Matrix matrix = matlabToMatrix(matlabFormula);
String matx = matrixToMaTX(matrix);
return matx;
}
/**
* MaTX文法の行列式をMatlab文法に変換します
*
* @param matxFormula MaTX文法式
* @return MatlabFormula
*/
public static String convertMatlab(String matxFormula) {
Matrix matrix = matxToMatrix(matxFormula);
String matlab = matrixToMatlab(matrix);
return matlab;
}
/**
* Matlab文法をMatrixに変換します.
*
* @param matlabFormula Matlab文法式
* @return Matrix
*/
public static Matrix matlabToMatrix(String matlabFormula) {
String formula = initMatlab(matlabFormula);
return toMatrix(formula);
}
/**
* MaTX文法をMatrixに変換します.
*
* @param matxFormula MaTX文法式
* @return Matrix
*/
public static Matrix matxToMatrix(String matxFormula) {
String formula = initMaTX(matxFormula);
return toMatrix(formula);
}
/**
* MatxもしくはMatlabの文法であった文字列をMatrixに変更します.
*
* @param matlabFormula 文字列
* @return Matrix
*/
public static Matrix toMatrix(String matlabFormula) {
String formula = matlabFormula;
HashMap<String, Matrix> map = new HashMap<>();
Matrix matrix = new Matrix();
boolean transposition = false;
if (formula.endsWith("'")) { //$NON-NLS-1$
formula = formula.substring(0, formula.length() - 1);
transposition = true;
}
if (formula.startsWith("[") == false) { //$NON-NLS-1$
matrix.setValue(formula);
return matrix;
}
Stack<String> stack = new Stack<>();
String element = ""; //$NON-NLS-1$
for (int i = 0; i < formula.length(); i++) {
String charactor = String.valueOf(formula.charAt(i));
if (charactor.equals("]") == false) { //$NON-NLS-1$
stack.push(charactor);
} else {
while (stack.get(stack.size() - 1).equals("[") == false) { //$NON-NLS-1$
if (formula.length() > i + 1 && String.valueOf(formula.charAt(i + 1)) == "'") { //$NON-NLS-1$
element = element + "'"; //$NON-NLS-1$
}
element = stack.pop() + element;
}
stack.pop();
Matrix subMatrix = new Matrix();
String[] row = element.split(";"); //$NON-NLS-1$
for (int rowNumber = 0; rowNumber < row.length; rowNumber++) {
Vector<Matrix> rowVector = new Vector<>();
String[] array = row[rowNumber].trim().split(" "); //$NON-NLS-1$
if (row[rowNumber].trim().equals("") == false) { //$NON-NLS-1$
for (int loop = 0; loop < array.length; loop++) {
Matrix subsubMatrix = new Matrix();
if (array[loop].contains(REPLACE_STRING)) {
subsubMatrix = map.get(array[loop].trim().replace("'", "")); //$NON-NLS-1$ //$NON-NLS-2$
if (array[loop].contains("'")) { //$NON-NLS-1$
subsubMatrix.setTransposition(true);
}
} else {
subsubMatrix.setValue(array[loop].trim());
}
rowVector.add(subsubMatrix);
}
subMatrix.addRowVector(rowVector);
}
}
String key = REPLACE_STRING + getNumber();
map.put(key, subMatrix);
setNumber(getNumber() + 1);
stack.push(key);
element = ""; //$NON-NLS-1$
}
}
matrix = map.get(stack.pop());
matrix.setTransposition(transposition);
return matrix;
}
/**
* Matlab文法式の事前処理
*
* @param matlabFormula Matlab文法式文字列
* @return 事後処理Matlab文法式文字列
*/
private static String initMatlab(String matlabFormula) {
String formula = matlabFormula.replaceAll("\n", ";"); //$NON-NLS-1$ //$NON-NLS-2$
// [ と ]の部分をきれいにしているはず
formula = formula.replaceAll("\u005D;\\u005B", ";"); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll("\u005D;\\u005D", ";]"); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll("\u005D\u005D*", "]"); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll("\\u005B\\u005B*", "["); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll("\t", " "); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll(",", " "); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll(" *", " "); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.trim();
return formula;
}
/**
* MaTX文法式の事前処理
*
* @param matxFormula MaTX文法式文字列
* @return 事後処理MaTX文法式文字列
*/
private static String initMaTX(String matxFormula) {
String formula = matxFormula;
// \u005B = [ (左大かっこ) , \u005D = ] (右大かっこ)
// ](空白*)[ を ];[に置き換えて,相互変換しやすい形に移動
formula = formula.replaceAll("\u005D *\\u005B", "\u005D;\u005B"); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll("\t", " "); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll(",", " "); //$NON-NLS-1$ //$NON-NLS-2$
formula = formula.replaceAll(" *", " "); //$NON-NLS-1$//$NON-NLS-2$
formula = formula.trim();
return formula;
}
/**
* @param number numberを設定します。
*/
public static void setNumber(int number) {
Matrix.number = number;
}
/**
* @return numberを返します。
*/
public static int getNumber() {
return number;
}
}