public double[,] Solve(double[,] value)
{
// Additionally an important property is that if there does not exists a solution
// when the matrix A is singular but replacing 1/Li with 0 will provide a solution
// that minimizes the residue |AX -Y|. SVD finds the least squares best compromise
// solution of the linear equation system. Interestingly SVD can be also used in an
// over-determined system where the number of equations exceeds that of the parameters.
// L is a diagonal matrix with non-negative matrix elements having the same
// dimension as A, Wi ? 0. The diagonal elements of L are the singular values of matrix A.
double[,] Y = value;
// Create L*, which is a diagonal matrix with elements
// L*[i] = 1/L[i] if L[i] < e, else 0,
// where e is the so-called singularity threshold.
// In other words, if L[i] is zero or close to zero (smaller than e),
// one must replace 1/L[i] with 0. The value of e depends on the precision
// of the hardware. This method can be used to solve linear equations
// systems even if the matrices are singular or close to singular.
//singularity threshold
double e = Threshold;
int scols = s.Length;
var Ls = new double[scols,scols];
for (int i = 0; i < s.Length; i++)
{
if (System.Math.Abs(s[i]) <= e)
Ls[i, i] = 0.0;
else Ls[i, i] = 1.0/s[i];
}
//(V x L*) x Ut x Y
double[,] VL = v.Multiply(Ls);
//(V x L* x Ut) x Y
int vrows = v.GetLength(0);
int urows = u.GetLength(0);
var VLU = new double[vrows,urows];
for (int i = 0; i < vrows; i++)
{
for (int j = 0; j < urows; j++)
{
double sum = 0;
for (int k = 0; k < urows; k++)
sum += VL[i, k]*u[j, k];
VLU[i, j] = sum;
}
}
//(V x L* x Ut x Y)
return VLU.Multiply(Y);
}