/// <summary> /// Find the nearest point. /// </summary> public Arguments Interpolate(Arguments start, Arguments finish, int axissIndex, double?isolevel = null) { var startValue = start[axissIndex].Value > finish[axissIndex].Value ? finish[axissIndex].Value : start[axissIndex].Value; var finishValue = start[axissIndex].Value > finish[axissIndex].Value ? start[axissIndex].Value : finish[axissIndex].Value; var curA = startValue; var curB = finishValue; double funcA = 0; double funcB = 0; double calcA = 0; double calcB = 0; var point = start.CloneArguments(); // Some constants var c = (3 - Math.Sqrt(5)) / 2; var fi = (Math.Sqrt(5) + 1) / 2; var calculated = Calculated.FirstIteration; for (; ;) { if ((curB - curA < accuracyEpsilon) && calculated != Calculated.FirstIteration) { var pointToReturn = point.CloneArguments(); if (GetNearestOrMin(funcA, funcB, isolevel)) { pointToReturn[axissIndex] = curA; } else { pointToReturn[axissIndex] = curB; } return(pointToReturn); } calcA = curA + c * (curB - curA); point[axissIndex] = calcA; funcA = function.Calculate(point); calcB = curA + (1 - c) * (curB - curA); point[axissIndex] = calcB; funcB = function.Calculate(point); var result = GetNearestOrMin(funcA, funcB, isolevel); if (result) { curB = calcB; calculated = Calculated.B; } else { curA = calcA; calculated = Calculated.A; } } }
public double GetDerivate(Arguments inArgs, int special) { if (function == null) { throw new ArgumentException("function is not set to object"); } if (special > inArgs.Count) { throw new ArgumentException(String.Format("Function cannot find argument number {0}", special)); } if (inArgs.Count != function.Dimension) { throw new ArgumentException(String.Format("Arguments count does not match function dimension")); } Arguments args = inArgs.CloneArguments(); if (special != -1) { int index = 1; foreach (Variable item in args) { if (index != special) { item.IsConstant = true; item.Value = 0; } index++; } } if (accurracy == DerivationAccuracy.Normal) { return((function.Calculate(args + h) - function.Calculate(args - h)) / (2 * h)); } else if (accurracy == DerivationAccuracy.High) { return((-function.Calculate(args + h * 2) + 8 * function.Calculate(args + h) - 8 * function.Calculate(args - h) + function.Calculate(args - h * 2)) / (12 * h)); } else { return(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; } } }