SparceStringMatrix.java
/*
* Created on 2004/02/04
* Copyright (C) 2004 Koga Laboratory. All rights reserved.
*/
package org.mklab.tool.control.system.graph;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import org.mklab.nfc.matrix.AbstractGrid;
import org.mklab.nfc.matrix.IntMatrix;
/**
* 文字列を成分とする疎な行列を表現するクラスです。
*
* @author Yusuke Tsutsui
* @version $Revision: 1.10 $, 2006/11/03
*/
public class SparceStringMatrix extends AbstractGrid<SparceStringMatrix> {
/** シリアル番号 */
private static final long serialVersionUID = 152527032306625817L;
/** 行列の成分 */
private Map<Position, String> elementMap = new HashMap<>();
/**
* 0x0の文字列行列を生成します。
*/
public SparceStringMatrix() {
this(0, 0);
}
// /**
// * コンストラクター
// *
// * @param matrix
// * 文字列で構成された伝達関数行列
// */
// public SparceStringMatrix(final SparceStringMatrix matrix) {
// this.rowSize = matrix.rowSize;
// this.columnSize = matrix.columnSize;
//
// for (int row = 1; row <= matrix.rowSize; row++) {
// for (int column = 1; column <= matrix.columnSize; column++) {
// setElement(row, column, matrix.getElement(row, column));
// }
// }
// }
/**
* <code>elements</code>で与えられた成分をもつ行ベクトルを生成します。
*
* @param elements {@link String}の配列
*/
public SparceStringMatrix(final String[] elements) {
this(new String[][] {elements});
}
/**
* コンストラクター
*
* @param rowSize 行の数
* @param columnSize 列の数
*/
public SparceStringMatrix(final int rowSize, final int columnSize) {
this(new String[rowSize][columnSize]);
}
/**
* <code>elements</code>で与えられた成分をもつ文字列行列を生成します。
*
* @param elements {@link String}の2次元配列
*/
public SparceStringMatrix(final String[][] elements) {
super(elements.length, elements.length == 0 ? 0 : elements[0].length);
//this.rowSize = elements.length;
//this.columnSize = getRowSize() == 0 ? 0 : elements[0].length;
for (int row = 1; row <= getRowSize(); row++) {
String[] rowMatrix = elements[row - 1];
for (int column = 1; column <= getColumnSize(); column++) {
setElement(row, column, rowMatrix[column - 1]);
}
}
}
/**
* <code>row</code>行<code>column</code>列の成分を返します。
*
* @param row 行番号
* @param column 列番号
* @return (row,column)成分
*/
public String getElement(final int row, final int column) {
Position pos = new Position(row, column);
if (this.elementMap.containsKey(pos)) {
return this.elementMap.get(pos);
}
return ""; //$NON-NLS-1$
}
/**
* 指定した位置に値が入っているか判定します。
*
* @param row 行番号
* @param column 列番号
* @return 指定した位置に値が入っていればtrue、入っていなければfalse
*/
public boolean hasElement(final int row, final int column) {
if (this.elementMap.containsKey(new Position(row, column))) {
return true;
}
return false;
}
/**
* 指定した位置に値を設定します。
*
* @param row 行番号
* @param column 列番号
* @param value (row,column)に設定する {@link String}
*/
public void setElement(final int row, final int column, final String value) {
Position pos = new Position(row, column);
if (value == null || value.equals("")) { //$NON-NLS-1$
this.elementMap.remove(pos);
} else {
this.elementMap.put(pos, value);
}
}
/**
* @see org.mklab.nfc.matrix.Grid#printElements(java.io.Writer)
*/
@Override
public void printElements(final Writer output) {
int maxColumnSize = Integer.MAX_VALUE;
printElements(output, maxColumnSize);
}
/**
* @see org.mklab.nfc.matrix.Grid#printElements(java.io.Writer, int)
*/
@Override
public void printElements(final Writer output, final int maxColumnSize) {
final PrintWriter pw = new PrintWriter(output);
int elementWidth = 0;
for (int row = 1; row <= getRowSize(); row++) {
for (int column = 1; column <= getColumnSize(); column++) {
elementWidth = Math.max(elementWidth, getElement(row, column).length());
}
}
elementWidth++;
for (int row = 1; row <= getRowSize(); row++) {
for (int column = 1; column <= getColumnSize(); column++) {
String element = getElement(row, column);
int cur;
if (element.equals("")) { //$NON-NLS-1$
pw.print("\"\""); //$NON-NLS-1$
cur = 2;
} else {
pw.print(element);
cur = element.length();
}
for (int k = cur; k < elementWidth; k++) {
pw.print(" "); //$NON-NLS-1$
}
}
pw.println();
}
pw.println();
pw.flush();
}
/**
* 指定されたノードを削除した文字列行列を返します。
*
* @param node 削除対象のノード
* @return 削除対象ノードを削除した文字列行列
*/
public SparceStringMatrix removeNode(final int node) {
return removeRowAndColumn(node);
}
/**
* 指定された行と列を削除した文字列行列を返します。
*
* @param n 削除対象の行番号、列番号
* @return 指定された行と列を削除した文字列行列
*/
public SparceStringMatrix removeRowAndColumn(final int n) {
SparceStringMatrix result = new SparceStringMatrix(getRowSize() - 1, getColumnSize() - 1);
for (int row = 1; row <= getRowSize() - 1; row++) {
for (int column = 1; column <= getColumnSize() - 1; column++) {
int r = row;
int c = column;
if (n <= row) {
r = row + 1;
}
if (n <= column) {
c = column + 1;
}
result.setElement(row, column, getElement(r, c));
}
}
return result;
}
/**
* @see org.mklab.nfc.matrix.Grid#exchangeRow(int, int)
*/
@Override
public void exchangeRow(final int row1, final int row2) {
for (int column = 1; column <= getColumnSize(); column++) {
String element1 = getElement(row1, column);
String element2 = getElement(row2, column);
setElement(row2, column, element1);
setElement(row1, column, element2);
}
}
/**
* @see org.mklab.nfc.matrix.Grid#exchangeColumn(int, int)
*/
@Override
public void exchangeColumn(final int column1, final int column2) {
for (int row = 1; row <= getRowSize(); row++) {
String element1 = getElement(row, column1);
String element2 = getElement(row, column2);
setElement(row, column2, element1);
setElement(row, column1, element2);
}
}
/**
* 行n1と行n2、列n1と列n2を同時に入れ替えた行列を返します。
*
* @param n1 行番号1、列番号1
* @param n2 行番号2、列番号2
* @return 行1と行2、列1と列2を入れ替えた文字行列
*/
public SparceStringMatrix exchangeRowAndColumn(final int n1, final int n2) {
SparceStringMatrix result = new SparceStringMatrix(getRowSize(), getColumnSize());
for (int row = 1; row <= getRowSize(); row++) {
for (int column = 1; column <= getColumnSize(); column++) {
int r = row;
int c = column;
if (row == n1) {
r = n2;
} else if (row == n2) {
r = n1;
}
if (column == n1) {
c = n2;
} else if (column == n2) {
c = n1;
}
result.setElement(row, column, getElement(r, c));
}
}
return result;
}
/**
* 指定した行に存在する空文字列でない成分の数を返します。
*
* @param row 行番号
* @return 指定した行に存在する空文字列でない成分の数
*/
public int getRowElementCount(final int row) {
int count = 0;
for (int column = 1; column <= getColumnSize(); column++) {
if (this.hasElement(row, column)) {
count++;
}
}
return count;
}
/**
* 指定した列に存在する空文字列でない成分の数を返します。
*
* @param column 列番号
* @return 指定した列に存在する空文字列でない成分の数
*/
public int getColumnElementCount(final int column) {
int count = 0;
for (int row = 1; row <= getRowSize(); row++) {
if (this.hasElement(row, column)) {
count++;
}
}
return count;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object opponent) {
if (this == opponent) {
return true;
}
if (opponent == null) {
return false;
}
if (opponent.getClass() != getClass()) {
return false;
}
SparceStringMatrix castedObj = (SparceStringMatrix)opponent;
return ((this.elementMap == null ? castedObj.elementMap == null : this.elementMap.equals(castedObj.elementMap)) && (getRowSize() == castedObj.getRowSize()) && (getColumnSize() == castedObj
.getColumnSize()));
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int hashCode = 1;
hashCode = 31 * hashCode + (this.elementMap == null ? 0 : this.elementMap.hashCode());
hashCode = 31 * hashCode + getRowSize();
hashCode = 31 * hashCode + getColumnSize();
return hashCode;
}
/**
* @see org.mklab.nfc.matrix.AbstractGrid#clone()
*/
@Override
public SparceStringMatrix clone() {
try {
SparceStringMatrix ans = (SparceStringMatrix)super.clone();
ans.elementMap = new HashMap<>();
ans.elementMap.putAll(this.elementMap);
return ans;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
/**
* @see org.mklab.nfc.matrix.Grid#isZero()
*/
@Override
public boolean isZero() {
return this.elementMap.size() == 0;
}
/**
* 行列の成分の位置を表現するクラスです。
*
* @author yusuke
* @version $Revision: 1.10 $, 2005/11/07
*/
private static class Position {
/** 行番号 */
private int row;
/** 列番号 */
private int column;
/**
* 新しく生成された<code>Position</code>オブジェクトを初期化します。
*
* @param row 行番号
* @param column 列番号
*/
public Position(final int row, final int column) {
this.row = row;
this.column = column;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object opponent) {
if (this == opponent) {
return true;
}
if (opponent == null) {
return false;
}
if (opponent.getClass() != getClass()) {
return false;
}
Position castedObj = (Position)opponent;
return ((this.row == castedObj.row) && (this.column == castedObj.column));
}
/**
* Override hashCode.
*
* @return the Objects hashcode.
*/
@Override
public int hashCode() {
int hashCode = 1;
hashCode = 31 * hashCode + this.row;
hashCode = 31 * hashCode + this.column;
return hashCode;
}
}
/**
* @see org.mklab.nfc.matrix.Grid#removeColumnVectors(int, int)
*/
@Override
public void removeColumnVectors( int columnMin, int columnMax) {
throw new UnsupportedOperationException();
}
/**
* @see org.mklab.nfc.matrix.Grid#removeColumnVectors(org.mklab.nfc.matrix.IntMatrix)
*/
@Override
public void removeColumnVectors( IntMatrix columnIndex) {
throw new UnsupportedOperationException();
}
/**
* @see org.mklab.nfc.matrix.Grid#removeRowVectors(int, int)
*/
@Override
public void removeRowVectors( int rowMin, int rowMax) {
throw new UnsupportedOperationException();
}
/**
* @see org.mklab.nfc.matrix.Grid#removeRowVectors(org.mklab.nfc.matrix.IntMatrix)
*/
@Override
public void removeRowVectors( IntMatrix rowIndex) {
throw new UnsupportedOperationException();
}
}