diff --git a/.gitignore b/.gitignore index c9e16fcc5d..e8929667da 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,8 @@ docs/cuopt/source/cuopt-server/client-api/sh-cli-help.txt docs/cuopt/source/cuopt-server/server-api/server-cli-help.txt docs/cuopt/source/cuopt-cli/cuopt-cli-help.txt docs/cuopt/source/cuopt_spec.yaml +docs/cuopt/source/cuopt-grpc/protos/ +docs/cuopt/source/cuopt-grpc/cuopt-protos.zip python/cuopt_self_hosted/cuopt_sh_client/tests/utils/certs/*.key docs/cuopt/build diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index c3b322e69d..0dd202dfa3 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,5 +1,156 @@ # Release Notes +## Release Notes 26.10 + +### New Features (26.10) + +- New Java interface for LP, QP, QCQP, SOCP and MIP +- New RENS (Relaxation Enforced Neighboorhood Search) and mutation heuristics for MIP +- MIP solver now runs diving and recursive sub-MIP heuristics during the cut passes +- New primal heuristic for MIPs with arc-flow formulations +- MIP solver includes new portfolio of CPUFJ heuristics with diversification +- New compound move types in MIP CPUFJ: 2-opt, probing implication chain, clique exchange, set-partitioning row exchange and compound repair +- New LNS heuristic for MIP that uses ruin-and-repair logic +- New techniques for exploiting degeneracy in MIP +- New implied indicator and capacity lifting presolve strengthening for fixed-charge MIP models +- New MIP presolve: Block Bounded Value Elimination for binary problems +- New MIP presolve: dual aggregation for binary variables with a single lock +- New MIP presolve: exhaustive coefficient reduction for binary rows +- New Curtis-Reid scaling for PDLP +- New primal simplex method for LPs +- Support for reusing the barrier ordering and symbolic factorization when solving a sequence of problems with different linear objectives and right-hand sides +- The C API now exposes solver statistics as scalar solution attributes +- New `cuOptSetLogCallback` for capturing solver logs in C API +- Routing now supports per-vehicle distance-based breaks, so charging, refueling, or rest stops can be constrained by cumulative travel distance rather than time +- The gRPC server now solves routing problems (VRP, TSP, and PDP). A Python gRPC routing client is included with cuOpt +- A new HTTP proxy forwards requests to the gRPC server. The 26.10 container starts the proxy and gRPC server by default + + +### Breaking Changes (26.10) + +- The container image now runs the proxy and gRPC servers by default; the legacy HTTP server is an optional start command +- The proxy and gRPC servers (container defaults) support routing problems of up to 5500 locations with a travel time matrix, or 8000 without one. For larger problems use the legacy HTTP server. +- `libcuopt` is split into client, mathopt and routing components, with separate wheels and conda packages; `libcuopt` is now a thin metapackage +- The CUOPT_DISTRIBUTED_PDLP_PARTITIONER setting introduced in 26.08 is now CUOPT_MULTIGPU_PDLP_PARTITIONER +- The CUOPT_USE_DISTRIBUTED_PDLP setting introduced in 26.08 has been removed; use method and num_gpus instead +- When building from source the build.sh script no longer installs libcuopt into conda env by default + +### Improvements (26.10) + +- MIP heuristics improved by 3.2x on primal integral metric (geomean over the feasible MIPLIB2017 instances) +- QP/QCQP solve 1.3X faster (geomean over QPLIB and Hans Mittelmann test set) +- PDLP now uses column reduction on large problems (~2x faster in geomean over LPFeas addendum instances) +- Dual simplex is 1.4X faster (geomean over MIPLIB root relaxations) +- PDLP now fuses the Halpern update into the projection kernels to improve performance +- Concurrent LP now uses a threshold on the number of nonzeros to decide whether to launch barrier and dual simplex +- LP presolve now uses less memory by freeing the transpose matrix and PSLP reduced problem +- LPs with poor scaling are now attempted without presolve, even if PSLP declares infeasibility +- LP presolve now uses PSLP version 0.1.0; this version includes many improvements and bug fixes +- MIP presolve now uses iteration and work limits rather than time limits +- Set solution callbacks now use presolve and postsolve +- Dual simplex now perturbs the cost more aggressively and uses primal simplex to remove perturbations +- Dual simplex now attempts to remove perturbations when variables leave the basis +- Dual simplex now tries several initial points on problems with dual degenerate bounded variables +- Dual simplex's bound flipping ratio test is now approximately O(n) and combines Harris ratio test with bound flips +- SOCP now use a tighter default tolerance on the duality gap without a performance regression +- QCQP to SOCP conversion performance is improved and memory required is reduced +- QP/SOCP presolve now eliminates free variables with zero cost +- QP presolve now removes empty columns +- Barrier now performs Ruiz scaling and builds the augmented system on the GPU +- Barrier now scales QCQP/SOCP constraints by variable bounds before Ruiz equilibration +- Barrier now performs iterative refinement on GPU when using the normal equations +- Barrier now prints the cumulative setup time before the solve +- Barrier termination check now has reduced GPU/host synchronization overhead +- Barrier now has parameters to control adaptive regularization +- Barrier now has parameters for tuning primal and dual regularization +- Barrier now has a parameter to control bounding free variables +- Barrier now has more initial point options +- MIP root relaxation now honors the LP method selected +- MIP performance improvement in duplicate cut detection +- MIP reduced cost strengthening now stores lurking bounds based on incumbent objective value +- MIP now includes a new Mod-2 cut separator for zero-half cuts +- MIP random number generators are now per-worker instead of process wide; eliminating a source of nondeterminism +- MIP time to first solution is improved by reducing overheads +- MIP CPUFJ now has a fast-path heuristic for binary problems with integer activities +- MIP CPUFJ now has structure-aware starts and repairs +- Solution callback publication is now unified across solver components +- Routing now uses cost instead of distance terminology when the objective does not represent a physical distance +- The gRPC server now accepts a MIP starting solution +- The gRPC server now checks GPU health and shuts down if the GPU is unusable. It also provides the standard gRPC readiness and liveness probes + +### Bug Fixes (26.10) + +- Fix an issue in the C API when accessing solutions on infeasible problems +- Fix an issue in MPS writer on problems with no linear constraints +- Fix ranged constraint conversion and MPS writing/reading round trips +- Fix an issue in LP/MIP presolve where the user specified feasibility tolerance was not propagated to Papilo +- Fix an issue in PDLP where reduced costs where not returned for the default PDLP preset (Stable3) +- Fix a missing header in log for multi-GPU PDLP +- Fix an issue in multi-GPU PDLP where the solver stopped silently when asking for more GPUs than available +- Fix an issue on the C API where performing a multi-GPU PDLP solve on a problem built from row types and RHS was not supported +- Fix an issue on multi-GPU PDLP where project_initial_primal was ignored +- Fix a barrier crash when concurrent LP solving returned from cuDSS before its asynchronous work finished +- Fix a segfault in concurrent LP if dual simplex or barrier finished without setting a solution +- Fix several issues in barrier related to the cuDSS threading layer +- Fix a bug on QCQP/SOCP problems with ranged rows +- Fix an issue in QP/SOCP presolve where removing empty columns could corrupt memory, causing heap corruption errors or `cudaErrorLaunchFailure` +- Fix nondeterminism in barrier when `--cudss-deterministic=1` +- Fix an issue with QPs where duality gap was not included in the termination criteria +- Fix a buffer overflow when getting the dual solution or reduced costs of a QCQP; these requests now return an error +- Fix an issue in QP and SOCP where a large dual residual was reported for the final solution, even at an optimal solution +- Fix an issue in dual simplex logs where bound flips were not accounted for in objective +- Fix an issue in dual simplex inside MIP where cut off incorrectly used the perturbed objective +- Fix an issue in dual simplex where dual variables and dual feasibility was not recomputed after basis repair +- Fix MIP presolve incorrectly fixing continuous variables using integer-variable tolerance +- Fix false optimality declaration in MIP deterministic mode +- Fix several issues in MIP where the time limit was not respected +- Fix an issue in MIP where flow cover cut generation was accidentally O(n^2) +- Fix an issue in MIP where a large amount of time could elapse between logs +- Fix an issue in MIP when converting knapsack constraints to rational coefficients could remove integer solutions +- Fix an issue in MIP where termination was delayed during root cut passes +- Fix an issue in MIP where the sub-MIP was not correctly stopped when the main solve finished +- Fix an issue in MIP with halting cut passes +- Fix an issue in MIP feasibility jump where weights were uninitialized when adding an objective cut +- Fix an issue in MIP GF2 presolve where rank-deficient problems were incorrectly classified as infeasible +- Fix an issue in MIP GF2 presolve where some one-sided rows were treated as equalities +- Fix an issue in MIP presolve when performing single-lock-dual-aggregation +- Fix an issue with tolerances in MIP mod-2 cuts +- Fix a race condition in the asynchronous clique table generator and clique cuts +- Fix an unsynchronized read/write of the MIP clique table +- Fix a memory overflow in MIP when there were many feasible solutions +- Disable clique table generation in MIP when running in deterministic mode +- Fix an issue where the random number seed could change if multiple solves were performed within the same process +- Fix an issue in routing: keep host sources alive for async route-view copies +- Fix an issue in routing: avoid division by zero when vehicle capacity is zero +- Fix an issue in routing: guard diagonal element lookup against negative offsets in top_k +- Fix an issue in routing: uncapturable RMM copies inside CUDA graph captures +- Fix an issue in routing: handle CUDA graph errors +- Fix an issue where a PDLP warm start was ignored on a remote gRPC solve +- Fix an issue where a gRPC connection could be closed during a long or idle solve because the server did not accept the client's keepalive pings +- Fix an issue where stopping `cuopt_cli` or `cuopt_grpc_server` did not stop the solver process +- Fix an issue in the Python gRPC client where waiting for a remote solve blocked other Python threads + +### Deprecations (26.10) + +- The container's default server is now the HTTP proxy plus `cuopt_grpc_server`, in place of the legacy HTTP server. The legacy HTTP server is still shipped in 26.10 and will be removed in 26.12. See "Starting the Container" on the Legacy HTTP Server page in the 26.10 user guide for the legacy container command and for `CUOPT_SERVER_TYPE=legacy` in Kubernetes. That page links to the 26.08 guide. Differences are in "Deprecated Interfaces Not Provided by the Proxy Server" in the 26.10 user guide. +- Custom gRPC clients should now send solver settings through the `parameters` string map; individual setting fields are deprecated + +### Documentation (26.10) + +- Show mamba commands directly instead of a conda-then-swap note +- Document the VRP gRPC client (RoutingClient) +- Update NVIDIA Brev documentation links + +### New Contributors (26.10) + +- @nvidiacbrissette (#1524) +- @vgong-nv (#1888) +- @Juan-Francisco-Robles (#1299) +- @ZedingZhang (#1925) +- @vuule (#1900) +- @neuriv (#1947) +- @derluke (#1775) + ## Release Notes 26.08 ### New Features (26.08) diff --git a/docs/cuopt/source/conf.py b/docs/cuopt/source/conf.py index 524668ac44..a2a919e73d 100644 --- a/docs/cuopt/source/conf.py +++ b/docs/cuopt/source/conf.py @@ -8,6 +8,7 @@ import cuopt import yaml from packaging.version import Version +import shutil import subprocess import sys import os @@ -35,6 +36,21 @@ ["cuopt_cli", "--help"], stdout=open("cuopt-cli/cuopt-cli-help.txt", "w") ) +# Copy the gRPC protos next to the docs so api.rst can offer them for download. They import +# each other by file name, so they share one directory. +_grpc_src = Path(__file__).resolve().parents[3] / "cpp" / "src" / "grpc" +_proto_dir = Path("cuopt-grpc/protos") +_proto_dir.mkdir(exist_ok=True) +for _proto in ( + "cuopt_remote_service.proto", + "cuopt_remote.proto", + "codegen/generated/cuopt_remote_data.proto", + "routing/cuopt_routing.proto", + "routing/cuopt_routing_solution.proto", +): + shutil.copy(_grpc_src / _proto, _proto_dir) +shutil.make_archive("cuopt-grpc/cuopt-protos", "zip", _proto_dir) + with open("cuopt_spec.yaml", "w") as f: yaml.dump( get_openapi( diff --git a/docs/cuopt/source/convex-features.rst b/docs/cuopt/source/convex-features.rst index 5120b1ca9e..774b46cc0c 100644 --- a/docs/cuopt/source/convex-features.rst +++ b/docs/cuopt/source/convex-features.rst @@ -239,16 +239,18 @@ Method .. note:: PDLP solves to 1e-4 relative accuracy by default. -**Barrier**: The barrier method (also known as interior-point method) solves linear and quadratic programs using a primal-dual predictor-corrector algorithm. This method uses GPU-accelerated sparse Cholesky and sparse LDLT solves via cuDSS, and GPU-accelerated sparse matrix-vector and matrix-matrix operations via cuSparse. Barrier is particularly effective for large-scale problems and can automatically apply techniques like folding, dualization, and dense column elimination to improve performance. This method solves the linear systems at each iteration using the augmented system or the normal equations (ADAT). Enable crossover to obtain a highly accurate basic solution from a barrier solution. +**Barrier**: The barrier method (also known as interior-point) solves linear, quadratic, and second-order cone programs using a primal-dual predictor-corrector algorithm. This method uses GPU-accelerated sparse Cholesky and sparse LDLT solves via cuDSS, and GPU-accelerated sparse matrix-vector and matrix-matrix operations via cuSparse. Barrier is particularly effective for large-scale problems and can automatically apply techniques like folding, dualization, and dense column elimination to improve performance. This method solves the linear systems at each iteration using the augmented system or the normal equations (ADAT). Enable crossover to obtain a highly accurate basic solution from a barrier solution. .. note:: Barrier solves to 1e-8 relative accuracy by default. -**Dual Simplex**: Dual simplex is the simplex method applied to the dual of the linear program. Dual simplex requires the basis factorization of linear program fit into memory. Select this method if your LP is small to medium sized, or if you require a high-quality basic solution. +**Dual Simplex**: Dual simplex begins with a dual feasible point and iterates until primal feasibility and optimality is established. Dual simplex requires the basis factorization of linear program fit into memory. Select this method if your LP is small to medium sized, or if you require a high-quality basic solution. .. note:: Dual Simplex solves to 1e-6 absolute accuracy by default. +**Primal Simplex**: Primal simplex begins with a primal feasible point and iterates until dual feasibility and optimality is established. Primal simplex is also used by dual simplex to remove cost perturbations. Primal simplex is typically slower than dual simplex (about 2.3x in internal testing). Select dual simplex or the default concurrent method unless you have a specific reason to use primal simplex. + Crossover --------- @@ -313,6 +315,15 @@ Users can submit a set of problems which will be solved in a batch. Problems wil parallel today; callers may see a ``DeprecationWarning`` or a deprecation message in server ``warnings``. +Sequence Solves +--------------- + +When a sequence of convex optimization problems with the same constraint matrix are solved, cuOpt can reuse work from the first solve. To enable this, set the ``sequence_solve`` setting to true and solve with the barrier method. After the first solve you can change the linear objective with :meth:`~cuopt.linear_programming.data_model.DataModel.update_linear_objective` or the constraint right-hand side with :meth:`~cuopt.linear_programming.data_model.DataModel.update_rhs`, and solve again. Subsequent solves skip ordering and symbolic factorization. + +The quadratic objective, the constraint matrix, the row senses, and the variable bounds must stay unchanged between solves. See ``CUOPT_SEQUENCE_SOLVE`` in :doc:`convex-settings` for details and limits. + +.. note:: Sequence solves are currently only supported with the Python API. + PDLP Precision Modes -------------------- @@ -327,4 +338,9 @@ By default, PDLP operates in the native precision of the problem type (FP64 for Multi-GPU Mode -------------- -Users can use multiple GPUs to solve a problem by specifying the ``num_gpus`` parameter. The feature is restricted to LP problems that uses concurrent mode and supports up to 2 GPUs at the moment. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. +Multiple GPUs may be used to solve a linear program by specifying the ``num_gpus`` parameter. Multiple GPUs are used differently depending on the ``method`` parameter: + +* When the PDLP method is specified, multi-GPU PDLP is used to solve LPs faster or solve very large LPs that do not fit in the memory of a single GPU. +* When the concurrent method is specified, setting ``num_gpus=2``, will run PDLP and barrier concurrently on two GPUs to avoid sharing resources on a single GPU. Increasing ``num_gpus`` beyond two has no effect in this mode. + +.. note:: Concurrent is the default method; to run multi-GPU PDLP, users must specify the PDLP method. Multi-GPU mode is not supported on QP, QCQP, or SOCP problems. diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index cb5a78a789..27c4771646 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -78,25 +78,104 @@ We now describe the parameter settings used to control cuOpt's Linear Programmin Method ^^^^^^ -``CUOPT_METHOD`` controls the method to solve the linear programming problem. Four methods are available: +``CUOPT_METHOD`` controls the method to solve the linear program. Five methods are available: * ``Concurrent``: Use PDLP, dual simplex, and barrier in parallel (default). * ``PDLP``: Use the PDLP method. * ``Dual Simplex``: Use the dual simplex method. * ``Barrier``: Use the barrier (interior-point) method. +* ``Primal Simplex``: Use the primal simplex method. .. note:: The default method is ``Concurrent``. -Default accuracy for each method: +Default tolerances for each method: -* PDLP solves to 1e-4 relative accuracy by default. -* Barrier solves to 1e-8 relative accuracy by default. -* Dual Simplex solves to 1e-6 *absolute* accuracy by default. +* PDLP solves to 1e-4 relative tolerance by default. +* Barrier solves to 1e-8 relative tolerance by default. +* Simplex solves to 1e-6 *absolute* tolerance by default. + +See below for how to change the default tolerances. C API users should use the constants defined in :ref:`method-constants` for this parameter. Server Thin client users should use the :class:`cuopt_sh_client.SolverMethod` for this parameter. +Absolute Primal Tolerance +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_ABSOLUTE_PRIMAL_TOLERANCE`` controls the absolute primal tolerance used in the primal feasibility check. +Changing this value might have a significant impact on accuracy and runtime if the relative part +(the right-hand side vector b L2 norm) is close to, or equal to, 0. + + +The primal feasibility condition is computed as follows:: + + primal_feasiblity < absolute_primal_tolerance + relative_primal_tolerance * l2_norm(b) + +Default value is ``1e-4``. + + +Relative Primal Tolerance +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_RELATIVE_PRIMAL_TOLERANCE`` controls the relative primal tolerance used in the primal feasibility check. +Changing this value has a significant impact on accuracy and runtime. +The primal feasibility condition is computed as follows:: + + primal_feasiblity < absolute_primal_tolerance + relative_primal_tolerance * l2_norm(b) + +.. note:: The default value is ``1e-4``. + +Absolute Dual Tolerance +^^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_ABSOLUTE_DUAL_TOLERANCE`` controls the absolute dual tolerance used in the dual feasibility check. +Changing this value might have a significant impact on accuracy and runtime if the relative part +(the objective vector L2 norm) is close to, or equal to, 0. + +The dual feasibility condition is computed as follows:: + + dual_feasiblity < absolute_dual_tolerance + relative_dual_tolerance * l2_norm(c) + +.. note:: The default value is ``1e-4``. + +Relative Dual Tolerance +^^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_RELATIVE_DUAL_TOLERANCE`` controls the relative dual tolerance used in the dual feasibility check. +Changing this value has a significant impact on accuracy and runtime. +The dual feasibility condition is computed as follows:: + + dual_feasiblity < absolute_dual_tolerance + relative_dual_tolerance * l2_norm(c) + +.. note:: The default value is ``1e-4``. + + +Absolute Gap Tolerance +^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_ABSOLUTE_GAP_TOLERANCE`` controls the absolute gap tolerance used in the duality gap check. +Changing this value might have a significant impact on accuracy and runtime if the relative part ``(|primal_objective| + |dual_objective|)`` is close to, or equal to, 0. + +The duality gap is computed as follows:: + + duality_gap < absolute_gap_tolerance + relative_gap_tolerance * (|primal_objective| + |dual_objective|) + +.. note:: The default value is ``1e-4``. + + +Relative Gap Tolerance +^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_RELATIVE_GAP_TOLERANCE`` controls the relative gap tolerance used in the duality gap check. +Changing this value has a significant impact on accuracy and runtime. +The duality gap is computed as follows:: + + duality_gap < absolute_gap_tolerance + relative_gap_tolerance * (|primal_objective| + |dual_objective|) + +.. note:: The default value is ``1e-4``. + + PDLP Solver Mode ^^^^^^^^^^^^^^^^ @@ -144,11 +223,7 @@ Multi-GPU PDLP Partitioner ``CUOPT_MULTIGPU_PDLP_PARTITIONER`` selects how multi-GPU PDLP splits the problem across GPUs: ``0`` Auto (default; RoundRobin on 1 GPU, KaMinPar otherwise), ``1`` KaMinPar (multi-threaded graph partitioner, better balanced shards at the cost of extra partitioning time), or ``2`` -RoundRobin (no partitioning graph built). This constant was previously named -``CUOPT_DISTRIBUTED_PDLP_PARTITIONER`` (``distributed_pdlp_partitioner`` as a Server Thin client -key, now ``multigpu_pdlp_partitioner``); the separate ``CUOPT_USE_DISTRIBUTED_PDLP`` toggle has -been removed. - +RoundRobin (no partitioning graph built). Infeasibility Detection ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -230,6 +305,44 @@ available: .. note:: The default value is 0 (default precision). +Simplex Settings +^^^^^^^^^^^^^^^^ + +The following settings control the behavior of the simplex methods: + +Primal Simplex Pricing +"""""""""""""""""""""" + +``CUOPT_PRIMAL_SIMPLEX_PRICING`` controls the pricing rule used by the primal simplex algorithm. + +* ``0``: Dantzig pricing +* ``1``: Devex pricing (default) + +.. note:: The default value is ``1`` (Devex). + +Dual Simplex Initial Perturbation +""""""""""""""""""""""""""""""""" + +``CUOPT_DUAL_SIMPLEX_INITIAL_PERTURBATION`` controls whether the dual simplex method perturbs the objective at the start of solve. + +* ``-1``: Automatic (default) - cuOpt decides whether and how strongly to perturb +* ``0``: Do not perturb +* ``1``: Perturb + +.. note:: The default value is ``-1`` (automatic). + +Dual Simplex Remove Perturbation +"""""""""""""""""""""""""""""""" + +``CUOPT_DUAL_SIMPLEX_REMOVE_PERTURBATION`` controls whether dual simplex removes the cost perturbation during the solve, when variables leave the basis, +rather than only at the end. Removing perturbations earlier helps avoid clean up at the end of the solve. + +* ``-1``: Automatic (default) +* ``0``: Disabled +* ``1``: Enabled + +.. note:: The default value is ``-1`` (automatic). + Barrier Solver Settings ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -310,86 +423,22 @@ Dual Initial Point ``CUOPT_BARRIER_DUAL_INITIAL_POINT`` controls the method used to compute the dual initial point for the barrier solver. The choice of initial point will affect the number of iterations performed by barrier. * ``-1``: Automatic (default) - cuOpt selects the best method -* ``0``: Use an initial point from a heuristic approach based on the paper "On Implementing Mehrotra's Predictor–Corrector Interior-Point Method for Linear Programming" (SIAM J. Optimization, 1992) by Lustig, Martsten, Shanno. -* ``1``: Use an initial point from solving a least squares problem that minimizes the norms of the dual variables and reduced costs while statisfying the dual equality constraints. +* ``0``: Use an initial point from a heuristic approach based on the paper "On Implementing Mehrotra's Predictor–Corrector Interior-Point Method for Linear Programming" (SIAM J. Optimization, 1992) by Lustig, Martsten, Shanno +* ``1``: Use an initial point from solving a least squares problem that minimizes the norms of the dual variables and reduced costs while statisfying the dual equality constraints +* ``2``: Use an initial point from a heurisitic approach based on SeDuMi by Jos Sturm .. note:: The default value is ``-1`` (automatic). -Absolute Primal Tolerance -^^^^^^^^^^^^^^^^^^^^^^^^^ - -``CUOPT_ABSOLUTE_PRIMAL_TOLERANCE`` controls the absolute primal tolerance used in the primal feasibility check. -Changing this value might have a significant impact on accuracy and runtime if the relative part -(the right-hand side vector b L2 norm) is close to, or equal to, 0. - - -The primal feasibility condition is computed as follows:: - - primal_feasiblity < absolute_primal_tolerance + relative_primal_tolerance * l2_norm(b) - -Default value is ``1e-4``. - - -Relative Primal Tolerance -^^^^^^^^^^^^^^^^^^^^^^^^^ - -``CUOPT_RELATIVE_PRIMAL_TOLERANCE`` controls the relative primal tolerance used in PDLP's primal feasibility check. -Changing this value has a significant impact on accuracy and runtime. -The primal feasibility condition is computed as follows:: - - primal_feasiblity < absolute_primal_tolerance + relative_primal_tolerance * l2_norm(b) - -.. note:: The default value is ``1e-4``. - -Absolute Dual Tolerance -^^^^^^^^^^^^^^^^^^^^^^^ - -``CUOPT_ABSOLUTE_DUAL_TOLERANCE`` controls the absolute dual tolerance used in PDLP's dual feasibility check. -Changing this value might have a significant impact on accuracy and runtime if the relative part -(the objective vector L2 norm) is close to, or equal to, 0. - -The dual feasibility condition is computed as follows:: - - dual_feasiblity < absolute_dual_tolerance + relative_dual_tolerance * l2_norm(c) - -.. note:: The default value is ``1e-4``. - -Relative Dual Tolerance -^^^^^^^^^^^^^^^^^^^^^^^ - -``CUOPT_RELATIVE_DUAL_TOLERANCE`` controls the relative dual tolerance used in PDLP's dual feasibility check. -Changing this value has a significant impact on accuracy and runtime. -The dual feasibility condition is computed as follows:: - - dual_feasiblity < absolute_dual_tolerance + relative_dual_tolerance * l2_norm(c) - -.. note:: The default value is ``1e-4``. - - -Absolute Gap Tolerance -^^^^^^^^^^^^^^^^^^^^^^ - -``CUOPT_ABSOLUTE_GAP_TOLERANCE`` controls the absolute gap tolerance used in PDLP's duality gap check. -Changing this value might have a significant impact on accuracy and runtime if the relative part ``(|primal_objective| + |dual_objective|)`` is close to, or equal to, 0. - -The duality gap is computed as follows:: +Barrier Initial Point Safeguard +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - duality_gap < absolute_gap_tolerance + relative_gap_tolerance * (|primal_objective| + |dual_objective|) +``CUOPT_BARRIER_INITIAL_POINT_SAFEGUARD`` sets the margin used to push the barrier method's initial point into the interior of the +nonnegative orthant and, for second-order cone problems, into the interior of the cones. The initial point is shifted so that it is +at least this far from the boundary. The value must be greater than or equal to ``0``. This setting only has an effect when ``CUOPT_BARRIER_DUAL_INITIAL_POINT`` is ``0`` or ``1``. -.. note:: The default value is ``1e-4``. +.. note:: The default value is ``10.0``. -Relative Gap Tolerance -^^^^^^^^^^^^^^^^^^^^^^ - -``CUOPT_RELATIVE_GAP_TOLERANCE`` controls the relative gap tolerance used in PDLP's duality gap check. -Changing this value has a significant impact on accuracy and runtime. -The duality gap is computed as follows:: - - duality_gap < absolute_gap_tolerance + relative_gap_tolerance * (|primal_objective| + |dual_objective|) - -.. note:: The default value is ``1e-4``. - Barrier Iterative Refinement ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -419,3 +468,42 @@ Barrier Adaptive Regularization * ``1``: Enable adaptive regularization .. note:: The default value is ``-1`` (automatic). + +Barrier Presolve Bound Free Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_BARRIER_PRESOLVE_BOUND_FREE_VARIABLES`` controls whether the barrier presolve attempts to put bounds on free variables using the linear constraints. + +* ``-1``: Automatic (default) - cuOpt decides based on the problem +* ``0``: Disable bounding of free variables +* ``1``: Enable bounding of free variables + +.. note:: The default value is ``-1`` (automatic). + +Barrier Primal and Dual Regularization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_BARRIER_PRIMAL_REGULARIZATION`` and ``CUOPT_BARRIER_DUAL_REGULARIZATION`` set the initial primal and dual regularization +applied to the augmented system. They apply to the first factorization only. If adaptive regularization is enabled +(see ``CUOPT_BARRIER_ADAPTIVE_REGULARIZATION``), it can still scale the regularization up or down in later iterations. + +* ``-1``: Automatic (default) - cuOpt uses its built-in heuristic +* A value greater than or equal to ``0``: Use this value as the starting regularization + +.. note:: The default value of both settings is ``-1`` (automatic). + + +Sequence Solve +^^^^^^^^^^^^^^ + +``CUOPT_SEQUENCE_SOLVE`` controls whether cuOpt caches the ordering and symbolic factorization so that a sequence of related barrier solves can reuse it. +When enabled, and the first solve with the barrier method finishes with an optimal solution, cuOpt stores information about the factorization. In subsequent solves, +the linear objective and the right-hand side of the linear equality constraints may be changed with :meth:`~cuopt.linear_programming.data_model.DataModel.update_linear_objective` or +:meth:`~cuopt.linear_programming.data_model.DataModel.update_rhs` without recomputing the ordering or the symbolic factorization. + +* ``true``: Cache the ordering and symbolic factorization for later solves +* ``false``: Do not cache (default) + +.. note:: The default value is ``false``. + +.. note:: Reuse requires that the quadratic objective, the constraint matrix, the row senses, and the variable bounds stay unchanged between solves. Problems with range rows are not supported. When sequence solve is enabled, ``CUOPT_FOLDING`` and ``CUOPT_BARRIER_PRESOLVE_BOUND_FREE_VARIABLES`` are disabled. diff --git a/docs/cuopt/source/cuopt-c/convex/convex-c-api.rst b/docs/cuopt/source/cuopt-c/convex/convex-c-api.rst index 650b306bb1..0b7ba54143 100644 --- a/docs/cuopt/source/cuopt-c/convex/convex-c-api.rst +++ b/docs/cuopt/source/cuopt-c/convex/convex-c-api.rst @@ -172,6 +172,16 @@ The following functions are used to set and get parameters. You can find more de .. doxygenfunction:: cuOptSetFloatParameter .. doxygenfunction:: cuOptGetFloatParameter +Solver Log Callback +------------------- + +A callback can be registered to receive each solver log line, for example to display or forward solver output in a GUI. +The callback is invoked in addition to any console or file logging enabled with ``CUOPT_LOG_TO_CONSOLE`` and ``CUOPT_LOG_FILE``. +Pass ``NULL`` to remove a registered callback. + +.. doxygentypedef:: cuOptLogCallback +.. doxygenfunction:: cuOptSetLogCallback + .. _parameter-constants: Parameter Constants @@ -194,6 +204,9 @@ These constants are used as parameter names in the :c:func:`cuOptSetParameter`, .. doxygendefine:: CUOPT_TIME_LIMIT .. doxygendefine:: CUOPT_PDLP_SOLVER_MODE .. doxygendefine:: CUOPT_METHOD +.. doxygendefine:: CUOPT_PRIMAL_SIMPLEX_PRICING +.. doxygendefine:: CUOPT_DUAL_SIMPLEX_INITIAL_PERTURBATION +.. doxygendefine:: CUOPT_DUAL_SIMPLEX_REMOVE_PERTURBATION .. doxygendefine:: CUOPT_PER_CONSTRAINT_RESIDUAL .. doxygendefine:: CUOPT_SAVE_BEST_PRIMAL_SO_FAR .. doxygendefine:: CUOPT_FIRST_PRIMAL_FEASIBLE @@ -210,6 +223,12 @@ These constants are used as parameter names in the :c:func:`cuOptSetParameter`, .. doxygendefine:: CUOPT_BARRIER_DUAL_INITIAL_POINT .. doxygendefine:: CUOPT_BARRIER_ITERATIVE_REFINEMENT .. doxygendefine:: CUOPT_BARRIER_STEP_SCALE +.. doxygendefine:: CUOPT_BARRIER_ADAPTIVE_REGULARIZATION +.. doxygendefine:: CUOPT_BARRIER_PRESOLVE_BOUND_FREE_VARIABLES +.. doxygendefine:: CUOPT_BARRIER_PRIMAL_REGULARIZATION +.. doxygendefine:: CUOPT_BARRIER_DUAL_REGULARIZATION +.. doxygendefine:: CUOPT_BARRIER_INITIAL_POINT_SAFEGUARD +.. doxygendefine:: CUOPT_SEQUENCE_SOLVE .. doxygendefine:: CUOPT_DUAL_POSTSOLVE .. doxygendefine:: CUOPT_SOLUTION_FILE .. doxygendefine:: CUOPT_NUM_CPU_THREADS @@ -254,8 +273,32 @@ These constants are used to configure `CUOPT_METHOD` via :c:func:`cuOptSetIntege .. doxygendefine:: CUOPT_METHOD_PDLP .. doxygendefine:: CUOPT_METHOD_DUAL_SIMPLEX .. doxygendefine:: CUOPT_METHOD_BARRIER +.. doxygendefine:: CUOPT_METHOD_PRIMAL_SIMPLEX .. doxygendefine:: CUOPT_METHOD_UNSET +.. _barrier-dual-initial-point-constants: + +Barrier Dual Initial Point Constants +------------------------------------ + +These constants are used to configure `CUOPT_BARRIER_DUAL_INITIAL_POINT` via :c:func:`cuOptSetIntegerParameter`. + +.. doxygendefine:: CUOPT_BARRIER_DUAL_INITIAL_POINT_AUTOMATIC +.. doxygendefine:: CUOPT_BARRIER_DUAL_INITIAL_POINT_LUSTIG_MARSTEN_SHANNO +.. doxygendefine:: CUOPT_BARRIER_DUAL_INITIAL_POINT_LEAST_SQUARES +.. doxygendefine:: CUOPT_BARRIER_DUAL_INITIAL_POINT_SEDUMI_MU + +.. _multigpu-pdlp-partitioner-constants: + +Multi-GPU PDLP Partitioner Constants +------------------------------------ + +These constants are used to configure `CUOPT_MULTIGPU_PDLP_PARTITIONER` via :c:func:`cuOptSetIntegerParameter`. + +.. doxygendefine:: CUOPT_MULTIGPU_PDLP_PARTITIONER_AUTO +.. doxygendefine:: CUOPT_MULTIGPU_PDLP_PARTITIONER_KAMINPAR +.. doxygendefine:: CUOPT_MULTIGPU_PDLP_PARTITIONER_ROUND_ROBIN + .. _barrier-iterative-refinement-constants: Barrier Iterative Refinement Constants diff --git a/docs/cuopt/source/cuopt-c/convex/convex-examples.rst b/docs/cuopt/source/cuopt-c/convex/convex-examples.rst index 70211660a5..6df2a9e267 100644 --- a/docs/cuopt/source/cuopt-c/convex/convex-examples.rst +++ b/docs/cuopt/source/cuopt-c/convex/convex-examples.rst @@ -466,3 +466,23 @@ output below, ``x1..x5`` are ``a, b, s, p, q`` in column order: x5 = 1.414214 Solver completed successfully! + + +Solving an LP on Multiple GPUs +------------------------------ + +Multi-GPU PDLP shards an LP across GPUs. Set the method to PDLP and ``CUOPT_NUM_GPUS`` to ``-1`` (all visible GPUs) or to a value greater than 1 before calling ``cuOptSolve``. This helps most on large LPs, or LPs that do not fit in the memory of a single GPU. It is not supported for QP, QCQP or SOCP problems, and it needs at least 2 visible GPUs to spread the work. Add the following to the LP example above, after creating the solver settings: + +.. code-block:: c + + // Use PDLP and all GPUs visible to the process + status = cuOptSetIntegerParameter(settings, CUOPT_METHOD, CUOPT_METHOD_PDLP); + status = cuOptSetIntegerParameter(settings, CUOPT_NUM_GPUS, -1); + + // Optional: how the problem is split across GPUs + // (CUOPT_MULTIGPU_PDLP_PARTITIONER_AUTO, _KAMINPAR or _ROUND_ROBIN) + status = cuOptSetIntegerParameter(settings, + CUOPT_MULTIGPU_PDLP_PARTITIONER, + CUOPT_MULTIGPU_PDLP_PARTITIONER_AUTO); + +Check ``status`` against ``CUOPT_SUCCESS`` after each call, as the example above does. diff --git a/docs/cuopt/source/cuopt-c/mip/mip-c-api.rst b/docs/cuopt/source/cuopt-c/mip/mip-c-api.rst index 85592bb766..6b7f99bb7c 100644 --- a/docs/cuopt/source/cuopt-c/mip/mip-c-api.rst +++ b/docs/cuopt/source/cuopt-c/mip/mip-c-api.rst @@ -63,6 +63,11 @@ These constants configure MIP-specific solver behavior. Use them with :c:func:`c .. doxygendefine:: CUOPT_MIP_BATCH_PDLP_RELIABILITY_BRANCHING .. doxygendefine:: CUOPT_MIP_STRONG_BRANCHING_SIMPLEX_ITERATION_LIMIT .. doxygendefine:: CUOPT_MIP_SEMICONTINUOUS_BIG_M +.. doxygendefine:: CUOPT_MIP_RENS +.. doxygendefine:: CUOPT_MIP_MUTATION +.. doxygendefine:: CUOPT_MIP_PRIMAL_DEGENERATE_PIVOTS +.. doxygendefine:: CUOPT_MIP_DUAL_DEGENERATE_PIVOTS +.. doxygendefine:: CUOPT_MIP_DUAL_DEGENERATE_FEASIBILITY_PUMP .. _mip-determinism-mode-constants: diff --git a/docs/cuopt/source/cuopt-cli/cli-examples.rst b/docs/cuopt/source/cuopt-cli/cli-examples.rst index 62e794285b..12cd128779 100644 --- a/docs/cuopt/source/cuopt-cli/cli-examples.rst +++ b/docs/cuopt/source/cuopt-cli/cli-examples.rst @@ -105,3 +105,15 @@ You can customize the solver behavior using various command line parameters. Her .. literalinclude:: examples/lp/examples/solver_parameters_example.sh :language: bash :linenos: + + +Solving an LP on Multiple GPUs +############################## + +Multi-GPU PDLP shards an LP across GPUs. Select it with ``--method 1`` (PDLP) and set ``--num-gpus`` to ``-1`` (all visible GPUs) or to a value greater than 1. ``--multigpu-pdlp-partitioner`` chooses how the problem is split (``0`` auto, ``1`` KaMinPar, ``2`` round robin). Multi-GPU PDLP supports LPs only, and the number of GPUs cannot exceed the number of visible CUDA devices. + +:download:`multi_gpu_pdlp_example.sh ` + +.. literalinclude:: examples/lp/examples/multi_gpu_pdlp_example.sh + :language: bash + :linenos: diff --git a/docs/cuopt/source/cuopt-cli/examples/lp/examples/multi_gpu_pdlp_example.sh b/docs/cuopt/source/cuopt-cli/examples/lp/examples/multi_gpu_pdlp_example.sh new file mode 100755 index 0000000000..197545f453 --- /dev/null +++ b/docs/cuopt/source/cuopt-cli/examples/lp/examples/multi_gpu_pdlp_example.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# TEST_SKIP: requires multiple GPUs +# +# Multi-GPU PDLP Example using cuopt_cli +# +# This example shows how to shard an LP across several GPUs with PDLP. +# Multi-GPU PDLP is selected by --method 1 (PDLP) together with --num-gpus set +# to -1 (all visible GPUs) or to a value greater than 1. +# +# Requirements: +# - cuopt_cli installed and available in PATH +# - At least 2 visible GPUs +# - An LP in LP or MPS format (multi-GPU PDLP only supports LPs, and helps +# most on large problems; the tiny model below only illustrates the options) +# + +# Create a sample LP file +cat > sample.lp << 'LP' +Minimize + -0.2 VAR1 + 0.1 VAR2 +Subject To + ROW1: 3 VAR1 + 4 VAR2 <= 5.4 + ROW2: 2.7 VAR1 + 10.1 VAR2 <= 4.9 +End +LP + +echo "=== Example 1: Use all visible GPUs ===" +cuopt_cli --method 1 --num-gpus -1 sample.lp + +echo "" +echo "=== Example 2: Use exactly 2 GPUs ===" +cuopt_cli --method 1 --num-gpus 2 sample.lp + +echo "" +echo "=== Example 3: Choose how the problem is split across GPUs ===" +# 0 = auto (default), 1 = KaMinPar, 2 = round robin +cuopt_cli --method 1 --num-gpus -1 --multigpu-pdlp-partitioner 2 sample.lp + +# Clean up +rm -f sample.lp diff --git a/docs/cuopt/source/cuopt-grpc/api.rst b/docs/cuopt/source/cuopt-grpc/api.rst index 82954b37ef..73a5773bad 100644 --- a/docs/cuopt/source/cuopt-grpc/api.rst +++ b/docs/cuopt/source/cuopt-grpc/api.rst @@ -6,12 +6,29 @@ gRPC API (Reference) ====================== -The **CuOptRemoteService** gRPC API is defined in Protocol Buffers under the ``cuopt.remote`` package. Source files in the repository: +The **CuOptRemoteService** gRPC API is defined in Protocol Buffers under the ``cuopt.remote`` package: -* ``cpp/src/grpc/cuopt_remote_service.proto`` — service and job/chunk/log RPCs -* ``cpp/src/grpc/cuopt_remote.proto`` — LP/MIP problem, settings, and result messages -* ``cpp/src/grpc/routing/cuopt_routing.proto`` — VRP request messages -* ``cpp/src/grpc/routing/cuopt_routing_solution.proto`` — VRP result messages +* :download:`cuopt_remote_service.proto ` — service and job/chunk/log RPCs +* :download:`cuopt_remote.proto ` — LP/MIP problem, settings, and result messages +* :download:`cuopt_remote_data.proto ` — problem and result fields, including the array field ids used by chunked transfer. Generated from ``cpp/src/grpc/codegen/field_registry.yaml`` and committed to the repository. +* :download:`cuopt_routing.proto ` — VRP request messages +* :download:`cuopt_routing_solution.proto ` — VRP result messages + +Download all five as :download:`cuopt-protos.zip `. They import each other by file name, so keep them in one directory. + +The ``libcuopt-client`` wheel and conda package install the same five files: + +* pip: ``/libcuopt_client/share/cuopt/proto`` +* conda: ``$CONDA_PREFIX/share/cuopt/proto`` + +Generate stubs for your language with that directory as the include path, for example for Python: + +.. code-block:: bash + + python -m grpc_tools.protoc -I "$PROTO_DIR" --python_out=. --grpc_python_out=. \ + "$PROTO_DIR"/*.proto + +The same files are in the repository under ``cpp/src/grpc/``, ``cpp/src/grpc/routing/`` and ``cpp/src/grpc/codegen/generated/``. The chunked-transfer wire format is described in `GRPC_INTERFACE.md `_. Most users do **not** call these RPCs directly: diff --git a/docs/cuopt/source/cuopt-python/convex/convex-examples.rst b/docs/cuopt/source/cuopt-python/convex/convex-examples.rst index eacdc03bff..f7715db530 100644 --- a/docs/cuopt/source/cuopt-python/convex/convex-examples.rst +++ b/docs/cuopt/source/cuopt-python/convex/convex-examples.rst @@ -263,3 +263,14 @@ The response is as follows: x = 25.001763214569394 y = 0.0 Objective value = 50.00352642913879 + +Solving an LP on Multiple GPUs +------------------------------ + +Multi-GPU PDLP shards an LP across GPUs. Set the method to PDLP and ``CUOPT_NUM_GPUS`` to ``-1`` (all visible GPUs) or to a value greater than 1. This helps most on large LPs, or LPs that do not fit in the memory of a single GPU. It is not supported for QP, QCQP or SOCP problems. + +:download:`multi_gpu_pdlp_example.py ` + +.. literalinclude:: examples/multi_gpu_pdlp_example.py + :language: python + :linenos: diff --git a/docs/cuopt/source/cuopt-python/convex/examples/multi_gpu_pdlp_example.py b/docs/cuopt/source/cuopt-python/convex/examples/multi_gpu_pdlp_example.py new file mode 100644 index 0000000000..dd4158b828 --- /dev/null +++ b/docs/cuopt/source/cuopt-python/convex/examples/multi_gpu_pdlp_example.py @@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# TEST_SKIP: requires multiple GPUs + +""" +Multi-GPU PDLP Example + +This example demonstrates: +- Selecting the PDLP method +- Using all visible GPUs (num_gpus = -1) or a fixed number of GPUs +- Choosing how the problem is partitioned across GPUs + +Multi-GPU PDLP shards the problem across GPUs. It helps most on large LPs, +or LPs that do not fit in the memory of a single GPU. The small model below +only illustrates the settings. Multi-GPU PDLP supports LPs only, and needs at +least 2 visible GPUs. + +Problem: + Maximize: 2*x + y + Subject to: + 4*x + 10*y <= 130 + 8*x - 3*y >= 40 + x, y >= 0 +""" + +from cuopt.linear_programming.problem import Problem, CONTINUOUS, MAXIMIZE +from cuopt.linear_programming.solver.solver_parameters import ( + CUOPT_METHOD, + CUOPT_NUM_GPUS, + CUOPT_MULTIGPU_PDLP_PARTITIONER, +) +from cuopt.linear_programming.solver_settings import ( + SolverSettings, + SolverMethod, +) + + +def main(): + """Run the multi-GPU PDLP example.""" + problem = Problem("Simple LP") + + x = problem.addVariable(lb=0, vtype=CONTINUOUS, name="x") + y = problem.addVariable(lb=0, vtype=CONTINUOUS, name="y") + + problem.addConstraint(4 * x + 10 * y <= 130, name="c1") + problem.addConstraint(8 * x - 3 * y >= 40, name="c2") + + problem.setObjective(2 * x + y, sense=MAXIMIZE) + + settings = SolverSettings() + # Multi-GPU PDLP needs the PDLP method + settings.set_parameter(CUOPT_METHOD, SolverMethod.PDLP) + # -1 uses all GPUs visible to the process; a value > 1 uses that many + settings.set_parameter(CUOPT_NUM_GPUS, -1) + # How to split the problem: 0 = auto (default), 1 = KaMinPar, + # 2 = round robin + settings.set_parameter(CUOPT_MULTIGPU_PDLP_PARTITIONER, 0) + + problem.solve(settings) + + print(f"Status: {problem.Status.name}") + print(f"Solved in {problem.SolveTime:.4f} seconds") + print(f"x = {x.getValue()}, y = {y.getValue()}") + print(f"Objective value = {problem.ObjValue}") + + +if __name__ == "__main__": + main() diff --git a/docs/cuopt/source/mip-settings.rst b/docs/cuopt/source/mip-settings.rst index d2ff84be53..416ef2b89f 100644 --- a/docs/cuopt/source/mip-settings.rst +++ b/docs/cuopt/source/mip-settings.rst @@ -85,25 +85,6 @@ under active development. We now describe parameter settings for the MIP solver. - -Heuristics Only -^^^^^^^^^^^^^^^ - -``CUOPT_MIP_HEURISTICS_ONLY`` controls if only the GPU heuristics should be run for the MIP problem. When set to true, only the primal -bound is improved via the GPU. When set to false, both the GPU and CPU are used and -the dual bound is improved on the CPU. - -.. note:: The default value is false. - -Scaling -^^^^^^^ - -``CUOPT_MIP_SCALING`` controls if scaling should be applied to the MIP problem. - -* ``0``: Scaling is off. -* ``1``: Scaling is on. -* ``2``: Scaling is not applied to the objective (default). - Absolute Tolerance ^^^^^^^^^^^^^^^^^^ @@ -154,6 +135,23 @@ gap is infinity. .. note:: The default value is ``1e-4``. +Heuristics Only +^^^^^^^^^^^^^^^ + +``CUOPT_MIP_HEURISTICS_ONLY`` controls if only the GPU heuristics should be run for the MIP problem. When set to true, only the primal +bound is improved via the GPU. When set to false, both the GPU and CPU are used and the dual bound is improved on the CPU. + +.. note:: The default value is false. + +Scaling +^^^^^^^ + +``CUOPT_MIP_SCALING`` controls if scaling should be applied to the MIP problem. + +* ``0``: Scaling is off. +* ``1``: Scaling is on. +* ``2``: Scaling is not applied to the objective (default). + Node Limit ^^^^^^^^^^ @@ -209,6 +207,46 @@ Set this value to 0 to disable knapsack cuts. .. note:: The default value is ``-1`` (automatic). +Flow Cover Cuts +^^^^^^^^^^^^^^^^ + +``CUOPT_MIP_FLOW_COVER_CUTS`` controls whether to use flow cover cuts. +Set this value to ``-1`` (automatic) to let the solver decide. +Set this value to ``0`` to disable flow cover cuts. +Set this value to ``1`` to enable flow cover cuts. + +.. note:: The default value is ``-1`` (automatic). + +Implied Bound Cuts +^^^^^^^^^^^^^^^^^^^ + +``CUOPT_MIP_IMPLIED_BOUND_CUTS`` controls whether to use implied bound cuts. +Set this value to ``-1`` (automatic) to let the solver decide. +Set this value to ``0`` to disable implied bound cuts. +Set this value to ``1`` to enable implied bound cuts. + +.. note:: The default value is ``-1`` (automatic). + +Clique Cuts +^^^^^^^^^^^^ + +``CUOPT_MIP_CLIQUE_CUTS`` controls whether to use clique cuts. +Set this value to ``-1`` (automatic) to let the solver decide. +Set this value to ``0`` to disable clique cuts. +Set this value to ``1`` to enable clique cuts. + +.. note:: The default value is ``-1`` (automatic). + +Zero-Half Cuts +^^^^^^^^^^^^^^ + +``CUOPT_MIP_ZERO_HALF_CUTS`` controls whether to use zero-half cuts. +Set this value to ``-1`` (automatic) to let the solver decide. +Set this value to ``0`` to disable zero-half cuts. +Set this value to ``1`` to enable zero-half cuts. + +.. note:: The default value is ``-1`` (automatic). + Cut Change Threshold ^^^^^^^^^^^^^^^^^^^^ @@ -302,45 +340,6 @@ MIP Symmetry .. note:: The default value is ``-1`` (automatic). -Flow Cover Cuts -^^^^^^^^^^^^^^^^ - -``CUOPT_MIP_FLOW_COVER_CUTS`` controls whether to use flow cover cuts. -Set this value to ``-1`` (automatic) to let the solver decide. -Set this value to ``0`` to disable flow cover cuts. -Set this value to ``1`` to enable flow cover cuts. - -.. note:: The default value is ``-1`` (automatic). - -Implied Bound Cuts -^^^^^^^^^^^^^^^^^^^ - -``CUOPT_MIP_IMPLIED_BOUND_CUTS`` controls whether to use implied bound cuts. -Set this value to ``-1`` (automatic) to let the solver decide. -Set this value to ``0`` to disable implied bound cuts. -Set this value to ``1`` to enable implied bound cuts. - -.. note:: The default value is ``-1`` (automatic). - -Clique Cuts -^^^^^^^^^^^^ - -``CUOPT_MIP_CLIQUE_CUTS`` controls whether to use clique cuts. -Set this value to ``-1`` (automatic) to let the solver decide. -Set this value to ``0`` to disable clique cuts. -Set this value to ``1`` to enable clique cuts. - -.. note:: The default value is ``-1`` (automatic). - -Zero-Half Cuts -^^^^^^^^^^^^^^ - -``CUOPT_MIP_ZERO_HALF_CUTS`` controls whether to use zero-half cuts. -Set this value to ``-1`` (automatic) to let the solver decide. -Set this value to ``0`` to disable zero-half cuts. -Set this value to ``1`` to enable zero-half cuts. - -.. note:: The default value is ``-1`` (automatic). Objective Step ^^^^^^^^^^^^^^^ @@ -361,6 +360,58 @@ Set this to a positive value that is at least as large as the upper bound of any .. note:: By default cuOpt derives the Big-M from the variable's upper bound. +RENS +^^^^ + +``CUOPT_MIP_RENS`` controls whether the RENS (Relaxation Enforced Neighborhood Search) heuristic is used. RENS builds a sub-MIP from the solution of the LP relaxation: +integer variables that already take integral values in the relaxation are fixed, and the remaining integer variables are restricted to their neighboring integer values. +The sub-MIP is then solved to look for improved feasible solutions. +The default value of ``-1`` (automatic) means that the solver will decide whether to use RENS. +Set this value to 0 to disable RENS. +Set this value to 1 to enable RENS. + +.. note:: The default value is ``-1`` (automatic). + +Mutation +^^^^^^^^ + +``CUOPT_MIP_MUTATION`` controls whether the mutation heuristic is used. Mutation fixes a random subset of the integer variables to their values in the current incumbent +and solves the resulting sub-MIP. It only runs once an incumbent solution is available. +The default value of ``-1`` (automatic) means that the solver will decide whether to use mutation. +Set this value to 0 to disable mutation. +Set this value to 1 to enable mutation. + +.. note:: The default value is ``-1`` (automatic). + +Primal Degenerate Pivots +^^^^^^^^^^^^^^^^^^^^^^^^ + +``CUOPT_MIP_PRIMAL_DEGENERATE_PIVOTS`` controls whether primal degenerate pivots are performed to improve reduced cost strengthening. These pivots attempt to move +basic integer variables on their bound out of the basis. This can lead to more reduced cost bound strengthening. This setting only has an affect when +``CUOPT_REDUCED_COST_STRENGTHENING`` is enabled. +The default value of ``-1`` (automatic) means the solver will decide whether to do primal degenerate pivots. +Set this value to 0 to disable primal degenerate pivots. +Set this value to 1 to enable primal degenerate pivots. + +Dual Degenerate Pivots +^^^^^^^^^^^^^^^^^^^^^^ +``CUOPT_MIP_DUAL_DEGENERATE_PIVOTS`` controls whether dual degenerate pivots are performed. These pivots attempt to remove fractional integer variables from the basis. +This can lead to less integer infeasibilities. +The default value of ``-1`` (automatic) means the solver will decide whether to do dual degenerate pivots. +Set this value to 0 to disable dual degenerate pivots. +Set this value to 1 to enable dual degenerate pivots at the root node. +Set this value to 2 to enable dual degenerate pivots at all branch and bound nodes. + +Dual Degenerate Feasibility Pump +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +``CUOPT_MIP_DUAL_DEGENERATE_FEASIBILITY_PUMP`` controls whether the dual degenerate feasibility pump is run. If the solution of the root relaxation is dual degenerate, +an auxillarly LP is constructed that is restricted to the optimal face; the feasibility pump is used to alter the objective of the LP to attempt to reduce the number of integer infeasibilities +in the relaxation solution. This LP is solved with the primal simplex method. +The default value of ``-1`` (automatic) means the solver will decide whether to run the dual degenerate feasibility pump. +Set this value to 0 to disable the dual degenerate feasibility pump. +Set this value to 1 to enable the dual degenerate feasibility pump. + + Work Limit ^^^^^^^^^^