/// <summary> /// Inverts square matrix as long as det != 0. /// </summary> /// <returns>Inverse of matrix.</returns> public SafeMatrix Inverse() { if (!this.IsSquare()) { throw new InvalidOperationException("Cannot invert non-square matrix."); } double det = this.Determinant(); if (det == 0) { throw new InvalidOperationException("Cannot invert (nearly) singular matrix."); } SafeMatrix buf = new SafeMatrix(m_ColumnCount, m_ColumnCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_ColumnCount; j++) { buf.m_Elements[i * buf.m_ColumnCount + j] = (Math.Pow(-1, i + j) * this.Minor(j, i).Determinant()) / det; } } return(buf); }
public SafeMatrix Minor(int row, int col) { // THIS IS THE LOW-LEVEL SOLUTION ~ O(n^2) SafeMatrix buf = new SafeMatrix(m_RowCount - 1, m_ColumnCount - 1); int r = 0; int c = 0; for (int i = 0; i < m_RowCount; i++) { if (i != row) { for (int j = 0; j < m_ColumnCount; j++) { if (j != col) { buf.m_Elements[r * buf.m_ColumnCount + c] = m_Elements[i * m_ColumnCount + j]; c++; } } c = 0; r++; } } return(buf); }
public double Determinant() { if (!this.IsSquare()) { throw new InvalidOperationException("Cannot calc determinant of non-square matrix."); } if (this.m_ColumnCount == 1) { return(this[0, 0]); } // perform LU-decomposition & return product of diagonal elements of U SafeMatrix X = this.Clone(); // for speed concerns, use this try { X.LU(); return(X.DiagProd()); } catch (DivideByZeroException) { // this is slower and needs more memory... . //Matrix P = X.LUSafe(); //return (double)P.Signum() * X.DiagProd(); throw; } }
public SafeMatrix Clone() { SafeMatrix A = new SafeMatrix(m_RowCount, m_ColumnCount); for (int i = 0; i < m_MatrixSize; i++) { A.m_Elements[i] = m_Elements[i]; } return(A); }
public static SafeMatrix operator *(double x, SafeMatrix A) { SafeMatrix B = new SafeMatrix(A.RowCount, A.ColumnCount); for (int i = 0; i < A.m_MatrixSize; i++) { B.m_Elements[i] = A.m_Elements[i] * x; } return(B); }
public SafeMatrix Transpose() { SafeMatrix M = new SafeMatrix(m_ColumnCount, m_RowCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_RowCount; j++) { M.m_Elements[i * M.m_ColumnCount + j] = m_Elements[j * m_ColumnCount + i]; } } return(M); }
public static double Dot(SafeMatrix v, int vRow, SafeMatrix w, int wCol) { if (v.ColumnCount != w.RowCount) { throw new ArgumentException("Vectors must be of the same length."); } double buf = 0; for (int i = 0; i < v.ColumnCount; i++) { buf += v.m_Elements[vRow * v.m_ColumnCount + i] * w.m_Elements[i * w.m_ColumnCount + wCol]; } return(buf); }
public static SafeMatrix operator *(SafeMatrix A, SafeMatrix B) { if (A.ColumnCount != B.RowCount) { throw new ArgumentException("Inner matrix dimensions must agree."); } SafeMatrix C = new SafeMatrix(A.RowCount, B.ColumnCount); for (int i = 0; i < A.RowCount; i++) { for (int j = 0; j < B.ColumnCount; j++) { C.m_Elements[i * C.m_ColumnCount + j] = Dot(A, i, B, j); } } return(C); }
public static SafeMatrix operator *(double x, SafeMatrix A) { SafeMatrix B = new SafeMatrix(A.RowCount, A.ColumnCount); for (int i = 0; i < A.m_MatrixSize; i++) { B.m_Elements[i] = A.m_Elements[i] * x; } return B; }
public SafeMatrix Transpose() { SafeMatrix M = new SafeMatrix(m_ColumnCount, m_RowCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_RowCount; j++) { M.m_Elements[i * M.m_ColumnCount + j] = m_Elements[j * m_ColumnCount + i]; } } return M; }
public SafeMatrix Minor(int row, int col) { // THIS IS THE LOW-LEVEL SOLUTION ~ O(n^2) SafeMatrix buf = new SafeMatrix(m_RowCount - 1, m_ColumnCount - 1); int r = 0; int c = 0; for (int i = 0; i < m_RowCount; i++) { if (i != row) { for (int j = 0; j < m_ColumnCount; j++) { if (j != col) { buf.m_Elements[r * buf.m_ColumnCount + c] = m_Elements[i * m_ColumnCount + j]; c++; } } c = 0; r++; } } return buf; }
/// <summary> /// Inverts square matrix as long as det != 0. /// </summary> /// <returns>Inverse of matrix.</returns> public SafeMatrix Inverse() { if (!this.IsSquare()) throw new InvalidOperationException("Cannot invert non-square matrix."); double det = this.Determinant(); if (det == 0) throw new InvalidOperationException("Cannot invert (nearly) singular matrix."); SafeMatrix buf = new SafeMatrix(m_ColumnCount, m_ColumnCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_ColumnCount; j++) { buf.m_Elements[i * buf.m_ColumnCount + j] = (Math.Pow(-1, i + j) * this.Minor(j, i).Determinant()) / det; } } return buf; }
public SafeMatrix Clone() { SafeMatrix A = new SafeMatrix(m_RowCount, m_ColumnCount); for (int i = 0; i < m_MatrixSize; i++) A.m_Elements[i] = m_Elements[i]; return A; }
public static double Dot(SafeMatrix v, int vRow, SafeMatrix w, int wCol) { if (v.ColumnCount != w.RowCount) throw new ArgumentException("Vectors must be of the same length."); double buf = 0; for (int i = 0; i < v.ColumnCount; i++) { buf += v.m_Elements[vRow * v.m_ColumnCount + i] * w.m_Elements[i * w.m_ColumnCount + wCol]; } return buf; }
public void Solve(bool useNormalisation, double t0_initialVal) { var varTimes = new List<double>(); var varMagnitudes = new List<double>(); double constNorm = double.NaN; if (!useNormalisation) { List<double> medianCalcList = new List<double>(m_CompData); medianCalcList.Sort(); constNorm = medianCalcList[medianCalcList.Count/2]; } C = 1; // Fix C to 1 M0 = FitM0ForT0(t0_initialVal, constNorm) - 1; // Get from known max magnitude of star for (int i = 0; i < m_NumObs; i++) { double mag = M0 - 2.5 * Math.Log10(m_VarData[i] / (!useNormalisation ? constNorm : m_CompData[i])); if (IsOutlier(i, mag)) continue; varTimes.Add(m_Times[i]); varMagnitudes.Add(mag); } if (varMagnitudes.Count < 7) { // Not enought data points for solving 5 variables IsSolved = false; return; } // Starting values C = 1; T0 = t0_initialVal; // Get from Kwee van Worden G = 0.5; // Get D from solving the equation to D (with other starting values specified) D = (varTimes[varMagnitudes.Count - 1] - T0) / Acosh(1 - Math.Log(1 - Math.Pow(1 - (varMagnitudes[varMagnitudes.Count - 1] - M0) / C, 1 / G))); if (double.IsNaN(D) || double.IsInfinity(D)) D = 0.1; NumberIterations = 100; double[] minCorr = new double[] {double.MaxValue, double.MaxValue, double.MaxValue, double.MaxValue, double.MaxValue}; //// Our guess ot T0 is very close, so assume it is contant and solve for G and D //for (int iter = NumberIterations; iter > 0; iter--) //{ // var A = new SafeMatrix(varMagnitudes.Count, 2); // var X = new SafeMatrix(varMagnitudes.Count, 1); // for (int index = 0; index < varMagnitudes.Count; index++) // { // double t = varTimes[index]; // double difference = ComputeModelValue(t) - varMagnitudes[index]; // X[index, 0] = -difference; // double GAMMA = 1 - Math.Exp(1 - Math.Cosh((t - T0) / D)); // double GAMMA_G = Math.Pow(GAMMA, G); // A[index, 0] = GAMMA_G * Math.Log(G); // G // A[index, 1] = -(G / D) * Math.Pow(GAMMA, G - 1) * Math.Exp(1 - Math.Cosh((t - T0) / D)) * Math.Sinh((t - T0) / D) * (t - T0) / D; // D // } // SafeMatrix a_T = A.Transpose(); // SafeMatrix aa = a_T * A; // SafeMatrix aa_inv = aa.Inverse(); // SafeMatrix Y = (aa_inv * a_T) * X; // D += Y[1, 0]; // if (D < 0) D = 0.001; // // Enforce maximum correction for G of |0.1|. G > 0 // //if (Y[0, 0] > 0.01) Y[0, 0] = 0.01; // //if (Y[0, 0] < -0.01) Y[0, 0] = -0.01; // G += Y[0, 0]; // if (G < 0) G = 0.001; // Trace.WriteLine(string.Format("D Corr: {0}\t\t G Corr: {1}", Y[1, 0], Y[0, 0])); //} for (int iter = NumberIterations; iter > 0; iter--) { var A = new SafeMatrix(varMagnitudes.Count, 3); var X = new SafeMatrix(varMagnitudes.Count, 1); for (int index = 0; index < varMagnitudes.Count; index++) { double t = varTimes[index]; double difference = ComputeModelValue(t) - varMagnitudes[index]; X[index, 0] = -difference; double GAMMA = 1 - Math.Exp(1 - Math.Cosh((t - T0) / D)); double GAMMA_G = Math.Pow(GAMMA, G); A[index, 0] = -GAMMA_G * Math.Log(G); // G A[index, 1] = (G / D) * Math.Pow(GAMMA, G - 1) * Math.Exp(1 - Math.Cosh((t - T0) / D)) * Math.Sinh((t - T0) / D); // T0 A[index, 2] = A[index, 1] * (t - T0) / D; // D } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix Y = (aa_inv * a_T) * X; if (minCorr[0] > Math.Abs(Y[0, 0])) minCorr[0] = Y[0, 0]; if (minCorr[1] > Math.Abs(Y[1, 0])) minCorr[1] = Y[1, 0]; if (minCorr[2] > Math.Abs(Y[2, 0])) minCorr[2] = Y[2, 0]; //if (Y[1, 0] > 0.0001) Y[1, 0] = 0.0001; //if (Y[1, 0] < -0.0001) Y[1, 0] = -0.0001; T0 += Y[1, 0]; Trace.WriteLine(string.Format("T0 Corr: {0}; ", Y[1, 0])); //if (Y[2, 0] > 0.01) Y[2, 0] = 0.01; //if (Y[2, 0] < -0.01) Y[2, 0] = -0.01; D += Y[2, 0]; if (D < 0) D = 0.001; // Enforce maximum correction for G of |0.1|. G > 0 //if (Y[0, 0] > 0.01) Y[0, 0] = 0.01; //if (Y[0, 0] < -0.01) Y[0, 0] = -0.01; G += Y[0, 0]; if (G < 0) G = 0.001; } //Trace.WriteLine(string.Format("{0}; {1}; {2}; {3}; {4}", minCorr[0], minCorr[1], minCorr[2], minCorr[3], minCorr[4])); Times.Clear(); NormIntensities.Clear(); var residuals = new List<double>(); for (int index = 0; index < varMagnitudes.Count; index++) { double t = varTimes[index]; Times.Add(t); double magVal = ComputeModelValue(t); double residual = magVal - varMagnitudes[index]; NormIntensities.Add(Math.Pow(10, (10 - magVal)/2.5)); residuals.Add(residual); } }
public void Solve(bool useNormalisation, double t0_initialVal) { var varTimes = new List <double>(); var varMagnitudes = new List <double>(); double constNorm = double.NaN; if (!useNormalisation) { List <double> medianCalcList = new List <double>(m_CompData); medianCalcList.Sort(); constNorm = medianCalcList[medianCalcList.Count / 2]; } C = 1; // Fix C to 1 M0 = FitM0ForT0(t0_initialVal, constNorm) - 1; // Get from known max magnitude of star for (int i = 0; i < m_NumObs; i++) { double mag = M0 - 2.5 * Math.Log10(m_VarData[i] / (!useNormalisation ? constNorm : m_CompData[i])); if (IsOutlier(i, mag)) { continue; } varTimes.Add(m_Times[i]); varMagnitudes.Add(mag); } if (varMagnitudes.Count < 7) { // Not enought data points for solving 5 variables IsSolved = false; return; } // Starting values C = 1; T0 = t0_initialVal; // Get from Kwee van Worden G = 0.5; // Get D from solving the equation to D (with other starting values specified) D = (varTimes[varMagnitudes.Count - 1] - T0) / Acosh(1 - Math.Log(1 - Math.Pow(1 - (varMagnitudes[varMagnitudes.Count - 1] - M0) / C, 1 / G))); if (double.IsNaN(D) || double.IsInfinity(D)) { D = 0.1; } NumberIterations = 100; double[] minCorr = new double[] { double.MaxValue, double.MaxValue, double.MaxValue, double.MaxValue, double.MaxValue }; //// Our guess ot T0 is very close, so assume it is contant and solve for G and D //for (int iter = NumberIterations; iter > 0; iter--) //{ // var A = new SafeMatrix(varMagnitudes.Count, 2); // var X = new SafeMatrix(varMagnitudes.Count, 1); // for (int index = 0; index < varMagnitudes.Count; index++) // { // double t = varTimes[index]; // double difference = ComputeModelValue(t) - varMagnitudes[index]; // X[index, 0] = -difference; // double GAMMA = 1 - Math.Exp(1 - Math.Cosh((t - T0) / D)); // double GAMMA_G = Math.Pow(GAMMA, G); // A[index, 0] = GAMMA_G * Math.Log(G); // G // A[index, 1] = -(G / D) * Math.Pow(GAMMA, G - 1) * Math.Exp(1 - Math.Cosh((t - T0) / D)) * Math.Sinh((t - T0) / D) * (t - T0) / D; // D // } // SafeMatrix a_T = A.Transpose(); // SafeMatrix aa = a_T * A; // SafeMatrix aa_inv = aa.Inverse(); // SafeMatrix Y = (aa_inv * a_T) * X; // D += Y[1, 0]; // if (D < 0) D = 0.001; // // Enforce maximum correction for G of |0.1|. G > 0 // //if (Y[0, 0] > 0.01) Y[0, 0] = 0.01; // //if (Y[0, 0] < -0.01) Y[0, 0] = -0.01; // G += Y[0, 0]; // if (G < 0) G = 0.001; // Trace.WriteLine(string.Format("D Corr: {0}\t\t G Corr: {1}", Y[1, 0], Y[0, 0])); //} for (int iter = NumberIterations; iter > 0; iter--) { var A = new SafeMatrix(varMagnitudes.Count, 3); var X = new SafeMatrix(varMagnitudes.Count, 1); for (int index = 0; index < varMagnitudes.Count; index++) { double t = varTimes[index]; double difference = ComputeModelValue(t) - varMagnitudes[index]; X[index, 0] = -difference; double GAMMA = 1 - Math.Exp(1 - Math.Cosh((t - T0) / D)); double GAMMA_G = Math.Pow(GAMMA, G); A[index, 0] = -GAMMA_G *Math.Log(G); // G A[index, 1] = (G / D) * Math.Pow(GAMMA, G - 1) * Math.Exp(1 - Math.Cosh((t - T0) / D)) * Math.Sinh((t - T0) / D); // T0 A[index, 2] = A[index, 1] * (t - T0) / D; // D } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix Y = (aa_inv * a_T) * X; if (minCorr[0] > Math.Abs(Y[0, 0])) { minCorr[0] = Y[0, 0]; } if (minCorr[1] > Math.Abs(Y[1, 0])) { minCorr[1] = Y[1, 0]; } if (minCorr[2] > Math.Abs(Y[2, 0])) { minCorr[2] = Y[2, 0]; } //if (Y[1, 0] > 0.0001) Y[1, 0] = 0.0001; //if (Y[1, 0] < -0.0001) Y[1, 0] = -0.0001; T0 += Y[1, 0]; Trace.WriteLine(string.Format("T0 Corr: {0}; ", Y[1, 0])); //if (Y[2, 0] > 0.01) Y[2, 0] = 0.01; //if (Y[2, 0] < -0.01) Y[2, 0] = -0.01; D += Y[2, 0]; if (D < 0) { D = 0.001; } // Enforce maximum correction for G of |0.1|. G > 0 //if (Y[0, 0] > 0.01) Y[0, 0] = 0.01; //if (Y[0, 0] < -0.01) Y[0, 0] = -0.01; G += Y[0, 0]; if (G < 0) { G = 0.001; } } //Trace.WriteLine(string.Format("{0}; {1}; {2}; {3}; {4}", minCorr[0], minCorr[1], minCorr[2], minCorr[3], minCorr[4])); Times.Clear(); NormIntensities.Clear(); var residuals = new List <double>(); for (int index = 0; index < varMagnitudes.Count; index++) { double t = varTimes[index]; Times.Add(t); double magVal = ComputeModelValue(t); double residual = magVal - varMagnitudes[index]; NormIntensities.Add(Math.Pow(10, (10 - magVal) / 2.5)); residuals.Add(residual); } }
public static SafeMatrix operator *(SafeMatrix A, SafeMatrix B) { if (A.ColumnCount != B.RowCount) throw new ArgumentException("Inner matrix dimensions must agree."); SafeMatrix C = new SafeMatrix(A.RowCount, B.ColumnCount); for (int i = 0; i < A.RowCount; i++) { for (int j = 0; j < B.ColumnCount; j++) { C.m_Elements[i * C.m_ColumnCount + j] = Dot(A, i, B, j); } } return C; }