internal static List <fsValue> SolveC1Xp1C2Xp2C3Xp3C4(fsValue c1, fsValue p1, fsValue c2, fsValue p2, fsValue c3, fsValue p3, fsValue c4) { List <fsValue> breakPoints = SolveC1Xp1C2Xp2C3(c1 * p1, p1 - p3, c2 * p2, p2 - p3, c3 * p3, Infinity); while (breakPoints.Count > 0 && breakPoints[0] == Zero) { breakPoints.RemoveAt(0); } breakPoints.Insert(0, Zero); breakPoints.Add(Infinity); const int interations = 100; // precision is 1e20 / 2^100 ~~ 1e-11 var result = new List <fsValue>(); for (int i = 1; i < breakPoints.Count; ++i) { fsValue localRoot = fsBisectionMethod.FindRoot( new fsFunctionC1Xp1C2Xp2C3P3C4(c1, p1, c2, p2, c3, p3, c4), breakPoints[i - 1], breakPoints[i], interations); if (localRoot.Defined) { result.Add(localRoot); } } result.Sort(); return(result); }
static public List <fsValue> SolvePowerSumEquation(fsValue freeCoeff, fsValue[,] coeffsAndPowers) { var compressing = new SortedList <fsValue, fsValue>(); for (int i = 0; i < coeffsAndPowers.GetLength(0); ++i) { fsValue c = coeffsAndPowers[i, 0]; fsValue p = coeffsAndPowers[i, 1]; if (!compressing.ContainsKey(p)) { compressing.Add(p, Zero); } compressing[p] += c; } var compressing2 = new SortedList <fsValue, fsValue>(); foreach (KeyValuePair <fsValue, fsValue> cp in compressing) { if (cp.Value != Zero) { compressing2.Add(cp.Key, cp.Value); } } compressing = compressing2; { var compressedCoeffsAndPowers = new fsValue[compressing.Count - (compressing.ContainsKey(Zero) ? 1 : 0), 2]; int i = 0; foreach (KeyValuePair <fsValue, fsValue> cp in compressing) { if (cp.Key == Zero) { freeCoeff += cp.Value; } else { compressedCoeffsAndPowers[i, 0] = cp.Value; compressedCoeffsAndPowers[i, 1] = cp.Key; ++i; } } coeffsAndPowers = compressedCoeffsAndPowers; } var result = new List <fsValue>(); for (int i = 0; i < coeffsAndPowers.GetLength(0); ++i) { if (coeffsAndPowers[i, 1] == new fsValue(0)) { throw new Exception( "SolvePowerSumEquation: Powers must be non-zero values. Move such elemets to freeCoeff"); } } for (int i = 1; i < coeffsAndPowers.GetLength(0); ++i) { if (coeffsAndPowers[i - 1, 1] >= coeffsAndPowers[i, 1]) { throw new Exception("SolvePowerSumEquation: Powers must be sorted in increasing order"); } } if (coeffsAndPowers.GetLength(0) == 0) { return(result); } if (coeffsAndPowers.GetLength(0) == 1) { fsValue resVal = fsValue.Pow(-freeCoeff / coeffsAndPowers[0, 0], 1 / coeffsAndPowers[0, 1]); if (resVal.Defined) { result.Add(resVal); } return(result); } if (freeCoeff == Zero) { result.Add(Zero); } var newFreeCoeff = new fsValue(coeffsAndPowers[0, 0] * coeffsAndPowers[0, 1]); var newCoeffsAndPowers = new fsValue[coeffsAndPowers.GetLength(0) - 1, 2]; for (int i = 0; i < newCoeffsAndPowers.GetLength(0); ++i) { newCoeffsAndPowers[i, 0] = coeffsAndPowers[i + 1, 0] * coeffsAndPowers[i + 1, 1]; newCoeffsAndPowers[i, 1] = coeffsAndPowers[i + 1, 1] - coeffsAndPowers[0, 1]; } var changingPoints = new List <fsValue> { Zero }; changingPoints.AddRange(SolvePowerSumEquation(newFreeCoeff, newCoeffsAndPowers)); changingPoints.Add(Infinity); const int iterations = 100; // precision is 1e20 / 2^100 ~~ 1e-11 for (int i = 1; i < changingPoints.Count; ++i) { fsValue localSolution = fsBisectionMethod.FindRoot(new fsFunctionPowerSum(freeCoeff, coeffsAndPowers), changingPoints[i - 1], changingPoints[i], iterations); if (localSolution.Defined) { result.Add(localSolution); } } var eps = new fsValue(1e-12); result.Sort(); for (int i = result.Count - 1; i > 0; --i) { if (result[i] <= (1 + eps) * result[i - 1] || result[i] - result[i - 1] <= eps) { result.RemoveAt(i); } } return(result); }
public abstract fsValue Eval(fsValue x);
public fsFunctionPowerSum(fsValue freeCoeff, fsValue[,] coeffsAndPowers) { m_freeCoeff = freeCoeff; m_coeffsAndPowers = coeffsAndPowers; }
public fsJustValueParameter(fsJustValueParameter other) { Value = other.Value; }
public fsJustValueParameter(fsValue value) { Value = value; }
public static bool FindMinimum(fsFunction function, fsValue beginArg, fsValue endArg, int iterationsCount, out fsValue beginRes, out fsValue endRes) { beginRes = new fsValue(); endRes = new fsValue(); if (beginArg.Defined == false || endArg.Defined == false) { return(false); } fsValue len = endArg - beginArg; if (len <= new fsValue(0)) { throw new Exception("Wrong interval for ternary search"); } var eps = new fsValue(1e-8); fsValue left = beginArg; fsValue right = endArg; for (int i = 0; i < iterationsCount; ++i) { fsValue middle = 0.5 * (left + right); fsValue mid1 = middle - eps * (right - left); fsValue mid2 = middle + eps * (right - left); fsValue val1 = function.Eval(mid1); fsValue val2 = function.Eval(mid2); if (!val1.Defined) { throw new Exception("Function given to TernaryMethod not defind in point " + mid1.Value); } if (!val2.Defined) { throw new Exception("Function given to TernaryMethod not defind in point " + mid2.Value); } if (val1 > val2) { left = mid1; } else { right = mid2; } } beginRes = left; endRes = right; return(true); }
public fsJustValueParameter() { Value = new fsValue(); }
public static fsValue Calculate(fsFunction function, fsValue beginArg, fsValue endArg, fsValue tolerance) { if (beginArg > endArg) { throw new Exception("fsDefiniteIntegral: provided limits are: beginAng > endArg"); } if (beginArg == endArg) { return(fsValue.Zero); } fsValue kronrodValue, gaussValue; EvalIntegrals(function, beginArg, endArg, out kronrodValue, out gaussValue); fsValue kronrodResult = kronrodValue; fsValue gaussResult = gaussValue; var queue = new SortedDictionary <fsIntegrationSegment, int> { { new fsIntegrationSegment(kronrodValue, gaussValue, beginArg, endArg), 0 } }; int iterationsCount = 0; while (fsValue.Abs(kronrodResult - gaussResult) > tolerance || fsValue.Abs(kronrodResult / gaussResult - 1) > tolerance) { if (++iterationsCount >= 1000) // If we made too many iterations { // and still don't have proper precision break; // then just return not precise answer. } fsIntegrationSegment currentSegment = queue.Last().Key; queue.Remove(currentSegment); beginArg = currentSegment.BeginArg; endArg = currentSegment.EndArg; if (IsNeighbouringNumbers(beginArg, endArg)) { continue; } kronrodResult -= currentSegment.KronrodIntergralValue; gaussResult -= currentSegment.GaussIntergralValue; EvalIntegrals(function, beginArg, 0.5 * (beginArg + endArg), out kronrodValue, out gaussValue); kronrodResult += kronrodValue; gaussResult += gaussValue; queue.Add(new fsIntegrationSegment(kronrodValue, gaussValue, beginArg, 0.5 * (beginArg + endArg)), 0); EvalIntegrals(function, 0.5 * (beginArg + endArg), endArg, out kronrodValue, out gaussValue); kronrodResult += kronrodValue; gaussResult += gaussValue; queue.Add(new fsIntegrationSegment(kronrodValue, gaussValue, 0.5 * (beginArg + endArg), endArg), 0); } return((kronrodResult + gaussResult) / 2); }
public fsIntegrationSegment(fsValue kronrodIntergralValue, fsValue gaussIntergralValue, fsValue beginArg, fsValue endArg) { KronrodIntergralValue = kronrodIntergralValue; GaussIntergralValue = gaussIntergralValue; BeginArg = beginArg; EndArg = endArg; }
private static bool IsNeighbouringNumbers(fsValue a, fsValue b) { double mid = (a.Value + b.Value) / 2; return(a.Value == mid || b.Value == mid); }
static private void EvalIntegrals(fsFunction function, fsValue beginArg, fsValue endArg, out fsValue kronrodResult, out fsValue gaussResult) { fsValue c0 = 0.5 * (endArg + beginArg); fsValue c1 = 0.5 * (endArg - beginArg); kronrodResult = fsValue.Zero; gaussResult = fsValue.Zero; for (int i = 0; i <= 60; ++i) { fsValue fValue = function.Eval(c0 + c1 * X[i]); kronrodResult += WKronrod[i] * fValue; gaussResult += WGauss[i] * fValue; } kronrodResult *= c1; gaussResult *= c1; }
private static int Compare(fsValue first, fsValue second) { return(first.Value <second.Value ? -1 : first.Value> second.Value ? 1 : 0); }