private double LUSubstitute(MatrixR m, VectorR v) // m = A, v = b { int n = v.GetSize(); double det = 1.0; for (int i = 0; i < n; i++) // Ly = b { double d = v[i]; for (int j = 0; j < i; j++) { d -= m[i, j] * v[j]; } double dd = m[i, i]; if (Math.Abs(d) < epsilon) { throw new ArgumentException("Diagonal element is too small!"); } d /= dd; v[i] = d; //v = y det *= m[i, i]; } for (int i = n - 1; i >= 0; i--) { double d = v[i]; for (int j = i + 1; j < n; j++) { d -= m[i, j] * v[j]; } v[i] = d; // v=x } return(det); }
public static void Power(MatrixR A, double tolerance, out VectorR x, out double lambda) { int n = A.GetCols(); x = new VectorR(n); lambda = 0.0; double delta = 0.0; Random random = new Random(); for (int i = 0; i < n; i++) { x[i] = random.NextDouble(); } do { VectorR temp = x; x = MatrixR.Transform(A, x); x.Normalize(); if (VectorR.DotProduct(temp, x) < 0) { x = -x; } VectorR dx = temp - x; delta = dx.GetNorm(); }while (delta > tolerance); lambda = VectorR.DotProduct(x, MatrixR.Transform(A, x)); }
public VectorR GaussSeidel(MatrixR A, VectorR b, int MaxIterations, double tolerance) { int n = b.GetSize(); VectorR x = new VectorR(n); for (int nIteration = 0; nIteration < MaxIterations; nIteration++) { VectorR xOld = x.Clone(); for (int i = 0; i < n; i++) { double db = b[i]; double da = A[i, i]; if (Math.Abs(da) < epsilon) { throw new ArgumentException("Diagonal element is too small!"); } for (int j = 0; j < i; j++) { db -= A[i, j] * x[j]; } for (int j = i + 1; j < n; j++) { db -= A[i, j] * xOld[j]; } x[i] = db / da; } VectorR dx = x - xOld; if (dx.GetNorm() < tolerance) { //MessageBox.Show(nIteration.ToString()); return(x); } } return(x); }
public static void Rayleigh(MatrixR A, double tolerance, out VectorR x, out double lambda) { int n = A.GetCols(); double delta = 0.0; Random random = new Random(); x = new VectorR(n); for (int i = 0; i < n; i++) { x[i] = random.NextDouble(); } x.Normalize(); VectorR x0 = MatrixR.Transform(A, x); x0.Normalize(); lambda = VectorR.DotProduct(x, x0); double temp = lambda; do { temp = lambda; x0 = x; x0.Normalize(); x = MatrixR.Transform(A, x0); lambda = VectorR.DotProduct(x, x0); delta = Math.Abs((temp - lambda) / lambda); }while (delta > tolerance); x.Normalize(); }
public static void Inverse(MatrixR A, double s, double tolerance, out VectorR x, out double lambda) { int n = A.GetCols(); x = new VectorR(n); lambda = 0.0; double delta = 0.0; MatrixR identity = new MatrixR(n, n); A = A - s * (identity.Identity()); LinearSystem ls = new LinearSystem(); A = ls.LUInverse(A); Random random = new Random(); for (int i = 0; i < n; i++) { x[i] = random.NextDouble(); } do { VectorR temp = x; x = MatrixR.Transform(A, x); x.Normalize(); if (VectorR.DotProduct(temp, x) < 0) { x = -x; } VectorR dx = temp - x; delta = dx.GetNorm(); }while (delta > tolerance); lambda = s + 1.0 / (VectorR.DotProduct(x, MatrixR.Transform(A, x))); }
public static VectorR Transform(VectorR v, MatrixR m) { VectorR result = new VectorR(v.GetSize()); if (!m.IsSquared()) { throw new ArgumentOutOfRangeException( "Dimension", m.GetRows(), "The matrix must be squared!"); } if (m.GetRows() != v.GetSize()) { throw new ArgumentOutOfRangeException( "Size", v.GetSize(), "The size of the vector must be equal" + "to the number of rows of the matrix!"); } for (int i = 0; i < m.GetRows(); i++) { result[i] = 0.0; for (int j = 0; j < m.GetCols(); j++) { result[i] += v[j] * m[j, i]; } } return(result); }
public static void RayleighQuotient(MatrixR A, double tolerance, int flag, out VectorR x, out double lambda) { int n = A.GetCols(); double delta = 0.0; Random random = new Random(); x = new VectorR(n); if (flag != 2) { for (int i = 0; i < n; i++) { x[i] = random.NextDouble(); } x.Normalize(); lambda = VectorR.DotProduct(x, MatrixR.Transform(A, x)); } else { lambda = 0.0; Rayleigh(A, 1e-2, out x, out lambda); } double temp = lambda; MatrixR identity = new MatrixR(n, n); LinearSystem ls = new LinearSystem(); do { temp = lambda; double d = ls.LUCrout(A - lambda * identity.Identity(), x); x.Normalize(); lambda = VectorR.DotProduct(x, MatrixR.Transform(A, x)); delta = Math.Abs((temp - lambda) / lambda); }while (delta > tolerance); }
public VectorR GetUnitVector() { VectorR result = new VectorR(vector); result.Normalize(); return(result); }
public VectorR Clone() { // returns a deep copy of the vector VectorR v = new VectorR(vector); v.vector = (double[])vector.Clone(); return(v); }
public static VectorR operator -(VectorR v1, VectorR v2) { VectorR result = new VectorR(v1.size); for (int i = 0; i < v1.size; i++) { result[i] = v1[i] - v2[i]; } return(result); }
public static double DotProduct(VectorR v1, VectorR v2) { double result = 0.0; for (int i = 0; i < v1.size; i++) { result += v1[i] * v2[i]; } return(result); }
public static VectorR operator /(double d, VectorR v) { VectorR result = new VectorR(v.size); for (int i = 0; i < v.size; i++) { result[i] = d / v[i]; } return(result); }
public static VectorR operator /(VectorR v, double d) { VectorR result = new VectorR(v.size); for (int i = 0; i < v.size; i++) { result[i] = v[i] / d; } return(result); }
public static void Jacobi(MatrixR A, double tolerance, out MatrixR x, out VectorR lambda) { MatrixR AA = A.Clone(); int n = A.GetCols(); int maxTransform = 5 * n * n; MatrixR matrix = new MatrixR(n, n); MatrixR R = matrix.Identity(); MatrixR R1 = R; MatrixR A1 = A; lambda = new VectorR(n); x = R; double maxTerm = 0.0; int I, J; do { maxTerm = MaxTerm(A, out I, out J); Transformation(A, R, I, J, out A1, out R1); A = A1; R = R1; }while (maxTerm > tolerance); x = R; for (int i = 0; i < n; i++) { lambda[i] = A[i, i]; } for (int i = 0; i < n - 1; i++) { int index = i; double d = lambda[i]; for (int j = i + 1; j < n; j++) { if (lambda[j] > d) { index = j; d = lambda[j]; } } if (index != i) { lambda = lambda.GetSwap(i, index); x = x.GetColSwap(i, index); } } }
public VectorR GetColVector(int n) { if (n < 0 || n > Cols) { throw new ArgumentOutOfRangeException( "n", n, "n is out of range!"); } VectorR v = new VectorR(Rows); for (int i = 0; i < Rows; i++) { v[i] = matrix[i, n]; } return(v); }
public static VectorR NewtonMultiEquations(MFunction f, VectorR x0, double tolerance) { LinearSystem ls = new LinearSystem(); VectorR dx = new VectorR(x0.GetSize()); do { MatrixR A = Jacobian(f, x0); if (Math.Sqrt(VectorR.DotProduct(f(x0), f(x0)) / x0.GetSize()) < tolerance) { return(x0); } dx = ls.GaussJordan(A, -f(x0)); x0 = x0 + dx; }while (Math.Sqrt(VectorR.DotProduct(dx, dx)) > tolerance); return(x0); }
private static MatrixR Jacobian(MFunction f, VectorR x) { double h = 0.0001; int n = x.GetSize(); MatrixR jacobian = new MatrixR(n, n); VectorR x1 = x.Clone(); for (int j = 0; j < n; j++) { x1[j] = x[j] + h; for (int i = 0; i < n; i++) { jacobian[i, j] = (f(x1)[i] - f(x)[i]) / h; } } return(jacobian); }
public VectorR GaussJordan(MatrixR A, VectorR b) { Triangulate(A, b); int n = b.GetSize(); VectorR x = new VectorR(n); for (int i = n - 1; i >= 0; i--) { double d = A[i, i]; if (Math.Abs(d) < epsilon) { throw new ArgumentException("Diagonal element is too small!"); } x[i] = (b[i] - VectorR.DotProduct(A.GetRowVector(i), x)) / d; } return(x); }
public MatrixR LUInverse(MatrixR m) { int n = m.GetRows(); MatrixR u = m.Identity(); LUDecompose(m); VectorR uv = new VectorR(n); for (int i = 0; i < n; i++) { uv = u.GetRowVector(i); LUSubstitute(m, uv); u.ReplaceRow(uv, i); } MatrixR inv = u.GetTranspose(); return(inv); }
public MatrixR ReplaceCol(VectorR v, int n) { if (n < 0 || n > Cols) { throw new ArgumentOutOfRangeException( "n", n, "n is out of range!"); } if (v.GetSize() != Rows) { throw new ArgumentOutOfRangeException( "Vector size", v.GetSize(), "vector size is out of range!"); } for (int i = 0; i < Rows; i++) { matrix[i, n] = v[i]; } return(new MatrixR(matrix)); }
public static MatrixR Transform(VectorR v1, VectorR v2) { /*if (v1.GetSize() != v2.GetSize()) * { * throw new ArgumentOutOfRangeException( * "v1", v1.GetSize(), "The vectors must have the same size!"); * }*/ MatrixR result = new MatrixR(v1.GetSize(), v2.GetSize()); for (int i = 0; i < v1.GetSize(); i++) { for (int j = 0; j < v2.GetSize(); j++) { result[i, j] = v1[i] * v2[j]; } } return(result); }
public static VectorR CrossProduct(VectorR v1, VectorR v2) { if (v1.size != 3) { throw new ArgumentOutOfRangeException( "v1", v1, "Vector v1 must be 3 dimensional!"); } if (v2.size != 3) { throw new ArgumentOutOfRangeException( "v2", v2, "Vector v2 must be 3 dimensional!"); } VectorR result = new VectorR(3); result[0] = v1[1] * v2[2] - v1[2] * v2[1]; result[1] = v1[2] * v2[0] - v1[0] * v2[2]; result[2] = v1[0] * v2[1] - v1[1] * v2[0]; return(result); }
public static VectorR TriVectorProduct(VectorR v1, VectorR v2, VectorR v3) { if (v1.size != 3) { throw new ArgumentOutOfRangeException( "v1", v1, "Vector v1 must be 3 dimensional!"); } if (v1.size != 3) { throw new ArgumentOutOfRangeException( "v2", v2, "Vector v2 must be 3 dimensional!"); } if (v1.size != 3) { throw new ArgumentOutOfRangeException( "v3", v3, "Vector v3 must be 3 dimensional!"); } return(v2 * VectorR.DotProduct(v1, v3) - v3 * VectorR.DotProduct(v1, v2)); }
public static VectorR TridiagonalEigenvector(double s, double tolerance, out double lambda) { int n = Alpha.GetLength(0); double[] gamma = (double[])Beta.Clone(); double[] beta = (double[])Beta.Clone(); double[] alpha = new double[n]; for (int i = 0; i < n; i++) { alpha[i] = Alpha[i] - s; } double[] gamma1, alpha1, beta1; LUDecomposition(gamma, alpha, beta, out gamma1, out alpha1, out beta1); VectorR x = new VectorR(n); Random random = new Random(); for (int i = 0; i < n; i++) { x[i] = random.NextDouble(); } x.Normalize(); VectorR x1 = new VectorR(n);; double sign; do { x1 = x.Clone(); LUSolver(gamma1, alpha1, beta1, x); x.Normalize(); if (VectorR.DotProduct(x1, x) < 0.0) { sign = -1.0; x = -x; } else { sign = 1.0; } }while ((x - x1).GetNorm() > tolerance); lambda = s + sign / x.GetNorm(); return(x); }
private double pivot(MatrixR A, VectorR b, int q) { int n = b.GetSize(); int i = q; double d = 0.0; for (int j = q; j < n; j++) { double dd = Math.Abs(A[j, q]); if (dd > d) { d = dd; i = j; } } if (i > q) { A.GetRowSwap(q, i); b.GetSwap(q, i); } return(A[q, q]); }
public static MatrixR operator *(MatrixR m1, MatrixR m2) { if (m1.GetCols() != m2.GetRows()) { throw new ArgumentOutOfRangeException( "Columns", m1, "The numbers of columns of the first matrix must be equal to" + " the number of rows of the second matrix!"); } MatrixR result = new MatrixR(m1.GetRows(), m2.GetCols()); VectorR v1 = new VectorR(m1.GetCols()); VectorR v2 = new VectorR(m2.GetRows()); for (int i = 0; i < m1.GetRows(); i++) { v1 = m1.GetRowVector(i); for (int j = 0; j < m2.GetCols(); j++) { v2 = m2.GetColVector(j); result[i, j] = VectorR.DotProduct(v1, v2); } } return(result); }
public static double TriScalarProduct(VectorR v1, VectorR v2, VectorR v3) { if (v1.size != 3) { throw new ArgumentOutOfRangeException( "v1", v1, "Vector v1 must be 3 dimensional!"); } if (v1.size != 3) { throw new ArgumentOutOfRangeException( "v2", v2, "Vector v2 must be 3 dimensional!"); } if (v1.size != 3) { throw new ArgumentOutOfRangeException( "v3", v3, "Vector v3 must be 3 dimensional!"); } double result = v1[0] * (v2[1] * v3[2] - v2[2] * v3[1]) + v1[1] * (v2[2] * v3[0] - v2[0] * v3[2]) + v1[2] * (v2[0] * v3[1] - v2[1] * v3[0]); return(result); }
private void Triangulate(MatrixR A, VectorR b) { int n = A.GetRows(); VectorR v = new VectorR(n); for (int i = 0; i < n - 1; i++) { //double d = A[i, i]; double d = pivot(A, b, i); if (Math.Abs(d) < epsilon) { throw new ArgumentException("Diagonal element is too small!"); } for (int j = i + 1; j < n; j++) { double dd = A[j, i] / d; for (int k = i + 1; k < n; k++) { A[j, k] -= dd * A[i, k]; } b[j] -= dd * b[i]; } } }
public static VectorR LUSolver(double[] gamma, double[] alpha, double[] beta, VectorR b) { int n = alpha.GetLength(0); for (int i = 1; i < n; i++) { b[i] -= gamma[i - 1] * b[i - 1]; } b[n - 1] /= alpha[n - 1]; for (int i = n - 2; i > -1; i--) { b[i] = (b[i] - beta[i] * b[i + 1]) / alpha[i]; } return(b); }
public static MatrixR Tridiagonalize(MatrixR A) { int n = A.GetCols(); MatrixR A1 = new MatrixR(n, n); A1 = A.Clone(); double h, g, unorm; for (int i = 0; i < n - 2; i++) { VectorR u = new VectorR(n - i - 1); for (int j = i + 1; j < n; j++) { u[j - i - 1] = A[i, j]; } unorm = u.GetNorm(); if (u[0] < 0.0) { unorm = -unorm; } u[0] += unorm; for (int j = i + 1; j < n; j++) { A[j, i] = u[j - i - 1]; } h = VectorR.DotProduct(u, u) * 0.5; VectorR v = new VectorR(n - i - 1); MatrixR a1 = new MatrixR(n - i - 1, n - i - 1); for (int j = i + 1; j < n; j++) { for (int k = i + 1; k < n; k++) { a1[j - i - 1, k - i - 1] = A[j, k]; } } v = MatrixR.Transform(a1, u) / h; g = VectorR.DotProduct(u, v) / (2.0 * h); v -= g * u; for (int j = i + 1; j < n; j++) { for (int k = i + 1; k < n; k++) { A[j, k] = A[j, k] - v[j - i - 1] * u[k - i - 1] - u[j - i - 1] * v[k - i - 1]; } } A[i, i + 1] = -unorm; } Alpha = new double[n]; Beta = new double[n - 1]; Alpha[0] = A[0, 0]; for (int i = 1; i < n; i++) { Alpha[i] = A[i, i]; Beta[i - 1] = A[i - 1, i]; } MatrixR V = new MatrixR(n, n); V = V.Identity(); for (int i = 0; i < n - 2; i++) { VectorR u = new VectorR(n - i - 1); for (int j = i + 1; j < n; j++) { u[j - i - 1] = A.GetColVector(i)[j]; } h = VectorR.DotProduct(u, u) * 0.5; VectorR v = new VectorR(n - 1); MatrixR v1 = new MatrixR(n - 1, n - i - 1); for (int j = 1; j < n; j++) { for (int k = i + 1; k < n; k++) { v1[j - 1, k - i - 1] = V[j, k]; } } v = MatrixR.Transform(v1, u) / h; for (int j = 1; j < n; j++) { for (int k = i + 1; k < n; k++) { V[j, k] -= v[j - 1] * u[k - i - 1]; } } } return(V); }