标题:自编MATLAB版单纯性算法 可以列出单纯形表以及其他相关数据
只看楼主
月下寒心
Rank: 1
等 级:新手上路
帖 子:98
专家分:0
注 册:2009-3-21
结帖率:97.5%
 问题点数:0 回复次数:1 
自编MATLAB版单纯性算法 可以列出单纯形表以及其他相关数据
function [dcxb,x,fval,exitflag,flag]=simplex(f,A,b,Aeq,beq)
%本程序相关说明:
%(1)本函数基本使用方法与MATLAB自身函数使用方法类似
%(2)dcxb表示整个过程的单纯形表,flag=1表示没有出现退化情况,flag=-1表示出现退化情况,改为依照勃兰德法则确定进基变量和出基变量
%(3)程序运行结果dcxb中inf无意义,表的第一行两inf中间的数字表示变量的下标,本程序默认变量下标从1开始
%(4)dcxb其余各行如果仅仅行首和行尾出现inf,则两inf中间内容为检验数
%(5)dcxb第一列列相邻两inf间的内容为基变量的下标
%(6)exitflag为负表示无解,此时x,fval并不是相应的基可行解和最有值,仅仅代表程序中止时的基解和该基解所对应的函数值
%(7)函数名暂时命名为simplex,simplex是谷歌翻译给出的单纯形法的英文翻译,不知是否为专业术语
%(8)flag=-1时dcxb中会出现一行全为inf,无实际意义,仅表示该行一下依照勃兰德法则确定进基变量和出基变量(参见用法示例(2))
%(9)其他参数与linprog中相应参数意义相似
%(10)exitflag=1表示有唯一最优解,exitflag=2表示有无穷解,exitflag=-1表示目标函数无下界,exitflag=-2表示可行域为空
%(11)flag=2表示用到了两阶段法,此时程序运行结果将出现“第一阶段单纯形表为”“第二阶段单纯形表为”字样,并显示两个阶段各自的单纯形表,详见用法示例(3)
%用法示例(1):题目为束金龙编的《线性规划理论与模型应用》P44第23题(1)小题
%在命令窗口依次输入以下语句:
%f=[1 -2 1 -3]';
%A=[1 1 3 1;0 -2 1 1;0 -1 6 -1];
%b=[6 3 4]';
%[dcxb,x,fval,exitflag,flag]=simplex(f,A,b)
%用法示例(2):题目为束金龙编的《线性规划理论与模型应用》P23例1.8
%命令窗口输入的命令为:
%f=[-0.75 20 -0.5 6 0 0 0]';
%Aeq=[0.25 -8 -1 9 1 0 0;0.5 -12 -0.5 3 0 1 0;0 0 1 0 0 0 1];
%A=[];
%b=[];
%beq=[0 0 1]';
%[dcxb,x,fval,exitflag,flag]=simplex(f,A,b,Aeq,beq)
%用法示例(3):题目为课本《线性规划理论与模型应用》P29例1.9
%命令窗口输入的命令为:
%f=[1 -2]';
%A=[-1 -1;1 -1;0 1];
%b=[-2 -1 3]';
%[dcxb,x,fval,exitflag,flag]=simplex(f,A,b)
flag=1;
if nargin < 5, beq = [];
    if nargin < 4, Aeq = [];
    end
end
[A_m,A_n]=size(A);
[Aeq_m,Aeq_n]=size(Aeq);
bb=[b;beq];
m=A_m+Aeq_m;
n = max([length(f),A_n,Aeq_n]); % In case A is empty
if isempty(f), f=zeros(n,1); end%4
if isempty(A), A=zeros(0,n); end
if isempty(b), b=zeros(0,1); end
if isempty(Aeq), Aeq=zeros(0,n); end
if isempty(beq), beq=zeros(0,1); end
if(all(b>=0)==0)
    flag=3;
    b_len=length(b);
    k=1;
    for r=1:inf
        if(k<=b_len)
            if b(k)<0
                Aeq=[Aeq,zeros(Aeq_m,1);A(k,:),1];%1%5
                beq=[beq;b(k)];%2
                A=[A(1:k-1,:);A(k+1:A_m,:)];%3
                A=[A,zeros(A_m-1,1)];
                b=[b(1:k-1);b(k+1:A_m)];
                k=k-1;
                b_len=b_len-1;
                A_m=A_m-1;
                Aeq_m=Aeq_m+1;
                Aeq_n=Aeq_n+1;
                f=[f;0];
            else
                Aeq=[Aeq,zeros(Aeq_m,1);A(k,:),1];
                beq=[beq;b(k)];
                A=[A(1:k-1,:);A(k+1:A_m,:)];
                A=[A,zeros(A_m-1,1)];
                b=[b(1:k-1);b(k+1:A_m)];
                k=k-1;
                b_len=b_len-1;
                A_m=A_m-1;
                Aeq_m=Aeq_m+1;
                Aeq_n=Aeq_n+1;
                f=[f;0];
            end
            k=k+1;
        else break;
        end
    end
    A=[];
    b=[];
end
for k=1:Aeq_m
    if beq(k)<0
        Aeq(k,:)=-Aeq(k,:);
        beq(k)=-beq(k);
    end
end
[A_m,A_n]=size(A);
[Aeq_m,Aeq_n]=size(Aeq);
bb=[b;beq];
m=A_m+Aeq_m;
n = max([length(f),A_n,Aeq_n]);
if isempty(f), f=zeros(n,1); end
if isempty(A), A=zeros(0,n); end
if isempty(b), b=zeros(0,1); end
if isempty(Aeq), Aeq=zeros(0,n); end
if isempty(beq), beq=zeros(0,1); end
AA=[A;Aeq];
pq=0;
PQ=zeros(n+m,1);
QP=zeros(n,1);
for k=1:n
    D=AA(:,k);
    [maxk,maxK]=max(D);
    [mink,minK]=min(D);
    if(maxk~=0)%这种情况是不正确的
        if(mink==0)
            D(maxK)=0;
            maxk=max(D);
            if(maxk==0)
                pq=pq+1;
                PQ(maxK)=k;
                QP(pq)=maxK;
                for s=1:pq-1
                    if(A(:,s)==A(:,pq))
                        pq=pq-1;
                    end
                end
            end
        end
    end
end
PQ=PQ(1:m);
QP=QP(1:pq);
W=eye(m);
for k=1:pq
    W(:,QP(k))=zeros(m,1);
end
WW=zeros(m,0);
kk=1;
for k=1:m
    if(W(:,k)==zeros(m,1))
    else
        for r=1:m
            if PQ(r)==0
                PQ(r)=n+kk;
                break;
            end
        end
        WW=[WW,W(:,k)];
        kk=kk+1;
    end
end
AA=[AA,WW];
Ab=[AA,bb];
FF=zeros(1,m+n-pq);
for r=n+1:m+n-pq
    for s=1:m
        if AA(s,r)~=0
            FF=FF+AA(s,:)/AA(s,r);
        end
    end
end
TT=f;
FF=[FF(1:n),zeros(1,m-pq)];
if flag==3
    ff=-FF';
    T=[f;zeros(m-pq,1)];
else
    ff=[f;zeros(m-pq,1)];
end
F=ff;
B=PQ;
BB=B;
dcxb=[inf,1:m+n-pq,inf;B,Ab;inf,ff',inf];
for loop=1:inf
    [minff,i]=min(ff);
    if(flag~=1)
        for k=1:i
            if(ff(k)<0)
                i=k;
                break;
            end
        end
    end
    C=inf*ones(m,1);
    if(minff>=0)
        exitflag=1;
        break;
    else
        if(AA(:,i)+abs(AA(:,i))==0)%注意等号
            exitflag=-1;%exitflag为负表示无解
            dcxb=[dcxb;inf(1,m+n-pq)];
            break;
        else
            for h=1:m
                if(AA(h,i)>0)
                    C(h)=bb(h)/AA(h,i);
                end
            end
            [minC,j]=min(C);
            B(j)=i;
            Ab(j,:)=Ab(j,:)/Ab(j,i);
            ff=ff-AA(j,:)'*ff(i)/AA(j,i);
            if flag>1
                T=T-AA(j,:)'*T(i)/AA(j,i);
            end
            for k=1:m
                if(k~=j)%不等号<>不对吗?
                    Ab(k,:)=Ab(k,:)-Ab(j,:)*Ab(k,i)/Ab(j,i);
                end
            end
            bb=Ab(:,n+m-pq+1);
            AA=Ab(:,1:n+m-pq);
            dcxb=[dcxb;B,Ab;inf,ff',inf];
            BB=[BB,B];
        end
    end
    if flag==1
        for r=1:(loop)
            if(BB(:,r)==BB(:,loop+1))
                flag=-1;
                dcxb=[dcxb;inf*ones(1,m+n+2-pq)];
                break;
            end
        end
    end
end
if flag==3
    x=zeros(length(ff),1);
    for k=1:m
        x(B(k))=bb(k);
    end
    if x'*ff~=0
        exitflag=-2
    end
    fprintf('本题采用两阶段法求解\n第一阶段单纯形表为:\n')
    dcxb
    flag=2;
    BB=[];
    ff=T(1:n);
end
if flag==2
    F=ff;
    AA=AA(:,1:n);
    Ab=[Ab(:,1:n),bb];
    BB=B;%%%%%
    dcxb=[inf,1:n,inf;B,Ab;inf,ff',inf];
    for loop=1:inf
        [minff,i]=min(ff);
        if(flag==-1)
            for k=1:i
                if(ff(k)<0)
                    i=k;
                    break;
                end
            end
        end
        C=inf*ones(m,1);
        if(minff>=0)
            exitflag=1;
            break;
        else
            if(AA(:,i)+abs(AA(:,i))==0)%注意等号
                exitflag=-1;%exitflag为负表示无解
                dcxb=[dcxb;inf(1,m+n-pq)];
                break;
            else
                for h=1:m
                    if(AA(h,i)>0)
                        C(h)=bb(h)/AA(h,i);
                    end
                end
                [minC,j]=min(C);
                B(j)=i;
                Ab(j,:)=Ab(j,:)/Ab(j,i);
                ff=ff-AA(j,:)'*ff(i)/AA(j,i);
                for k=1:m
                    if(k~=j)%不等号<>不对吗?
                        Ab(k,:)=Ab(k,:)-Ab(j,:)*Ab(k,i)/Ab(j,i);
                    end
                end
                bb=Ab(:,n+1);
                AA=Ab(:,1:n);
                dcxb=[dcxb;B,Ab;inf,ff',inf];
                BB=[BB,B];
            end
        end
        if flag==1
            for r=1:(loop)
                if(BB(:,r)==BB(:,loop+1))
                    flag=-1;
                    dcxb=[dcxb;inf*ones(1,n+2)];
                    break;
                end
            end
        end
    end
end
if flag==2
    x=zeros(n,1);
    F=TT;
    fprintf('第二阶段单纯形表为:\n')
else
    x=zeros(m+n-pq,1);
end
for k=1:m
    x(B(k))=bb(k);
end
if sum(ff==0)~=m
    exitflag=2;
end
fval=x'*F;



程序可能会有瑕疵之处  因为我并没有怎么学过程序  MATLAB也是刚接触  若有错误请见谅  但求抛砖引玉




搜索更多相关主题的帖子: 数据 算法 单纯性 MATLAB 
2009-10-25 11:09
岩土刘甜
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2013-9-29
得分:0 
谢谢,学习一下!
2013-09-29 08:57



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-289843-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.331573 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved