Fix and Bound: An efficient approach for solving large-scale quadratic programming problems with box constraints
This repository contains the source code of the B&B algorithm described in the paper "Fix and bound: an efficient approach for solving large-scale quadratic programming problems with box constraints" for solving non-convex BoxQPs to global optimality:
where
M. Locatelli, V. Piccialli, A. M. Sudoso (2024). Fix and bound: an efficient approach for solving large-scale quadratic programming problems with box constraints. Mathematical Programming Computation, https://doi.org/10.1007/s12532-024-00270-y.
The B&B algorithm is implemented in C++/MATLAB and requires the following solvers:
SDPNAL+ is called by using the MATLAB Engine API for C++, whereas Gurobi and SNOPT are called from MATLAB functions.
Ubuntu and Debian instructions:
- Install CMake and Armadillo:
sudo apt-get update
sudo apt-get install cmake libarmadillo-dev
- Open the makefile
boxqp_cpp/Makefile
- Set the variable
matlab_path
to the MATLAB installation folder.
- Set the variable
- Compile the code:
make
This code has been tested on Ubuntu 20.04 LTS with MATLAB R2020b Update 7, SDPNAL+ 1.0, Gurobi 10.0.2 and SNOPT 7.7. To speed up the B&B search, the code features a configurable pool of POSIX threads.
Various parameters used in the B&B algorithm can be modified via the configuration file boxqp_cpp/config.txt
:
BRANCH_AND_BOUND_TOL
- Optimality gap toleranceBRANCH_AND_BOUND_PARALLEL
- Thread pool size: single thread (1); multi-thread (> 1)BRANCH_AND_BOUND_MAX_NODES
- Maximum number of nodesBRANCH_AND_BOUND_VISITING_STRATEGY
- Best first (0); depth first (1); breadth first (2)BRANCH_AND_BOUND_FIXING
- Do not fix variables (0); try to fix variables (1)BRANCH_AND_BOUND_FIXING_TOL
- Tolerance for fixing variables (only if fixing is enabled)MATLAB_SESSION_THREADS_ROOT
- Number of threads for the MATLAB session at the rootMATLAB_SESSION_THREADS_CHILD
- Number of threads for the MATLAB session of child nodesMATLAB_SOURCE_FOLDER
- Full path of the MATLAB folder containing source files (boxqp_matlab
)SDP_SOLVER_TOL
- Accuracy tolerance of SDPNAL+ in the relative KKT residualSDP_SOLVER_VERBOSE
- Do not display SDP log (0), display SDP log (1)GUROBI_FOLDER
- Gurobi installation folderSNOPT_FOLDER
- SNOPT installation folderSNOPT_LICENSE
- SNOPT license file (.lic)SDPNAL_FOLDER
- SDPNAL+ installation folderCP_MAX_ITER
- Maximum number of cutting-plane iterationsCP_TOL
- Tolerance between two consecutive cutting-plane iterationsCP_MAX_INEQ
- Maximum number of triangle inequalities to separateCP_PERC_INEQ
- Fraction of the most violated triangle inequalities to addCP_EPS_INEQ
- Tolerance for checking the violation of triangle inequalitiesCP_EPS_ACTIVE
- Tolerance for detecting active triangle inequalities
./bb <config_file> <data_file> <log_file> <sol_file>
-
config_file
- configuration file -
data_file
- problem data${\bf Q}$ ,${\bf c}$ -
log_file
- log file -
sol_file
- optimal solution${\bf x^\star}$
File data_file
contains the problem data in the following format:
n
c_1 c_2 ... c_n
Q_11 Q_12 ... Q_1n
Q_21 Q_22 ... Q_2n
...
Q_n1 Q_n2 ... Q_nn
The log file reports the progress of the algorithm at the node level:
-
N
- node size -
BIN
- number of variables in set$N$ -
PARENT
- parent node ID -
NODE
- node ID -
LB_PAR
- lower bound of the parent node -
LB
- lower bound -
TIME (s)
- running time in seconds -
CP_ITER
- number of cutting-plane iterations -
CP_FLAG
- termination flag of the cutting-plane procedure-
-1
- maximum number of iterations -
0
- node must be pruned -
1
- less than$10n$ triangle inequalities -
2 - 3
- lower bound not significantly improved
-
-
CP_INEQ
- number of inequalities added in the last cutting-plane iteration -
SDP_FIX
- number of SDPs solved for fixing variables -
TIME_FIX
- time spent in seconds for fixing variables -
N_FIX
- number of fixed variables -
UB
- current upper bound -
GUB
- global upper bound -
I_FIX
- current branching decision -
NODE_GAP
- gap at the node -
GAP
- overall gap -
OPEN
- number of open nodes
At the end of the file, it shows the statistics:
TIME
- overall computational time in secondsNODES
- overall number of nodesROOT_GAP
- gap at the root nodeGAP
- overall optimality gapOPT
- optimal objective function value
Log file example:
DATA_PATH: /boxqp_instances/spar200-075-2.in
LOG_PATH: /log_spar200-075-2.txt
BRANCH_AND_BOUND_TOL: 0.0001
BRANCH_AND_BOUND_PARALLEL: 2
BRANCH_AND_BOUND_MAX_NODES: 1000
BRANCH_AND_BOUND_VISITING_STRATEGY: 0
BRANCH_AND_BOUND_FIXING: 1
BRANCH_AND_BOUND_FIXING_TOL: 0.01
MATLAB_SESSION_THREADS_ROOT: 4
MATLAB_SESSION_THREADS_CHILD: 2
MATLAB_SOURCE_FOLDER: /bb-boxqp-fixing/boxqp_matlab/
SDP_SOLVER_TOL: 0.0001
SDP_SOLVER_VERBOSE: 0
CP_MAX_ITER: 10
CP_TOL: 0.0001
CP_MAX_INEQ: 100000
CP_PERC_INEQ: 0.1
CP_EPS_INEQ: 0.0001
CP_EPS_ACTIVE: 0.00
GUROBI_FOLDER: /gurobi951/
SNOPT_FOLDER: /snopt7_matlab/
SNOPT_LICENSE: /snopt7.lic
SDPNAL_FOLDER: /SDPNAL+/
| N| BIN| PARENT| NODE| LB_PAR| LB| TIME (s)| CP_ITER| CP_FLAG| CP_INEQ| SDP_FIX| TIME_FIX| N_FIX| UB| GUB| I_FIX| NODE_GAP| GAP| OPEN|
| 200| 126| -1| 0| -inf| -22266.4| 364| 3| 1| 76669| 1| 58.1208| 19| -22163| -22163*| -1| 0.00466673| 0.00466673| 0|
| 180| 106| 0| 1| -22266.4| -22223.6| 110| 1| 1| 59120| 0| 0| 0| -22062| -22163| 38| 0.00273636| 0.00273636| 0|
| 180| 106| 0| 2| -22266.4| -22210.9| 240| 2| 1| 60048| 1| 40.9975| 10| -22163| -22163| 38| 0.00215997| 0.00273636| 1|
| 179| 105| 1| 3| -22223.6| -22183.4| 156| 1| 1| 59324| 1| 38.8991| 2| -22062| -22163| 199| 0.000921238| 0.00215997| 2|
| 179| 105| 1| 4| -22223.6| -22187.3| 161| 1| 1| 59630| 1| 41.3265| 3| -22099.4| -22163| 199| 0.0010967| 0.00215997| 3|
| 169| 95| 2| 5| -22210.9| -22172.6| 188| 1| 1| 58267| 1| 60.8439| 17| -22163| -22163| 81| 0.000432555| 0.0010967| 4|
| 175| 101| 4| 6| -22187.3| -22153.1| 62| 0| 0| 56624| 0| 0| 0| -22099.4| -22163| 97| -0.000447315| 0.0010967| 5|
| 169| 95| 2| 7| -22210.9| -22171.6| 156| 1| 1| 55533| 1| 37.3501| 7| -22136| -22163| 81| 0.000385916| 0.000921238| 4|
| 175| 101| 4| 8| -22187.3| -22163| 57| 0| 0| 56624| 0| 0| 0| -22095.4| -22163| 97| 9.47342e-08| 0.000921238| 5|
| 176| 102| 3| 9| -22183.4| -22156.2| 60| 0| 0| 57021| 0| 0| 0| -22056.5| -22163| 119| -0.00030788| 0.000432555| 4|
| 176| 102| 3| 10| -22183.4| -22157.1| 67| 0| 0| 57021| 0| 0| 0| -22029.7| -22163| 119| -0.0002681| 0.000432555| 3|
| 151| 77| 5| 11| -22172.6| -22163.1| 58| 0| 0| 45312| 0| 0| 0| -22163| -22163| 18| 3.10148e-06| 0.000385916| 2|
| 151| 77| 5| 12| -22172.6| -22139.5| 55| 0| 0| 45312| 0| 0| 0| -22138| -22163| 18| -0.00106123| 0.000385916| 1|
| 161| 87| 7| 13| -22171.6| -22145.9| 63| 0| 0| 49688| 0| 0| 0| -22124.8| -22163| 18| -0.000771785| -0.000771785| 0|
| 161| 87| 7| 14| -22171.6| -22149.5| 52| 0| 0| 49688| 0| 0| 0| -22136| -22163| 18| -0.000609419| -0.000609419| 0|
TIME: 1145 sec
NODES: 15
ROOT_GAP: 0.00466673
GAP: 0
OPT: -22163