⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bmibnb.m

📁 matlab波形优化算法经常要用到的matlab toolbox工具箱:yalmip
💻 M
📖 第 1 页 / 共 2 页
字号:
function output = bmibnb(p)
%BMIBNB Branch-and-bound scheme for bilinear programs
%
% BMIBNB is never called by the user directly, but is called by YALMIP from
% SOLVESDP, by choosing the solver tag 'bmibnb' in sdpsettings
%
% The behaviour of BMIBNB can be altered using the fields in the field
% 'bmibnb' in SDPSETTINGS
%
% bmibnb.lowersolver    - Solver for lower bound [solver tag ('')]
% bmibnb.uppersolver    - Solver for upper bound [solver tag ('')]
% bmibnb.lpsolver       - Solver for LP bound tightening [solver tag ('')]
% bmibnb.branchmethod   - Branch strategy ['maxvol' | 'best' ('best')]
% bmibnb.branchrule     - Branch position ['omega' | 'bisect' ('omega')]
% bmibnb.lpreduce       - Improve variable bounds using LP [ real [0,1] (0 means no reduction, 1 means all variables)
% bmibnb.lowrank        - Partition variables into two disjoint sets and branch on smallest [ 0|1 (0)]
% bmibnb.target         - Exit if upper bound<target [double (-inf)]
% bmibnb.roottight      - Improve variable bounds in root using full problem [ 0|1 (1)]
% bmibnb.vartol         - Cut tree when x_U-x_L < vartol on all branching variables
% bmibnb.relgaptol      - Tolerance on relative objective error (UPPER-LOWER)/(1+|UPPER|) [real (0.01)]
% bmibnb.absgaptol      - Tolerance on objective error (UPPER-LOWER) [real (0.01)]
% bmibnb.pdtol          - A number is declared non-negative if larger than...[ double (-1e-6)]
% bmibnb.eqtol          - A number is declared zero if abs(x) smaller than...[ double (1e-6)]
% bmibnb.maxiter        - Maximum number nodes [int (100)]
% bmibnb.maxtime        - Maximum CPU time (sec.) [int (3600)]

% Author Johan L鰂berg
% $Id: bmibnb.m,v 1.76 2008/02/22 15:38:17 joloef Exp $

bnbsolvertime = clock;
showprogress('Branch and bound started',p.options.showprogress);

% *************************************************************************
% INITIALIZE DIAGNOSTICS AND DISPLAY LOGICS (LOWER VERBOSE IN SOLVERS)
% *************************************************************************
switch max(min(p.options.verbose,3),0)
case 0
    p.options.bmibnb.verbose = 0;
case 1
    p.options.bmibnb.verbose = 1;
    p.options.verbose = 0;
case 2
    p.options.bmibnb.verbose = 2;
    p.options.verbose = 0;
case 3
    p.options.bmibnb.verbose = 2;
    p.options.verbose = 1;
otherwise
    p.options.bmibnb.verbose = 0;
    p.options.verbose = 0;
end

if ~isempty(p.F_struc)
    if any(isnan(p.F_struc) | isinf(p.F_struc))
        output = yalmip_default_output;
        output.problem = 1;
        output.solved_nodes = 0;
        output.Primal       = zeros(length(p.c),1);
        output.infostr      = yalmiperror(output.problem,'BNB');
        output.solvertime   = 0;
        output.lower = inf;
        return
    end
end

% *************************************************************************
% Assume feasible (this property can be changed in the presolve codes
% *************************************************************************
p.feasible = 1;

% *************************************************************************
% Ensure that bond propagation is performed
% *************************************************************************
p.changedbounds = 1;

% *************************************************************************
% Some preprocessing to put the model in a better format
% *************************************************************************
p = convert_perspective_log(p);
n_in = length(p.c);

% *************************************************************************
% Extract bounds from model using direct information available
% *************************************************************************
p = presolve_bounds_from_domains(p);
p = presolve_bounds_from_modelbounds(p);
p = update_eval_bounds(p);
p = update_monomial_bounds(p);

% *************************************************************************
% Improve the bounds by performing some standard presolve
% *************************************************************************
p = presolve_bounds_from_equalities(p); 
p = update_eval_bounds(p);
p = update_monomial_bounds(p);
p = presolve_bounds_from_inequalities(p);
p = update_eval_bounds(p);
p = update_monomial_bounds(p);

% *************************************************************************
% For quadratic nonconvex programming over linear constraints, we
% diagonalize the problem to obtain less number of bilinear terms. Not
% theoretically any reason to do so, but practical performance is better
% *************************************************************************
p = diagonalize_quadratic_program(p);

% *************************************************************************
% Try to generate a feasible solution, by using avialable x0 (if usex0=1),
% or by trying the zero solution, or my trying the (lb+ub)/2 solution. Note
% that we do this here before the problem possibly is bilinearized, thus
% avoiding to introduce possibly complicating bilinear constraints
% *************************************************************************
p = compile_nonlinear_table(p);
[p,x_min,upper] = initializesolution(p);

% *************************************************************************
% If the upper bound solver is capable of solving the original problem,
% without bilinearizing it first, we might try to get a local solution,
% possibly based on our initial crude solution
% *************************************************************************
if solver_can_solve(p.solver.uppersolver,p) & any(p.variabletype>2)
    p.high_monom_model = [];
    p = build_recursive_scheme(p);
    p = compile_nonlinear_table(p);
    p = preprocess_bilinear_bounds(p);
    p = update_eval_bounds(p);
    p = updateboundsfromupper(p,upper);
    p = propagatecomplementary(p);
    p = updatemonomialbounds(p);
    p = presolve_bounds_from_equalities(p);
    p = updatemonomialbounds(p);   
    p = updatemonomialbounds(p);    
    p = update_eval_bounds(p);    
    [upper,p.x0,info_text,numglobals] = solve_upper_in_node(p,p,x_min,upper,x_min,p.solver.uppersolver.call,'',0);
    if numglobals > 0
        x_min = p.x0;
    end
end
if isempty(p.x0)
    p.x0 = zeros(length(p.c),1);
end

% *************************************************************************
% Sigmonial terms are converted to evaluation based expressions.
% *************************************************************************
p = convert_sigmonial_to_sdpfun(p);
%p = convert_polynomial_to_sdpfun(p);

% *************************************************************************
% The bilinear solver does not support non-quadratic models
% Hence, we need to bilinearize the problem. However, the upper bound
% solver might support general problems, so we should keep a copy of the
% original problem also in that case
% *************************************************************************
[p_bilin,changed] = convert_polynomial_to_quadratic(p);
if (p.solver.uppersolver.constraint.equalities.polynomial &  p.solver.uppersolver.objective.polynomial)
    p_bilin.originalModel = p;
    p = p_bilin;
else
    p = p_bilin;
    p.originalModel = p_bilin;
end

% *************************************************************************
% Build an evaluation tree for computing nonlinear terms when running the
% upper-bound solver, typically fmincon. Operators have to be applied in
% a particular order, to cope with terms such as sin(cos(x^2)^2)
p.originalModel = build_recursive_scheme(p.originalModel);

% *************************************************************************
% Fast derivbation of upper and lower bounds also requires an evaluation
% order
p = build_recursive_scheme(p);

% *************************************************************************
% Pre-calc lists of linear/bilinear/nonlinear variables (we have bilineared
% the model now, so the old precompiled table could be wrong
% *************************************************************************
p = compile_nonlinear_table(p);

% *************************************************************************
% Select branch variables. We should branch on all variables that are
% involved in bilinear terms.
% *************************************************************************
p.branch_variables = decide_branch_variables(p);
p.branch_variables = setdiff(p.branch_variables,p.evalVariables);

% *************************************************************************
% Tighten bounds (might be useful after bilinearization?)
% *************************************************************************
p = preprocess_bilinear_bounds(p);
p = update_eval_bounds(p);

% *************************************************************************
% Now reduce the branch variables by removing bilinear terms that only have
% been introduced due to a convex quadratic objective
% *************************************************************************
p = reduce_bilinear_branching_variables(p);

% *************************************************************************
% Simple pre-solve loop. The loop is needed for variables defined as w =
% x*y, x = t*u,y=..
% ******************************************[******************************
p = presolveloop(p,upper);
% while goon
%     start = [p.lb;p.ub];
%     i = i+1;
%     p = updateboundsfromupper(p,upper);
%     p = propagatecomplementary(p);
%     p = updatemonomialbounds(p);
%     p = presolve_bounds_from_equalities(p);
%     p = updatemonomialbounds(p);   
%     p = updatemonomialbounds(p);    
%     p = update_eval_bounds(p);
%     i = i+1;
%     goon = (norm(start-[p.lb;p.ub],'inf') > 1e-2) & i < 150;
%     start = [p.lb;p.ub];
% end

% *************************************************************************
% Try a little more root node tigthening
% *************************************************************************
close = find(abs(p.lb - p.ub) < 1e-12);
p.lb(close) = (p.lb(close)+p.ub(close))/2;
p.ub(close) = p.lb(close);
p = root_node_tighten(p,upper);
p = updatemonomialbounds(p);
p = update_eval_bounds(p);
p = presolve_bounds_from_equalities(p);
p = updatemonomialbounds(p);
output = yalmip_default_output;

% Detect complementary constraints
p.complementary = [];
complementary = find(p.lb==0 & p.ub==0 & p.variabletype'==1);
if ~isempty(complementary)
    for i = 1:length(complementary)
        index = find(p.bilinears(:,1) == complementary(i));
        x = p.bilinears(index,2);
        y = p.bilinears(index,3);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -