/// <summary>
/// 行列式计算,本程序属于MyMathLib的一部分。欢迎使用,參考,提意见。
/// 有时间用函数语言改写,做自己得MathLib,里面的算法经过验证,但没经过
/// 严格測试,如需參考,请谨慎.
/// </summary>
public static partial class LinearAlgebra
{ /// <summary>
/// 获取指定i,j的余子式
/// </summary>
/// <param name="Determinants">N阶行列式</param>
/// <param name="i">第i行</param>
/// <param name="j">第j列</param>
/// <returns>计算结果</returns>
public static T[,] GetDeterminantMij<T>(T[,] Determinants, int i, int j)
{
var theN = Determinants.GetLength(0);
var theNewDeter = new T[theN - 1, theN - 1];
int theI = -1; for (int k = 0; k < theN; k++)
{
if (k == i - 1)
{
continue;
}
theI++;
int theJ = -1;
for (int l = 0; l < theN; l++)
{
if (l == j - 1)
{
continue;
}
theJ++;
theNewDeter[theI, theJ] = Determinants[k, l];
}
}
return theNewDeter;
}
/// <summary>
/// 获取指定i,j的余子式
/// </summary>
/// <param name="Determinants">N阶行列式</param>
/// <param name="Rows">要取得行</param>
/// <param name="Cols">要取得列</param>
/// <returns>计算结果</returns>
public static T[,] GetDeterminantMij<T>(T[,] Determinants, int[] Rows, int[] Cols)
{
if (Rows.Length != Cols.Length)
{
throw new Exception("所取行数和列数必须相等!");
}
var theN = Determinants.GetLength(0);
var theNewN = theN - Rows.Length;
var theNewDeter = new T[theNewN, theNewN];
int theI = -1; for (int k = 0; k < theN; k++)
{
if (Rows.Contains(k + 1))
{
continue;
}
theI++;
int theJ = -1;
for (int l = 0; l < theN; l++)
{
if (Cols.Contains(l + 1))
{
continue;
}
theJ++;
theNewDeter[theI, theJ] = Determinants[k, l];
}
}
return theNewDeter;
}
/// <summary>
/// 获取指定k阶子式N
/// </summary>
/// <param name="Determinants">N阶行列式</param>
/// <param name="Rows">要取得行</param>
/// <param name="Cols">要取得列</param>
/// <returns>计算结果</returns>
public static T[,] GetDeterminantKN<T>(T[,] Determinants, int[] Rows, int[] Cols)
{
if (Rows.Length != Cols.Length)
{
throw new Exception("所取行数和列数必须相等!");
}
var theNewN = Rows.Length;
var theNewDeter = new T[theNewN, theNewN];
for (int k = 0; k < Rows.Length; k++)
{
for (int l = 0; l < Cols.Length; l++)
{
theNewDeter[k, l] = Determinants[Rows[k] - 1, Cols[l] - 1];
}
}
return theNewDeter;
}
/// <summary>
/// 计算余子式的符号。 /// </summary>
/// <param name="i"></param>
/// <param name="j"></param>
/// <returns></returns>
public static int CalcDeterMijSign(int i, int j)
{
int theSign = 1;
if ((i + j) % 2 == 1)
{
theSign = -1;
}
return theSign;
}
/// <summary>
/// 计算余子式的符号。
/// </summary>
/// <param name="i"></param>
/// <param name="j"></param>
/// <returns></returns>
public static int CalcDeterMijSign(int[] Rows, int[] Cols)
{
int theSign = 1;
var theSum = Rows.Sum() + Cols.Sum();
if (theSum % 2 == 1)
{
theSign = -1;
}
return theSign;
}
/// <summary>
/// 降阶法计算行列式
/// </summary>
/// <param name="Determinants">N阶行列式</param>
/// <param name="ZeroOptimization">是否0优化</param>
/// <returns>计算结果</returns>
public static decimal CalcDeterminantAij(decimal[,] Determinants, bool ZeroOptimization = false)
{
var theN = Determinants.GetLength(0);
//假设为2阶,直接计算
if (theN == 2)
{
return Determinants[0, 0] * Determinants[1, 1] - Determinants[0, 1] * Determinants[1, 0];
}
if (ZeroOptimization)
{
//找0最多的行
int theRowIndex = 0;
int theMaxZeroCountR = -1;
for (int i = 0; i < theN; i++)
{
int theZeroNum = 0;
for (int j = 0; j < theN; j++)
{
if (Determinants[i, j] == 0)
{
theZeroNum++;
}
}
if (theZeroNum > theMaxZeroCountR)
{
theRowIndex = i;
theMaxZeroCountR = theZeroNum;
}
}
//找0最多的列
int theColIndex = 0;
int theMaxZeroCountC = -1;
for (int i = 0; i < theN; i++)
{
int theZeroNum = 0;
for (int j = 0; j < theN; j++)
{
if (Determinants[j, i] == 0)
{
theZeroNum++;
}
}
if (theZeroNum > theMaxZeroCountC)
{
theColIndex = i;
theMaxZeroCountC = theZeroNum;
}
}
if (theMaxZeroCountR >= theMaxZeroCountC)
{
decimal theRetDec = 0;
//第i=theRowIndex+1行展开
int i = theRowIndex + 1;
for (int j = 1; j <= theN; j++)
{
var theSign = CalcDeterMijSign(i, j);
var theNewMij = GetDeterminantMij(Determinants, i, j);
theRetDec += theSign * Determinants[i - 1, j - 1] * CalcDeterminantAij(theNewMij, ZeroOptimization);
}
return theRetDec;
}
else
{
decimal theRetDec = 0;
//第j=theColIndex+1列展开
int j = theColIndex + 1;
for (int i = 1; i <= theN; i++)
{
var theSign = CalcDeterMijSign(i, j);
var theNewMij = GetDeterminantMij(Determinants, i, j);
theRetDec += theSign * Determinants[i, j] * CalcDeterminantAij(theNewMij, ZeroOptimization);
}
return theRetDec;
}
}
else
{
//採用随机法展开一行
var i = new Random().Next(1, theN);
decimal theRetDec = 0;
for (int j = 1; j <= theN; j++)
{
var theSign = CalcDeterMijSign(i, j);
var theNewMij = GetDeterminantMij(Determinants, i, j);
theRetDec += theSign * Determinants[i-1, j-1] * CalcDeterminantAij(theNewMij, ZeroOptimization);
}
return theRetDec;
}
} /// <summary>
/// 计算范德蒙行列式
/// </summary>
/// <param name="Determinants">范德蒙行列式简记序列</param>
/// <returns>计算结果</returns>
public static decimal CalcVanDerModeDeter(decimal[] VanDerModeDeter)
{
var theN = VanDerModeDeter.Length;
if (theN == 1)
{
return 1;
}
decimal theRetDec = 1;
for (int i = 0; i < theN; i++)
{
for (int j = i + 1; j < theN; j++)
{
theRetDec *= (VanDerModeDeter[j] - VanDerModeDeter[i]);
}
}
return theRetDec;
}
/// <summary>
/// 获取奇数序列
/// </summary>
/// <param name="N"></param>
/// <returns></returns>
private static int[] GetLaplaceRowsOdd(int N)
{
var theRet = new List<int>();
for (int i = 0; i < N; i = i + 2)
{
theRet.Add(i + 1);
}
return theRet.ToArray();
} /// <summary>
/// 依据拉普拉斯定理计算行列式值。 /// </summary>
/// <param name="Determinants">N阶行列式</param>
/// <param name="Rows">初始展开行,里面採用奇数行展开</param>
/// <returns>计算结果</returns>
public static decimal CalcDeterByLaplaceLaw(decimal[,] Determinants, int[] Rows)
{
var n = Determinants.GetLength(0);
var k = Rows.Length;
//假设阶数小于3,则不是必需採用拉普拉斯展开
if (n <= 3)
{
return CalcDeterminantAij(Determinants, false);
}
//从P(theN,theK)
var theRetList = GetCombination(n, k);
decimal theRetDec = 0;
foreach (var theCols in theRetList)
{
var theSign = CalcDeterMijSign(Rows, theCols.ToArray());
var theKN = GetDeterminantKN(Determinants, Rows, theCols.ToArray());
var theN = GetDeterminantMij(Determinants, Rows, theCols.ToArray());
decimal theRetKN = 0;
//假设剩余阶数>4则採用随机半数处理.
if (n - k >= 4)
{
var theRows = GetLaplaceRowsOdd(n - k);
theRetKN = CalcDeterByLaplaceLaw(theKN, theRows);
}
else
{
theRetKN = CalcDeterminantAij(theKN);
}
decimal theRetAk = 0;
if (k >= 4)
{
var theRows = GetLaplaceRowsOdd(k);
theRetAk = CalcDeterByLaplaceLaw(theN, theRows);
}
else
{
theRetAk = CalcDeterminantAij(theN);
}
theRetDec += theSign * theRetKN * theRetAk;
}
return theRetDec;
}
/// <summary>
/// 从N个数中取k个数的组合结果。考虑到组合数没有顺序区分,因此仅仅要考虑从小
/// 到大的排列下的组合情况就可以,另外,假设组合也不用考虑元素反复的
/// 问题。假设有反复数,仅仅要除重就可以。 /// </summary>
/// <param name="N">N个数1-N</param>
/// <param name="k">取K个</param>
/// <returns></returns>
public static List<List<int>> GetCombination(int N, int k)
{
var theList = new List<int>();
for (int i = 1; i <= N; i++)
{
theList.Add(i);
}
return GetCombination(theList, k);
}
/// <summary>
/// 从N个中取k个数,算法原理C(N,k)=C(N-1,k)+ (a + C(Na-1,k-1));当中Na是N中去掉a后的集合.
/// </summary>
/// <param name="N">元素总个数</param>
/// <param name="k">取k个</param>
/// <returns></returns>
public static List<List<int>> GetCombination(List<int> N, int k)
{
if (k==0)
{
return null;
}
if (N.Count < k)
{
return null;
}
if (k == 1)
{
var theResultsList = new List<List<int>>();
foreach (var theN in N)
{
var theList = new List<int>();
theList.Add(theN);
theResultsList.Add(theList);
}
return theResultsList;
}
if (N.Count == k)
{
var theResultsList = new List<List<int>>();
var theList = new List<int>();
theList.AddRange(N);
theResultsList.Add(theList);
return theResultsList;
}
var theRet3 = new List<List<int>>();
int theLeft = N[0];
var theRight = new List<int>();
theRight.AddRange(N);
theRight.Remove(N[0]); var theRet2 = GetCombination(theRight, k);
theRet3.AddRange(theRet2); theRet2 = GetCombination(theRight, k - 1);
for (int n = 0; n < theRet2.Count; n++)
{
var theList = new List<int>();
theList.Add(theLeft);
theList.AddRange(theRet2[n]);
theRet3.Add(theList);
}
return theRet3;
}
}
}

MyMathLib系列(行列式计算2)的更多相关文章

  1. MyMathLib系列(行列式计算)

    靠人不如靠己,准备做自己得MathLib,在学校的时候,就想过把数学数理的东西都计算机化.但一直没有时间去做这件事情,如今认为空余 时间比較闲,就做做这件事情,先从线性代数開始,毕竟这里面的非常多算法 ...

  2. 行列式计算(C#)

    最近几天学习高等代数老师说要写个程序算行列式的结果,闲来无事就简单写了一下. 不多说了,上代码 using System; using System.Collections.Generic; usin ...

  3. n阶行列式计算----c语言实现(完结)

    花了半天时间,写了这个n阶行列式计算的程序,应该算是比较优美吧,有很多地方多次做了优化,程序占用内存不是很大,要是说小吧,也不合适,因为里边有一个递归,而且递归的深度还比较深.时间复杂度具体没有细看, ...

  4. Java实现行列式计算

    前天我看线代书,看到行列式,发现是个递归的式子,恰巧又正在学java,产生写程序实现的想法.写了两个小时,觉得实现了,写了个行列式放进去测试,我放的是 这个行列式,经过程序计算后发现结果是0.我以为我 ...

  5. 辛巴学院-Unity-剑英陪你零基础学c#系列(三)计算与类型

    辛巴学院:正大光明的不务正业. 中秋节快乐,每逢佳节倍思亲,尤其是那素未谋面的老婆,对吧,屌丝们.   今天我们来探索一下C#里面奇怪的计算,奇怪的类型. 奇怪的计算 当我刚刚接触计算机编程的时候,一 ...

  6. JavaScript系列:计算一个结果为30的加法智力题

    用下面这段JavaScript代码可以计算出来 function findTheThreeNum(numFix) { var a = ["1", "3", &q ...

  7. Vue.js系列之四计算属性和观察者

    一.计算属性 1.模版内的表达式非常便利,但是设计它们的初衷是用于简单计算的.在模版中放入太多的逻辑运算会让模版过重且难以维护,例如如下代码: <div id="example&quo ...

  8. python 行列式计算

    N= #声明2x2的数组arr并将所有元素赋值为 None arr=[[None] * N for row in range(N)] print('|a1 b1|') print('|a2 b2|') ...

  9. HDU 5852 Intersection is not allowed! ( 2016多校9、不相交路径的方案、LGV定理、行列式计算 )

    题目链接 题意 : 给定方格中第一行的各个起点.再给定最后一行与起点相对应的终点.问你从这些起点出发到各自的终点.不相交的路径有多少条.移动方向只能向下或向右 分析 : 首先对于多起点和多终点的不相交 ...

随机推荐

  1. (2016北京集训十)【xsy1530】小Q与内存

    一道很有意思的神题~ 暴力平衡树的复杂度很对(并不),但是$2^{30}$的空间一脸屎 这题的正解是一个类似线段树的数据结构,我觉得很有创新性Orz 首先可以想到一种暴力就是用一个点代表一个区间,然后 ...

  2. 解决new Date的值为Invalid Date、NaN-NaN的问题

    错误代码: let timespan = 1515239514230; let dateTime = new Date(timespan); console.log(dateTime) // 返回 I ...

  3. shell学习日志

    0.shell的变量同环境变量不同,存在用户环境区. 变量赋值的方式是: variable_name = variable_value a= "hello" $a对a进行取值 关于 ...

  4. mariadb数据库基础知识及备份

    数据库介绍 1.什么是数据库? 简单的说,数据库就是一个存放数据的仓库,这个仓库是按照一定的数据结构(数据结构是指数据的组织形式或数据之间的联系)来组织,存储的,我们可以通过数据库提供的多种方法来管理 ...

  5. ElementUi rules表单验证

    ElementUi 表单验证 工作中常用到的JS验证 可以在pattern中书写正则,并且配合elementUI进行表单验证. pattern 属性规定用于验证输入字段的模式.模式指的是正则表达式. ...

  6. C++容器(二):关联容器简介

    关联容器(associative container)与顺序容器的本质区别在于:关联容器通过键(Key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素.虽然,关联容器的大部分行为 ...

  7. LaTeX 简介与安装

    1 LaTeX 简介 Leslie Lamport 开发的 LaTeX 是当今世界上最流行和使用最为广泛的TeX格式.它构筑在Plain TeX的基础之上,并加进了很多的功能以使得使用者可以更为方便的 ...

  8. wget 升级

    漏洞描述: Wget是GNU计划开发的一套用于在网络上进行下载的自由软件,是Unix/Linux系统最常用的下载工具,支持通过HTTP.HTTPS以及FTP这三个最常见的TCP/IP协议下载. Wge ...

  9. List methods

    Python provides methods that operate on lists. For example, append adds a new element to the end of ...

  10. 版本控制器:SVN(精讲)

    版本控制器:SVN 1 开发中的实际问题 1.1 小明负责的模块就要完成了,就在即将Release之前的一瞬间,电脑突然蓝屏,硬盘光荣牺牲!几个月来的努力付之东流——需求之一:备份! 1.2 这个项目 ...