/// <summary> /// Normalize according to folowing rules /// a) if there is a minus sign it will remain only in numerator /// b) if there is common divisor, both numerator and denominator are divided by this common divisor /// </summary> /// <returns></returns> public Rational <T, TPolicy> Normalize() { if (Policy.IsOne(Denominator)) { return(this); } if (Policy.IsZero(Numerator)) { return(new Rational <T, TPolicy>(Policy.Zero(), Policy.One())); } var n = Numerator; var d = Denominator; if ((Policy.IsBelowZero(n) && Policy.IsBelowZero(d)) || Policy.IsBelowZero(d)) { n = Policy.Negate(n); d = Policy.Negate(d); } var gcd = Policy.Gcd(Policy.Abs(n), d); if (!Policy.IsOne(gcd)) { n = Policy.Div(n, gcd); d = Policy.Div(d, gcd); } return(new Rational <T, TPolicy>(n, d)); }
/// <summary> /// Returns the column with the most negative coefficient in the objective function row. /// </summary> /// <param name="tableau"></param> /// <returns></returns> private int?GetPivotColumn(SimplexTableau <T, TPolicy> tableau) { T minValue = Policy.Zero(); int?minPos = null; for (int i = tableau.NumObjectiveFunctions; i < tableau.Width - 1; i++) { T entry = tableau.GetEntry(0, i); // check if the entry is strictly smaller than the current minimum // do not use a ulp/epsilon check if (Policy.IsBelowZero(Policy.Sub(entry, minValue))) { minValue = entry; minPos = i; // Bland's rule: chose the entering column with the lowest index if (pivotSelection == PivotSelectionRule.BLAND && IsValidPivotColumn(tableau, i)) { break; } } } return(minPos); }
/// <summary> /// True if |x - y| <= eps /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="eps"></param> /// <returns></returns> public static bool Equals(T x, T y, T eps) { return(Policy.IsBelowZero(Policy.Sub(Policy.Abs(Policy.Sub(y, x)), eps))); }