Смекни!
smekni.com

Исследование методов оптимизации (стр. 8 из 8)

В результате реализации градиентного метода минимальное значение функции составляет

. Данный оптимум достигнут в точке
. Этот метод позволяет найти минимум (при начальной точке Х(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