В результате реализации градиентного метода минимальное значение функции составляет
. Данный оптимум достигнут в точке . Этот метод позволяет найти минимум (при начальной точке Х(1;1)) за 1263 итерации при точности решения . При этом параметр останова равен 0,000099491.Для каждого из методов была установлена зависимость числа итераций от заданной точности . Анализируя полученные результаты, можно сделать вывод о том, что по числу итераций более эффективным является метод Нелдера-Мида. Однако следует отметить, что эффективность этих методов может изменяться в зависимости от выбора начального приближения и вида функции. Следует также учесть, что градиентный метод может быть непригоден в тех случаях, если расчет производных вызывает затруднение.
7. ПРИЛОЖЕНИЕ
В таблицах представлены координаты точек, образующих линии уровня
В настоящем приложении представлена реализация программного кода для каждого из методов оптимизации. Используемый язык программирования – VisualStudio C# 2005.
Градиентный метод с дроблением шага
namespace GradientL
{public partial class Form1 : Form
{public Form1()
{InitializeComponent();}
public static string[] str = new string[100000];
struct Tk
{public double x1, x2;
public Tk(double X, double Y)
{x1 = X;
x2 = Y;}
public static Tk operator /(Tk v1, double q)
{return new Tk(v1.x1 / q, v1.x2 / q);}
public static Tk operator *(Tk v, double d)
{return new Tk(v.x1 * d, v.x2 * d);}
public static Tk operator *(Tk v1, Tk v2)
{return new Tk(v1.x1 * v2.x1, v1.x2 * v2.x2);}
public static Tk operator -(Tk v1, Tk v2)
{return new Tk(v1.x1 - v2.x1, v1.x2 - v2.x2);}
public static Tk operator +(Tk v1, Tk v2)
{return new Tk(v1.x1 + v2.x1, v1.x2 + v2.x2);}
public static double Dist(Tk v1, Tk v2)
{return Math.Sqrt((v1.x1 - v2.x1) * (v1.x1 - v2.x1) + (v1.x2 - v2.x2) * (v1.x2 - v2.x2));}
public override string ToString()
{return "(" + this.x1.ToString("f5") + ";" + this.x2.ToString("f5") + ")";}}
class Pr
{public static double f(Tk c)
{return 12 + c.x1 * c.x1 + (1 + c.x2 * c.x2) * c.x2 * c.x2 + (c.x1 * c.x1 * c.x2 * c.x2 + 100) * (c.x1 - c.x2) * (c.x1 - c.x2);}
static Tk gradient(Tk c)
{Tk N = new Tk(2 * c.x1 + 2 * c.x1 * c.x2 * c.x2 *
( c.x1 - c.x2)*(c.x1 - c.x2) + 2 * (c.x1 * c.x1 * c.x2 * c.x2 + 100) * (c.x1 - c.x2),
2 * c.x2*c.x2*c.x2+2*c.x2*(1+c.x2*c.x2)+
2*c.x2*c.x1*c.x1*(c.x1-c.x2)*(c.x1-c.x2)-2*(c.x1-c.x2)*
(c.x1*c.x1*c.x2*c.x2+100));
return N;}
public static double Dl(Tk c)
{return Math.Sqrt(c.x1 * c.x1 + c.x2 * c.x2);}
public static void Tr(double eps, ref Tk ca, out double fn, out int i)
{Tk cb = new Tk(1, 1), st = new Tk(0.5, 0.5);
Tk step = new Tk(1, 1), eq; i = 0;
do
{while (true)
{cb = ca - step * gradient(ca);
eq = st * step * gradient(cb) * gradient(cb);
if (f(cb - step * gradient(cb)) >= (f(cb) - Dl(eq)))
{ step.x1 /= 2;
step.x2 /= 2;}
else break;}
fn = f(ca);
i++;
str[i] = String.Format("{0}" + ") " + "{1}" + "; " +
"{2}" + "; " + "{3}" + ".", i.ToString(), ca.ToString(), fn.ToString("f6"), Dl(gradient(cb)).ToString("f6"));
ca = cb;}
while (Dl(gradient(cb)) >= eps);
fn = f(cb);}}
private void button1_Click(object sender, EventArgs e)
{listBox1.Items.Clear();
double Et = Convert.ToDouble(textBox3.Text);
double fn;
int j;
Tk mas = new Tk(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text));
Pr.Tr(Et, ref mas, out fn, out j);
Min.Visible = true;
Min.Text = String.Format("{0}" + "; " + "{1}" + "; " +
"{2}", mas.ToString(), fn.ToString(), j.ToString());
for (int i = 1; i < j; i++)
listBox1.Items.Add(str[i]);}
private void Form1_Load(object sender, EventArgs e){}}}
Метод Нелдера-Мида
namespace Nelder_Method
{public partial class Form1 : Form
{public Form1()
{InitializeComponent();}
static double Al = 1.0;
static double Bt = 0.5;
static double Gm = 2.0;
static int n=0;
static string[] op = new string[1000];
const int cap = 2;
struct Tk
{public double x1, x2;
public Tk(double X, double Y)
{x1 = X;
x2 = Y;}
public static Tk operator /(Tk v1, double q)
{return new Tk(v1.x1 / q, v1.x2 / q);}
public static Tk operator *(Tk v, double d)
{return new Tk(v.x1 * d, v.x2 * d);}
public static Tk operator *(Tk v1, Tk v2)
{return new Tk(v1.x1 * v2.x1, v1.x2 * v2.x2);}
public static Tk operator -(Tk v1, Tk v2)
{return new Tk(v1.x1 - v2.x1, v1.x2 - v2.x2);}
public static Tk operator +(Tk v1, Tk v2)
{return new Tk(v1.x1 + v2.x1, v1.x2 + v2.x2);}
public static double Dist(Tk v1, Tk v2)
{return Math.Sqrt((v1.x1 - v2.x1) * (v1.x1 - v2.x1) + (v1.x2 - v2.x2) * (v1.x2 - v2.x2));}
public override string ToString()
{return "(" + this.x1.ToString("f5") + ";" + this.x2.ToString("f5") + ")";}}
class Cnt
{public static double function(Tk c)
{return 12 + c.x1*c.x1 + (1+c.x2*c.x2)*c.x2*c.x2 + (c.x1*c.x1*c.x2*c.x2+100)*(c.x1-c.x2)*(c.x1-c.x2);}
public static void Pr(ref Tk[] c, ref double[] ot)
{double fir; Tk tk;
for (int k = 1; k <= cap; k++)
for (int l = k; l >= 1; l--)
if (ot[l - 1] > ot[l])
{fir = ot[l];
tk = c[l];
ot[l] = ot[l - 1];
c[l] = c[l - 1];
ot[l - 1] = fir;
c[l - 1] = tk;}
else break;}
public static bool Ostanov(Tk[] w, double E, double n, Tk c, out double Ost)
{double Lp;
double d = 0.5;
double p1 = 0;
Tk p2 = new Tk(0, 0);
for (int i = 0; i <= cap; i++)
{p1 += (function(w[i]) - function(c)) * (function(w[i]) - function(c));
p2 += (w[i] - c) * (w[i] - c);}
Lp = Math.Sqrt(p2.x1 * p2.x1 + p2.x2 * p2.x2);
Ost = d * (Math.Sqrt((1 / (n + 1)) * p1)) + (1 - d) * (Math.Sqrt((1 / (n + 1)) * Lp));
if (Ost < E)
return true;
else return false;}
public static double Met(Tk[] c, double tchn)
{double[] f = new double[cap + 1];
double val1=0, val2=0, val3 = 0, val4, val5, val6, val7;
Tk sim1, sim2, sim3, sim4, sim5, sim6, sim_cen, sim7;
sim_cen.x1 = sim_cen.x2 = 0;
int i;
double J1;
bool flag;
for (i = 0; i <= cap; i++) // Вычисление значений функции на начальном симплексе
f[i] = function(c[i]);
while (!Ostanov(c, tchn, n, sim_cen, out J1))// Проверка на условие выхода
{n++;
// Шаг 1. Сортировка
Pr(ref c, ref f);
sim1 = c[cap]; val1 = f[cap];
sim2 = c[cap - 1]; val2 = f[cap - 1];
sim3 = c[0]; val3 = f[0];
// Шаг 2. Вычисление центра тяжести симплекса
sim_cen.x1 = sim_cen.x2 = 0;
for (i = 0; i < cap; i++)
sim_cen = sim_cen + c[i];
sim_cen = sim_cen / cap;
// 3Шаг . Отражение
sim4 = sim_cen * (1 + Al) - sim1 * Al; val4 = function(sim4);
// Шаг 4.
if (val4 <= val3)
{ // Шаг 4a.
sim5 = sim_cen * (1 - Gm) + sim4 * Gm;
val5 = function(sim5);
if (val5 < val3)
{c[cap] = sim5;
f[cap] = val5;}
else
{c[cap] = sim4;
f[cap] = val4;}}
if ((val3 < val4) && (val4 <= val2))
{ // Шаг 4.b
c[cap] = sim4;
f[cap] = val4;}
flag = false;
if ((val1 >= val4) && (val4 > val2))
{ // Шаг 4c.
flag = true;
val7 = val1;
sim7 = sim1;
c[cap] = sim4;
f[cap] = val4;
sim4 = sim7;
val4 = val7;}
// Шаг 4d.
if (val4 > val1) flag = true;
if (flag)
{// Шаг 5. Сжатие
sim6 = sim1 * Bt + sim_cen * (1 - Bt);
val6 = function(sim6);
if (val6 < val1)
{ // Шаг 6.
val7 = val1;
sim7 = sim1;
c[cap] = sim6;
f[cap] = val6;
sim6 = sim7;
val6 = val7;}
else
{ // Шаг 7. Глобальноесжатие
for (i = 0; i <= cap; i++)
c[i] = sim3 + (c[i] - sim3) / 2;}}
op[n - 1] = Convert.ToString(n) + "; " + sim1.ToString() +
"; " + sim2.ToString() + "; " + sim3.ToString();}
return (val3 + val1 + val2) / 3;}}
private void button1_Click(object sender, EventArgs e)
{Tk ta = new Tk(0, 0);
Tk tb = new Tk(0.26, 0.96);
Tk tc = new Tk(0.96, 0.26);
Tk[] t = new Tk[3] { ta, tb, tc };
listBox1.Items.Clear();
n = 0;
op = new string[200];
double eps1 = Convert.ToDouble(textBox2.Text);
label4.Text = Cnt.Met(t, eps1).ToString("f5") + "; " + Convert.ToString(n) + ".";
for (int i = 0; i < n; i++)
listBox1.Items.Add(op[i]);}
private void Form1_Load(object sender, EventArgs e){}}
8. СПИСОК ИСПОЛЬЗУЕМОЙ ЛИТЕРАТУРЫ
1. Агуров П.В. C# в подлиннике (программирование на языке С#) – Петербург, 2006
2. Агуров П.В. Сборник рецептов по C# - Петербург,2006
3. Банди Б. Методы оптимизации – Москва, 1988
4. Базара М, Шетти К. Нелинейное программироваине. Теория и алгоритмы – М.:Мир, 1988
5. Поляк Б.Т. Введение в оптимизацию. - М.: Наука, 1983
6. Раскин Л.Г. Математическое программирование: Учебное пособие – Харьков: НТУ «ХПИ» , 2002
7. Рихтер Д. Программирование на платформе Microsoft. NET Freamework для профессионалов – М.Microsoft Press, 2003
8. Серая О.В. Методические указания для проведения лабораторных работ по курсу «Математическое программирование» - Харьков: НТУ «ХПИ» , 2003
9. Сухарев А.Г., Тимохов А.В Курс методов оптимизации – М.: Наука, 1986
10. Химмельблау Д. Прикладное нелинейное программирование М.:Мир, 1989