/// <summary> /// Put the matrix in sorted form /// </summary> /// <param name="m"></param> /// <param name="constructor">The constructor for a null element of T</param> /// <param name="toIgnore"></param> /// <returns></returns> private static Matrix <T> ToSortedForm <T>( this Matrix <T> m, Func <T> constructor, int toIgnore = 0) where T : FieldMember, new() { Matrix <T> n = m.SortNullRows(constructor, toIgnore); int rowsSorted = -1; // Sort all the rows by switching while (!n.IsSorted(constructor, toIgnore)) { rowsSorted++; List <int> rows = Enumerable.Range(rowsSorted, n.Height - n.AmountOfNullRows(toIgnore) - rowsSorted).ToList(); int min = rows.Select(i => n.GetPivot(i, constructor, toIgnore)).Min(); int next = rows.First(i => n.GetPivot(i, constructor, toIgnore) == min); if (next == rowsSorted) { continue; } RowOperation <T> .SwitchingOperation(next, rowsSorted).ActOn(n); } return(n); }
/// <summary> /// Scale the rows so that each pivot is a 1 /// </summary> /// <param name="m"></param> /// <param name="constructor"></param> /// <param name="toIgnore"></param> /// <returns></returns> private static Matrix <T> ToUnitPivots <T>( this Matrix <T> m, Func <T> constructor, int toIgnore = 0) where T : FieldMember, new() { Matrix <T> n = m.ToEchelonForm(constructor, toIgnore); int i = 0; foreach (var vector in n[VectorType.Row]) { if (n.GetPivot(i, constructor, toIgnore) == -1) { continue; } try { T scale = constructor().Unit <T>() .Multiply(vector[n.GetPivot(i, constructor, toIgnore)].Inverse <T>()); RowOperation <T> .ScaleOperation(i, scale).ActOn(n); } catch (IncompatibleOperationException) { throw new ImpossibleEchelonFormException(); } i++; } return(n); }
public static Matrix <T> ToEchelonForm <T>( this Matrix <T> m, Func <T> constructor, int toIgnore = 0) where T : FieldMember, new() { Matrix <T> n = m.ToSortedForm(constructor); int from = -1; // Put the rows in echelon form (some substitution will be required) while (!n.IsEchelon(constructor, toIgnore)) { from++; // Substitution can unsort the rows if (!n.IsSorted(constructor, toIgnore)) { n = n.ToSortedForm(constructor, toIgnore); } List <int> rows = Enumerable.Range(from + 1, n.Height - n.AmountOfNullRows(toIgnore) - from - 1).ToList(); int pivot = n.GetPivot(from, constructor, toIgnore); foreach (var to in rows) { if (n.GetPivot(from, constructor, toIgnore) < n.GetPivot(to, constructor, toIgnore)) { continue; } if (n.GetPivot(from, constructor, toIgnore) == n.GetPivot(to, constructor, toIgnore)) { try { T scale = n[to, pivot].Negative <T>().Multiply(n[from, pivot].Inverse <T>()); RowOperation <T> .SubstitutionOperation(from, to, scale).ActOn(n); } catch (IncompatibleOperationException) { throw new ImpossibleEchelonFormException(); } } if (n.GetPivot(from, constructor, toIgnore) > n.GetPivot(to, constructor, toIgnore) && n.GetPivot(to, constructor, toIgnore) != -1) { RowOperation <T> .SwitchingOperation(from, to).ActOn(n); } } } return(n); }
/// <summary> /// Put all the null rows on the bottom of the matrix /// </summary> /// <param name="m"></param> /// <param name="constructor"></param> /// <param name="toIgnore"></param> /// <returns></returns> private static Matrix <T> SortNullRows <T>( this Matrix <T> m, Func <T> constructor, int toIgnore = 0) where T : FieldMember, new() { // First clone the matrix so that the original is not changed Matrix <T> n = new Matrix <T>(m); // Put all null rows on the bottom of the matrix while (!n.AreNullRowsBelow(constructor, toIgnore)) { List <int> toSwitch = n.MisplacedNullRows(constructor, toIgnore); int next = toSwitch.First(); // Switch the null row with the last non-null row RowOperation <T> .SwitchingOperation(next, n.Height + toSwitch.Count - n.AmountOfNullRows(toIgnore) - 1).ActOn(n); } return(n); }
/// <summary> /// Convert the Matrix to reduced echelon form /// </summary> /// <param name="m"></param> /// <param name="constructor">The constructor to make a null instance of T</param> /// <param name="toIgnore">The amount of rows that needn't be considered when converting.</param> /// <returns></returns> public static Matrix <T> ToReducedEchelonForm <T>( this Matrix <T> m, Func <T> constructor, int toIgnore = 0) where T : FieldMember, new() { // First convert to normal echelon form Matrix <T> n = m.ToUnitPivots(constructor, toIgnore); int from = n.Height - n.AmountOfNullRows(toIgnore); // Put the rows in echelon form (some substitution will be required) while (!n.IsReducedEchelon(constructor, toIgnore)) { from--; List <int> rows = Enumerable.Range(0, from).ToList(); // Go from the bottom to the top rows.Reverse(); int pivot = n.GetPivot(from, constructor, toIgnore); foreach (var to in rows) { if (!n[to, pivot].IsNull()) { try { T scale = n[to, pivot].Negative <T>().Multiply(n[from, pivot].Inverse <T>()); RowOperation <T> .SubstitutionOperation(from, to, scale).ActOn(n); } catch (IncompatibleOperationException) { throw new ImpossibleEchelonFormException(); } } } } return(n); }