1 /*
  2  * Copyright (C) 2012-2013 たかはしのんき. All rights reserved.
  3  *
  4  * History:
  5  *  0.5 2013-06-15 JsDoc Toolkit対応。
  6  *  0.4 2013-03-16 行ベクトルのサポート。行ベクトルを行列として扱う。
  7  *  0.3 2012-05-17 メソッド mul の性能改善。
  8  *  0.2 2012-05-16 メソッド toString の行と列が逆だったのを修正。
  9  *  0.1 2012-05-14 新規作成。Java 版より移植。
 10  */
 11 
 12 /**
 13  * @fileOverview BMatrix - 2進行列オブジェクトの定義
 14  * @name bmatrix05.js
 15  * @version 0.5
 16  * @author たかはしのんき
 17  * 
 18  */
 19 
 20 /**
 21  * 2進行列オブジェクトを定義します。
 22  * @constructor
 23  * @this {BMatrix}
 24  * @since 0.1
 25  */
 26 BMatrix = function() {
 27 	this.init = arguments.length - 2;
 28 	if (this.init < 0)
 29 		return null;
 30 	this.n = arguments[0];
 31 	this.m = arguments[1];
 32 	this.colv = new Array(this.m);
 33 	this.clear();
 34 	for (var k = 1; k <= this.init; k++) {
 35 		var i = arguments[k + 1][0];
 36 		var j = arguments[k + 1][1];
 37 		this.setValue(i, j, 1);
 38 	}
 39 };
 40 
 41 BMatrix.prototype = {
 42 	/**
 43 	 * 2進行列をゼロクリアします。
 44 	 * @since 0.1
 45 	 */
 46 	clear : function() {
 47 		for (var j = 0; j < this.m; j++) {
 48 			if (this.colv[j] == undefined)
 49 				this.colv[j] = new BVector(this.n);
 50 			this.colv[j].clear();
 51 		}
 52 	},
 53 
 54 	/**
 55 	 * 2進行列のある要素i,jに値(0か1)を設定します。
 56 	 * @param i 設定する要素の行番号(1 origin)
 57 	 * @param j 設定する要素の列番号(1 origin)
 58 	 * @param value 設定する値0か1
 59 	 * @since 0.1
 60 	 */
 61 	setValue : function(i, j, value) {
 62 		var j0 = j - 1;		// 0 originに変換
 63 		this.colv[j0].setValue(i, value);
 64 	},
 65 
 66 	/**
 67 	 * 2進行列のある要素i,jの値(0か1)を返します。
 68 	 * @param i 設定する要素の行番号(1 origin)
 69 	 * @param j 設定する要素の列番号(1 origin)
 70 	 * @return 要素iの値(0か1)を返します。
 71 	 * @since 0.1
 72 	 */
 73 	getValue : function(i, j) {
 74 		var j0 = j - 1;		// 0 originに変換
 75 		return this.colv[j0].getValue(i);
 76 	},
 77 
 78 	/**
 79 	 * 2進行列をコピーします。
 80 	 * @return 行列のコピーを返します。
 81 	 * @since 0.1
 82 	 */
 83 	clone : function() {
 84 		var bm = new BMatrix(this.n, this.m);
 85 		for (var j = 0; j < this.m; j++)
 86 			bm.colv[j] = this.colv[j].clone();
 87 		return bm;
 88 	},
 89 
 90 	/**
 91 	 * 2進行列の値が1の要素を数え上げます。
 92 	 * @return 値が1の要素を数え上げた数を返します。
 93 	 * @since 0.1
 94 	 */
 95 	abs : function() {
 96 		var n = 0;
 97 		for (var j = 0; j < this.m; j++)
 98 			n += this.colv[j].abs();
 99 		return n;
100 	},
101 
102 	/**
103 	 * 2進行列を反転して(invert)返します。
104 	 * @return 行列の反転を返します。
105 	 * @since 0.1
106 	 */
107 	inv : function() {
108 		var bm = new BMatrix(this.n, this.m);
109 		for (var j = 0; j < this.m; j++)
110 			bm.colv[j] = this.colv[j].inv();
111 		return bm;
112 	},
113 
114 	/**
115 	 * 2進行列の転置して(transpose)返します。
116 	 * @return 行列の転置を返します。行ベクトルの場合は列ベクトルを返します。
117 	 * @since 0.4
118 	 */
119 	tran : function() {
120 		if (this.n == 1) {	// 行ベクトル
121 			var bv = new BVector(this.m);
122 			for (var j = 1; j <= this.m; j++)
123 				bv.setValue(j, this.getValue(1, j));
124 			return bv;
125 		} else {	
126 			var bm = new BMatrix(this.m, this.n);
127 			for (var i = 1; i <= this.n; i++)
128 				for (var j = 1; j <= this.m; j++)
129 					bm.setValue(j, i, this.getValue(i, j));
130 			return bm;
131 		}
132 	},
133 
134 	/**
135 	 * 2つの2進行列が等しければtrueを返します。同じでないかエラーの場合はfalseを返します。
136 	 * @param bm2 比較対象の行列
137 	 * @return 2つの行列が等しければtrueを返します。
138 	 * @since 0.1
139 	 */
140 	equals : function(bm2) {
141 		if (this.n != bm2.n || this.m != bm2.m)
142 			return false;				// 次元が異なる
143 		for (var j = 0; j < this.m; j++)
144 			if (!((this.colv[j]).equals(bm2.colv[j])))
145 				return false;			// 値が異なる
146 		return true;
147 	},
148 
149 	/**
150 	 * 2進行列同士の論理和を返します。エラーの場合はnullを返します。
151 	 * @param bm2 論理和の第2オペランド
152 	 * @return 2つの行列の論理和を返します。
153 	 * @since 0.1
154 	 */
155 	or : function(bm2) {
156 		if (this.n != bm2.n || this.m != bm2.m)
157 			return null;				// 次元が異なる
158 		var bm = new BMatrix(this.n, this.m);
159 		for (var j = 0; j < this.m; j++)
160 			bm.colv[j] = this.colv[j].or(bm2.colv[j]);
161 		return bm;
162 	},	
163 
164 	/**
165 	 * 2進行列同士の論理積を返します。エラーの場合はnullを返します。
166 	 * @param bm2 論理積の第2オペランド
167 	 * @return 2つの行列の論理積を返します。
168 	 * @since 0.1
169 	 */
170 	and : function(bm2) {
171 		if (this.n != bm2.n || this.m != bm2.m)
172 			return null;				// 次元が異なる
173 		var bm = new BMatrix(this.n, this.m);
174 		for (var j = 0; j < this.m; j++)
175 			bm.colv[j] = this.colv[j].and(bm2.colv[j]);
176 		return bm;
177 	},	
178 
179 	/**
180 	 * 2進行列同士の論理差を返します。エラーの場合はnullを返します。
181 	 * @param bm2 論理差の第2オペランド
182 	 * @return 2つの行列の論理差を返します。
183 	 * @since 0.1
184 	 */
185 	diff : function(bm2) {
186 		if (this.n != bm2.n || this.m != bm2.m)
187 			return null;				// 次元が異なる
188 		var bm = new BMatrix(this.n, this.m);
189 		for (var j = 0; j < this.m; j++)
190 			bm.colv[j] = this.colv[j].diff(bm2.colv[j]);
191 		return bm;
192 	},
193 
194 	/**
195 	 * 2進行列同士の排他的論理和を返します。エラーの場合はnullを返します。
196 	 * @param bv2 排他的論理和の第2オペランド
197 	 * @return 2つの行列の排他的論理和を返します。
198 	 * @since 0.1
199 	 */
200 	xor : function(bm2) {
201 		if (this.n != bm2.n || this.m != bm2.m)
202 			return null;				// 次元が異なる
203 		var bm = new BMatrix(this.n, this.m);
204 		for (var j = 0; j < this.m; j++)
205 			bm.colv[j] = this.colv[j].xor(bm2.colv[j]);
206 		return bm;
207 	},
208 
209 	/**
210 	 * 2進行列と2進行列(または2進ベクトル)の積を返します。エラーの場合はnullを返します。
211 	 * @param bx2 積の第2オペランド
212 	 * @return 行列と行列(またはベクトル)の積を返します。
213 	 * @since 0.1
214 	 */
215 	mul : function(bx2) {
216 		if (bx2.n == undefined) {
217 			// bx2 はベクトル
218 			if (this.m != bx2.order)
219 				return null;
220 			var bv = new BVector(bx2.order);
221 			for (var k = 0; k < this.m; k++)
222 				if (bx2.getValue(k + 1) == 1)
223 					bv = bv.or(this.colv[k]);
224 			return bv;
225 		} else {
226 			// bx2 は行列
227 			if (this.m != bx2.n)
228 				return null;
229 			var bm = new BMatrix(bx2.n, bx2.m);
230 			for (var j = 0; j < bx2.m; j++)
231 				for (var k = 0; k < this.m; k++)
232 					if (bx2.getValue(k + 1, j + 1) == 1)
233 						bm.colv[j] = bm.colv[j].or(this.colv[k]);
234 			return bm;
235 		}
236 	},
237 
238 	/**
239 	 * 2進行列を文字列に変換します。
240 	 * @return 文字列を返します。
241 	 * @since 0.1
242 	 */
243 	toString : function() {
244 		var str = "";
245 		for (var i = 1; i <= this.n; i++) {
246 			for (var j = 1; j <= this.m; j++) {
247 				str = str + this.getValue(i, j);
248 				if (j < this.m)
249 					str = str + " ";
250 			}
251 			str = str + "\n";
252 		}
253 		return str;
254 	},
255 
256 	/**
257 	 * 2進行列を TeX 文字列に変換します。
258 	 * @return TeX 文字列を返します。
259 	 * @since 0.1
260 	 */
261 	toTeX : function() {
262 		var str = "\\begin{pmatrix}";
263 		for (var i = 1; i <= this.n; i++) {
264 			for (var j = 1; j <= this.m; j++) {
265 				str = str + this.getValue(i, j);
266 				if (j < this.m)
267 					str = str + " & ";
268 			}
269 			if (i < this.n)
270 				str = str + "\\\\";
271 		}
272 		str = str + "\\end{pmatrix}";
273 		return str;
274 	}
275 };
276