package jp.ac.takushoku_u.cs;
import java.util.Set;
import java.util.Iterator;

/**
* LFTAnalysisクラスはLFT分析を行うためのクラスです。<BR>
* また、このクラスを利用し隣接マトリクスにおける枝の重要度や要素対集合を求めることができます。
* @version 1.3.1
* @author 笠島 裕史(Kasajima Hiroshi)
*/
/*
* 最終更新日 2004年12月06日
*/
public class LFTAnalysis{
	
/**
* 教授者のマトリクスを保持するマトリクス
*/
	private BooleanMatrix teacherMatrix;
	
/**
* 学習者のマトリクスを保持するマトリクス
*/
	private BooleanMatrix studentMatrix;
	
/**
* 有向枝がある場合を表す定数
*/
	private static final int LFT_EDGE_INT_TRUE = 1;
	
/**
* 有向枝がある場合を表す定数
*/
	private static final boolean LFT_EDGE_TRUE = true;
	
/**
* 有向枝がある場合を表す定数
*/
	private static final String LFT_EDGE_STRING_TRUE = "1";
	
/**
* 有向枝がない場合を表す定数
*/
	private static final int LFT_EDGE_INT_FALSE = 0;
	
/**
* 有向枝がない場合を表す定数
*/
	private static final boolean LFT_EDGE_FALSE = false;
	
/**
* 有向枝がない場合を表す定数
*/
	private static final String LFT_EDGE_STRING_FALSE = "0";
	
/**
* 一緒にしたマトリクスで教授者のマトリクスにのみ枝がある場合を表す定数
*/
	private static final int LFT_EDGE_TEACHER = 3;
	
/**
* 一緒にしたマトリクスで教授者のマトリクスにのみ枝がある場合を表す定数
*/
	private static final String LFT_EDGE_STRING_TEACHER = "T";
	
/**
* 一緒にしたマトリクスで学習者のマトリクスにのみ枝がある場合を表す定数
*/
	private static final int LFT_EDGE_STUDENT = 4;
	
/**
* 一緒にしたマトリクスで学習者のマトリクスにのみ枝がある場合を表す定数
*/
	private static final String LFT_EDGE_STRING_STUDENT = "S";
	
/**
* マトリクスサイズのデフォルト値
*/
	private static final int LFT_MATRIX_VALUE = 5;
	
/**
* 設定されているデフォルトのサイズで分析を行うマトリクスを設定します。<BR>
* 教授者と学習者両方のマトリクスの要素は全て0となります。
*/
	public LFTAnalysis(){
		BooleanMatrix baseTeacherMatrix = new BooleanMatrix(LFT_MATRIX_VALUE, LFT_MATRIX_VALUE);
		BooleanMatrix baseStudentMatrix = new BooleanMatrix(LFT_MATRIX_VALUE, LFT_MATRIX_VALUE);
		
		//教授者のマトリクスを設定する
		setTeacherMatrix(baseTeacherMatrix);
		
		//学習者のマトリクスを設定する
		setStudentMatrix(baseStudentMatrix);
	}
	
/**
* 教授者のマトリクスを設定します。<BR>
* 学習者のマトリクスは教授者のマトリクスサイズと同じで、要素は全て0となります。<BR>
* 教授者のマトリクスは正方行列である必要があります。
* @param baseTeacherMatrix 教授者のマトリクス
* @exception NotSquareMatrixException 教授者のマトリクスが正方行列ではない場合
*/
	public LFTAnalysis(BooleanMatrix baseTeacherMatrix){
		BooleanMatrix baseStudentMatrix =
		new BooleanMatrix(baseTeacherMatrix.getRowLength(), baseTeacherMatrix.getColLength(),
			baseTeacherMatrix.getRowNameArray(), baseTeacherMatrix.getColNameArray());
			
		//教授者のマトリクスを設定する
		setTeacherMatrix(baseTeacherMatrix);
			
		//学習者のマトリクスを設定する
		setStudentMatrix(baseStudentMatrix);
	}
	
/**
* 教授者のマトリクスと学習者のマトリクスを設定します。<BR>
* 教授者のマトリクスと学習者のマトリクスサイズが一致し、両者とも正方行列である必要があります。
* @param baseTeacherMatrix 教授者のマトリクス
* @param baseStudentMatrix 学習者のマトリクス
* @exception NotSquareMatrixException 教授者または学習者のマトリクスが正方行列ではない場合
* @exception DisagreementMatrixSizeException 教授者のマトリクスと学習者のマトリクスサイズが一致しない場合
*/
	public LFTAnalysis(BooleanMatrix baseTeacherMatrix, BooleanMatrix baseStudentMatrix){
		
		//教授者のマトリクスを設定する
		setTeacherMatrix(baseTeacherMatrix);
			
		//学習者のマトリクスを設定する
		setStudentMatrix(baseStudentMatrix);
	}
	
/**
* 教授者のマトリクスを設定します。<BR>
* 学習者のマトリクスは教授者のマトリクスサイズと同じで、要素は全て0となります。<BR>
* 教授者のマトリクスは正方行列である必要があります。
* @param baseTeacherMatrix 教授者のマトリクス
* @exception NotSquareMatrixException 教授者のマトリクスが正方行列ではない場合
*/
	public LFTAnalysis(ArithmeticMatrix baseTeacherMatrix){
		BooleanMatrix baseStudentMatrix =
		new BooleanMatrix(baseTeacherMatrix.getRowLength(), baseTeacherMatrix.getColLength(),
			baseTeacherMatrix.getRowNameArray(), baseTeacherMatrix.getColNameArray());
			
		//教授者のマトリクスを設定する
		setTeacherMatrix(baseTeacherMatrix.toBooleanMatrix());
			
		//学習者のマトリクスを設定する
		setStudentMatrix(baseStudentMatrix);
	}
	
/**
* 教授者のマトリクスと学習者のマトリクスを設定します。<BR>
* 教授者のマトリクスと学習者のマトリクスサイズが一致し、両者とも正方行列である必要があります。
* @param baseTeacherMatrix 教授者のマトリクス
* @param baseStudentMatrix 学習者のマトリクス
* @exception NotSquareMatrixException 教授者または学習者のマトリクスが正方行列ではない場合
* @exception DisagreementMatrixSizeException 教授者のマトリクスと学習者のマトリクスサイズが一致しない場合
*/
	public LFTAnalysis(ArithmeticMatrix baseTeacherMatrix, ArithmeticMatrix baseStudentMatrix){
		
		//教授者のマトリクスを設定する
		setTeacherMatrix(baseTeacherMatrix.toBooleanMatrix());
			
		//学習者のマトリクスを設定する
		setStudentMatrix(baseStudentMatrix.toBooleanMatrix());
	}
	
/**
* 教授者のマトリクスを設定します。<BR>
* 学習者のマトリクスは教授者のマトリクスサイズと同じで、要素は全て0となります。<BR>
* 教授者のマトリクスは正方行列である必要があります。
* @param baseTeacherMatrix 教授者のマトリクス
* @param value BooleanMatrixに変換する際のしきい値
* @exception NotSquareMatrixException 教授者のマトリクスが正方行列ではない場合
*/
	public LFTAnalysis(ArithmeticMatrix baseTeacherMatrix, double value){
		BooleanMatrix baseStudentMatrix =
		new BooleanMatrix(baseTeacherMatrix.getRowLength(), baseTeacherMatrix.getColLength(),
			baseTeacherMatrix.getRowNameArray(), baseTeacherMatrix.getColNameArray());
			
		//教授者のマトリクスを設定する
		setTeacherMatrix(baseTeacherMatrix.toBooleanMatrix());
			
		//学習者のマトリクスを設定する
		setStudentMatrix(baseStudentMatrix);
	}
	
/**
* 教授者のマトリクスと学習者のマトリクスを設定します。<BR>
* 教授者のマトリクスと学習者のマトリクスサイズが一致し、両者とも正方行列である必要があります。
* @param baseTeacherMatrix 教授者のマトリクス
* @param baseStudentMatrix 学習者のマトリクス
* @param value BooleanMatrixに変換する際のしきい値
* @exception NotSquareMatrixException 教授者または学習者のマトリクスが正方行列ではない場合
* @exception DisagreementMatrixSizeException 教授者のマトリクスと学習者のマトリクスサイズが一致しない場合
*/
	public LFTAnalysis(ArithmeticMatrix baseTeacherMatrix, ArithmeticMatrix baseStudentMatrix, double value){
		
		//教授者のマトリクスを設定する
		setTeacherMatrix(baseTeacherMatrix.toBooleanMatrix());
			
		//学習者のマトリクスを設定する
		setStudentMatrix(baseStudentMatrix.toBooleanMatrix());
	}
	
/**
* 類似度を返します。
* @return 類似度
*/
	public double getResemble(){
		double denominator = 0.0; //分母(OR)
		double numerator = 0.0; //分子(AND)
		
		//要素対を求めるマトリクス
		BooleanMatrix pairTeacherMatrix = new BooleanMatrix(getElement(), getElement());
		BooleanMatrix pairStudentMatrix = new BooleanMatrix(getElement(), getElement());
		
		//可到達マトリクス
		BooleanMatrix reachTeacherMatrix = new BooleanMatrix();
		reachTeacherMatrix.matrixCopy(getReachTeacherMatrix());
		BooleanMatrix reachStudentMatrix = new BooleanMatrix();
		reachStudentMatrix.matrixCopy(getReachStudentMatrix());
		
		//計算過程で使用するマトリクス
		BooleanMatrix resultMatrix = new BooleanMatrix(getElement(), getElement());
		for (int i = 0; i < getElement(); i++){
			for (int j = 0; j < getElement(); j++){
				
				//教授者のマトリクスでその2要素間に枝があればその要素間の要素対集合を求める
				if (teacherMatrix.getCell(i, j) == true){
				pairTeacherMatrix.matrixCopy(getPairMatrix(reachTeacherMatrix, i, j));
				}
				
				//枝がなければ要素対集合は空集合
				else{
					pairTeacherMatrix.clearMatrix();
				}
				
				//学習者のマトリクスでその2要素間に枝があればその要素間の要素対集合を求める
				if (studentMatrix.getCell(i, j) == true){
				pairStudentMatrix.matrixCopy(getPairMatrix(reachStudentMatrix, i, j));
				}
				
				//枝がなければ要素対集合は空集合
				else{
					pairStudentMatrix.clearMatrix();
				}
				
				//分母の計算
				resultMatrix.matrixCopy(pairTeacherMatrix.getOrMatrix(pairStudentMatrix));
				denominator = resultMatrix.getElement() + denominator;
				
				//分子の計算
				resultMatrix.matrixCopy(pairTeacherMatrix.getAndMatrix(pairStudentMatrix));
				numerator = resultMatrix.getElement() + numerator;
			}
		}
		
		return numerator / denominator;
	}
	
/**
* 到達度を返します。
* @return 到達度
*/
	public double getAttainment(){
		return Math.sqrt(getResemble()) * 100;
	}

/**
* ある2点間における教授者と学習者の枝の状態を返します。
* どちらも枝が無ければ0、どちらも枝があれば1、教授者のマトリクスのみに枝がある場合は3、
* 学習者のマトリクスのみに枝がある場合は4が入ります。
* @param baseMatrix 比較元のマトリクス
* @param compareMatrix 比較されるマトリクス
* @param Ij 有向枝の始点
* @param Ik 有向枝の終点
* @return 枝の状態
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
* @exception DisagreementMatrixSizeException 2つのマトリクスサイズが一致しない場合
* @exception NotElementException 指定した要素番号が存在しない場合
* @see #getBlendMatrix()
*/
	private int getBlendEdge(BooleanMatrix baseMatrix, BooleanMatrix compareMatrix, int Ij, int Ik){
		if(baseMatrix.isSquare() && compareMatrix.isSquare()){
			if (baseMatrix.isSameMatrixSize(compareMatrix)){
				int value;
				if (baseMatrix.isMatrixEntityPoint(Ij, Ik) && compareMatrix.isMatrixEntityPoint(Ij, Ik)){
					if (baseMatrix.getCell(Ij, Ik) == compareMatrix.getCell(Ij, Ik)){
							if(baseMatrix.getCell(Ij, Ik) == LFT_EDGE_TRUE){
								value = LFT_EDGE_INT_TRUE;
							}
							else{
								value = LFT_EDGE_INT_FALSE;
							}
						}
						else if (baseMatrix.getCell(Ij, Ik) == LFT_EDGE_TRUE &&
							compareMatrix.getCell(Ij, Ik) == LFT_EDGE_FALSE){
							value = LFT_EDGE_TEACHER;
						}
						else{
							value = LFT_EDGE_STUDENT;
						}
					return value;
				}
				else{
					throw new NotElementException("point(" + Ij + "," + Ik + ")");
				}
			}
			else{
				throw new DisagreementMatrixSizeException();
			}
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* ある2点間における教授者と学習者の枝の状態を返します。
* どちらも枝が無ければ0、どちらも枝があれば1、教授者のマトリクスのみに枝がある場合はT、
* 学習者のマトリクスのみに枝がある場合はSが入ります。
* @param baseMatrix 比較元のマトリクス
* @param compareMatrix 比較されるマトリクス
* @param Ij 有向枝の始点
* @param Ik 有向枝の終点
* @return 枝の状態
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
* @exception DisagreementMatrixSizeException 2つのマトリクスサイズが一致しない場合
* @exception NotElementException 指定した要素番号が存在しない場合
* @see #getBlendStringMatrix()
* @see #getBlendStringMatrix(BooleanMatrix baseMatrix, BooleanMatrix compareMatrix)
*/
	public String getBlend(BooleanMatrix baseMatrix, BooleanMatrix compareMatrix, int Ij, int Ik){
		if(baseMatrix.isSquare() && compareMatrix.isSquare()){
			if (baseMatrix.isSameMatrixSize(compareMatrix)){
				String st;
				if (baseMatrix.isMatrixEntityPoint(Ij, Ik) && compareMatrix.isMatrixEntityPoint(Ij, Ik)){
					if (baseMatrix.getCell(Ij,Ik) == compareMatrix.getCell(Ij, Ik)){
							if(baseMatrix.getCell(Ij,Ik) == LFT_EDGE_TRUE){
								st = LFT_EDGE_STRING_TRUE;
							}
							else{
								st = LFT_EDGE_STRING_FALSE;
							}
						}
						else if (baseMatrix.getCell(Ij,Ik) == LFT_EDGE_TRUE &&
							compareMatrix.getCell(Ij,Ik) == LFT_EDGE_FALSE){
							st = LFT_EDGE_STRING_TEACHER;
						}
						else{
							st = LFT_EDGE_STRING_STUDENT;
						}
					return st;
				}
				else{
					throw new NotElementException("point(" + Ij + "," + Ik + ")");
				}
			}
			else{
				throw new DisagreementMatrixSizeException();
			}
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* 指定した2つの隣接マトリクスを一緒にしたマトリクスを返します。<BR>
* どちらも枝が無ければ0、どちらも枝があれば1、baseMatrixで指定したマトリクスのみに枝がある場合は3、
* compareMatrixで指定したマトリクスにのみに枝がある場合は4が入ります。
* 一緒にしたマトリクスの行名と列名はbaseMatrixで指定したマトリクスと同じになります。
* @param baseMatrix 比較元のマトリクス
* @param compareMatrix 比較されるマトリクス
* @return 一緒にしたマトリクス
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
* @exception DisagreementMatrixSizeException 2つのマトリクスサイズが一致しない場合
*/
	private ArithmeticMatrix getBlendMatrix(BooleanMatrix baseMatrix, BooleanMatrix compareMatrix){
		if(baseMatrix.isSquare() && compareMatrix.isSquare()){
			if (baseMatrix.isSameMatrixSize(compareMatrix)){
				ArithmeticMatrix returnMatrix = new ArithmeticMatrix(getElement(), getElement(),
					baseMatrix.getRowNameArray(), baseMatrix.getColNameArray());
				
				for (int i = 0; i < getElement(); i++){
					for (int j = 0; j < getElement(); j++){
						returnMatrix.setCell(i, j, getBlendEdge(baseMatrix, compareMatrix, i ,j));
					}
				}
				return returnMatrix;
			}
			else{
				throw new DisagreementMatrixSizeException();
			}
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* 指定した2つの隣接マトリクスを一緒にしたマトリクスを返します。<BR>
* どちらも枝が無ければ0、どちらも枝があれば1、baseMatrixで指定したマトリクスのみに枝がある場合はT、
* compareMatrixで指定したマトリクスにのみに枝がある場合はSが入ります。
* 一緒にしたマトリクスの行名と列名はbaseMatrixで指定したマトリクスと同じになります。
* @param baseMatrix 比較元のマトリクス
* @param compareMatrix 比較されるマトリクス
* @return 一緒にしたマトリクス
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
* @exception DisagreementMatrixSizeException 2つのマトリクスサイズが一致しない場合
* @see #getBlend(BooleanMatrix baseMatrix, BooleanMatrix compareMatrix, int Ij, int Ik)
* @see #getBlendStringMatrix()
*/
	public StringMatrix getBlendStringMatrix(BooleanMatrix baseMatrix, BooleanMatrix compareMatrix){
		if(baseMatrix.isSquare() && compareMatrix.isSquare()){
			if (baseMatrix.isSameMatrixSize(compareMatrix)){
				StringMatrix returnMatrix = new StringMatrix(getElement(), getElement(),
					baseMatrix.getRowNameArray(), baseMatrix.getColNameArray());
				
				for (int i = 0; i < getElement(); i++){
					for (int j = 0; j < getElement(); j++){
						returnMatrix.setCell(i, j, getBlend(baseMatrix, compareMatrix, i, j));
					}
				}
				return returnMatrix;
			}
			else{
				throw new DisagreementMatrixSizeException();
			}
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* 教授者のマトリクスと学習者のマトリクスを一緒にしたマトリクスを返します。<BR>
* どちらも枝が無ければ0、どちらも枝があれば1、教授者のマトリクスのみに枝がある場合は3、
* 学習者のマトリクスのみに枝がある場合は4が入ります。
* 一緒にしたマトリクスの行名と列名は教授者のマトリクスと同じになります。
* @return 一緒にしたマトリクス
*/
	private ArithmeticMatrix getBlendMatrix(){
		return getBlendMatrix(teacherMatrix, studentMatrix);
	}
	
/**
* 教授者のマトリクスと学習者のマトリクスを一緒にしたマトリクスを返します。<BR>
* どちらも枝が無ければ0、どちらも枝があれば1、教授者のマトリクスのみに枝がある場合はT、
* 学習者のマトリクスのみに枝がある場合はSが入ります。
* 一緒にしたマトリクスの行名と列名は教授者のマトリクスと同じになります。
* @return 一緒にしたマトリクス
* @see #getBlend(BooleanMatrix baseMatrix, BooleanMatrix compareMatrix, int Ij, int Ik)
* @see #getBlendStringMatrix(BooleanMatrix baseMatrix, BooleanMatrix compareMatrix)
*/
	public StringMatrix getBlendStringMatrix(){
		return getBlendStringMatrix(teacherMatrix, studentMatrix);
	}
	
/**
* 隣接マトリクスを元にある要素間の要素対集合を求めます。
* @param nextMatrix 調べる隣接マトリクス
* @param Ij 有向枝の始点
* @param Ik 有向枝の先の終点
* @return どの要素間が要素対か示したマトリクス
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
* @exception NotElementException 指定した要素番号が存在しない場合
*/
	public BooleanMatrix getElementPairMatrix(BooleanMatrix nextMatrix, int Ij, int Ik){
		if(nextMatrix.isSquare()){
			if (nextMatrix.isMatrixEntityPoint(Ij, Ik)){
				
				//可到達マトリクスを生成
				BooleanMatrix lookMatrix = new BooleanMatrix(nextMatrix.getRowLength(), nextMatrix.getColLength(),
					nextMatrix.getRowNameArray(), nextMatrix.getColNameArray());
				lookMatrix.matrixCopy(nextMatrix.getReachMatrix());
				
				BooleanMatrix returnMatrix = new BooleanMatrix(lookMatrix.getRowLength(), lookMatrix.getColLength(), 
					lookMatrix.getRowNameArray(), lookMatrix.getColNameArray());
				
				//枝が存在するかどうか
				if (nextMatrix.getCell(Ij, Ik) == LFT_EDGE_TRUE){
					returnMatrix.matrixCopy(getPairMatrix(lookMatrix, Ij, Ik));
				}
				return returnMatrix;
			}
			else{
				throw new NotElementException("point(" + Ij + "," + Ik + ")");
			}
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* 隣接マトリクスを元にある要素間の要素対集合を求めます。
* @param nextMatrix 調べる隣接マトリクス
* @param Ij 有向枝の始点
* @param Ik 有向枝の先の終点
* @return 要素対集合となる枝の集合
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
* @exception NotElementException 指定した要素番号が存在しない場合
*/
	public EdgeSet getElementPairSet(BooleanMatrix nextMatrix, int Ij, int Ik){
		if(nextMatrix.isSquare()){
			if (nextMatrix.isMatrixEntityPoint(Ij, Ik)){
				
				//可到達マトリクスを生成
				BooleanMatrix lookMatrix = new BooleanMatrix(nextMatrix.getRowLength(), nextMatrix.getColLength(),
					nextMatrix.getRowNameArray(), nextMatrix.getColNameArray());
				lookMatrix.matrixCopy(nextMatrix.getReachMatrix());
				
				EdgeSet edgeHash = new EdgeSet();
				
				//枝が存在するかどうか
				if (nextMatrix.getCell(Ij, Ik) == LFT_EDGE_TRUE){
					for (int i = 0; i < lookMatrix.getRowLength(); i++){
						for (int j = 0; j < lookMatrix.getColLength(); j++){
							if (lookMatrix.getCell(i, Ij) && lookMatrix.getCell(Ik, j) == LFT_EDGE_TRUE){
								edgeHash.add(new Edge(i,j));
							}
						}
					}
				}
				return edgeHash;
			}
			else{
				throw new NotElementException("point(" + Ij + "," + Ik + ")");
			}
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* 可到達マトリクスを元にある要素間の要素対集合を求めます。<BR>
* 隣接マトリクスから求めるのに比べ、2要素間が隣接しているかが保証されないため、
* このメソッドを使用する場合はその要素間同士が隣接していることをチェックする必要があります。
* @param lookMatrix 調べる可到達マトリクス
* @param Ij 有向枝の元の要素番号
* @param Ik 有向枝の先の要素番号
* @return どの要素間が要素対か示したマトリクス
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
* @exception NotElementException 指定した要素番号が存在しない場合
*/
	private BooleanMatrix getPairMatrix(BooleanMatrix lookMatrix, int Ij, int Ik){
		if(lookMatrix.isSquare()){
			if (lookMatrix.isMatrixEntityPoint(Ij, Ik)){
				BooleanMatrix returnMatrix = new BooleanMatrix(lookMatrix.getRowLength(),lookMatrix.getColLength(), 
					lookMatrix.getRowNameArray(), lookMatrix.getColNameArray());
				for (int i = 0; i < lookMatrix.getRowLength(); i++){
					for (int j = 0; j < lookMatrix.getColLength(); j++){
						if (lookMatrix.getCell(i, Ij) && lookMatrix.getCell(Ik, j) == LFT_EDGE_TRUE){
							returnMatrix.setCell(i, j, LFT_EDGE_TRUE);
						}
						else{
							returnMatrix.setCell(i, j, LFT_EDGE_FALSE);
						}
					}
				}
				return returnMatrix;
			}
			else{
				throw new NotElementException("point(" + Ij + "," + Ik + ")");
			}
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* マトリクスに存在する枝の重要度を求めます。
* @param baseMatrix 重要度を求める対象の隣接マトリクス
* @return 枝の重要度を格納したマトリクス
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
*/
	public ArithmeticMatrix getImportantEdgeMatrix(BooleanMatrix baseMatrix){
		if(baseMatrix.isSquare()){
			ArithmeticMatrix returnMatrix = new ArithmeticMatrix(baseMatrix.getRowLength(), baseMatrix.getColLength(),
				baseMatrix.getRowNameArray(), baseMatrix.getColNameArray());
			
			for (int i = 0;i < baseMatrix.getRowLength(); i++){
				for (int j = 0; j < baseMatrix.getColLength(); j++){
					returnMatrix.setCell(i, j, getImportantEdge(baseMatrix, i, j));
				}
			}
			return returnMatrix;
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* マトリクスの2項目間の枝の重要度を返します。
* @param baseMatrix 重要度を求めるマトリクス
* @param Ij 有向枝の始点となる項目Ij
* @param Ik 有向枝の終点となる項目Ik
* @return 指定した項目間の重要度
* @exception NotSquareMatrixException 設定したマトリクスが正方行列ではない場合
*/
	public double getImportantEdge(BooleanMatrix baseMatrix, int Ij, int Ik){
		if(baseMatrix.isSquare()){
			BooleanMatrix temporaryMatrix = new BooleanMatrix(baseMatrix.getRowLength(), baseMatrix.getColLength());
			double cont = Math.floor(getElement() / 2) * Math.floor((getElement() + 1) / 2);
			double value = 0.0;
			
			//枝が存在するかどうか
			if (baseMatrix.getCell(Ij, Ik) == LFT_EDGE_TRUE){
				temporaryMatrix.matrixCopy(getElementPairMatrix(baseMatrix, Ij, Ik));
				value = temporaryMatrix.getElement();
				value = value / cont;
			}
			return value;
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* 教授者のマトリクスにある指定した枝の重要度を返します。
* @param Ij 有向枝の始点
* @param Ik 有向枝の終点
* @return 重要度
* @exception NotElementException 指定した要素番号が存在しない場合
* @see #getImportantEdgeStudent(int Ij, int Ik)
* @see #getEdgeTeacherMatrix()
*/
	public double getImportantEdgeTeacher(int Ij, int Ik){
		if (teacherMatrix.isMatrixEntityPoint(Ij, Ik)){
			return getImportantEdge(teacherMatrix, Ij, Ik);
		}
		else{
			throw new NotElementException("point(" + Ij + "," + Ik + ")");
		}
	}
	
/**
* 教授者の枝の重要度を求めたマトリクスを返します。
* @return 重要度を求めたマトリクス
* @see #getEdgeStudentMatrix()
* @see #getImportantEdgeTeacher(int Ij, int Ik)
*/
	public ArithmeticMatrix getEdgeTeacherMatrix(){
		return getImportantEdgeMatrix(teacherMatrix);
	}
	
/**
* 学習者のマトリクスにある指定した枝の重要度を返します。
* @param Ij 有向枝の始点
* @param Ik 有向枝の終点
* @return 重要度
* @exception NotElementException 指定した要素番号が存在しない場合
* @see #getEdgeTeacherMatrix()
* @see #getImportantEdgeStudent(int Ij, int Ik)
*/
	public double getImportantEdgeStudent(int Ij, int Ik){
		if (studentMatrix.isMatrixEntityPoint(Ij, Ik)){
			return getImportantEdge(studentMatrix, Ij, Ik);
		}
		else{
			throw new NotElementException("point(" + Ij + "," + Ik + ")");
		}
	}
	
/**
* 学習者の枝の重要度を求めたマトリクスを返します。
* @return 重要度を求めたマトリクス
* @see #getEdgeStudentMatrix()
* @see #getImportantEdgeTeacher(int Ij, int Ik)
*/
	public ArithmeticMatrix getEdgeStudentMatrix(){
		return getImportantEdgeMatrix(studentMatrix);
	}
	
/**
* 教授者のマトリクスを返します。
* @return 教授者のマトリクス
* @see #getStudentMatrix()
*/
	public BooleanMatrix getTeacherMatrix(){
		return teacherMatrix;
	}
	
/**
* 学習者のマトリクスを返します。
* @return 学習者のマトリクス
* @see #getTeacherMatrix()
*/
	public BooleanMatrix getStudentMatrix(){
		return studentMatrix;
	}
	
/**
* 教授者の可到達マトリクスを返します。
* @return 教授者の可到達マトリクス
* @see #getReachStudentMatrix()
*/
	public BooleanMatrix getReachTeacherMatrix(){
		BooleanMatrix reachTeacherMatrix = new BooleanMatrix();
		reachTeacherMatrix.matrixCopy(teacherMatrix.getReachMatrix());
		return reachTeacherMatrix;
	}
	
/**
* 学習者の可到達マトリクスを返します。
* @return 学習者の可到達マトリクス
* @see #getReachTeacherMatrix()
*/
	public BooleanMatrix getReachStudentMatrix(){
		BooleanMatrix reachStudentMatrix = new BooleanMatrix();
		reachStudentMatrix.matrixCopy(studentMatrix.getReachMatrix());
		return reachStudentMatrix;
	}
	
/**
* マトリクスにおける要素数(行または列数)を返します。
* @return 要素数
*/
	public int getElement(){
		return teacherMatrix.getRowLength();
	}
	
/**
* 教授者のマトリクスにある有向枝の数を返します。
* @return 教授者のマトリクスにある有向枝の数
* @see #getStudentEdge()
* @see #getTeacherOnlyEdge()
* @see #getTotelEdge()
* @see #getAccordEdge()
*/
	public int getTeacherEdge(){
		return teacherMatrix.getElement();
	}
	
/**
* 学習者のマトリクスにある有向枝の数を返します。
* @return 学習者のマトリクスにある有向枝の数
* @see #getTeacherEdge()
* @see #getStudentOnlyEdge()
* @see #getTotelEdge()
* @see #getAccordEdge()
*/
	public int getStudentEdge(){
		return studentMatrix.getElement();
	}
	
/**
* 教授者のマトリクスと学習者のマトリクスのどちらか一方にでも存在する有向枝の数を返します。
* @return どちらか一方にでもある有向枝の数
* @see #getAccordEdge()
* @see #getTeacherEdge()
* @see #getStudentEdge()
* @see #getTeacherOnlyEdge()
* @see #getStudentOnlyEdge()
*/
	public int getTotelEdge(){
		ArithmeticMatrix mixMatrix = new ArithmeticMatrix(getElement(), getElement());
		mixMatrix.matrixCopy(getBlendMatrix());
		return mixMatrix.getElement();
	}
	
/**
* 教授者のマトリクスにのみ存在する有向枝の数を返します。
* @return 教授者のマトリクスにのみ存在する有向枝の数
* @see #getTeacherEdge()
* @see #getStudentOnlyEdge()
* @see #getTotelEdge()
* @see #getAccordEdge()
*/
	public int getTeacherOnlyEdge(){
		int count = 0;
		ArithmeticMatrix mixMatrix = new ArithmeticMatrix(getElement(), getElement());
		mixMatrix.matrixCopy(getBlendMatrix());
		for (int i = 0; i < mixMatrix.getRowLength(); i++){
			for (int j = 0; j < mixMatrix.getColLength(); j++){
				if (mixMatrix.getCell(i, j) == LFT_EDGE_TEACHER){
					count = count + 1;
				}
			}
		}
		return count;
	}
	
/**
* 学習者のマトリクスにのみ存在する有向枝の数を返します。
* @return 学習者のマトリクスにのみ存在する有向枝の数
* @see #getStudentEdge()
* @see #getTeacherOnlyEdge()
* @see #getTotelEdge()
* @see #getAccordEdge()
*/
	public int getStudentOnlyEdge(){
		int count = 0;
		ArithmeticMatrix mixMatrix = new ArithmeticMatrix(getElement(), getElement());
		mixMatrix.matrixCopy(getBlendMatrix());
		for (int i = 0; i < mixMatrix.getRowLength(); i++){
			for (int j = 0; j < mixMatrix.getColLength(); j++){
				if (mixMatrix.getCell(i, j) == LFT_EDGE_STUDENT){
					count = count + 1;
				}
			}
		}
		return count;
	}
	
/**
* 教授者のマトリクスにも学習者のマトリクスにも存在する有向枝の数を返します。
* @return 両者にある有向枝の数
* @see #getTotelEdge()
* @see #getTeacherEdge()
* @see #getStudentEdge()
* @see #getTeacherOnlyEdge()
* @see #getStudentOnlyEdge()
*/
	public int getAccordEdge(){
		int count = 0;
		ArithmeticMatrix mixMatrix = new ArithmeticMatrix(getElement(), getElement());
		mixMatrix.matrixCopy(getBlendMatrix());
		for (int i = 0; i < mixMatrix.getRowLength(); i++){
			for (int j = 0; j < mixMatrix.getColLength(); j++){
				if (mixMatrix.getCell(i, j) == LFT_EDGE_INT_TRUE){
					count = count + 1;
				}
			}
		}
		return count;
	}
	
/**
* 教授者のマトリクスを設定します。
* @param baseTeacherMatrix 設定をする教授者のマトリクス
* @exception NotSquareMatrixException 教授者のマトリクスが正方行列ではない場合
*/
	private void setTeacherMatrix(BooleanMatrix baseTeacherMatrix){
		if (baseTeacherMatrix.isSquare()){
			teacherMatrix = new BooleanMatrix();
			teacherMatrix.matrixCopy(baseTeacherMatrix);
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
/**
* 学習者のマトリクスを設定します。<BR>
* 学習者のマトリクスは正方行列であり、教授者のマトリクスとサイズが一致する必要があります。
* @param baseStudentMatrix 設定をする学習者のマトリクス
* @exception NotSquareMatrixException 学習者のマトリクスが正方行列ではない場合
* @exception DisagreementMatrixSizeException 教授者のマトリクスと学習者のマトリクスサイズが一致しない場合
*/
	public void setStudentMatrix(BooleanMatrix baseStudentMatrix){
		if (baseStudentMatrix.isSquare()){
			if (teacherMatrix.isSameMatrixSize(baseStudentMatrix)){
				studentMatrix = new BooleanMatrix();
				studentMatrix.matrixCopy(baseStudentMatrix);
			}
			else{
				throw new DisagreementMatrixSizeException();
			}
		}
		else{
			throw new NotSquareMatrixException();
		}
	}
	
}