
Приложение d
using System;
class SteepestDescent
{
public static double F1(double[] x) => 8 * Math.Pow(x[0] - 1, 2) + 3 * Math.Pow(x[1] - 1, 2);
public static double F2(double[] x) => Math.Pow(x[0] - 5, 2) + Math.Pow(x[1] - 1, 2) + 30 * Math.Pow(x[1] + x[0] - 6, 2) + 9.5;
// Градиент функции
public static double[] Gradient(Func<double[], double> f, double[] x)
{
double h = 1e-6;
double[] grad = new double[x.Length];
for (int i = 0; i < x.Length; i++)
{
double[] xForward = (double[])x.Clone();
double[] xBackward = (double[])x.Clone();
xForward[i] += h;
xBackward[i] -= h;
grad[i] = (f(xForward) - f(xBackward)) / (2 * h);
}
return grad;
}
// Метод золотого сечения для поиска шага
public static double GoldenSection(Func<double, double> f, double a, double b, double epsilon)
{
double phi = (1 + Math.Sqrt(5)) / 2;
double resphi = 2 - phi;
double x1 = a + resphi * (b - a);
double x2 = b - resphi * (b - a);
double f1 = f(x1);
double f2 = f(x2);
while (Math.Abs(b - a) > epsilon)
{
if (f1 < f2)
{
b = x2;
x2 = x1;
f2 = f1;
x1 = a + resphi * (b - a);
f1 = f(x1);
}
else
{
a = x1;
x1 = x2;
f1 = f2;
x2 = b - resphi * (b - a);
f2 = f(x2);
}
}
return (a + b) / 2;
}
// Метод наискорейшего спуска
public static (double[], double, List<double[]>)
SteepestDescentMethod(Func<double[], double> f, double[] x0, double epsilon)
{
List<double[]> sequence = new List<double[]> { (double[])x0.Clone() };
double[] x = (double[])x0.Clone();
double[] grad = Gradient(f, x);
int maxIterations = 1000;
for (int iter = 0; iter < maxIterations && Math.Sqrt(grad[0] * grad[0] + grad[1] *
grad[1]) > epsilon; iter++)
{
// Определяем функцию для поиска шага t
Func<double, double> phi = t =>
{
double[] xNew = { x[0] - t * grad[0], x[1] - t * grad[1] };
return f(xNew);
};
// Поиск шага методом золотого сечения
double t = GoldenSection(phi, 0, 1, epsilon);
// Обновляем x
x[0] -= t * grad[0];
x[1] -= t * grad[1];
sequence.Add((double[])x.Clone());
grad = Gradient(f, x);
}
return (x, f(x), sequence);
}
public static void Main(string[] args)
{
// Начальные точки для функций
double[] x0_F1 = { 3, 3 }; // Далеко от минимума
double[] x0_F2 = { 3, 3 }; // Далеко от минимума
double epsilon = 1e-6;// Точность
// Запуск для первой функции
Console.WriteLine("Функция 1:");
var result1 = SteepestDescentMethod(F1, x0_F1, epsilon);
Console.WriteLine($" Найденный минимум: x = ({Math.Round(result1.Item1[0], 2)},{Math.Round(result1.Item1[1], 2)}), f(x) = {Math.Round(result1.Item2, 2)}");
Console.WriteLine(" Последовательность точек:");
foreach (var x in result1.Item3)
{
Console.WriteLine($" ({Math.Round(x[0], 2)}, {Math.Round(x[1], 2)})");
}
Console.WriteLine();
// Запуск для второй функции
Console.WriteLine("Функция 2: ");
var result2 = SteepestDescentMethod(F2, x0_F2, epsilon);
Console.WriteLine($" Найденный минимум: x = ({Math.Round(result2.Item1[0], 2)},{Math.Round(result2.Item1[1], 2)}), f(x) = {Math.Round(result2.Item2, 2)}");
Console.WriteLine(" Последовательность точек:");
foreach (var x in result2.Item3)
{
Console.WriteLine($" ({Math.Round(x[0], 2)}, {Math.Round(x[1], 2)})");
}
}
}