private double GetdF(Double[] V, Int32 Index, double accuracy) { double[] temp = new double[V.Length]; for (Int32 i = 0; i < V.Length; i++) { if (i == Index) { temp.SetValue(V[i] + accuracy, i); } else { temp.SetValue(V[i], i); } } return((FunctionClass.Function3(temp) - FunctionClass.Function3(V)) / accuracy); }
private void HookJeevesButton_Click(object sender, EventArgs e) { OutBox.Text = string.Empty; double eps = Convert.ToDouble(EpsilonBox.Text); // Точность вычислений double step = Convert.ToDouble(StepBox.Text); // Начальный шаг // Начальное приближение double x = Convert.ToDouble(x0Box.Text); double y = Convert.ToDouble(y0Box.Text); double y0 = FunctionClass.Function2(x, y); int IterCount = 0; double fx; double lenght, y1, y2, y3, x1n, x2n, x1nn, x2nn; int fl = 0; lenght = 1; do { fx = FunctionClass.Function2(x, y); OutBox.Text += "x = " + Math.Round(x, 6).ToString() + " y = " + Math.Round(y, 6).ToString() + " f(x, y) = " + Math.Round(fx, 6).ToString() + "\r\n"; fl = 0; y1 = FunctionClass.Function2(x + step, y); if (y1 < y0) { x1n = x + step; } else { y1 = FunctionClass.Function2(x - step, y); if (y1 < y0) { x1n = x - step; } else { x1n = x; y1 = y0; } } y2 = FunctionClass.Function2(x1n, y + step); if (y2 < y1) { x2n = y + step; } else { y2 = FunctionClass.Function2(x1n, y - step); if (y2 < y1) { x2n = y - step; } else { x2n = y; y2 = y1; } } if ((x1n == x) && (x2n == y)) { if (step > eps) { fl = 1; step = step / 2; } } else { fl = 1; do { x1nn = x1n + lenght * (x1n - x); x2nn = x2n + lenght * (x2n - y); y3 = FunctionClass.Function2(x1nn, x2nn); x = x1nn; y = x2nn; lenght = lenght * 0.5; } while (y2 < y3); IterCount++; y0 = y3; } } while (fl == 1); fx = FunctionClass.Function2(x, y); MinXBox.Text = x.ToString(); MinYBox.Text = y.ToString(); MinFBox.Text = fx.ToString(); IterCountBox.Text = IterCount.ToString(); }
private void BuildButton_Click(object sender, EventArgs e) { // Границы вычисления функции по осям X и Y double minX = Convert.ToDouble(MinXBox.Text); double maxX = Convert.ToDouble(MaxXBox.Text); double minY = Convert.ToDouble(MinYBox.Text); double maxY = Convert.ToDouble(MaxYBox.Text); // Масштаб double intervalX = maxX - minX; double intervalY = maxY - minY; double zoomX = intervalX / bitmap.Width; // 1 пиксель : 1 ед.измерения оси X double zoomY = intervalY / bitmap.Height; // 1 пиксель : 1 ед.измерения оси Y double eps = Convert.ToDouble(EpsilonBox.Text); // Точность int levelCount = Convert.ToInt32(LevelBox.Text); // Количество линий уровня // Уровни int countX = Convert.ToInt32(bitmap.Width); int countY = Convert.ToInt32(bitmap.Height); double[,] values = new double[countX, countY]; // Сетка функции double[] levels = new double[levelCount]; // Уровни функции for (int i = 0; i < bitmap.Width; i++) { for (int j = 0; j < bitmap.Height; j++) { double x = minX + i * zoomX; double y = minY + j * zoomY; double z = FunctionClass.Function2(x, y); values[i, j] = z; } } double minValue = values[0, 0]; // Локальный минимум функции double maxValue = values[0, 0]; // Локальный максимум функции for (int i = 0; i < values.GetLength(0); i++) { for (int j = 0; j < values.GetLength(1); j++) { if (values[i, j] < minValue) { minValue = values[i, j]; } if (values[i, j] > maxValue) { maxValue = values[i, j]; } } } int levelStepX = bitmap.Width / levelCount / 2; int levelStepY = bitmap.Height / levelCount / 2; for (int i = 0; i < levelCount; i++) { levels[i] = values[i * levelStepX, i *levelStepY]; } // Рисуем линии уровней ProgressBar.Value = 0; ProgressBar.Maximum = bitmap.Width * bitmap.Height * levels.Length; for (int i = 0; i < bitmap.Width; i++) { for (int j = 0; j < bitmap.Height; j++) { for (int k = 0; k < levels.Length; k++) { double x = minX + i * zoomX; double y = minY + j * zoomY; double z = FunctionClass.Function2(x, y); if (z >= levels[k] - eps && z <= levels[k] + eps) { int c = (int)(255 * Math.Abs(z - levels[k]) / eps); DrawPoint(i, bitmap.Height - j - 1, Color.FromArgb(c, c, c)); } ProgressBar.Value++; } } } }
private void GaussButton_Click(object sender, EventArgs e) { OutBox.Text = string.Empty; double eps = Convert.ToDouble(EpsilonBox.Text); // Точность вычислений double step = Convert.ToDouble(StepBox.Text); // Начальный шаг // Начальное приближение double x = Convert.ToDouble(x0Box.Text); double y = Convert.ToDouble(y0Box.Text); int IterCount = 0; double fx, prevX, prevY, curX = x, curY = y; double leftBorder, rightBorder; double x1, xm, x2; double y1, ym, y2; double z1, zm, z2; do { IterCount++; prevX = curX; prevY = curY; // По 1 координате leftBorder = prevX - step; rightBorder = prevX + step; x1 = leftBorder + (rightBorder - leftBorder) / 4; xm = (leftBorder + rightBorder) / 2; x2 = rightBorder - (rightBorder - leftBorder) / 4; z1 = FunctionClass.Function2(x1, prevY); zm = FunctionClass.Function2(xm, prevY); z2 = FunctionClass.Function2(x2, prevY); while (Math.Abs(rightBorder - leftBorder) > eps) { if ((z1 > zm) && (zm < z2)) { leftBorder = x1; rightBorder = x2; x1 = leftBorder + (rightBorder - leftBorder) / 4; x2 = rightBorder - (rightBorder - leftBorder) / 4; } else if ((z1 > zm) && (zm > z2)) { leftBorder = xm; x1 = leftBorder + (rightBorder - leftBorder) / 4; x2 = rightBorder - (rightBorder - leftBorder) / 4; xm = (leftBorder + rightBorder) / 2; zm = FunctionClass.Function2(xm, prevY); } else if ((z1 < zm) && (zm < z2)) { rightBorder = xm; x1 = leftBorder + (rightBorder - leftBorder) / 4; x2 = rightBorder - (rightBorder - leftBorder) / 4; xm = (leftBorder + rightBorder) / 2; zm = FunctionClass.Function2(xm, prevY); } z1 = FunctionClass.Function2(x1, prevY); z2 = FunctionClass.Function2(x2, prevY); } curX = (leftBorder + rightBorder) / 2; // По 2 координате leftBorder = prevY - step; rightBorder = prevY + step; y1 = leftBorder + (rightBorder - leftBorder) / 4; ym = (leftBorder + rightBorder) / 2; y2 = rightBorder - (rightBorder - leftBorder) / 4; z1 = FunctionClass.Function2(curX, y1); zm = FunctionClass.Function2(curX, ym); z2 = FunctionClass.Function2(curX, y2); while (Math.Abs(rightBorder - leftBorder) > eps) { if ((z1 > zm) && (zm < z2)) { leftBorder = y1; rightBorder = y2; y1 = leftBorder + (rightBorder - leftBorder) / 4; y2 = rightBorder - (rightBorder - leftBorder) / 4; } else if ((z1 > zm) && (zm > z2)) { leftBorder = ym; y1 = leftBorder + (rightBorder - leftBorder) / 4; y2 = rightBorder - (rightBorder - leftBorder) / 4; ym = (leftBorder + rightBorder) / 2; zm = FunctionClass.Function2(curX, ym); } else if ((z1 < zm) && (zm < z2)) { rightBorder = ym; y1 = leftBorder + (rightBorder - leftBorder) / 4; y2 = rightBorder - (rightBorder - leftBorder) / 4; ym = (leftBorder + rightBorder) / 2; zm = FunctionClass.Function2(curX, ym); } z1 = FunctionClass.Function2(curX, y1); z2 = FunctionClass.Function2(curX, y2); } curY = (leftBorder + rightBorder) / 2; }while (Math.Abs(FunctionClass.Function2(curX, curY) - FunctionClass.Function2(prevX, prevY)) > eps); fx = FunctionClass.Function2(curX, curY); MinXBox.Text = curX.ToString(); MinYBox.Text = curY.ToString(); MinFBox.Text = fx.ToString(); IterCountBox.Text = IterCount.ToString(); }
private void NewtonButton_Click(object sender, EventArgs e) { OutBox.Text = string.Empty; // Шаг 1 int k = 0; // Счетчик итераций double x0, y0; // Начальное приближение double a = 1; // Шаг для модифицированного метода x0 = Convert.ToDouble(x0Box.Text); y0 = Convert.ToDouble(y0Box.Text); eps = Convert.ToDouble(EpsilonBox.Text); //a = Convert.ToDouble(StepBox.Text); double x = x0, y = y0; // Текущая точка double[] grad = new double[2]; // Градиент double [,] matrix = new double[2, 2]; // Матрица Гессе double[,] invertMatrix = new double[2, 2]; // Обратная матрица Гессе double[] p = new double[2]; // Направление спуска double[] curPoint = new double[2]; // Текущая точка double[] nextPoint = new double[2]; // Следущая точка calculate: OutBox.Text += "Итерация № " + k.ToString() + "\r\n" + "Текущая точка (" + x + ", " + y + ")\r\n" + "Значение функции в точке " + FunctionClass.Function2(x, y) + "\r\n"; // Вычисляем градиент grad = GetGrad(x, y); OutBox.Text += "Градиент\r\n (" + grad[0] + ", " + grad[1] + ")\r\n"; // Вычисляем матрицу Гессе matrix = GetHesse(x, y); OutBox.Text += "Матрица Гессе\r\n" + "| " + matrix[0, 0] + " | " + matrix[0, 1] + " |\r\n" + "| " + matrix[1, 0] + " | " + matrix[1, 1] + " |\r\n"; // Шаг 2 // Определяем обратную матрицу invertMatrix = InvertMatrix(matrix); if (invertMatrix == null) { return; } OutBox.Text += "Обратная матрица Гессе\r\n" + "| " + invertMatrix[0, 0] + " | " + invertMatrix[0, 1] + " |\r\n" + "| " + invertMatrix[1, 0] + " | " + invertMatrix[1, 1] + " |\r\n"; // Шаг 3 // Определяем направление спуска p = GetDirect(grad, invertMatrix); OutBox.Text += "Направление спуска\r\n (" + p[0] + ", " + p[1] + ")\r\n"; // Шаг 4 // Определяем следующую точку curPoint[0] = x; curPoint[1] = y; //a = GoldenSection(curPoint, eps, -10, 10, p); nextPoint = GetNextPoint(curPoint, a, p); OutBox.Text += "Новая точка (" + nextPoint[0] + ", " + nextPoint[1] + ")\r\n"; // Шаг 5 // Вычисление в новой точке градиента grad = GetGrad(nextPoint[0], nextPoint[1]); // Шаг 6 // Если точность не достигнута, то продолжаем итерации x = nextPoint[0]; y = nextPoint[1]; if ((Math.Sqrt(grad[0] * grad[0] + grad[1] * grad[1]) > eps && Math.Abs(FunctionClass.Function2(curPoint[0], curPoint[1]) - FunctionClass.Function2(nextPoint[0], nextPoint[1])) > eps)) { k++; OutBox.Text += "________________________________\r\n"; goto calculate; } double f = FunctionClass.Function2(x, y); OutBox.Text += "*************************************\r\n" + "Минимум функции равен " + f + "\r\n" + "в точке (" + x + ", " + y + ")\r\n"; MinXBox.Text = x.ToString(); MinYBox.Text = y.ToString(); MinFBox.Text = f.ToString(); IterCountBox.Text = (k + 1).ToString(); }
public double GetDfDy(double _x, double _y) { return((FunctionClass.Function2(_x, _y + Math.Pow(eps, 2)) - FunctionClass.Function2(_x, _y)) / Math.Pow(eps, 2)); }
// Метод Коши (Наискорейший градиентный спуск) private string Grad(double[] x0, double eps, double h) { // 1 шаг string result = ""; double[] x = new double[x0.Length], grad = new double[x0.Length]; double deltaX = 0; Int32 index = 0; x0.CopyTo(x, 0); result += "Начальная точка:\r\n"; for (Int32 i = 0; i < x0.Length; i++) { result += "x[" + i + "]=" + x0[i] + "\r\n"; } result += "F(x[0], x[1]) = " + FunctionClass.Function3(x0) + "\r\n\r\n"; do { index++; // 2 шаг result += "Вычисление градиенты: \r\n"; for (Int32 i = 0; i < x.Length; i++) { grad[i] = GetdF(x0, i, eps); result += grad[i] + "\r\n"; } // 3 шаг отпадает, т.к. нет ограничений на кол-во итераций // 4 шаг h = GoldenSection(x, eps, leftBorder, rightBorder); result += "Шаг: " + h + "\r\n"; // 5 шаг for (Int32 i = 0; i < x.Length; i++) { x[i] = x0[i] - h * GetdF(x0, i, eps); } result += "\r\nНовая точка: \r\n"; for (Int32 i = 0; i < x.Length; i++) { result += "x[" + i + "] = " + x[i] + "\r\n"; deltaX = Math.Pow(x[i] - x0[i], 2); } result += "F(x[0], x[1]) = " + FunctionClass.Function3(x) + "\r\n\r\n"; x.CopyTo(x0, 0); } // 6 шаг while (Math.Sqrt(Math.Abs(deltaX)) > eps); result += "Минимум:\r\n"; for (Int32 i = 0; i < x.Length; i++) { result += "x[" + i + "] = " + x[i] + "\r\n"; } result += "Значение: " + FunctionClass.Function3(x); MinXBox.Text = x[0].ToString(); MinYBox.Text = x[1].ToString(); MinFBox.Text = FunctionClass.Function3(x).ToString(); IterCountBox.Text = index.ToString(); return(result); }
private double GoldenSection(out string log, double leftBorder, double rightBorder, double accuracy) { log = "Метод золотого сечения:\r\n\r\n" + "Входные данные:\r\n" + " Левая граница a = " + leftBorder + "\r\n" + " Правая граница b = " + rightBorder + "\r\n" + " Точность eps = " + accuracy + "\r\n\r\n" + "Итерации:\r\n\r\n"; double tau = (-1 + Math.Sqrt(5)) / 2.0; double x1 = leftBorder + (rightBorder - leftBorder) * tau; double x2 = rightBorder - (rightBorder - leftBorder) * tau; double xm = (leftBorder + rightBorder) / 2; double y1 = FunctionClass.Function1(x1); double y2 = FunctionClass.Function1(x2); double ym = FunctionClass.Function1(xm); log += "a = " + leftBorder + " " + "b = " + rightBorder + " " + "xm = " + xm + " " + "x1 = " + x1 + " " + "x2 = " + x2 + "\r\n"; log += "F(a) = " + FunctionClass.Function1(leftBorder) + " " + "F(b) = " + FunctionClass.Function1(rightBorder) + " " + "F(xm) = " + ym + " " + "F(x1) = " + y1 + " " + "F(x2) = " + y2 + "\r\n\r\n"; int i = 0; while (Math.Abs(rightBorder - leftBorder) > accuracy) { i++; if ((y1 < y2)) { log += "# " + i + " y1 < y2\r\n"; leftBorder = x2; x2 = x1; x1 = leftBorder + (rightBorder - leftBorder) * tau; log += "x1 = " + x1 + "\r\n"; log += "x2 = " + x2 + "\r\n"; } else if ((y1 > y2)) { log += "# " + i + " y1 > y2\r\n"; rightBorder = x1; x1 = x2; x2 = rightBorder - (rightBorder - leftBorder) * tau; log += "x1 = " + x1 + "\r\n"; log += "x2 = " + x2 + "\r\n"; } y1 = FunctionClass.Function1(x1); y2 = FunctionClass.Function1(x2); xm = (leftBorder + rightBorder) / 2; ym = FunctionClass.Function1(xm); log += "# " + i + " " + xm + "\r\n\r\n"; } return(xm); }
private double Bisection(out string log, double leftBorder, double rightBorder, double accuracy) { log = "Метод половинного деления:\r\n\r\n" + "Входные данные:\r\n" + " Левая граница a = " + leftBorder + "\r\n" + " Правая граница b = " + rightBorder + "\r\n" + " Точность eps = " + accuracy + "\r\n\r\n" + "Итерации:\r\n\r\n"; double x1 = leftBorder + (rightBorder - leftBorder) / 4; double xm = (leftBorder + rightBorder) / 2; double x2 = rightBorder - (rightBorder - leftBorder) / 4; double y1 = FunctionClass.Function1(x1); double ym = FunctionClass.Function1(xm); double y2 = FunctionClass.Function1(x2); log += "a = " + leftBorder + " " + "b = " + rightBorder + " " + "xm = " + xm + " " + "x1 = " + x1 + " " + "x2 = " + x2 + "\r\n"; log += "F(a) = " + FunctionClass.Function1(leftBorder) + " " + "F(b) = " + FunctionClass.Function1(rightBorder) + " " + "F(xm) = " + ym + " " + "F(x1) = " + y1 + " " + "F(x2) = " + y2 + "\r\n\r\n"; int i = 0; while (Math.Abs(rightBorder - leftBorder) > accuracy) { i++; if ((y1 > ym) && (ym < y2)) { log += "# " + i + " y1 > ym && ym < y2\r\n"; leftBorder = x1; rightBorder = x2; log += "a = " + leftBorder + " " + "b = " + rightBorder + "\r\n"; x1 = leftBorder + (rightBorder - leftBorder) / 4; x2 = rightBorder - (rightBorder - leftBorder) / 4; log += "x1 = " + x1 + " " + "x2 = " + x2 + "\r\n"; } else if ((y1 > ym) && (ym > y2)) { log += "# " + i + " y1 > ym && ym > y2\r\n"; leftBorder = xm; log += "a = " + leftBorder + "\r\n"; x1 = leftBorder + (rightBorder - leftBorder) / 4; x2 = rightBorder - (rightBorder - leftBorder) / 4; xm = (leftBorder + rightBorder) / 2; log += "x1 = " + x1 + " " + "xm = " + xm + " " + "x2 = " + x2 + "\r\n"; ym = FunctionClass.Function1(xm); } else if ((y1 < ym) && (ym < y2)) { log += "# " + i + " y1 < ym && ym < y2\r\n"; rightBorder = xm; log += "b = " + rightBorder + "\r\n"; x1 = leftBorder + (rightBorder - leftBorder) / 4; x2 = rightBorder - (rightBorder - leftBorder) / 4; xm = (leftBorder + rightBorder) / 2; log += "x1 = " + x1 + " " + "xm = " + xm + " " + "x2 = " + x2 + "\r\n"; ym = FunctionClass.Function1(xm); } y1 = FunctionClass.Function1(x1); y2 = FunctionClass.Function1(x2); log += "y1 = " + y1 + " " + "ym = " + ym + " " + "y2 = " + y2 + "\r\n"; log += "xm = " + xm + "\r\n\r\n"; } return(xm); }