/// <summary> /// Filters the surges in a sequence whose absolute values deviate from the specified positive value by a /// positive factor specified. /// </summary> /// <typeparam name="T">The type of elements in the incoming sequence.</typeparam> /// <typeparam name="C">The calculator for the sequence elements type.</typeparam> /// <param name="sequence">A calling sequence object.</param> /// <param name="centerValue">A nonnegative value. Sequence elements that deviate from this value by more than <paramref name="allowedDeviationFactor"/> will be filtered out.</param> /// <param name="allowedDeviationFactor">The allowed factor of absolute deviation.</param> /// <param name="deviationType"> /// If deviation type is Downwards, values which are smaller than <paramref name="centerValue"/> /// by a factor of <paramref name="allowedDeviationFactor"/> will be filtered. /// If deviation type is Upwards, values which are bigger than <paramref name="centerValue"/> /// by a factor of <paramref name="allowedDeviationFactor"/> will be filtered. /// If deviation type is EitherSide, all values that differ from the <paramref name="centerValue"/> /// by a factor of <paramref name="allowedDeviationFactor"/> will be filtered. /// </param> /// <param name="filteredValues">A reference to a collection to store the filtered values. May be null.</param> /// <returns>The list containing all incoming values except for the filtered ones.</returns> public static List <T> filterSurgesByAbsoluteFactorDeviationFromValue <T, C>(this IEnumerable <T> sequence, T centerValue, double allowedDeviationFactor, DeviationType deviationType = DeviationType.EitherSide, ICollection <T> filteredValues = null) where C : ICalc <T>, new() { ICalc <T> calc = Numeric <T, C> .Calculator; (centerValue > Numeric <T, C> .Zero).Assert(new ArgumentException("The center value specified should be positive.")); (allowedDeviationFactor > 0).Assert(new ArgumentException("The allowed deviation factor should be positive.")); List <T> result = new List <T>(); foreach (Numeric <T, C> current in sequence) { Numeric <T, C> absCurrent = WhiteMath <T, C> .Abs(current); Numeric <T, C> multipliedValue = (Numeric <T, C>)allowedDeviationFactor * centerValue; Numeric <T, C> multipliedCurrent = (Numeric <T, C>)allowedDeviationFactor * absCurrent; if (deviationType == DeviationType.EitherSide && (absCurrent > multipliedValue || multipliedCurrent < centerValue) || deviationType == DeviationType.Upwards && absCurrent > multipliedValue || deviationType == DeviationType.Downwards && multipliedCurrent < centerValue) { // Filter the surge. if (filteredValues != null) { filteredValues.Add(current); } } else { result.Add(current); } } return(result); }
/// <summary> /// Adds relative (factor) surges from a symmetric distribution random generator to each value of a numeric sequence /// and returns the nosiy sequence in the form of a list. /// </summary> /// <typeparam name="T">The type of elements in the numeric sequence.</typeparam> /// <typeparam name="C">The calculator for the <typeparamref name="T"/> type.</typeparam> /// <param name="sequence">The calling numeric sequence object.</param> /// <param name="symmetricDistributionGenerator">A random generator providing values of some symmetric distribution.</param> /// <param name="deviationType">Which deviations (positive, negative or both) should be added to the sequence.</param> /// <returns></returns> public static List <T> addRelativeSurgesFromSymmetricDistribution <T, C>(this IEnumerable <T> sequence, IRandomUnbounded <T> symmetricDistributionGenerator, DeviationType deviationType) where C : ICalc <T>, new() { List <T> result = new List <T>(sequence.Count()); foreach (Numeric <T, C> value in sequence) { if (deviationType == DeviationType.EitherSide) { result.Add(value + value * symmetricDistributionGenerator.Next()); } else if (deviationType == DeviationType.Downwards) { result.Add(value - WhiteMath <T, C> .Abs(value * symmetricDistributionGenerator.Next())); } else { result.Add(value + WhiteMath <T, C> .Abs(value * symmetricDistributionGenerator.Next())); } } return(result); }
/// <summary> /// Filters the surges in a sequence whose absolute values deviate from the specified positive value by a /// nonnegative value specified. /// </summary> /// <typeparam name="T">The type of elements in the incoming sequence.</typeparam> /// <typeparam name="C">The calculator for the sequence elements type.</typeparam> /// <param name="sequence">A calling sequence object.</param> /// <param name="centerValue">Some value. Sequence elements that deviate from this value by more than <paramref name="allowedEpsilon"/> will be filtered out.</param> /// <param name="allowedEpsilon">The allowed nonnegative value of deviation from <paramref name="centerValue"/>.</param> /// <param name="deviationType"> /// If deviation type is Downwards, values which are smaller than <paramref name="centerValue"/> /// by <paramref name="allowedEpsilon"/> will be filtered. /// If deviation type is Upwards, values which are bigger than <paramref name="centerValue"/> /// by <paramref name="allowedEpsilon"/> will be filtered. /// If deviation type is EitherSide, all values that differ from the <paramref name="centerValue"/> /// by <paramref name="allowedEpsilon"/> will be filtered. /// </param> /// <param name="filteredValues">A reference to a collection to store the filtered values. May be null.</param> /// <returns>The list containing all incoming values except for the filtered ones.</returns> public static List <T> filterSurgesByEpsilonDeviationFromValue <T, C>(this IEnumerable <T> sequence, T centerValue, T allowedEpsilon, DeviationType deviationType = DeviationType.EitherSide, ICollection <T> filteredValues = null) where C : ICalc <T>, new() { ICalc <T> calc = Numeric <T, C> .Calculator; (allowedEpsilon >= Numeric <T, C> .Zero).Assert(new ArgumentException("Allowed deviation epsilon should be a non-negative value.")); List <T> result = new List <T>(); foreach (Numeric <T, C> current in sequence) { if (deviationType == DeviationType.EitherSide && WhiteMath <T, C> .Abs(centerValue - current) < (Numeric <T, C>)allowedEpsilon || deviationType == DeviationType.Downwards && centerValue - current < allowedEpsilon || deviationType == DeviationType.Upwards && current - centerValue < allowedEpsilon) { result.Add(current); } else if (filteredValues != null) { filteredValues.Add(current); } } return(result); }
// ------------------- FACTORIZATION ---------------------------- /// <summary> /// Preforms the LUP-factorization of a matrix (let it be A) /// in the form of: /// /// P*A = L*U. /// /// The P is an identity matrix with a plenty of row inversions. /// For the economy of space it is provided as a single-dimensional array of integers: /// /// (0, 1, 2, 3, ..., n). /// /// Element indices of this array stand for matrix rows, and elements value /// mean the position of '1' in a row. /// /// Requirements: works for any square and nonsingular matrix (having a non-zero determinant). /// If these requirements aren't met, either a MatrixSingularException or a MatrixSizeException /// would be thrown. /// </summary> /// <param name="C">The matrix C containing L + U - E. It is clear that both L and U can be easily extracted from this matrix.</param> /// <param name="P">The identity matrix with a plenty of row inversions in the form of array.</param> public void LUP_Factorization(out int[] P, out Matrix_SDA <T, C> C) { if (this.rows != this.columns) { throw new MatrixSizeException("The matrix is not square an thus cannot be factorized."); } int n = this.rows; // размер матрицы C = new Matrix_SDA <T, C>(n, n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { C.setItemAt(i, j, this.getItemAt(i, j)); } } P = new int[n]; P.FillByAssign(delegate(int i) { return(i); }); // ----- пошел ---------- Numeric <T, C> pivot; Numeric <T, C> abs; int pivotIndex; for (int i = 0; i < n; i++) { pivot = Numeric <T, C> .Zero; pivotIndex = -1; for (int row = i; row < n; row++) { abs = WhiteMath <T, C> .Abs(this.getItemAt(row, i)); if (abs > pivot) { pivot = abs; pivotIndex = row; } } if (pivot == Numeric <T, C> .Zero) { throw new MatrixSingularityException("The matrix is singular. It cannot be factorized."); } if (pivotIndex != i) { P.Swap(pivotIndex, i); C.swapRows(pivotIndex, i); } try { for (int j = i + 1; j < n; j++) { C.setItemAt(j, i, C.getItemAt(j, i) / C.getItemAt(i, i)); if (Numeric <T, C> .isInfinity(C.getItemAt(j, i)) || Numeric <T, C> .isNaN(C.getItemAt(j, i))) { throw new DivideByZeroException(); } for (int k = i + 1; k < n; k++) { C.setItemAt(j, k, C.getItemAt(j, k) - C.getItemAt(j, i) * C.getItemAt(i, k)); } } } catch (DivideByZeroException) { throw new MatrixSingularityException("The matrix is singular. It cannot be factorized."); } } return; }
// --------- this is the key to happiness private static T _PositiveLagrangeBound(IList <Numeric <T, C> > coefficients, Func <int, Numeric <T, C>, Numeric <T, C> > selector) { // нули в начале нам совсем не нужны. int minus = 1; while (coefficients[coefficients.Count - minus] == Numeric <T, C> .Zero) { minus++; if (minus > coefficients.Count) { throw new ArgumentException("This polynom contains only zero coefficients. Cannot evaluate the finite roots interval."); } // todo - return INFINITY. } // ------- начальный коэффициент - меньше нуля? // заменяем функцию g(x) = -f(x) и сохраняем корни и нервы. if (selector(coefficients.Count - minus, coefficients[coefficients.Count - minus]) < Numeric <T, C> .Zero) { object target = selector.Target; MethodInfo method = selector.Method; selector = delegate(int i, Numeric <T, C> obj) { return(-(Numeric <T, C>)method.Invoke(target, new object[] { i, obj })); }; } // ----------------- T nCoef = coefficients[coefficients.Count - minus]; T cur; T one = calc.fromInt(1); T max = calc.zero; int index = -1; // индекс первого отрицательного коэффициента bool found = false; // найдены ли отрицательные коэффициенты! for (int i = coefficients.Count - minus; i >= 0; i--) { cur = selector(i, coefficients[i]); if (!found && calc.mor(calc.zero, cur)) { found = true; index = coefficients.Count - i - minus; } // -- здесь cur больше не нужна, а нужно только ее // абсолютное значение. его и используем. cur = WhiteMath <T, C> .Abs(cur); if (calc.mor(cur, max)) { max = cur; } } if (!found) { return(calc.zero); } return(calc.sum(one, WhiteMath <T, C> .Power(calc.div(max, WhiteMath <T, C> .Abs(nCoef)), calc.div(one, calc.fromInt(index))))); }
/// <summary> /// Returns the string representation of the polynomial function /// as an array of coefficients - or, in the functional form /// i.e. 'f(x) = ...'. /// </summary> /// <param name="type">The type of the string representation.</param> /// <returns>The string representation of the current object.</returns> public string ToString(PolynomStringRepresentationType type) { if (type == PolynomStringRepresentationType.Coefficients) { string coefString = ""; for (int i = 0; i < coefficients.Length; i++) { coefString += "|" + this.coefficients[i].ToString(); } coefString += "|"; return(coefString); } else { string functionString = "f(x) = "; Numeric <T, C> one = calc.fromInt(1); for (int i = coefficients.Length - 1; i > 0; i--) { if (coefficients[i] != Numeric <T, C> .Zero) { functionString += string.Format("{0}{1}x{2}", (coefficients[i] >= calc.zero ? (i < coefficients.Length - 1?" + ":"") : (i < coefficients.Length - 1?" - ":"-")), (coefficients[i] != one ? WhiteMath <T, C> .Abs(coefficients[i]).ToString() : ""), (i == 1 ? "" : "^" + i.ToString())); } } if (coefficients[0] != Numeric <T, C> .Zero) { functionString += string.Format(" {0} {1} ", (coefficients[0] > Numeric <T, C> .Zero ? "+" : "-"), WhiteMath <T, C> .Abs(coefficients[0])); } return(functionString); } }