
Приложение b
using System;
using System.Collections.Generic;
public class DichotomyMethod
{
public static double F1(double x) => 5 - 3 * Math.Exp(-Math.Pow((x - 5) / 3, 2));
public static double F2(double x) => 3 * (x - 4) * (x - 3) * (x - 1);
public static double F3(double x) => (x / 2) + 5 * Math.Sin(5 * Math.PI * x + 4);
public static (double minX, double minVal, int iterCount, List<double> xSequence)
Dichotomy(Func<double, double> f, double a, double b, double tol = 1e-5, int maxIter = 100)
{
List<double> xSequence = new List<double>();
int iterCount = 0;
while ((b - a) > tol && iterCount < maxIter)
{
double c1 = (a + b) / 2 - tol / 2;
double c2 = (a + b) / 2 + tol / 2;
xSequence.Add(c1);
xSequence.Add(c2);
if (f(c1) < f(c2))
{
b = c2;
}
else
{
a = c1;
}
iterCount++;
}
double xMin = (a + b) / 2;
xSequence.Add(xMin);
return (xMin, f(xMin), iterCount, xSequence);
}
public static double[] GenerateLinearSpace(double start, double end, int numPoints)
{
double[] result = new double[numPoints];
double step = (end - start) / (numPoints - 1);
for (int i = 0; i < numPoints; i++)
{
result[i] = start + i * step;
}
return result;
}
public static void Main(string[] args)
{
Func<double, double>[] functions = { F1, F2, F3 };
string[] functionNames = { "f1", "f2", "f3" };
(double, double)[] intervals = { (0, 10), (-2, 8), (-5, 5) };
for (int i = 0; i < functions.Length; i++)
{
Console.WriteLine($"Функция {functionNames[i]}:");
(double minX, double minVal, int iterCount, List<double> xSequence) =
Dichotomy(functions[i], intervals[i].Item1, intervals[i].Item2);
Console.WriteLine($" Метод дихотомии:");
Console.WriteLine($" Начальный отрезок: [{Math.Round(intervals[i].Item1, 2)}, {Math.Round(intervals[i].Item2, 2)}]");
Console.WriteLine($" Число итераций: {iterCount}");
Console.WriteLine($" Найденный минимум: x = {Math.Round(minX, 2)}, f(x) = {Math.Round(minVal, 2)}");
Console.WriteLine($" Последовательность точек: {string.Join(", ", xSequence.ConvertAll(x => Math.Round(x, 2)))}");
}
}
}
Приложение c
using System;
class NelderMeadMethod
{
// Первая целевая функция
static double Function1(double x1, double x2)
{
return 8 * Math.Pow(x1 - 1, 2) + 3 * Math.Pow(x2 - 1, 2);
}
// Вторая целевая функция
static double Function2(double x1, double x2)
{
return Math.Pow(x1 - 5, 2) + Math.Pow(x2 - 1, 2) + 30 * Math.Pow(x2 + x1 - 6, 2) + 9.5;
}
public static void FindMinimum(double[][] simplex, double alpha, double beta,
double gamma, double epsilon, Func<double, double, double> function)
{
int dimensions = simplex[0].Length;
int iterations = 0;
while (true)
{
iterations++;
Array.Sort(simplex, (a, b) => function(a[0], a[1]).CompareTo(function(b[0],
b[1])));
// Лучшая, вторая лучшая и худшая точки
double[] best = simplex[0];
double[] secondBest = simplex[1];
double[] worst = simplex[dimensions - 1];
// Вычисляем центроид
double[] centroid = new double[dimensions];
for (int i = 0; i < dimensions; i++)
{
centroid[i] = 0;
for (int j = 0; j < dimensions - 1; j++)
{
centroid[i] += simplex[j][i];
}
centroid[i] /= (dimensions - 1);
}
// Отражение
double[] reflected = new double[dimensions];
for (int i = 0; i < dimensions; i++)
{
reflected[i] = centroid[i] + alpha * (centroid[i] - worst[i]);
}
if (function(reflected[0], reflected[1]) < function(best[0], best[1]))
{
// Расширение
double[] expanded = new double[dimensions];
for (int i = 0; i < dimensions; i++)
{
expanded[i] = centroid[i] + gamma * (reflected[i] - centroid[i]);
}
if (function(expanded[0], expanded[1]) < function(reflected[0], reflected[1]))
{
simplex[dimensions - 1] = expanded;
}
else
{
simplex[dimensions - 1] = reflected;
}
}
else if (function(reflected[0], reflected[1]) < function(secondBest[0],
secondBest[1]))
{
simplex[dimensions - 1] = reflected;
}
else
{
// Сжатие
double[] contracted = new double[dimensions];
for (int i = 0; i < dimensions; i++)
{
contracted[i] = centroid[i] + beta * (worst[i] - centroid[i]);
}
if (function(contracted[0], contracted[1]) < function(worst[0], worst[1]))
{
simplex[dimensions - 1] = contracted;
}
else
{
// Уменьшение
for (int i = 1; i < dimensions; i++)
{
simplex[i] = new double[dimensions];
for (int j = 0; j < dimensions; j++)
{
simplex[i][j] = best[j] + 0.5 * (simplex[i][j] - best[j]);
}
}
}
}
// Вывод текущих точек симплекса
Console.WriteLine($"Итерация {iterations}:");
for (int i = 0; i < simplex.Length; i++)
{
double f = function(simplex[i][0], simplex[i][1]);
Console.WriteLine($"Точка {i + 1}: x1 = {Math.Round(simplex[i][0], 2)}, x2 = {Math.Round(simplex[i][1], 2)}, f(x1, x2) = {Math.Round(f, 2)}");
}
Console.WriteLine();
// Проверка на сходимость
double range = 0;
for (int i = 0; i < dimensions; i++)
{
range = Math.Max(range, Math.Abs(simplex[i][0] - simplex[0][0]));
range = Math.Max(range, Math.Abs(simplex[i][1] - simplex[0][1]));
}
if (range < epsilon)
{
break;
}
}
Console.WriteLine($"Минимум найден в точке: x1 = {Math.Round(simplex[0][0], 2)}, x2 = {Math.Round(simplex[0][1], 2)}");
Console.WriteLine($"Значение минимума для f(x1, x2): {Math.Round(function(simplex[0][0], simplex[0][1]), 2)}");
Console.WriteLine($"Количество итераций: {iterations}");
}
static void Main(string[] args)
{
// Начальные точки симплекса для первой функции
double[][] simplex1 = new double[][]
{
new double[] { 0.0, 0.0 }, new double[] { 5.0, 5.0 }, new double[] { 10.0, 10.0 }
};
// Начальные точки симплекса для второй функции
double[][] simplex2 = new double[][]
{
new double[] { 0.0, 0.0 }, new double[] { 5.0, 5.0 }, new double[] { 10.0, -10.0 }
};
// Параметры метода Нелдера-Мида
double alpha = 1.0; // коэффициент отражения
double beta = 0.5; // коэффициент сжатия
double gamma = 2.0; // коэффициент расширения
double epsilon = 1e-5; // точность
// Запуск метода Нелдера-Мида для первой функции
Console.WriteLine("Минимизация первой функции:");
FindMinimum(simplex1, alpha, beta, gamma, epsilon, Function1);
Console.WriteLine();
// Запуск метода Нелдера-Мида для второй функции
Console.WriteLine("Минимизация второй функции:");
FindMinimum(simplex2, alpha, beta, gamma, epsilon, Function2);
}
}