WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit b3cdd00

Browse files
authored
Add support for quadratic programming to the barrier method (#500)
This PR adds support for quadratic programs (QPs) using the barrier method. Only quadratic terms in the objective (pure QPs) are supported. Quadratic constraints (or QCQPs) are not supported at this time. The following changes are included in this PR: - The barrier method is modified to support quadratic objectives. LPs remain unchanged. - When Q matrix is diagonal, normal equations are formed, otherwise augmented system is formed - C and C++ APIs for setting up quadratic objective - Python API for setting Q matrix in CSR format - MPS and QPS/SIF formats are supported and can be run directly with cuopt_cli Authors: - Chris Maes (https://github.com/chris-maes) - Ramakrishnap (https://github.com/rgsl888prabhu) - Rajesh Gandham (https://github.com/rg20) Approvers: - Rajesh Gandham (https://github.com/rg20) - Trevor McKay (https://github.com/tmckayus) URL: #500
1 parent 7162916 commit b3cdd00

File tree

38 files changed

+1867
-164
lines changed

38 files changed

+1867
-164
lines changed

benchmarks/linear_programming/run_mps_files.sh

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ while [[ $# -gt 0 ]]; do
127127
TIME_LIMIT="$2"
128128
shift 2
129129
;;
130+
--iteration-limit)
131+
echo "ITERATION_LIMIT: $2"
132+
ITERATION_LIMIT="$2"
133+
shift 2
134+
;;
130135
--output-dir)
131136
echo "OUTPUT_DIR: $2"
132137
OUTPUT_DIR="$2"
@@ -152,6 +157,11 @@ while [[ $# -gt 0 ]]; do
152157
NUM_CPU_THREADS="$2"
153158
shift 2
154159
;;
160+
--method)
161+
echo "METHOD: $2"
162+
METHOD="$2"
163+
shift 2
164+
;;
155165
--presolve)
156166
echo "PRESOLVE: $2"
157167
PRESOLVE="$2"
@@ -200,7 +210,6 @@ RELAXATION=${RELAXATION:-false}
200210
MIP_HEURISTICS_ONLY=${MIP_HEURISTICS_ONLY:-false}
201211
WRITE_LOG_FILE=${WRITE_LOG_FILE:-false}
202212
NUM_CPU_THREADS=${NUM_CPU_THREADS:-1}
203-
PRESOLVE=${PRESOLVE:-true}
204213
BATCH_NUM=${BATCH_NUM:-0}
205214
N_BATCHES=${N_BATCHES:-1}
206215
LOG_TO_CONSOLE=${LOG_TO_CONSOLE:-true}
@@ -281,7 +290,8 @@ if [[ -n "$MODEL_LIST" && -f "$MODEL_LIST" ]]; then
281290
# Skip empty lines
282291
[[ -z "$line" ]] && continue
283292
# If the line does not end with .mps, append it
284-
if [[ "$line" != *.mps ]]; then
293+
# ignore if it ends with .SIF
294+
if [[ "$line" != *.mps && "$line" != *.SIF ]]; then
285295
echo "${line}.mps" >> "$TMP_MODEL_LIST"
286296
else
287297
echo "$line" >> "$TMP_MODEL_LIST"
@@ -314,7 +324,10 @@ if [[ -n "$MODEL_LIST" ]]; then
314324
exit 1
315325
fi
316326
else
317-
mapfile -t mps_files < <(ls "$MPS_DIR"/*.mps)
327+
# Gather both .mps and .SIF files in the directory
328+
mapfile -t mps_files < <(ls "$MPS_DIR"/*.mps "$MPS_DIR"/*.SIF 2>/dev/null)
329+
330+
echo "Found ${#mps_files[@]} .mps and .SIF files in $MPS_DIR"
318331
fi
319332

320333
# Calculate batch size and start/end indices
@@ -375,6 +388,9 @@ worker() {
375388

376389
# Build arguments string
377390
args=""
391+
if [ -n "$ITERATION_LIMIT" ]; then
392+
args="$args --iteration-limit $ITERATION_LIMIT"
393+
fi
378394
if [ -n "$NUM_CPU_THREADS" ]; then
379395
args="$args --num-cpu-threads $NUM_CPU_THREADS"
380396
fi
@@ -391,7 +407,12 @@ worker() {
391407
args="$args --num-gpus $GPUS_PER_INSTANCE"
392408
fi
393409
args="$args --log-to-console $LOG_TO_CONSOLE"
394-
args="$args --presolve $PRESOLVE"
410+
if [ -n "$PRESOLVE" ]; then
411+
args="$args --presolve $PRESOLVE"
412+
fi
413+
if [ -n "$METHOD" ]; then
414+
args="$args --method $METHOD"
415+
fi
395416

396417
CUDA_VISIBLE_DEVICES=$gpu_devices cuopt_cli "$mps_file" --time-limit $TIME_LIMIT $args
397418
done

cpp/include/cuopt/linear_programming/cuopt_c.h

Lines changed: 157 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ cuopt_int_t cuOptReadProblem(const char* filename, cuOptOptimizationProblem* pro
114114
/** @brief Create an optimization problem of the form
115115
*
116116
* @verbatim
117-
* minimize/maximize cᵀx + offset
118-
* subject to A x {=, ≤, ≥} b
119-
* l x u
117+
* minimize/maximize c^T x + offset
118+
* subject to A x {=, <=, >=} b
119+
* l <= x <= u
120120
* x_i integer for some i
121121
* @endverbatim
122122
*
@@ -238,6 +238,160 @@ cuopt_int_t cuOptCreateRangedProblem(cuopt_int_t num_constraints,
238238
const char* variable_types,
239239
cuOptOptimizationProblem* problem_ptr);
240240

241+
/** @brief Create an optimization problem of the form
242+
*
243+
* @verbatim
244+
* minimize/maximize c^T x + x^T Q x + offset
245+
* subject to A x {=, <=, >=} b
246+
* l ≤ x ≤ u
247+
* @endverbatim
248+
*
249+
* @param[in] num_constraints The number of constraints
250+
* @param[in] num_variables The number of variables
251+
* @param[in] objective_sense The objective sense (CUOPT_MINIMIZE for
252+
* minimization or CUOPT_MAXIMIZE for maximization)
253+
* @param[in] objective_offset An offset to add to the linear objective
254+
* @param[in] objective_coefficients A pointer to an array of type cuopt_float_t
255+
* of size num_variables containing the coefficients of the linear objective
256+
* @param[in] quadratic_objective_matrix_row_offsets A pointer to an array of type
257+
* cuopt_int_t of size num_variables + 1. quadratic_objective_matrix_row_offsets[i] is
258+
* the index of the first non-zero element of the i-th row of the quadratic objective matrix in
259+
* quadratic_objective_matrix_column_indices and
260+
* quadratic_objective_matrix_coefficent_values. This is part of the compressed sparse row
261+
* representation of the quadratic objective matrix.
262+
* @param[in] quadratic_objective_matrix_column_indices A pointer to an array of type
263+
* cuopt_int_t of size quadratic_objective_matrix_row_offsets[num_variables] containing
264+
* the column indices of the non-zero elements of the quadratic objective matrix.
265+
* This is part of the compressed sparse row representation of the quadratic objective
266+
* matrix.
267+
* @param[in] quadratic_objective_matrix_coefficent_values A pointer to an array of type
268+
* cuopt_float_t of size quadratic_objective_matrix_row_offsets[num_variables] containing
269+
* the values of the non-zero elements of the quadratic objective matrix.
270+
* @param[in] constraint_matrix_row_offsets A pointer to an array of type
271+
* cuopt_int_t of size num_constraints + 1. constraint_matrix_row_offsets[i] is the
272+
* index of the first non-zero element of the i-th constraint in
273+
* constraint_matrix_column_indices and constraint_matrix_coefficent_values. This is
274+
* part of the compressed sparse row representation of the constraint matrix
275+
* @param[in] constraint_matrix_column_indices A pointer to an array of type
276+
* cuopt_int_t of size constraint_matrix_row_offsets[num_constraints] containing
277+
* the column indices of the non-zero elements of the constraint matrix. This is
278+
* part of the compressed sparse row representation of the constraint matrix
279+
* @param[in] constraint_matrix_coefficent_values A pointer to an array of type
280+
* cuopt_float_t of size constraint_matrix_row_offsets[num_constraints] containing
281+
* the values of the non-zero elements of the constraint matrix. This is
282+
* part of the compressed sparse row representation of the constraint matrix
283+
* @param[in] constraint_sense A pointer to an array of type char of size
284+
* num_constraints containing the sense of the constraints (CUOPT_LESS_THAN,
285+
* CUOPT_GREATER_THAN, or CUOPT_EQUAL)
286+
* @param[in] rhs A pointer to an array of type cuopt_float_t of size num_constraints
287+
* containing the right-hand side of the constraints
288+
* @param[in] lower_bounds A pointer to an array of type cuopt_float_t of size num_variables
289+
* containing the lower bounds of the variables
290+
* @param[in] upper_bounds A pointer to an array of type cuopt_float_t of size num_variables
291+
* containing the upper bounds of the variables
292+
* @param[out] problem_ptr Pointer to store the created optimization problem
293+
* @return CUOPT_SUCCESS if successful, CUOPT_ERROR otherwise
294+
*/
295+
cuopt_int_t cuOptCreateQuadraticProblem(
296+
cuopt_int_t num_constraints,
297+
cuopt_int_t num_variables,
298+
cuopt_int_t objective_sense,
299+
cuopt_float_t objective_offset,
300+
const cuopt_float_t* objective_coefficients,
301+
const cuopt_int_t* quadratic_objective_matrix_row_offsets,
302+
const cuopt_int_t* quadratic_objective_matrix_column_indices,
303+
const cuopt_float_t* quadratic_objective_matrix_coefficent_values,
304+
const cuopt_int_t* constraint_matrix_row_offsets,
305+
const cuopt_int_t* constraint_matrix_column_indices,
306+
const cuopt_float_t* constraint_matrix_coefficent_values,
307+
const char* constraint_sense,
308+
const cuopt_float_t* rhs,
309+
const cuopt_float_t* lower_bounds,
310+
const cuopt_float_t* upper_bounds,
311+
cuOptOptimizationProblem* problem_ptr);
312+
313+
/** @brief Create an optimization problem of the form *
314+
* @verbatim
315+
* minimize/maximize c^T x + x^T Q x + offset
316+
* subject to bl <= A*x <= bu
317+
* l <= x <= u
318+
* @endverbatim
319+
*
320+
* @param[in] num_constraints - The number of constraints.
321+
*
322+
* @param[in] num_variables - The number of variables.
323+
*
324+
* @param[in] objective_sense - The objective sense (CUOPT_MINIMIZE for
325+
* minimization or CUOPT_MAXIMIZE for maximization)
326+
*
327+
* @param[in] objective_offset - An offset to add to the linear objective.
328+
*
329+
* @param[in] objective_coefficients - A pointer to an array of type cuopt_float_t
330+
* of size num_variables containing the coefficients of the linear objective.
331+
*
332+
* @param[in] quadratic_objective_matrix_row_offsets - A pointer to an array of type
333+
* cuopt_int_t of size num_variables + 1. quadratic_objective_matrix_row_offsets[i] is the
334+
* index of the first non-zero element of the i-th row of the quadratic objective matrix in
335+
* quadratic_objective_matrix_column_indices and quadratic_objective_matrix_coefficent_values.
336+
* This is part of the compressed sparse row representation of the quadratic objective matrix.
337+
*
338+
* @param[in] quadratic_objective_matrix_column_indices - A pointer to an array of type
339+
* cuopt_int_t of size quadratic_objective_matrix_row_offsets[num_variables] containing
340+
* the column indices of the non-zero elements of the quadratic objective matrix.
341+
* This is part of the compressed sparse row representation of the quadratic objective matrix.
342+
*
343+
* @param[in] quadratic_objective_matrix_coefficent_values - A pointer to an array of type
344+
* cuopt_float_t of size quadratic_objective_matrix_row_offsets[num_variables] containing
345+
* the values of the non-zero elements of the quadratic objective matrix.
346+
*
347+
* @param[in] constraint_matrix_row_offsets - A pointer to an array of type
348+
* cuopt_int_t of size num_constraints + 1. constraint_matrix_row_offsets[i] is the
349+
* index of the first non-zero element of the i-th constraint in
350+
* constraint_matrix_column_indices and constraint_matrix_coefficients.
351+
*
352+
* @param[in] constraint_matrix_column_indices - A pointer to an array of type
353+
* cuopt_int_t of size constraint_matrix_row_offsets[num_constraints] containing
354+
* the column indices of the non-zero elements of the constraint matrix.
355+
*
356+
* @param[in] constraint_matrix_coefficients - A pointer to an array of type
357+
* cuopt_float_t of size constraint_matrix_row_offsets[num_constraints] containing
358+
* the values of the non-zero elements of the constraint matrix.
359+
*
360+
* @param[in] constraint_lower_bounds - A pointer to an array of type
361+
* cuopt_float_t of size num_constraints containing the lower bounds of the constraints.
362+
*
363+
* @param[in] constraint_upper_bounds - A pointer to an array of type
364+
* cuopt_float_t of size num_constraints containing the upper bounds of the constraints.
365+
*
366+
* @param[in] variable_lower_bounds - A pointer to an array of type
367+
* cuopt_float_t of size num_variables containing the lower bounds of the variables.
368+
*
369+
* @param[in] variable_upper_bounds - A pointer to an array of type
370+
* cuopt_float_t of size num_variables containing the upper bounds of the variables.
371+
*
372+
* @param[out] problem_ptr - A pointer to a cuOptOptimizationProblem.
373+
* On output the problem will be created and initialized with the provided data.
374+
*
375+
* @return A status code indicating success or failure.
376+
*/
377+
cuopt_int_t cuOptCreateQuadraticRangedProblem(
378+
cuopt_int_t num_constraints,
379+
cuopt_int_t num_variables,
380+
cuopt_int_t objective_sense,
381+
cuopt_float_t objective_offset,
382+
const cuopt_float_t* objective_coefficients,
383+
const cuopt_int_t* quadratic_objective_matrix_row_offsets,
384+
const cuopt_int_t* quadratic_objective_matrix_column_indices,
385+
const cuopt_float_t* quadratic_objective_matrix_coefficent_values,
386+
const cuopt_int_t* constraint_matrix_row_offsets,
387+
const cuopt_int_t* constraint_matrix_column_indices,
388+
const cuopt_float_t* constraint_matrix_coefficients,
389+
const cuopt_float_t* constraint_lower_bounds,
390+
const cuopt_float_t* constraint_upper_bounds,
391+
const cuopt_float_t* variable_lower_bounds,
392+
const cuopt_float_t* variable_upper_bounds,
393+
cuOptOptimizationProblem* problem_ptr);
394+
241395
/** @brief Destroy an optimization problem
242396
*
243397
* @param[in, out] problem_ptr - A pointer to a cuOptOptimizationProblem. On

cpp/include/cuopt/linear_programming/optimization_problem.hpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,48 @@ class optimization_problem_t {
186186
* @param objective_offset Objective offset value.
187187
*/
188188
void set_objective_offset(f_t objective_offset);
189+
190+
/**
191+
* @brief Set the quadratic objective matrix (Q) in CSR format for QPS files.
192+
*
193+
* @note This is used for quadratic programming problems where the objective
194+
* function contains quadratic terms: x^T * Q * x + c^T * x
195+
*
196+
* @param[in] Q_values Values of the CSR representation of the quadratic objective matrix
197+
* @param size_values Size of the Q_values array
198+
* @param[in] Q_indices Indices of the CSR representation of the quadratic objective matrix
199+
* @param size_indices Size of the Q_indices array
200+
* @param[in] Q_offsets Offsets of the CSR representation of the quadratic objective matrix
201+
* @param size_offsets Size of the Q_offsets array
202+
* @param validate_positive_semi_definite Whether to validate if the matrix is positive semi
203+
* definite
204+
*/
205+
void set_quadratic_objective_matrix(const f_t* Q_values,
206+
i_t size_values,
207+
const i_t* Q_indices,
208+
i_t size_indices,
209+
const i_t* Q_offsets,
210+
i_t size_offsets,
211+
bool validate_positive_semi_definite = false);
212+
213+
/**
214+
* @brief Get the quadratic objective matrix offsets
215+
* @return const reference to the Q_offsets vector
216+
*/
217+
const std::vector<i_t>& get_quadratic_objective_offsets() const;
218+
219+
/**
220+
* @brief Get the quadratic objective matrix indices
221+
* @return const reference to the Q_indices vector
222+
*/
223+
const std::vector<i_t>& get_quadratic_objective_indices() const;
224+
225+
/**
226+
* @brief Get the quadratic objective matrix values
227+
* @return const reference to the Q_values vector
228+
*/
229+
const std::vector<f_t>& get_quadratic_objective_values() const;
230+
189231
/**
190232
* @brief Set the variables (x) lower bounds.
191233
* @note Setting before calling the solver is optional, default value for all
@@ -341,6 +383,8 @@ class optimization_problem_t {
341383
const std::vector<std::string>& get_variable_names() const;
342384
const std::vector<std::string>& get_row_names() const;
343385

386+
bool has_quadratic_objective() const;
387+
344388
/**
345389
* @brief Gets the device-side view (with raw pointers), for ease of access
346390
* inside cuda kernels
@@ -382,6 +426,12 @@ class optimization_problem_t {
382426
f_t objective_scaling_factor_{1};
383427
/** offset of the objective function */
384428
f_t objective_offset_{0};
429+
430+
/** Quadratic objective matrix in CSR format (for (1/2) * x^T * Q * x term) */
431+
std::vector<i_t> Q_offsets_;
432+
std::vector<i_t> Q_indices_;
433+
std::vector<f_t> Q_values_;
434+
385435
/** lower bounds of the variables (primal part) */
386436
rmm::device_uvector<f_t> variable_lower_bounds_;
387437
/** upper bounds of the variables (primal part) */

cpp/libmps_parser/include/mps_parser/mps_data_model.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class mps_data_model_t {
115115
* @param objective_offset Objective offset value.
116116
*/
117117
void set_objective_offset(f_t objective_offset);
118+
118119
/**
119120
* @brief Set the variables (x) lower bounds.
120121
* @note Setting before calling the solver is optional, default value for all is 0.
@@ -356,7 +357,7 @@ class mps_data_model_t {
356357

357358
// QPS-specific data members for quadratic programming support
358359
/** Quadratic objective matrix in CSR format (for (1/2) * x^T * Q * x term) */
359-
std::vector<f_t> Q_objective_;
360+
std::vector<f_t> Q_objective_values_;
360361
std::vector<i_t> Q_objective_indices_;
361362
std::vector<i_t> Q_objective_offsets_;
362363

cpp/libmps_parser/src/mps_data_model.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ void mps_data_model_t<i_t, f_t>::set_quadratic_objective_matrix(const f_t* Q_val
201201
mps_parser_expects(
202202
Q_values != nullptr, error_type_t::ValidationError, "Q_values cannot be null");
203203
}
204-
Q_objective_.resize(size_values);
205-
std::copy(Q_values, Q_values + size_values, Q_objective_.data());
204+
Q_objective_values_.resize(size_values);
205+
std::copy(Q_values, Q_values + size_values, Q_objective_values_.data());
206206

207207
if (size_indices != 0) {
208208
mps_parser_expects(
@@ -421,13 +421,13 @@ i_t mps_data_model_t<i_t, f_t>::get_nnz() const
421421
template <typename i_t, typename f_t>
422422
const std::vector<f_t>& mps_data_model_t<i_t, f_t>::get_quadratic_objective_values() const
423423
{
424-
return Q_objective_;
424+
return Q_objective_values_;
425425
}
426426

427427
template <typename i_t, typename f_t>
428428
std::vector<f_t>& mps_data_model_t<i_t, f_t>::get_quadratic_objective_values()
429429
{
430-
return Q_objective_;
430+
return Q_objective_values_;
431431
}
432432

433433
template <typename i_t, typename f_t>
@@ -457,7 +457,7 @@ std::vector<i_t>& mps_data_model_t<i_t, f_t>::get_quadratic_objective_offsets()
457457
template <typename i_t, typename f_t>
458458
bool mps_data_model_t<i_t, f_t>::has_quadratic_objective() const noexcept
459459
{
460-
return !Q_objective_.empty();
460+
return !Q_objective_values_.empty();
461461
}
462462

463463
// NOTE: Explicitly instantiate all types here in order to avoid linker error

0 commit comments

Comments
 (0)