From dddf42dcb64645eea9695a999b62425443a10aad Mon Sep 17 00:00:00 2001
From: Alice Boucher <160623740+aliceb-nv@users.noreply.github.com>
Date: Thu, 11 Dec 2025 17:52:36 +0100
Subject: [PATCH 1/3] CI crash fixes (#691)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary by CodeRabbit
## Release Notes
* **Performance**
* Optimized branch-and-bound algorithm with improved search termination conditions
* **Improvements**
* Enhanced concurrency control mechanisms across solver components
* Improved logger initialization and lifecycle management for better resource handling
✏️ Tip: You can customize this high-level summary in your review settings.
Authors:
- Alice Boucher (https://github.com/aliceb-nv)
Approvers:
- Nicolas Blin (https://github.com/Kh4ster)
URL: https://github.com/NVIDIA/cuopt/pull/691
---
.../pdlp/solver_settings.hpp | 2 +-
cpp/src/dual_simplex/branch_and_bound.cpp | 5 ++++
cpp/src/dual_simplex/branch_and_bound.hpp | 4 +--
.../dual_simplex/simplex_solver_settings.hpp | 4 +--
cpp/src/linear_programming/solve.cu | 2 +-
cpp/src/mip/diversity/diversity_manager.cuh | 2 +-
cpp/src/mip/relaxed_lp/relaxed_lp.cuh | 16 ++++++------
cpp/src/utilities/logger.cpp | 26 ++++++++++++++++---
cpp/src/utilities/logger.hpp | 6 +++--
9 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp b/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp
index ea697e1e10..76388504e0 100644
--- a/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp
+++ b/cpp/include/cuopt/linear_programming/pdlp/solver_settings.hpp
@@ -212,7 +212,7 @@ class pdlp_solver_settings_t {
method_t method{method_t::Concurrent};
bool inside_mip{false};
// For concurrent termination
- volatile int* concurrent_halt{nullptr};
+ std::atomic* concurrent_halt{nullptr};
static constexpr f_t minimal_absolute_tolerance = 1.0e-12;
private:
diff --git a/cpp/src/dual_simplex/branch_and_bound.cpp b/cpp/src/dual_simplex/branch_and_bound.cpp
index 77acca8f7d..6161f4d3fb 100644
--- a/cpp/src/dual_simplex/branch_and_bound.cpp
+++ b/cpp/src/dual_simplex/branch_and_bound.cpp
@@ -1135,6 +1135,7 @@ void branch_and_bound_t::diving_thread(const csr_matrix_t& A
if (get_upper_bound() < start_node->node.lower_bound) { continue; }
bool recompute_bounds_and_basis = true;
+ i_t nodes_explored = 0;
search_tree_t subtree(std::move(start_node->node));
std::deque*> stack;
stack.push_front(&subtree.root);
@@ -1152,6 +1153,8 @@ void branch_and_bound_t::diving_thread(const csr_matrix_t& A
if (toc(exploration_stats_.start_time) > settings_.time_limit) { return; }
+ if (nodes_explored >= 1000) { break; }
+
node_solve_info_t status = solve_node(node_ptr,
subtree,
leaf_problem,
@@ -1165,6 +1168,8 @@ void branch_and_bound_t::diving_thread(const csr_matrix_t& A
start_node->upper,
log);
+ nodes_explored++;
+
recompute_bounds_and_basis = !has_children(status);
if (status == node_solve_info_t::TIME_LIMIT) {
diff --git a/cpp/src/dual_simplex/branch_and_bound.hpp b/cpp/src/dual_simplex/branch_and_bound.hpp
index 7891711f75..38438cc9eb 100644
--- a/cpp/src/dual_simplex/branch_and_bound.hpp
+++ b/cpp/src/dual_simplex/branch_and_bound.hpp
@@ -113,7 +113,7 @@ class branch_and_bound_t {
f_t get_lower_bound();
i_t get_heap_size();
bool enable_concurrent_lp_root_solve() const { return enable_concurrent_lp_root_solve_; }
- volatile int* get_root_concurrent_halt() { return &root_concurrent_halt_; }
+ std::atomic* get_root_concurrent_halt() { return &root_concurrent_halt_; }
void set_root_concurrent_halt(int value) { root_concurrent_halt_ = value; }
lp_status_t solve_root_relaxation(simplex_solver_settings_t const& lp_settings);
@@ -170,7 +170,7 @@ class branch_and_bound_t {
std::vector edge_norms_;
std::atomic root_crossover_solution_set_{false};
bool enable_concurrent_lp_root_solve_{false};
- volatile int root_concurrent_halt_{0};
+ std::atomic root_concurrent_halt_{0};
// Pseudocosts
pseudo_costs_t pc_;
diff --git a/cpp/src/dual_simplex/simplex_solver_settings.hpp b/cpp/src/dual_simplex/simplex_solver_settings.hpp
index 98be9d4cbe..a1cc049e71 100644
--- a/cpp/src/dual_simplex/simplex_solver_settings.hpp
+++ b/cpp/src/dual_simplex/simplex_solver_settings.hpp
@@ -145,8 +145,8 @@ struct simplex_solver_settings_t {
std::function heuristic_preemption_callback;
std::function&, std::vector&, f_t)> set_simplex_solution_callback;
mutable logger_t log;
- volatile int* concurrent_halt; // if nullptr ignored, if !nullptr, 0 if solver should
- // continue, 1 if solver should halt
+ std::atomic* concurrent_halt; // if nullptr ignored, if !nullptr, 0 if solver should
+ // continue, 1 if solver should halt
};
} // namespace cuopt::linear_programming::dual_simplex
diff --git a/cpp/src/linear_programming/solve.cu b/cpp/src/linear_programming/solve.cu
index ed141a0c43..ab418bf5a9 100644
--- a/cpp/src/linear_programming/solve.cu
+++ b/cpp/src/linear_programming/solve.cu
@@ -306,7 +306,7 @@ void setup_device_symbols(rmm::cuda_stream_view stream_view)
detail::set_pdlp_hyper_parameters(stream_view);
}
-volatile int global_concurrent_halt;
+std::atomic global_concurrent_halt{0};
template
optimization_problem_solution_t convert_dual_simplex_sol(
diff --git a/cpp/src/mip/diversity/diversity_manager.cuh b/cpp/src/mip/diversity/diversity_manager.cuh
index 4a78f6cff7..9f3b4c90f0 100644
--- a/cpp/src/mip/diversity/diversity_manager.cuh
+++ b/cpp/src/mip/diversity/diversity_manager.cuh
@@ -95,7 +95,7 @@ class diversity_manager_t {
// mutex for the simplex solution update
std::mutex relaxed_solution_mutex;
// atomic for signalling pdlp to stop
- volatile int global_concurrent_halt{0};
+ std::atomic global_concurrent_halt{0};
rins_t rins;
diff --git a/cpp/src/mip/relaxed_lp/relaxed_lp.cuh b/cpp/src/mip/relaxed_lp/relaxed_lp.cuh
index 01931a3dde..0094f5982d 100644
--- a/cpp/src/mip/relaxed_lp/relaxed_lp.cuh
+++ b/cpp/src/mip/relaxed_lp/relaxed_lp.cuh
@@ -17,14 +17,14 @@
namespace cuopt::linear_programming::detail {
struct relaxed_lp_settings_t {
- double tolerance = 1e-4;
- double time_limit = 1.0;
- bool check_infeasibility = true;
- bool return_first_feasible = false;
- bool save_state = true;
- bool per_constraint_residual = true;
- bool has_initial_primal = true;
- volatile int* concurrent_halt = nullptr;
+ double tolerance = 1e-4;
+ double time_limit = 1.0;
+ bool check_infeasibility = true;
+ bool return_first_feasible = false;
+ bool save_state = true;
+ bool per_constraint_residual = true;
+ bool has_initial_primal = true;
+ std::atomic* concurrent_halt = nullptr;
};
template
diff --git a/cpp/src/utilities/logger.cpp b/cpp/src/utilities/logger.cpp
index a16c49c113..217f9c64cb 100644
--- a/cpp/src/utilities/logger.cpp
+++ b/cpp/src/utilities/logger.cpp
@@ -137,9 +137,26 @@ void reset_default_logger()
default_logger().flush_on(rapids_logger::level_enum::debug);
}
+// Guard object whose destructor resets the logger
+struct logger_config_guard {
+ ~logger_config_guard() { cuopt::reset_default_logger(); }
+};
+
+// Weak reference to detect if any init_logger_t instance is still alive
+static std::weak_ptr g_active_guard;
+static std::mutex g_guard_mutex;
+
init_logger_t::init_logger_t(std::string log_file, bool log_to_console)
{
- // until this function is called, the default sink is the buffer sink
+ std::lock_guard lock(g_guard_mutex);
+
+ auto existing_guard = g_active_guard.lock();
+ if (existing_guard) {
+ // Reuse existing configuration, just hold a reference to keep it alive
+ guard_ = existing_guard;
+ return;
+ }
+
cuopt::default_logger().sinks().clear();
// re-initialize sinks
@@ -164,8 +181,11 @@ init_logger_t::init_logger_t(std::string log_file, bool log_to_console)
for (const auto& entry : buffered_messages) {
cuopt::default_logger().log(entry.level, entry.msg.c_str());
}
-}
-init_logger_t::~init_logger_t() { cuopt::reset_default_logger(); }
+ // Create guard and store weak reference for future instances to find
+ auto guard = std::make_shared();
+ g_active_guard = guard;
+ guard_ = guard;
+}
} // namespace cuopt
diff --git a/cpp/src/utilities/logger.hpp b/cpp/src/utilities/logger.hpp
index 13c5e36e3f..08556a4c78 100644
--- a/cpp/src/utilities/logger.hpp
+++ b/cpp/src/utilities/logger.hpp
@@ -33,11 +33,13 @@ rapids_logger::logger& default_logger();
*/
void reset_default_logger();
+// Ref-counted logger initializer
class init_logger_t {
+ // Using shared_ptr for ref-counting
+ std::shared_ptr guard_;
+
public:
init_logger_t(std::string log_file, bool log_to_console);
-
- ~init_logger_t();
};
} // namespace cuopt
From d97ff6b4762f9df4459534ccf56d70c8e172bc81 Mon Sep 17 00:00:00 2001
From: Jake Awe
Date: Thu, 11 Dec 2025 13:28:18 -0600
Subject: [PATCH 2/3] REL v25.12.00 release
---
.pre-commit-config.yaml | 9 ++-
.../all_cuda-129_arch-aarch64.yaml | 14 ++---
.../all_cuda-129_arch-x86_64.yaml | 14 ++---
.../all_cuda-130_arch-aarch64.yaml | 14 ++---
.../all_cuda-130_arch-x86_64.yaml | 14 ++---
dependencies.yaml | 58 +++++++++----------
.../cuopt/linear_programming/pyproject.toml | 6 +-
python/cuopt/pyproject.toml | 26 ++++-----
python/cuopt_self_hosted/pyproject.toml | 2 +-
python/cuopt_server/pyproject.toml | 2 +-
python/libcuopt/pyproject.toml | 12 ++--
11 files changed, 87 insertions(+), 84 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 799eb291f8..447b03a32c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -56,6 +56,11 @@ repos:
- repo: https://github.com/rapidsai/pre-commit-hooks
rev: v1.2.1
hooks:
+ - id: verify-alpha-spec
+ args:
+ - --fix
+ - --mode
+ - release
- id: verify-copyright
args: [--fix, --spdx]
files: |
@@ -83,7 +88,5 @@ repos:
entry: python ci/utils/update_doc_versions.py
language: system
files: docs/cuopt/source/versions1.json
-
-
default_language_version:
- python: python3
+ python: python3
diff --git a/conda/environments/all_cuda-129_arch-aarch64.yaml b/conda/environments/all_cuda-129_arch-aarch64.yaml
index 59d6b43c0d..7a4a54a1d9 100644
--- a/conda/environments/all_cuda-129_arch-aarch64.yaml
+++ b/conda/environments/all_cuda-129_arch-aarch64.yaml
@@ -19,7 +19,7 @@ dependencies:
- cuda-python>=12.9.2,<13.0a0
- cuda-sanitizer-api
- cuda-version=12.9
-- cudf==25.12.*,>=0.0.0a0
+- cudf==25.12.*
- cupy>=13.6.0
- cxx-compiler
- cython>=3.0.3
@@ -35,8 +35,8 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
-- libraft-headers==25.12.*,>=0.0.0a0
-- librmm==25.12.*,>=0.0.0a0
+- libraft-headers==25.12.*
+- librmm==25.12.*
- make
- msgpack-numpy==0.4.8
- msgpack-python==1.1.0
@@ -53,16 +53,16 @@ dependencies:
- pip
- pre-commit
- psutil>=6.0.0
-- pylibraft==25.12.*,>=0.0.0a0
+- pylibraft==25.12.*
- pyrsistent
- pytest-cov
- pytest<8
- python>=3.10,<3.14
- rapids-build-backend>=0.4.0,<0.5.0.dev0
-- rapids-dask-dependency==25.12.*,>=0.0.0a0
-- rapids-logger==0.2.*,>=0.0.0a0
+- rapids-dask-dependency==25.12.*
+- rapids-logger==0.2.*
- requests
-- rmm==25.12.*,>=0.0.0a0
+- rmm==25.12.*
- scikit-build-core>=0.10.0
- sphinx
- sphinx-copybutton
diff --git a/conda/environments/all_cuda-129_arch-x86_64.yaml b/conda/environments/all_cuda-129_arch-x86_64.yaml
index 4aad50d006..6c5ae382e0 100644
--- a/conda/environments/all_cuda-129_arch-x86_64.yaml
+++ b/conda/environments/all_cuda-129_arch-x86_64.yaml
@@ -19,7 +19,7 @@ dependencies:
- cuda-python>=12.9.2,<13.0a0
- cuda-sanitizer-api
- cuda-version=12.9
-- cudf==25.12.*,>=0.0.0a0
+- cudf==25.12.*
- cupy>=13.6.0
- cxx-compiler
- cython>=3.0.3
@@ -35,8 +35,8 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
-- libraft-headers==25.12.*,>=0.0.0a0
-- librmm==25.12.*,>=0.0.0a0
+- libraft-headers==25.12.*
+- librmm==25.12.*
- make
- msgpack-numpy==0.4.8
- msgpack-python==1.1.0
@@ -53,16 +53,16 @@ dependencies:
- pip
- pre-commit
- psutil>=6.0.0
-- pylibraft==25.12.*,>=0.0.0a0
+- pylibraft==25.12.*
- pyrsistent
- pytest-cov
- pytest<8
- python>=3.10,<3.14
- rapids-build-backend>=0.4.0,<0.5.0.dev0
-- rapids-dask-dependency==25.12.*,>=0.0.0a0
-- rapids-logger==0.2.*,>=0.0.0a0
+- rapids-dask-dependency==25.12.*
+- rapids-logger==0.2.*
- requests
-- rmm==25.12.*,>=0.0.0a0
+- rmm==25.12.*
- scikit-build-core>=0.10.0
- sphinx
- sphinx-copybutton
diff --git a/conda/environments/all_cuda-130_arch-aarch64.yaml b/conda/environments/all_cuda-130_arch-aarch64.yaml
index 5adb8aeaef..82c250f017 100644
--- a/conda/environments/all_cuda-130_arch-aarch64.yaml
+++ b/conda/environments/all_cuda-130_arch-aarch64.yaml
@@ -19,7 +19,7 @@ dependencies:
- cuda-python>=13.0.1,<14.0a0
- cuda-sanitizer-api
- cuda-version=13.0
-- cudf==25.12.*,>=0.0.0a0
+- cudf==25.12.*
- cupy>=13.6.0
- cxx-compiler
- cython>=3.0.3
@@ -35,8 +35,8 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
-- libraft-headers==25.12.*,>=0.0.0a0
-- librmm==25.12.*,>=0.0.0a0
+- libraft-headers==25.12.*
+- librmm==25.12.*
- make
- msgpack-numpy==0.4.8
- msgpack-python==1.1.0
@@ -53,16 +53,16 @@ dependencies:
- pip
- pre-commit
- psutil>=6.0.0
-- pylibraft==25.12.*,>=0.0.0a0
+- pylibraft==25.12.*
- pyrsistent
- pytest-cov
- pytest<8
- python>=3.10,<3.14
- rapids-build-backend>=0.4.0,<0.5.0.dev0
-- rapids-dask-dependency==25.12.*,>=0.0.0a0
-- rapids-logger==0.2.*,>=0.0.0a0
+- rapids-dask-dependency==25.12.*
+- rapids-logger==0.2.*
- requests
-- rmm==25.12.*,>=0.0.0a0
+- rmm==25.12.*
- scikit-build-core>=0.10.0
- sphinx
- sphinx-copybutton
diff --git a/conda/environments/all_cuda-130_arch-x86_64.yaml b/conda/environments/all_cuda-130_arch-x86_64.yaml
index 11c24d5890..e89e322d6b 100644
--- a/conda/environments/all_cuda-130_arch-x86_64.yaml
+++ b/conda/environments/all_cuda-130_arch-x86_64.yaml
@@ -19,7 +19,7 @@ dependencies:
- cuda-python>=13.0.1,<14.0a0
- cuda-sanitizer-api
- cuda-version=13.0
-- cudf==25.12.*,>=0.0.0a0
+- cudf==25.12.*
- cupy>=13.6.0
- cxx-compiler
- cython>=3.0.3
@@ -35,8 +35,8 @@ dependencies:
- libcurand-dev
- libcusolver-dev
- libcusparse-dev
-- libraft-headers==25.12.*,>=0.0.0a0
-- librmm==25.12.*,>=0.0.0a0
+- libraft-headers==25.12.*
+- librmm==25.12.*
- make
- msgpack-numpy==0.4.8
- msgpack-python==1.1.0
@@ -53,16 +53,16 @@ dependencies:
- pip
- pre-commit
- psutil>=6.0.0
-- pylibraft==25.12.*,>=0.0.0a0
+- pylibraft==25.12.*
- pyrsistent
- pytest-cov
- pytest<8
- python>=3.10,<3.14
- rapids-build-backend>=0.4.0,<0.5.0.dev0
-- rapids-dask-dependency==25.12.*,>=0.0.0a0
-- rapids-logger==0.2.*,>=0.0.0a0
+- rapids-dask-dependency==25.12.*
+- rapids-logger==0.2.*
- requests
-- rmm==25.12.*,>=0.0.0a0
+- rmm==25.12.*
- scikit-build-core>=0.10.0
- sphinx
- sphinx-copybutton
diff --git a/dependencies.yaml b/dependencies.yaml
index 393b99293f..c46f11b742 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -297,8 +297,8 @@ dependencies:
packages:
- boost
- cpp-argparse
- - librmm==25.12.*,>=0.0.0a0
- - libraft-headers==25.12.*,>=0.0.0a0
+ - librmm==25.12.*
+ - libraft-headers==25.12.*
- tbb-devel
- zlib
- bzip2
@@ -313,7 +313,7 @@ dependencies:
common:
- output_types: [conda]
packages:
- - libcuopt-tests==25.12.*,>=0.0.0a0
+ - libcuopt-tests==25.12.*
build_wheels:
common:
- output_types: [requirements, pyproject]
@@ -350,7 +350,7 @@ dependencies:
packages:
- numba-cuda>=0.19.1,<0.20.0a0
- numba>=0.60.0
- - rapids-dask-dependency==25.12.*,>=0.0.0a0
+ - rapids-dask-dependency==25.12.*
- &pandas pandas>=2.0
- output_types: requirements
packages:
@@ -420,7 +420,7 @@ dependencies:
common:
- output_types: conda
packages:
- - &libcuopt_unsuffixed libcuopt==25.12.*,>=0.0.0a0
+ - &libcuopt_unsuffixed libcuopt==25.12.*
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
@@ -433,18 +433,18 @@ dependencies:
cuda: "12.*"
cuda_suffixed: "true"
packages:
- - libcuopt-cu12==25.12.*,>=0.0.0a0
+ - libcuopt-cu12==25.12.*
- matrix:
cuda: "13.*"
cuda_suffixed: "true"
packages:
- - libcuopt-cu13==25.12.*,>=0.0.0a0
+ - libcuopt-cu13==25.12.*
- {matrix: null, packages: [*libcuopt_unsuffixed]}
depends_on_cuopt:
common:
- output_types: conda
packages:
- - &cuopt_unsuffixed cuopt==25.12.*,>=0.0.0a0
+ - &cuopt_unsuffixed cuopt==25.12.*
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
@@ -457,18 +457,18 @@ dependencies:
cuda: "12.*"
cuda_suffixed: "true"
packages:
- - cuopt-cu12==25.12.*,>=0.0.0a0
+ - cuopt-cu12==25.12.*
- matrix:
cuda: "13.*"
cuda_suffixed: "true"
packages:
- - cuopt-cu13==25.12.*,>=0.0.0a0
+ - cuopt-cu13==25.12.*
- {matrix: null, packages: [*cuopt_unsuffixed]}
depends_on_cuopt_server:
common:
- output_types: conda
packages:
- - &cuopt_server_unsuffixed cuopt-server==25.12.*,>=0.0.0a0
+ - &cuopt_server_unsuffixed cuopt-server==25.12.*
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
@@ -481,18 +481,18 @@ dependencies:
cuda: "12.*"
cuda_suffixed: "true"
packages:
- - cuopt-server-cu12==25.12.*,>=0.0.0a0
+ - cuopt-server-cu12==25.12.*
- matrix:
cuda: "13.*"
cuda_suffixed: "true"
packages:
- - cuopt-server-cu13==25.12.*,>=0.0.0a0
+ - cuopt-server-cu13==25.12.*
- {matrix: null, packages: [*cuopt_server_unsuffixed]}
depends_on_cuopt_sh_client:
common:
- output_types: [conda, requirements, pyproject]
packages:
- - &cuopt_sh_client_unsuffixed cuopt-sh-client==25.12.*,>=0.0.0a0
+ - &cuopt_sh_client_unsuffixed cuopt-sh-client==25.12.*
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
@@ -502,7 +502,7 @@ dependencies:
common:
- output_types: [requirements, pyproject, conda]
packages:
- - cuopt-mps-parser==25.12.*,>=0.0.0a0
+ - cuopt-mps-parser==25.12.*
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
@@ -512,12 +512,12 @@ dependencies:
common:
- output_types: conda
packages:
- - libraft-headers==25.12.*,>=0.0.0a0
+ - libraft-headers==25.12.*
depends_on_librmm:
common:
- output_types: conda
packages:
- - &librmm_unsuffixed librmm==25.12.*,>=0.0.0a0
+ - &librmm_unsuffixed librmm==25.12.*
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
@@ -530,12 +530,12 @@ dependencies:
cuda: "12.*"
cuda_suffixed: "true"
packages:
- - librmm-cu12==25.12.*,>=0.0.0a0
+ - librmm-cu12==25.12.*
- matrix:
cuda: "13.*"
cuda_suffixed: "true"
packages:
- - librmm-cu13==25.12.*,>=0.0.0a0
+ - librmm-cu13==25.12.*
- {matrix: null, packages: [*librmm_unsuffixed]}
depends_on_cupy:
common:
@@ -560,7 +560,7 @@ dependencies:
common:
- output_types: [conda, requirements, pyproject]
packages:
- - rapids-logger==0.2.*,>=0.0.0a0
+ - rapids-logger==0.2.*
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
@@ -570,7 +570,7 @@ dependencies:
common:
- output_types: conda
packages:
- - &rmm_unsuffixed rmm==25.12.*,>=0.0.0a0
+ - &rmm_unsuffixed rmm==25.12.*
- output_types: requirements
packages:
# pip recognizes the index as a global option for the requirements.txt file
@@ -583,12 +583,12 @@ dependencies:
cuda: "12.*"
cuda_suffixed: "true"
packages:
- - rmm-cu12==25.12.*,>=0.0.0a0
+ - rmm-cu12==25.12.*
- matrix:
cuda: "13.*"
cuda_suffixed: "true"
packages:
- - rmm-cu13==25.12.*,>=0.0.0a0
+ - rmm-cu13==25.12.*
- matrix:
packages:
- *rmm_unsuffixed
@@ -597,7 +597,7 @@ dependencies:
common:
- output_types: conda
packages:
- - &cudf_unsuffixed cudf==25.12.*,>=0.0.0a0
+ - &cudf_unsuffixed cudf==25.12.*
- output_types: requirements
packages:
- --extra-index-url=https://pypi.nvidia.com
@@ -609,12 +609,12 @@ dependencies:
cuda: "12.*"
cuda_suffixed: "true"
packages:
- - cudf-cu12==25.12.*,>=0.0.0a0
+ - cudf-cu12==25.12.*
- matrix:
cuda: "13.*"
cuda_suffixed: "true"
packages:
- - cudf-cu13==25.12.*,>=0.0.0a0
+ - cudf-cu13==25.12.*
- matrix:
packages:
- *cudf_unsuffixed
@@ -623,7 +623,7 @@ dependencies:
common:
- output_types: conda
packages:
- - &pylibraft_unsuffixed pylibraft==25.12.*,>=0.0.0a0
+ - &pylibraft_unsuffixed pylibraft==25.12.*
- output_types: requirements
packages:
- --extra-index-url=https://pypi.nvidia.com
@@ -635,12 +635,12 @@ dependencies:
cuda: "12.*"
cuda_suffixed: "true"
packages:
- - pylibraft-cu12==25.12.*,>=0.0.0a0
+ - pylibraft-cu12==25.12.*
- matrix:
cuda: "13.*"
cuda_suffixed: "true"
packages:
- - pylibraft-cu13==25.12.*,>=0.0.0a0
+ - pylibraft-cu13==25.12.*
- matrix:
packages:
- *pylibraft_unsuffixed
diff --git a/python/cuopt/cuopt/linear_programming/pyproject.toml b/python/cuopt/cuopt/linear_programming/pyproject.toml
index c11cd3a580..24907d83f8 100644
--- a/python/cuopt/cuopt/linear_programming/pyproject.toml
+++ b/python/cuopt/cuopt/linear_programming/pyproject.toml
@@ -20,7 +20,7 @@ license = { text = "Apache-2.0" }
requires-python = ">=3.10"
dependencies = [
"numpy>=1.23.5,<3.0a0",
- "rapids-logger==0.2.*,>=0.0.0a0",
+ "rapids-logger==0.2.*",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../../../dependencies.yaml and run `rapids-dependency-file-generator`.
classifiers = [
"Intended Audience :: Developers",
@@ -39,7 +39,7 @@ Source = "https://github.com/nvidia/cuopt"
test = [
"pytest-cov",
"pytest<8",
- "rapids-logger==0.2.*,>=0.0.0a0",
+ "rapids-logger==0.2.*",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../../../dependencies.yaml and run `rapids-dependency-file-generator`.
[tool.setuptools]
@@ -83,5 +83,5 @@ requires = [
"cython>=3.0.3",
"ninja",
"numpy>=1.23.5,<3.0a0",
- "rapids-logger==0.2.*,>=0.0.0a0",
+ "rapids-logger==0.2.*",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../../../dependencies.yaml and run `rapids-dependency-file-generator`.
diff --git a/python/cuopt/pyproject.toml b/python/cuopt/pyproject.toml
index f3f2dbbf8d..f27e3f23a9 100644
--- a/python/cuopt/pyproject.toml
+++ b/python/cuopt/pyproject.toml
@@ -20,18 +20,18 @@ license = { text = "Apache-2.0" }
requires-python = ">=3.10"
dependencies = [
"cuda-python>=13.0.1,<14.0a0",
- "cudf==25.12.*,>=0.0.0a0",
- "cuopt-mps-parser==25.12.*,>=0.0.0a0",
+ "cudf==25.12.*",
+ "cuopt-mps-parser==25.12.*",
"cupy-cuda13x>=13.6.0",
- "libcuopt==25.12.*,>=0.0.0a0",
+ "libcuopt==25.12.*",
"numba-cuda>=0.19.1,<0.20.0a0",
"numba>=0.60.0",
"numpy>=1.23.5,<3.0a0",
"pandas>=2.0",
- "pylibraft==25.12.*,>=0.0.0a0",
- "rapids-dask-dependency==25.12.*,>=0.0.0a0",
- "rapids-logger==0.2.*,>=0.0.0a0",
- "rmm==25.12.*,>=0.0.0a0",
+ "pylibraft==25.12.*",
+ "rapids-dask-dependency==25.12.*",
+ "rapids-logger==0.2.*",
+ "rmm==25.12.*",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`.
classifiers = [
"Intended Audience :: Developers",
@@ -48,7 +48,7 @@ test = [
"numpy>=1.23.5,<3.0a0",
"pytest-cov",
"pytest<8",
- "rapids-logger==0.2.*,>=0.0.0a0",
+ "rapids-logger==0.2.*",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`.
[project.urls]
@@ -112,12 +112,12 @@ dependencies-file = "../../dependencies.yaml"
matrix-entry = "cuda_suffixed=true;use_cuda_wheels=true"
requires = [
"cmake>=3.30.4",
- "cuopt-mps-parser==25.12.*,>=0.0.0a0",
+ "cuopt-mps-parser==25.12.*",
"cupy-cuda13x>=13.6.0",
"cython>=3.0.3",
- "libcuopt==25.12.*,>=0.0.0a0",
+ "libcuopt==25.12.*",
"ninja",
- "pylibraft==25.12.*,>=0.0.0a0",
- "rapids-logger==0.2.*,>=0.0.0a0",
- "rmm==25.12.*,>=0.0.0a0",
+ "pylibraft==25.12.*",
+ "rapids-logger==0.2.*",
+ "rmm==25.12.*",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`.
diff --git a/python/cuopt_self_hosted/pyproject.toml b/python/cuopt_self_hosted/pyproject.toml
index 5b94fb74f4..79b2de0793 100644
--- a/python/cuopt_self_hosted/pyproject.toml
+++ b/python/cuopt_self_hosted/pyproject.toml
@@ -19,7 +19,7 @@ authors = [
license = { text = "Apache-2.0" }
requires-python = ">=3.10"
dependencies = [
- "cuopt-mps-parser==25.12.*,>=0.0.0a0",
+ "cuopt-mps-parser==25.12.*",
"msgpack-numpy==0.4.8",
"msgpack==1.1.0",
"requests",
diff --git a/python/cuopt_server/pyproject.toml b/python/cuopt_server/pyproject.toml
index 4e4dc15a27..cbf9429c75 100644
--- a/python/cuopt_server/pyproject.toml
+++ b/python/cuopt_server/pyproject.toml
@@ -20,7 +20,7 @@ authors = [
license = { text = "Apache-2.0" }
requires-python = ">=3.10"
dependencies = [
- "cuopt==25.12.*,>=0.0.0a0",
+ "cuopt==25.12.*",
"cupy-cuda13x>=13.6.0",
"fastapi",
"jsonref==1.1.0",
diff --git a/python/libcuopt/pyproject.toml b/python/libcuopt/pyproject.toml
index 1fdd8ad2cc..5e955f3ba3 100644
--- a/python/libcuopt/pyproject.toml
+++ b/python/libcuopt/pyproject.toml
@@ -31,8 +31,8 @@ classifiers = [
"Programming Language :: Python :: 3.13",
]
dependencies = [
- "cuopt-mps-parser==25.12.*,>=0.0.0a0",
- "librmm==25.12.*,>=0.0.0a0",
+ "cuopt-mps-parser==25.12.*",
+ "librmm==25.12.*",
"nvidia-cublas",
"nvidia-cudart",
"nvidia-cudss",
@@ -40,7 +40,7 @@ dependencies = [
"nvidia-cusolver",
"nvidia-cusparse",
"nvidia-nvtx",
- "rapids-logger==0.2.*,>=0.0.0a0",
+ "rapids-logger==0.2.*",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`.
[project.urls]
@@ -82,8 +82,8 @@ dependencies-file = "../../dependencies.yaml"
matrix-entry = "cuda_suffixed=true;use_cuda_wheels=true"
requires = [
"cmake>=3.30.4",
- "cuopt-mps-parser==25.12.*,>=0.0.0a0",
- "librmm==25.12.*,>=0.0.0a0",
+ "cuopt-mps-parser==25.12.*",
+ "librmm==25.12.*",
"ninja",
- "rapids-logger==0.2.*,>=0.0.0a0",
+ "rapids-logger==0.2.*",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`.
From 9120ce2670ee6f930cf609460aa41a839df79197 Mon Sep 17 00:00:00 2001
From: Christopher Maes
Date: Thu, 18 Dec 2025 12:37:31 -0800
Subject: [PATCH 3/3] Fix an issue with rank-deficient basis in dual push
---
cpp/src/dual_simplex/crossover.cpp | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/cpp/src/dual_simplex/crossover.cpp b/cpp/src/dual_simplex/crossover.cpp
index 23d9a0e8e0..86ff4f9a96 100644
--- a/cpp/src/dual_simplex/crossover.cpp
+++ b/cpp/src/dual_simplex/crossover.cpp
@@ -502,7 +502,18 @@ i_t dual_push(const lp_problem_t& lp,
std::vector q(m);
std::vector deficient;
std::vector slacks_needed;
- factorize_basis(lp.A, settings, basic_list, L, U, p, pinv, q, deficient, slacks_needed);
+ i_t rank = factorize_basis(lp.A, settings, basic_list, L, U, p, pinv, q, deficient, slacks_needed);
+ if (rank != m) {
+ settings.log.printf("Failed to factorize basis. rank %d m %d\n", rank, m);
+ basis_repair(lp.A, settings, deficient, slacks_needed, basic_list, nonbasic_list, vstatus);
+ if (factorize_basis(lp.A, settings, basic_list, L, U, p, pinv, q, deficient, slacks_needed) ==
+ -1) {
+ settings.log.printf("Failed to factorize basis after repair. rank %d m %d\n", rank, m);
+ return -1;
+ } else {
+ settings.log.printf("Basis repaired\n");
+ }
+ }
reorder_basic_list(q, basic_list);
// Reordering the basic list causes us to mess up the superbasic list index
// so we need to update it
@@ -1203,8 +1214,8 @@ crossover_status_t crossover(const lp_problem_t& lp,
i_t primal_push_status = primal_push(
lp, settings, start_time, solution, ft, basic_list, nonbasic_list, superbasic_list, vstatus);
if (primal_push_status < 0) { return return_to_status(primal_push_status); }
- print_crossover_info(lp, settings, vstatus, solution, "Primal push complete");
compute_dual_solution_from_basis(lp, ft, basic_list, nonbasic_list, solution.y, solution.z);
+ print_crossover_info(lp, settings, vstatus, solution, "Primal push complete");
} else {
settings.log.printf("No primal push needed. No superbasic variables\n");
}
@@ -1353,7 +1364,8 @@ crossover_status_t crossover(const lp_problem_t& lp,
}
}
settings.log.debug("Num flips %d\n", num_flips);
- solution = phase1_solution;
+ solution.y = phase1_solution.y;
+ solution.z = phase1_solution.z;
print_crossover_info(lp, settings, vstatus, solution, "Dual phase 1 complete");
std::vector edge_norms;
dual::status_t status = dual_phase2(