/// <returns>true if 'm' is symmetric up to a small epsilon constant</returns> public static bool IsSymmetric(DotNetMatrix.GeneralMatrix m) { const double EPS = 1e-6; DotNetMatrix.GeneralMatrix Z = m.Transpose(); Z = Z.Subtract(m); return (Z.NormInf() < EPS); }
public static String ToString(DotNetMatrix.GeneralMatrix m) { System.Text.StringBuilder result = new System.Text.StringBuilder(); for (int i = 0; i < m.RowDimension; i++) { for (int j = 0; j < m.ColumnDimension; j++) { result.Append(m.GetElement(i, j)); result.Append(" "); } result.Append("\n"); } return result.ToString(); }
public static bool IsDiagonal(DotNetMatrix.GeneralMatrix m) { const double EPS = 1e-6; for (int i = 0; i < m.RowDimension; i++) for (int j = 0; j < m.ColumnDimension; j++) if ((i != j) && (Math.Abs(m.GetElement(i, j)) > EPS)) return false; return true; }
/// <summary> /// Returns true when the matrix is diagonal and has only exact 0, +1 and/or -1 entries on the diagonal. /// </summary> /// <param name="m">the (square) matrix</param> /// <returns></returns> public static bool IsSimpleDiagonal(DotNetMatrix.GeneralMatrix m) { for (int i = 0; i < m.RowDimension; i++) for (int j = 0; j < m.ColumnDimension; j++) { double v = m.GetElement(i, j); if ((i != j) && (v != 0.0)) return false; else if (i == j) { if (!((v == 0.0) || (v == 1.0) || (v == -1.0))) return false; } } return true; }
/// <returns>true when exact 'value' is anywhere on the diagonal.</returns> public static bool HasValueOnDiagonal(DotNetMatrix.GeneralMatrix m, double value) { for (int i = 0; i < Math.Min(m.RowDimension, m.ColumnDimension); i++) { if (m.GetElement(i, i) == value) return true; } return false; }
/// <summary>Creates a new instance of Metric</summary> /// <param name="m">The NxN metric matrix</param> public Metric(DotNetMatrix.GeneralMatrix m) { init(m); // forward call to init() }
/// <summary>Initializes this Metric object from metric matrix (called by constructor) </summary> /// <param name="m">The NxN metric matrix</param> private void init(DotNetMatrix.GeneralMatrix m) { if (!Util.IsSymmetric(m)) throw new Exception("The metric matrix must be symmetric"); m_matrix = m.Copy(); // System.Console.WriteLine("m_matrix: " + Util.ToString(m_matrix)); // compute eigen value decomposition m_eig = new DotNetMatrix.EigenvalueDecomposition(m_matrix); // System.Console.WriteLine("m_eig: " + Util.ToString(m_eig.GetV())); m_invEigMatrix = m_eig.GetV().Transpose(); m_eigenMetric = m_eig.RealEigenvalues; // { // DotNetMatrix.GeneralMatrix D = Util.Diagonal(m_eigenMetric); // DotNetMatrix.GeneralMatrix tmp = m_eig.GetV().Multiply(D).Multiply(m_invEigMatrix); // System.Console.WriteLine("input_matrix = " + Util.ToString(tmp)); // } m_isDiagonal = Util.IsDiagonal(m_matrix); if (!m_isDiagonal) { m_isEuclidean = m_isAntiEuclidean = false; } else { m_isEuclidean = m_isAntiEuclidean = true; for (int i = 0; i < m.RowDimension; i++) { if (m_matrix.GetElement(i, i) != 1.0) m_isEuclidean = false; if (m_matrix.GetElement(i, i) != -1.0) m_isAntiEuclidean = false; } } }
/// <summary> /// Transforms a basis blade to another basis which is represented by the columns of M. /// </summary> /// <param name="a">The basis blade to transform according to <paramref name="M"/>.</param> /// <param name="M">The matrix to use to transform <paramref name="a"/>.</param> /// <returns>a list of BasisBlade whose sum represents <paramref name="a"/> on the new basis.</returns> public static ArrayList Transform(BasisBlade a, DotNetMatrix.GeneralMatrix M) { ArrayList A = new ArrayList(); A.Add(new BasisBlade(0, a.scale, a.symScale)); // start with just the scalar part; int dim = M.RowDimension; // for each 1 bit: convert to list of blades int i = 0; uint b = a.bitmap; while (b != 0) { if ((b & 1) != 0) { // take column 'i' out of the matrix, wedge it to 'A' ArrayList tmp = new ArrayList(); for (int j = 0; j < dim; j++) { double m = M.GetElement(j, i); if (m != 0.0) { for (int k = 0; k < A.Count; k++) { BasisBlade o = BasisBlade.op((BasisBlade)A[k], new BasisBlade((uint)(1 << j), m)); if (o.scale != 0.0) tmp.Add(o); } } } A = tmp; } b >>= 1; i++; } return A; }
/// <summary> /// Constructor where caller determines the value of all fields (used internally by RoundEigenMetric()) /// </summary> protected Metric(DotNetMatrix.GeneralMatrix matrix, DotNetMatrix.EigenvalueDecomposition eig, double[] eigenMetric, DotNetMatrix.GeneralMatrix invEigMatrix, bool isDiagonal, bool isEuclidean, bool isAntiEuclidean) { m_eigenMetric = eigenMetric; m_matrix = matrix; m_eig = eig; m_eigenMetric = eigenMetric; m_invEigMatrix = invEigMatrix; m_isDiagonal = isDiagonal; m_isEuclidean = isEuclidean; m_isAntiEuclidean = isAntiEuclidean; }