Exemplo n.º 1
0
        /// <summary>
        /// 2つの行列を左側右側として連結した1個の行列を戻す。
        /// </summary>
        /// <param name="left">左側の行列</param>
        /// <param name="right">右側の行列</param>
        /// <returns>[left right]</returns>
        public static WWMatrix JoinH(WWMatrix left, WWMatrix right)
        {
            if (left.Row != right.Row)
            {
                throw new ArgumentException("left.Row != right.Row");
            }

            var r = new WWMatrix(left.Row, left.Column + right.Column);

            for (int y = 0; y < left.Row; ++y)
            {
                for (int x = 0; x < left.Column; ++x)
                {
                    r.Set(y, x, left.At(y, x));
                }
            }
            for (int y = 0; y < right.Row; ++y)
            {
                for (int x = 0; x < right.Column; ++x)
                {
                    r.Set(y, left.Column + x, right.At(y, x));
                }
            }

            return(r);
        }
Exemplo n.º 2
0
        /// <summary>
        /// 2つの行列を上側、下側として連結した1個の行列を戻す。
        /// </summary>
        /// <param name="top">上側の行列</param>
        /// <param name="bottom">下側の行列</param>
        /// <returns>[top;bottom]</returns>
        public static WWMatrix JoinV(WWMatrix top, WWMatrix bottom)
        {
            if (top.Column != bottom.Column)
            {
                throw new ArgumentException("top.column != bottom.column");
            }

            var r = new WWMatrix(top.Row + bottom.Row, top.Column);

            for (int y = 0; y < top.Row; ++y)
            {
                for (int x = 0; x < top.Column; ++x)
                {
                    r.Set(y, x, top.At(y, x));
                }
            }
            for (int y = 0; y < bottom.Row; ++y)
            {
                for (int x = 0; x < bottom.Column; ++x)
                {
                    r.Set(top.Row + y, x, bottom.At(y, x));
                }
            }

            return(r);
        }
Exemplo n.º 3
0
        public static WWMatrix Mul(WWMatrix lhs, WWMatrix rhs)
        {
            if (lhs.Column != rhs.Row)
            {
                throw new ArgumentException("lhs.Column != rhs.Row");
            }

            int loopCount = lhs.Column;

            var rv = new WWMatrix(lhs.Row, rhs.Column);

            for (int r = 0; r < rv.Row; ++r)
            {
                for (int c = 0; c < rv.Column; ++c)
                {
                    double v = 0;
                    for (int i = 0; i < loopCount; ++i)
                    {
                        v += lhs.At(r, i) * rhs.At(i, c);
                    }
                    rv.Set(r, c, v);
                }
            }

            return(rv);
        }
Exemplo n.º 4
0
        /// <summary>
        /// aを縦行列と見做して後から掛ける
        /// rv := M x aT
        /// 自分自身を変更しない。
        /// </summary>
        /// <returns>乗算結果の行列を転置したもの</returns>
        public double[] Mul(double[] a)
        {
            if (mCol != a.Length)
            {
                throw new ArgumentException("a.Length != mat.Col");
            }

            var aT = new WWMatrix(a.Length, 1, a);
            var rv = Mul(aT);

            return(rv.ToArray());
        }
Exemplo n.º 5
0
        public WWMatrix ToMatrix()
        {
            WWMatrix rv = new WWMatrix(mRow, mCol);

            for (int r = 0; r < mRow; ++r)
            {
                for (int c = 0; c < mCol; ++c)
                {
                    rv.Set(r, c, At(r, c).Val);
                }
            }

            return(rv);
        }
Exemplo n.º 6
0
        /// <summary>
        /// 転置した行列を作って戻す。
        /// 自分自身を変更しない。
        /// </summary>
        /// <returns>転置した行列。</returns>
        public WWMatrix Transpose()
        {
            var t = new WWMatrix(mCol, mRow);

            for (int y = 0; y < mRow; ++y)
            {
                for (int x = 0; x < mCol; ++x)
                {
                    t.Set(x, y, At(y, x));
                }
            }

            return(t);
        }
Exemplo n.º 7
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);
        }
Exemplo n.º 8
0
        public static double[] Transform(double[] from)
        {
            if (!IsPowerOf2(from.Length))
            {
                throw new ArgumentException("from length is not power of 2");
            }

            int L = from.Length;

            // Lは2のN乗。
            int N = 0;

            for (int i = L; 1 < i; i /= 2)
            {
                ++N;
            }

            var m = new WWMatrix(L, N + 1);

            for (int r = 0; r < L; ++r)
            {
                m.Set(r, 0, from[r]);
            }

            for (int c = 0; c < N; ++c)
            {
                for (int r = 0; r < L / 2; ++r)
                {
                    m.Set(r, c + 1, m.At(r * 2, c) + m.At(r * 2 + 1, c));
                }
                for (int r = 0; r < L / 2; ++r)
                {
                    m.Set(r + L / 2, c + 1, m.At(r * 2, c) - m.At(r * 2 + 1, c));
                }
            }

            var rv = new double[L];

            for (int r = 0; r < L; ++r)
            {
                rv[r] = m.At(r, N);
            }

            return(rv);
        }
Exemplo n.º 9
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);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Solve and find f for Ku = f
        /// </summary>
        /// <param name="K">N * N matrix</param>
        /// <param name="f">N elem vertical vector</param>
        /// <returns>u : N elem vertical vector. zero elem vector returns when failed.</returns>
        public static double[] SolveKu_eq_f(WWMatrix K, double[] f)
        {
            int N = K.Row;

            if (K.Column != N)
            {
                throw new ArgumentException("K.col != K.row");
            }
            if (f.Length != N)
            {
                throw new ArgumentException("f.Length != K.row");
            }

            var u = new double[N];

            WWMatrix L;
            WWMatrix P;
            WWMatrix U;
            var      r = WWMatrix.LUdecompose2(K, out L, out P, out U);

            if (r != WWMatrix.ResultEnum.Success)
            {
                return(new double[0]);
            }

            // Reorder f
            var fr = P.Mul(f);

            var c = new double[N];

            // 前進消去 Lc=fによりcを求める。
            // L c = f
            // L → L (既知)
            // c → c (既知)
            // f → fr (既知)
            for (int i = 0; i < N; ++i)
            {
                double t = fr[i];
                for (int j = 0; j < i; ++j)
                {
                    // i: row番号、j:col番号。
                    t -= L.At(i, j) * c[j];
                }
                c[i] = t / L.At(i, i);
            }
            // cが求まった。

            // U u = c
            // U → U (既知)
            // u → u (解)
            // c → c (既知)
            // 後退代入で解uを得る。
            for (int i = N - 1; 0 <= i; --i)
            {
                double t = c[i];

                // j=i+1行目より下のu_jは求まっている。
                for (int j = i + 1; j < N; ++j)
                {
                    t -= U.At(i, j) * u[j];
                }

                u[i] = t / U.At(i, i);
            }

            return(u);
        }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
0
 /// <summary>
 /// rv := this x a
 /// 自分自身を変更しない。
 /// </summary>
 /// <returns>乗算結果。</returns>
 public WWMatrix Mul(WWMatrix a)
 {
     return(Mul(this, a));
 }
Exemplo n.º 13
0
        /// <summary>
        /// コピーを作って戻す。
        /// mの実体も複製される。
        /// </summary>
        public WWMatrix DeepCopy()
        {
            var r = new WWMatrix(mRow, mCol, m);

            return(r);
        }