русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

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

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Симплекс-метод решения ОЗЛП


Дата добавления: 2015-01-16; просмотров: 729; Нарушение авторских прав


//файл включения для векторных и матричных объектов

#include "matrix.h"

 

/*определяем типы "действительная матрица" и "действительный вектор"*/

typedef matrix<double> dmatrix;

typedef vector<double> dvector;

 

 

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

void rotate(dmatrix &x, long index)

{

/*нам необходимо, чтобы в процедуре прямого хода на главной диагонали не было нулевых составляющих; если же таковые есть, находим "ниже" по матрице вектор-уравнение с ненулевой соответствующей компонентой и ставим его на место текущего*/

for(long i=index;i<x.getm();i++)

if(x[i][index])

{

dvector temp=x[i];

x[i]=x[index];

x[index]=temp;

}

}

 

 

/*функция, выполняющая прямой ход Гаусса с попутным подсчётом количества линейно-независимых векторов данной матрицы (ранга матрицы)*/

long rank(dmatrix &x)

{

long i;

//перебираем вектора матрицы

for(i=0;i<x.getm();i++)

{

if(!x[i][i])/*если диагональный элемент равен нулю*/

rotate(x,i);//меняем строки матрицы

/*делаем нулевым столбец под текущим диагональным элементом*/

for(long j=i+1;j<x.getm();j++)

if(x[i][i])

x[j]+=(-x[j][i]/x[i][i])*x[i];



}

//создаём пустой вектор заданной размерности

dvector empty=x.getn();

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

for(i=0;i<x.getm();i++)

if(x[i]==empty)/*сравниваем текущий вектор с нулевым*/

break;

return i;//возвращаем ранг

}

 

 

/*процедура обратного хода Гаусса без нормирования элементов главной диагонали*/

void diagonalize(dmatrix &x)

{

for(long i=x.getm()-1;i>=0;i--)

for(long j=i-1;j>=0;j--)

if(x[i][i])

x[j]+=(-x[j][i]/x[i][i])*x[i];



}

 

/*Процедура обмена двух столбцов матрицы - перестановки местами переменных с попутным переразрешением полученной системы. Параметрами её являются матрица ОЗЛП, вектор линейной формы, номера обмениваемых переменных и вектор, в котором учитывается производимая перестановка*/

void swap(dmatrix &x, dvector &l, long sw1, long sw2, dvector &swapvalues)

{

//временный вектор для обмена значениями

dvector save(x.getm()+2);

//сохраняем первый столбец

for(long i=0;i<x.getm();i++)

save[i]=x[i][sw1];

/*сохраняем элемент линейной формы, соответствующий первому столбцу*/

save[x.getm()]=l[sw1];

//сохраняем номер переставляемого столбца и т.д.

save[x.getm()+1]=swapvalues[sw1];

for(long i=0;i<x.getm();i++)

x[i][sw1]=x[i][sw2];

l[sw1]=l[sw2];

swapvalues[sw1]=swapvalues[sw2];

for(long i=0;i<x.getm();i++)

x[i][sw2]=save[i];

l[sw2]=save[x.getm()];

swapvalues[sw2]=save[x.getm()+1];

rank(x);//осуществляем прямой и

diagonalize(x);//обратный ход Гаусса

for(long i=0;i<x.getm();i++)

x[i]*=(1/x[i][i]);

/*подставляем значений переменных в линейную форму, определяя её коэффициенты в данной перестановке*/

for(long i=0;i<x.getm();i++)

l+=-l[i]*x[i];

}

 

 

/*процедура определения опорного решения принимает три параметра - матрицу ОЗЛП, вектор линейной формы и вектор перестановок*/

void getoporsol(dmatrix &x, dvector &l, dvector &swapvalues)

{

long i,j,k,s;

double otn;

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

for(i=0;i<x.getm();i++)

if(-x[i][x.getn()-1]<0)

break;

if(i==x.getm())

return;/*опорное решение найдено - все свободные члены неотрицательны */

/*в строке, где мы нашли отрицательный свободный член, среди коэффициентов пытаемся найти положительный*/

for(j=x.getm();j<x.getn()-1;j++)

if(x[i][j]<0)

break;

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

if(j==x.getn()-1)

throw xmsg("Допустимых решений нет");

/*среди строк, в которых в определённом (разрешающем) столбце отрицательному свободному члену соответствует положительный коэффициент, выбираем ту, в которой отношение -x[k][n-1]/x[k][j] принимает наименьшее значение*/

for(k=0;k<x.getm();k++)

if(sign(x[k][j])==sign(-x[k][x.getn()-1])

&&x[k][j])

{

s=k;

otn=-x[k][x.getn()-1]/x[k][j];

break;

}

for(;k<x.getm();k++)

if(sign(x[k][j])==sign(-x[k][x.getn()-1])

&&x[k][j])

if(otn>-x[k][x.getn()-1]/x[k][j])

s=k,

otn=-x[k][x.getn()-1]/x[k][j];

/*j - разрешающий столбец, s - разрешающая строка. Меняем в нашей матрице столбцы с соответствующими индексами */

swap(x, l, s, j, swapvalues);

//снова пытаемся определить опорное решение

getoporsol(x,l,swapvalues);

}

 

 

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

dvector getoptsol(dmatrix &x, dvector &l, dvector &swapvalues)

{

long i,j,k,s;

double otn;

//ищем в линейной форме отрицательный коэффициент

for(i=0;i<l.getm()-1;i++)

if(l[i]<0)

break;

/*если таковых нет, полученное решение является оптимальным*/

if(i==l.getm()-1)

{

//формируем вектор результата

dvector res=l.getm()-1;

/*используя массив перестановок, записываем значения компонент вектора решения на их прежние позиции*/

for(long i=0;i<x.getm();i++)

res[swapvalues[i]]=-x[i][x.getn()-1];

return res;//возвращаем оптимальное решение

}

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

for(j=0;j<x.getm();j++)

if(-x[j][i]<0)

break;

/*если такого уравнения нет, то данную переменную можно увеличивать безгранично, а, значит, оптимального решения ОЗЛП не существует*/

if(j==x.getm())

throw xmsg("Линейная форма не ограничена снизу");

/*если же такие уравнения нашлись, определяем среди них ту переменную, которая при увеличении данной наиболее быстро обратится в нуль*/

for(k=0;k<x.getm();k++)

if(-x[k][i]<0)//опасное уравнение

{

s=k;

otn=-x[k][x.getn()-1]/x[k][i];

break;

}

for(;k<x.getm();k++)

if(-x[k][i]<0)//опасное уравнение

if(otn>-x[k][x.getn()-1]/x[k][i])

s=k,//наиболее угрожаемая переменная

otn=-x[k][x.getn()-1]/x[k][i];

/*меняем местами переменную при отрицательном коэффициенте линейной формы с наиболее угрожаемой */

swap(x,l,s,i,swapvalues);

/*после замены вновь пытаемся найти оптимальное решение*/

return getoptsol(x,l,swapvalues);

}

 

 

/*функция для решения ОЗЛП, заданной основной матрицей (левой частью), столбцом свободных членов правой части и линейной формой без св. члена */

dvector simplex(dmatrix a, dvector b, dvector c)

{

if(a.getm()!=b.getm())

throw xmsg("Количество уравнений должно совпадать");

if(a.getn()!=c.getm())

throw xmsg("Количество неизвестных должно совпадать");

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

dmatrix ab(a.getm(),a.getn()+1);

dvector swapvalues=c.getm();/*вектор учёта обмена переменных*/

//вначале порядок переменных не нарушен

for(long i=0;i<swapvalues.getm();i++)

swapvalues[i]=i;

//формируем матрицу СЛАУ из левой и правой частей

for(long i=0,j;i<a.getm();i++)

{

for(j=0;j<a.getn();j++)

ab[i][j]=a[i][j];

ab[i][j]=-b[i];

}

long r;

//определяем ранги основной и расширенной матрицы

if((r=rank(a))!=rank(ab))

throw xmsg("Система несовместна - ранги основной и расширенной матриц не совпадают");

/*в случае совместной системы ранги этих матриц совпадают, поэтому мы можем отбросить уравнения-следствия*/

dmatrix x(r,ab.getn());

/*в новую матрицу ОЗЛП переписываем только линейно-независимые уравнения*/

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

x[i]=ab[i];

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

dvector l(c.getm()+1);

for(long i=0;i<c.getm();i++)

l[i]=c[i];

//выполняем обратный ход Гаусса

diagonalize(x);

for(long i=0;i<x.getm();i++)

x[i]*=(1/x[i][i]);

/*подстановка значений базисных переменных в линейную форму*/

for(long i=0;i<x.getm();i++)

l+=-l[i]*x[i];

//поиск опорного решения

getoporsol(x,l,swapvalues);

//возвращаем оптимальное решение

return getoptsol(x,l,swapvalues);

}

 

//тестовая программа работает с задачей вида:

//-5*x1-x2+2*x3<=2

//-x1+x3+x4<=5

//-3*x1+5*x4<=7 L=5*x1-2*x3

//x1>=0

//x2>=0

//x3>=0

//x4>=0

//==>

//5*x1+x2-2*x3>=-2

//x1-x3-x4>=-5

//3*x1-5*x4>=-7 L=5*x1-2*x3

//x1>=0

//x2>=0

//x3>=0

//x4>=0

//==>

//5*x1+x2-2*x3+2>=0

//x1-x3-x4+5>=0

//3*x1-5*x4+7>=0 L=5*x1-2*x3

//x1>=0

//x2>=0

//x3>=0

//x4>=0

//==>

//y1=5*x1+x2-2*x3+2

//y2=x1-x3-x4+5

//y3=3*x1-5*x4+7 L=5*x1-2*x3

//y1>=0

//y2>=0

//y3>=0

//x1>=0

//x2>=0

//x3>=0

//x4>=0

//==>

//-y1+5*x1+x2-2*x3+2=0

//-y2+x1-x3-x4+5=0

//-y3+3*x1-5*x4+7=0 L=5*x1-2*x3

//y1>=0

//y2>=0

//y3>=0

//x1>=0

//x2>=0

//x3>=0

//x4>=0

//

void main()

{

double mtr[]=

{

-1,0,0, 5,1,-2,0,

0,-1,0, 1,0,-1,-1,

0,0,-1, 3,0,0,-5

};

double vec1[]={-2, -5, -7};

double vec2[]={0,0,0,5,0,-2,0};

dmatrix a(3,7,mtr), b(3,vec1), c(7,vec2);

dvector res=simplex(a,b,c);

cout<<res<<endl;

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

double L=c*res;

cout<<"L="<<L<<endl;

}



<== предыдущая лекция | следующая лекция ==>
Транспортная задача с временным критерием | Программная реализация метода решения транспортной задачи


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.075 сек.