public PointN FindMin(double eps) { int dimensionsCount = x0.Coordinates.Count; int k = 0; double ak = 0.0; PointN xk = x0; while (true) { VectorN gradFxk = Gradient.Calculate(funcND, xk); // Градиент все время прыгает во все стороны, а xk все наращивается Log.Add(String.Format("Grad(F({0, -23})) = {1, -25}", xk, gradFxk)); if (gradFxk.Length <= eps) { return(xk); } Function1D func1D = (double alpha) => { return(funcND(xk - gradFxk * alpha)); }; // TODO alpha >= 0 ak = OneDimensionalMinimization.FindMin(func1D, ak, eps); // TODO негибкая стратегия выбора eps Log.Add(String.Format("ak = {0}", ak)); xk = xk - gradFxk * ak; k++; Log.Add("==================Next Iteration===================="); } }
// Это хорошая идея - выносить параметры вроде eps сюда // Можно добавить список строк List<String> // И выводить в него информацию по алгоритму // Затем, в output мы берем его и выводим на экран (по желанию) public PointNMathNet FindMin(double eps) { int k = 0; PointNMathNet xk = x0; // x(k) PointNMathNet xk_1 = x0; // x(k-1) Matrix <double> Hk = H0.Clone(); // Квазиньютоновская матрицы double ak = 0.0; // Вспомогательные вектора VectorNMathNet sk = VectorNMathNet.Build.Dense(n); VectorNMathNet yk = VectorNMathNet.Build.Dense(n); while (true) { VectorNMathNet gradient = Gradient.Calculate(funcND, xk); Log.Add(String.Format("Grad(F(\n{0, -23})) = \n{1, -25}", xk, gradient)); // TODO: некрасивый вывод if (gradient.L2Norm() <= eps) // градиент слишком мал, максимум очень близко { return(xk); } if (k != 0) { sk = xk - xk_1; //Log.Add(String.Format("sk:\n{0}", sk)); Matrix <double> m_sk = sk.ToColumnMatrix(); Matrix <double> m_sk_t = m_sk.Transpose(); yk = Gradient.Calculate(funcND, xk) - Gradient.Calculate(funcND, xk_1); // TODO Один из членов этого вектора становится слишком мал (или Hk или M_yk_t) //Log.Add(String.Format("yk:\n{0}", yk)); Matrix <double> m_yk = yk.ToColumnMatrix(); Matrix <double> m_yk_t = m_yk.Transpose(); Hk = Hk - ((Hk * m_yk * m_yk_t * Hk) / (m_yk_t * Hk * m_yk)[0, 0]) + ((m_sk * m_sk_t)[0, 0] / (m_yk_t * m_sk)[0, 0]); Log.Add(String.Format("Hk:\n{0}", Hk)); } VectorNMathNet pk = -Hk * gradient; Function1D func1D = (double alpha) => { return(funcND((xk + pk * alpha))); }; ak = OneDimensionalMinimization.FindMin(func1D, ak, eps); Log.Add(String.Format("ak = {0}", ak)); // Инкремент xk_1 = xk; xk = xk + ak * pk; k++; Log.Add("==================Next Iteration===================="); } }