Министерство образования науки РФ. Высшего профессионального учреждения Тверского государственный технический университет. Кафедра программного обеспечения. Методы вычислений Лабораторная работа №8 1 вариант выполнил студент группы ПИН 1106 Александренков А.Ю. проверил Грязнов Е. Н. Виноградов С. Ю. Тверь,2012 Задание: 1. Напишите программу, реализующую нахождение минимума функции методом равномерного поиска. 2. Напишите программу, реализующую нахождение минимума функции методом дихотомии. 3. Напишите программу, реализующую нахождение минимума функции методом золотого сечения. Замечания по реализации: 1. В качестве исходной функции брать f(x) = x^3 + 8*x^2 + x + 5, интервала – [-2, 1]. Метод перебора Метод перебора (метод равномерного поиска) — простейший из методов поиска значений действительно-значных функций по какому-либо из критериев сравнения (на максимум, на минимум, на определённую константу). Применительно к экстремальным задачам является примером прямого метода условной одномерной пассивной оптимизации. Oписание Проиллюстрируем суть метода равномерного поиска посредством рассмотрения задачи нахождения минимума. Пусть задана функция . И задача оптимизации выглядит так: Пусть также задано число наблюдений . Тогда отрезок разбивают на равных частей точками деления: Вычислив значения в точках , найдем путем сравнения точку , где — это число от до такую, что для всех от до . Тогда интервал неопределённости составляет величину а погрешность определения точки минимума функции соответственно составляет : . Модификация Если заданное количество измерений чётно ( проводить другим, более изощрённым способом: , ), то разбиение можно , где — некая константа из интервала Тогда в худшем случае интервал неопределённости имеет длину . . Метод дихотомии Метод дихотомии несколько схож с методом бисекции, однако отличается от него критерием отбрасывания концов. Пусть задана функция . Разобьём мысленно заданный отрезок пополам и возьмём две симметричные относительно центра точки и так, что: где — некоторое число в интервале . Вычислим два значения функции в двух новых точках. Сравнением определим в какой из двух новых точек значение функции максимально. Отбросим тот из концов изначального отрезка, к которому точка с максимальным значением функции оказалась ближе (напомним, мы ищем минимум), то есть: Если , то берётся отрезок , а отрезок отбрасывается. Иначе берётся зеркальный относительно середины отрезок ,а отбрасывается . Процедура повторяется, пока не будет достигнута заданная точность, к примеру, пока длина отрезка не достигнет удвоенного значения заданной погрешности. На каждой итерации приходится вычислять новые точки. Можно добиться того, чтобы на очередной итерации было необходимо высчитывать лишь одну новую точку, что заметно способствовало бы оптимизации процедуры. Это достигается путём зеркального деления отрезка в золотом сечении, в этом смысле метод золотого сечения можно рассматривать, как улучшение метода дихотомии с параметром где , — золотое сечение. Золотое сечение Золотое сечение (золотая пропорция, деление в крайнем и среднем отношении) — деление непрерывной величины на две части в таком отношении, при котором меньшая часть так относится к большей, как большая ко всей величине. Отношение большей части к меньшей в этой пропорции выражается квадратичной иррациональностью и, наоборот, отношение меньшей части к большей Число называется также золотым числом. В дошедшей до нас античной литературе деление отрезка в крайнем и среднем отношении (ἄκρος καὶ μέσος λόγος) впервые встречается в«Началах» Евклида (ок. 300 лет до н. э.), где оно применяется для построения правильного пятиугольника. Лука Пачоли, современник и друг Леонардо да Винчи, называл это отношение «божественной пропорцией». Термин «золотое сечение» (goldener Schnitt) был введён в обиход Мартином Омом в 1835 году. Золотое сечение имеет множество замечательных свойств, но ещё больше свойств вымышленных. Листинг Form using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms; namespace ClassLibrary { public partial class About8 : Form { public About8() { InitializeComponent(); Text = "Alex #8"; comboBox1.SelectedIndex = 0; } private void button1_Click(object sender, EventArgs e) { try { System.Diagnostics.Process proc = new System.Diagnostics.Process(); string Расчет; //задание директории в которой располагается изначальная программа Расчет = System.Windows.Forms.Application.StartupPath.ToString(); //задание параметров запускаемой программы proc.StartInfo.FileName = Расчет + "\\8.docx"; proc.StartInfo.WorkingDirectory = Расчет + "\\8.docx"; //запуск программы proc.Start(); } catch { MessageBox.Show("Ненайден файл !"); } } private void buttonGo_Click(object sender, EventArgs e) { { double a, b; int n = 0; double eps = 0; MinFyn answer; try { a = Convert.ToDouble(textBoxA.Text); b = Convert.ToDouble(textBoxB.Text); if (textBoxN.Enabled) { n = Convert.ToInt32(textBoxN.Text); if (n <= 0) throw new Exception(); } if (textBoxEps.Enabled) { eps = Convert.ToDouble(textBoxEps.Text); if (eps <= 0) throw new Exception(); } if (a > b) { double temp = a; a = b; b = temp; } } catch (Exception exc) { MessageBox.Show(exc.Message); return; } switch (comboBox1.Text) { case "Равномерного поиска": { answer = Calculation.MethodPerepor(a, b, n); break; } case "Дихотомии": { answer = Calculation.MethodDih(a, b, eps); break; } default: { answer = Calculation.MethodGoldSection(a, b, eps); break; } } textBoxAnswerX.Text = answer.Arg.ToString(); textBoxAnswerY.Text = answer.Value.ToString(); } } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (comboBox1.Text == "Равномерного поиска") { textBoxEps.Enabled = false; textBoxN.Enabled=true; textBoxN.Text="1"; } else { textBoxEps.Enabled = true; } if (comboBox1.Text == "Дихотомии" || comboBox1.Text == "Золотого сечения" ) { textBoxEps.Text = ("0,01"); textBoxN.Enabled = false; textBoxN.Clear(); } } } } Листинг dll using using using using System; System.Collections.Generic; System.Linq; System.Text; namespace ClassLibrary { public class MinFyn { double arg; double value; public MinFyn(double arg, double value) { this.arg = arg; this.value = value; } public double Arg { get { return this.arg; } } public double Value { get { return this.value; } } } /// <summary> /// Методы решения задачи /// </summary> public static class Calculation { /// <summary> /// Расчет значения функции по заданному аргументу /// </summary> /// <param name="arg">Аргумент</param> /// <returns>Значение</returns> static double GetValue(double arg) { return Math.Pow(arg, 3) + 8 * Math.Pow(arg, 2) + arg + 5; } /// <summary> /// Метод перебора /// </summary> /// <param name="a">Левая граница</param> /// <param name="b">Правая граница</param> /// <param name="n">Число отрезков</param> /// <returns>Значение</returns> public static MinFyn MethodPerepor(double a, double b, int n) { double h = (double)(b - a) / n; MinFyn[] array = new MinFyn[n + 1]; for (int i = 0; i < n + 1; i++) { array[i] = new MinFyn(a, GetValue(a)); a += h; } double minValue = array[0].Value; int minIndex = 0; for (int i = 1; i < n + 1; i++) { if (minValue > array[i].Value) { minValue = array[i].Value; minIndex = i; } } return array[minIndex]; } /// <summary> /// Метод дихотомии /// </summary> /// <param name="a">Левая граница</param> /// <param name="b">Правая граница</param> /// <param name="eps">Заданная точность</param> /// <returns>Значение </returns> public static MinFyn MethodDih(double a, double b, double eps) { double x1, x2; while (Math.Abs((b - a)) > 2 * eps) { x1 = a + (b - a) / 4; x2 = b - (b - a) / 4; if (GetValue(x1) > GetValue(x2)) a = x1; if (GetValue(x1) < GetValue(x2)) b = x2; if (GetValue(x1) == GetValue(x2)) { a = x1; b = x2; break; } } return new MinFyn((a + b) / 2, GetValue((a + b) / 2)); } /// <summary> /// Метод золотого сечения /// </summary> /// <param name="a">Левая граница</param> /// <param name="b">Правая граница</param> /// <param name="eps">Заданная точность</param> /// <returns>Значение</returns> public static MinFyn MethodGoldSection(double a, double b, double eps) { double fi = (1 + Math.Sqrt(5)) / 2; double x1, x2; while ((b - a) > 2 * eps) { x1 = b - ((b - a) / fi); x2 = a + ((b - a) / fi); if (GetValue(x1) > GetValue(x2)) a = x1; if (GetValue(x1) < GetValue(x2)) b = x2; if (GetValue(x1) == GetValue(x2)) { a = x1; b = x2; break; } } return new MinFyn((a + b) / 2, GetValue((a + b) / 2)); } } }