/// <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. c/s结构的自动化——pyautogui

    环境:Python 3.5.3 pip install pyautogui -i http://pypi.douban.com/simple --trusted-host pypi.douban.co ...

  2. [细节版]Let'sEncrypt 免费通配符/泛域名SSL证书添加使用教程

    参考网址:https://lnmp.org/faq/letsencrypt-wildcard-ssl.html 使用的dns服务商:阿里云 , 更多服务商地址可见参考网址. 遇见的问题一. [Sat ...

  3. windows下安装redis以及测试 Window 下安装

    下载地址:https://github.com/dmajkic/redis/downloads. 下载到的Redis支持32bit和64bit.根据自己实际情况选择,将64bit的内容cp到自定义盘符 ...

  4. unity Android在streamingAssets路径下文件无法读取的的解决方法

    unity Android在streamingAssets路径下文件,有时候plugin下的.jar或者.so无法直接读取: 解决方法之一,拷贝至其他路径: #if UNITY_ANDROID str ...

  5. UI布局【转】

    转载自: https://www.cnblogs.com/wangdaijun/p/5519459.html https://www.jianshu.com/p/f781c40df57c Good U ...

  6. C#-CLR各版本特点

    来自为知笔记(Wiz) 附件列表 CLR与NET版本关系.png NET框架工作流程.png VS与CLR关系.png

  7. Qt之图形(渐变填充)

    简述 QGradient可以和QBrush组合使用,来指定渐变填充. Qt目前支持三种类型的渐变填充: QLinearGradient:显示从起点到终点的渐变. QRadialGradient:以圆心 ...

  8. 页面头部带loading进度指示的jQuery滚动页面特效

    这是一款非常有用且效果非常酷的jQuery页面头部带loading进度指示的滚动页面特效. 该特效在页面滚动的时候页面头部有Loading进度条指示当前页面滚动的位置,这能够让用户知道当前阅读的地方距 ...

  9. 转:百分百激活office for mac2011的激活文件

    方法:1点击finder             2点击系统盘             3点击资源库             4找到Preferences文件夹             5用压缩包里的 ...

  10. excle查找操作-vlookup的使用心得

    百度了一下vlookup的语法规则: 该函数的语法规则例如以下: VLOOKUP(lookup_value,table_array,col_index_num,range_lookup) 參数 简单说 ...