Метод бажаної точки при прийнятті рішень в умовах визначеності та його програмна реалізація

Автор: Пользователь скрыл имя, 23 Марта 2012 в 08:23, дипломная работа

Описание работы

Мета роботи полягає у вивченні теоретичних основ щодо прийняття рішень в умовах визначеності, задач багатокритеріальної оптимізації та програмної реалізації методу багатокритеріальної оптимізації, а саме методу бажаної точки.
Виходячи з поставленої мети, в роботі розв’язано низку наступних завдань:
- розгляд прикладів багатокритеріальності;
- ознайомлення із задачами багатокритеріального програмування;
- вивчення основних понять та принципів теорії прийняття рішень в умовах визначеності;
- з’ясування основних методів багатокритеріальної оптимізації;
- розробка програмної реалізації методу бажаної точки.

Содержание

ВСТУП………………………………………………………...……………………...3
РОЗДІЛ 1. ІНФОРМАЦІЙНИЙ ОГЛЯД…………………………………………...5
1.1. Огляд задач багатокритеріального програмування,
приклади багатокритеріальності………...………………………..……5
1.2. Поняття про багатокритеріальну оптимізацію……………...…………8
РОЗДІЛ 2. ТЕОРЕТИЧНА ЧАСТИНА………………………………..………….11
2.1. Основні поняття та визначення теорії прийняття рішень
в умовах визначеності…………………………..…………………….11
2.2. Загальні відомості про задачі багатокритеріальної оптимізації..….12
2.3. Постановка задачі багатокритеріальної оптимізації……..…………18
2.4. Методи багатокритеріальної оптимізації………..…………………..29
2.5. Метод бажаної точки при прийнятті рішень в умовах
визначеності…………………………………………………………...32
РОЗДІЛ 3. ПРАКТИЧНА РЕАЛІЗАЦІЯ…………………………………. ………36
3.1. Блок-схема алгоритму …………………….………………………...36
3.2. Опис програмної реалізації методу бажаної точки………………....38
ВИСНОВКИ………………………………………………………………………...45
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ ………………………………………..46
ДОДАТОК А………………….…………………………………………………….48

Работа содержит 1 файл

Жездріс.docx

— 437.85 Кб (Скачать)

  Form1.Label15.Visible:=false;

  Form1.Label16.Visible:=false;

  Form1.Label17.Visible:=false;

  Form1.Label18.Visible:=false;

  Form1.Label19.Visible:=false;

end; end.

 

Програмний код  модуля Unit2.pas

 

unit Unit2;

interface

// підключення модулів  Unit3,StdCtrls

// в Unit3 оголошено новий тип даних func і функції, які будемо викоритовути

// в StdCtrls описан, зокрема, клас TMemo

uses Unit3,StdCtrls;

// пошук екстремуму градієнтним  методом

// z - функція, екструмум якої шукають

// dz_dx1 - функція, похідна функцї f по х1

// dz_dx2 - функція, похідна функцї f по х2

// dz_dx3 - функція, похідна функцї f по х3

// Memo1 - компонент Memo - текстове багаторядкове поле, в яке будуть виведені результати

// x1_Edit,x2_Edit,x3_Edit - компоненти  xEdit, з яких будуть зчитані значення початкової точки

// y_opt - мінімальне значення  функції z

procedure GradientMethod (z, dz_dx1, dz_dx2, dz_dx3: func; Memo1: TMemo; x1_Edit, x2_Edit,x3_Edit:TEdit; var y_opt:real);

procedure MethodBaganTochki(y_f,y_t:real; zz,mm:func);

// оголошення глобальних  змінних

// змінні використаємо  в моднлі Unit4

var

  f1_min_gr,f1_max_gr:real; // мінімальне та максимальне значення першого критерію

  f2_min_gr,f2_max_gr:real; // мінімальне та максимальне значення другого критерію

 

implementation

// підключення модулів  QDialogs,SysUtils, Unit1,QForms

// в цих модулях описані  функції FloatToStr, ShowMessage - та інші

uses QDialogs,SysUtils, Unit4, Unit1,QForms;

// пошук екстремуму градієнтним  методом

// z - функція, екструмум  якої шукають

// dz_dx1 - функція, похідна функцї f по х1

// dz_dx2 - функція, похідна функцї f по х2

// dz_dx3 - функція, похідна функцї f по х3

// Memo1 - компонент Memo - текстове багаторядкове поле, в яке будуть виведені результати

// x1_Edit,x2_Edit,x3_Edit - компоненти  Edit, з яких будуть зчитані значення початкової точки

// y_opt - мінімальне значення  функції z

procedure GradientMethod (z, dz_dx1, dz_dx2, dz_dx3: func; Memo1:TMemo; x1_Edit, x2_Edit, x3_Edit:TEdit; var y_opt:real);

const

  epsilon=0.001; // точність, з  якою знаходимо екстремум

  SIZE=10000;    // вимірність  масивів x1,x2,x3; кількість ітерацій

var

  Ro:real;

  x1,x2,x3:array [0..SIZE]of real;

// масиви для зберігання  значення x1,x2,x3 на кожній ітерації

  y1, y2:real;

// y2 - для обчислення значення функції на поточній ітерації,

// y1 - для обчислення значення функції на попередні1 ітерації

  g:textfile;  // текстовий файл

  i,k:integer; // лічильники

  q1,q2:real; 

// q1 - значення похідної функції z по x3 на попередній ітерації

// q2 - значення похідної функції z по x3 на поточній ітерації

  w1,w2:real; 

// w1 - значення похідної функції z по x1 на попередній ітерації

// w2 - значення похідної функції z по x1 на поточній ітерації

  v1,v2:real; 

// v1 - значення похідної функції z по x2 на попередній ітерації

// v2 - значення похідної функції z по x2 на поточній ітерації

begin

    // вказуємо, що  працюємо з файлом result.txt

  // файл повинен розміщуватися  в тій же папці, що і програма

  assignfile(g,'result.txt');

  append(g);// відкриваємо файл і дописуємо інформацію в кінець

  writeln(g,'');//вивід пустого рядочка в файл

  if Form1.Tag=0 then

    writeln(g, 'Шукаємо мінімальне значення першої цільової функції градієнтним методом') // виведення в файл

  else

     writeln(g, 'Шукаємо мінімальне значення другої цільової функції градієнтним методом'); // виведення в файл

  // виведення в файл  змінної epsilon

  // файл збірігає рядочки  символів, змінна epsilon є дійсною

  // для перетворення  з дійсного типу в рядок 

  // використовується функція  FloatToStr

  writeln(g,'Точність epsilon = '+FloatToStr(epsilon));

  writeln(g,''); // записуємо в файл пустий рядок

  // вибір початкової  точки Х0

  i:=0; // - номер ітерації, використовується в якості індексу

// масивів x1[i], x3[i], x3[i]

  // зчитуємо значення початкової точки з компонентів x1_Edit,

  // x2_Edit, x3_Edit

  x1[i]:=StrToFloat(x1_Edit.Text);

// StrToFloat перетворює рядок символів в дійсне число

  x2[i]:=StrToFloat(x2_Edit.Text);

  x3[i]:=StrToFloat(x3_Edit.Text);

  // виведення в файл початкової точки і значення функції в цій точці

  // FloatToStr - перетворює змінного дійсного типу в рядок символів

  // знак "+" обєднує  декілька текстових рядочків  в один

  writeln(g,'Вибираємо початкову точку:');

  writeln(g,'x1['+ IntToStr(i)+'] = '+FloatToStr(x1[i]));

  writeln(g,'x2['+ IntToStr(i)+'] = '+FloatToStr(x2[i]));

  writeln(g,'x3['+IntToStr(i)+'] = '+FloatToStr(x3[i]));

  writeln(g,'Значення функції в початковiй точці:');

  writeln(g,'y['+IntToStr(i)+']= ',FloatToStr(z(x1[i], x2[i], x3[i])));

// викликаємо функцію z, для того, щоб обчислити значення функції

// в початковій точці

  // виведення в файл

  writeln(g,'');

  writeln(g,'Вибираємо ro:');

  Ro:=1 ;

  repeat

    Ro:=Ro/10;

// на кожному виткові  циклу зменьшуємо Ro,

// зменьшуючи його в  10 разів

    writeln(g, 'ro = '+FloatToStr(Ro)); // виведення в файл значення Ro

    writeln(g,'');

    k:=0;

    repeat

      k:=k+1; // показує кількість ітерацій з цим Ro

      i:=i+1;

      if i>SIZE then // якщо кількість ітерацій більше ніж вимірність

// масиву, то буде логічна  помилка!

      begin

        // виводимо  повідмлення за допомогою функції  ShowMessage

        ShowMessage('В програмі маленька вимірність масивів. Аварійний вихід! Візьміть іншу початкову точку!');

        closefile(g); // перез виходом закриваємо файл

        exit;// вихід з процедури GradientMethod

      end;

      // обчислення наступної точки

      x1[i]:= x1[i-1]-RO*dz_dx1(x1[i-1],x2[i-1],x3[i-1]);

      x2[i]:= x2[i-1]-RO*dz_dx2(x1[i-1],x2[i-1],x3[i-1]);

      x3[i]:= x3[i-1]-RO*dz_dx3(x1[i-1],x2[i-1],x3[i-1]);

      // y2 обчислення значення функції в цій точці

      y2:=z(x1[i], x2[i], x3[i]);

      y1:=z(x1[i-1], x2[i-1], x3[i-1]);

// y1 обчислення значення функції в цій точці,

// яка була на попередній ітерації

// виводимо в файл точку  на поточній ітерацій 

// і значення функцій  в цій точці

      writeln(g,'Ітерація №'+IntToStr(k)+' для ro='+FloatToStr(Ro)); 

// IntToStr перетворює цілу змінну в рядок символів

      writeln(g,'Отримали точку:');

      writeln(g,'x1['+IntToStr(i)+'] = '+FloatToStr(x1[i]));

      writeln(g,'x2['+IntToStr(i)+'] = '+FloatToStr(x2[i]));

      writeln(g,'x3['+IntToStr(i)+'] = '+FloatToStr(x3[i]));

      writeln(g,'Значення функції в точці:');

      writeln(g,'y['+IntToStr(i)+'] = ',FloatToStr(y2));

      writeln(g,''); // пустий рядок виводимо в файл

      // якщо значення  функцій на цій ітерації більше  ніж значення 

      // функцій  на попередній ітерації

      if y2>=y1 then

      begin

        writeln(g,FloatToStr(y2)+'>='+FloatToStr(y1));

        writeln(g,'Ітерація  з ro = '+FloatToStr(Ro)+' завершилась');

      end

      else

        writeln(g,FloatToStr(y2)+'<'+FloatToStr(y1));

    until  (y2>=y1); // кінець  циклу repeat until

    writeln(g,''); // пустий рядок виводимо в файл

    if y1>0 then

      writeln(g, '|' + FloatToStr(y2) + '-' + FloatTostr(y1) + '| = ' + FloatToStr (abs (y2-y1)))

//abs  - модуль числа

    else

      writeln(g, '|' + FloatToStr(y2) + '+' + FloatTostr (y1*(-1)) + '| = ' + FloatToStr (abs(y2-y1)));

    // w1 - значення похідної функції z по x1 на попередній ітерації

    w1:=dz_dx1(x1[i-1],x2[i-1],x3[i-1]);

    // w2 - значення похідної функції z по x1 на поточній ітерації

    w2:=dz_dx1(x1[i],x2[i],x3[i]);

    writeln (g, 'df_dx1 (попередня ітерація) = ' + FloatToStr(w1) + ' df_dx1 (поточна ітерація)= '+FloatToStr(w2));

    if w1>=0 then

      writeln(g, '|' + FloatToStr(w2) + '-' + FloatTostr(w1)+'| = '+ FloatToStr (abs(w2-w1)))

    else

      writeln(g, '|' + FloatToStr(w2) + '+' + FloatTostr (w1*(-1)) + '| = ' + FloatToStr (abs(w2-w1)));

    // v1 - значення похідної функції z по x2 на попередній ітерації

    v1:= dz_dx2(x1[i-1],x2[i-1],x3[i-1]);

    // v2 - значення похідної функції z по x2 на поточній ітерації

    v2:= dz_dx2(x1[i],x2[i],x3[i]);

    writeln(g, 'df_dx2 (попередня ітерація) = ' + FloatToStr(v1) + ' df_dx2 (поточна ітерація) = '+FloatToStr(v2));

    if v1>=0 then

      writeln(g,'|'+FloatToStr(v2)+'-'+FloatTostr(v1)+'| = '+FloatToStr(abs(v2-v1)))

    else

      writeln(g, '|' + FloatToStr(v2) + '+' + FloatTostr(v1*(-1)) + '| = ' + FloatToStr(abs(v2-v1)));

    // q1 - значення похідної функції z по x3 на попередній ітерації

    q1:= dz_dx3(x1[i-1],x2[i-1],x3[i-1]);

    // q2 - значення похідної функції z по x3 на поточній ітерації

    q2:= dz_dx3(x1[i],x2[i],x3[i]);

    writeln(g, 'df_dx3 (попередня ітерація)= ' + FloatToStr(q1) + ' df_dx3 (поточна ітерація) = '+FloatToStr(q2));

    if q1>=0 then

      writeln(g,'|'+FloatToStr(q2)+'-'+FloatTostr(q1)+'| = '+FloatToStr(abs(q2-q1)))

    else

      writeln(g, '|' + FloatToStr(q2) + '+' + FloatTostr(q1*(-1)) + '| = '+FloatToStr(abs(q2-q1)));

    // якщо різниця (за модулем) значень функції на цій ітерації і на попередній менше за точність epsilon

    // і різниця  (за модулем) значень похідних  функції на цій ітерації і  на попередній менше за точність  epsilon

    // то екстремум знайшли

    if (abs(y2-y1) <= epsilon) and (abs(w2-w1) <= epsilon) and (abs(v2-v1)<=epsilon)

    and (abs(q2-q1)<=epsilon)  then

    begin

      // вивід  в файл екстремуму

      writeln(g,'');

      writeln(g, 'Екстремум функції з точністю ' + FloatToStr(epsilon) + ' знайдено.');

      writeln(g, 'x1 = '+FloatToStr(x1[i]));

      writeln(g, 'x2 = '+FloatToStr(x2[i]));

      writeln(g, 'x3 = '+FloatToStr(x3[i]));

      writeln(g, 'y = '+FloatToStr(y2));

      // вивід  в Memo1 екстремуму

      Memo1.Lines.Add(' x1 = '+FloatToStr(x1[i]));

      Memo1.Lines.Add(' x2 = '+FloatToStr(x2[i]));

      Memo1.Lines.Add(' x3 = '+FloatToStr(x3[i]));

      Memo1.Lines.Add(' y min = '+FloatToStr(y2));

      if Form1.Tag=0 then

      begin

        // Caption дозволяє вивести текст в компонент  Label

        // Label4 - текстова статична мітка

        // FloatToStrF - перетворює дійсне число в рядок символів

        // і  задає формат виведення

        // ffNumber означає, що формат буде числовий

        // 3 означає,  що під чсило віводиться три  знаки

        // 0 означає,  що після десяткової коми буде  виведоно 0 знаків

        Form4.Label4.Caption:='Межі: від '+FloatToStrF(y2,ffNumber,3,0);

        f1_min_gr:=y2;

// наймеше значення першого  критерію запамятали в змінній  f1_min_gr

      end;

      if Form1.Tag=1 then

      begin

        Form4.Label5.Caption:='Межі: від '+FloatToStrF(y2,ffNumber,3,0);

        f2_min_gr:=y2;

// наймеше значення другого  критерію запамятали в змінній  f1_min_gr

      end;      

      y_opt:=y2;

// y_opt - значення, яке процелура повертає,

// мінімальне значення  функції

    end

  until (abs(y2-y1)<=epsilon)  and (abs(w2-w1)<=epsilon)  and  (abs(v2-v1)<=epsilon)

    and (abs(q2-q1)<=epsilon) ;

  closefile(g);  // закриття  файлу

end;

// перетворення бажаних  значень цільових функцій

// до нормованого безрозмірного  вигляду

// ksi - бажане значення функції

// max - максимальне значення функції

// min - мінімальне значення функції

function w(ksi, max, min:real):real;

begin

  result:=(max-ksi)/(max-min); // result - вказує, що функцій повертає

end;

// метод Монте-Карло для  знаходження максимального значення

// max_f,max_t - максимальні значення функцій

// y_f,y_t  - мінімальні значення функцій

// f1,t1 - функції

// Ro_f,Ro_t - вагові коефіцієнти критеріїв

// x1_max,x2_max,x3_max - ефективна альтернатива

procedure MethodMonteKarlo (max_f, max_t, y_f ,y_t: real; f1, t1:func; Ro_f, Ro_t: real; var x1_max, x2_max, x3_max: real);

const

  a=10;

var

  x1,x2,x3:real; // точка

  kr1,kr2:real;

  min,max:real;

  ww1,ww2:real;

  i:integer; // лічильник

begin

  // генеруємо  точку  з діапазону [0,а] випадковим  чином

  // random - повертає випадкове число з діапазону [0,1]

  // тоді a*random буде повертати випадкове число з діапозону [0,а]

  x1:=a*random;

  x2:=a*random;

  x3:=a*random;

  ww1:=(max_f- f1(x1,x2,x3))/(max_f-y_f);

  ww2:=(max_t- t1(x1,x2,x3))/(max_t-y_t);

  kr1:=Ro_f*ww1;

  kr2:=Ro_t*ww2;

  // шукаємо мінімальне з чисел kr1, kr2

  // мінімальне значення будемо зберігати в змінній min

  min:=kr1;

  if kr2<kr1 then

    min:=kr2;

  // далі 1000 раз генеруємо  точку випадковим чином

  // при цьому кожен  раз шукаємо kr1,kr2

  // обираємо з kr1 і kr2 мінімальне значення

  // і запамятовуємо  саме велике значення змінної  min

  // саме велике буде  зберігатися в змінній  max

  max:=min;

  x1_max:=x1;

  x2_max:=x2;

  x3_max:=x3;

  for i:=1 to 10000 do

  begin

    x1:=a*random;

    x2:=a*random;

    x3:=a*random;

    ww1:=(max_f- f1(x1,x2,x3))/(max_f-y_f);

    ww2:=(max_t- t1(x1,x2,x3))/(max_t-y_t);

    kr1:=Ro_f*ww1;

    kr2:=Ro_t*ww2;

    min:=kr1;

    if kr2<kr1 then

      min:=kr2; 

    if min>max then

    begin

      max:=min;

      x1_max:=x1;

      x2_max:=x2;

      x3_max:=x3;

    end;

  end;

end;

// реалізація методу бажаної  точки

// y_f - найменше значення першого критерію

// y_t - найменше значення другого критерію

// zz - перший критерій

// mm - другий критерій

procedure MethodBaganTochki(y_f,y_t:real; zz,mm:func);

const

  a=10;

var

  p:array [1..8] of real;

  s:array[1..8] of real;

  max_f, max_t:real; //  max_f - максимальне  значення першої функції, zz

                      // max_t -  максимальне значення другої функції, mm

  i:integer;   // лічильник

  ksi_f:real;  // бажані значення аргументів для першої функції

  ksi_t:real;  // бажані значення аргументів для другої функції

  w_f,w_t:real;

  Ro_t,Ro_f:real;  // вагові коефіцієнти критеріїв

  x1_max,x2_max,x3_max:real;

// точка x1_max,x2_max,x3_max <- ефективна альтернативу

  g:textfile; // текстовий файл

begin

  assignfile(g,'result.txt');// звязати файл result.txt зі змінною g

  append(g); // відкрити файл і додавати нову інформацію в кінець файла

  // шукаємо максимальне  значення  першої функції, zz

  p[1]:=zz(0,0,0);

  p[2]:=zz(0,0,a);

  p[3]:=zz(0,a,0);

  p[4]:=zz(a,0,0);

  p[5]:=zz(0,a,a);

  p[6]:=zz(a,0,a);

  p[7]:=zz(a,a,0);

  p[8]:=zz(a,a,a);

  max_f:=p[1];

  for i:=2 to 8 do

    if p[i]>max_f then

      max_f:=p[i];//  max_f - максимальне значення першої  функції, zz

  f1_max_gr:=max_f;

// f1_max_gr - максимальне значення першої функції

  // виводимо максимальне  значення першої функції в  файл

  // FloatToStrF - перетворює дійсне число в рядок символів

  // і задає формат  виведення

  // ffNumber означає, що формат буде числовий

  writeln(g,'');

  writeln(g, 'Максимальне значення першої функції =' + FloatToStrF (max_f, ffNumber,6,3));

  // і на екран в  компонент Label

  Form4.Label4.Caption := Form4.Label4.Caption + ' до ' + FloatToStrF (max_f, ffNumber,3,0);

  // виводимо на екран максимальне значення першої функції, zz

  // в компонент Memo1

  Form1.Memo1.Lines.Add('');

  Form1.Memo1.Lines.Add('Максимальне  значення функції');

  Form1.Memo1.Lines.Add('(x1-1)^2+(x2-3)^2+(x3-2)^2');

  Form1.Memo1.Lines.Add('y max = '+FloatToStr(max_f));

Информация о работе Метод бажаної точки при прийнятті рішень в умовах визначеності та його програмна реалізація