Exemple #1
0
        public override void OnLoad(ConfigNode node)
        {
            Instance = this;
            GeneratePresets();
            int index = 4;

            if (node.HasValue("newGame"))
            {
                newGame = bool.Parse(node.GetValue("newGame"));
            }

            if (node.HasValue("index"))
            {
                index = int.Parse(node.GetValue("index"));
            }

            dropdown = new GUIDropDown <FARDifficultyAndExactnessSettings>(presetNames.ToArray(),
                                                                           presets.ToArray(),
                                                                           index < 0 ? 2 : index);
            voxelSettings = new FARVoxelSettings();

            if (node.HasValue("numVoxelsControllableVessel"))
            {
                voxelSettings.numVoxelsControllableVessel = int.Parse(node.GetValue("numVoxelsControllableVessel"));
            }
            if (node.HasValue("numVoxelsDebrisVessel"))
            {
                voxelSettings.numVoxelsDebrisVessel = int.Parse(node.GetValue("numVoxelsDebrisVessel"));
            }
            if (node.HasValue("minPhysTicksPerUpdate"))
            {
                voxelSettings.minPhysTicksPerUpdate = int.Parse(node.GetValue("minPhysTicksPerUpdate"));
            }
            if (node.HasValue("useHigherResVoxelPoints"))
            {
                voxelSettings.useHigherResVoxelPoints = bool.Parse(node.GetValue("useHigherResVoxelPoints"));
            }

            if (index == -1)
            {
                settings = new FARDifficultyAndExactnessSettings(index);

                if (node.HasValue("fractionTransonicDrag"))
                {
                    settings.fractionTransonicDrag = double.Parse(node.GetValue("fractionTransonicDrag"));
                }
                if (node.HasValue("gaussianVehicleLengthFractionForSmoothing"))
                {
                    settings.gaussianVehicleLengthFractionForSmoothing =
                        double.Parse(node.GetValue("gaussianVehicleLengthFractionForSmoothing"));
                }

                if (node.HasValue("numAreaSmoothingPasses"))
                {
                    settings.numAreaSmoothingPasses = int.Parse(node.GetValue("numAreaSmoothingPasses"));
                }
                if (node.HasValue("numDerivSmoothingPasses"))
                {
                    settings.numDerivSmoothingPasses = int.Parse(node.GetValue("numDerivSmoothingPasses"));
                }


                customSettings = settings;
            }
            else
            {
                settings       = presets[index];
                customSettings = new FARDifficultyAndExactnessSettings(-1);
            }

            currentIndex = index;


            FARLogger.Info("Loading FAR Data");
            flightGUISettings = new List <ConfigNode>();
            if (node.HasNode("FlightGUISettings"))
            {
                foreach (ConfigNode flightGUINode in node.GetNode("FlightGUISettings").nodes)
                {
                    flightGUISettings.Add(flightGUINode);
                }
            }

            FARDebugAndSettings.LoadConfigs(node);
        }
        // ReSharper disable once UnusedMember.Global
        public static OptimizationResult BrentsMethod(
            Func <double, double> function,
            double a,
            double b,
            double epsilon = 0.001,
            int maxIter    = int.MaxValue
            )
        {
            double delta = epsilon * 100;
            double fa    = function(a);
            double fb    = function(b);

            if (fa * fb >= 0)
            {
                FARLogger.Debug("Brent's method failed to converge in 2 calls due to invalid brackets");
                return(new OptimizationResult(0, 2));
            }

            if (Math.Abs(fa) < Math.Abs(fb))
            {
                double tmp = fa;
                fa = fb;
                fb = tmp;

                tmp = a;
                a   = b;
                b   = tmp;
            }

            double c = a, d = a, fc = function(c);
            int    funcCalls = 3;

            double s = b, fs = fb;

            bool flag = true;

            for (int iter = 0; iter < maxIter; iter++)
            {
                if (fa - fc > double.Epsilon && fb - fc > double.Epsilon) //inverse quadratic interpolation
                {
                    s  = a * fc * fb / ((fa - fb) * (fa - fc));
                    s += b * fc * fa / ((fb - fa) * (fb - fc));
                    s += c * fc * fb / ((fc - fa) * (fc - fb));
                }
                else
                {
                    s  = (b - a) / (fb - fa); //secant method
                    s *= fb;
                    s  = b - s;
                }

                double b_s = Math.Abs(b - s), b_c = Math.Abs(b - c), c_d = Math.Abs(c - d);

                //Conditions for bisection method
                bool   condition1;
                double a3pb_over4 = (3 * a + b) * 0.25;

                if (a3pb_over4 > b)
                {
                    if (s < a3pb_over4 && s > b)
                    {
                        condition1 = false;
                    }
                    else
                    {
                        condition1 = true;
                    }
                }
                else if (s > a3pb_over4 && s < b)
                {
                    condition1 = false;
                }
                else
                {
                    condition1 = true;
                }

                bool condition2;

                if (flag && b_s >= b_c * 0.5)
                {
                    condition2 = true;
                }
                else
                {
                    condition2 = false;
                }

                bool condition3;

                if (!flag && b_s >= c_d * 0.5)
                {
                    condition3 = true;
                }
                else
                {
                    condition3 = false;
                }

                bool condition4;

                if (flag && b_c <= delta)
                {
                    condition4 = true;
                }
                else
                {
                    condition4 = false;
                }

                bool condition5;

                if (!flag && c_d <= delta)
                {
                    condition5 = true;
                }
                else
                {
                    condition5 = false;
                }

                if (condition1 || condition2 || condition3 || condition4 || condition5)
                {
                    s    = a + b;
                    s   *= 0.5;
                    flag = true;
                }
                else
                {
                    flag = false;
                }

                fs = function(s);
                funcCalls++;
                d = c;
                c = b;

                if (fa * fs < 0)
                {
                    b  = s;
                    fb = fs;
                }
                else
                {
                    a  = s;
                    fa = fs;
                }

                if (Math.Abs(fa) < Math.Abs(fb))
                {
                    double tmp = fa;
                    fa = fb;
                    fb = tmp;

                    tmp = a;
                    a   = b;
                    b   = tmp;
                }

                if (fs.NearlyEqual(0) || Math.Abs(a - b) <= epsilon)
                {
                    return(new OptimizationResult(s, funcCalls, true));
                }
            }

            FARLogger.Debug($"Brent's method failed to converged in {funcCalls.ToString()} function calls");

            return(new OptimizationResult(s, funcCalls));
        }
        /// <summary>
        ///     C# implementation of
        ///     https://github.com/scipy/scipy/blob/d5617d81064885ef2ec961492bc703f36bb36ee9/scipy/optimize/zeros.py#L95-L363
        ///     with optional <see cref="minLimit" /> and <see cref="maxLimit" /> constraints for physical problems. The solver
        ///     terminates when it either reaches the maximum number of iterations <see cref="maxIter" />, current and previous
        ///     <see cref="function" /> values are equal, current and previous solutions are close enough, are both NaN  or both
        ///     fall outside limits.
        /// </summary>
        /// <param name="function">Function to find root of</param>
        /// <param name="x0">Initial guess</param>
        /// <param name="x1">Optional second guess</param>
        /// <param name="tol">Absolute convergence tolerance</param>
        /// <param name="rTol">Relative convergence tolerance</param>
        /// <param name="maxIter">Maximum number of iterations</param>
        /// <param name="maxLimit">Maximum value of the solution</param>
        /// <param name="minLimit">Minimum value of the solution</param>
        /// <returns><see cref="OptimizationResult" /> solution</returns>
        /// <exception cref="ArgumentException">When initial and second guesses are equal</exception>
        public static OptimizationResult Secant(
            Func <double, double> function,
            double x0,
            double?x1       = null,
            double tol      = 0.001,
            double rTol     = 0.001,
            int maxIter     = 50,
            double maxLimit = double.PositiveInfinity,
            double minLimit = double.NegativeInfinity
            )
        {
            // ReSharper disable CompareOfFloatsByEqualityOperator
            int    funcCalls = 0;
            double p0        = x0;
            double p1;

            if (x1 is null)
            {
                const double eps = 1e-4;
                p1  = x0 * (1 + eps);
                p1 += p1 >= 0 ? eps : -eps;
            }
            else
            {
                if (x1 == x0)
                {
                    throw new ArgumentException($"{nameof(x1)} and {nameof(x0)} must be different");
                }
                p1 = (double)x1;
            }

            double q0 = function(p0);
            double q1 = function(p1);

            funcCalls += 2;
            double p = 0;

            if (Math.Abs(q1) < Math.Abs(q0))
            {
                Swap(ref p0, ref p1);
                Swap(ref q0, ref q1);
            }

            for (int itr = 0; itr < maxIter; itr++)
            {
                if (q1 == q0)
                {
                    if (p1 != p0)
                    {
                        FARLogger.Warning($"Tolerance of {(p1 - p0).ToString(CultureInfo.InvariantCulture)} reached");
                    }
                    FARLogger.Debug($"Secant method converged in {funcCalls.ToString()} function calls");
                    return(new OptimizationResult((p1 + p0) / 2, funcCalls, true));
                }

                if (Math.Abs(q1) > Math.Abs(q0))
                {
                    p = (-q0 / q1 * p1 + p0) / (1 - q0 / q1);
                }
                else
                {
                    p = (-q1 / q0 * p0 + p1) / (1 - q1 / q0);
                }

                if (IsClose(p, p1, tol, rTol))
                {
                    FARLogger.Debug($"Secant method converged in {funcCalls.ToString()} function calls with tolerance of {(p1 - p).ToString(CultureInfo.InvariantCulture)}");
                    return(new OptimizationResult(p, funcCalls, true));
                }

                p0 = p1;
                q0 = q1;
                p1 = p;

                if (double.IsNaN(p0) && double.IsNaN(p1))
                {
                    FARLogger.Warning($"Both {nameof(p0)} and {nameof(p1)} are NaN, used {funcCalls.ToString()} function calls");
                    return(new OptimizationResult(p, funcCalls));
                }

                if (p1 < minLimit && p0 < minLimit || p1 > maxLimit && p0 > maxLimit)
                {
                    FARLogger.Warning($"{nameof(p1)} and {nameof(p0)} are outside the limits, used {funcCalls.ToString()} function calls");
                    return(new OptimizationResult(p, funcCalls));
                }

                q1 = function(p1);
                funcCalls++;
            }

            FARLogger.Warning($"Secant method failed to converge in {funcCalls.ToString()} function calls");
            return(new OptimizationResult(p, funcCalls));
            // ReSharper restore CompareOfFloatsByEqualityOperator
        }
 public double BrentSolve(string dbgmsg)
 {
     FARLogger.Info("MirroredFunction (mirrored= " + mirror + ") reverting to BrentsMethod: " + dbgmsg);
     return(FARMathUtil.BrentsMethod(this.F, leftedge, rightedge, tol_brent, iterlim));
 }