Пример #1
0
 private static void EasyParse_addfactor(ref Rational r, Gen::Dictionary <string, int> dic, string w, char mode)
 {
     try{
         long val = long.Parse(w);
         if (mode == '/')
         {
             r /= val;
         }
         else
         {
             r *= val;
         }
     }catch {
         int exp = mode == '/'?-1:1;
         if (!dic.ContainsKey(w))
         {
             dic[w] = exp;
         }
         else
         {
             if ((dic[w] += exp) == 0)
             {
                 dic.Remove(w);
             }
         }
     }
 }
Пример #2
0
        /// <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);
        }
Пример #3
0
 /// <summary>
 /// <paramref name="line1"/> から <paramref name="r"/> * <paramref name="line2"/>
 /// を引いた結果を <paramref name="line1"/> に格納します。
 /// </summary>
 /// <param name="line1">引かれる側の行を指定します。</param>
 /// <param name="line2">引く側の行を指定します。</param>
 /// <param name="factor">line2 に掛ける倍率を指定します。</param>
 public void SubtractLine(int line1, int line2, Rational factor)
 {
     if (line1 < 0 || parent.height <= line1 || line2 < 0 || parent.height <= line2)
     {
         throw new System.ArgumentOutOfRangeException("line1,line2", "行番号が正しくありません。");
     }
     for (int column = 0; column < parent.width; column++)
     {
         parent.vals[line1, column] -= factor * parent.vals[line2, column];
     }
 }
Пример #4
0
 public void Divide(int line, Rational value)
 {
     if (line < 0 || parent.height <= line)
     {
         throw new System.ArgumentOutOfRangeException("line", "行番号が正しくありません。");
     }
     for (int column = 0; column < parent.width; column++)
     {
         parent.vals[line, column] /= value;
     }
 }
Пример #5
0
        /// <summary>
        /// 簡単な文字列読み取りを実行します。
        /// 正しくない文字列の読み取りを実行した場合の動作は未定です。
        /// </summary>
        /// <param name="str">各変数を空白、'*'、'/' で区切ったリストを項の表現として渡します。</param>
        /// <returns>読み取った結果生成した文字列を返します。</returns>
        public static Member EasyParse(string str)
        {
            int    i    = 0;
            char   mode = '*';
            string w    = "";

            Rational r = 1;
            Gen::Dictionary <string, int> dic = new Gen::Dictionary <string, int>();

            while (i < str.Length)
            {
                char c = str[i++];

                // 文字分類
                if (c <= ' ')
                {
                    c = '*';
                }
                else if (c == ':')
                {
                    c = '/';
                }

                // 読み取り
                if (c == '/' || c == '*')
                {
                    // 変数の登録
                    if (w != "")
                    {
                        EasyParse_addfactor(ref r, dic, w, mode);
                    }
                    mode = c; w = "";
                }
                else
                {
                    w += c;
                }
            }

            // 変数の登録
            if (w != "")
            {
                EasyParse_addfactor(ref r, dic, w, mode);
            }

            // Member 生成
            Variable[] vars = new Variable[dic.Count];
            i = 0;
            foreach (Gen::KeyValuePair <string, int> pair in dic)
            {
                vars[i++] = new Variable(pair.Key, pair.Value);
            }
            return(new Member(r, vars));
        }
Пример #6
0
        /// <summary>
        /// x[n] の式を生成します。
        /// </summary>
        private void MainEquation()
        {
            Rational f   = 1;
            string   var = string.Format("f[{0}]", ORDER - 1);
            string   exp = var;

            for (int i = 1; i < ORDER; i++)
            {
                f   /= (i + 1);
                var  = "h" + var + "'";
                exp += "+" + f.ToString() + " " + var;
            }
            e_f = Expression.EasyParse(exp);
        }
Пример #7
0
        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());
        }
Пример #8
0
 /// <summary>
 /// 指定した行の内容を交換します。
 /// </summary>
 /// <param name="line1">交換する行の一方を指定します。</param>
 /// <param name="line2">交換する行の他方を指定します。</param>
 public void ExchangeLines(int line1, int line2)
 {
     if (line1 < 0 || parent.height <= line1 || line2 < 0 || parent.height <= line2)
     {
         throw new System.ArgumentOutOfRangeException("line1,line2", "行番号が正しくありません。");
     }
     if (line1 == line2)
     {
         return;
     }
     for (int column = 0; column < parent.width; column++)
     {
         Rational c = parent.vals[line1, column];
         parent.vals[line1, column] = parent.vals[line2, column];
         parent.vals[line2, column] = c;
     }
 }
Пример #9
0
        //===========================================================
        //		計算
        //===========================================================
        /// <summary>
        /// 式を生成します。
        /// </summary>
        private void InitializeEquations()
        {
            string   exp = "-f[{0}]+f[{1}]";
            Rational f   = 1;
            string   var = "f[{1}]";

            for (int i = 1; i < ORDER; i++)
            {
                f   /= i;
                var  = "h" + var + "'";
                exp += "+" + f.ToString() + " " + var;
            }
            for (int i = ORDER - 2; i >= 0; i--)
            {
                equations[i] = Expression.EasyParse(string.Format(exp, i + 1, i));
            }
        }
Пример #10
0
        /// <summary>
        /// 式を f[n-1]^(m) で表し直します。
        /// </summary>
        private void UpdatePastDifferentials()
        {
            build.Append("<ul>\r\n");
            string var = "f[{0}]";

            for (int n = 1; n < ORDER; n++)
            {
                var = "h" + var + "'";

                // 代入する式の書式文字列を生成
                Rational f2   = 1;
                string   var2 = var;
                string   exp2 = var;
                for (int m = 1; m < ORDER - n; m++)
                {
                    f2   /= -m;
                    var2  = "h" + var2 + "'";
                    exp2 += "+" + f2.ToString() + " " + var2;
                }

                // 式を表示
                for (int i = 0; i <= ORDER - 2; i++)
                {
                    string     varname = string.Format(var, i);
                    Expression x       = Expression.EasyParse(string.Format(exp2, i + 1));
                    for (int j = 0; j < equations.Length; j++)
                    {
                        equations[j] = equations[j].Substitute(varname, x);
                    }
                    //----------
                    build.Append("<li>");
                    build.Append(Expression.EasyParse(varname).ToHtml(true));
                    build.Append(" = ");
                    build.Append(x.ToHtml(true));
                    build.Append(" + O(h<sup>" + ORDER.ToString() + "</sup>)</li>\r\n");
                }
            }
            build.Append("</ul>\r\n");
        }
Пример #11
0
 private Member(Rational r, Variable[] vars)
 {
     this.factor = r;
     this.vars   = vars;
 }
Пример #12
0
 private Member(Variable v)
 {
     this.factor = 1;
     this.vars   = new Variable[] { v };
 }
Пример #13
0
 public Member(Rational r)
 {
     this.factor = r;
     this.vars   = new Variable[0];
 }
Пример #14
0
 /// <summary>
 /// 単なる有理数を値に持つ Expression を初期化します。
 /// </summary>
 /// <param name="r">Expression の値を有理数で指定します。</param>
 public Expression(Rational r) : this()
 {
     this.AddMember(new Member(r));
 }
Пример #15
0
        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());
        }