单纯形法详解及MATLAB实现,对偶单纯形法详解及MATLAB实现

本文详细介绍了单纯形法和对偶单纯形法的解题步骤、MATLAB实现过程,包括寻找基可行解、最优性检验、迭代运算和无界解判断。同时展示了如何使用这两种方法求解线性规划问题,并通过实例演示了代码操作和结果分析。
摘要由CSDN通过智能技术生成

单纯形法详解及MATLAB实现,对偶单纯形法详解及MATLAB实现

单纯形法

我们以这样一个方程组做为例子,来看一下单纯形法是如何解题的
在这里插入图片描述这是一个已经化成标准形式的方程组,x4和x5是我们加入的松弛变量

第一步确定一个基可行解

我们将上面方程组写作Ax=b的形式,然后从A中找出一个单位矩阵,这个单位矩阵就先做为我们的初始基矩阵,对应的解也就是基可行解。我们直接选取松弛变量的系数作为单位矩阵(这个是一定满足的),如图A矩阵对应4和5位置上的列向量组成单位矩阵
在这里插入图片描述接下来很容易算出了基可行解
在这里插入图片描述

第二步最优性检验

也就是看一下这个解是不是最优解
简单来说,换一个x取值会不会使结果变大,如果会那这个解就不是最优解,如果不是,那我们就已经找到最优解啦。
这里当然不会是直接用眼睛看,我们是有公式的哦。
当当当,我们的检验数来啦。
首先选取基变量对应位置的c数组值
比如这里我就选取4,5位置上的c数组值,也就是0,0作为一个新的数组
我们可以记为cb=[0 0]
接下来我们对每一个变量x,xi(i=1,2,3,4,5)
计算
在这里插入图片描述作为该变量所对应的检验数,m为基变量个数也就是cb数组长度,如果所有的检验数都小于等于0,那我们就找到最优解了,否则我们就要进行下一步了。

迭代运算

在开始迭代之前,我们要先看一下是不是有无界解。如果对于一个大于0的检验数,它所对应的A矩阵中的列向量元素全部小于等于0,那么我们就知道是有无界解。
否则我们就要开始迭代
具体流程我们可以用一个流程图来看一看
在这里插入图片描述

代码部分

首先是函数文件

function [x_opt,fx_opt,iter] = Simplex_eye(A,b,c)
%x_opt为最优解,fx_opt为最优函数值,iter为迭代次数
iter=0;%初始化迭代次数
[m,n]=size(A);%A矩阵大小
r=nchoosek(1:n,m);%选择排列
I=eye(m,m);%设置一个m阶单位矩阵,用于之后计算的比较和计算
len=length(r);
for i=1:len %A中寻找一个单位矩阵,也就是基矩阵
    if A(:,[r(i,:)])==I
        bs=r(i,:);
        break;
    end
end
s=[1:n];
t=setdiff(s,bs);%setdiff可以计算出s数组中有,而bs数组中没有的元素
flag=0;%flag=1唯一最优解,2无穷多最优解,3有无界解
x=[];%基变量数组
while flag==0 %开始迭代
    iter=iter+1;%迭代次数加1
    x(t)=0;
    x(bs)=b;
    cb=c(bs);
    c_z=zeros(1,n); %计算检验数cj-zj
    for i=1:n
        z=sum(cb'.*A(:,i));
        c_z(i)=c(:,i)-z;
    end
    disp("----------------------第"+iter+"次---------------------------");
    All=[cb',bs',b,A];
    disp(All);
    disp(c_z);
    if all(c_z <= 0)%最优解
        x_opt=x;
        fx_opt=sum(c.*x_opt);
        if all(c_z(t) < 0)%非基变量都小于0
            flag=1;%唯一最优解
        else
            flag=2;%无穷多最优解
        end
        break;
    end
    
    [~,n1]=max(c_z);%找到最大的检验数所在位置
    disp(n1);
    disp("--------------");
    if all(A(:,n1) <= 0)%判断无界解,否则继续迭代
        x_opt=[];
        flag=3;
        break;
    end
    b1 = b./ A(:,n1);
    b1(b1<=0)=inf;%将小于等于0的数设为无穷大,
    [~,m1]=min(b1);%选出非负中的最小值对应的变量换出
    bs(m1)=n1;%n1对应为换入变量,m1对应换出变量
    t=setdiff(s,bs);
    A(:,t) = inv(A(:,bs))*A(:,t); %基矩阵的逆乘以非基矩阵
    b = inv(A(:,bs))*b;  %基矩阵的逆乘以b
    A(:,bs) = I;  %基矩阵更新为单位矩阵
end
if flag==1
    disp('唯一最优解');
    return
elseif flag==2
    disp('无穷多最优解');
    return
elseif flag==3
    disp('有无界解');
    fx_opt=inf;
    return
end

接下来是测试的脚本文件

A=[2 -3 2 1 0;1/3 1 5 0 1];
b=[15;20];
c=[1 2 3 0 0];
[x_opt,fx_opt,iter] = Simplex_eye(A,b,c)

运行结果
在这里插入图片描述

对偶单纯形法

函数接口文件

// DSimplex_eye.m
function [x_opt,fx_opt,iter] = DSimplex_eye(A,b,c)
% 输入参数: c为目标函数系数, A为约束方程组系数矩阵, b为约束方程组常数项
% 输出参数: x_opt最优解, fx_opt最优目标函数值, iter迭代次数
iter=0;%初始化迭代次数
[m,n]=size(A);%A矩阵大小
r=nchoosek(1:n,m);%选择排列
I=eye(m,m);%设置一个m阶单位矩阵,用于之后计算的比较和计算
len=length(r);
for i=1:len %A中寻找一个单位矩阵,也就是基矩阵
    if A(:,[r(i,:)])==I
        ind_B=r(i,:);
        break;
    end
end
ind_N = setdiff(1:n, ind_B); 
x=[];%基变量数组
while true         % 迭代
    x(ind_N)=0;
    x(ind_B) = b;
    cB = c(ind_B);                %计算cB
    Sigma = zeros(1,n); %检验数数组
    for i=1:n
        z=sum(cB'.*A(:,i));
        Sigma(i)=c(:,i)-z;
    end
    [~,q] = min(b);               %选出最小的b,换出
    r = ind_B(q);        
    Theta = Sigma ./ A(q,:);      %计算θ
    Theta(Theta<=0) = inf;
    [~,s] = min(Theta);         %确定进基变量索引s, 主元为A(q,s)
    vals = [cB',ind_B',b,A];
    vals = [vals; NaN, NaN, NaN, Sigma];
    disp("-----------------------第"+iter+"次--------------------------")
    disp(vals);
    if all(b >= 0)         %最优解       
        x_opt = x;
        fx_opt = sum(c .* x_opt);
        return
    end
    iter=iter+1;
    % 换基
    ind_B(ind_B == r) = s;      %新的基变量索引
    ind_N = setdiff(1:n, ind_B); %非基变量索引
    % 更新A和b
    A(:,ind_N) = inv(A(:,ind_B))* A(:,ind_N);
    b = inv(A(:,ind_B))* b;
    A(:,ind_B) = I;
end


函数脚本文件

// DSimplex_eye_script.m
A=[-1 -2 -1 1 0;
    -2 1 -3 0 1];
b=[-3 -4]';
c=[-2 -3 -4 0 0];
[x_opt,fx_opt,iter] = DSimplex_eye(A,b,c)

运行结果

在这里插入图片描述

  • 27
    点赞
  • 260
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫头丁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值