主要是线性代数的第2章的算法,由于本章的大部分都是概念性的,而且后面还有矩阵,因此算法较少:
/*Vector.cs
* Albert.Tian on 20141225
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyMathLib
{
/// <summary>
/// 向量相关运算,这里没有给出向量的基本变换。因为
/// 向量组可以用矩阵表达,因此很多向量的运算最终都归于矩阵运算。
/// 本算法中的求极大线性无关组,是根据课本算法得出,不是最简单的一种方法,
/// 在矩阵表达中,可以根据矩阵的初等变换,很容易求到极大线性无关组.
/// 这个类在后面被重新定义.
/// </summary>
public class Vectors
{
/// <summary>
/// 判断从0到指定结束位的元素是否全是0.
/// </summary>
/// <param name="CurrVector">当前向量</param>
/// <param name="EndIndex">结束索引</param>
/// <returns></returns>
public static bool IsZeroVector(double[] CurrVector, int EndIndex = 0)
{
int theEndIndex = EndIndex;
if (theEndIndex == 0)
{
theEndIndex = CurrVector.Length;
}
var theIsZeroVector = true;
for (int i = 0; i < theEndIndex; i++)
{
if (CurrVector[i] != 0)
{
theIsZeroVector = false;
break;
}
}
return theIsZeroVector;
}
/// <summary>
/// 判断当前向量是否与前面的向量线性相关,采用的是消元化
/// </summary>
/// <param name="CurrVector">当前向量</param>
/// <param name="PrevMaxLIVectors">已有的线性无关的向量组</param>
/// <returns></returns>
private static bool IsLinearCorrelation(double[] CurrVector, List<double[]> PrevMaxLIVectors)
{
//零向量必是线性相关
var theIsZeroVector = IsZeroVector(CurrVector);
if (theIsZeroVector)
{
return true;
}
//如果前面没有向量,则当前非零向量必是线性无关的.
if (PrevMaxLIVectors.Count <= 0)
{
return false;
}
//构造方程式,判断是否线性相关
var theECount = CurrVector.Length;
var theVCount = PrevMaxLIVectors.Count;
//加入当前向量为常量向量,因此方程组的列为theVCount+1.
var theEquealGroup = new double[theECount, theVCount + 1];
//导入PrevMaxLIVectors
for (int i = 0; i < theVCount; i++)
{
for (int j = 0; j < theECount; j++)
{
theEquealGroup[j, i] = PrevMaxLIVectors[i][j];
}
}
//加入当前向量作为常量向量
for (int j = 0; j < theECount; j++)
{
theEquealGroup[j, theVCount] = CurrVector[j];
}
//消元,这里的消元法变成了求矩阵秩的基本算法.
LinearAlgebra.EquationsElimination(theEquealGroup);
//如果theRA<theRA1,则有矛盾方程,必然线性无关,如果theRA>=theRA1,则至少有一个非零解。
//这里如此判断,主要是因为消元的方法。当然,这在矩阵有证。
var theRA = 0;
var theRA1 = 0;
for (int i = 0; i < theECount; i++)
{
if (!IsZeroVector(theEquealGroup.GetVectorRow(i), theVCount))
{
theRA++;
}
if (!IsZeroVector(theEquealGroup.GetVectorRow(i)))
{
theRA1++;
}
}
return (theRA >= theRA1);
}
/// <summary>
/// 这个函数暂时无用,判断两个向量的等价性
/// </summary>
/// <param name="V1"></param>
/// <param name="V2"></param>
/// <returns></returns>
private static bool IsEquivalent(double[] V1, double[] V2)
{
var theV1IsZeroVector = IsZeroVector(V1);
var theV2IsZeroVector = IsZeroVector(V2);
//两个都是0向量
if (theV1IsZeroVector && theV2IsZeroVector)
{
return true;
}
//其中一个零向量,另一个是非零向量
if (theV1IsZeroVector || theV2IsZeroVector)
{
return false;
}
//一个分量肯定成比例
if (V1.Length <= 1)
{
return true;
}
double thePreRate = 0;
var theCount = V1.Length;
var theIndex = 0;
for (int i = 0; i < theCount; i++)
{
//如果都等于0,则不比较
if (V1[i] == V2[i] && V2[i] == 0)
{
continue;
}
//如果其中一个是0,则必然不成比例,不等价
if (V1[i] == 0 || V2[i] == 0)
{
return false;
}
if (theIndex == 0)
{
thePreRate = V1[i] / V2[i];
theIndex++;
}
else
{
if (thePreRate != V1[i] / V2[i])
{
return false;
}
}
}
return true;
}
/// <summary>
/// 获取向量组的极大线性无关组,方法是依照教科书写的。
/// 这个方法的效率比较低,后面的矩阵方法会比较好.
/// </summary>
/// <param name="Vectors">向量组</param>
/// <returns></returns>
public static List<double[]> GetMaxLinearIndependentGroup(double[,] Vectors)
{
//向量个数
var theVCount = Vectors.GetLength(0);
//元数个数
var theECount = Vectors.GetLength(1);
List<double[]> theTempVectors = new List<double[]>();
for (int i = 0; i < theVCount; i++)
{
var theTempVector = Vectors.GetVectorRow(i);
//如果当前向量不能被前面的向量线性表出,则加入到极大组
//能不能线性表出,实际上就是求当前向量加入前面的向量组后,
//还是不是线性相关
if (!IsLinearCorrelation(theTempVector, theTempVectors))
{
theTempVectors.Add(theTempVector);
}
}
return theTempVectors;
}
}
}