Автор: Пользователь скрыл имя, 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
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:
// оголошення глобальних змінних
// змінні використаємо в моднлі 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.
// StrToFloat перетворює рядок символів в дійсне число
x2[i]:=StrToFloat(x2_Edit.
x3[i]:=StrToFloat(x3_Edit.
// виведення в файл початкової точки і значення функції в цій точці
// 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('В програмі маленька вимірність масивів. Аварійний вихід! Візьміть іншу початкову точку!');
closefile(g); // перез виходом закриваємо файл
exit;// вихід з процедури GradientMethod
end;
// обчислення наступної точки
x1[i]:= x1[i-1]-RO*dz_dx1(x1[i-1],x2[
x2[i]:= x2[i-1]-RO*dz_dx2(x1[i-1],x2[
x3[i]:= x3[i-1]-RO*dz_dx3(x1[i-1],x2[
// 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)+'>='+
writeln(g,'Ітерація з ro = '+FloatToStr(Ro)+' завершилась');
end
else
writeln(g,FloatToStr(y2)+'<'+
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[
// 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)+'
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)+'
else
writeln(g, '|' + FloatToStr(q2) + '+' + FloatTostr(q1*(-1)) + '| = '+FloatToStr(abs(q2-q1)));
// якщо різниця (за модулем) значень функції на цій ітерації і на попередній менше за точність 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
дозволяє вивести текст в
// 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,
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:
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)^
Form1.Memo1.Lines.Add('y max = '+FloatToStr(max_f));