Exemplo n.º 1
0
        public override double findAlphaStar(double[] x, double[] dir)
        {
            // include the first two points in this SortedList (essentially, the a, b and c).
            var alphaAndF = new SortedList <double, double>
            {
                { 0.0, calcF(x, 0.0, dir) },
                { stepSize, calcF(x, stepSize, dir) }
            };

            // third point is based on if second point is better or worse
            if (alphaAndF[stepSize] <= alphaAndF[0.0])
            {
                alphaAndF.Add(3 * stepSize, calcF(x, 3 * stepSize, dir));
            }
            else
            {
                alphaAndF.Add(stepSize / 2, calcF(x, stepSize / 2, dir));
            }

            var k        = 0;
            var fMin     = alphaAndF.Values.Min();
            var minIndex = alphaAndF.IndexOfValue(fMin);

            #region start main loop
            while (((Math.Abs(alphaAndF.Keys[2] - alphaAndF.Keys[0]) / 2) > epsilon) && (k++ < kMax))
            {
                k++;
                double alphaNew;
                DSCPowellLoopStatus loopStatus;
                #region find new alpha
                if (!quadraticApprox(out alphaNew, alphaAndF))
                {
                    /* if the quadratic approximatoin fails, we make note of it with this enumerator. */
                    loopStatus = DSCPowellLoopStatus.SecondDerivNegative;
                    SearchIO.output("<<< uh-oh! negative 2nd deriv @ k=" + k + "!>>>", 5);
                }
                else if (alphaAndF.Keys.Contains(alphaNew))
                {
                    /* if the alpha is already one of the three, then no point in keeping it. */
                    loopStatus = DSCPowellLoopStatus.NewPointAlreadyFound;
                    SearchIO.output("<<< uh-oh! new point is a repeat @ k=" + k + "!>>>", 5);
                }
                else
                {
                    var fNew = calcF(x, alphaNew, dir);
                    if (fNew > alphaAndF.Values.Min() && NewPointIsFarthest(alphaNew, alphaAndF.Keys, minIndex))
                    {
                        SearchIO.output("<<< uh-oh! new point is not best and too far away @ k=" + k + "!>>>", 5);

                        /* the new point is not the best and is farthest from the current best, so it will simply
                         * be deleted after it is added. That's not good. */
                        loopStatus = DSCPowellLoopStatus.NewPointIsFarthest;
                    }
                    else
                    {
                        /* whew! it looks like the new point (point d) is a keeper */
                        loopStatus = DSCPowellLoopStatus.Normal;
                        alphaAndF.Add(alphaNew, fNew);
                    }
                }
                #endregion
                #region if alpha via quadratic approximation failed, then set here.
                if (loopStatus != DSCPowellLoopStatus.Normal)
                {
                    switch (minIndex)
                    {
                    case 0:
                        alphaNew = alphaAndF.Keys[0] + (alphaAndF.Keys[0] - alphaAndF.Keys[2]);
                        break;

                    case 1:
                        alphaNew = (alphaAndF.Keys[0] + alphaAndF.Keys[1] + alphaAndF.Keys[2]) / 3;
                        break;

                    case 2:
                        alphaNew = alphaAndF.Keys[2] + (alphaAndF.Keys[2] - alphaAndF.Keys[0]);
                        break;
                    }
                    alphaAndF.Add(alphaNew, calcF(x, alphaNew, dir));
                }
                #endregion
                #region remove farthest value from min
                fMin     = alphaAndF.Values.Min();
                minIndex = alphaAndF.IndexOfValue(fMin);
                switch (minIndex)
                {
                case 0:
                    alphaAndF.RemoveAt(3); break;

                case 1:
                    if (alphaAndF.Keys[3] - alphaAndF.Keys[1] > alphaAndF.Keys[1] - alphaAndF.Keys[0])
                    {
                        alphaAndF.RemoveAt(3);
                    }
                    else
                    {
                        alphaAndF.RemoveAt(0);
                    }
                    break;

                case 2:
                    if (alphaAndF.Keys[3] - alphaAndF.Keys[2] > alphaAndF.Keys[2] - alphaAndF.Keys[0])
                    {
                        alphaAndF.RemoveAt(3);
                    }
                    else
                    {
                        alphaAndF.RemoveAt(0);
                    }
                    break;

                case 3:
                    alphaAndF.RemoveAt(0); break;
                }
                #endregion
                fMin     = alphaAndF.Values.Min();
                minIndex = alphaAndF.IndexOfValue(fMin);
            }
            #endregion

            return(alphaAndF.Keys[minIndex]);
        }