运筹学——使用matlab实现整数规划割平面法

题目

在这里插入图片描述

代码

A = [-1 3 1 0; 7 1 0 1]; 
b = [6 35]'; 
c = [7 9 0 0];
[xstar,fxstar,iter] = Gomory(A,b,c)

function [xstar,fxstar,iter] = Gomory(A,b,c)
format rat
%UNTITLED 此处显示有关此函数的摘要
iter=0;%初始化迭代次数
while true
    [m,n]=size(A);%A矩阵大小
    if min(b)>=0
        [x_opt,fx_opt,CA,Cb] = simplex(A,b,c);
    else
        [x_opt,fx_opt,CA,Cb] = DSimplex_eye(A,b,c);
    end
    %判断是否已经解出了整数最优解
    flag_zhengshu=1;%flag_zhengshu初始化为1,只要有一个不是整数,flag_zhengshu赋值0
    for pos_x = 1:m
        if abs(round(x_opt(pos_x))-x_opt(pos_x))>=1e-3%判断整数条件
            flag_zhengshu=0;
            break;
        end
    end
    if flag_zhengshu==1 %如果解全是整数,满足条件,循环结束
        xstar=x_opt;
        fxstar=fx_opt;
        break;
    end
    iter=iter+1;
    %否则增加约束条件的行
    %找出b中和整数相差最大的数
    %循环遍历
    cha=0;
    row=0;
    for r=1:m
        t=abs(floor(x_opt(r))-x_opt(r));
        if t>cha
            cha=t;
            row=r;%标记当前最大差值的位置
        end
    end
    n=n+1;
    m=m+1;
    iter=iter+1;
    %更新矩阵系数,在原基础上增加一行一列,第(m,n)=1
    tmp_A=zeros(m,n);
    tmp_b=zeros(m,1);
    tmp_c=zeros(1,n);
    for i=1:m-1
        for j=1:n-1
            tmp_A(i,j)=CA(i,j);
        end
        tmp_b(i,1)=Cb(i,1);
    end
    tmp_b(m,1)=floor(Cb(row,1))-Cb(row,1);
    tmp_A(m,n)=1;
    for i =1:n-1
        tmp_c(1,i)=c(i);
    end
    %加上约束条件
    for i=1:n-1
        if tmp_A(row,i)==0
            tmp_A(m,i)=0;
        else
            tmp_A(m,i)=floor(tmp_A(row,i))-tmp_A(row,i);
        end
    end
    A=tmp_A;
    b=tmp_b;
    c=tmp_c;
end         
end

function [x_opt,fx_opt,A,b] = simplex(A,b,c)
% 单纯形法求解标准形线性规划问题: max cx s.t. Ax=b x>=0
% x_opt,fx_opt,iter(最优解、最优函数值、迭代次数)
format rat %元素使用分数表示
[m,n] = size(A);              %m约束条件个数, n决策变量数
ind_B =has_ones(A);
ind_N = setdiff(1:n, ind_B);  %非基变量的索引,原理是返回在1:n中出现而不在ind_B即基变量索引中出现的元素,并从小到大排序
% 循环求解
while true
    x0 = zeros(n,1);
    x0(ind_B) = b;               %初始基可行解,令基变量的位置为方程组右边系数,非基变量取值为0
    cB = c(ind_B);               %计算cB,即目标函数在基变量处对应的系数
    Sigma = zeros(1,n);          %Sigma为检验数向量
    Sigma(ind_N) = c(ind_N) - cB*A(:,ind_N);   %计算检验数(非基变量),因为基变量对应的初始检验数一定为0
    [~, k] = max(Sigma);         %选出最大检验数, 确定进基变量索引k;~表示忽略第一个参数(即最大值),k是索引
    if ~any(Sigma > 0)           %所有检验数都小于0,此基可行解为最优解, any表示存在某个检验数>0        
        x_opt = x0;
        fx_opt = c * x_opt;      %算出最优解
        return
    end
    if all(A(:,k) <= 0)          %表示检验数这一列每个数都<=0,有无界解
        x_opt = [];
        break
    end
    Theta = b ./ A(:,k);         %计算θ(点除,即矩阵中对应元素相除,得到一个新的矩阵)
    Theta(Theta<=0) = 10000;
    [~, q] = min(Theta);         %选出最小θ
    el = ind_B(q);               %确定出基变量在系数矩阵中的列索引el, 主元为A(q,k)
    % 换基
    ind_B(ind_B == el) = k;      %新的基变量索引
    ind_N = setdiff(1:n, ind_B); %非基变量索引
    % 更新A和b
    A(:,ind_N) = A(:,ind_B) \ A(:,ind_N); %基矩阵的逆乘以非基矩阵
    b = A(:,ind_B) \ b;  %基矩阵的逆乘以b
    A(:,ind_B) = eye(m,m);  %基矩阵更新为单位矩阵
end
end

function [x_opt,fx_opt,A,b] = DSimplex_eye(A,b,c)
% 对偶单纯形法求解标准形线性规划问题: max cx s.t. Ax = b x>=0
% 输入参数: c为目标函数系数, A为约束方程组系数矩阵, b为约束方程组常数项
% 输出参数: x_opt为最求解,fx_opt为最优函数值,iter为迭代次数
format rat                    %元素使用分数表示
[m,n] = size(A);              %m约束条件个数, n决策变量数
ind_B = has_ones(A);
ind_N = setdiff(1:n, ind_B);  %非基变量的索引,原理是返回在1:n中出现而不在ind_B即基变量索引中出现的元素,并从小到大排序
while true
    x0 = zeros(n,1);
    x0(ind_B) = b;                %初始基可行解
    cB = c(ind_B);                %计算cB
    if ~any(b < 0)                %此基可行解为最优解, any存在某个<0        
        x_opt = x0;
        fx_opt = c*x_opt;
        return
    end
    index=find(b<0);
    for i = 1:numel(index)
        if all(A(index(i),:)>=0)
            x_opt=[];
            fx_opt = [];         %此时原问题无可行解,对偶问题存在无界解
            return
        end
    end
    Sigma = zeros(1,n);
    Sigma(ind_N) = c(ind_N) - cB*A(:,ind_N);   %计算检验数
    [~,q] = min(b);               %选出最小的b
    r = ind_B(q);                 %确定出基变量索引r
    Theta = Sigma ./ A(q,:);      %计算θ
    Theta(Theta<=0) = 10000;
    [~,s] = min(Theta);           %确定进基变量索引s, 主元为A(q,s)
    % 换基
    ind_B(ind_B == r) = s;        %新的基变量索引
    ind_N = setdiff(1:n, ind_B);  %非基变量索引
    % 更新A和b
    A(:,ind_N) = A(:,ind_B) \ A(:,ind_N);
    b = A(:,ind_B) \ b;
    A(:,ind_B) = eye(m,m);
end
end

function [index]=has_ones(a)  %判断矩阵是否含有单位阵
    [m,n]=size(a);
    b=min(m,n);
    one=eye(b);
    index=[];
    result=zeros(m,1);
    for i =1:n
        for j=1:b
            if a(:,i)==one(:,j)
                index=[index,i];
                break;
            end
        end
    end
    for k=index
        result=result+a(:,k);
    end
    if result ~= ones(m,1)
       index=[];
    end
end

结果

>> Gomoryhomework

xstar =

       4       
       3       
       1       
       4       
       0       
       0       


fxstar =

      55       


iter =

       4       

作者创作不易,麻烦各位看官点赞收藏转发哈~

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值