русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


Программная реализация класса подпрограмм для многомерного поиска экстремума унимодальных функций


Дата додавання: 2015-01-16; переглядів: 1115.


#include <conio.h>

#include <iostream.h>

#include "matrix.h"

 

typedef matrix<double> dmatrix;

typedef vector<double> dvector;

 

 

//Определим некоторые вспомогательные подпрограммы

//Возвращает код знака числа

inline long sign(double x)

{

return (x>0)?1:((x<0)?-1:0);

}

 

 

/*Простой параболоид для тестирования многомерного поиска*/

double gv(dvector x)

{

double sum=0;

int i;

int r=x.getm();

for(i=0;i<r;i++)

sum+=10.0*(x[i]-4)*(x[i]-4);

return sum;

}

 

 

/*Простейшая функция для численного дифференцирования, возвращающая значение вектора градиента в заданной точке при заданной матрице ограничений на составляющие аргумента*/

dvector GetGrad(dvector x, dmatrix rm)

{

int r=x.getm();

dvector grad(r);

double _yold=gv(x), //Текущее значение функции

_ynew, dx;

for(int i=0;i<r;i++)

{

/*Приращение аргумента возьмем в малую долю его интервала*/

dx=fabs(rm[i][1]-rm[i][0])*1e-10;

x[i]+=dx;

_ynew=(gv(x)); //Новое значение функции

/*Составляющая вектора градиента*/

grad[i]=(_ynew-_yold)/(dx);

x[i]-=dx;

}

return (~grad);//Возвращаем, нормировав по модулю

}

 

 

/*Функциональный класс объектов для многомерного поиска экстремума*/

class MultiExtremum

{

/*Размерность вектора аргументов исследуемой функции*/

long range;

/*матрица ограничений на значения составляющих вектора аргументов*/

dmatrix rm;

dvector veps;/*Вектор допустимых погрешностей по аргументу*/

/*Указатель на подпрограмму, возвращающую значение исследуемой функции при заданном векторе ее аргументов*/

double (*getv)(dvector x);

public:

/*Конструктор для многомерного поиска примет аргументы - мерность пространства, матрицу ограничений, вектор допустимых погрешностей, указатель на подпрограмму вычисления значений функции*/

MultiExtremum(long RANGE, dmatrix RM, dvector VEPS, double (*GETV)(dvector XM)): range(RANGE), rm(RM), veps(VEPS), getv(GETV) {}

/*Прототипы функций решения задачи условной оптимизации*/

void MultiDihot(dvector& x,int n); /*вспомогательный метод дихотомии*/

dvector Coord(); //метод покоординатного спуска

dvector Grad(); //метод градиента

dvector PSM(); //последовательный симплекс-метод

};

 

 

/*Реализация локального поиска экстремума по одной координате методом дихотомии*/

void MultiExtremum::MultiDihot(dvector& x,int n)

{

double xl,xr,yl,yr,dt=rm[n][1],ct=rm[n][0];

for(;(dt-ct)>veps[n];)

{

x[n]=xl=(ct+dt)/2-0.01*fabs(dt-ct);

yl=getv(x);

x[n]=xr=(ct+dt)/2+0.01*fabs(dt-ct);

yr=getv(x);

if(sign(yl-yr)>0)

{

ct=xl;

xl=xr;

xr=ct+dt-xl;

}

else

{

dt=xr;

xr=xl;

xl=ct+dt-xr;

}

}

x[n]=(ct+dt)/2;

}

 

 

//Методы многомерного поиска

//Координатный спуск

dvector MultiExtremum ::Coord()

{

dvector xtp(range),xtn(range), xeps(range);

int i,flag;

for(i=0;i<range;i++)

xtp[i]=xtn[i]=0.5*(rm[i][0]+rm[i][1]);

for(;;)

{

flag=0;

for(i=0;i<range;i++)

MultiDihot(xtn,i);

xeps=xtn-xtp;

for(i=0;i<range;i++)

if(fabs(xeps[i])>fabs(veps[i]))

flag++;

if(!flag)

break;

else

xtp=xtn;

}

return xtn;

}

 

 

//Метод градиента

dvector MultiExtremum::Grad()

{

double k=5.0,vn,vp;

dvector xtp(range), xtn(range), xeps(range), gr(range);

/*Вначале станем в средину допустимой области поиска*/

for(int i=0;i<range;i++)

xtp[i]=(0.5*(rm[i][0]+rm[i][1]));

for(;;)

{

//Вычислим градиент

gr=GetGrad(xtp,rm);

/*Корректируем аргумент в направлении, противоположном градиенту*/

xtn=xtp-k*gr;

vn=getv(xtn);

vp=getv(xtp);

//Если шаг слишком большой - уменьшаем его

for(;vn>vp;)

{

k/=1.2;

xtn=xtp-k*gr;

vn=getv(xtn);

vp=getv(xtp);

}

/*Если шаг по градиенту не изменяет существенно значение функции - прекращаем поиск*/

if(fabs(getv(xtn)-getv(xtp))<1e-8)

break;

xtp=xtn;

}

return xtn;

}

 

 

/*Последовательный симплекс-метод.

Этот метод достаточно громоздок в программном исполнении, особенно при использовании переменного размера поискового симплекса, защиты от вращения симплекса вокруг одной из вершин и других манипуляций, необходимых для его эффективной работы. Мы приводим упрощенный, а, следовательно, не очень точный в вычислениях пример программы, демонстрирующий принцип работы алгоритма */

dvector MultiExtremum::PSM()

{

double sum;

int i,j;

 

dvector yv(range+1);/*Вектор значений функции в вершинах симплекса*/

/*Формируем исходный регулярный симплекс в пространстве размерности range с центром в начале координат */

dmatrix simp(range+1,range);/*матрица для вершин симплекса*/

dvector stmp(range);

const double L=2.0L;

//заполняем матрицу симплекса

//Сначала нулевую строку

for(j=0;j<range;j++)

simp[0][j]=0.0;

//Затем остальные

double pk=(L/(range*sqrt(2)))*

(sqrt(range+1)+double(range)-1.0);

double qk=L*(pk-0.5*sqrt(2));

for(i=1;i<(range+1);i++)

for(j=0;j<range;j++)

simp[i][j]=(j==(i-1))?pk:qk;

int pmax=-1,//предыдущая плохая

cicl;

int vmin=0,vmax=0;

//Бесконечный цикл поиска

for(cicl=1;/*cicl<100000*/;cicl++)

{

//Вычисляем значения функции во всех вершинах

for(i=0;i<(range+1);i++)

yv[i]=getv(simp[i]);

/*Отыскиваем номера наихудшей и наилучшей вершин*/

for(i=1;i<(range+1);i++)

{

if(yv[i]>yv[vmax])

vmax=i;

if(yv[i]<yv[vmin])

vmin=i;

}

/*Если наилучшая нас устраивает - прекращаем поиск*/

if(fabs(yv[vmin])<0.05)

break;/*Грубая оценка попадания в зону экстремума. В этом месте вместо break можно было бы уменьшить размер симплекса и условие достижения экстремума*/

/*Если плохая не сменила номер - ищем ближайшую плохую*/

if((cicl>1)&&(vmax==pmax))

for(i=1;i<(range+1);i++)

{

if((yv[i]>yv[vmax])&&(i!=pmax))

vmax=i;

}

pmax=vmax;//Запоминаем как предыдущую плохую

//меняем плохую вершину на зеркально отраженную

for(j=0;j<range;j++)//j-номер координаты

{

/*Для каждой координаты вычислим ее среднее значение по всем вершинам*/

sum=0;

for(int k=0;k<(range+1);k++)

sum+=simp[k][j];//k- номер вершины

sum*=(2.0/(range+1));

/*Из среднего вычитаем плохое значение и результат сохраняем в промежуточном векторе*/

stmp[j]=sum-simp[vmax][j];

}

/*Новый вектор координат переносим на место наихудшей вершины*/

simp[vmax]=stmp;

}//бесконечный цикл

return simp[vmin];

}

 

 

//Программа тестирования методов поиска экстремума

main()

{

//Тестируем многомерные методы поиска экстремума

/*Формируем размерность, матрицу ограничений и вектор погрешностей*/

int r=5;

dmatrix m(r,2);dvector e(R);

for(int i=0;i<r;i++)

{

m[i][0]=-8.0;

m[i][1]=15.0;

e[i]=0.0001;

}

MultiExtremum extM(r,m,e,gv);/*Конструируем объект*/

/*Вызываем для этого объекта методы поиска минимума*/

dvector resCoord=extM.Coord(); /*Метод покоординатного спуска*/

cout<<endl<<gv(resCoord);

cout<<endl<<resCoord;

dvector resGrad=extM.Grad(); /*Метод градиента (наискорейшего спуска)*/

cout<<endl<<gv(resGrad);

cout<<endl<<resGrad;

 

dvector resPSM=extM.PSM(); /*Последовательный симплекс-метод*/

cout<<endl<<gv(resPSM);

cout<<endl<<resPSM;

getch();

}

Приложение. Как переносить данные в Ехсеl и отображать графики зависимостей

Пусть Вам необходимо отобразить в виде графика данные, которые находятся в файле. Вначале Вам необходимо скопировать эти данные в буфер обмена, используя, к примеру, Far. Для этого выберите режим редактирования файла, нажав клавишу F4 на имени файла, выделите необходимые Вам данные клавишами управления курсором (с прижатой Shift), нажатием Ctrl+Ins скопируйте помеченный блок в буфер обмена. Далее определите, какой вид у этих данных:

1. одна строка произвольной длины

2. один столбец произвольной длины

3. два столбца произвольной длины, первый из которых содержит независимую переменную, а второй – зависимую.

4. две строки произвольной длины, первая из которых содержит независимую переменную, а вторая – зависимую.

5. две строки длины до 64 чисел каждая, первая из которых содержит независимую переменную, а вторая – зависимую.

Случаи большего числа строк (столбцов) сводятся к этим пяти.

Запустите редактор Word и комбинацией Shift+Ins вставьте содержимое буфера обмена. Произведите замену точек на запятые: нажатием Ctrl+H вызовите диалоговое окно Найти и заменить, в поле Найти ввести точку, в поле Заменить на – запятую и нажать на клавишу Заменить все.

Рассмотрим возможные случаи:

1. Этот случай сводится ко второму заменой пробелов на символы абзаца:

3, 5. Комбинацией Ctrl+А выделите весь текст в окне. Затем в пункте меню Таблица выберите пункт Преобразовать в таблицу.

В появившемся диалоговом окне в качестве символа разделителя введите пробел (поле другой) и нажмите на клавишу ОК.

4. А не транспонировать ли Вам данные перед выводом в файл? Сводится к случаю 3.

Следующий этап – выделение всего содержимого окна (Ctrl+А) и копирование выделенного фрагмента в буфер обмена (Ctrl+Ins), затем – запуск табличного процессора Excel и вставка содержимого буфера обмена нажатием Shift+Ins. Не снимая пометки, выберите пункт меню Вставка, а в нём – подпункт Диаграмма:

1, 2. В списке Тип выберите пункт График, а в разделе Вид – первый из предложенных видов графиков и нажмите на кнопку Готово.

3, 4, 5. В списке Тип выберите пункт Точечная, а в разделе Вид – третий из предлагаемых видов графиков и нажмите на кнопку Готово.

 

Литература

1. Алгоритмы и программы восстановления зависимостей. – М.: Наука, 1984.

2. Анго А. Математика для электро- и радиоинженеров. – М.: Наука, 1964.

3. Бабак В.П., Хандецький В.С., Шрюфер Е. Обробка сигналів. – К.: Либідь, 1996.

4. Боглаев Ю.П. Вычислительная математика и программирование: Учебное пособие для студентов втузов. – М.: Высшая школа, 1990.

5. Вайнер Р., Пинсон Л. С++ изнутри. – Киев: ДиаСофт, 1993.

6. Вентцель Д.А., Вентцель Е.С. Элементы теории приближенных вычислений. – М.: Издательство ВВИА им. Н.Е. Жуковского, 1949.

7. Вентцель Е.С. Исследование операций. – М.: Радио и связь, 1970.

8. Вентцель Е.С. Теория вероятностей. – М.: Наука, 1969.

9. Гавурин М.К. Лекции по методам вычислений. – М.: Наука, 1971.

10. Гантмахер Ф.Р. Теория матриц. – М.: Государственное издательство технико-теоретической литературы, 1953.

11. Гринчишин Я.Т., Ефимов В.И., Ломакович А.Н. Алгоритмы и программы на Бейсике. – М.: Просвещение, 1988.

12. Гринчишин Я.Т. TURBO PASCAL: Чисельні методи в фізиці та математиці: Навч. посібник – Тернопіль, 1994.

13. Гулд Х., Тобочник Я. Компьютерное моделирование в физике: В 2-х частях. Часть 2: Пер. с англ. – М.: Мир, 1990.

14. Гутер Р.С., Овчинский Б.В. Элементы численного анализа и математической обработки результатов опыта. – М.: Наука, 1970.

15. Дамбраускас А.П. Симплексный поиск. – М.: Энергия, 1979.

16. Демидович Б.П., Марон И.А. Основы вычислительной математики. – М.: Физматгиз, 1963.

17. Демидович Б.П., Марон И.А., Шувалова Э.З. Численные методы анализа. – М.: Наука, 1967.

18. Джордж А., Лю Дж. Численное решение больших разряжённых систем уравнений. – М.: Мир, 1984.

19. Дьяконов В.П. Справочник по алгоритмам и программам на языке Бейсик для персональных ЭВМ. – М.: Наука, 1987.

20. Иванов В. В. Методы вычислений на ЭВМ: Справочное пособие. – К.: Наукова думка, 1986.

21. Кантор И.Л., Солодовников А.С. Гиперкомплексные числа. – М. Наука, 1973.

22. Лукас П. С++ под рукой. – Киев: ДиаСофт, 1993.

23. Лукомский Я.И. Теория корреляции и её применение к анализу производства. – М.: Госстатиздат ЦСУ СССР, 1961.

24. Мак-Кракен Д., Дорн У. Численные методы и программирование на Фортране. – М.: Мир, 1977.

25. Маликов В.Т., Кветный Р.Н. Вычислительные методы и применение ЭВМ: Учебное пособие. – К.: Выща школа, 1989.

26. Мудров А.Е. Численные методы для ПЭВМ на языках Бейсик, Фортран и Паскаль. – Томск: Раско, 1991.

27. Ортега Дж., Пул У. Введение в численные методы решения дифференциальных уравнений. – М.: Наука, 1986.

28. Плис А.И., Сливина Н.А. Лабораторный практикум по высшей математике. – М.: Высшая школа, 1983.

29. Полищук А.П. Персональный компьютер и его программирование (С, С++, Паскаль). Учебно-справочное пособие. – Кривой Рог: КГПИ, 1997.

30. Попов В.С., Мансуров Н.Н., Николаев С.А. Электротехника. – М.: Издательство Министерства коммунального хозяйства РСФСР, 1958.

31. Смирнов В.И. Курс высшей математики. Т. 1-5. – М.: Наука, 1974.

32. Статистическая обработка результатов экспериментов на микро-ЭВМ и программируемых калькуляторах. – Л.: Энергоатомиздат, 1991.

33. Страуструп Б. Язык программирования С++: В 2-х частях. – К.: Диасофт, 1993.

34. Тихонов А.Н., Арсенин В.Я. Методы решения некорректных задач. Учебное пособие для вузов. – М.: Наука, 1986.

35. Тихонов А.Н., Самарский А.А. Уравнения математической физики. – М.-Л.: Государственное издательство технико-теоретической литературы, 1951.

36. Уилкинсон Дж., Райнш К. Справочник алгоритмов на языке Алгол. Линейная алебра. – М.: Машиностроение, 1976.

37. Уткіна С.В., Наришкіна Л.С. Алгебра і числові системи: Навч. посібник. – К.: Вища школа, 1995.

38. Фаддеева В.Н. Вычислительные методы линейной алгебры. – М.: Гостехиздат, 1950.

39. Фейсон Т. Объектно-ориентированное программирование на Borland C++ 4.5. – Киев: Диалектика, 1996.

40. Форсайт Д., Малькольм М., Моллер К. Машинные методы математических вычислений. – М.: Мир, 1980.

41. Форсайт Д., Моллер К. Численное решение систем линейных алгебраических уравнений. – М.: Мир, 1968.

42. Хемминг Р.В. Численные методы. – М.: Наука, 1968.

43. Шуп Т.Е. Прикладные численные методы в физике и технике. – М.: Высшая школа, 1990.

44. Шуп Т.Е. Решение инженерных задач на ЭВМ. Практическое руководство. – М.: Мир, 1982.

 

Учебное пособие

 

Александр Павлович Полищук

Сергей Алексеевич Семериков

Методы вычислений в классах языка С++

 

Подп. к печати 28.12.98 Бумага офсетная №1 Усл. кр.-от. 18,38 Тираж 500 Формат 80х84 1/16. Усл. печ. л. 18,38 Уч.-изд. л. 22,29 Зак. №12-2483

 

КГПИ, 324086, Кривой Рог-86, пр. Гагарина, 54

 

Криворожская городская типография

324050, Кривой Рог-50, пр. Металлургов, 28.

 


<== попередня лекція | наступна лекція ==>
Схемы включения счётчиков для измерения активной и реактивной энергий в трёхфазных цепях | Пирамиды.


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн