/// <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. requests 后续1

    发送带数据post请求 import requests # 发送post请求 data = { } response = requests.post(url, data=data) # 内网 需要 认 ...

  2. 2017年6月28日 python爬虫学习

    1.写入csv文件2.lxml的用法3.自定义字典类的方法4.bytes解码得到str,str编码得到bytes5.json 1 import csv import lxml.html class S ...

  3. tinymce原装插件源码分析(三)-code

    code: 用于显示源码.主要包含一个弹框.设置显示内容以及内容的更新. function showDialog() { var win = editor.windowManager.open({ t ...

  4. 紫书 例题8-11 UVa 10954 (优先队列)

    解法和合并果子是一样的, 每次取最小的两个, 更新答案, 加入队列 #include<cstdio> #include<queue> #define REP(i, a, b) ...

  5. shell的通俗理解

    (引自:https://zhidao.baidu.com/question/557066905.html) [一] shell的含义: 首先shell的英文含义是“壳”: 它是相对于内核来说的,因为它 ...

  6. pydev 安装

    pydev断断续续空余时间安装了好几天,终于安装上了,需要注意的几点有, 1.插件地址 http://update-production-pydev.s3.amazonaws.com/pydev/up ...

  7. Querying mergeinfo requires version 3 of the FSFS filesystem schema svn右键没菜单

    svn 报错,Querying mergeinfo requires version 3 of the FSFS filesystem schema 经过查询,是svn客户端和服务端版本不一致造成的. ...

  8. angularjs 自定义服务

    <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...

  9. eclipse:报错信息The superclass “javax.servlet.http.HttpServlet” was not found on the Java Build Path

    JavaWeb: 报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the Java Bui ...

  10. Cms WebSite 编译非常慢

    第一次编译非常慢 如果遇到错误,中途中断的话. 下一次编译的时候,上一次已经编译过的文件,会非常快的略过.很快就会到上一次遇到错误的地方,继续往下进行编译.