Beispiel #1
0
        /// <summary>
        /// https://en.wikipedia.org/wiki/Crout_matrix_decomposition
        /// </summary>
        public static ResultEnum LUdecompose(WWMatrix inA, out WWMatrix outL, out WWMatrix outU, double epsilon = 1.0e-7)
        {
            if (inA.Row < 2 || inA.Row != inA.Column)
            {
                outL = new WWMatrix(0, 0);
                outU = new WWMatrix(0, 0);
                return(ResultEnum.UnsupportedMatrixShape);
            }

            int N = inA.Row;

            outL = new WWMatrix(N, N);
            outU = new WWMatrix(N, N);

            outU.SetIdentity();

            for (int x = 0; x < N; ++x)
            {
                for (int y = x; y < N; ++y)
                {
                    double sum = 0;
                    for (int k = 0; k < x; ++k)
                    {
                        sum += outL.At(y, k) * outU.At(k, x);
                    }
                    outL.Set(y, x, inA.At(y, x) - sum);
                }

                for (int y = x; y < N; ++y)
                {
                    double sum = 0;
                    for (int k = 0; k < x; ++k)
                    {
                        sum += outL.At(x, k) * outU.At(k, y);
                    }
                    if (WWMathUtil.IsAlmostZero(outL.At(x, x), epsilon))
                    {
                        return(ResultEnum.FailedToChoosePivot);
                    }

                    outU.Set(x, y, (inA.At(x, y) - sum) / outL.At(x, x));
                }
            }

            return(ResultEnum.Success);
        }
Beispiel #2
0
        /// <summary>
        /// aとbが大体同じ時true。異なるときfalse。
        /// </summary>
        public static bool IsSame(WWMatrix a, WWMatrix b, double epsilon = 1.0e-7)
        {
            if (a.Column != b.Column ||
                a.Row != b.Row)
            {
                return(false);
            }

            for (int y = 0; y < a.Row; ++y)
            {
                for (int x = 0; x < a.Column; ++x)
                {
                    if (!WWMathUtil.IsAlmostZero(a.At(y, x) - b.At(y, x), epsilon))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Beispiel #3
0
        public ulong DetermineMatType(double epsilon = 1.0e-7)
        {
            mMatTypeFlags = 0;

            if (mRow != mCol)
            {
                // 正方行列でない。
                return(mMatTypeFlags);
            }

            // 正方行列である。
            mMatTypeFlags |= (ulong)MatType.Square;

            {   // 上三角行列か。
                // 上三角行列=左下が0。
                bool b = true;
                for (int x = 0; x < mCol; ++x)
                {
                    for (int y = x + 1; y < mRow; ++y)
                    {
                        if (!WWMathUtil.IsAlmostZero(At(y, x), epsilon))
                        {
                            b = false;
                            break;
                        }
                    }
                    if (!b)
                    {
                        break;
                    }
                }
                if (b)
                {
                    mMatTypeFlags |= (ulong)MatType.UpperTriangular;
                }
            }

            {   // 下三角行列か。
                // 下三角行列=右上が0。
                bool b = true;
                for (int y = 0; y < mRow; ++y)
                {
                    for (int x = y + 1; x < mCol; ++x)
                    {
                        if (!WWMathUtil.IsAlmostZero(At(y, x), epsilon))
                        {
                            b = false;
                            break;
                        }
                    }
                    if (!b)
                    {
                        break;
                    }
                }
                if (b)
                {
                    mMatTypeFlags |= (ulong)MatType.LowerTriangular;
                }
            }

            if (0 != (mMatTypeFlags & (ulong)MatType.UpperTriangular) &&
                0 != (mMatTypeFlags & (ulong)MatType.LowerTriangular))
            {
                // 上三角かつ下三角のとき、対角行列。
                mMatTypeFlags |= (ulong)MatType.Diagonal;
            }

            {   // 三重対角行列か。
                bool isTriDiag = true;

                // 右上が0である事。
                for (int y = 0; y < mRow; ++y)
                {
                    for (int x = y + 2; x < mCol; ++x)
                    {
                        if (!WWMathUtil.IsAlmostZero(At(y, x), epsilon))
                        {
                            isTriDiag = false;
                            break;
                        }
                    }
                    if (!isTriDiag)
                    {
                        break;
                    }
                }
                if (isTriDiag)
                {
                    // 左下が0である事。
                    for (int x = 0; x < mCol; ++x)
                    {
                        for (int y = x + 2; y < mRow; ++y)
                        {
                            if (!WWMathUtil.IsAlmostZero(At(y, x), epsilon))
                            {
                                isTriDiag = false;
                                break;
                            }
                        }
                        if (!isTriDiag)
                        {
                            break;
                        }
                    }
                }
                if (isTriDiag)
                {
                    mMatTypeFlags |= (ulong)MatType.Tridiagonal;
                }
            }
            return(mMatTypeFlags);
        }
Beispiel #4
0
        /// <summary>
        /// https://www.student.cs.uwaterloo.ca/~cs370/notes/LUExample2.pdf
        /// </summary>
        public static ResultEnum LUdecompose2(WWMatrix inA, out WWMatrix outL, out WWMatrix outP, out WWMatrix outU, double epsilon = 1.0e-7)
        {
            if (inA.Row < 2 || inA.Row != inA.Column)
            {
                outP = new WWMatrix(0, 0);
                outL = new WWMatrix(0, 0);
                outU = new WWMatrix(0, 0);
                return(ResultEnum.UnsupportedMatrixShape);
            }

            int N = inA.Row;

            outP = new WWMatrix(N, N).SetIdentity();
            outL = new WWMatrix(N, N).SetIdentity();
            outU = new WWMatrix(N, N);

            outU = inA.DeepCopy();

            var PA = new WWMatrix(N, N);

            // Lの0行目は [1 0 0 ... 0]

            for (int c = 0; c < N - 1; ++c)
            {
                // c個目のピボットを選択する。
                // Uのc列を比較し、絶対値が最大のものを選ぶ。
                // Pのc行目が決定する。
                int maxRow = c;
                {
                    double maxAbs = 0;
                    for (int y = c; y < N; ++y)
                    {
                        if (maxAbs < Math.Abs(outU.At(y, c)))
                        {
                            maxAbs = Math.Abs(outU.At(y, c));
                            maxRow = y;
                        }
                    }
                }
                // ピボットは、maxRow行c列。

                outU.ExchangeRows(c, maxRow);
                outP.ExchangeRows(c, maxRow);

                outL.ExchangeRows(c, maxRow);
                outL.ExchangeCols(c, maxRow);

                // 並び替えによりuccがピボットになった。
                double ucc = outU.At(c, c);
                if (WWMathUtil.IsAlmostZero(ucc, epsilon))
                {
                    return(ResultEnum.FailedToChoosePivot);
                }

                for (int k = c + 1; k < N; ++k)
                {
                    // Uのk列目の計算。
                    // Uのk列目を0にするために、1列目を何倍して足すか。
                    double ukc = outU.At(k, c);

                    double ratio = ukc / ucc;
                    for (int x = 0; x < N; ++x)
                    {
                        double ucx = outU.At(c, x);
                        double ukx = outU.At(k, x);
                        outU.Set(k, x, ukx - ratio * ucx);
                    }

                    // Lのk行c列 = ratio。
                    outL.Set(k, c, ratio);
                }
            }

            return(ResultEnum.Success);
        }