/// <summary> /// 行基本変形による頭の単位化を実行します。 /// </summary> /// <returns>Rank を返します。</returns> internal int _Identicalize() { int cmin = System.Math.Min(height, width); bool[] sweeped = new bool[this.height]; for (int c = 0; c < cmin; c++) { // 列 c で最大の絶対値を持つ物 l_m Rational max = -1; int l_m = -1; for (int l = 0; l < height; l++) { Rational cand = Rational.Abs(vals[l, c]); if (!sweeped[l] && Rational.Abs(vals[l, c]) > max) { max = cand; l_m = l; } } if (vals[l_m, c].IsZero) { return(c); } // pivot[l_m,c] で掃き出し if (vals[l_m, c] != Rational.One) { lines.Divide(l_m, this.vals[l_m, c]); } for (int l = 0; l < height; l++) { if (l == l_m || vals[l, c].IsZero) { continue; } lines.SubtractLine(l, l_m, vals[l, c]); } sweeped[l_m] = true; } // 並び替え for (int c = 0; c < height; c++) { for (int l = c; l < height; l++) { if (vals[l, c] == Rational.One) { lines.ExchangeLines(l, c); break; } } } return(cmin); }
public static string Calc1() { Rational hf = new Rational(1, 2); Matrix m = new Matrix(new ksh.Rational[, ] { { 1, new Rational(1, 2), 0, -1, 1 }, { 1, -new Rational(3, 2), -1, 1, 0 }, }); int cmin = System.Math.Min(m.Height, m.Width); bool[] sweeped = new bool[m.Height]; for (int c = 0; c < cmin; c++) { // 列 c で最大の絶対値を持つ物 l_m Rational max = -1; int l_m = -1; for (int l = 0; l < m.Height; l++) { Rational cand = Rational.Abs(m[l, c]); if (!sweeped[l] && Rational.Abs(m[l, c]) > max) { max = cand; l_m = l; } } if (m[l_m, c].IsZero) { continue; } if (m[l_m, c] != Rational.One) { m.Lines.Divide(l_m, m[l_m, c]); } for (int l = 0; l < m.Height; l++) { if (l == l_m || m[l, c].IsZero) { continue; } m.Lines.SubtractLine(l, l_m, m[l, c]); } sweeped[l_m] = true; } return(m.ToHtml()); }
public static string InverseMatrix() { Matrix m = new Matrix(new ksh.Rational[, ] { { 3, 0, 2 }, { 5, 4, 6 }, { 2, 7, -4 }, }); System.Text.StringBuilder build = new System.Text.StringBuilder(); build.Append("<h1>逆行列の求め方</h1>\r\n"); build.Append("<p>以下の行列の逆行列を求めたいと思います。</p>\r\n"); build.Append("<p>" + m.ToHtml() + "</p>\r\n"); build.Append("<p>先ず右から単位行列をくっつけます。</p>\r\n"); m |= Matrix.Identical(m.Height); build.Append("<p>" + m.ToHtml() + "</p>\r\n"); bool[] sweeped = new bool[m.Height]; for (int c = 0; c < 3; c++) { // 列 c で最大の絶対値を持つ物 l_m (既に掃き出した物は除く) Rational max = -1; int l_m = -1; for (int l = 0; l < m.Height; l++) { Rational cand = Rational.Abs(m[l, c]); if (!sweeped[l] && Rational.Abs(m[l, c]) > max) { max = cand; l_m = l; } } if (m[l_m, c].IsZero) { build.Append("<p>やっぱり何だか求められない雰囲気です...</p>"); break; } build.AppendFormat("<p>({0},{1}) 成分に注目します。これが 1 に為る様に行全体を割り算します。</p>\r\n", l_m + 1, c + 1); if (m[l_m, c] == Rational.One) { build.Append("<p>(と思ったら、元から 1 でした...)</p>\r\n"); } else { m.Lines.Divide(l_m, m[l_m, c]); build.Append("<p>" + m.ToHtml() + "</p>\r\n"); } build.AppendFormat("<p>次に ({0},{1}) 成分を使って掃き出しを実行します。</p>\r\n", l_m + 1, c + 1); bool haki = false; for (int l = 0; l < m.Height; l++) { if (l == l_m || m[l, c].IsZero) { continue; } haki = true; build.AppendFormat("<p>{0} 行目から ({1} 行目)×{2} を引き去ります</p>\r\n", l + 1, l_m + 1, m[l, c].ToHtml()); m.Lines.SubtractLine(l, l_m, m[l, c]); build.Append("<p>" + m.ToHtml() + "</p>\r\n"); } if (!haki) { build.Append("<p>と思ったら、元から掃き出された形になっているので次に進みます。</p>\r\n"); } sweeped[l_m] = true; } return(build.ToString()); }