最近一直在看建模老哥的课,在分支定界法这块他的代码我跑起来一直报错,打了很多断点也是没能发现问题所在,在网上搜索出现的基本都是和他一样的代码,我不知道其他人是否能正常运行,但是我实在是不行,所以干脆重写。
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
测试了三组数据,和割平面等其他算法结果一致,这里不再演示,可以用数据自己进行测试,如有疑问可以评论区讨论