Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion ci/test_self_hosted_service.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,18 @@ CUOPT_SERVER_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="cuopt_server_${RAPIDS_PY_CUDA_SU
CUOPT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="cuopt_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-github python)
LIBCUOPT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="libcuopt_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-github cpp)

# echo to expand wildcard before adding `[extra]` requires for pip
# generate constraints (possibly pinning to oldest support versions of dependencies)
rapids-generate-pip-constraints test_python "${PIP_CONSTRAINT}"

# notes:
#
# * echo to expand wildcard before adding `[test]` requires for pip
# * just providing --constraint="${PIP_CONSTRAINT}" to be explicit, and because
# that environment variable is ignored if any other --constraint are passed via the CLI
#
rapids-pip-retry install \
--prefer-binary \
--constraint "${PIP_CONSTRAINT}" \
"${CUOPT_MPS_PARSER_WHEELHOUSE}"/cuopt_mps_parser*.whl \
"${CUOPT_WHEELHOUSE}"/cuopt*.whl \
"${LIBCUOPT_WHEELHOUSE}"/libcuopt*.whl \
Expand Down
14 changes: 13 additions & 1 deletion ci/test_wheel_cuopt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,18 @@ cuopt-sh-client @ file://$(echo ${CUOPT_SH_CLIENT_WHEELHOUSE}/cuopt_sh_client-*.
libcuopt-${RAPIDS_PY_CUDA_SUFFIX} @ file://$(echo ${LIBCUOPT_WHEELHOUSE}/libcuopt_${RAPIDS_PY_CUDA_SUFFIX}-*.whl)
EOF

# echo to expand wildcard before adding `[extra]` requires for pip
# generate constraints (possibly pinning to oldest support versions of dependencies)
rapids-generate-pip-constraints test_python "${PIP_CONSTRAINT}"

# notes:
#
# * echo to expand wildcard before adding `[test]` requires for pip
# * just providing --constraint="${PIP_CONSTRAINT}" to be explicit, and because
# that environment variable is ignored if any other --constraint are passed via the CLI
#
rapids-pip-retry install \
--prefer-binary \
--constraint "${PIP_CONSTRAINT}" \
--constraint "${PIP_CONSTRAINT}" \
"${CUOPT_MPS_PARSER_WHEELHOUSE}"/cuopt_mps_parser*.whl \
"$(echo "${CUOPT_WHEELHOUSE}"/cuopt*.whl)[test]" \
Expand Down Expand Up @@ -67,4 +77,6 @@ timeout 30m ./ci/run_cuopt_pytests.sh --verbose --capture=no
if [[ "${RAPIDS_BUILD_TYPE}" == "nightly" ]]; then
./ci/thirdparty-testing/run_jump_tests.sh
./ci/thirdparty-testing/run_cvxpy_tests.sh
./ci/thirdparty-testing/run_pulp_tests.sh
./ci/thirdparty-testing/run_pyomo_tests.sh
fi
12 changes: 11 additions & 1 deletion ci/test_wheel_cuopt_server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,18 @@ CUOPT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="cuopt_${RAPIDS_PY_CUDA_SUFFIX}" rapids-
CUOPT_SH_CLIENT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="cuopt_sh_client" RAPIDS_PY_WHEEL_PURE="1" rapids-download-wheels-from-github python)
LIBCUOPT_WHEELHOUSE=$(RAPIDS_PY_WHEEL_NAME="libcuopt_${RAPIDS_PY_CUDA_SUFFIX}" rapids-download-wheels-from-github cpp)

# echo to expand wildcard before adding `[extra]` requires for pip
# generate constraints (possibly pinning to oldest support versions of dependencies)
rapids-generate-pip-constraints test_python "${PIP_CONSTRAINT}"

# notes:
#
# * echo to expand wildcard before adding `[test]` requires for pip
# * just providing --constraint="${PIP_CONSTRAINT}" to be explicit, and because
# that environment variable is ignored if any other --constraint are passed via the CLI
#
rapids-pip-retry install \
--prefer-binary \
--constraint "${PIP_CONSTRAINT}" \
"${CUOPT_MPS_PARSER_WHEELHOUSE}"/cuopt_mps_parser*.whl \
"$(echo "${CUOPT_SERVER_WHEELHOUSE}"/cuopt_server*.whl)[test]" \
"${CUOPT_WHEELHOUSE}"/cuopt*.whl \
Expand Down
43 changes: 43 additions & 0 deletions ci/thirdparty-testing/run_pulp_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

set -e -u -o pipefail

rapids-logger "building 'pulp' from source and running cuOpt tests"

if [ -z "${PIP_CONSTRAINT:-}" ]; then
rapids-logger "PIP_CONSTRAINT is not set; ensure ci/test_wheel_cuopt.sh (or equivalent) has set it so cuopt wheels are used."
exit 1
fi

git clone --depth 1 https://github.com/coin-or/pulp.git
pushd ./pulp || exit 1

# Install PuLP in editable form so it uses the environment's cuopt (from PIP_CONSTRAINT)
python -m pip install \
--constraint "${PIP_CONSTRAINT}" \
--extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple \
pytest \
-e .

pip check

rapids-logger "running PuLP tests (cuOpt-related)"
# PuLP uses pytest; run only tests that reference cuopt/CUOPT
# Exit code 5 = no tests collected; then try run_tests.py which detects solvers (including cuopt)
pytest_rc=0
timeout 5m python -m pytest \
--verbose \
--capture=no \
-k "cuopt or CUOPT" \
pulp/tests/ || pytest_rc=$?

if [ "$pytest_rc" -eq 5 ]; then
rapids-logger "No pytest -k cuopt tests found; running PuLP run_tests.py (solver auto-detection, includes cuopt)"
timeout 5m python pulp/tests/run_tests.py
pytest_rc=$?
fi

popd || exit 1
exit "$pytest_rc"
34 changes: 34 additions & 0 deletions ci/thirdparty-testing/run_pyomo_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

set -e -u -o pipefail

rapids-logger "building 'pyomo' from source and running cuOpt tests"

if [ -z "${PIP_CONSTRAINT:-}" ]; then
rapids-logger "PIP_CONSTRAINT is not set; ensure ci/test_wheel_cuopt.sh (or equivalent) has set it so cuopt wheels are used."
exit 1
fi

git clone --depth 1 https://github.com/Pyomo/pyomo.git
pushd ./pyomo || exit 1

# Install Pyomo in editable form so it uses the environment's cuopt (from PIP_CONSTRAINT)
python -m pip install \
--constraint "${PIP_CONSTRAINT}" \
--extra-index-url=https://pypi.anaconda.org/rapidsai-wheels-nightly/simple \
pytest \
-e .

pip check

rapids-logger "running Pyomo tests (cuopt_direct / cuOpt-related)"
# Run only tests that reference cuopt (cuopt_direct solver)
timeout 5m python -m pytest \
--verbose \
--capture=no \
-k "cuopt or CUOPT" \
pyomo/solvers/tests/

popd || exit 1
1 change: 1 addition & 0 deletions cpp/include/cuopt/linear_programming/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#define CUOPT_NUM_CPU_THREADS "num_cpu_threads"
#define CUOPT_NUM_GPUS "num_gpus"
#define CUOPT_USER_PROBLEM_FILE "user_problem_file"
#define CUOPT_PRESOLVE_FILE "presolve_file"
#define CUOPT_RANDOM_SEED "random_seed"
#define CUOPT_PDLP_PRECISION "pdlp_precision"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class mip_solver_settings_t {
std::string log_file;
std::string sol_file;
std::string user_problem_file;
std::string presolve_file;

/** Initial primal solutions */
std::vector<std::shared_ptr<rmm::device_uvector<f_t>>> initial_solutions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ class pdlp_solver_settings_t {
std::string log_file{""};
std::string sol_file{""};
std::string user_problem_file{""};
std::string presolve_file{""};
bool per_constraint_residual{false};
bool crossover{false};
bool cudss_deterministic{false};
Expand Down
4 changes: 3 additions & 1 deletion cpp/src/math_optimization/solver_settings.cu
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ solver_settings_t<i_t, f_t>::solver_settings_t() : pdlp_settings(), mip_settings
{CUOPT_SOLUTION_FILE, &mip_settings.sol_file, ""},
{CUOPT_SOLUTION_FILE, &pdlp_settings.sol_file, ""},
{CUOPT_USER_PROBLEM_FILE, &mip_settings.user_problem_file, ""},
{CUOPT_USER_PROBLEM_FILE, &pdlp_settings.user_problem_file, ""}
{CUOPT_USER_PROBLEM_FILE, &pdlp_settings.user_problem_file, ""},
{CUOPT_PRESOLVE_FILE, &mip_settings.presolve_file, ""},
{CUOPT_PRESOLVE_FILE, &pdlp_settings.presolve_file, ""}
};
// clang-format on
}
Expand Down
5 changes: 5 additions & 0 deletions cpp/src/mip_heuristics/solve.cu
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ mip_solution_t<i_t, f_t> solve_mip(optimization_problem_t<i_t, f_t>& op_problem,
settings.tolerances.relative_tolerance,
presolve_time_limit,
settings.num_cpu_threads);

if (!result.has_value()) {
return mip_solution_t<i_t, f_t>(mip_termination_status_t::Infeasible,
solver_stats_t<i_t, f_t>{},
Expand All @@ -306,6 +307,10 @@ mip_solution_t<i_t, f_t> solve_mip(optimization_problem_t<i_t, f_t>& op_problem,
CUOPT_LOG_INFO("Writing user problem to file: %s", settings.user_problem_file.c_str());
op_problem.write_to_mps(settings.user_problem_file);
}
if (run_presolve && settings.presolve_file != "") {
CUOPT_LOG_INFO("Writing presolved problem to file: %s", settings.presolve_file.c_str());
presolve_result->reduced_problem.write_to_mps(settings.presolve_file);
}

auto sol = run_mip(problem, settings, timer);

Expand Down
4 changes: 4 additions & 0 deletions cpp/src/pdlp/solve.cu
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,10 @@ optimization_problem_solution_t<i_t, f_t> solve_lp(
CUOPT_LOG_INFO("Writing user problem to file: %s", settings.user_problem_file.c_str());
op_problem.write_to_mps(settings.user_problem_file);
}
if (run_presolve && settings.presolve_file != "") {
CUOPT_LOG_INFO("Writing presolved problem to file: %s", settings.presolve_file.c_str());
result->reduced_problem.write_to_mps(settings.presolve_file);
}

// Set the hyper-parameters based on the solver_settings
if (use_pdlp_solver_mode) { set_pdlp_solver_mode(settings); }
Expand Down
92 changes: 67 additions & 25 deletions dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -633,22 +633,16 @@ dependencies:
- matrix:
packages:
- *pylibraft_unsuffixed
# 'cuda_version' intentionally does not contain fallback entries... we want
# a loud error if an unsupported 'cuda' value is passed
cuda_version:
specific:
- output_types: conda
matrices:
- matrix:
cuda: "12.0"
packages:
- cuda-version=12.0
- matrix:
cuda: "12.2"
packages:
- cuda-version=12.2
- matrix:
cuda: "12.4"
packages:
- cuda-version=12.4
- matrix:
cuda: "12.5"
packages:
Expand All @@ -669,6 +663,51 @@ dependencies:
cuda: "13.1"
packages:
- cuda-version=13.1
- output_types: requirements
matrices:
# if use_cuda_wheels=false is provided, do not add dependencies on any CUDA wheels
# (e.g. for DLFW and pip devcontainers)
- matrix:
use_cuda_wheels: "false"
packages:
- matrix:
arch: aarch64
cuda: "12.2"
use_cuda_wheels: "true"
packages:
# some components (like nvidia-cublas-cu12 and nvidia-cuda-nvcc-cu12) didn't have
# aarch64 wheels until CTK 12.3, so allow a slightly looser bound here
- cuda-toolkit>=12.2,<12.4
- matrix:
cuda: "12.2"
use_cuda_wheels: "true"
packages:
- cuda-toolkit==12.2.*
- matrix:
cuda: "12.5"
use_cuda_wheels: "true"
packages:
- cuda-toolkit==12.5.*
- matrix:
cuda: "12.8"
use_cuda_wheels: "true"
packages:
- cuda-toolkit==12.8.*
- matrix:
cuda: "12.9"
use_cuda_wheels: "true"
packages:
- cuda-toolkit==12.9.*
- matrix:
cuda: "13.0"
use_cuda_wheels: "true"
packages:
- cuda-toolkit==13.0.*
- matrix:
cuda: "13.1"
use_cuda_wheels: "true"
packages:
- cuda-toolkit==13.1.*
cuda:
common:
- output_types: [conda]
Expand All @@ -682,37 +721,40 @@ dependencies:

cuda_wheels:
specific:
# cuOpt needs 'nvJitLink>={whatever-cuopt-was-built-against}' at runtime, and mixing
# old-CTK with new-nvJitLink is supported, so maintain 1 entry here per CUDA major.minor
# cuOpt is built against.
#
# nvJitLink has historically roughly followed the CTK's minor versioning scheme,
# but check at https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html
- output_types: [requirements, pyproject]
matrices:
# if use_cuda_wheels=false is provided, do not add dependencies on any CUDA wheels
# (e.g. for DLFW and pip devcontainers)
- matrix:
use_cuda_wheels: "false"
packages:
- matrix:
cuda: "12.*"
use_cuda_wheels: "true"
packages:
- cuda-toolkit[cublas,cudart,curand,cusolver,cusparse,nvjitlink,nvtx]==12.*
- cuda-toolkit[cublas,cudart,curand,cusolver,cusparse,nvtx]==12.*
- nvidia-cudss-cu12
- nvidia-nvjitlink-cu12>=12.9,<13
- matrix:
cuda: "13.*"
use_cuda_wheels: "true"
packages:
- cuda-toolkit[cublas,cudart,curand,cusolver,cusparse,nvjitlink,nvtx]==13.*
- nvidia-cudss-cu13
# if use_cuda_wheels=false is provided, do not add dependencies on any CUDA wheels
# (e.g. for DLFW and pip devcontainers)
- matrix:
use_cuda_wheels: "false"
packages: []
# if no matching matrix selectors passed, list the unsuffixed packages
- &ctk_cu13 cuda-toolkit[cublas,cudart,curand,cusolver,cusparse,nvtx]==13.*
- &cudss_cu13 nvidia-cudss-cu13
- &nvjitlink_cu13 nvidia-nvjitlink>=13.0,<14
# if no matching matrix selectors passed, list the CUDA 13 requirement
# (just as a source of documentation, as this populates pyproject.toml in source control)
- matrix:
packages:
- nvidia-cudart
- nvidia-cublas
- nvidia-cudss
- nvidia-curand
- nvidia-cusparse
- nvidia-nvjitlink
- nvidia-cusolver
- nvidia-nvtx
- *ctk_cu13
- *cudss_cu13
- *nvjitlink_cu13
develop:
common:
- output_types: [conda, requirements]
Expand Down
5 changes: 5 additions & 0 deletions docs/cuopt/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@
nbsphinx_execute = "never"
ipython_mplbackend = "str"

# GPU routing example: Sphinx execution can fail when CUDA/CuPy don't match the docs
# environment. Listed paths are skipped by myst-nb; this notebook is rendered from
# checked-in cell outputs.
nb_execution_excludepatterns = ["cuopt-python/routing/routing-example.ipynb"]

# Add any files to exclude from the build
exclude_patterns = ["hidden"]

Expand Down
11 changes: 3 additions & 8 deletions python/libcuopt/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,11 @@ classifiers = [
"Programming Language :: Python :: 3.14",
]
dependencies = [
"cuda-toolkit[cublas,cudart,curand,cusolver,cusparse,nvtx]==13.*",
"cuopt-mps-parser==26.4.*,>=0.0.0a0",
"librmm==26.4.*,>=0.0.0a0",
"nvidia-cublas",
"nvidia-cudart",
"nvidia-cudss",
"nvidia-curand",
"nvidia-cusolver",
"nvidia-cusparse",
"nvidia-nvjitlink",
"nvidia-nvtx",
"nvidia-cudss-cu13",
"nvidia-nvjitlink>=13.0,<14",
"rapids-logger==0.2.*,>=0.0.0a0",
] # This list was generated by `rapids-dependency-file-generator`. To make changes, edit ../../dependencies.yaml and run `rapids-dependency-file-generator`.

Expand Down
Loading