MATLAB分支定界法

最近一直在看建模老哥的课,在分支定界法这块他的代码我跑起来一直报错,打了很多断点也是没能发现问题所在,在网上搜索出现的基本都是和他一样的代码,我不知道其他人是否能正常运行,但是我实在是不行,所以干脆重写。

function [x, fval, status] = Branch_Bound(f, A, B, Aeq, Beq, lb, ub, fcheck, e)
    if nargin < 9, e = 1e-10; end
    if nargin < 8, fcheck = 1; end %-1求最大值
    if nargin < 7, ub = []; end
    if nargin < 6, lb = []; end
    if nargin < 5, Beq = []; end
    if nargin < 4, Aeq = []; end
    if nargin < 3, B = []; end
    if nargin < 2 || isempty(f)
        error('Not enough input arguments. ');
    end
    options = optimset('display', 'off');
    [xx, fvalx, exitflag] = linprog(f, A, B, Aeq, Beq, lb, ub, [], options);
    if exitflag < 0
        disp('No feasible integer solution found.');
        x = xx;
        fval = fvalx;
        status = exitflag;
        return;
    else
        [x, fval, status] = branch_bound(f, A, B, Aeq, Beq, lb, ub, e, 1:length(f), xx, fvalx, inf, -1);
        if fcheck==-1
            fval=-fval;
        end
    end
end

function [x, fval, status, bound] = branch_bound(f, A, B, Aeq, Beq, lb, ub, e, I, x, fval, bound, parent)
    %%因为存在多重递归,为了防止局部变量只在函数体内部变化,我们把关键变量定义为全局变量
    %xr 当前最优解 
    % fr当前最优值 
    % bound当前边界
    global xr;
    global fr;
    global bound;
    options = optimoptions('linprog', 'Display', 'off');
    if all(abs(x(I) - round(x(I))) <= e)%终止条件,全为整数解
        status = 1;
        return;
    end
    intindex = I(find(abs(x(I) - round(x(I))) > e, 1));%获取最近的非整数解
    %%增加约束分枝
    n = intindex;
    addA = zeros(1, length(f));
    addA(n) = 1;
    A1 = [A; addA];
    B1 = [B; floor(x(n))];
    [x1, fval1, status1] = linprog(f, A1, B1, Aeq, Beq, lb, ub, [], options);
    A2 = [A; -addA];
    B2 = [B; -ceil(x(n))];
    [x2, fval2, status2] = linprog(f, A2, B2, Aeq, Beq, lb, ub, [], options);

    %%定界 
    if status1 > 0 && fval1 < bound
        [x, fval, status, bound] = branch_bound(f, A1, B1, Aeq, Beq, lb, ub, e, I, x1, fval1, bound, n);
        if status == 1
            bound = min(bound, fval);
            x=x1;
            fval=fval1;
        end
    else
        status = -1;
        return;
    end
    if status==1&&fval<=bound  %给全局变量赋值以记录当前最优解,并更新迭代
        xr=x;
        fr=fval;
    end
    if status2 > 0 && fval2 < bound
        [x, fval, status, bound] = branch_bound(f, A2, B2, Aeq, Beq, lb, ub, e, I, x2, fval2, bound, n);
        
        if status == 1
            bound = min(bound, fval);
        end
    else
        status = -1;
        return;
    end
    if parent ~= -1 && all(abs(x - round(x)) > e)
        status = -1;
        return;
    end
    if status==1&&fval<=bound   %给全局变量赋值以记录当前最优解,并更新迭代
        xr=x;
        fr=fval;
    end
    %%将结果赋值给输出
    x=xr;
    fval=fr;
end

测试了三组数据,和割平面等其他算法结果一致,这里不再演示,可以用数据自己进行测试,如有疑问可以评论区讨论

下面是一个使用分支定界算法求解整数规划问题的简单MATLAB代码示例: ```matlab function [x_opt, f_opt] = branchAndBound(c, A, b, intcon) % c: 目标函数的系数向量 % A: 约束矩阵 % b: 约束向量 % intcon: 整数变量的索引向量 n = length(c); % 变量个数 % 初始化上下界 lb = zeros(n, 1); ub = ones(n, 1); [x_opt, f_opt, exitflag] = intlinprog(c, intcon, A, b, [], [], lb, ub); % 检查是否找到整数解 if exitflag == 1 disp('找到整数解:'); disp(x_opt); disp('目标函数值:'); disp(f_opt); else disp('未找到整数解,进行分支定界...'); [x_opt, f_opt] = branchAndBoundRecursive(c, A, b, intcon, lb, ub); end end function [x_opt, f_opt] = branchAndBoundRecursive(c, A, b, intcon, lb, ub) n = length(c); % 选择一个分支变量,例如第一个非整数变量 branch_var = find(mod(lb,intcon) ~= 0, 1); % 分支左子树 lb_left = lb; ub_left = ub; ub_left(branch_var) = floor((lb(branch_var) + ub(branch_var)) / 2); [x_opt_left, f_opt_left] = intlinprog(c, intcon, A, b, [], [], lb_left, ub_left); % 分支右子树 lb_right = lb; ub_right = ub; lb_right(branch_var) = ceil((lb(branch_var) + ub(branch_var)) / 2); [x_opt_right, f_opt_right] = intlinprog(c, intcon, A, b, [], [], lb_right, ub_right); % 递归处理左右子树 if f_opt_left < f_opt_right [x_opt, f_opt] = branchAndBoundRecursive(c, A, b, intcon, lb_left, ub_left); else [x_opt, f_opt] = branchAndBoundRecursive(c, A, b, intcon, lb_right, ub_right); end end ``` 请注意,这只是一个简单的示例代码,用于说明分支定界算法的基本思想。在实际应用中,可能需要进行更多的优化和改进,以提高算法的效率和准确性。此外,对于大规模问题,可能需要采用其他高效的整数规划求解算法来处理。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值