C#,码海拾贝(31)——约化“对称矩阵“为“对称三对角阵“的“豪斯荷尔德Householder变换法“之C#源代码

 

using System;

namespace Zhou.CSharp.Algorithm
{
    ///


    /// 矩阵类
    /// 作者:周长发
    /// 改进:深度混淆
    /// https://blog.csdn.net/beijinghorn
    ///

    public partial class Matrix
    {


        ///


        /// 约化对称矩阵为对称三对角阵的豪斯荷尔德Householder变换法
        ///

        /// 源矩阵
        /// 豪斯荷尔德变换的乘积矩阵Q
        /// 求得的对称三对角阵
        /// 一维数组,长度为矩阵的阶数,返回对称三对角阵的主对角线元素
        /// 一维数组,长度为矩阵的阶数,前n-1个元素返回对称三对角阵的
        /// 求解是否成功
        public static bool MakeSymTri(Matrix src, Matrix mtxQ, Matrix mtxT, double[] dblB, double[] dblC)
        {
            int i, j, k, u;
            double h, f, g, h2;

            // 初始化矩阵Q和T
            if (mtxQ.Init(src.Columns, src.Columns) == false || mtxT.Init(src.Columns, src.Columns) == false)
            {
                return false;
            }
            if (dblB == null || dblC == null)
            {
                return false;
            }
            for (i = 0; i <= src.Columns - 1; i++)
            {
                for (j = 0; j <= src.Columns - 1; j++)
                {
                    u = i * src.Columns + j;
                    mtxQ[u] = src[u];
                }
            }

            for (i = src.Columns - 1; i >= 1; i--)
            {
                h = 0.0;
                if (i > 1)
                {
                    for (k = 0; k <= i - 1; k++)
                    {
                        u = i * src.Columns + k;
                        h = h + mtxQ[u] * mtxQ[u];
                    }
                }

                if (Math.Abs(h) < float.Epsilon)
                {
                    dblC[i] = 0.0;
                    if (i == 1)
                    {
                        dblC[i] = mtxQ[i * src.Columns + i - 1];
                    }
                    dblB[i] = 0.0;
                }
                else
                {
                    dblC[i] = Math.Sqrt(h);
                    u = i * src.Columns + i - 1;
                    if (mtxQ[u] > 0.0)
                    {
                        dblC[i] = -dblC[i];
                    }
                    h = h - mtxQ[u] * dblC[i];
                    mtxQ[u] = mtxQ[u] - dblC[i];
                    f = 0.0;
                    for (j = 0; j <= i - 1; j++)
                    {
                        mtxQ[j * src.Columns + i] = mtxQ[i * src.Columns + j] / h;
                        g = 0.0;
                        for (k = 0; k <= j; k++)
                        {
                            g = g + mtxQ[j * src.Columns + k] * mtxQ[i * src.Columns + k];
                        }
                        if (j + 1 <= i - 1)
                        {
                            for (k = j + 1; k <= i - 1; k++)
                            {
                                g = g + mtxQ[k * src.Columns + j] * mtxQ[i * src.Columns + k];
                            }
                        }
                        dblC[j] = g / h;
                        f = f + g * mtxQ[j * src.Columns + i];
                    }

                    h2 = f / (h + h);
                    for (j = 0; j <= i - 1; j++)
                    {
                        f = mtxQ[i * src.Columns + j];
                        g = dblC[j] - h2 * f;
                        dblC[j] = g;
                        for (k = 0; k <= j; k++)
                        {
                            u = j * src.Columns + k;
                            mtxQ[u] = mtxQ[u] - f * dblC[k] - g * mtxQ[i * src.Columns + k];
                        }
                    }

                    dblB[i] = h;
                }
            }

            for (i = 0; i <= src.Columns - 2; i++)
            {
                dblC[i] = dblC[i + 1];
            }
            dblC[src.Columns - 1] = 0.0;
            dblB[0] = 0.0;
            for (i = 0; i <= src.Columns - 1; i++)
            {
                if ((dblB[i] != (double)0.0) && (i - 1 >= 0))
                {
                    for (j = 0; j <= i - 1; j++)
                    {
                        g = 0.0;
                        for (k = 0; k <= i - 1; k++)
                        {
                            g = g + mtxQ[i * src.Columns + k] * mtxQ[k * src.Columns + j];
                        }
                        for (k = 0; k <= i - 1; k++)
                        {
                            u = k * src.Columns + j;
                            mtxQ[u] = mtxQ[u] - g * mtxQ[k * src.Columns + i];
                        }
                    }
                }

                u = i * src.Columns + i;
                dblB[i] = mtxQ[u]; mtxQ[u] = 1.0;
                if (i - 1 >= 0)
                {
                    for (j = 0; j <= i - 1; j++)
                    {
                        mtxQ[i * src.Columns + j] = 0.0;
                        mtxQ[j * src.Columns + i] = 0.0;
                    }
                }
            }

            // 构造对称三对角矩阵
            for (i = 0; i < src.Columns; ++i)
            {
                for (j = 0; j < src.Columns; ++j)
                {
                    mtxT.SetElement(i, j, 0);
                    k = i - j;
                    if (k == 0)
                    {
                        mtxT.SetElement(i, j, dblB[j]);
                    }
                    else if (k == 1)
                    {
                        mtxT.SetElement(i, j, dblC[j]);
                    }
                    else if (k == -1)
                    {
                        mtxT.SetElement(i, j, dblC[i]);
                    }
                }
            }

            return true;
        }
 

    }
}
 

你可能感兴趣的:(C#数值计算,Numerical,Recipes,c#,开发语言)