public static Vector CalculateFFT(Vector v) { if (Math.Log(v.Size, 2) % 1 > 0) { v = PadWithZeros(v); } return CFFT(v); }
private void MakeDecomposition() { //if (!(M.IsSquare())) { // throw new MatrixException("The matrix needs to be square to compute the eigenvalues/eigenvectors!"); //} if (!(M.IsReal() && M.IsSymmetric())) { throw new MatrixException("The matrix needs to be real and symmetric, to reliably compute the eigenvalues/eigenvectors!"); } HessenbergDecomposition hessen = new HessenbergDecomposition(M); Matrix P = hessen.P; Matrix Ai = M.Copy(); QRDecomposition qr = Ai.QR(); Eigenvalues = new Vector(Ai.Width); Eigenvectors = qr.Q; for (int i = 0; i < ITERATION_DEPTH; i++) { Ai = qr.R * qr.Q; qr = Ai.QR(); Eigenvectors *= qr.Q; if (Ai.IsUpperTriangular()) { break; } } for (int j = 0; j < Ai.Height; j++) { Eigenvalues[j] = Ai[j, j]; } }
private static Vector DFT_Slow(Vector x) { int N = x.Size; Vector k = Vector.Arrange(N); Matrix n = k.Transpose(); Matrix M = MatrixMath.Exp(new Complex(0, 2) * Math.PI * k * n / N); return (M * x).ToColumnVector(); }
public static Vector CalculateIFFT(Vector v) { if (Math.Log(v.Size, 2) % 1 > 0) { v = PadWithZeros(v); } // The IFFT is the same as the FFT applied on the complex conjugate of the vector, divided by the size. return 1.0 / v.Size * CFFT(v.AppyToAllElements(x => x.Conjugate()).ToColumnVector()); }
public Vector this[Vector v] { get { return this[v, 0]; } set { this[v, 0] = value; } }
public static Matrix CalculateHouseholderTransform(Vector x) { if (x.EuclidianNorm() == 0) { return MatrixFactory.IdentityMatrix(x.Height); } double a = x[0].R == 0 ? x.EuclidianNorm() : Math.Sign(x[0].R) * x.EuclidianNorm(); Vector u = x + a * Vector.Ei(x.Size, 0); Vector v = u / u.EuclidianNorm(); Complex w = (x.ConjugateTranspose() * v).ToComplexNumber() / (v.ConjugateTranspose() * x).ToComplexNumber(); return (MatrixFactory.IdentityMatrix(x.Height) - (1.0 + w) * v * v.ConjugateTranspose()); }
private static Vector PadWithZeros(Vector x) { int N = x.Size; int pow2Size = (int)Math.Pow(2, Math.Ceiling(Math.Log(N) / Math.Log(2))); Vector newVec = new Vector(pow2Size); for (int i = 0; i < N; i++) { newVec[i] = x[i]; } for (int i = N; i < pow2Size; i++) { newVec[i] = 0; } return newVec; }
/// <summary> /// Create an n x n Hankel matrix based on the specified first and last column. /// </summary> /// <param name="firstColumn"></param> /// <param name="lastColumn"></param> /// <returns></returns> public static Matrix Hankel(Vector firstColumn, Vector lastColumn) { if (firstColumn.Size != lastColumn.Size) { throw new IncompatibleMatrixDimensionsException(firstColumn, lastColumn); } if (firstColumn[firstColumn.Size - 1] != lastColumn[0]) { throw new MatrixException("The last and first index of the specified vectors don't match!"); } Vector concat = firstColumn.ConcatenateRows(lastColumn[Vector.Arrange(1, lastColumn.Size)]).ToColumnVector(); Matrix newMat = new Matrix(firstColumn.Size); for (int i = 0; i < firstColumn.Size; i++) { newMat[Vector.Arrange(firstColumn.Size), i] = concat.SubMatrix(i, i + firstColumn.Size, 0, 1).ToColumnVector(); } return newMat; }
private void MakeDecomposition() { Matrix A = M.Copy(); Q = MatrixFactory.IdentityMatrix(M.Height); for (int k = 0; k < Math.Min(M.Height - 1, M.Width); k++) { Vector x = new Vector(A, 0); Matrix Q_k = MatrixMath.CalculateHouseholderTransform(x); A = (Q_k * A).SubMatrix(1, A.Height, 1, A.Width); Matrix Q_temp = MatrixFactory.IdentityMatrix(M.Height); Q_temp[Vector.Arrange(k, M.Height), Vector.Arrange(k, M.Height)] = Q_k; Q *= Q_temp.ConjugateTranspose(); } R = Q.ConjugateTranspose() * M; }
/// <summary> /// Given a vector space defined by the columns of the matrix x, an orthonormal projection y is calculated using the Gram-Schmidt process. /// </summary> /// <param name="x"></param> /// <returns></returns> public static Matrix GramSchmidthProcess(Matrix x) { Matrix y = MatrixFactory.Zeros(x.Height, x.Width); y[Vector.Arrange(y.Height), 0] = x[Vector.Arrange(x.Height), 0]; for (int i = 1; i < x.Width; i++) { Vector xi = x[Vector.Arrange(x.Height), i]; Vector projection = new Vector(xi.Size); for (int j = 0; j < i - 1; j++) { Vector yj = y[Vector.Arrange(y.Height), j]; projection += xi.DotProduct(yj) / yj.DotProduct(yj) * yj; } y[Vector.Arrange(y.Height), i] = x[Vector.Arrange(x.Height), i] - projection; } return y.NormalizeColumns(); }
private static Vector CFFT(Vector x) { int N = x.Size; if (N <= 32) { return DFT_Slow(x); } Vector evenIndices = Vector.Arrange(0, N, 2); Vector oddIndices = Vector.Arrange(1, N, 2); Vector X_even = CFFT(x[evenIndices]); Vector X_odd = CFFT(x[oddIndices]); Vector firstHalf = Vector.Arrange(N / 2); Vector secondHalf = Vector.Arrange(N / 2, N); Vector factor = MatrixMath.Exp(new Complex(0, 2) * Math.PI * Vector.Arrange(N) / N).ToColumnVector(); return (X_even + factor[firstHalf].ElementMultiply(X_odd)).ConcatenateRows( X_even + factor[secondHalf].ElementMultiply(X_odd)).ToColumnVector(); }
public Vector Solve(Vector b) { if (M.Height != b.Height) { throw new MatrixException("Wrong number of results in solution vector!"); } Vector x = new Vector(M.Height); if (M.IsSquare()) { // use LU decomposition LUDecomposition lu = M.LU(); Vector bp = (lu.P * b).ToColumnVector(); // Solves Ly = b using forward substitution Vector y = ForwardSubstitution(lu.L, bp); // Solves Ux = y using back substitution x = BackSubstitution(lu.U, y); } else { // use QR decomposition // TODO: Only works if M is full rank // overdetermined system if (M.Height >= M.Width) { QRDecomposition qr = M.QR(); Matrix R1 = qr.R.SubMatrix(0, M.Width, 0, M.Width); // Solves R1*x = Q.T*b using back substitution x = BackSubstitution(R1, (qr.Q.ConjugateTranspose() * b).ToColumnVector()); } else { // underdetermined system QRDecomposition qr = M.Transpose().QR(); // note the transpose here Matrix R1 = qr.R.SubMatrix(0, M.Height, 0, M.Height); Matrix Q1 = qr.Q.SubMatrix(0, M.Width, 0, M.Height); // Multiplies Q1 with the solution of R1.T*x = b using forward substitution x = (Q1 * ForwardSubstitution(R1.ConjugateTranspose(), b)).ToColumnVector(); } } return x; }
/// <summary> /// Index the matrix at the specified column with vector v. /// </summary> /// <param name="v"></param> /// <param name="column"></param> /// <returns></returns> public Vector this[Vector v, int column] { get { Vector newVec = new Vector(v.Size); for (int i = 0; i < v.Size; i++) { newVec[i] = Mat[(int)v[i].R, column]; } return newVec; } set { for (int i = 0; i < value.Size; i++) { Mat[(int)v[i].R, column] = value[i]; } } }
public MedianFilter(Vector data, int windowSize = 5) { Data = data.Copy(); WindowSize = windowSize; }
public IFilter Filter() { RectangularSmoothingFilter rFilter = new RectangularSmoothingFilter(Data); Data = rFilter.Filter().Filter().Data; return rFilter; }
public TriangularSmoothingFilter(Vector data) { Data = data.Copy(); }
/// <summary> /// Matrix A needs to be lower triangular /// </summary> /// <param name="A"></param> /// <param name="b"></param> /// <returns></returns> private Vector ForwardSubstitution(Matrix A, Vector b) { Vector x = new Vector(A.Height); for (int i = 0; i < A.Height; i++) { x[i] = b[i]; for (int j = 0; j < i; j++) { x[i] -= A[i, j] * x[j]; } x[i] = x[i] / A[i, i]; } return x; }
public Vector GetColumnVector(int column) { if (column < 0 || column >= Width) { throw new MatrixException("Exceeds matrix dimensions!"); } Vector v = new Vector(Height); for (int i = 0; i < Height; i++) { v[i] = this[i, column]; } return v; }
public Vector(Vector v) : base(v) { Size = this.Height; }
public Vector ToColumnVector() { if (Width != 1) { throw new MatrixException("Wrong matrix dimension to convert to column vector!"); } Vector v = new Vector(Height); for (int i = 0; i < Height; i++) { v[i] = Mat[i, 0]; } return v; }
public Complex DotProduct(Vector v) { if (Size != v.Size) { throw new IncompatibleMatrixDimensionsException(this, v); } Complex cSum = new Complex(); for (int i = 0; i < Size; i++) { cSum += this[i] * v[i].Conjugate(); } return cSum; }
public static Vector ParseFrom(string vecString) { vecString = vecString.Replace(" ", ""); string[] rows = vecString.Split(new char[] { ',', ';' }); Vector newVec = new Vector(rows.Length); try { for (int i = 0; i < newVec.Size; i++) { newVec[i] = new Complex(rows[i]); } } catch (Exception e) { Console.WriteLine(e.Message); } return newVec; }
/// <summary> /// Matrix A needs to be upper triangular /// </summary> /// <param name="A"></param> /// <param name="b"></param> /// <returns></returns> private Vector BackSubstitution(Matrix A, Vector b) { Vector x = new Vector(A.Height); for (int i = A.Height - 1; i > -1; i--) { x[i] = b[i]; for (int j = A.Width - 1; j > i; j--) { x[i] -= A[i, j] * x[j]; } x[i] = x[i] / A[i, i]; } return x; }
/// <summary> /// Index the matrix at the specified row with vector v. /// </summary> /// <param name="row"></param> /// <param name="v"></param> /// <returns></returns> public Vector this[int row, Vector v] { get { Vector newVec = new Vector(v.Size); for (int i = 0; i < v.Size; i++) { newVec[i] = Mat[row, (int)v[i].R]; } return newVec; } set { for (int i = 0; i < value.Size; i++) { Mat[row, (int)v[i].R] = value[i]; } } }
/// <summary> /// Index the matrix with all column vector and row vector indices. /// </summary> /// <param name="column"></param> /// <param name="row"></param> /// <returns></returns> public Matrix this[Vector column, Vector row] { get { Matrix newMat = new Matrix(column.Size, row.Size); for (int i = 0; i < column.Size; i++) { for (int j = 0; j < row.Size; j++) { newMat[i, j] = Mat[(int)column[i].R, (int)row[j].R]; } } return newMat; } set { for (int i = 0; i < value.Height; i++) { for (int j = 0; j < value.Width; j++) { Mat[(int)column[i].R, (int)row[j].R] = value[i, j]; } } } }
public Vector CrossProduct(Vector v) { if (Size != 3) { throw new MatrixException("Cross product only exists in 3D"); } Vector newV = new Vector(3); newV[0] = this[2] * v[3] - v[2] * this[3]; newV[1] = this[3] * v[1] - v[3] * this[1]; newV[2] = this[1] * v[2] - v[1] * this[2]; return newV; }
public void SetColumnVector(Vector v, int column) { if (column < 0 || column >= Width || Height != v.Size) { throw new MatrixException("Exceeds matrix dimensions!"); } for (int i = 0; i < Height; i++) { this[i, column] = v[i]; } }
public bool IsOrthogonalTo(Vector v) { return DotProduct(v) == 0; }
public PlotData(Vector x, Vector y, string name) { this.X = x; this.Y = y; this.Name = name; }
public Vector CircShift(int shift) { Vector newV = new Vector(Size); for (int i = 0; i < Size; i++) { newV[i] = this[ComplexMath.Mod((i + shift), Size)]; } return newV; }