单纯形方法(SimplexMethod)Matlab仿真详解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单纯形方法(SimplexMethod)Matlab仿真详解
最近在上最优理论这门课,刚开始是线性规划部分,主要的方法就是单纯形方法,学完之后做了一下大M 算法和分段法的仿真,拿出来与大家分享一下。
单纯形方法是求解线性规划问题的一种基本方法。
单纯形方法基本步骤如下:1)将所给的线性规划问题化为标准形式:min ()..0
T
f x c x s t Ax b
x ==≥
s.t.是英文subject to 的简写,意思是受约束,也就是说第一个方程(目标函数)受到后面两个方程的约束。
对于求最大值问题可以将目标函数加负号转换为最小值问题。
max ()min ()T T f x c x f x c x =?=-
其他的问题就是将实际问题中的不等式约束改为等式约束,主要方法是引进松弛变量和剩余变量,以及将自有变量转换为非负变量。
①对于不等式
1
b ,1,2,n
ij j
i j a x
i m =≤=∑ ,
引入松弛变量将其变为等式形式如下:
1
b ,1,2,0,
1,2,n
ij j
n i i j n i a x
x i m
x i m
+=++==≥=∑
②对于不等式
1
b ,1,2,n
ij j
i j a x
i m =≥=∑ ,
引入剩余变量将其变为等式形式如下:
1
b ,1,2,0,
1,2,n
ij j
n i i j n i a x
x i m
x i m
+=+-==≥=∑
③若变量为自有变量(可取正、负或零,符号无限制),则引入两个非负变量将其表示如下:
j j j j j x x x x x '''?=-?
'≥??''
≥? 2)找出一个初始可行基B ,作出单纯形表,这里假设输入的线性规划问题已经有初始可行基。
0T c S A b ??=
3)测试所有的检验数(目标函数的系数C ),记录检验数中的正数,若全部小于等于0,则
已经找到最优解,计算终止。
否则转至4)。
4)测试所有为正的检验数,若在单纯性表中,其所在的列中其他元素全部小于等于0,则此问题无最优解,计算终止,否则转至5)。
5)找出检验数中的最大值,此最大值元素所在列为A(i,:),令约束条
件中约束向量b 与A(i,:)的比值为向量r ,向量r 中为正的最小值为h ,计算过程如下图。
S 单纯形表 X1 X2 X3 X4 X5 f (检验数) 5 10(最大值) 0
0 0 0 X3 1/14 1/7 1 0 0 1 X4 1/7 1/12 0 1 0 1 X5
1
1
1
8
表格中黄色部分组成的向量点除(对应元素相除)红色部分,得到向量(7,12,8),那么7就是我们要找的那个元素,此时记录元素大小h 和坐标(i,j),注意是在S 表中行号和列号,此处是2和2(如果有多个相等的最小值则任取一个即可)。
这个元素1/7就是所谓的转轴元(或称基本元),找到他之后要围绕他进行一系列的行变换,称之为换基。
步骤如下:
①使转轴元变为1,方法很简单,就是让本行所有元素同时除以转轴元1/7。
②把转轴元所在列的其他元素都变为0,做法是通过一个循环,遍历每一个行(自身所在行除外),每行中与转轴元同列的元素为a ,令每行减去转轴元所在行的第a 倍即可。
转至3)。
理论部分到此为止,大家有不懂的再去百度或者查书吧。
matlab 仿真程序编写: 此程序假设输入的问题已经有了基本可行解!%Simplex Method
function [x,y]=Simplex(f,A,b)
%输入f 是检验数的数组,1*n 维 %输入A 是约束矩阵, m*n 维 %输入b 是约束向量, 1*m 维 %输出x 是解向量 %输出y 是最优解%判断输入维数是否相符
%做初始单纯形表
format rat %将结果以分数表示
S=[f 0;A b'];
[n,m]=size(S);
%判断检验数r<=0
r=find(f>0);
len=length(r);
%有大于0的检验数则进入循环
while(len)
%检查非负检验数所对列向量元素是否都小于等于0 for k=1:length(r)
d=find(S(:,r(k))>0);
if(length(d)+1==2)
error('无最优解')
%break;
end
end
%找到检验数中最大值
[Rk,j]=max(S(1,1:m-1));
%b与最大值所在列的比值
rb=S(2:n,m)./S(2:n,j);
%把比值中的负数都变无穷,便于寻找最小正值
for p=1:length(rb)
if(rb(p)<0)
rb(p)=Inf;
end
end
[h,i]=min(rb);%列向量比值最小值
% i+1为转轴元行号(在S中),j为转轴元列号
i=i+1;
%进行换基,转轴元置1
S(i,:)=S(i,:)./S(i,j);
%转轴元所在列其他元素都置0
for k=1:n
if(k~=i)
S(k,:)=S(k,:)-S(i,:)*S(k,j);
end
end
%判断检验数r<=0
r=find(S(1,1:m-1)>0);
len=length(r);
end
%检验数全部非正,找到最优解
%初始化解向量,非基变量置0
x=zeros(1,m-1);
for i=1:m-1
%找到基变量,每列中只有一个1,其他全为0,则1为基变量j=find(S(:,i)==1);%每列中1的个数
k=find(S(:,i)==0);%每列中0的个数
if((length(j)+1==2)&&(length(k)+1==n))
%i为基变量列号,j是行号
x(i)=S(j,m);%基变量的值为S表基变量所在行最右端的值end end
y=S(1,m);%最优解为检验数所在行最右端的数
S
end。