コード例 #1
0
        public Trajectory GradientDescent()
        {
            var parameters = this.Parameters;

            if (function == null || derivation == null || parameters == null)
            {
                throw new OperationCanceledException("Неможливо розпочати роботу. Не всі параметри вказано");
            }

            var    curPoint     = parameters.StartPoint;
            var    curBeta      = parameters.Beta;
            var    staticBeta   = curBeta;
            double curAlpha     = 0;
            bool   pointChanged = false;

            Arguments antiGrad           = derivation.GetAntiGradient(curPoint);
            double    functionInCurPoint = function.Calculate(curPoint);
            double    antiGradModule     = antiGrad.Pow(2).GetSumm();
            var       allPoints          = new Trajectory();

            allPoints.Add(curPoint);
            for (; ;)
            {
                if (pointChanged)
                {
                    antiGrad           = derivation.GetAntiGradient(curPoint);
                    functionInCurPoint = function.Calculate(curPoint);
                    antiGradModule     = antiGrad.Pow(2).GetSumm();
                }
                Arguments nextPoint = curPoint + (antiGrad * curBeta);

                double functionInNextPoint = function.Calculate(nextPoint);

                if (!IsValidValue(antiGradModule))
                {
                    return(allPoints);
                }

                //F(Xk)-F(xk=B*antigrad(xk))>=epsilon|antigrad(xk)|^2
                double toTest     = antiGradModule * (curBeta * parameters.Epsilon);
                double toTestLeft = functionInCurPoint - functionInNextPoint;
                if (toTestLeft >= toTest)
                {
                    //add point it is normal
                    allPoints.Add(nextPoint);
                    double exitValue = (nextPoint - curPoint).GetModule();
                    if (exitValue < parameters.AccuracyEpsilon)
                    {
                        return(allPoints); //exit
                    }
                    else
                    {
                        curPoint = nextPoint;
                        // Increase step
                        Arguments antiGradNew = derivation.GetAntiGradient(curPoint);
                        antiGrad = antiGradNew;
                        bool      calculated    = false;
                        Arguments newValue      = null;
                        double    funcResultNew = 0;
                        Arguments oldValue      = null;
                        double    funcResultOld = 0;
                        for (; ;)
                        {
                            if (calculated)
                            {
                                oldValue      = newValue;
                                funcResultOld = funcResultNew;
                            }
                            else
                            {
                                oldValue      = curPoint + (antiGradNew * curBeta);
                                funcResultOld = function.Calculate(oldValue);
                            }

                            var nextInfinity = Double.IsInfinity(curBeta * parameters.M);
                            if (!nextInfinity)
                            {
                                curBeta = curBeta * parameters.M;
                                // Step is too big.
                                newValue      = curPoint + (antiGradNew * curBeta);
                                funcResultNew = function.Calculate(newValue);
                            }
                            calculated = true;

                            if (nextInfinity || funcResultOld <= funcResultNew)
                            {
                                curBeta      = curBeta / parameters.M;
                                staticBeta   = curBeta;
                                pointChanged = true;
                                curPoint     = curPoint + (antiGrad * curBeta);
                                curAlpha     = 0;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    pointChanged = false;

                    if (curAlpha == 0)
                    {
                        curAlpha = parameters.Alpha;
                    }
                    else
                    {
                        curAlpha = curAlpha * curAlpha;
                    }

                    curBeta = staticBeta * curAlpha;
                }
            }
        }