Esempio n. 1
0
        /// <summary>
        /// LU 分解
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public static Lud Lud(Matrix x)
        {
            MatrixChecker.IsNotZeroSize(x);

            Matrix lu = new Matrix(x);

            int[] p = new int[0];
            int   zeroValueIndex = -1;

            int ret = krdlab.law.func.dgetrf(lu._body, lu._rsize, lu._csize, ref p);

            if (0 < ret)
            {
                zeroValueIndex = ret - 1;
            }

            // 置換行列を構成

            /*
             * 配列 p には,例えば2行目と3行目が置換された場合に,
             *     p = {1, 3, 3};
             *            ↑1回だけ発生したということが解る
             * と格納されている.
             */
            int permutationCount = 0;

            Matrix _p = Matrix.Identity(lu.RowSize);

            // row==column, row < column の場合は p.Length == lu.RowSize
            // row > column              の場合は p.Length <  lu.RowSize

            // どうも下から入れ替えないといけないみたい
            // p[0] = 2
            // p[1] = 1
            // p[2] = 4 <- 「0と入れ替えた後の2と交換」なのか「入れ替える前の2と交換」なのか? => どうも後者のようだ
            for (int from = p.Length - 1; 0 <= from; --from)
            {
                int to = p[from];
                if (0 <= to && from != to)
                {
                    _p.Rows.Swap(from, to);
                    //this.p[from, from] = this.p[to, to] = 0;
                    //this.p[to, from] = 1;
                    //this.p[from, to] = 1;

                    if (to < p.Length && p[to] == from)
                    {
                        p[to] = -1;  // 置換が完了していることを示すフラグ
                    }

                    // 置換が発生したときだけカウントアップ
                    ++permutationCount;
                }
            }

            int    minSize = Math.Min(lu.RowSize, lu.ColumnSize);
            Matrix _l      = Matrix.Zero(lu.RowSize, minSize);
            Matrix _u      = Matrix.Zero(minSize, lu.ColumnSize);

            // set L
            for (int r = 0; r < lu.RowSize; ++r)
            {
                for (int c = 0; c <= r; ++c)
                {
                    if (_l.ColumnSize <= c)
                    {
                        break;
                    }
                    _l[r, c] = (r == c ? 1.0 : lu[r, c]);
                }
            }

            // set U
            for (int r = 0; r < _u.RowSize; ++r)
            {
                for (int c = r; c < lu.ColumnSize; ++c)
                {
                    _u[r, c] = lu[r, c];
                }
            }
            return(new Lud(_p, _l, _u, permutationCount, zeroValueIndex));
        }