44 namespace SpikingNeuronNetwork.Lib
47 using System.Collections.Generic;
48 using System.Text.RegularExpressions;
55 private const double Epsilon = 1e-5;
58 private double _detOfP = 1;
60 private double[,] Mat {
get; set; }
69 Mat =
new double[iRows, iCols];
77 get {
return Mat.GetLength(0); }
85 get {
return Mat.GetLength(1); }
93 get {
return (Rows == Cols); }
102 public double this[
int iRow,
int iCol]
104 get {
return Mat[iRow, iCol]; }
105 set { Mat[iRow, iCol] = value; }
115 if (ReferenceEquals(null, obj))
return false;
116 if (ReferenceEquals(
this, obj))
return true;
117 return obj.GetType() == GetType() && Equals((
Matrix)obj);
133 var hashCode = (Mat != null ? Mat.GetHashCode() : 0);
134 hashCode = (hashCode * 397) ^ Rows;
135 hashCode = (hashCode * 397) ^ Cols;
147 var m =
new Matrix(1, Cols);
148 for (var i = 0; i < Cols; i++) m[0, i] = Mat[k, i];
159 var m =
new Matrix(Rows, 1);
160 for (var i = 0; i < Rows; i++) m[i, 0] = Mat[i, k];
171 var indices =
new List<int>();
172 for (var row = 0; row < Rows; row ++)
174 for (var col = 0; col < Cols; col++)
176 if (Math.Abs(Mat[row, col] - val) < Epsilon)
178 indices.Add(col + row*Cols);
192 var indices =
new List<int>();
193 for (var row = 0; row < Rows; row++)
195 for (var col = 0; col < Cols; col++)
197 if (Math.Abs(Mat[row, col] - val) >= Epsilon)
199 indices.Add(col + row * Cols);
213 for (var i = 0; i < Rows; i++) Mat[i, k] = v[i, 0];
222 L = IdentityMatrix(Rows, Cols);
226 for (var i = 0; i < Rows; i++) _pi[i] = i;
230 for (var k = 0; k < Cols - 1; k++)
233 for (var i = k; i < Rows; i++)
235 if (Math.Abs(U[i, k]) > p)
237 p = Math.Abs(U[i, k]);
241 if (Math.Abs(p - 0) < Epsilon)
249 for (var i = 0; i < k; i++)
256 if (k != k0) _detOfP *= -1;
258 for (var i = 0; i < Cols; i++)
265 for (var i = k + 1; i < Rows; i++)
267 L[i, k] = U[i, k]/U[k, k];
268 for (var j = k; j < Cols; j++)
269 U[i, j] = U[i, j] - L[i, k]*U[k, j];
281 if (Rows != Cols)
throw new MatrixException(
"The matrix is not square!");
282 if (Rows != v.
Rows)
throw new MatrixException(
"Wrong number of results in solution vector!");
283 if (L == null) MakeLU();
285 var b =
new Matrix(Rows, 1);
286 for (var i = 0; i < Rows; i++) b[i, 0] = v[_pi[i], 0];
288 var z = SubsForth(L, b);
289 var x = SubsBack(U, z);
300 if (L == null) MakeLU();
302 var inv =
new Matrix(Rows, Cols);
304 for (var i = 0; i < Rows; i++)
306 var ei = ZeroMatrix(Rows, 1);
308 var col = SolveWith(ei);
320 if (L == null) MakeLU();
322 for (var i = 0; i < Rows; i++) det *= U[i, i];
332 if (L == null) MakeLU();
334 var matrix = ZeroMatrix(Rows, Cols);
335 for (var i = 0; i < Rows; i++) matrix[_pi[i], i] = 1;
345 var matrix =
new Matrix(Rows, Cols);
346 for (var i = 0; i < Rows; i++)
347 for (var j = 0; j < Cols; j++)
348 matrix[i, j] = Mat[i, j];
360 if (mA.L == null) mA.MakeLU();
364 for (var i = 0; i < n; i++)
367 for (var j = 0; j < i; j++) x[i, 0] -= mA[i, j]*x[j, 0];
368 x[i, 0] = x[i, 0]/mA[i, i];
381 if (mA.L == null) mA.MakeLU();
385 for (var i = n - 1; i > -1; i--)
388 for (var j = n - 1; j > i; j--) x[i, 0] -= mA[i, j]*x[j, 0];
389 x[i, 0] = x[i, 0]/mA[i, i];
402 var matrix =
new Matrix(iRows, iCols);
403 for (var i = 0; i < iRows; i++)
404 for (var j = 0; j < iCols; j++)
418 var matrix =
new Matrix(iRows, iCols);
419 for (var i = 0; i < iRows; i++)
420 for (var j = 0; j < iCols; j++)
433 var matrix = ZeroMatrix(iRows, iCols);
434 for (var i = 0; i < Math.Min(iRows, iCols); i++)
449 var random =
new Random();
450 var matrix =
new Matrix(iRows, iCols);
451 for (var i = 0; i < iRows; i++)
452 for (var j = 0; j < iCols; j++)
453 matrix[i, j] = (random.NextDouble() <= probability) ? dispersion*2*(random.NextDouble() - 0.5) : 0;
464 var s = NormalizeMatrixString(ps);
465 var rows = Regex.Split(s,
"\r\n");
466 var nums = rows[0].Split(
' ');
467 var matrix =
new Matrix(rows.Length, nums.Length);
470 for (var i = 0; i < rows.Length; i++)
472 nums = rows[i].Split(
' ');
473 for (var j = 0; j < nums.Length; j++) matrix[i, j] =
double.Parse(nums[j]);
476 catch (FormatException)
490 for (
int i = 0; i < Rows; i++)
492 for (
int j = 0; j < Cols; j++) s += String.Format(
"{0,5:0.00}", Mat[i, j]) +
" ";
506 for (
int i = 0; i < m.Rows; i++)
507 for (
int j = 0; j < m.Cols; j++)
520 if (pow == 0)
return IdentityMatrix(m.
Rows, m.
Cols);
521 if (pow == 1)
return m.Clone();
522 if (pow == -1)
return m.Invert();
536 if ((pow & 1) == 1) ret *= x;
543 private static void SafeAplusBintoC(
Matrix mA,
int xa,
int ya,
Matrix mB,
int xb,
int yb,
Matrix mC,
int size)
545 for (
int i = 0; i < size; i++)
546 for (
int j = 0; j < size; j++)
549 if (xa + j < mA.
Cols && ya + i < mA.
Rows) mC[i, j] += mA[ya + i, xa + j];
550 if (xb + j < mB.
Cols && yb + i < mB.
Rows) mC[i, j] += mB[yb + i, xb + j];
554 private static void SafeAminusBintoC(Matrix mA,
int xa,
int ya, Matrix mB,
int xb,
int yb, Matrix mC,
int size)
556 for (
int i = 0; i < size; i++)
557 for (
int j = 0; j < size; j++)
560 if (xa + j < mA.Cols && ya + i < mA.Rows) mC[i, j] += mA[ya + i, xa + j];
561 if (xb + j < mB.Cols && yb + i < mB.Rows) mC[i, j] -= mB[yb + i, xb + j];
565 private static void SafeACopytoC(Matrix mA,
int xa,
int ya, Matrix mC,
int size)
567 for (
int i = 0; i < size; i++)
568 for (
int j = 0; j < size; j++)
571 if (xa + j < mA.Cols && ya + i < mA.Rows) mC[i, j] += mA[ya + i, xa + j];
575 private static void AplusBintoC(Matrix mA,
int xa,
int ya, Matrix mB,
int xb,
int yb, Matrix mC,
int size)
577 for (
int i = 0; i < size; i++)
578 for (
int j = 0; j < size; j++) mC[i, j] = mA[ya + i, xa + j] + mB[yb + i, xb + j];
581 private static void AminusBintoC(Matrix mA,
int xa,
int ya, Matrix mB,
int xb,
int yb, Matrix mC,
int size)
583 for (
int i = 0; i < size; i++)
584 for (
int j = 0; j < size; j++) mC[i, j] = mA[ya + i, xa + j] - mB[yb + i, xb + j];
587 private static void ACopytoC(Matrix mA,
int xa,
int ya, Matrix mC,
int size)
589 for (
int i = 0; i < size; i++)
590 for (
int j = 0; j < size; j++) mC[i, j] = mA[ya + i, xa + j];
593 private static Matrix StrassenMultiply(Matrix mA, Matrix mB)
595 if (mA.Cols != mB.Rows)
throw new MatrixException(
"Wrong dimension of matrix!");
599 int msize = Math.Max(Math.Max(mA.Rows, mA.Cols), Math.Max(mB.Rows, mB.Cols));
603 mR = ZeroMatrix(mA.Rows, mB.Cols);
604 for (
int i = 0; i < mR.Rows; i++)
605 for (
int j = 0; j < mR.Cols; j++)
606 for (
int k = 0; k < mA.Cols; k++)
607 mR[i, j] += mA[i, k]*mB[k, j];
622 var mField =
new Matrix[n,9];
631 for (var i = 0; i < n - 4; i++)
633 var z = (int) Math.Pow(2, n - i - 1);
634 for (
int j = 0; j < 9; j++) mField[i, j] =
new Matrix(z, z);
637 SafeAplusBintoC(mA, 0, 0, mA, h, h, mField[0, 0], h);
638 SafeAplusBintoC(mB, 0, 0, mB, h, h, mField[0, 1], h);
639 StrassenMultiplyRun(mField[0, 0], mField[0, 1], mField[0, 1 + 1], 1, mField);
641 SafeAplusBintoC(mA, 0, h, mA, h, h, mField[0, 0], h);
642 SafeACopytoC(mB, 0, 0, mField[0, 1], h);
643 StrassenMultiplyRun(mField[0, 0], mField[0, 1], mField[0, 1 + 2], 1, mField);
645 SafeACopytoC(mA, 0, 0, mField[0, 0], h);
646 SafeAminusBintoC(mB, h, 0, mB, h, h, mField[0, 1], h);
647 StrassenMultiplyRun(mField[0, 0], mField[0, 1], mField[0, 1 + 3], 1, mField);
649 SafeACopytoC(mA, h, h, mField[0, 0], h);
650 SafeAminusBintoC(mB, 0, h, mB, 0, 0, mField[0, 1], h);
651 StrassenMultiplyRun(mField[0, 0], mField[0, 1], mField[0, 1 + 4], 1, mField);
653 SafeAplusBintoC(mA, 0, 0, mA, h, 0, mField[0, 0], h);
654 SafeACopytoC(mB, h, h, mField[0, 1], h);
655 StrassenMultiplyRun(mField[0, 0], mField[0, 1], mField[0, 1 + 5], 1, mField);
657 SafeAminusBintoC(mA, 0, h, mA, 0, 0, mField[0, 0], h);
658 SafeAplusBintoC(mB, 0, 0, mB, h, 0, mField[0, 1], h);
659 StrassenMultiplyRun(mField[0, 0], mField[0, 1], mField[0, 1 + 6], 1, mField);
661 SafeAminusBintoC(mA, h, 0, mA, h, h, mField[0, 0], h);
662 SafeAplusBintoC(mB, 0, h, mB, h, h, mField[0, 1], h);
663 StrassenMultiplyRun(mField[0, 0], mField[0, 1], mField[0, 1 + 7], 1, mField);
665 mR =
new Matrix(mA.Rows, mB.Cols);
668 for (
int i = 0; i < Math.Min(h, mR.Rows); i++)
669 for (
int j = 0; j < Math.Min(h, mR.Cols); j++)
670 mR[i, j] = mField[0, 1 + 1][i, j] + mField[0, 1 + 4][i, j] - mField[0, 1 + 5][i, j] +
671 mField[0, 1 + 7][i, j];
674 for (
int i = 0; i < Math.Min(h, mR.Rows); i++)
675 for (
int j = h; j < Math.Min(2*h, mR.Cols); j++)
676 mR[i, j] = mField[0, 1 + 3][i, j - h] + mField[0, 1 + 5][i, j - h];
679 for (
int i = h; i < Math.Min(2*h, mR.Rows); i++)
680 for (
int j = 0; j < Math.Min(h, mR.Cols); j++)
681 mR[i, j] = mField[0, 1 + 2][i - h, j] + mField[0, 1 + 4][i - h, j];
684 for (
int i = h; i < Math.Min(2*h, mR.Rows); i++)
685 for (
int j = h; j < Math.Min(2*h, mR.Cols); j++)
686 mR[i, j] = mField[0, 1 + 1][i - h, j - h] - mField[0, 1 + 2][i - h, j - h] +
687 mField[0, 1 + 3][i - h, j - h] + mField[0, 1 + 6][i - h, j - h];
694 private static void StrassenMultiplyRun(Matrix mA, Matrix mB, Matrix mC,
int l, Matrix[,] f)
702 for (
int i = 0; i < mC.Rows; i++)
703 for (
int j = 0; j < mC.Cols; j++)
706 for (
int k = 0; k < mA.Cols; k++) mC[i, j] += mA[i, k]*mB[k, j];
711 AplusBintoC(mA, 0, 0, mA, h, h, f[l, 0], h);
712 AplusBintoC(mB, 0, 0, mB, h, h, f[l, 1], h);
713 StrassenMultiplyRun(f[l, 0], f[l, 1], f[l, 1 + 1], l + 1, f);
715 AplusBintoC(mA, 0, h, mA, h, h, f[l, 0], h);
716 ACopytoC(mB, 0, 0, f[l, 1], h);
717 StrassenMultiplyRun(f[l, 0], f[l, 1], f[l, 1 + 2], l + 1, f);
719 ACopytoC(mA, 0, 0, f[l, 0], h);
720 AminusBintoC(mB, h, 0, mB, h, h, f[l, 1], h);
721 StrassenMultiplyRun(f[l, 0], f[l, 1], f[l, 1 + 3], l + 1, f);
723 ACopytoC(mA, h, h, f[l, 0], h);
724 AminusBintoC(mB, 0, h, mB, 0, 0, f[l, 1], h);
725 StrassenMultiplyRun(f[l, 0], f[l, 1], f[l, 1 + 4], l + 1, f);
727 AplusBintoC(mA, 0, 0, mA, h, 0, f[l, 0], h);
728 ACopytoC(mB, h, h, f[l, 1], h);
729 StrassenMultiplyRun(f[l, 0], f[l, 1], f[l, 1 + 5], l + 1, f);
731 AminusBintoC(mA, 0, h, mA, 0, 0, f[l, 0], h);
732 AplusBintoC(mB, 0, 0, mB, h, 0, f[l, 1], h);
733 StrassenMultiplyRun(f[l, 0], f[l, 1], f[l, 1 + 6], l + 1, f);
735 AminusBintoC(mA, h, 0, mA, h, h, f[l, 0], h);
736 AplusBintoC(mB, 0, h, mB, h, h, f[l, 1], h);
737 StrassenMultiplyRun(f[l, 0], f[l, 1], f[l, 1 + 7], l + 1, f);
740 for (
int i = 0; i < h; i++)
741 for (
int j = 0; j < h; j++)
742 mC[i, j] = f[l, 1 + 1][i, j] + f[l, 1 + 4][i, j] - f[l, 1 + 5][i, j] + f[l, 1 + 7][i, j];
745 for (
int i = 0; i < h; i++)
746 for (
int j = h; j < size; j++)
747 mC[i, j] = f[l, 1 + 3][i, j - h] + f[l, 1 + 5][i, j - h];
750 for (
int i = h; i < size; i++)
751 for (
int j = 0; j < h; j++)
752 mC[i, j] = f[l, 1 + 2][i - h, j] + f[l, 1 + 4][i - h, j];
755 for (
int i = h; i < size; i++)
756 for (
int j = h; j < size; j++)
757 mC[i, j] = f[l, 1 + 1][i - h, j - h] - f[l, 1 + 2][i - h, j - h] + f[l, 1 + 3][i - h, j - h] +
758 f[l, 1 + 6][i - h, j - h];
761 private static Matrix Multiply(
double n, Matrix m)
763 var r =
new Matrix(m.Rows, m.Cols);
764 for (
int i = 0; i < m.Rows; i++)
765 for (
int j = 0; j < m.Cols; j++)
770 private static Matrix Add(Matrix m1, Matrix m2)
772 if (m1.Rows != m2.Rows || m1.Cols != m2.Cols)
773 throw new MatrixException(
"Matrices must have the same dimensions!");
774 var r =
new Matrix(m1.Rows, m1.Cols);
775 for (
int i = 0; i < r.Rows; i++)
776 for (
int j = 0; j < r.Cols; j++)
777 r[i, j] = m1[i, j] + m2[i, j];
781 private static string NormalizeMatrixString(
string matStr)
784 while (matStr.IndexOf(
" ", StringComparison.Ordinal) != -1)
785 matStr = matStr.Replace(
" ",
" ");
788 matStr = matStr.Replace(
" \r\n",
"\r\n");
789 matStr = matStr.Replace(
"\r\n ",
"\r\n");
794 matStr = matStr.Replace(
"\r\n",
"|");
795 while (matStr.LastIndexOf(
"|", StringComparison.Ordinal) == (matStr.Length - 1))
796 matStr = matStr.Substring(0, matStr.Length - 1);
798 matStr = matStr.Replace(
"|",
"\r\n");
811 return Multiply(-1, m);
823 for (var i = 0; i < m2.Rows; i++)
824 for (var j = 0; j < m2.Cols; j++)
825 m3[i, j] = m2[i,j] + m1;
870 return StrassenMultiply(m1, m2);
881 return Multiply(n, m);
894 for (var i = 0; i < m1.Rows; i++)
895 for (var j = 0; j < m1.Cols; j++)
896 if (Math.Abs(m1[i, j] - m2[i, j]) > Epsilon)
return false;
static Matrix IdentityMatrix(int iRows, int iCols)
Gets an indentity matrix of size iRows by iCols
Matrix SolveWith(Matrix v)
Solve Ax = v for x, where A is the current matrix
double Det()
Calculates the matrix determinant
Matrix Clone()
Gets a deep copy of the matrix
Matrix GetCol(int k)
Gets a column matrix
static Matrix Transpose(Matrix m)
Gets a transposed matrix
override string ToString()
Returns a string representation of the matrix
Matrix Invert()
Inverts the current matrix
override bool Equals(object obj)
Indicates if a matrix is equal to an object
int Cols
Gets the number of columns in the matrix
override int GetHashCode()
Gets a hash code representation of the matrix
static Matrix SubsBack(Matrix mA, Matrix b)
Solves Ax = b for A as an upper triangular matrix
static Matrix ZeroMatrix(int iRows, int iCols)
Gets a matrix of zeros of size iRows by iCols
Matrix(int iRows, int iCols)
Creates a new instance of Matrix of size iRows and iCols
static Matrix Power(Matrix m, int pow)
Gets a matrix raised to an integer power
Matrix GetRow(int k)
Gets a row matrix
static Matrix ConstantMatrix(int iRows, int iCols, double val)
Gets a matrix of constant values equal to val of size iRows by iCols
void MakeLU()
Perform LU Decomposition
Matrix GetPermutationMatrix()
Gets a permutation matrix "P" due to permutation vector "pi"
void SetCol(Matrix v, int k)
Sets a column of the matrix to a given column matrix
static Matrix RandomMatrix(int iRows, int iCols, double dispersion, double probability=1.0)
Gets a matrix of random numbers of size iRows by iCols
List< int > FindAllIndexOfNot(double val)
Gets a list of a indices where the value is not equal to val within epsilon
int Rows
Gets the number of rows in the matrix
static Matrix SubsForth(Matrix mA, Matrix b)
Solves Ax = b for A as a lower triangular matrix
static Matrix Parse(string ps)
Gets a matrix as parsed from a string delimited by spaces and newlines
List< int > FindAllIndexOf(double val)
Gets a list of a indices where the value is equal to val within epsilon