C#,数值计算——计算实对称矩阵所有特征值和特征向量的雅可比(Jacobi)方法与源程序

本文主要是介绍C#,数值计算——计算实对称矩阵所有特征值和特征向量的雅可比(Jacobi)方法与源程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 文本格式

using System;

namespace Legalsoft.Truffer
{
    /// <summary>
    /// Computes all eigenvalues and eigenvectors of
    /// a real symmetric matrix by Jacobi's method.
    /// </summary>
    public class Jacobi
    {
        private int n { get; set; }
        private double[,] a;
        private double[,] v;
        private double[] d;
        private int nrot { get; set; }
        private double EPS { get; set; }


        /// <summary>
        /// Computes all eigenvalues and eigenvectors of a real symmetric matrix
        /// a[0..n - 1][0..n - 1]. On output, d[0..n - 1] contains the eigenvalues of a
        /// sorted into descending order, while v[0..n - 1][0..n - 1] is a matrix whose
        /// columns contain the corresponding normalized eigenvectors.nrot contains
        /// the number of Jacobi rotations that were required.Only the upper triangle
        /// of a is accessed.
        /// </summary>
        /// <param name="aa"></param>
        /// <exception cref="Exception"></exception>
        public Jacobi(double[,] aa)
        {
            this.n = aa.GetLength(0);
            this.a = aa;
            this.v = new double[n, n];
            this.d = new double[n];
            this.nrot = 0;
            this.EPS = float.Epsilon;

            double[] b = new double[n];
            double[] z = new double[n];

            for (int ip = 0; ip < n; ip++)
            {
                for (int iq = 0; iq < n; iq++)
                {
                    v[ip, iq] = 0.0;
                }
                v[ip, ip] = 1.0;
            }
            for (int ip = 0; ip < n; ip++)
            {
                b[ip] = d[ip] = a[ip, ip];
                z[ip] = 0.0;
            }
            for (int i = 1; i <= 50; i++)
            {
                double sm = 0.0;
                for (int ip = 0; ip < n - 1; ip++)
                {
                    for (int iq = ip + 1; iq < n; iq++)
                    {
                        sm += Math.Abs(a[ip, iq]);
                    }
                }
                //if (sm == 0.0)
                if (Math.Abs(sm) <= float.Epsilon)
                {
                    eigsrt( d,  v);
                    return;
                }
                double tresh;
                if (i < 4)
                {
                    tresh = 0.2 * sm / (n * n);
                }
                else
                {
                    tresh = 0.0;
                }
                for (int ip = 0; ip < n - 1; ip++)
                {
                    for (int iq = ip + 1; iq < n; iq++)
                    {
                        double g = 100.0 * Math.Abs(a[ip, iq]);
                        if (i > 4 && g <= EPS * Math.Abs(d[ip]) && g <= EPS * Math.Abs(d[iq]))
                        {
                            a[ip, iq] = 0.0;
                        }
                        else if (Math.Abs(a[ip, iq]) > tresh)
                        {
                            double h = d[iq] - d[ip];
                            double t;
                            if (g <= EPS * Math.Abs(h))
                            {
                                t = (a[ip, iq]) / h;
                            }
                            else
                            {
                                double theta = 0.5 * h / (a[ip, iq]);
                                t = 1.0 / (Math.Abs(theta) + Math.Sqrt(1.0 + theta * theta));
                                if (theta < 0.0)
                                {
                                    t = -t;
                                }
                            }
                            double c = 1.0 / Math.Sqrt(1 + t * t);
                            double s = t * c;
                            double tau = s / (1.0 + c);
                            h = t * a[ip, iq];
                            z[ip] -= h;
                            z[iq] += h;
                            d[ip] -= h;
                            d[iq] += h;
                            a[ip, iq] = 0.0;
                            for (int j = 0; j < ip; j++)
                            {
                                rot( a, s, tau, j, ip, j, iq);
                            }
                            for (int j = ip + 1; j < iq; j++)
                            {
                                rot( a, s, tau, ip, j, j, iq);
                            }
                            for (int j = iq + 1; j < n; j++)
                            {
                                rot( a, s, tau, ip, j, iq, j);
                            }
                            for (int j = 0; j < n; j++)
                            {
                                rot( v, s, tau, j, ip, j, iq);
                            }
                            ++nrot;
                        }
                    }
                }
                for (int ip = 0; ip < n; ip++)
                {
                    b[ip] += z[ip];
                    d[ip] = b[ip];
                    z[ip] = 0.0;
                }
            }
            throw new Exception("Too many iterations in routine jacobi");
        }

        public void rot(double[,] a, double s, double tau, int i, int j, int k, int l)
        {
            double g = a[i, j];
            double h = a[k, l];
            a[i, j] = g - s * (h + g * tau);
            a[k, l] = h + s * (g - h * tau);
        }

        /// <summary>
        /// Given the eigenvalues d[0..n - 1] and(optionally) the eigenvectors
        /// v[0..n - 1][0..n - 1] as determined by Jacobi or tqli, this routine sorts the
        /// eigenvalues into descending order and rearranges the columns of v
        /// correspondingly.The method is straight insertion.
        /// </summary>
        /// <param name="d"></param>
        /// <param name="v"></param>
        public static void eigsrt(double[] d, double[,] v)
        {
            int k;
            int n = d.Length;
            for (int i = 0; i < n - 1; i++)
            {
                double p = d[k = i];
                for (int j = i; j < n; j++)
                {
                    if (d[j] >= p)
                    {
                        p = d[k = j];
                    }
                }
                if (k != i)
                {
                    d[k] = d[i];
                    d[i] = p;
                    if (v != null)
                    {
                        for (int j = 0; j < n; j++)
                        {
                            p = v[j, i];
                            v[j, i] = v[j, k];
                            v[j, k] = p;
                        }
                    }
                }
            }
        }
    }
}
 

2 代码格式

using System;namespace Legalsoft.Truffer
{/// <summary>/// Computes all eigenvalues and eigenvectors of/// a real symmetric matrix by Jacobi's method./// </summary>public class Jacobi{private int n { get; set; }private double[,] a;private double[,] v;private double[] d;private int nrot { get; set; }private double EPS { get; set; }/// <summary>/// Computes all eigenvalues and eigenvectors of a real symmetric matrix/// a[0..n - 1][0..n - 1]. On output, d[0..n - 1] contains the eigenvalues of a/// sorted into descending order, while v[0..n - 1][0..n - 1] is a matrix whose/// columns contain the corresponding normalized eigenvectors.nrot contains/// the number of Jacobi rotations that were required.Only the upper triangle/// of a is accessed./// </summary>/// <param name="aa"></param>/// <exception cref="Exception"></exception>public Jacobi(double[,] aa){this.n = aa.GetLength(0);this.a = aa;this.v = new double[n, n];this.d = new double[n];this.nrot = 0;this.EPS = float.Epsilon;double[] b = new double[n];double[] z = new double[n];for (int ip = 0; ip < n; ip++){for (int iq = 0; iq < n; iq++){v[ip, iq] = 0.0;}v[ip, ip] = 1.0;}for (int ip = 0; ip < n; ip++){b[ip] = d[ip] = a[ip, ip];z[ip] = 0.0;}for (int i = 1; i <= 50; i++){double sm = 0.0;for (int ip = 0; ip < n - 1; ip++){for (int iq = ip + 1; iq < n; iq++){sm += Math.Abs(a[ip, iq]);}}//if (sm == 0.0)if (Math.Abs(sm) <= float.Epsilon){eigsrt( d,  v);return;}double tresh;if (i < 4){tresh = 0.2 * sm / (n * n);}else{tresh = 0.0;}for (int ip = 0; ip < n - 1; ip++){for (int iq = ip + 1; iq < n; iq++){double g = 100.0 * Math.Abs(a[ip, iq]);if (i > 4 && g <= EPS * Math.Abs(d[ip]) && g <= EPS * Math.Abs(d[iq])){a[ip, iq] = 0.0;}else if (Math.Abs(a[ip, iq]) > tresh){double h = d[iq] - d[ip];double t;if (g <= EPS * Math.Abs(h)){t = (a[ip, iq]) / h;}else{double theta = 0.5 * h / (a[ip, iq]);t = 1.0 / (Math.Abs(theta) + Math.Sqrt(1.0 + theta * theta));if (theta < 0.0){t = -t;}}double c = 1.0 / Math.Sqrt(1 + t * t);double s = t * c;double tau = s / (1.0 + c);h = t * a[ip, iq];z[ip] -= h;z[iq] += h;d[ip] -= h;d[iq] += h;a[ip, iq] = 0.0;for (int j = 0; j < ip; j++){rot( a, s, tau, j, ip, j, iq);}for (int j = ip + 1; j < iq; j++){rot( a, s, tau, ip, j, j, iq);}for (int j = iq + 1; j < n; j++){rot( a, s, tau, ip, j, iq, j);}for (int j = 0; j < n; j++){rot( v, s, tau, j, ip, j, iq);}++nrot;}}}for (int ip = 0; ip < n; ip++){b[ip] += z[ip];d[ip] = b[ip];z[ip] = 0.0;}}throw new Exception("Too many iterations in routine jacobi");}public void rot(double[,] a, double s, double tau, int i, int j, int k, int l){double g = a[i, j];double h = a[k, l];a[i, j] = g - s * (h + g * tau);a[k, l] = h + s * (g - h * tau);}/// <summary>/// Given the eigenvalues d[0..n - 1] and(optionally) the eigenvectors/// v[0..n - 1][0..n - 1] as determined by Jacobi or tqli, this routine sorts the/// eigenvalues into descending order and rearranges the columns of v/// correspondingly.The method is straight insertion./// </summary>/// <param name="d"></param>/// <param name="v"></param>public static void eigsrt(double[] d, double[,] v){int k;int n = d.Length;for (int i = 0; i < n - 1; i++){double p = d[k = i];for (int j = i; j < n; j++){if (d[j] >= p){p = d[k = j];}}if (k != i){d[k] = d[i];d[i] = p;if (v != null){for (int j = 0; j < n; j++){p = v[j, i];v[j, i] = v[j, k];v[j, k] = p;}}}}}}
}

这篇关于C#,数值计算——计算实对称矩阵所有特征值和特征向量的雅可比(Jacobi)方法与源程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/457011

相关文章

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

在Golang中实现定时任务的几种高效方法

《在Golang中实现定时任务的几种高效方法》本文将详细介绍在Golang中实现定时任务的几种高效方法,包括time包中的Ticker和Timer、第三方库cron的使用,以及基于channel和go... 目录背景介绍目的和范围预期读者文档结构概述术语表核心概念与联系故事引入核心概念解释核心概念之间的关系

在Linux终端中统计非二进制文件行数的实现方法

《在Linux终端中统计非二进制文件行数的实现方法》在Linux系统中,有时需要统计非二进制文件(如CSV、TXT文件)的行数,而不希望手动打开文件进行查看,例如,在处理大型日志文件、数据文件时,了解... 目录在linux终端中统计非二进制文件的行数技术背景实现步骤1. 使用wc命令2. 使用grep命令

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

XML重复查询一条Sql语句的解决方法

《XML重复查询一条Sql语句的解决方法》文章分析了XML重复查询与日志失效问题,指出因DTO缺少@Data注解导致日志无法格式化、空指针风险及参数穿透,进而引发性能灾难,解决方案为在Controll... 目录一、核心问题:从SQL重复执行到日志失效二、根因剖析:DTO断裂引发的级联故障三、解决方案:修复

C++ 检测文件大小和文件传输的方法示例详解

《C++检测文件大小和文件传输的方法示例详解》文章介绍了在C/C++中获取文件大小的三种方法,推荐使用stat()函数,并详细说明了如何设计一次性发送压缩包的结构体及传输流程,包含CRC校验和自动解... 目录检测文件的大小✅ 方法一:使用 stat() 函数(推荐)✅ 用法示例:✅ 方法二:使用 fsee

Java继承映射的三种使用方法示例

《Java继承映射的三种使用方法示例》继承在Java中扮演着重要的角色,它允许我们创建一个类(子类),该类继承另一个类(父类)的所有属性和方法,:本文主要介绍Java继承映射的三种使用方法示例,需... 目录前言一、单表继承(Single Table Inheritance)1-1、原理1-2、使用方法1-