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 ea697e1e1..76388504e 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 77acca8f7..6161f4d3f 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 7891711f7..38438cc9e 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 98be9d4cb..a1cc049e7 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 ed141a0c4..ab418bf5a 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 4a78f6cff..9f3b4c90f 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 01931a3dd..0094f5982 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 a16c49c11..217f9c64c 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 13c5e36e3..08556a4c7 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 799eb291f..447b03a32 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 59d6b43c0..7a4a54a1d 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 4aad50d00..6c5ae382e 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 5adb8aeae..82c250f01 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 11c24d589..e89e322d6 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 393b99293..c46f11b74 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 c11cd3a58..24907d83f 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 f3f2dbbf8..f27e3f23a 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 5b94fb74f..79b2de079 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 4e4dc15a2..cbf9429c7 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 1fdd8ad2c..5e955f3ba 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 f341e345d2a11736b18c2c787e70ed6d494e4b95 Mon Sep 17 00:00:00 2001
From: Christopher Maes
Date: Thu, 11 Dec 2025 18:52:50 -0800
Subject: [PATCH 3/3] Fix incorrect infeasible list
---
cpp/src/dual_simplex/basis_solves.cpp | 14 +++++++-
cpp/src/dual_simplex/basis_solves.hpp | 2 ++
cpp/src/dual_simplex/basis_updates.cpp | 4 ++-
cpp/src/dual_simplex/basis_updates.hpp | 2 ++
cpp/src/dual_simplex/crossover.cpp | 6 ++--
cpp/src/dual_simplex/phase2.cpp | 45 ++++++++++++++------------
cpp/src/dual_simplex/primal.cpp | 2 +-
7 files changed, 49 insertions(+), 26 deletions(-)
diff --git a/cpp/src/dual_simplex/basis_solves.cpp b/cpp/src/dual_simplex/basis_solves.cpp
index db24f55a2..3080f269d 100644
--- a/cpp/src/dual_simplex/basis_solves.cpp
+++ b/cpp/src/dual_simplex/basis_solves.cpp
@@ -613,6 +613,8 @@ i_t factorize_basis(const csc_matrix_t& A,
template
i_t basis_repair(const csc_matrix_t& A,
const simplex_solver_settings_t& settings,
+ const std::vector& lower,
+ const std::vector& upper,
const std::vector& deficient,
const std::vector& slacks_needed,
std::vector& basis_list,
@@ -658,7 +660,15 @@ i_t basis_repair(const csc_matrix_t& A,
nonbasic_list[nonbasic_map[replace_j]] = bad_j;
vstatus[replace_j] = variable_status_t::BASIC;
// This is the main issue. What value should bad_j take on.
- vstatus[bad_j] = variable_status_t::NONBASIC_FREE;
+ if (lower[bad_j] == -inf && upper[bad_j] == inf) {
+ vstatus[bad_j] = variable_status_t::NONBASIC_FREE;
+ } else if (lower[bad_j] > -inf) {
+ vstatus[bad_j] = variable_status_t::NONBASIC_LOWER;
+ } else if (upper[bad_j] < inf) {
+ vstatus[bad_j] = variable_status_t::NONBASIC_UPPER;
+ } else {
+ assert(1 == 0);
+ }
}
return 0;
@@ -849,6 +859,8 @@ template int factorize_basis(const csc_matrix_t& A,
template int basis_repair(const csc_matrix_t& A,
const simplex_solver_settings_t& settings,
+ const std::vector& lower,
+ const std::vector& upper,
const std::vector& deficient,
const std::vector& slacks_needed,
std::vector& basis_list,
diff --git a/cpp/src/dual_simplex/basis_solves.hpp b/cpp/src/dual_simplex/basis_solves.hpp
index b668c0f46..0745806a6 100644
--- a/cpp/src/dual_simplex/basis_solves.hpp
+++ b/cpp/src/dual_simplex/basis_solves.hpp
@@ -42,6 +42,8 @@ i_t factorize_basis(const csc_matrix_t& A,
template
i_t basis_repair(const csc_matrix_t& A,
const simplex_solver_settings_t& settings,
+ const std::vector& lower,
+ const std::vector& upper,
const std::vector& deficient,
const std::vector& slacks_needed,
std::vector& basis_list,
diff --git a/cpp/src/dual_simplex/basis_updates.cpp b/cpp/src/dual_simplex/basis_updates.cpp
index 6b79f3c86..11056a65e 100644
--- a/cpp/src/dual_simplex/basis_updates.cpp
+++ b/cpp/src/dual_simplex/basis_updates.cpp
@@ -2046,6 +2046,8 @@ template
int basis_update_mpf_t::refactor_basis(
const csc_matrix_t& A,
const simplex_solver_settings_t& settings,
+ const std::vector& lower,
+ const std::vector& upper,
std::vector& basic_list,
std::vector& nonbasic_list,
std::vector& vstatus)
@@ -2066,7 +2068,7 @@ int basis_update_mpf_t::refactor_basis(
deficient,
slacks_needed) == -1) {
settings.log.debug("Initial factorization failed\n");
- basis_repair(A, settings, deficient, slacks_needed, basic_list, nonbasic_list, vstatus);
+ basis_repair(A, settings, lower, upper, deficient, slacks_needed, basic_list, nonbasic_list, vstatus);
#ifdef CHECK_BASIS_REPAIR
const i_t m = A.m;
diff --git a/cpp/src/dual_simplex/basis_updates.hpp b/cpp/src/dual_simplex/basis_updates.hpp
index cea907074..9b5d3e614 100644
--- a/cpp/src/dual_simplex/basis_updates.hpp
+++ b/cpp/src/dual_simplex/basis_updates.hpp
@@ -373,6 +373,8 @@ class basis_update_mpf_t {
// Compute L*U = A(p, basic_list)
int refactor_basis(const csc_matrix_t& A,
const simplex_solver_settings_t& settings,
+ const std::vector& lower,
+ const std::vector& upper,
std::vector& basic_list,
std::vector& nonbasic_list,
std::vector& vstatus);
diff --git a/cpp/src/dual_simplex/crossover.cpp b/cpp/src/dual_simplex/crossover.cpp
index 23d9a0e8e..3dd61b152 100644
--- a/cpp/src/dual_simplex/crossover.cpp
+++ b/cpp/src/dual_simplex/crossover.cpp
@@ -786,7 +786,7 @@ i_t primal_push(const lp_problem_t& lp,
if (rank != m) {
settings.log.debug("Failed to factorize basis. rank %d m %d\n", rank, m);
basis_repair(
- lp.A, settings, deficient, slacks_needed, basic_list, nonbasic_list, vstatus);
+ lp.A, settings, lp.lower, lp.upper, 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);
@@ -1132,7 +1132,7 @@ crossover_status_t crossover(const lp_problem_t& lp,
rank = factorize_basis(lp.A, settings, basic_list, L, U, p, pinv, q, deficient, slacks_needed);
if (rank != m) {
settings.log.debug("Failed to factorize basis. rank %d m %d\n", rank, m);
- basis_repair(lp.A, settings, deficient, slacks_needed, basic_list, nonbasic_list, vstatus);
+ basis_repair(lp.A, settings, lp.lower, lp.upper, 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);
@@ -1323,7 +1323,7 @@ crossover_status_t crossover(const lp_problem_t& lp,
factorize_basis(lp.A, settings, basic_list, L, U, p, pinv, q, deficient, slacks_needed);
if (rank != m) {
settings.log.debug("Failed to factorize basis. rank %d m %d\n", rank, m);
- basis_repair(lp.A, settings, deficient, slacks_needed, basic_list, nonbasic_list, vstatus);
+ basis_repair(lp.A, settings, lp.lower, lp.upper, 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);
diff --git a/cpp/src/dual_simplex/phase2.cpp b/cpp/src/dual_simplex/phase2.cpp
index 56298ef4d..e0ac7239e 100644
--- a/cpp/src/dual_simplex/phase2.cpp
+++ b/cpp/src/dual_simplex/phase2.cpp
@@ -623,14 +623,17 @@ f_t compute_initial_primal_infeasibilities(const lp_problem_t& lp,
const std::vector& basic_list,
const std::vector& x,
std::vector& squared_infeasibilities,
- std::vector& infeasibility_indices)
+ std::vector& infeasibility_indices,
+ f_t& primal_inf)
{
const i_t m = lp.num_rows;
const i_t n = lp.num_cols;
- squared_infeasibilities.resize(n, 0.0);
+ squared_infeasibilities.resize(n);
+ std::fill(squared_infeasibilities.begin(), squared_infeasibilities.end(), 0.0);
infeasibility_indices.reserve(n);
infeasibility_indices.clear();
- f_t primal_inf = 0.0;
+ f_t primal_inf_squared = 0.0;
+ primal_inf = 0.0;
for (i_t k = 0; k < m; ++k) {
const i_t j = basic_list[k];
const f_t lower_infeas = lp.lower[j] - x[j];
@@ -640,10 +643,11 @@ f_t compute_initial_primal_infeasibilities(const lp_problem_t& lp,
const f_t square_infeas = infeas * infeas;
squared_infeasibilities[j] = square_infeas;
infeasibility_indices.push_back(j);
- primal_inf += square_infeas;
+ primal_inf_squared += square_infeas;
+ primal_inf += infeas;
}
}
- return primal_inf;
+ return primal_inf_squared;
}
template
@@ -2241,7 +2245,7 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
assert(superbasic_list.size() == 0);
assert(nonbasic_list.size() == n - m);
- if (ft.refactor_basis(lp.A, settings, basic_list, nonbasic_list, vstatus) > 0) {
+ if (ft.refactor_basis(lp.A, settings, lp.lower, lp.upper, basic_list, nonbasic_list, vstatus) > 0) {
return dual::status_t::NUMERICAL;
}
@@ -2268,7 +2272,7 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
#ifdef COMPUTE_DUAL_RESIDUAL
std::vector dual_res1;
- compute_dual_residual(lp.A, objective, y, z, dual_res1);
+ phase2::compute_dual_residual(lp.A, objective, y, z, dual_res1);
f_t dual_res_norm = vector_norm_inf(dual_res1);
if (dual_res_norm > settings.tight_tol) {
settings.log.printf("|| A'*y + z - c || %e\n", dual_res_norm);
@@ -2357,8 +2361,9 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
std::vector bounded_variables(n, 0);
phase2::compute_bounded_info(lp.lower, lp.upper, bounded_variables);
- f_t primal_infeasibility = phase2::compute_initial_primal_infeasibilities(
- lp, settings, basic_list, x, squared_infeasibilities, infeasibility_indices);
+ f_t primal_infeasibility;
+ f_t primal_infeasibility_squared = phase2::compute_initial_primal_infeasibilities(
+ lp, settings, basic_list, x, squared_infeasibilities, infeasibility_indices, primal_infeasibility);
#ifdef CHECK_BASIC_INFEASIBILITIES
phase2::check_basic_infeasibilities(basic_list, basic_mark, infeasibility_indices, 0);
@@ -2557,8 +2562,8 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
phase2::compute_primal_solution_from_basis(
lp, ft, basic_list, nonbasic_list, vstatus, unperturbed_x);
x = unperturbed_x;
- primal_infeasibility = phase2::compute_initial_primal_infeasibilities(
- lp, settings, basic_list, x, squared_infeasibilities, infeasibility_indices);
+ primal_infeasibility_squared = phase2::compute_initial_primal_infeasibilities(
+ lp, settings, basic_list, x, squared_infeasibilities, infeasibility_indices, primal_infeasibility);
settings.log.printf("Updated primal infeasibility: %e\n", primal_infeasibility);
objective = lp.objective;
@@ -2594,8 +2599,8 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
phase2::compute_primal_solution_from_basis(
lp, ft, basic_list, nonbasic_list, vstatus, unperturbed_x);
x = unperturbed_x;
- primal_infeasibility = phase2::compute_initial_primal_infeasibilities(
- lp, settings, basic_list, x, squared_infeasibilities, infeasibility_indices);
+ primal_infeasibility_squared = phase2::compute_initial_primal_infeasibilities(
+ lp, settings, basic_list, x, squared_infeasibilities, infeasibility_indices, primal_infeasibility);
const f_t orig_dual_infeas = phase2::dual_infeasibility(
lp, settings, vstatus, z, settings.tight_tol, settings.dual_tol);
@@ -2810,7 +2815,7 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
delta_xB_0_sparse.i,
squared_infeasibilities,
infeasibility_indices,
- primal_infeasibility);
+ primal_infeasibility_squared);
// Update primal infeasibilities due to changes in basic variables
// from the leaving and entering variables
phase2::update_primal_infeasibilities(lp,
@@ -2822,7 +2827,7 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
scaled_delta_xB_sparse.i,
squared_infeasibilities,
infeasibility_indices,
- primal_infeasibility);
+ primal_infeasibility_squared);
// Update the entering variable
phase2::update_single_primal_infeasibility(lp.lower,
lp.upper,
@@ -2883,14 +2888,14 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
#endif
if (should_refactor) {
bool should_recompute_x = false;
- if (ft.refactor_basis(lp.A, settings, basic_list, nonbasic_list, vstatus) > 0) {
+ if (ft.refactor_basis(lp.A, settings, lp.lower, lp.upper, basic_list, nonbasic_list, vstatus) > 0) {
should_recompute_x = true;
settings.log.printf("Failed to factorize basis. Iteration %d\n", iter);
if (toc(start_time) > settings.time_limit) { return dual::status_t::TIME_LIMIT; }
i_t count = 0;
i_t deficient_size;
while ((deficient_size =
- ft.refactor_basis(lp.A, settings, basic_list, nonbasic_list, vstatus)) > 0) {
+ ft.refactor_basis(lp.A, settings, lp.lower, lp.upper, basic_list, nonbasic_list, vstatus)) > 0) {
settings.log.printf("Failed to repair basis. Iteration %d. %d deficient columns.\n",
iter,
static_cast(deficient_size));
@@ -2912,8 +2917,8 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
lp, ft, basic_list, nonbasic_list, vstatus, unperturbed_x);
x = unperturbed_x;
}
- phase2::compute_initial_primal_infeasibilities(
- lp, settings, basic_list, x, squared_infeasibilities, infeasibility_indices);
+ primal_infeasibility_squared = phase2::compute_initial_primal_infeasibilities(
+ lp, settings, basic_list, x, squared_infeasibilities, infeasibility_indices, primal_infeasibility);
}
#ifdef CHECK_BASIC_INFEASIBILITIES
phase2::check_basic_infeasibilities(basic_list, basic_mark, infeasibility_indices, 7);
@@ -2951,7 +2956,7 @@ dual::status_t dual_phase2_with_advanced_basis(i_t phase,
iter,
compute_user_objective(lp, obj),
infeasibility_indices.size(),
- primal_infeasibility,
+ primal_infeasibility_squared,
sum_perturb,
now);
}
diff --git a/cpp/src/dual_simplex/primal.cpp b/cpp/src/dual_simplex/primal.cpp
index 80406dcf0..445177fac 100644
--- a/cpp/src/dual_simplex/primal.cpp
+++ b/cpp/src/dual_simplex/primal.cpp
@@ -298,7 +298,7 @@ primal::status_t primal_phase2(i_t phase,
factorize_basis(lp.A, settings, basic_list, L, U, p, pinv, q, deficient, slacks_needed);
if (rank != m) {
settings.log.debug("Failed to factorize basis. rank %d m %d\n", rank, m);
- basis_repair(lp.A, settings, deficient, slacks_needed, basic_list, nonbasic_list, vstatus);
+ basis_repair(lp.A, settings, lp.lower, lp.upper, 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);